Hello,
attached is patch for ltrace 0.5.3 (from unstable) to add PIE support. Just in case somebody is interested - upstream's current git still does not grok PIE executables either.
                                        Thanks,
                                                Petr
diff -urN ltrace-0.5.3/breakpoints.c ltrace-0.5.3.pie/breakpoints.c
--- ltrace-0.5.3/breakpoints.c  2009-07-25 08:13:02.000000000 -0700
+++ ltrace-0.5.3.pie/breakpoints.c      2012-09-23 00:00:32.561719352 -0700
@@ -77,6 +77,22 @@
        }
 }
 
+static void
+parse_auxv(Process *proc) {
+       struct library_symbol *sym;
+       void *entry_point;
+       ptrdiff_t offset;
+
+       debug(DEBUG_FUNCTION, "parse_auxv(pid=%d)", proc->pid);
+       entry_point = get_entry_point(proc);
+       debug(1, "Header entry point %lX, loaded %p\n", proc->e_entry, 
entry_point);
+       offset = (uintptr_t)entry_point - proc->e_entry;
+       for (sym = proc->list_of_symbols; sym; sym = sym->next) {
+               sym->enter_addr += offset;
+               insert_breakpoint(proc, sym2addr(proc, sym), sym);
+       }
+}
+
 void
 enable_all_breakpoints(Process *proc) {
        debug(DEBUG_FUNCTION, "enable_all_breakpoints(pid=%d)", proc->pid);
@@ -99,7 +115,10 @@
 #endif
 
                debug(1, "Enabling breakpoints for pid %u...", proc->pid);
-               if (proc->breakpoints) {
+               if (proc->need_to_relocate_breakpoints) {
+                       proc->need_to_relocate_breakpoints = 0;
+                       parse_auxv(proc);
+               } else if (proc->breakpoints) {
                        dict_apply_to_all(proc->breakpoints, enable_bp_cb,
                                          proc);
                }
@@ -198,9 +217,19 @@
        } else {
                proc->list_of_symbols = NULL;
        }
-       for (sym = proc->list_of_symbols; sym; sym = sym->next) {
-               /* proc->pid==0 delays enabling. */
-               insert_breakpoint(proc, sym2addr(proc, sym), sym);
+       /*
+        * Only 386 & x86_64 are tested, so use DYN-via-auxv only for them.
+        * I think it works on other platforms too (as long as .plt is
+        * in same segment as entry point), but there are some suspicious
+        * mips and ppc ifdefs...
+        */
+       proc->need_to_relocate_breakpoints = proc->e_type == ET_DYN &&
+               (proc->e_machine == EM_386 || proc->e_machine == EM_X86_64);
+       if (!proc->need_to_relocate_breakpoints) {
+               for (sym = proc->list_of_symbols; sym; sym = sym->next) {
+                       /* proc->pid==0 delays enabling. */
+                       insert_breakpoint(proc, sym2addr(proc, sym), sym);
+               }
        }
        proc->callstack_depth = 0;
        proc->breakpoints_enabled = -1;
diff -urN ltrace-0.5.3/common.h ltrace-0.5.3.pie/common.h
--- ltrace-0.5.3/common.h       2009-07-25 08:13:02.000000000 -0700
+++ ltrace-0.5.3.pie/common.h   2012-09-22 23:41:48.067146052 -0700
@@ -177,7 +177,10 @@
        void * return_addr;
        Breakpoint * breakpoint_being_enabled;
        void * arch_ptr;
-       short e_machine;
+       GElf_Half e_type;
+       GElf_Half e_machine;
+       GElf_Addr e_entry;
+       short need_to_relocate_breakpoints;
        short need_to_reinitialize_breakpoints;
 #ifdef __arm__
        int thumb_mode;           /* ARM execution mode: 0: ARM, 1: Thumb */
@@ -247,6 +250,7 @@
 extern int umovelong (Process * proc, void * addr, long * result, 
arg_type_info * info);
 extern int ffcheck(void * maddr);
 extern void * sym2addr(Process *, struct library_symbol *);
+extern void * get_entry_point(Process *);
 
 #if 0                          /* not yet */
 extern int umoven(Process * proc, void * addr, int len, void * laddr);
diff -urN ltrace-0.5.3/elf.c ltrace-0.5.3.pie/elf.c
--- ltrace-0.5.3/elf.c  2009-07-25 08:13:02.000000000 -0700
+++ ltrace-0.5.3.pie/elf.c      2012-09-22 22:31:31.125049219 -0700
@@ -466,6 +466,8 @@
 
        do_init_elf(lte, proc->filename);
        proc->e_machine = lte->ehdr.e_machine;
+       proc->e_type = lte->ehdr.e_type;
+       proc->e_entry = lte->ehdr.e_entry;
        for (i = 0; i < library_num; ++i)
                do_init_elf(&lte[i + 1], library[i]);
 #ifdef __mips__
diff -urN ltrace-0.5.3/sysdeps/README ltrace-0.5.3.pie/sysdeps/README
--- ltrace-0.5.3/sysdeps/README 2009-07-25 08:13:02.000000000 -0700
+++ ltrace-0.5.3.pie/sysdeps/README     2012-09-22 23:35:00.708248113 -0700
@@ -30,3 +30,4 @@
 void trace_me(void);
 int trace_pid(pid_t pid);
 void untrace_pid(pid_t pid);
+void * get_entry_point(Process * proc);
diff -urN ltrace-0.5.3/sysdeps/linux-gnu/proc.c 
ltrace-0.5.3.pie/sysdeps/linux-gnu/proc.c
--- ltrace-0.5.3/sysdeps/linux-gnu/proc.c       2009-07-25 08:13:02.000000000 
-0700
+++ ltrace-0.5.3.pie/sysdeps/linux-gnu/proc.c   2012-09-23 00:07:26.420759968 
-0700
@@ -1,6 +1,10 @@
 #include "config.h"
 
+#include "common.h"
+
 #include <sys/types.h>
+#include <errno.h>
+#include <fcntl.h>
 #include <stdio.h>
 #include <string.h>
 #include <signal.h>
@@ -34,3 +38,61 @@
        }
        return NULL;
 }
