39 # include <imagehlp.h>
43 # include <sys/wait.h>
44 # include <sys/resource.h>
45 # if HAVE_BACKTRACE_SYMBOLS_FD // GNU
46 # include <execinfo.h>
50 # if HAVE_DLADDR // Linux, Solaris
57 # if defined __KCC && defined __sgi
58 # include </usr/include/exception.h>
60 # include <exception.h>
63 # if HAVE_EXCPT_H // IRIX
65 # undef try // Defined on SGI to structured exception handling goop
66 # undef catch // Defined on SGI to structured exception handling goop
68 # if HAVE_RLD_INTERFACE_H // Tru64 (IRIX)
69 # include <rld_interface.h>
71 # if HAVE_PDSC_H // Tru64
74 # if __GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) // GCC 3.4+ C++ ABI
81 # define STDERR_HANDLE GetStdHandle (STD_ERROR_HANDLE)
83 # define STDERR_HANDLE STDERR_FILENO
90 # define MYWRITE(fd,data,n) do { DWORD written; WriteFile(fd,data,n,\
91 &written,0); } while (0)
93 # define MYWRITE(fd,data,n) write(fd,data,n)
97 # define MYWRITELIT(fd,str) MYWRITE(fd,str,sizeof(str)-1)
103 #if HAVE_BACKTRACE_SYMBOLS_FD
106 static const int MAX_BACKTRACE_DEPTH = 128;
110 #if HAVE_BACKTRACE_SYMBOLS_FD && HAVE_DLADDR
117 std::string addr2LinePath =
"/usr/bin/eu-addr2line";
129 if (
access (addr2LinePath.c_str(), F_OK) == 0) {
135 while (!
path.empty()) {
136 std::string::size_type
pos =
path.find (
':');
138 if (
pos != std::string::npos) ++
pos;
141 std::string
p1 =
dir +
"/eu-addr2line";
142 if (
access (
p1.c_str(), F_OK) == 0) {
147 std::string
p2 =
dir +
"/addr2line";
148 if (
access (
p2.c_str(), F_OK) == 0) {
155 BacktraceInit backtraceInit;
161 int stacktracePopenFD (
const char*
cmd,
pid_t& child_pid)
171 int parent_end = fds[0];
172 int child_end = fds[1];
186 if (child_pid == 0) {
187 int child_std_end = 1;
189 if (child_end != child_std_end) {
190 dup2 (child_end, child_std_end);
200 execl (
"/bin/sh",
"sh",
"-c",
cmd, (
char *) 0);
214 int stacktracePcloseFD (
int fd,
pid_t child_pid)
226 wait_pid = waitpid (child_pid, &wstatus, 0);
227 }
while (wait_pid == -1 && errno == EINTR);
235 int stacktraceReadline (
int fd,
char* buf,
int buflen)
238 while (len < buflen-1) {
241 if (
stat == 0)
break;
242 if (*buf ==
'\n')
break;
286 GetLogicalAddress (PVOID addr, PTSTR
name, DWORD
length,
289 MEMORY_BASIC_INFORMATION
info;
291 if (! VirtualQuery (addr, &
info,
sizeof (
info)))
298 PIMAGE_DOS_HEADER dosheader = (PIMAGE_DOS_HEADER)
module;
299 PIMAGE_NT_HEADERS ntheader
300 = (PIMAGE_NT_HEADERS) (
module + dosheader->e_lfanew);
301 PIMAGE_SECTION_HEADER sect = IMAGE_FIRST_SECTION (ntheader);
302 DWORD rva = (DWORD) addr -
module;
304 for (
unsigned i = 0;
i < ntheader->FileHeader.NumberOfSections; ++
i,++sect)
306 DWORD sect_start = sect->VirtualAddress;
307 DWORD sect_end = sect_start +
std::max (sect->SizeOfRawData,
308 sect->Misc.VirtualSize);
310 if ((rva >= sect_start) && (rva <= sect_end))
313 offset = rva - sect_start;
334 char addrbuf [addrbuf_size];
336 #if HAVE_BACKTRACE_SYMBOLS_FD && HAVE_DLADDR
338 char diffbuf [diffbuf_size];
339 static const char trailer [] =
"]\n";
342 char dembuf[ LINE_MAX ];
343 char line[ LINE_MAX ];
345 char relbuf [relbuf_size];
347 if (dladdr ((
void*)addr, &
info) &&
info.dli_fname &&
info.dli_fname[0])
349 const char *libname =
info.dli_fname;
351 unsigned long symaddr = (
unsigned long)
info.dli_saddr;
352 bool gte = (addr >= symaddr);
353 unsigned long diff = (gte ? addr - symaddr : symaddr - addr);
359 unsigned long libaddr = (
unsigned long)
info.dli_fbase;
360 unsigned long relative_address = (addr >= libaddr) ? addr - libaddr : libaddr - addr;
370 if (strstr (
info.dli_fname,
".so") == 0 && libaddr == 0x400000)
371 relative_address = addr;
376 const char* symname = dembuf;
380 size_t len = strlen(
info.dli_fname);
381 if ( len > 0 && len + 80 < LINE_MAX)
383 if (
getenv (
"LD_PRELOAD"))
384 unsetenv (
"LD_PRELOAD");
386 if ( addr2LinePath ==
"/usr/bin/eu-addr2line" )
388 snprintf (
line, LINE_MAX,
"%s -f -e %s %p | /usr/bin/c++filt | /usr/bin/tr \\\\012 \\\\040 ",
389 addr2LinePath.c_str(),
391 (
void*)relative_address);
395 snprintf (
line, LINE_MAX,
"%s -f -C -e %s %p",
396 addr2LinePath.c_str(),
398 (
void*)relative_address);
401 pfd = stacktracePopenFD(
line, child_pid );
409 demlen = stacktraceReadline (pfd, dembuf,
sizeof(dembuf));
414 int stat = stacktracePcloseFD (pfd, child_pid);
423 if (
stat || demlen <= 0 || dembuf[0] ==
'?') {
424 symname =
info.dli_sname;
425 if (!symname) symname =
"???";
426 demlen = strlen (symname);
433 bufs [nbufs].iov_base = addrbuf;
434 bufs [nbufs].iov_len = snprintf (addrbuf, addrbuf_size,
" 0x%08lx ", addr);
437 bufs [nbufs].iov_base = (
void *) symname;
438 bufs [nbufs].iov_len = demlen;
442 bufs [nbufs].iov_base =
line;
443 bufs [nbufs].iov_len =
length;
447 bufs [nbufs].iov_base = diffbuf;
448 bufs [nbufs].iov_len = snprintf (diffbuf, diffbuf_size,
" %c 0x%lx [",
449 gte ?
'+' :
'-',
diff);
452 bufs [nbufs].iov_base = (
void *) libname;
453 bufs [nbufs].iov_len = strlen (libname);
457 bufs [nbufs].iov_base = relbuf;
458 bufs [nbufs].iov_len = snprintf( relbuf, relbuf_size,
" D[%p]", (
void*)relative_address );
462 bufs [nbufs].iov_base = (
void *) trailer;
463 bufs [nbufs].iov_len = 2;
470 bufs [nbufs].iov_base = addrbuf;
471 bufs [nbufs].iov_len = snprintf (addrbuf, addrbuf_size,
" 0x%08lx ", addr);
474 bufs [nbufs].iov_base = (
void *)
"<unknown function>\n";
475 bufs [nbufs].iov_len = 19;
479 writev (
fd, bufs, nbufs);
483 #if !(HAVE_BACKTRACE_SYMBOLS_FD && HAVE_DLADDR) && __GNUC__ >=4
485 typedef unsigned _Unwind_Ptr
__attribute__((__mode__(__pointer__)));
486 struct _Unwind_Context;
490 _URC_FOREIGN_EXCEPTION_CAUGHT = 1,
491 _URC_FATAL_PHASE2_ERROR = 2,
492 _URC_FATAL_PHASE1_ERROR = 3,
493 _URC_NORMAL_STOP = 4,
494 _URC_END_OF_STACK = 5,
495 _URC_HANDLER_FOUND = 6,
496 _URC_INSTALL_CONTEXT = 7,
497 _URC_CONTINUE_UNWIND = 8
498 } _Unwind_Reason_Code;
499 typedef _Unwind_Reason_Code (*_Unwind_Trace_Fn) (_Unwind_Context *,
void *);
500 extern _Unwind_Reason_Code _Unwind_Backtrace (_Unwind_Trace_Fn,
void *);
501 extern _Unwind_Ptr _Unwind_GetIP (_Unwind_Context *);
502 extern _Unwind_Ptr _Unwind_GetRegionStart (_Unwind_Context *);
512 unwindWalkStack (_Unwind_Context *ctx,
void *
data)
518 char addrbuf [addrbuf_size];
520 char diffbuf [diffbuf_size];
521 static const char trailer [] =
"]\n";
522 unsigned long ip = _Unwind_GetIP (ctx);
523 unsigned long ir = _Unwind_GetRegionStart (ctx);
527 if (dladdr ((
void *)
ir, &
info) &&
info.dli_fname &&
info.dli_fname[0])
529 const char *libname =
info.dli_fname;
530 const char *symname = (
info.dli_sname &&
info.dli_sname[0]
531 ?
info.dli_sname :
"?");
532 unsigned long symaddr = (
unsigned long)
info.dli_saddr;
533 bool gte = (
ip >= symaddr);
534 unsigned long diff = (gte ?
ip - symaddr : symaddr -
ip);
536 bufs [nbufs].iov_base = addrbuf;
537 bufs [nbufs].iov_len = snprintf (addrbuf, addrbuf_size,
" 0x%08lx ",
ip);
540 bufs [nbufs].iov_base = (
char *) symname;
541 bufs [nbufs].iov_len = strlen (symname);
544 bufs [nbufs].iov_base = diffbuf;
545 bufs [nbufs].iov_len = snprintf (diffbuf, diffbuf_size,
" %s 0x%lx [",
546 gte ?
"+" :
"-",
diff);
549 bufs [nbufs].iov_base = (
char *) libname;
550 bufs [nbufs].iov_len = strlen (libname);
553 bufs [nbufs].iov_base = (
char *) trailer;
554 bufs [nbufs].iov_len = 2;
558 # endif // HAVE_DLADDR
560 bufs [nbufs].iov_base = addrbuf;
561 bufs [nbufs].iov_len = snprintf (addrbuf, addrbuf_size,
" 0x%08lx ",
ip);
564 bufs [nbufs].iov_base = diffbuf;
565 bufs [nbufs].iov_len = snprintf (diffbuf, diffbuf_size,
" <?%08lx> + 0x%lx\n",
570 writev (
fd, bufs, nbufs);
571 return _URC_NO_REASON;
580 addr2LinePath =
path;
584 #if HAVE_U_STACK_TRACE
586 extern "C" void U_STACK_TRACE (
void);
591 extern "C" void xl__trbk (
void);
644 if (! SymInitialize (GetCurrentProcess (), NULL,
TRUE))
647 " cannot get symbolic information\n"));
653 BYTE
buffer [
sizeof (IMAGEHLP_SYMBOL) + 512 ];
664 const int buf_size = 2*40+6;
670 context.ContextFlags = CONTEXT_FULL;
671 if (! GetThreadContext (GetCurrentThread (), &context))
680 memset (&frame, 0,
sizeof (frame));
684 frame.AddrPC.Offset = context.Eip;
685 frame.AddrPC.Mode = AddrModeFlat;
686 frame.AddrStack.Offset = context.Esp;
687 frame.AddrStack.Mode = AddrModeFlat;
688 frame.AddrFrame.Offset = context.Ebp;
689 frame.AddrFrame.Mode = AddrModeFlat;
693 if (! StackWalk (IMAGE_FILE_MACHINE_I386,
694 GetCurrentProcess (),
699 SymFunctionTableAccess,
702 || frame.AddrFrame.Offset == 0)
711 MYWRITE (
fd, buf, snprintf (buf, buf_size,
"(%2u) 0x%08lx 0x%08lx ",
712 level, frame.AddrPC.Offset,
713 frame.AddrFrame.Offset));
715 memset (&symbol, 0,
sizeof (symbol));
716 symbol.sym.SizeOfStruct =
sizeof (symbol);
717 symbol.sym.MaxNameLength =
sizeof (symbol) -
sizeof (symbol.sym);
720 if (SymGetSymFromAddr (GetCurrentProcess (), frame.AddrPC.Offset,
731 MYWRITE (
fd, symbol.sym.Name, STDC::strlen (symbol.sym.Name));
734 if (SymGetModuleInfo (GetCurrentProcess(), frame.AddrPC.Offset,
739 STDC::strlen (
module.ImageName));
745 GetLogicalAddress ((PVOID) frame.AddrPC.Offset,
755 SymCleanup (GetCurrentProcess ());
757 #elif (HAVE_U_STACK_TRACE || HAVE_XL_TRBK) // hp-ux, aix
759 int stderrfd = dup (STDERR_FILENO);
763 int newfd = dup2 (
fd, STDERR_FILENO);
770 # if HAVE_U_STACK_TRACE // hp-ux
772 # elif HAVE_XL_TRBK // aix
775 # error "oops, you shouldn't have gotten here!"
779 dup2 (stderrfd, STDERR_FILENO);
781 #elif HAVE_LINUX_UNWIND_BACKTRACE
782 CxxUtils::backtraceByUnwind (stacktraceLine,
fd);
784 #elif HAVE_BACKTRACE_SYMBOLS_FD && HAVE_DLADDR // linux
787 void *trace [MAX_BACKTRACE_DEPTH];
792 unsigned long addr = (
unsigned long) trace [
n];
793 stacktraceLine (
fd, addr);
796 #elif HAVE_EXCPT_H && HAVE_PDSC_H && HAVE_RLD_INTERFACE_H // tru64
802 char buffer [buffer_size];
806 exc_capture_context (&context);
807 while (!rc && context.sc_pc)
810 pdsc_crd *func, *
base, *crd
811 = exc_remote_lookup_function_entry(0, 0, context.sc_pc, 0, &func, &
base);
812 Elf32_Addr addr = PDSC_CRD_BEGIN_ADDRESS(
base, func);
814 const char *
name =
"<unknown function>";
815 snprintf (
buffer, buffer_size,
" 0x%012lx %.100s + 0x%lx\n",
816 context.sc_pc,
name, context.sc_pc - addr);
818 rc = exc_virtual_unwind(0, &context);
821 #elif HAVE_EXCEPTION_H && defined __sgi // irix
830 exc_setjmp (&context);
831 while (context.sc_pc >= 4)
840 const char *libname = 0;
841 const char *symname = 0;
845 Elf32_Addr
pc = context.sc_pc;
846 Dwarf_Fde fde = find_fde_name (&
pc, &
name);
847 Dwarf_Addr low_pc = context.sc_pc;
848 Dwarf_Unsigned udummy;
857 if (dwarf_get_fde_range (fde, &low_pc, &udummy, &pdummy, &udummy,
858 &odummy, &sdummy, &odummy, &
err) == DW_DLV_OK)
859 offset = context.sc_pc - low_pc;
868 Elf32_Addr addr = context.sc_pc;
871 if (_rld_new_interface (_RLD_DLADDR, addr, &
info))
873 if (
info.dli_fname &&
info.dli_fname [0])
874 libname =
info.dli_fname;
876 Elf32_Addr symaddr = (Elf32_Addr)
info.dli_saddr;
877 if (symaddr == low_pc)
879 else if (
info.dli_sname
880 &&
info.dli_sname [0]
881 && addr - symaddr <
offset)
884 symname =
info.dli_sname;
889 if (libname && symname)
891 (
buffer, buffer_size,
" 0x%012lx %.100s + 0x%lx [%.200s]\n",
892 addr, symname,
offset, libname));
895 (
buffer, buffer_size,
" 0x%012lx %.100s + 0x%lx\n",
899 (
buffer, buffer_size,
" 0x%012lx <unknown function>\n", addr));
913 if (
pc != context.sc_pc)
916 exc_unwind (&context, fde);
919 #elif defined PROG_PSTACK // solaris
921 # define CXXFILTER " | " PROG_CXXFILT
928 char buffer [buffer_size];
929 snprintf (
buffer, buffer_size,
"%s %lu%s 1>&%d", PROG_PSTACK, (
unsigned long) getpid (),
934 #elif __GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 4)
936 _Unwind_Backtrace (unwindWalkStack, &
fd);
981 if ((corepid = ::fork ()) == 0)
1006 else if (corepid > 0) {
1009 wait_pid = ::waitpid (corepid, &
status, 0);
1010 }
while (wait_pid == -1 && errno == EINTR);
1028 struct rlimit core_limit;
1029 getrlimit(RLIMIT_CORE, &core_limit);
1031 unsigned long old_limit = core_limit.rlim_cur;
1032 core_limit.rlim_cur = core_limit.rlim_max;
1033 if ( setrlimit(RLIMIT_CORE, &core_limit) == 0 ) {
1034 return core_limit.rlim_cur;
1048 struct rlimit core_limit;
1049 core_limit.rlim_cur = 0;
1050 setrlimit(RLIMIT_CORE, &core_limit);