summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gdb/gdbserver/ChangeLog11
-rw-r--r--gdb/gdbserver/linux-aarch64-ipa.c43
-rw-r--r--gdb/gdbserver/linux-amd64-ipa.c18
-rw-r--r--gdb/gdbserver/linux-i386-ipa.c15
-rw-r--r--gdb/gdbserver/tracepoint.c25
-rw-r--r--gdb/gdbserver/tracepoint.h1
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);