[Date Prev][Date Next] [Thread Prev][Thread Next] [Date Index] [Thread Index]

[Patch] #2: Support symbolic tracebacks



Index: patches/ada-symbolic-tracebacks.dpatch
===================================================================
RCS file: patches/ada-symbolic-tracebacks.dpatch
diff -N patches/ada-symbolic-tracebacks.dpatch
--- /dev/null   1 Jan 1970 00:00:00 -0000
+++ patches/ada-symbolic-tracebacks.dpatch      7 Apr 2006 06:23:13 -0000       1.5
@@ -0,0 +1,296 @@
+#! /bin/sh -e
+
+# DP: - Enable support for symbolic tracebacks in exceptions.
+
+dir=
+if [ $# -eq 3 -a "$2" = '-d' ]; then
+    pdir="-d $3"
+    dir="$3/"
+elif [ $# -ne 1 ]; then
+    echo >&2 "`basename $0`: script expects -patch|-unpatch as argument"
+    exit 1
+fi
+case "$1" in
+    -patch)
+        patch $pdir -f --no-backup-if-mismatch -p0 < $0
+        ;;
+    -unpatch)
+        patch $pdir -f --no-backup-if-mismatch -R -p0 < $0
+        ;;
+    *)
+        echo >&2 "`basename $0`: script expects -patch|-unpatch as argument"
+        exit 1
+esac
+exit 0
+
+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.
+
+
+--- gcc/ada/g-trasym.adb~      Thu Oct 24 11:02:18 2002
++++ gcc/ada/g-trasym.adb       Fri Jul  4 16:16:30 2003
+@@ -33,16 +33,16 @@
+ ------------------------------------------------------------------------------
+ 
+ --  Run-time symbolic traceback support
++--  This file has been modified by Juergen Pfeifer (31-Dec-1999) for
++--  the purpose to support the Ada for Linux Team implementation of
++--  convert_addresses. This implementation has the advantage to run
++--  on the binutils as they are deployed on Linux.
+ 
+ with System.Soft_Links;
+ with Ada.Exceptions.Traceback; use Ada.Exceptions.Traceback;
+ 
+ package body GNAT.Traceback.Symbolic is
+ 
+-   pragma Linker_Options ("-laddr2line");
+-   pragma Linker_Options ("-lbfd");
+-   pragma Linker_Options ("-liberty");
+-
+    package TSL renames System.Soft_Links;
+ 
+    ------------------------
+@@ -56,16 +56,19 @@
+          buf      : System.Address;
+          len      : System.Address);
+       pragma Import (C, convert_addresses, "convert_addresses");
+-      --  This is the procedure version of the Ada aware addr2line that will
+-      --  use argv[0] as the executable containing the debug information.
+-      --  This procedure is provided by libaddr2line on targets that support
+-      --  it. A dummy version is in a-adaint.c for other targets so that build
+-      --  of shared libraries doesn't generate unresolved symbols.
++      --  This is the ALT Linux specific version adapted to the binutils
++      --  deployed with most Linuxes. These binutils already have an
++      --  addr2line tool that demangles Ada symbolic names, but there are
++      --  version dependant variants for the option names. Therefore our
++      --  implementation spawns a shell script that does normalization of
++      --  the option and then executes addr2line and communicates with it
++      --  through a bidirectional pipe.
+       --
+       --  Note that this procedure is *not* thread-safe.
+ 
+-      Res : String (1 .. 256 * Traceback'Length);
+-      Len : Integer;
++      B_Size : constant Integer := 256 * Traceback'Length;
++      Len    : Integer := B_Size;
++      Res    : String (1 .. B_Size);
+ 
+    begin
+       if Traceback'Length > 0 then
+--- gcc/ada/convert_addresses.c~       1970-01-01 01:00:00.000000000 +0100
++++ gcc/ada/convert_addresses.c        2005-04-27 15:06:51.000000000 +0200
+@@ -0,0 +1,157 @@
++/*
++  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
++( void* addrs[],
++  int   n_addr,
++  char* buf,
++  int*  len)
++{
++  int max_len = *len;
++  pid_t pid = getpid();
++  pid_t child;
++
++  struct sigaction act, oact;
++
++  int fd1[2], fd2[2];
++  char exe_name[128];
++
++  *buf = 0; *len = 0;
++  /* Thanx to the /proc filesystem we can very easily reference our own
++     executable image:-)*/
++  snprintf(exe_name,sizeof(exe_name),"--exe=/proc/%ld/exe", (long)pid);
++
++  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 *const argv[] = { "addr2line",
++                                 exe_name,
++                                 "--demangle=gnat",
++                                 "--functions",
++                                 "--basenames",
++                                 NULL };
++          char *const envp[] = { NULL };
++          if (execve("/usr/bin/addr2line", argv, envp) < 0) {
++            CLOSE1; CLOSE2;
++          }
++        }
++      }
++      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;
++}
+--- gcc/ada/Makefile.in~       2006-02-24 04:49:43.000000000 +0100
++++ gcc/ada/Makefile.in        2006-04-07 08:15:50.000000000 +0200
+@@ -1352,7 +1352,7 @@
+ include $(fsrcdir)/Makefile.rtl
+ 
+ GNATRTL_OBJS = $(GNATRTL_NONTASKING_OBJS) $(GNATRTL_TASKING_OBJS) \
+-  g-trasym.o memtrack.o
++  g-trasym.o memtrack.o convert_addresses.o
+ 
+ # Default run time files
+ 
+@@ -1507,7 +1507,6 @@
+       for file in rts/*.ali; do \
+           $(INSTALL_DATA_DATE) $$file $(DESTDIR)$(ADA_RTL_OBJ_DIR); \
+       done
+-      -$(INSTALL_DATA) rts/g-trasym$(objext) $(DESTDIR)$(ADA_RTL_OBJ_DIR)
+       -cd rts; for file in *$(arext);do \
+           $(INSTALL_DATA) $$file $(DESTDIR)$(ADA_RTL_OBJ_DIR); \
+           $(RANLIB_FOR_TARGET) $(DESTDIR)$(ADA_RTL_OBJ_DIR)/$$file; \
+@@ -1607,7 +1606,7 @@
+               $(GNATRTL_OBJS)
+       $(RM) rts/libgnat$(arext) rts/libgnarl$(arext)
+       $(AR_FOR_TARGET) $(AR_FLAGS) rts/libgnat$(arext) \
+-         $(addprefix rts/,$(GNATRTL_NONTASKING_OBJS) $(LIBGNAT_OBJS))
++         $(addprefix rts/,$(GNATRTL_NONTASKING_OBJS) $(LIBGNAT_OBJS) g-trasym.o convert_addresses.o)
+         ifneq ($(PREFIX_OBJS),)
+               $(AR_FOR_TARGET) $(AR_FLAGS) rts/libgccprefix$(arext) \
+                 $(PREFIX_OBJS);
+@@ -1637,6 +1636,7 @@
+               $(TARGET_LIBGCC2_CFLAGS) \
+               -o libgnat$(hyphen)$(LIBRARY_VERSION)$(soext) \
+               $(GNATRTL_NONTASKING_OBJS) $(LIBGNAT_OBJS) \
++              g-trasym.o convert_addresses.o \
+               $(SO_OPTS)libgnat$(hyphen)$(LIBRARY_VERSION)$(soext) \
+               $(MISCLIB) -lm
+       cd rts; ../../xgcc -B../../ -shared $(GNATLIBCFLAGS) \
+@@ -1859,6 +1859,7 @@
+ sysdep.o  : sysdep.c
+ raise-gcc.o : raise-gcc.c raise.h
+ raise.o   : raise.c raise.h
++convert_addresses.o : convert_addresses.c
+ 
+ gen-soccon: gen-soccon.c gsocket.h
+       $(CC) $(ALL_CFLAGS) $(ADA_CFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) \
Index: rules.patch
===================================================================
RCS file: /var/lib/cvs/gcc-debian/F-590C83D3C4DDFAAC5F6B64349CB06DF2.patch,v
retrieving revision 1.1.2.3
diff -u -r1.1.2.3 rules.patch
--- rules.patch 1 Apr 2006 14:06:00 -0000       1.1.2.3
+++ rules.patch 8 Apr 2006 13:16:40 -0000
@@ -63,9 +63,10 @@
 endif
 
 ifeq ($(with_ada),yes)
   debian_patches += ada-gcc-name ada-default-project-path #ada-names
+  debian_patches += ada-symbolic-tracebacks
   ifeq ($(with_libgnat),yes)
     debian_patches += ada-link-lib
   endif
   ifeq ($(DEB_TARGET_ARCH)-$(distribution),ia64-Debian)
     debian_patches += ignore-comp-fail
   endif



Reply to: