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(<e[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;
+}