Initial Patch of Auction House bot rev. 135
[auctionmangos.git] / dep / ACE_wrappers / ace / Stack_Trace.cpp
blob082cca8a88a93ffe60a94f7d49898b1c125e03e7
1 //=============================================================================
2 /**
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)
30 : buflen_(0)
32 // cannot initialize arrays, so we must assign.
33 this->buf_[0] = '\0';
34 this->generate_trace (starting_frame_offset, num_frames);
37 const char*
38 ACE_Stack_Trace::c_str () const
40 return &this->buf_[0];
43 static inline size_t
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>
53 void
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;
61 char** stack_syms;
63 if (num_frames == 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]));
70 if (stack_size != 0)
72 stack_syms = ::backtrace_symbols (stack, stack_size);
74 for (size_t i = starting_frame;
75 i < stack_size && num_frames > 0;
76 i++, num_frames--)
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
88 ::free (stack_syms);
90 else
92 ACE_OS::strcpy (&this->buf_[0], UNABLE_TO_GET_TRACE);
95 #elif defined(VXWORKS) && !defined(__RTP__)
96 # include <trcLib.h>
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)
105 char* buf;
106 size_t& buflen;
107 size_t num_frames;
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;
115 static void
116 ACE_Stack_Trace_Add_Frame_To_Buf (INSTR *caller,
117 unsigned int func,
118 unsigned int nargs,
119 unsigned int *args)
121 if (ACE_Stack_Trace_stateptr == 0)
122 return;
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)
132 return;
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)
148 if (i != 0)
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");
156 void
157 ACE_Stack_Trace::generate_trace (ssize_t starting_frame_offset,
158 size_t num_frames)
160 const size_t MAX_FRAMES = 128;
161 const ssize_t INITIAL_FRAME = 3;
163 if (num_frames == 0)
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);
172 REG_SET regs;
174 taskRegsGet ((int)taskIdSelf(), &regs);
175 // Maybe we should take a lock here to guard stateptr?
176 ACE_Stack_Trace_stateptr = &state;
177 trcStack (&regs, (FUNCPTR)ACE_Stack_Trace_Add_Frame_To_Buf, taskIdSelf ());
181 #elif defined(VXWORKS) && defined(__RTP__)
182 # include <setjmp.h>
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;
193 void
194 ACE_Stack_Trace::generate_trace (ssize_t starting_frame_offset,
195 size_t num_frames)
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);
204 jmp_buf regs;
205 setjmp (regs);
207 TASK_DESC desc;
208 if (taskInfoGet (taskIdSelf (), &desc) == ERROR) return;
210 TRC_OS_CTX osCtx;
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)
220 char *prevFp;
221 INSTR *prevPc;
222 INSTR *prevFn;
224 if (trcLibFuncs.lvlInfoGet (fp, pc, &osCtx, &prevFp, &prevPc, &prevFn)
225 == ERROR)
227 ACE_OS::strcpy (this->buf_, UNABLE_TO_GET_TRACE);
228 return;
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;
241 int buf[N_ARGS];
242 int *pArgs = 0;
243 int numArgs =
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",
254 prevFn, fnName);
255 cursor += written;
256 space -= written;
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",
264 pArgs[arg]);
265 cursor += written;
266 space -= written;
267 if (space && arg == numArgs - 1) *cursor++ = ')', --space;
269 if (space) *cursor++ = '\n', --space;
270 *cursor++ = 0; //we saved space for the null terminator
273 fp = prevFp;
274 pc = prevPc;
278 #elif defined(sun)
280 * walks up call stack, printing library:routine+offset for each routine
283 # include <dlfcn.h>
284 # include <setjmp.h>
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
297 # endif
298 # endif
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
304 # endif
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
310 # endif
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
316 # endif
318 static frame*
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.
332 static int
333 cs_operate(int (*func)(void *, void *), void * usrarg,
334 size_t starting_frame, size_t num_frames_arg)
336 ACE_STACK_TRACE_FLUSHWIN();
338 jmp_buf env;
339 setjmp(env);
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
349 // I use it:
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;
358 #else
359 size_t skip_frames =
360 ACE_STACK_TRACE_SKIP_FRAMES > starting_skip ?
361 ACE_STACK_TRACE_SKIP_FRAMES : starting_skip;
362 #endif /* ACE_STACK_TRACE_SKIP_FRAMES == 0 */
363 size_t i;
364 for (i = 0; i < skip_frames && sp; ++i)
366 sp = cs_frame_adjust((frame*) sp->fr_savfp);
369 i = 0;
371 while ( sp
372 && sp->fr_savpc
373 && ++i
374 && --num_frames
375 && (*func)((void*)sp->fr_savpc, usrarg))
377 sp = cs_frame_adjust((frame*) sp->fr_savfp);
380 return(i);
383 static int
384 add_frame_to_buf (void* pc, void* usrarg)
386 char* buf = (char*)usrarg;
387 Dl_info info;
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,
399 "%s%s:%s+0x%x\n",
400 buf,
401 lib,
402 func,
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);
409 return(1);
412 void
413 ACE_Stack_Trace::generate_trace (ssize_t starting_frame_offset,
414 size_t num_frames)
416 const size_t MAX_FRAMES = 128;
417 const ssize_t INITIAL_FRAME = 3;
419 if (num_frames == 0)
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 "\
434 "0x501.")
435 # undef STRING
436 # undef STRING2
437 # endif /*_MSC_VER*/
438 void
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
451 # define SYMSIZE 100
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,
480 BOOL invasive);
481 SymInitialize_t SymInitialize;
483 typedef BOOL
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;
494 } dbghelp_functions;
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
503 //first on the path.
504 if (!(pDbg->hMod = ACE_TEXT_LoadLibrary (ACE_TEXT ("Dbghelp"))))
505 return false;
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);
517 # undef LINK
518 # undef LINK_T
520 # pragma warning (pop)
523 struct frame_state {
524 STACKFRAME64 sf;
525 PSYMBOL_INFO pSym;
526 dbghelp_functions *pDbg;
529 static int
530 add_frame_to_buf (struct frame_state const *fs, void *usrarg)
532 if (fs == 0 || usrarg == 0)
533 return -1;
535 char *buf = static_cast<char *> (usrarg);
537 DWORD64 disp;
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)};
544 DWORD lineDisp;
545 if (fs->pDbg->SymGetLineFromAddr64 (GetCurrentProcess (),
546 fs->sf.AddrPC.Offset,
547 &lineDisp, &line))
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);
554 else
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);
562 else
564 (void) ACE_OS::snprintf (buf, ACE_Stack_Trace::SYMBUFSIZ,
565 "%s[0x%x]\n",
566 buf, fs->sf.AddrPC.Offset - dwModBase);
568 return 0;
571 static void emptyStack () { }
573 static int
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);
583 return 1;
586 frame_state fs;
587 ZeroMemory (&fs.sf, sizeof (fs.sf));
588 fs.pDbg = &dbg;
589 emptyStack (); //Not sure what this should do, Chad?
591 CONTEXT c;
592 ZeroMemory (&c, sizeof (CONTEXT));
593 c.ContextFlags = CONTEXT_FULL;
595 # if defined (_M_IX86)
596 DWORD machine = IMAGE_FILE_MACHINE_I386;
597 __asm {
598 call x
599 x: pop eax
600 mov c.Eip, eax
601 mov c.Ebp, ebp
602 mov c.Esp, esp
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;
630 # endif
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;
643 ++current_frame)
645 BOOL ok = dbg.StackWalk64 (machine,
646 GetCurrentProcess (),
647 GetCurrentThread (),
648 &fs.sf, &c, 0,
649 dbg.SymFunctionTableAccess64,
650 dbg.SymGetModuleBase64, 0);
651 if (!ok || fs.sf.AddrFrame.Offset == 0)
652 break;
654 if (current_frame < starting_frame)
655 continue;
657 func (&fs, usrarg);
660 dbg.SymCleanup (GetCurrentProcess ());
661 GlobalFree (fs.pSym);
662 FreeLibrary (dbg.hMod);
664 return 0;
667 void
668 ACE_Stack_Trace::generate_trace (ssize_t starting_frame_offset,
669 size_t num_frames)
671 const size_t MAX_FRAMES = 128;
672 const ssize_t INITIAL_FRAME = 3;
674 if (num_frames == 0)
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
684 void
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);
691 #endif
693 ACE_OS::strcpy (&this->buf_[0], UNSUPPORTED);
695 #endif