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;
142 std::string
p1 =
dir +
"/eu-addr2line";
143 if (
access (
p1.c_str(), F_OK) == 0) {
144 addr2LinePath = std::move (
p1);
150 std::string
p2 =
dir +
"/addr2line";
151 if (
access (
p2.c_str(), F_OK) == 0) {
152 addr2LinePath = std::move (
p2);
159 BacktraceInit backtraceInit;
165 int stacktracePopenFD (
const char*
cmd,
pid_t& child_pid)
175 int parent_end = fds[0];
176 int child_end = fds[1];
190 if (child_pid == 0) {
191 int child_std_end = 1;
193 if (child_end != child_std_end) {
194 dup2 (child_end, child_std_end);
204 execl (
"/bin/sh",
"sh",
"-c",
cmd, (
char *) 0);
218 int stacktracePcloseFD (
int fd,
pid_t child_pid)
230 wait_pid = waitpid (child_pid, &wstatus, 0);
231 }
while (wait_pid == -1 && errno == EINTR);
239 int stacktraceReadline (
int fd,
char* buf,
int buflen)
242 while (len < buflen-1) {
245 if (
stat == 0)
break;
246 if (*buf ==
'\n')
break;
290 GetLogicalAddress (PVOID addr, PTSTR
name, DWORD
length,
293 MEMORY_BASIC_INFORMATION
info;
295 if (! VirtualQuery (addr, &
info,
sizeof (
info)))
302 PIMAGE_DOS_HEADER dosheader = (PIMAGE_DOS_HEADER)
module;
303 PIMAGE_NT_HEADERS ntheader
304 = (PIMAGE_NT_HEADERS) (
module + dosheader->e_lfanew);
305 PIMAGE_SECTION_HEADER sect = IMAGE_FIRST_SECTION (ntheader);
306 DWORD rva = (DWORD) addr -
module;
308 for (
unsigned i = 0;
i < ntheader->FileHeader.NumberOfSections; ++
i,++sect)
310 DWORD sect_start = sect->VirtualAddress;
311 DWORD sect_end = sect_start +
std::max (sect->SizeOfRawData,
312 sect->Misc.VirtualSize);
314 if ((rva >= sect_start) && (rva <= sect_end))
317 offset = rva - sect_start;
338 char addrbuf [addrbuf_size];
340 #if HAVE_BACKTRACE_SYMBOLS_FD && HAVE_DLADDR
342 char diffbuf [diffbuf_size];
343 static const char trailer [] =
"]\n";
346 char dembuf[ LINE_MAX ];
347 char line[ LINE_MAX ];
349 char relbuf [relbuf_size];
351 if (dladdr ((
void*)addr, &
info) &&
info.dli_fname &&
info.dli_fname[0])
353 const char *libname =
info.dli_fname;
355 unsigned long symaddr = (
unsigned long)
info.dli_saddr;
356 bool gte = (addr >= symaddr);
357 unsigned long diff = (gte ? addr - symaddr : symaddr - addr);
363 unsigned long libaddr = (
unsigned long)
info.dli_fbase;
364 unsigned long relative_address = (addr >= libaddr) ? addr - libaddr : libaddr - addr;
374 if (strstr (
info.dli_fname,
".so") == 0 && libaddr == 0x400000)
375 relative_address = addr;
380 const char* symname = dembuf;
384 size_t len = strlen(
info.dli_fname);
385 if ( len > 0 && len + 80 < LINE_MAX)
387 if (
getenv (
"LD_PRELOAD"))
388 unsetenv (
"LD_PRELOAD");
390 if ( addr2LinePath ==
"/usr/bin/eu-addr2line" )
392 snprintf (
line, LINE_MAX,
"%s -f -e %s %p | /usr/bin/c++filt | /usr/bin/tr \\\\012 \\\\040 ",
393 addr2LinePath.c_str(),
395 (
void*)relative_address);
399 snprintf (
line, LINE_MAX,
"%s -f -C -e %s %p",
400 addr2LinePath.c_str(),
402 (
void*)relative_address);
405 pfd = stacktracePopenFD(
line, child_pid );
413 demlen = stacktraceReadline (pfd, dembuf,
sizeof(dembuf));
418 int stat = stacktracePcloseFD (pfd, child_pid);
427 if (
stat || demlen <= 0 || dembuf[0] ==
'?') {
428 symname =
info.dli_sname;
429 if (!symname) symname =
"???";
430 demlen = strlen (symname);
437 bufs [nbufs].iov_base = addrbuf;
438 bufs [nbufs].iov_len = snprintf (addrbuf, addrbuf_size,
" 0x%08lx ", addr);
441 bufs [nbufs].iov_base = (
void *) symname;
442 bufs [nbufs].iov_len = demlen;
446 bufs [nbufs].iov_base =
line;
447 bufs [nbufs].iov_len =
length;
451 bufs [nbufs].iov_base = diffbuf;
452 bufs [nbufs].iov_len = snprintf (diffbuf, diffbuf_size,
" %c 0x%lx [",
453 gte ?
'+' :
'-',
diff);
456 bufs [nbufs].iov_base = (
void *) libname;
457 bufs [nbufs].iov_len = strlen (libname);
461 bufs [nbufs].iov_base = relbuf;
462 bufs [nbufs].iov_len = snprintf( relbuf, relbuf_size,
" D[%p]", (
void*)relative_address );
466 bufs [nbufs].iov_base = (
void *) trailer;
467 bufs [nbufs].iov_len = 2;
474 bufs [nbufs].iov_base = addrbuf;
475 bufs [nbufs].iov_len = snprintf (addrbuf, addrbuf_size,
" 0x%08lx ", addr);
478 bufs [nbufs].iov_base = (
void *)
"<unknown function>\n";
479 bufs [nbufs].iov_len = 19;
483 writev (
fd, bufs, nbufs);
487 #if !(HAVE_BACKTRACE_SYMBOLS_FD && HAVE_DLADDR) && __GNUC__ >=4
489 typedef unsigned _Unwind_Ptr
__attribute__((__mode__(__pointer__)));
490 struct _Unwind_Context;
494 _URC_FOREIGN_EXCEPTION_CAUGHT = 1,
495 _URC_FATAL_PHASE2_ERROR = 2,
496 _URC_FATAL_PHASE1_ERROR = 3,
497 _URC_NORMAL_STOP = 4,
498 _URC_END_OF_STACK = 5,
499 _URC_HANDLER_FOUND = 6,
500 _URC_INSTALL_CONTEXT = 7,
501 _URC_CONTINUE_UNWIND = 8
502 } _Unwind_Reason_Code;
503 typedef _Unwind_Reason_Code (*_Unwind_Trace_Fn) (_Unwind_Context *,
void *);
504 extern _Unwind_Reason_Code _Unwind_Backtrace (_Unwind_Trace_Fn,
void *);
505 extern _Unwind_Ptr _Unwind_GetIP (_Unwind_Context *);
506 extern _Unwind_Ptr _Unwind_GetRegionStart (_Unwind_Context *);
516 unwindWalkStack (_Unwind_Context *ctx,
void *
data)
522 char addrbuf [addrbuf_size];
524 char diffbuf [diffbuf_size];
525 static const char trailer [] =
"]\n";
526 unsigned long ip = _Unwind_GetIP (ctx);
527 unsigned long ir = _Unwind_GetRegionStart (ctx);
531 if (dladdr ((
void *)
ir, &
info) &&
info.dli_fname &&
info.dli_fname[0])
533 const char *libname =
info.dli_fname;
534 const char *symname = (
info.dli_sname &&
info.dli_sname[0]
535 ?
info.dli_sname :
"?");
536 unsigned long symaddr = (
unsigned long)
info.dli_saddr;
537 bool gte = (
ip >= symaddr);
538 unsigned long diff = (gte ?
ip - symaddr : symaddr -
ip);
540 bufs [nbufs].iov_base = addrbuf;
541 bufs [nbufs].iov_len = snprintf (addrbuf, addrbuf_size,
" 0x%08lx ",
ip);
544 bufs [nbufs].iov_base = (
char *) symname;
545 bufs [nbufs].iov_len = strlen (symname);
548 bufs [nbufs].iov_base = diffbuf;
549 bufs [nbufs].iov_len = snprintf (diffbuf, diffbuf_size,
" %s 0x%lx [",
550 gte ?
"+" :
"-",
diff);
553 bufs [nbufs].iov_base = (
char *) libname;
554 bufs [nbufs].iov_len = strlen (libname);
557 bufs [nbufs].iov_base = (
char *) trailer;
558 bufs [nbufs].iov_len = 2;
562 # endif // HAVE_DLADDR
564 bufs [nbufs].iov_base = addrbuf;
565 bufs [nbufs].iov_len = snprintf (addrbuf, addrbuf_size,
" 0x%08lx ",
ip);
568 bufs [nbufs].iov_base = diffbuf;
569 bufs [nbufs].iov_len = snprintf (diffbuf, diffbuf_size,
" <?%08lx> + 0x%lx\n",
574 writev (
fd, bufs, nbufs);
575 return _URC_NO_REASON;
584 addr2LinePath =
path;
588 #if HAVE_U_STACK_TRACE
590 extern "C" void U_STACK_TRACE (
void);
595 extern "C" void xl__trbk (
void);
648 if (! SymInitialize (GetCurrentProcess (), NULL,
TRUE))
651 " cannot get symbolic information\n"));
657 BYTE
buffer [
sizeof (IMAGEHLP_SYMBOL) + 512 ];
668 const int buf_size = 2*40+6;
674 context.ContextFlags = CONTEXT_FULL;
675 if (! GetThreadContext (GetCurrentThread (), &context))
684 memset (&frame, 0,
sizeof (frame));
688 frame.AddrPC.Offset = context.Eip;
689 frame.AddrPC.Mode = AddrModeFlat;
690 frame.AddrStack.Offset = context.Esp;
691 frame.AddrStack.Mode = AddrModeFlat;
692 frame.AddrFrame.Offset = context.Ebp;
693 frame.AddrFrame.Mode = AddrModeFlat;
697 if (! StackWalk (IMAGE_FILE_MACHINE_I386,
698 GetCurrentProcess (),
703 SymFunctionTableAccess,
706 || frame.AddrFrame.Offset == 0)
715 MYWRITE (
fd, buf, snprintf (buf, buf_size,
"(%2u) 0x%08lx 0x%08lx ",
716 level, frame.AddrPC.Offset,
717 frame.AddrFrame.Offset));
719 memset (&symbol, 0,
sizeof (symbol));
720 symbol.sym.SizeOfStruct =
sizeof (symbol);
721 symbol.sym.MaxNameLength =
sizeof (symbol) -
sizeof (symbol.sym);
724 if (SymGetSymFromAddr (GetCurrentProcess (), frame.AddrPC.Offset,
735 MYWRITE (
fd, symbol.sym.Name, STDC::strlen (symbol.sym.Name));
738 if (SymGetModuleInfo (GetCurrentProcess(), frame.AddrPC.Offset,
743 STDC::strlen (
module.ImageName));
749 GetLogicalAddress ((PVOID) frame.AddrPC.Offset,
759 SymCleanup (GetCurrentProcess ());
761 #elif (HAVE_U_STACK_TRACE || HAVE_XL_TRBK) // hp-ux, aix
763 int stderrfd = dup (STDERR_FILENO);
767 int newfd = dup2 (
fd, STDERR_FILENO);
774 # if HAVE_U_STACK_TRACE // hp-ux
776 # elif HAVE_XL_TRBK // aix
779 # error "oops, you shouldn't have gotten here!"
783 dup2 (stderrfd, STDERR_FILENO);
785 #elif HAVE_LINUX_UNWIND_BACKTRACE
786 CxxUtils::backtraceByUnwind (stacktraceLine,
fd);
788 #elif HAVE_BACKTRACE_SYMBOLS_FD && HAVE_DLADDR // linux
791 void *trace [MAX_BACKTRACE_DEPTH];
796 unsigned long addr = (
unsigned long) trace [
n];
797 stacktraceLine (
fd, addr);
800 #elif HAVE_EXCPT_H && HAVE_PDSC_H && HAVE_RLD_INTERFACE_H // tru64
806 char buffer [buffer_size];
810 exc_capture_context (&context);
811 while (!rc && context.sc_pc)
814 pdsc_crd *func, *
base, *crd
815 = exc_remote_lookup_function_entry(0, 0, context.sc_pc, 0, &func, &
base);
816 Elf32_Addr addr = PDSC_CRD_BEGIN_ADDRESS(
base, func);
818 const char *
name =
"<unknown function>";
819 snprintf (
buffer, buffer_size,
" 0x%012lx %.100s + 0x%lx\n",
820 context.sc_pc,
name, context.sc_pc - addr);
822 rc = exc_virtual_unwind(0, &context);
825 #elif HAVE_EXCEPTION_H && defined __sgi // irix
834 exc_setjmp (&context);
835 while (context.sc_pc >= 4)
844 const char *libname = 0;
845 const char *symname = 0;
849 Elf32_Addr
pc = context.sc_pc;
850 Dwarf_Fde fde = find_fde_name (&
pc, &
name);
851 Dwarf_Addr low_pc = context.sc_pc;
852 Dwarf_Unsigned udummy;
861 if (dwarf_get_fde_range (fde, &low_pc, &udummy, &pdummy, &udummy,
862 &odummy, &sdummy, &odummy, &
err) == DW_DLV_OK)
863 offset = context.sc_pc - low_pc;
872 Elf32_Addr addr = context.sc_pc;
875 if (_rld_new_interface (_RLD_DLADDR, addr, &
info))
877 if (
info.dli_fname &&
info.dli_fname [0])
878 libname =
info.dli_fname;
880 Elf32_Addr symaddr = (Elf32_Addr)
info.dli_saddr;
881 if (symaddr == low_pc)
883 else if (
info.dli_sname
884 &&
info.dli_sname [0]
885 && addr - symaddr <
offset)
888 symname =
info.dli_sname;
893 if (libname && symname)
895 (
buffer, buffer_size,
" 0x%012lx %.100s + 0x%lx [%.200s]\n",
896 addr, symname,
offset, libname));
899 (
buffer, buffer_size,
" 0x%012lx %.100s + 0x%lx\n",
903 (
buffer, buffer_size,
" 0x%012lx <unknown function>\n", addr));
917 if (
pc != context.sc_pc)
920 exc_unwind (&context, fde);
923 #elif defined PROG_PSTACK // solaris
925 # define CXXFILTER " | " PROG_CXXFILT
932 char buffer [buffer_size];
933 snprintf (
buffer, buffer_size,
"%s %lu%s 1>&%d", PROG_PSTACK, (
unsigned long) getpid (),
938 #elif __GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 4)
940 _Unwind_Backtrace (unwindWalkStack, &
fd);
985 if ((corepid = ::fork ()) == 0)
1010 else if (corepid > 0) {
1013 wait_pid = ::waitpid (corepid, &
status, 0);
1014 }
while (wait_pid == -1 && errno == EINTR);
1032 struct rlimit core_limit;
1033 getrlimit(RLIMIT_CORE, &core_limit);
1035 unsigned long old_limit = core_limit.rlim_cur;
1036 core_limit.rlim_cur = core_limit.rlim_max;
1037 if ( setrlimit(RLIMIT_CORE, &core_limit) == 0 ) {
1038 return core_limit.rlim_cur;
1052 struct rlimit core_limit;
1053 core_limit.rlim_cur = 0;
1054 core_limit.rlim_max = 0;
1055 setrlimit(RLIMIT_CORE, &core_limit);