+
+void *
+get_entry_point(Process * proc) {
+       char auxv_path[30];
+       int fd;
+       struct {
+               GElf_Word a_type;
+               GElf_Word a_val;
+       } auxv;
+       ssize_t rd;
+       GElf_Addr entry_point = 0;
+
+       debug(DEBUG_FUNCTION, "get_entry_point(pid=%d)", proc->pid);
+       sprintf(auxv_path, "/proc/%d/auxv", proc->pid);
+       fd = open(auxv_path, O_RDONLY);
+       if (fd == -1) {
+               fprintf(stderr, "Cannot open %s: %s\n", auxv_path,
+                       strerror(errno));
+               return NULL;
+       }
+       while (1) {
+               if ((LT_ELFCLASS == ELFCLASS32
+                    /* PPC has 32bit as ELFCLASS, and 64bit
+                      * as ELFCLASS2.  So need to check both. */
+#ifdef LT_ELFCLASS2
+                    && LT_ELFCLASS2 == ELFCLASS32
+#endif
+                    ) || proc->mask_32bit) {
+                       struct {
+                               Elf32_Word a_type;
+                               Elf32_Word a_val;
+                       } auxv32;
+
+                       rd = read(fd, &auxv32, sizeof auxv32);
+                       if (rd == sizeof auxv32) {
+                               auxv.a_type = auxv32.a_type;
+                               auxv.a_val = auxv32.a_val;
+                               rd = sizeof auxv;
+                       }
+               } else {
+                       rd = read(fd, &auxv, sizeof auxv);
+               }
+               if (rd != sizeof auxv) {
+                       break;
+               }
+               switch (auxv.a_type) {
+               case 9: /* ENTRY */
+                       entry_point = auxv.a_val;
+                       break;
+               }
+       }
+       close(fd);
+       if (!entry_point) {
+               fprintf(stderr, "Could not find entry point in auxv\n");
+               return NULL;
+       }
+       return (void *)(uintptr_t)entry_point;
+}

Reply via email to