Produce a stack trace.
638{
641
642 std::cerr.flush ();
643 fflush (stderr);
644
645#ifdef _WIN32
646
647
648 if (! SymInitialize (GetCurrentProcess (), NULL, TRUE))
649 {
650 MYWRITELIT (fd, (
"failed to dump stack trace:"
651 " cannot get symbolic information\n"));
652 return;
653 }
654
655 union SYMBUFFER {
656 IMAGEHLP_SYMBOL sym;
657 BYTE
buffer [
sizeof (IMAGEHLP_SYMBOL) + 512 ];
658 };
659
662 STACKFRAME frame;
663 SYMBUFFER symbol;
668 const int buf_size = 2*40+6;
670
671
672
673
674 context.ContextFlags = CONTEXT_FULL;
675 if (! GetThreadContext (GetCurrentThread (), &context))
676 return;
677
678
679
680
681
682
683 memset (&module, 0, sizeof (module));
684 memset (&frame, 0, sizeof (frame));
685
686 module.SizeOfStruct = sizeof (module);
687
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;
694
695 while (true)
696 {
697 if (! StackWalk (IMAGE_FILE_MACHINE_I386,
698 GetCurrentProcess (),
699 GetCurrentThread (),
700 &frame,
701 &context,
702 NULL,
703 SymFunctionTableAccess,
704 SymGetModuleBase,
705 NULL)
706 || frame.AddrFrame.Offset == 0)
707 break;
708
709
710
711
712
713
714
715 MYWRITE (fd, buf, snprintf (buf, buf_size,
"(%2u) 0x%08lx 0x%08lx ",
716 level, frame.AddrPC.Offset,
717 frame.AddrFrame.Offset));
718
719 memset (&symbol, 0, sizeof (symbol));
720 symbol.sym.SizeOfStruct = sizeof (symbol);
721 symbol.sym.MaxNameLength = sizeof (symbol) - sizeof (symbol.sym);
722
724 if (SymGetSymFromAddr (GetCurrentProcess (), frame.AddrPC.Offset,
725 &offset, &symbol.sym))
726 {
727
728
729
730
731
732
733
734
735 MYWRITE (fd, symbol.sym.Name, STDC::strlen (symbol.sym.Name));
736 MYWRITE (fd, buf, snprintf (buf, buf_size,
" + %lx", offset));
737
738 if (SymGetModuleInfo (GetCurrentProcess(), frame.AddrPC.Offset,
739 &module))
740 {
743 STDC::strlen (
module.ImageName));
745 }
746 }
747 else
748 {
749 GetLogicalAddress ((PVOID) frame.AddrPC.Offset,
750 modulename, sizeof (modulename),
752 MYWRITE (fd, buf, snprintf (buf, buf_size,
"%04lx:%08lx [",
section, offset));
753 MYWRITE (fd, modulename, STDC::strlen (modulename));
755 }
758 }
759 SymCleanup (GetCurrentProcess ());
760
761#elif (HAVE_U_STACK_TRACE || HAVE_XL_TRBK)
762
763 int stderrfd = dup (STDERR_FILENO);
764 if (stderrfd == -1)
765 return;
766
767 int newfd = dup2 (fd, STDERR_FILENO);
768 if (newfd == -1)
769 {
770 close (stderrfd);
771 return;
772 }
773
774# if HAVE_U_STACK_TRACE
775 U_STACK_TRACE ();
776# elif HAVE_XL_TRBK
777 xl__trbk ();
778# else
779# error "oops, you shouldn't have gotten here!"
780# endif
781
782 fflush (stderr);
783 dup2 (stderrfd, STDERR_FILENO);
784 close (newfd);
785#elif HAVE_LINUX_UNWIND_BACKTRACE
786 CxxUtils::backtraceByUnwind (stacktraceLine, fd);
787
788#elif HAVE_BACKTRACE_SYMBOLS_FD && HAVE_DLADDR
789
790
791 void *trace [MAX_BACKTRACE_DEPTH];
793
794 for (
int n = 0;
n <
depth; ++
n)
795 {
796 unsigned long addr = (unsigned long) trace [n];
797 stacktraceLine (fd, addr);
798 }
799
800#elif HAVE_EXCPT_H && HAVE_PDSC_H && HAVE_RLD_INTERFACE_H
801
802
803
804
806 char buffer [buffer_size];
809
810 exc_capture_context (&context);
812 {
813
815 = exc_remote_lookup_function_entry(0, 0,
context.sc_pc, 0, &func, &
base);
816 Elf32_Addr addr = PDSC_CRD_BEGIN_ADDRESS(
base, func);
817
818 const char *
name =
"<unknown function>";
819 snprintf (buffer, buffer_size, " 0x%012lx %.100s + 0x%lx\n",
821 write (fd, buffer, STDC::strlen(buffer));
822 rc = exc_virtual_unwind(0, &context);
823 }
824
825#elif HAVE_EXCEPTION_H && defined __sgi
826
827
828
829
830
833
834 exc_setjmp (&context);
836 {
837
838
839
840
841
842
844 const char *libname = 0;
845 const char *symname = 0;
847
848
850 Dwarf_Fde fde = find_fde_name (&pc, &name);
851 Dwarf_Addr low_pc =
context.sc_pc;
852 Dwarf_Unsigned udummy;
853 Dwarf_Signed sdummy;
854 Dwarf_Ptr pdummy;
855 Dwarf_Off odummy;
857
859
860
861 if (dwarf_get_fde_range (fde, &low_pc, &udummy, &pdummy, &udummy,
862 &odummy, &sdummy, &odummy, &err) == DW_DLV_OK)
864
865
866
867
868
869
870
871
872 Elf32_Addr addr =
context.sc_pc;
874
875 if (_rld_new_interface (_RLD_DLADDR, addr, &info))
876 {
877 if (
info.dli_fname &&
info.dli_fname [0])
878 libname =
info.dli_fname;
879
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)
886 {
888 symname =
info.dli_sname;
889 }
890 }
891
892
893 if (libname && symname)
894 write (fd, buffer, snprintf
895 (buffer, buffer_size, " 0x%012lx %.100s + 0x%lx [%.200s]\n",
896 addr, symname, offset, libname));
897 else if (symname)
898 write (fd, buffer, snprintf
899 (buffer, buffer_size, " 0x%012lx %.100s + 0x%lx\n",
900 addr, symname, offset));
901 else
902 write (fd, buffer, snprintf
903 (buffer, buffer_size, " 0x%012lx <unknown function>\n", addr));
904
905
907
908
909
910
911
912
913
914
915
916
918 break;
919
920 exc_unwind (&context, fde);
921 }
922
923#elif defined PROG_PSTACK
924# ifdef PROG_CXXFILT
925# define CXXFILTER " | " PROG_CXXFILT
926# else
927# define CXXFILTER
928# endif
929
932 char buffer [buffer_size];
933 snprintf (buffer, buffer_size, "%s %lu%s 1>&%d", PROG_PSTACK, (unsigned long) getpid (),
934 "" CXXFILTER, fd);
935 system (buffer);
936# undef CXXFILTER
937
938#elif __GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 4)
939
940 _Unwind_Backtrace (unwindWalkStack, &fd);
941#endif
942
943
944
945
946
947
948
949}
#define IOFD_INVALID
Invalid channel descriptor constant.
#define MYWRITE(fd, data, n)
#define MYWRITELIT(fd, str)
std::string depth
tag string for intendation
void free(pointer p)
Free an element.