1 //=============================================================================
3 * @file Stack_Trace.cpp
5 * $Id: Stack_Trace.cpp 82575 2008-08-08 20:36:10Z mitza $
7 * @brief Encapsulate string representation of stack trace.
9 * Portions of the platform-specific code have been based on
10 * code found in various places on the internet e.g., google groups,
11 * VxWorks FAQ, etc., and adapted for use here.
13 //=============================================================================
15 #include "ace/Stack_Trace.h"
16 #include "ace/Min_Max.h"
17 #include "ace/OS_NS_string.h"
18 #include "ace/OS_NS_stdio.h"
20 ACE_RCSID (ace
, Stack_Trace
, "$Id: Stack_Trace.cpp 82575 2008-08-08 20:36:10Z mitza $")
23 This is ugly, simply because it's very platform-specific.
26 const char ACE_Stack_Trace::UNSUPPORTED
[] = "<stack traces unsupported platform>";
27 const char ACE_Stack_Trace::UNABLE_TO_GET_TRACE
[] = "<unable to get trace>";
29 ACE_Stack_Trace::ACE_Stack_Trace (ssize_t starting_frame_offset
, size_t num_frames
)
32 // cannot initialize arrays, so we must assign.
34 this->generate_trace (starting_frame_offset
, num_frames
);
38 ACE_Stack_Trace::c_str () const
40 return &this->buf_
[0];
44 determine_starting_frame (ssize_t initial_frame
, ssize_t offset
)
46 return ACE_MAX( initial_frame
+ offset
, static_cast<ssize_t
>(0));
49 #if (defined(__GLIBC__) || defined(ACE_HAS_EXECINFO_H)) && (__GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 3))
50 // This is the code for glibc
51 # include <execinfo.h>
54 ACE_Stack_Trace::generate_trace (ssize_t starting_frame_offset
, size_t num_frames
)
56 const size_t MAX_FRAMES
= 128;
57 const ssize_t INITIAL_FRAME
= 3;
59 void* stack
[MAX_FRAMES
];
60 size_t stack_size
= 0;
64 num_frames
= MAX_FRAMES
;
66 size_t starting_frame
=
67 determine_starting_frame (INITIAL_FRAME
, starting_frame_offset
);
69 stack_size
= ::backtrace (&stack
[0], sizeof(stack
)/sizeof(stack
[0]));
72 stack_syms
= ::backtrace_symbols (stack
, stack_size
);
74 for (size_t i
= starting_frame
;
75 i
< stack_size
&& num_frames
> 0;
78 // this could be more efficient by remembering where we left off in buf_
79 char *symp
= &stack_syms
[i
][0];
80 while (this->buflen_
< SYMBUFSIZ
&& *symp
!= '\0')
82 this->buf_
[this->buflen_
++] = *symp
++;
84 this->buf_
[this->buflen_
++] = '\n'; // put a newline at the end
86 this->buf_
[this->buflen_
+1] = '\0'; // zero terminate the string
92 ACE_OS::strcpy (&this->buf_
[0], UNABLE_TO_GET_TRACE
);
95 #elif defined(VXWORKS) && !defined(__RTP__)
97 # include <taskLib.h> // hopefully this is enough to get all the necessary #defines.
99 struct ACE_Stack_Trace_stackstate
101 ACE_Stack_Trace_stackstate (char* b
, size_t& bl
, size_t nf
, size_t sf
)
102 : buf(b
), buflen(bl
), num_frames(nf
), starting_frame(sf
)
108 size_t starting_frame
;
111 //@TODO: Replace with a TSS-based pointer to avoid problems in multithreaded environs,
112 // or use a mutex to serialize access to this.
113 static ACE_Stack_Trace_stackstate
* ACE_Stack_Trace_stateptr
= 0;
116 ACE_Stack_Trace_Add_Frame_To_Buf (INSTR
*caller
,
121 if (ACE_Stack_Trace_stateptr
== 0)
124 ACE_Stack_Trace_stackstate
*stackstate
= ACE_Stack_Trace_stateptr
;
126 // Decrement the num_frames and starting_frame elements,
127 // then see if we're ready to start or ready to finish.
128 --stackstate
->num_frames
;
129 --stackstate
->starting_frame
;
131 if (stackstate
->num_frames
== 0 || stackstate
->starting_frame
> 0)
134 // These are references so that the structure gets updated
135 // in the code below.
136 char*& buf
= stackstate
->buf
;
137 unsigned int& len
= stackstate
->buflen
;
139 // At some point try using symFindByValue() to lookup func (and caller?)
140 // to print out symbols rather than simply addresses.
142 // VxWorks can pass -1 for "nargs" if there was an error
143 if (nargs
== static_cast<unsigned int> (-1)) nargs
= 0;
145 len
+= ACE_OS::sprintf (&buf
[len
], "%#10x: %#10x (", (int)caller
, func
);
146 for (unsigned int i
= 0; i
< nargs
; ++i
)
149 len
+= ACE_OS::sprintf (&buf
[len
], ", ");
150 len
+= ACE_OS::sprintf(&buf
[len
], "%#x", args
[i
]);
153 len
+= ACE_OS::sprintf(&buf
[len
], ")\n");
157 ACE_Stack_Trace::generate_trace (ssize_t starting_frame_offset
,
160 const size_t MAX_FRAMES
= 128;
161 const ssize_t INITIAL_FRAME
= 3;
164 num_frames
= MAX_FRAMES
;
166 size_t starting_frame
=
167 determine_starting_frame (INITIAL_FRAME
, starting_frame_offset
);
169 ACE_Stack_Trace_stackstate
state (&this->buf_
[0], this->buflen_
,
170 num_frames
, starting_frame
);
174 taskRegsGet ((int)taskIdSelf(), ®s
);
175 // Maybe we should take a lock here to guard stateptr?
176 ACE_Stack_Trace_stateptr
= &state
;
177 trcStack (®s
, (FUNCPTR
)ACE_Stack_Trace_Add_Frame_To_Buf
, taskIdSelf ());
181 #elif defined(VXWORKS) && defined(__RTP__)
183 # include <taskLib.h>
184 # include <private/trcLibP.h>
186 // See memEdrLib.c in VxWorks RTP sources for an example of stack tracing.
188 static STATUS
ace_vx_rtp_pc_validate (INSTR
*pc
, TRC_OS_CTX
*pOsCtx
)
190 return ALIGNED (pc
, sizeof (INSTR
)) ? OK
: ERROR
;
194 ACE_Stack_Trace::generate_trace (ssize_t starting_frame_offset
,
197 const size_t MAX_FRAMES
= 128;
198 const ssize_t INITIAL_FRAME
= 2;
200 if (num_frames
== 0) num_frames
= MAX_FRAMES
;
201 size_t starting_frame
=
202 determine_starting_frame (INITIAL_FRAME
, starting_frame_offset
);
208 if (taskInfoGet (taskIdSelf (), &desc
) == ERROR
) return;
211 osCtx
.stackBase
= desc
.td_pStackBase
;
212 osCtx
.stackEnd
= desc
.td_pStackEnd
;
213 osCtx
.pcValidateRtn
= reinterpret_cast<FUNCPTR
> (ace_vx_rtp_pc_validate
);
215 char *fp
= _WRS_FRAMEP_FROM_JMP_BUF (regs
);
216 INSTR
*pc
= _WRS_RET_PC_FROM_JMP_BUF (regs
);
218 for (size_t depth
= 0; depth
< num_frames
+ starting_frame
; ++depth
)
224 if (trcLibFuncs
.lvlInfoGet (fp
, pc
, &osCtx
, &prevFp
, &prevPc
, &prevFn
)
227 ACE_OS::strcpy (this->buf_
, UNABLE_TO_GET_TRACE
);
231 if(prevPc
== 0 || prevFp
== 0) break;
233 if (depth
>= starting_frame
)
235 //Hopefully a future version of VxWorks will have a system call
236 //for an RTP to query its own symbols, but this is not possible now.
237 //An enhancement request has been filed under WIND00123307.
238 const char *fnName
= "(no symbols)";
240 static const int N_ARGS
= 12;
244 trcLibFuncs
.lvlArgsGet (prevPc
, prevFn
, prevFp
,
245 buf
, N_ARGS
, &pArgs
);
247 // VxWorks can return -1 for "numArgs" if there was an error
248 if (numArgs
== -1) numArgs
= 0;
250 size_t len
= ACE_OS::strlen (this->buf_
);
251 size_t space
= SYMBUFSIZ
- len
- 1;
252 char *cursor
= this->buf_
+ len
;
253 size_t written
= ACE_OS::snprintf (cursor
, space
, "%x %s",
258 if (space
< 1) return; //no point in logging when we're out of buffer
259 for (int arg
= 0; numArgs
!= -1 && pArgs
&& arg
< numArgs
; ++arg
)
261 if (arg
== 0) *cursor
++ = '(', --space
;
262 written
= ACE_OS::snprintf (cursor
, space
,
263 (arg
< numArgs
- 1) ? "%x, " : "%x",
267 if (space
&& arg
== numArgs
- 1) *cursor
++ = ')', --space
;
269 if (space
) *cursor
++ = '\n', --space
;
270 *cursor
++ = 0; //we saved space for the null terminator
280 * walks up call stack, printing library:routine+offset for each routine
285 # include <sys/types.h>
286 # include <sys/reg.h>
287 # include <sys/frame.h>
288 # define ACE_STACK_TRACE_BIAS 0
290 # if defined(sparc) || defined(__sparc)
291 # define ACE_STACK_TRACE_FLUSHWIN() asm("ta 3");
292 # define ACE_STACK_TRACE_FRAME_PTR_INDEX 1
293 # define ACE_STACK_TRACE_SKIP_FRAMES 0
294 # if defined(__sparcv9)
295 # undef ACE_STACK_TRACE_BIAS
296 # define ACE_STACK_TRACE_BIAS 2047
300 # if defined(i386) || defined(__i386)
301 # define ACE_STACK_TRACE_FLUSHWIN()
302 # define ACE_STACK_TRACE_FRAME_PTR_INDEX 3
303 # define ACE_STACK_TRACE_SKIP_FRAMES 0
306 # if defined(__amd64) || defined(__x86_64)
307 # define ACE_STACK_TRACE_FLUSHWIN()
308 # define ACE_STACK_TRACE_FRAME_PTR_INDEX 5
309 # define ACE_STACK_TRACE_SKIP_FRAMES 0
312 # if defined(ppc) || defined(__ppc)
313 # define ACE_STACK_TRACE_FLUSHWIN()
314 # define ACE_STACK_TRACE_FRAME_PTR_INDEX 0
315 # define ACE_STACK_TRACE_SKIP_FRAMES 2
319 cs_frame_adjust(frame
* sp
)
321 unsigned char* sp_byte
= (unsigned char*)sp
;
322 sp_byte
+= ACE_STACK_TRACE_BIAS
;
323 return (frame
*) sp_byte
;
327 this function walks up call stack, calling user-supplied
328 function once for each stack frame, passing the pc and the user-supplied
329 usrarg as the argument.
333 cs_operate(int (*func
)(void *, void *), void * usrarg
,
334 size_t starting_frame
, size_t num_frames_arg
)
336 ACE_STACK_TRACE_FLUSHWIN();
340 frame
* sp
= cs_frame_adjust((frame
*) env
[ACE_STACK_TRACE_FRAME_PTR_INDEX
]);
342 // make a copy of num_frames_arg to eliminate the following warning on some
343 // solaris platforms:
344 // Stack_Trace.cpp:318: warning: argument `size_t num_frames' might be clobbered by `longjmp' or `vfork'
345 size_t num_frames
= num_frames_arg
;
347 // I would like to use ACE_MAX below rather than ?:, but
348 // I get linker relocation errors such as the following when
350 // ld: fatal: relocation error: file: .shobj/Stack_Trace.o section:
351 // .rela.debug_line symbol: : relocation against a discarded symbol,
352 // symbol is part of discarded section:
353 // .text%const __type_0&ace_max<unsig\ned>(const __type_0&,const __type_0&)
355 const size_t starting_skip
= starting_frame
- 1;
356 #if ACE_STACK_TRACE_SKIP_FRAMES == 0
357 size_t skip_frames
= starting_skip
;
360 ACE_STACK_TRACE_SKIP_FRAMES
> starting_skip
?
361 ACE_STACK_TRACE_SKIP_FRAMES
: starting_skip
;
362 #endif /* ACE_STACK_TRACE_SKIP_FRAMES == 0 */
364 for (i
= 0; i
< skip_frames
&& sp
; ++i
)
366 sp
= cs_frame_adjust((frame
*) sp
->fr_savfp
);
375 && (*func
)((void*)sp
->fr_savpc
, usrarg
))
377 sp
= cs_frame_adjust((frame
*) sp
->fr_savfp
);
384 add_frame_to_buf (void* pc
, void* usrarg
)
386 char* buf
= (char*)usrarg
;
388 const char* func
= "??";
389 const char* lib
= "??";
391 if(dladdr(pc
, & info
) != 0)
393 lib
= (const char *) info
.dli_fname
;
394 func
= (const char *) info
.dli_sname
;
397 (void) ACE_OS::snprintf(buf
,
398 ACE_Stack_Trace::SYMBUFSIZ
,
403 //@@ Should the arithmetic on the following
404 //line be done with two void* ptrs? The result
405 //would be ptrdiff_t, and what is the correct
406 //sprintf() conversion character for that?
407 (size_t)pc
- (size_t)info
.dli_saddr
);
413 ACE_Stack_Trace::generate_trace (ssize_t starting_frame_offset
,
416 const size_t MAX_FRAMES
= 128;
417 const ssize_t INITIAL_FRAME
= 3;
420 num_frames
= MAX_FRAMES
;
422 size_t starting_frame
=
423 determine_starting_frame (INITIAL_FRAME
, starting_frame_offset
);
425 cs_operate (&add_frame_to_buf
, &this->buf_
[0], starting_frame
, num_frames
);
428 #elif defined(ACE_WIN64) && (_WIN32_WINNT <= _WIN32_WINNT_WIN2K)
429 # if defined(_MSC_VER)
430 # define STRING2(X) #X
431 # define STRING(X) STRING2(X)
432 # pragma message (__FILE__ "(" STRING(__LINE__) ") : warning: stack traces"\
433 " can't be generated on 64-bit Windows when _WIN32_WINNT is less than "\
439 ACE_Stack_Trace::generate_trace (ssize_t
, size_t)
441 ACE_OS::strcpy (&this->buf_
[0], "<stack traces unsupported on Win64 unless "
442 "ACE is built with _WIN32_WINNT set to 0x501 or above>");
445 #elif defined(ACE_WIN32) && !defined(ACE_HAS_WINCE) && !defined (__MINGW32__) \
446 && !defined(__BORLANDC__)
447 # include <windows.h>
448 # include <Dbghelp.h>
450 # define MAXTEXT 5000
453 //@TODO: Test with WCHAR
454 //@TODO: Need a common CriticalSection since dbghelp is not thread-safe
456 typedef struct _dbghelp_functions
458 HMODULE hMod
; //our handle to dbghelp.dll
460 //these already have typedefs in DbgHelp.h
461 DWORD64 (WINAPI
*SymGetModuleBase64
) (HANDLE hProc
, DWORD64 dwAddr
);
462 PVOID (WINAPI
*SymFunctionTableAccess64
) (HANDLE hProc
, DWORD64 AddrBase
);
464 typedef BOOL (WINAPI
*SymFromAddr_t
)
465 (HANDLE hProc
, DWORD64 Addr
, PDWORD64 Disp
, PSYMBOL_INFO Symbol
);
466 SymFromAddr_t SymFromAddr
;
468 typedef BOOL (WINAPI
*SymGetLineFromAddr64_t
) (HANDLE hProc
, DWORD64 dwAddr
,
469 PDWORD pdwDisplacement
,
470 PIMAGEHLP_LINE64 Line
);
471 SymGetLineFromAddr64_t SymGetLineFromAddr64
;
473 typedef DWORD (WINAPI
*SymSetOptions_t
) (DWORD SymOptions
);
474 SymSetOptions_t SymSetOptions
;
476 typedef DWORD (WINAPI
*SymGetOptions_t
) ();
477 SymGetOptions_t SymGetOptions
;
479 typedef BOOL (WINAPI
*SymInitialize_t
) (HANDLE hProc
, PCTSTR UserSearchPath
,
481 SymInitialize_t SymInitialize
;
484 (WINAPI
*StackWalk64_t
) (DWORD MachineType
, HANDLE hPRoc
, HANDLE hThr
,
485 LPSTACKFRAME64 StackFrame
, PVOID ContextRecord
,
486 PREAD_PROCESS_MEMORY_ROUTINE64 RMRoutine
,
487 PFUNCTION_TABLE_ACCESS_ROUTINE64 FTARoutine
,
488 PGET_MODULE_BASE_ROUTINE64 GMBRoutine
,
489 PTRANSLATE_ADDRESS_ROUTINE64 TranslateAddress
);
490 StackWalk64_t StackWalk64
;
492 typedef BOOL (WINAPI
*SymCleanup_t
) (HANDLE hProc
);
493 SymCleanup_t SymCleanup
;
497 # pragma warning (push)
498 # pragma warning (disable:4706)
499 static bool load_dbghelp_library_if_needed (dbghelp_functions
*pDbg
)
501 //@TODO: See codeproject's StackWalker.cpp for the list of locations to
502 //search so we get the "enhanced" dbghelp if the user has it but it is not
504 if (!(pDbg
->hMod
= ACE_TEXT_LoadLibrary (ACE_TEXT ("Dbghelp"))))
507 //@TODO: Cache this so we don't have to re-link every time. When to unload?
509 # define LINK(TYPE, NAME) (pDbg->NAME = \
510 (TYPE) GetProcAddress (pDbg->hMod, #NAME))
511 # define LINK_T(NAME) LINK (dbghelp_functions::NAME##_t, NAME)
512 return LINK (PGET_MODULE_BASE_ROUTINE64
, SymGetModuleBase64
)
513 && LINK (PFUNCTION_TABLE_ACCESS_ROUTINE64
, SymFunctionTableAccess64
)
514 && LINK_T (SymFromAddr
) && LINK_T (SymGetLineFromAddr64
)
515 && LINK_T (SymSetOptions
)&& LINK_T (SymGetOptions
)
516 && LINK_T (SymInitialize
) && LINK_T (StackWalk64
) && LINK_T (SymCleanup
);
520 # pragma warning (pop)
526 dbghelp_functions
*pDbg
;
530 add_frame_to_buf (struct frame_state
const *fs
, void *usrarg
)
532 if (fs
== 0 || usrarg
== 0)
535 char *buf
= static_cast<char *> (usrarg
);
538 DWORD64 dwModBase
= fs
->pDbg
->SymGetModuleBase64 (GetCurrentProcess (),
539 fs
->sf
.AddrPC
.Offset
);
540 if (fs
->pDbg
->SymFromAddr (GetCurrentProcess (),
541 fs
->sf
.AddrPC
.Offset
, &disp
, fs
->pSym
))
543 IMAGEHLP_LINE64 line
= {sizeof (IMAGEHLP_LINE64
)};
545 if (fs
->pDbg
->SymGetLineFromAddr64 (GetCurrentProcess (),
546 fs
->sf
.AddrPC
.Offset
,
549 (void) ACE_OS::snprintf (buf
, ACE_Stack_Trace::SYMBUFSIZ
,
550 "%s%s() %s: %d + 0x%x\n",
551 buf
, fs
->pSym
->Name
, line
.FileName
,
552 line
.LineNumber
, lineDisp
);
556 (void) ACE_OS::snprintf (buf
, ACE_Stack_Trace::SYMBUFSIZ
,
557 "%s%s()+0x%x [0x%x]\n",
558 buf
, fs
->pSym
->Name
, disp
,
559 fs
->sf
.AddrPC
.Offset
- dwModBase
);
564 (void) ACE_OS::snprintf (buf
, ACE_Stack_Trace::SYMBUFSIZ
,
566 buf
, fs
->sf
.AddrPC
.Offset
- dwModBase
);
571 static void emptyStack () { }
574 cs_operate(int (*func
)(struct frame_state
const *, void *), void *usrarg
,
575 size_t starting_frame
, size_t num_frames
)
577 dbghelp_functions dbg
;
578 if (!load_dbghelp_library_if_needed (&dbg
))
580 ACE_OS::strcpy (static_cast<char *> (usrarg
),
581 "<error loading dbghelp.dll>");
582 if (dbg
.hMod
) FreeLibrary (dbg
.hMod
);
587 ZeroMemory (&fs
.sf
, sizeof (fs
.sf
));
589 emptyStack (); //Not sure what this should do, Chad?
592 ZeroMemory (&c
, sizeof (CONTEXT
));
593 c
.ContextFlags
= CONTEXT_FULL
;
595 # if defined (_M_IX86)
596 DWORD machine
= IMAGE_FILE_MACHINE_I386
;
604 fs
.sf
.AddrPC
.Offset
= c
.Eip
;
605 fs
.sf
.AddrStack
.Offset
= c
.Esp
;
606 fs
.sf
.AddrFrame
.Offset
= c
.Ebp
;
607 fs
.sf
.AddrPC
.Mode
= AddrModeFlat
;
608 fs
.sf
.AddrStack
.Mode
= AddrModeFlat
;
609 fs
.sf
.AddrFrame
.Mode
= AddrModeFlat
;
610 # elif defined (_M_X64)
611 DWORD machine
= IMAGE_FILE_MACHINE_AMD64
;
612 RtlCaptureContext (&c
);
613 fs
.sf
.AddrPC
.Offset
= c
.Rip
;
614 fs
.sf
.AddrFrame
.Offset
= c
.Rsp
; //should be Rbp or Rdi instead?
615 fs
.sf
.AddrStack
.Offset
= c
.Rsp
;
616 fs
.sf
.AddrPC
.Mode
= AddrModeFlat
;
617 fs
.sf
.AddrFrame
.Mode
= AddrModeFlat
;
618 fs
.sf
.AddrStack
.Mode
= AddrModeFlat
;
619 # elif defined (_M_IA64)
620 DWORD machine
= IMAGE_FILE_MACHINE_IA64
;
621 RtlCaptureContext (&c
);
622 fs
.sf
.AddrPC
.Offset
= c
.StIIP
;
623 fs
.sf
.AddrFrame
.Offset
= c
.RsBSP
;
624 fs
.sf
.AddrBStore
.Offset
= c
.RsBSP
;
625 fs
.sf
.AddrStack
.Offset
= c
.IntSp
;
626 fs
.sf
.AddrPC
.Mode
= AddrModeFlat
;
627 fs
.sf
.AddrFrame
.Mode
= AddrModeFlat
;
628 fs
.sf
.AddrBStore
.Mode
= AddrModeFlat
;
629 fs
.sf
.AddrStack
.Mode
= AddrModeFlat
;
632 fs
.pSym
= (PSYMBOL_INFO
) GlobalAlloc (GMEM_FIXED
,
633 sizeof (SYMBOL_INFO
) +
634 sizeof (ACE_TCHAR
) * (SYMSIZE
- 1));
635 fs
.pSym
->SizeOfStruct
= sizeof (SYMBOL_INFO
);
636 fs
.pSym
->MaxNameLen
= SYMSIZE
* sizeof (ACE_TCHAR
);
637 dbg
.SymSetOptions (SYMOPT_DEFERRED_LOADS
| SYMOPT_LOAD_LINES
638 | SYMOPT_FAIL_CRITICAL_ERRORS
| dbg
.SymGetOptions ());
639 dbg
.SymInitialize (GetCurrentProcess (), 0, true);
640 //What does the "true" parameter mean when tracing the current process?
642 for (size_t current_frame
= 0; current_frame
< num_frames
+ starting_frame
;
645 BOOL ok
= dbg
.StackWalk64 (machine
,
646 GetCurrentProcess (),
649 dbg
.SymFunctionTableAccess64
,
650 dbg
.SymGetModuleBase64
, 0);
651 if (!ok
|| fs
.sf
.AddrFrame
.Offset
== 0)
654 if (current_frame
< starting_frame
)
660 dbg
.SymCleanup (GetCurrentProcess ());
661 GlobalFree (fs
.pSym
);
662 FreeLibrary (dbg
.hMod
);
668 ACE_Stack_Trace::generate_trace (ssize_t starting_frame_offset
,
671 const size_t MAX_FRAMES
= 128;
672 const ssize_t INITIAL_FRAME
= 3;
675 num_frames
= MAX_FRAMES
;
677 size_t starting_frame
=
678 determine_starting_frame (INITIAL_FRAME
, starting_frame_offset
);
680 cs_operate (&add_frame_to_buf
, &this->buf_
[0], starting_frame
, num_frames
);
683 #else // Unsupported platform
685 ACE_Stack_Trace::generate_trace (ssize_t
, size_t)
687 // Call determine_starting_frame() on HP aCC build to resolve declared
688 // method never referenced warning.
689 #if defined (__HP_aCC)
690 size_t starting_frame
= determine_starting_frame (0, 0);
693 ACE_OS::strcpy (&this->buf_
[0], UNSUPPORTED
);