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 if (dladdr ((
void*)addr, &
info) &&
info.dli_fname &&
info.dli_fname[0])
347 const char *libname =
info.dli_fname;
349 unsigned long symaddr = (
unsigned long)
info.dli_saddr;
350 bool gte = (addr >= symaddr);
351 unsigned long diff = (gte ? addr - symaddr : symaddr - addr);
357 char relbuf [relbuf_size];
360 unsigned long libaddr = (
unsigned long)
info.dli_fbase;
361 unsigned long relative_address = (addr >= libaddr) ? addr - libaddr : libaddr - addr;
371 if (strstr (
info.dli_fname,
".so") == 0 && libaddr == 0x400000)
372 relative_address = addr;
377 const char* symname = dembuf;
381 size_t len = strlen(
info.dli_fname);
382 if ( len > 0 && len + 80 < LINE_MAX)
384 if (
getenv (
"LD_PRELOAD"))
385 unsetenv (
"LD_PRELOAD");
387 if ( addr2LinePath ==
"/usr/bin/eu-addr2line" )
389 snprintf (
line, LINE_MAX,
"%s -f -e %s %p | /usr/bin/c++filt | /usr/bin/tr \\\\012 \\\\040 ",
390 addr2LinePath.c_str(),
392 (
void*)relative_address);
396 snprintf (
line, LINE_MAX,
"%s -f -C -e %s %p",
397 addr2LinePath.c_str(),
399 (
void*)relative_address);
402 pfd = stacktracePopenFD(
line, child_pid );
410 demlen = stacktraceReadline (pfd, dembuf,
sizeof(dembuf));
415 int stat = stacktracePcloseFD (pfd, child_pid);
424 if (
stat || demlen <= 0 || dembuf[0] ==
'?') {
425 symname =
info.dli_sname;
426 if (!symname) symname =
"???";
427 demlen = strlen (symname);
434 bufs [nbufs].iov_base = addrbuf;
435 bufs [nbufs].iov_len = snprintf (addrbuf, addrbuf_size,
" 0x%08lx ", addr);
438 bufs [nbufs].iov_base = (
void *) symname;
439 bufs [nbufs].iov_len = demlen;
443 bufs [nbufs].iov_base =
line;
444 bufs [nbufs].iov_len =
length;
448 bufs [nbufs].iov_base = diffbuf;
449 bufs [nbufs].iov_len = snprintf (diffbuf, diffbuf_size,
" %c 0x%lx [",
450 gte ?
'+' :
'-',
diff);
453 bufs [nbufs].iov_base = (
void *) libname;
454 bufs [nbufs].iov_len = strlen (libname);
458 bufs [nbufs].iov_base = relbuf;
459 bufs [nbufs].iov_len = snprintf( relbuf, relbuf_size,
" D[%p]", (
void*)relative_address );
463 bufs [nbufs].iov_base = (
void *) trailer;
464 bufs [nbufs].iov_len = 2;
471 bufs [nbufs].iov_base = addrbuf;
472 bufs [nbufs].iov_len = snprintf (addrbuf, addrbuf_size,
" 0x%08lx ", addr);
475 bufs [nbufs].iov_base = (
void *)
"<unknown function>\n";
476 bufs [nbufs].iov_len = 19;
480 writev (
fd, bufs, nbufs);
484 #if !(HAVE_BACKTRACE_SYMBOLS_FD && HAVE_DLADDR) && __GNUC__ >=4
486 typedef unsigned _Unwind_Ptr
__attribute__((__mode__(__pointer__)));
487 struct _Unwind_Context;
491 _URC_FOREIGN_EXCEPTION_CAUGHT = 1,
492 _URC_FATAL_PHASE2_ERROR = 2,
493 _URC_FATAL_PHASE1_ERROR = 3,
494 _URC_NORMAL_STOP = 4,
495 _URC_END_OF_STACK = 5,
496 _URC_HANDLER_FOUND = 6,
497 _URC_INSTALL_CONTEXT = 7,
498 _URC_CONTINUE_UNWIND = 8
499 } _Unwind_Reason_Code;
500 typedef _Unwind_Reason_Code (*_Unwind_Trace_Fn) (_Unwind_Context *,
void *);
501 extern _Unwind_Reason_Code _Unwind_Backtrace (_Unwind_Trace_Fn,
void *);
502 extern _Unwind_Ptr _Unwind_GetIP (_Unwind_Context *);
503 extern _Unwind_Ptr _Unwind_GetRegionStart (_Unwind_Context *);
513 unwindWalkStack (_Unwind_Context *ctx,
void *
data)
519 char addrbuf [addrbuf_size];
521 char diffbuf [diffbuf_size];
522 static const char trailer [] =
"]\n";
523 unsigned long ip = _Unwind_GetIP (ctx);
524 unsigned long ir = _Unwind_GetRegionStart (ctx);
528 if (dladdr ((
void *)
ir, &
info) &&
info.dli_fname &&
info.dli_fname[0])
530 const char *libname =
info.dli_fname;
531 const char *symname = (
info.dli_sname &&
info.dli_sname[0]
532 ?
info.dli_sname :
"?");
533 unsigned long symaddr = (
unsigned long)
info.dli_saddr;
534 bool gte = (
ip >= symaddr);
535 unsigned long diff = (gte ?
ip - symaddr : symaddr -
ip);
537 bufs [nbufs].iov_base = addrbuf;
538 bufs [nbufs].iov_len = snprintf (addrbuf, addrbuf_size,
" 0x%08lx ",
ip);
541 bufs [nbufs].iov_base = (
char *) symname;
542 bufs [nbufs].iov_len = strlen (symname);
545 bufs [nbufs].iov_base = diffbuf;
546 bufs [nbufs].iov_len = snprintf (diffbuf, diffbuf_size,
" %s 0x%lx [",
547 gte ?
"+" :
"-",
diff);
550 bufs [nbufs].iov_base = (
char *) libname;
551 bufs [nbufs].iov_len = strlen (libname);
554 bufs [nbufs].iov_base = (
char *) trailer;
555 bufs [nbufs].iov_len = 2;
559 # endif // HAVE_DLADDR
561 bufs [nbufs].iov_base = addrbuf;
562 bufs [nbufs].iov_len = snprintf (addrbuf, addrbuf_size,
" 0x%08lx ",
ip);
565 bufs [nbufs].iov_base = diffbuf;
566 bufs [nbufs].iov_len = snprintf (diffbuf, diffbuf_size,
" <?%08lx> + 0x%lx\n",
571 writev (
fd, bufs, nbufs);
572 return _URC_NO_REASON;
581 addr2LinePath =
path;
585 #if HAVE_U_STACK_TRACE
587 extern "C" void U_STACK_TRACE (
void);
592 extern "C" void xl__trbk (
void);
645 if (! SymInitialize (GetCurrentProcess (), NULL,
TRUE))
648 " cannot get symbolic information\n"));
654 BYTE
buffer [
sizeof (IMAGEHLP_SYMBOL) + 512 ];
665 const int buf_size = 2*40+6;
671 context.ContextFlags = CONTEXT_FULL;
672 if (! GetThreadContext (GetCurrentThread (), &context))
681 memset (&frame, 0,
sizeof (frame));
685 frame.AddrPC.Offset = context.Eip;
686 frame.AddrPC.Mode = AddrModeFlat;
687 frame.AddrStack.Offset = context.Esp;
688 frame.AddrStack.Mode = AddrModeFlat;
689 frame.AddrFrame.Offset = context.Ebp;
690 frame.AddrFrame.Mode = AddrModeFlat;
694 if (! StackWalk (IMAGE_FILE_MACHINE_I386,
695 GetCurrentProcess (),
700 SymFunctionTableAccess,
703 || frame.AddrFrame.Offset == 0)
712 MYWRITE (
fd, buf, snprintf (buf, buf_size,
"(%2u) 0x%08lx 0x%08lx ",
713 level, frame.AddrPC.Offset,
714 frame.AddrFrame.Offset));
716 memset (&symbol, 0,
sizeof (symbol));
717 symbol.sym.SizeOfStruct =
sizeof (symbol);
718 symbol.sym.MaxNameLength =
sizeof (symbol) -
sizeof (symbol.sym);
721 if (SymGetSymFromAddr (GetCurrentProcess (), frame.AddrPC.Offset,
732 MYWRITE (
fd, symbol.sym.Name, STDC::strlen (symbol.sym.Name));
735 if (SymGetModuleInfo (GetCurrentProcess(), frame.AddrPC.Offset,
740 STDC::strlen (
module.ImageName));
746 GetLogicalAddress ((PVOID) frame.AddrPC.Offset,
756 SymCleanup (GetCurrentProcess ());
758 #elif (HAVE_U_STACK_TRACE || HAVE_XL_TRBK) // hp-ux, aix
760 int stderrfd = dup (STDERR_FILENO);
764 int newfd = dup2 (
fd, STDERR_FILENO);
771 # if HAVE_U_STACK_TRACE // hp-ux
773 # elif HAVE_XL_TRBK // aix
776 # error "oops, you shouldn't have gotten here!"
780 dup2 (stderrfd, STDERR_FILENO);
782 #elif HAVE_LINUX_UNWIND_BACKTRACE
783 CxxUtils::backtraceByUnwind (stacktraceLine,
fd);
785 #elif HAVE_BACKTRACE_SYMBOLS_FD && HAVE_DLADDR // linux
788 void *trace [MAX_BACKTRACE_DEPTH];
793 unsigned long addr = (
unsigned long) trace [
n];
794 stacktraceLine (
fd, addr);
797 #elif HAVE_EXCPT_H && HAVE_PDSC_H && HAVE_RLD_INTERFACE_H // tru64
803 char buffer [buffer_size];
807 exc_capture_context (&context);
808 while (!rc && context.sc_pc)
811 pdsc_crd *func, *
base, *crd
812 = exc_remote_lookup_function_entry(0, 0, context.sc_pc, 0, &func, &
base);
813 Elf32_Addr addr = PDSC_CRD_BEGIN_ADDRESS(
base, func);
815 const char *
name =
"<unknown function>";
816 snprintf (
buffer, buffer_size,
" 0x%012lx %.100s + 0x%lx\n",
817 context.sc_pc,
name, context.sc_pc - addr);
819 rc = exc_virtual_unwind(0, &context);
822 #elif HAVE_EXCEPTION_H && defined __sgi // irix
831 exc_setjmp (&context);
832 while (context.sc_pc >= 4)
841 const char *libname = 0;
842 const char *symname = 0;
846 Elf32_Addr
pc = context.sc_pc;
847 Dwarf_Fde fde = find_fde_name (&
pc, &
name);
848 Dwarf_Addr low_pc = context.sc_pc;
849 Dwarf_Unsigned udummy;
858 if (dwarf_get_fde_range (fde, &low_pc, &udummy, &pdummy, &udummy,
859 &odummy, &sdummy, &odummy, &
err) == DW_DLV_OK)
860 offset = context.sc_pc - low_pc;
869 Elf32_Addr addr = context.sc_pc;
872 if (_rld_new_interface (_RLD_DLADDR, addr, &
info))
874 if (
info.dli_fname &&
info.dli_fname [0])
875 libname =
info.dli_fname;
877 Elf32_Addr symaddr = (Elf32_Addr)
info.dli_saddr;
878 if (symaddr == low_pc)
880 else if (
info.dli_sname
881 &&
info.dli_sname [0]
882 && addr - symaddr <
offset)
885 symname =
info.dli_sname;
890 if (libname && symname)
892 (
buffer, buffer_size,
" 0x%012lx %.100s + 0x%lx [%.200s]\n",
893 addr, symname,
offset, libname));
896 (
buffer, buffer_size,
" 0x%012lx %.100s + 0x%lx\n",
900 (
buffer, buffer_size,
" 0x%012lx <unknown function>\n", addr));
914 if (
pc != context.sc_pc)
917 exc_unwind (&context, fde);
920 #elif defined PROG_PSTACK // solaris
922 # define CXXFILTER " | " PROG_CXXFILT
929 char buffer [buffer_size];
930 snprintf (
buffer, buffer_size,
"%s %lu%s 1>&%d", PROG_PSTACK, (
unsigned long) getpid (),
935 #elif __GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 4)
937 _Unwind_Backtrace (unwindWalkStack, &
fd);
982 if ((corepid = ::fork ()) == 0)
1007 else if (corepid > 0) {
1010 wait_pid = ::waitpid (corepid, &
status, 0);
1011 }
while (wait_pid == -1 && errno == EINTR);
1029 struct rlimit core_limit;
1030 getrlimit(RLIMIT_CORE, &core_limit);
1032 unsigned long old_limit = core_limit.rlim_cur;
1033 core_limit.rlim_cur = core_limit.rlim_max;
1034 if ( setrlimit(RLIMIT_CORE, &core_limit) == 0 ) {
1035 return core_limit.rlim_cur;
1049 struct rlimit core_limit;
1050 core_limit.rlim_cur = 0;
1051 setrlimit(RLIMIT_CORE, &core_limit);