diff options
Diffstat (limited to 'gdb')
-rw-r--r-- | gdb/gdbserver/ChangeLog | 14 | ||||
-rw-r--r-- | gdb/gdbserver/linux-aarch64-ipa.c | 50 | ||||
-rw-r--r-- | gdb/gdbserver/linux-amd64-ipa.c | 18 | ||||
-rw-r--r-- | gdb/gdbserver/linux-i386-ipa.c | 15 | ||||
-rw-r--r-- | gdb/gdbserver/linux-s390-ipa.c | 59 | ||||
-rw-r--r-- | gdb/gdbserver/tracepoint.c | 53 | ||||
-rw-r--r-- | gdb/gdbserver/tracepoint.h | 4 |
7 files changed, 194 insertions, 19 deletions
diff --git a/gdb/gdbserver/ChangeLog b/gdb/gdbserver/ChangeLog index 644a81088fe..045faee1ba1 100644 --- a/gdb/gdbserver/ChangeLog +++ b/gdb/gdbserver/ChangeLog @@ -1,3 +1,17 @@ +2016-03-31 Marcin KoĆcielnicki <koriakin@0x04.net> + + * linux-aarch64-ipa.c: Add <sys/mman.h> and <sys/auxv.h> includes. + (alloc_jump_pad_buffer): New function. + * linux-amd64-ipa.c: Add <sys/mman.h> include. + (alloc_jump_pad_buffer): New function. + * linux-i386-ipa.c (alloc_jump_pad_buffer): New function. + * linux-s390-ipa.c: Add <sys/mman.h> and <sys/auxv.h> includes. + (alloc_jump_pad_buffer): New function. + * tracepoint.c (getauxval) [!HAVE_GETAUXVAL]: New function. + (initialize_tracepoint): Delegate to alloc_jump_pad_buffer. + * tracepoint.h (alloc_jump_pad_buffer): New prototype. + (getauxval) [!HAVE_GETAUXVAL]: New prototype. + 2016-03-30 Marcin KoĆcielnicki <koriakin@0x04.net> * linux-aarch64-ipa.c: Rename gdb_agent_get_raw_reg to get_raw_reg. diff --git a/gdb/gdbserver/linux-aarch64-ipa.c b/gdb/gdbserver/linux-aarch64-ipa.c index 00cbf3ee89d..50caeae4f3f 100644 --- a/gdb/gdbserver/linux-aarch64-ipa.c +++ b/gdb/gdbserver/linux-aarch64-ipa.c @@ -19,7 +19,11 @@ along with this program. If not, see <http://www.gnu.org/licenses/>. */ #include "server.h" +#include <sys/mman.h> #include "tracepoint.h" +#ifdef HAVE_GETAUXVAL +#include <sys/auxv.h> +#endif /* Defined in auto-generated file aarch64.c. */ void init_registers_aarch64 (void); @@ -153,6 +157,52 @@ get_ipa_tdesc (int idx) return tdesc_aarch64; } +/* Allocate buffer for the jump pads. The branch instruction has a reach + of +/- 128MiB, and the executable is loaded at 0x400000 (4MiB). + To maximize the area of executable that can use tracepoints, try + allocating at 0x400000 - size initially, decreasing until we hit + a free area. */ + +void * +alloc_jump_pad_buffer (size_t size) +{ + uintptr_t addr; + uintptr_t exec_base = getauxval (AT_PHDR); + int pagesize; + void *res; + + if (exec_base == 0) + exec_base = 0x400000; + + pagesize = sysconf (_SC_PAGE_SIZE); + if (pagesize == -1) + perror_with_name ("sysconf"); + + addr = exec_base - size; + + /* size should already be page-aligned, but this can't hurt. */ + addr &= ~(pagesize - 1); + + /* Search for a free area. If we hit 0, we're out of luck. */ + for (; addr; addr -= pagesize) + { + /* No MAP_FIXED - we don't want to zap someone's mapping. */ + res = mmap ((void *) addr, size, + PROT_READ | PROT_WRITE | PROT_EXEC, + MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); + + /* If we got what we wanted, return. */ + if ((uintptr_t) res == addr) + return res; + + /* If we got a mapping, but at a wrong address, undo it. */ + if (res != MAP_FAILED) + munmap (res, size); + } + + return NULL; +} + void initialize_low_tracepoint (void) { diff --git a/gdb/gdbserver/linux-amd64-ipa.c b/gdb/gdbserver/linux-amd64-ipa.c index 70889d293a7..c623dc204be 100644 --- a/gdb/gdbserver/linux-amd64-ipa.c +++ b/gdb/gdbserver/linux-amd64-ipa.c @@ -19,6 +19,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>. */ #include "server.h" +#include <sys/mman.h> #include "tracepoint.h" #include "linux-x86-tdesc.h" @@ -190,6 +191,23 @@ get_ipa_tdesc (int idx) } } +/* Allocate buffer for the jump pads. Since we're using 32-bit jumps + to reach them, and the executable is at low addresses, MAP_32BIT + works just fine. Shared libraries, being allocated at the top, + are unfortunately out of luck. */ + +void * +alloc_jump_pad_buffer (size_t size) +{ + void *res = mmap (NULL, size, PROT_READ | PROT_WRITE | PROT_EXEC, + MAP_PRIVATE | MAP_ANONYMOUS | MAP_32BIT, -1, 0); + + if (res == MAP_FAILED) + return NULL; + + return res; +} + void initialize_low_tracepoint (void) { diff --git a/gdb/gdbserver/linux-i386-ipa.c b/gdb/gdbserver/linux-i386-ipa.c index 7159eeed396..45e5a0d5f84 100644 --- a/gdb/gdbserver/linux-i386-ipa.c +++ b/gdb/gdbserver/linux-i386-ipa.c @@ -269,6 +269,21 @@ get_ipa_tdesc (int idx) } } +/* Allocate buffer for the jump pads. On i386, we can reach an arbitrary + address with a jump instruction, so just allocate normally. */ + +void * +alloc_jump_pad_buffer (size_t size) +{ + void *res = mmap (NULL, size, PROT_READ | PROT_WRITE | PROT_EXEC, + MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); + + if (res == MAP_FAILED) + return NULL; + + return res; +} + void initialize_low_tracepoint (void) { diff --git a/gdb/gdbserver/linux-s390-ipa.c b/gdb/gdbserver/linux-s390-ipa.c index cd4faddae8a..a9f86ad4441 100644 --- a/gdb/gdbserver/linux-s390-ipa.c +++ b/gdb/gdbserver/linux-s390-ipa.c @@ -19,8 +19,12 @@ along with this program. If not, see <http://www.gnu.org/licenses/>. */ #include "server.h" +#include <sys/mman.h> #include "tracepoint.h" #include "linux-s390-tdesc.h" +#ifdef HAVE_GETAUXVAL +#include <sys/auxv.h> +#endif #define FT_FPR(x) (0x000 + (x) * 0x10) #define FT_VR(x) (0x000 + (x) * 0x10) @@ -370,6 +374,61 @@ get_ipa_tdesc (int idx) } } +/* Allocate buffer for the jump pads. On 31-bit, JG reaches everywhere, + so just allocate normally. On 64-bit, we have +/-4GiB of reach, and + the executable is usually mapped at 0x80000000 - aim for somewhere + below it. */ + +void * +alloc_jump_pad_buffer (size_t size) +{ +#ifdef __s390x__ + uintptr_t addr; + uintptr_t exec_base = getauxval (AT_PHDR); + int pagesize; + void *res; + + if (exec_base == 0) + exec_base = 0x80000000; + + pagesize = sysconf (_SC_PAGE_SIZE); + if (pagesize == -1) + perror_with_name ("sysconf"); + + addr = exec_base - size; + + /* size should already be page-aligned, but this can't hurt. */ + addr &= ~(pagesize - 1); + + /* Search for a free area. If we hit 0, we're out of luck. */ + for (; addr; addr -= pagesize) + { + /* No MAP_FIXED - we don't want to zap someone's mapping. */ + res = mmap ((void *) addr, size, + PROT_READ | PROT_WRITE | PROT_EXEC, + MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); + + /* If we got what we wanted, return. */ + if ((uintptr_t) res == addr) + return res; + + /* If we got a mapping, but at a wrong address, undo it. */ + if (res != MAP_FAILED) + munmap (res, size); + } + + return NULL; +#else + void *res = mmap (NULL, size, PROT_READ | PROT_WRITE | PROT_EXEC, + MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); + + if (res == MAP_FAILED) + return NULL; + + return res; +#endif +} + void initialize_low_tracepoint (void) { diff --git a/gdb/gdbserver/tracepoint.c b/gdb/gdbserver/tracepoint.c index 83d1830db2b..56b8e69556c 100644 --- a/gdb/gdbserver/tracepoint.c +++ b/gdb/gdbserver/tracepoint.c @@ -216,6 +216,34 @@ static struct ipa_sym_addresses ipa_sym_addrs; static int read_inferior_integer (CORE_ADDR symaddr, int *val); +#if !defined HAVE_GETAUXVAL && defined IN_PROCESS_AGENT +/* Retrieve the value of TYPE from the auxiliary vector. If TYPE is not + found, 0 is returned. This function is provided if glibc is too old. */ + +unsigned long +getauxval (unsigned long type) +{ + unsigned long data[2]; + FILE *f = fopen ("/proc/self/auxv", "r"); + unsigned long value = 0; + + if (f == NULL) + return 0; + + while (fread (data, sizeof (data), 1, f) > 0) + { + if (data[0] == type) + { + value = data[1]; + break; + } + } + + fclose (f); + return value; +} +#endif + /* Returns true if both the in-process agent library and the static tracepoints libraries are loaded in the inferior, and agent has capability on static tracepoints. */ @@ -7400,35 +7428,22 @@ initialize_tracepoint (void) #ifdef IN_PROCESS_AGENT { - uintptr_t addr; int pagesize; + size_t jump_pad_size; pagesize = sysconf (_SC_PAGE_SIZE); if (pagesize == -1) perror_with_name ("sysconf"); - gdb_tp_heap_buffer = (char *) xmalloc (5 * 1024 * 1024); - #define SCRATCH_BUFFER_NPAGES 20 - /* Allocate scratch buffer aligned on a page boundary, at a low - address (close to the main executable's code). */ - for (addr = pagesize; addr != 0; addr += pagesize) - { - gdb_jump_pad_buffer - = (char *) mmap ((void *) addr, - pagesize * SCRATCH_BUFFER_NPAGES, - PROT_READ | PROT_WRITE | PROT_EXEC, - MAP_PRIVATE | MAP_ANONYMOUS | MAP_FIXED, - -1, 0); - if (gdb_jump_pad_buffer != MAP_FAILED) - break; - } + jump_pad_size = pagesize * SCRATCH_BUFFER_NPAGES; - if (addr == 0) + gdb_tp_heap_buffer = (char *) xmalloc (5 * 1024 * 1024); + gdb_jump_pad_buffer = alloc_jump_pad_buffer (jump_pad_size); + if (gdb_jump_pad_buffer == NULL) perror_with_name ("mmap"); - - gdb_jump_pad_buffer_end = gdb_jump_pad_buffer + pagesize * SCRATCH_BUFFER_NPAGES; + gdb_jump_pad_buffer_end = gdb_jump_pad_buffer + jump_pad_size; } gdb_trampoline_buffer = gdb_trampoline_buffer_end = 0; diff --git a/gdb/gdbserver/tracepoint.h b/gdb/gdbserver/tracepoint.h index df815efef54..679a32a3999 100644 --- a/gdb/gdbserver/tracepoint.h +++ b/gdb/gdbserver/tracepoint.h @@ -132,6 +132,10 @@ void supply_static_tracepoint_registers (struct regcache *regcache, CORE_ADDR pc); void set_trampoline_buffer_space (CORE_ADDR begin, CORE_ADDR end, char *errmsg); +void *alloc_jump_pad_buffer (size_t size); +#ifndef HAVE_GETAUXVAL +unsigned long getauxval (unsigned long type); +#endif #else void stop_tracing (void); |