diff options
author | Samuel Thibault <samuel.thibault@ens-lyon.org> | 2018-01-08 10:30:16 -0500 |
---|---|---|
committer | Simon Marchi <simon.marchi@ericsson.com> | 2018-01-08 10:33:41 -0500 |
commit | 9c4ac400f0f7d8daa8483dbe73b5699782ae3e22 (patch) | |
tree | b30c337adda923a12669b23c23b6f9ff7f24eabd | |
parent | 704a705d7aaab8041df76e2981e2a1efc014aad0 (diff) | |
download | gdb-9c4ac400f0f7d8daa8483dbe73b5699782ae3e22.zip gdb-9c4ac400f0f7d8daa8483dbe73b5699782ae3e22.tar.gz gdb-9c4ac400f0f7d8daa8483dbe73b5699782ae3e22.tar.bz2 |
hurd: Add enough auxv support for AT_ENTRY for PIE binaries
Add PIE support for hurd, by faking an AT_ENTRY auxv entry. That value
is expected to be read by svr4_exec_displacement, which will propagate
the executable displacement.
gdb/ChangeLog:
* gdb/gnu-nat.c: Include <elf.h> and <link.h>.
(gnu_xfer_auxv): New function.
(gnu_xfer_partial): Call gnu_xfer_auxv when `object' is
TARGET_OBJECT_AUXV.
-rw-r--r-- | gdb/ChangeLog | 7 | ||||
-rw-r--r-- | gdb/gnu-nat.c | 58 |
2 files changed, 65 insertions, 0 deletions
diff --git a/gdb/ChangeLog b/gdb/ChangeLog index cf93d22..238bcba 100644 --- a/gdb/ChangeLog +++ b/gdb/ChangeLog @@ -1,3 +1,10 @@ +2018-01-08 Samuel Thibault <samuel.thibault@ens-lyon.org> + + * gdb/gnu-nat.c: Include <elf.h> and <link.h>. + (gnu_xfer_auxv): New function. + (gnu_xfer_partial): Call gnu_xfer_auxv when `object' is + TARGET_OBJECT_AUXV. + 2018-01-08 Yao Qi <yao.qi@linaro.org> Simon Marchi <simon.marchi@ericsson.com> diff --git a/gdb/gnu-nat.c b/gdb/gnu-nat.c index 3972b22..f2d5fca 100644 --- a/gdb/gnu-nat.c +++ b/gdb/gnu-nat.c @@ -52,6 +52,8 @@ extern "C" #include <setjmp.h> #include <signal.h> #include <sys/ptrace.h> +#include <elf.h> +#include <link.h> #include "inferior.h" #include "symtab.h" @@ -2541,6 +2543,60 @@ gnu_xfer_memory (gdb_byte *readbuf, const gdb_byte *writebuf, } } +/* GNU does not have auxv, but we can at least fake the AT_ENTRY entry for PIE + binaries. */ +static enum target_xfer_status +gnu_xfer_auxv (gdb_byte *readbuf, const gdb_byte *writebuf, + CORE_ADDR memaddr, ULONGEST len, ULONGEST *xfered_len) +{ + task_t task = (gnu_current_inf + ? (gnu_current_inf->task + ? gnu_current_inf->task->port : 0) + : 0); + process_t proc; + int res; + kern_return_t err; + vm_address_t entry; + ElfW(auxv_t) auxv[2]; + + if (task == MACH_PORT_NULL) + return TARGET_XFER_E_IO; + if (writebuf != NULL) + return TARGET_XFER_E_IO; + + if (memaddr == sizeof (auxv)) + return TARGET_XFER_EOF; + if (memaddr > sizeof (auxv)) + return TARGET_XFER_E_IO; + + err = proc_task2proc (proc_server, task, &proc); + if (err != 0) + return TARGET_XFER_E_IO; + + /* Get entry from proc server. */ + err = proc_get_entry (proc, &entry); + if (err != 0) + return TARGET_XFER_E_IO; + + /* Fake auxv entry. */ + auxv[0].a_type = AT_ENTRY; + auxv[0].a_un.a_val = entry; + auxv[1].a_type = AT_NULL; + auxv[1].a_un.a_val = 0; + + inf_debug (gnu_current_inf, "reading auxv %s[%s] --> %s", + paddress (target_gdbarch (), memaddr), pulongest (len), + host_address_to_string (readbuf)); + + if (memaddr + len > sizeof (auxv)) + len = sizeof (auxv) - memaddr; + + memcpy (readbuf, (gdb_byte *) &auxv + memaddr, len); + *xfered_len = len; + + return TARGET_XFER_OK; +} + /* Target to_xfer_partial implementation. */ static enum target_xfer_status @@ -2553,6 +2609,8 @@ gnu_xfer_partial (struct target_ops *ops, enum target_object object, { case TARGET_OBJECT_MEMORY: return gnu_xfer_memory (readbuf, writebuf, offset, len, xfered_len); + case TARGET_OBJECT_AUXV: + return gnu_xfer_auxv (readbuf, writebuf, offset, len, xfered_len); default: return TARGET_XFER_E_IO; } |