diff options
-rw-r--r-- | gdb/gdbserver/ChangeLog | 11 | ||||
-rw-r--r-- | gdb/gdbserver/linux-aarch64-ipa.c | 43 | ||||
-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/tracepoint.c | 25 | ||||
-rw-r--r-- | gdb/gdbserver/tracepoint.h | 1 |
6 files changed, 94 insertions, 19 deletions
diff --git a/gdb/gdbserver/ChangeLog b/gdb/gdbserver/ChangeLog index 31120c5abf4..4a4a9bff42e 100644 --- a/gdb/gdbserver/ChangeLog +++ b/gdb/gdbserver/ChangeLog @@ -1,3 +1,14 @@ +2016-03-13 Marcin KoĆcielnicki <koriakin@0x04.net> + + * linux-aarch64-ipa.c: Add <sys/mman.h> include. + (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. + * tracepoint.c (initialize_tracepoint): Delegate to + alloc_jump_pad_buffer. + * tracepoint.h (alloc_jump_pad_buffer): New prototype. + 2016-03-12 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..b95751b4f08 100644 --- a/gdb/gdbserver/linux-aarch64-ipa.c +++ b/gdb/gdbserver/linux-aarch64-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" /* Defined in auto-generated file aarch64.c. */ @@ -153,6 +154,48 @@ 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; + int pagesize; + void *res; + + pagesize = sysconf (_SC_PAGE_SIZE); + if (pagesize == -1) + perror_with_name ("sysconf"); + + addr = 0x400000 - 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 < 0x400000) + 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..9ee0fe83085 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..52c0581ac29 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/tracepoint.c b/gdb/gdbserver/tracepoint.c index 061e1614d0b..0b6d3274955 100644 --- a/gdb/gdbserver/tracepoint.c +++ b/gdb/gdbserver/tracepoint.c @@ -7400,35 +7400,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..0f4d4980161 100644 --- a/gdb/gdbserver/tracepoint.h +++ b/gdb/gdbserver/tracepoint.h @@ -132,6 +132,7 @@ 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); #else void stop_tracing (void); |