summaryrefslogtreecommitdiff
path: root/gdb
diff options
context:
space:
mode:
Diffstat (limited to 'gdb')
-rw-r--r--gdb/gdbserver/ChangeLog14
-rw-r--r--gdb/gdbserver/linux-aarch64-ipa.c50
-rw-r--r--gdb/gdbserver/linux-amd64-ipa.c18
-rw-r--r--gdb/gdbserver/linux-i386-ipa.c15
-rw-r--r--gdb/gdbserver/linux-s390-ipa.c59
-rw-r--r--gdb/gdbserver/tracepoint.c53
-rw-r--r--gdb/gdbserver/tracepoint.h4
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);