summaryrefslogtreecommitdiff
path: root/debian/patches/ada-symbolic-tracebacks.diff
diff options
context:
space:
mode:
Diffstat (limited to 'debian/patches/ada-symbolic-tracebacks.diff')
-rw-r--r--debian/patches/ada-symbolic-tracebacks.diff401
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