diff options
Diffstat (limited to 'debian/patches/ada-symbolic-tracebacks.diff')
-rw-r--r-- | debian/patches/ada-symbolic-tracebacks.diff | 401 |
1 files changed, 401 insertions, 0 deletions
diff --git a/debian/patches/ada-symbolic-tracebacks.diff b/debian/patches/ada-symbolic-tracebacks.diff new file mode 100644 index 0000000..ae8f402 --- /dev/null +++ b/debian/patches/ada-symbolic-tracebacks.diff @@ -0,0 +1,401 @@ +# DP: - Enable support for symbolic tracebacks in exceptions (delete the dummy +# DP: convert_addresses from adaint.c, and provide a real one separately.) + +Ported Jürgen Pfeifer's patch to enable symbolic tracebacks on Debian +GNU/Linux. + +The binary distribution of GNAT 3.15p comes with an old version of +binutils that includes a library, libaddr2line.a. This library does +not exist in recent versions of binutils. The patch works around this +by calling /usr/bin/addr2line (still part of binutils) and parsing the +output. See debian/convert_addresses.c for the gory details. + +I have modified convert_addresses.c to not use a shell script anymore; +Debian controls the version of binutils which is installed. Also, I +use execve instead of execle. + +-- +Ludovic Brenta. + +# ' make emacs highlighting happy + +Index: b/src/gcc/ada/gcc-interface/Makefile.in +=================================================================== +--- a/src/gcc/ada/gcc-interface/Makefile.in ++++ b/src/gcc/ada/gcc-interface/Makefile.in +@@ -270,7 +270,8 @@ + # Both . and srcdir are used, in that order, + # so that tm.h and config.h will be found in the compilation + # subdirectory rather than in the source directory. +-INCLUDES = -I- -I. -I.. -I$(srcdir)/ada -I$(srcdir) -I$(ftop_srcdir)/include $(GMPINC) ++INCLUDES = -iquote . -iquote .. -iquote $(srcdir)/ada -iquote $(srcdir) \ ++ -iquote $(ftop_srcdir)/include $(GMPINC) + + ADA_INCLUDES = -I- -I. -I$(srcdir)/ada + +@@ -2426,7 +2427,7 @@ + # library. LIBGNAT_OBJS is the list of object files for libgnat. + # thread.c is special as put into GNATRTL_TASKING_OBJS by Makefile.rtl + LIBGNAT_OBJS = adadecode.o adaint.o argv.o aux-io.o \ +- cal.o cio.o cstreams.o ctrl_c.o \ ++ cal.o cio.o convert_addresses.o cstreams.o ctrl_c.o \ + env.o errno.o exit.o expect.o final.o \ + init.o initialize.o locales.o mkdir.o \ + raise.o seh_init.o socket.o sysdep.o \ +@@ -3104,6 +3105,7 @@ + socket.o : socket.c gsocket.h + sysdep.o : sysdep.c + raise.o : raise.c raise.h ++convert_addresses.o : convert_addresses.c + sigtramp-armdroid.o : sigtramp-armdroid.c sigtramp.h + sigtramp-armvxw.o : sigtramp-armvxw.c sigtramp.h + sigtramp-ppcvxw.o : sigtramp-ppcvxw.c sigtramp.h +Index: b/src/gcc/ada/adaint.c +=================================================================== +--- a/src/gcc/ada/adaint.c ++++ b/src/gcc/ada/adaint.c +@@ -3608,35 +3608,6 @@ + } + #endif + +-#if defined (IS_CROSS) \ +- || (! ((defined (sparc) || defined (i386)) && defined (sun) \ +- && defined (__SVR4)) \ +- && ! (defined (linux) && (defined (i386) || defined (__x86_64__))) \ +- && ! (defined (linux) && defined (__ia64__)) \ +- && ! (defined (linux) && defined (powerpc)) \ +- && ! defined (__FreeBSD__) \ +- && ! defined (__Lynx__) \ +- && ! defined (__hpux__) \ +- && ! defined (__APPLE__) \ +- && ! defined (_AIX) \ +- && ! defined (VMS) \ +- && ! defined (__MINGW32__)) +- +-/* Dummy function to satisfy g-trasym.o. See the preprocessor conditional +- just above for a list of native platforms that provide a non-dummy +- version of this procedure in libaddr2line.a. */ +- +-void +-convert_addresses (const char *file_name ATTRIBUTE_UNUSED, +- void *addrs ATTRIBUTE_UNUSED, +- int n_addr ATTRIBUTE_UNUSED, +- void *buf ATTRIBUTE_UNUSED, +- int *len ATTRIBUTE_UNUSED) +-{ +- *len = 0; +-} +-#endif +- + #if defined (_WIN32) + int __gnat_argument_needs_quote = 1; + #else +Index: b/src/gcc/ada/convert_addresses.c +=================================================================== +--- /dev/null ++++ b/src/gcc/ada/convert_addresses.c +@@ -0,0 +1,159 @@ ++/* ++ Copyright (C) 1999 by Juergen Pfeifer <juergen.pfeifer@gmx.net> ++ Ada for Linux Team (ALT) ++ ++ Permission is hereby granted, free of charge, to any person obtaining a ++ copy of this software and associated documentation files (the ++ "Software"), to deal in the Software without restriction, including ++ without limitation the rights to use, copy, modify, merge, publish, ++ distribute, distribute with modifications, sublicense, and/or sell ++ copies of the Software, and to permit persons to whom the Software is ++ furnished to do so, subject to the following conditions: ++ ++ The above copyright notice and this permission notice shall be included ++ in all copies or substantial portions of the Software. ++ ++ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS ++ OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF ++ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. ++ IN NO EVENT SHALL THE ABOVE COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, ++ DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR ++ OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR ++ THE USE OR OTHER DEALINGS IN THE SOFTWARE. ++ ++ Except as contained in this notice, the name(s) of the above copyright ++ holders shall not be used in advertising or otherwise to promote the ++ sale, use or other dealings in this Software without prior written ++ authorization. ++*/ ++#include <sys/types.h> ++#include <stdlib.h> ++#include <stdio.h> ++#include <unistd.h> ++#include <string.h> ++#include <signal.h> ++ ++#define STDIN_FILENO 0 ++#define STDOUT_FILENO 1 ++#define MAX_LINE 1024 ++ ++#define CLOSE1 close(fd1[0]); close(fd1[1]) ++#define CLOSE2 close(fd2[0]); close(fd2[1]) ++#define RESTSIG sigaction(SIGPIPE,&oact,NULL) ++ ++void convert_addresses ++(const char const *file_name, ++ void* addrs[], ++ int n_addr, ++ char* buf, ++ int* len) ++{ ++ int max_len = *len; ++ pid_t child; ++ ++ struct sigaction act, oact; ++ ++ int fd1[2], fd2[2]; ++ ++ if (!file_name) { ++ return; ++ } ++ ++ *buf = 0; *len = 0; ++ act.sa_handler = SIG_IGN; ++ sigemptyset(&act.sa_mask); ++ act.sa_flags = 0; ++ if (sigaction(SIGPIPE,&act,&oact) < 0) ++ return; ++ ++ if (pipe(fd1) >= 0) { ++ if (pipe(fd2)>=0) { ++ if ((child = fork()) < 0) { ++ CLOSE1; CLOSE2; RESTSIG; ++ return; ++ } ++ else { ++ if (0==child) { ++ close(fd1[1]); ++ close(fd2[0]); ++ if (fd1[0] != STDIN_FILENO) { ++ if (dup2(fd1[0],STDIN_FILENO) != STDIN_FILENO) { ++ CLOSE1; CLOSE2; ++ } ++ close(fd1[0]); ++ } ++ if (fd2[1] != STDOUT_FILENO) { ++ if (dup2(fd2[1],STDOUT_FILENO) != STDOUT_FILENO) { ++ CLOSE1; CLOSE2; ++ } ++ close(fd2[1]); ++ } ++ { ++ /* As pointed out by Florian Weimer to me, it is a ++ security threat to call the script with a user defined ++ environment and using the path. That would be Trojans ++ pleasure. Therefore we use the absolute path to ++ addr2line and an empty environment. That should be ++ safe. ++ */ ++ char *file_name_for_execve = strdup (file_name); /* non-const */ ++ char *const argv[] = { "addr2line", ++ "-e", ++ file_name_for_execve, ++ "--demangle=gnat", ++ "--functions", ++ "--basenames", ++ NULL }; ++ char *const envp[] = { NULL }; ++ if (execve("/usr/bin/addr2line", argv, envp) < 0) { ++ CLOSE1; CLOSE2; ++ } ++ if (file_name_for_execve) { free (file_name_for_execve); } ++ } ++ } ++ else { ++ int i, n; ++ char hex[16]; ++ char line[MAX_LINE + 1]; ++ char *p; ++ char *s = buf; ++ ++ /* Parent context */ ++ close(fd1[0]); ++ close(fd2[1]); ++ ++ for(i=0; i < n_addr; i++) { ++ snprintf(hex,sizeof(hex),"%p\n",addrs[i]); ++ write(fd1[1],hex,strlen(hex)); ++ n = read(fd2[0],line,MAX_LINE); ++ if (n<=0) ++ break; ++ line[n]=0; ++ /* We have approx. 16 additional chars for "%p in " clause. ++ We use this info to prevent a buffer overrun. ++ */ ++ if (n + 16 + (*len) > max_len) ++ break; ++ p = strchr(line,'\n'); ++ if (p) { ++ if (*(p+1)) { ++ *p = 0; ++ *len += snprintf(s, (max_len - (*len)), "%p in %s at %s",addrs[i], line, p+1); ++ } ++ else { ++ *len += snprintf(s, (max_len - (*len)), "%p at %s",addrs[i], line); ++ } ++ s = buf + (*len); ++ } ++ } ++ close(fd1[1]); ++ close(fd2[0]); ++ } ++ } ++ } ++ else { ++ CLOSE1; ++ } ++ } ++ RESTSIG; ++} +Index: b/src/gcc/ada/g-trasym.adb +=================================================================== +--- a/src/gcc/ada/g-trasym.adb ++++ b/src/gcc/ada/g-trasym.adb +@@ -33,40 +33,110 @@ + -- is not supported. It returns tracebacks as lists of LF separated strings of + -- the form "0x..." corresponding to the addresses. + ++with System.Soft_Links; + with Ada.Exceptions.Traceback; use Ada.Exceptions.Traceback; +-with System.Address_Image; + + package body GNAT.Traceback.Symbolic is + ++ package TSL renames System.Soft_Links; ++ ++ -- To perform the raw addresses to symbolic form translation we rely on a ++ -- libaddr2line symbolizer which examines debug info from a provided ++ -- executable file name, and an absolute path is needed to ensure the file ++ -- is always found. This is "__gnat_locate_exec_on_path (gnat_argv [0])" ++ -- for our executable file, a fairly heavy operation so we cache the ++ -- result. ++ ++ Exename : System.Address; ++ -- Pointer to the name of the executable file to be used on all ++ -- invocations of the libaddr2line symbolization service. ++ ++ Exename_Resolved : Boolean := False; ++ -- Flag to indicate whether we have performed the executable file name ++ -- resolution already. Relying on a not null Exename for this purpose ++ -- would be potentially inefficient as this is what we will get if the ++ -- resolution attempt fails. ++ + ------------------------ + -- Symbolic_Traceback -- + ------------------------ + + function Symbolic_Traceback (Traceback : Tracebacks_Array) return String is ++ ++ procedure convert_addresses ++ (filename : System.Address; ++ addrs : System.Address; ++ n_addrs : Integer; ++ buf : System.Address; ++ len : System.Address); ++ pragma Import (C, convert_addresses, "convert_addresses"); ++ -- This is the procedure version of the Ada-aware addr2line. It places ++ -- in BUF a string representing the symbolic translation of the N_ADDRS ++ -- raw addresses provided in ADDRS, looked up in debug information from ++ -- FILENAME. LEN points to an integer which contains the size of the ++ -- BUF buffer at input and the result length at output. ++ -- ++ -- Note that this procedure is *not* thread-safe. ++ ++ type Argv_Array is array (0 .. 0) of System.Address; ++ gnat_argv : access Argv_Array; ++ pragma Import (C, gnat_argv, "gnat_argv"); ++ ++ function locate_exec_on_path ++ (c_exename : System.Address) return System.Address; ++ pragma Import (C, locate_exec_on_path, "__gnat_locate_exec_on_path"); ++ ++ B_Size : constant Integer := 256 * Traceback'Length; ++ Len : Integer := B_Size; ++ Res : String (1 .. B_Size); ++ ++ use type System.Address; ++ + begin ++ -- The symbolic translation of an empty set of addresses is an empty ++ -- string. ++ + if Traceback'Length = 0 then + return ""; ++ end if; + +- else +- declare +- Img : String := System.Address_Image (Traceback (Traceback'First)); ++ -- If our input set of raw addresses is not empty, resort to the ++ -- libaddr2line service to symbolize it all. + +- Result : String (1 .. (Img'Length + 3) * Traceback'Length); +- Last : Natural := 0; ++ -- Compute, cache and provide the absolute path to our executable file ++ -- name as the binary file where the relevant debug information is to be ++ -- found. If the executable file name resolution fails, we have no ++ -- sensible basis to invoke the symbolizer at all. ++ ++ -- Protect all this against concurrent accesses explicitly, as the ++ -- underlying services are potentially thread unsafe. ++ ++ TSL.Lock_Task.all; ++ ++ if not Exename_Resolved then ++ Exename := locate_exec_on_path (gnat_argv (0)); ++ Exename_Resolved := True; ++ end if; ++ ++ if Exename /= System.Null_Address then ++ Len := Res'Length; ++ convert_addresses ++ (Exename, Traceback'Address, Traceback'Length, ++ Res (1)'Address, Len'Address); ++ end if; ++ ++ TSL.Unlock_Task.all; + +- begin +- for J in Traceback'Range loop +- Img := System.Address_Image (Traceback (J)); +- Result (Last + 1 .. Last + 2) := "0x"; +- Last := Last + 2; +- Result (Last + 1 .. Last + Img'Length) := Img; +- Last := Last + Img'Length + 1; +- Result (Last) := ASCII.LF; +- end loop; ++ -- Return what the addr2line symbolizer has produced if we have called ++ -- it (the executable name resolution succeeded), or an empty string ++ -- otherwise. + +- return Result (1 .. Last); +- end; ++ if Exename /= System.Null_Address then ++ return Res (1 .. Len); ++ else ++ return ""; + end if; ++ + end Symbolic_Traceback; + + function Symbolic_Traceback (E : Exception_Occurrence) return String is +Index: b/src/gcc/ada/tracebak.c +=================================================================== +--- a/src/gcc/ada/tracebak.c ++++ b/src/gcc/ada/tracebak.c +@@ -425,7 +425,7 @@ + /* Starting with GCC 4.6, -fomit-frame-pointer is turned on by default for + 32-bit x86/Linux as well and DWARF 2 unwind tables are emitted instead. + See the x86-64 case below for the drawbacks with this approach. */ +-#if defined (linux) && (__GNUC__ * 10 + __GNUC_MINOR__ > 45) ++#if (defined (linux) || defined(__GNU__)) && (__GNUC__ * 10 + __GNUC_MINOR__ > 45) + #define USE_GCC_UNWINDER + #else + #define USE_GENERIC_UNWINDER |