[PATCH 5/5 v4] Allow target to decide where to map jump-pad.

Wei-cheng Wang cole945@gmail.com
Sat Jun 27 16:22:00 GMT 2015


Ulrich Weigand wrote:
> Looks OK to me.  Note that getauxval was only introduced with
> a relatively recent glibc release, so might warrant a configure
> check to avoid breaking the build on older releases ...

Current configure.ac had alreadly check getauxval,

  AC_CHECK_FUNCS(getauxval pread pwrite pread64 setns)

so I simply add the old-fashioned-way getauxval fallback if it's not there.

Thanks,
Wei-cheng

---

This patch adds an IPA function, jump_pad_area_hint, for giving a hint
where to map jump pad buffer.  For some targets, addr = page-size is
too far to reach from executable.

gdb/gdbserver/ChangeLog

2015-06-27  Wei-cheng Wang  <cole945@gmail.com>

	* tracepoint.c (initialize_tracepoint): Call jump_pad_area_hint
        to get where to map gdb_jump_pad_buffer.  Remove MAP_FIXED.
	* tracepoint.h (jump_pad_area_hint): Add declaration.
	* linux-amd64-ipa.c (jump_pad_area_hint): New function.
	* linux-i386-ipa.c (jump_pad_area_hint): New function.
	* linux-ppc-ipa.c (jump_pad_area_hint): New function.
	(getauxvl): New function.
---
 gdb/gdbserver/linux-amd64-ipa.c | 10 ++++++++
 gdb/gdbserver/linux-i386-ipa.c  | 10 ++++++++
 gdb/gdbserver/linux-ppc-ipa.c   | 51 +++++++++++++++++++++++++++++++++++++++++
 gdb/gdbserver/tracepoint.c      |  7 +++---
 gdb/gdbserver/tracepoint.h      |  3 +++
 5 files changed, 77 insertions(+), 4 deletions(-)

diff --git a/gdb/gdbserver/linux-amd64-ipa.c b/gdb/gdbserver/linux-amd64-ipa.c
index a6dfb03..65cd748 100644
--- a/gdb/gdbserver/linux-amd64-ipa.c
+++ b/gdb/gdbserver/linux-amd64-ipa.c
@@ -77,6 +77,16 @@ gdb_agent_get_raw_reg (const unsigned char *raw_regs, int regnum)
   return *(ULONGEST *) (raw_regs + x86_64_ft_collect_regmap[regnum]);
 }
 
+/* See tracepoint.h.  */
+
+uintptr_t
+jump_pad_area_hint (void)
+{
+  /* Allocate scratch buffer aligned on a page boundary, at a low
+     address (close to the main executable's code).  */
+  return sysconf (_SC_PAGE_SIZE);
+}
+
 #ifdef HAVE_UST
 
 #include <ust/processor.h>
diff --git a/gdb/gdbserver/linux-i386-ipa.c b/gdb/gdbserver/linux-i386-ipa.c
index eb30dcd..dc0dfaf 100644
--- a/gdb/gdbserver/linux-i386-ipa.c
+++ b/gdb/gdbserver/linux-i386-ipa.c
@@ -114,6 +114,16 @@ gdb_agent_get_raw_reg (const unsigned char *raw_regs, int regnum)
     return *(int *) (raw_regs + i386_ft_collect_regmap[regnum]);
 }
 
+/* See tracepoint.h.  */
+
+uintptr_t
+jump_pad_area_hint (void)
+{
+  /* Allocate scratch buffer aligned on a page boundary, at a low
+     address (close to the main executable's code).  */
+  return sysconf (_SC_PAGE_SIZE);
+}
+
 #ifdef HAVE_UST
 
 #include <ust/processor.h>
diff --git a/gdb/gdbserver/linux-ppc-ipa.c b/gdb/gdbserver/linux-ppc-ipa.c
index 73d8899..ddb2174 100644
--- a/gdb/gdbserver/linux-ppc-ipa.c
+++ b/gdb/gdbserver/linux-ppc-ipa.c
@@ -21,6 +21,8 @@
 #include "server.h"
 #include "tracepoint.h"
 
+#include <sys/auxv.h>
+
 #if defined __PPC64__
 void init_registers_powerpc_64l (void);
 extern const struct target_desc *tdesc_powerpc_64l;
@@ -105,6 +107,55 @@ gdb_agent_get_raw_reg (const unsigned char *raw_regs, int regnum)
 			+ ppc_ft_collect_regmap[regnum] * REGSZ);
 }
 
+#ifndef HAVE_GETAUXVAL
+/* 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.  */
+
+static 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] == AT_HWCAP)
+	{
+	  value = data[1];
+	  break;
+	}
+    }
+
+  fclose (f);
+  return value;
+}
+#endif
+
+/* See tracepoint.h.  */
+
+uintptr_t
+jump_pad_area_hint (void)
+{
+  /* Use AT_PHDR address to guess where the main executable is mapped,
+     and try to map the jump pad before it.  The jump pad should be
+     closed enough to the executable for unconditional branch (+/- 32MB). */
+
+  const int SCRATCH_BUFFER_NPAGES = 20;
+  uintptr_t base = getauxval (AT_PHDR);
+  uintptr_t pagesz = sysconf (_SC_PAGE_SIZE);
+  uintptr_t hint = (base & ~(pagesz - 1)) - SCRATCH_BUFFER_NPAGES * pagesz;
+
+  /* Return the lowest possible value if wrap-around.  */
+  if (hint > base)
+    hint = pagesz;
+
+  return hint;
+}
+
 /* Initialize ipa_tdesc and others.  */
 
 void
diff --git a/gdb/gdbserver/tracepoint.c b/gdb/gdbserver/tracepoint.c
index fdec7db..d1c03cf 100644
--- a/gdb/gdbserver/tracepoint.c
+++ b/gdb/gdbserver/tracepoint.c
@@ -7355,13 +7355,12 @@ initialize_tracepoint (void)
 
 #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)
+    addr = jump_pad_area_hint ();
+    for (; addr != 0; addr += pagesize)
       {
 	gdb_jump_pad_buffer = mmap ((void *) addr, pagesize * SCRATCH_BUFFER_NPAGES,
 				    PROT_READ | PROT_WRITE | PROT_EXEC,
-				    MAP_PRIVATE | MAP_ANONYMOUS | MAP_FIXED,
+				    MAP_PRIVATE | MAP_ANONYMOUS,
 				    -1, 0);
 	if (gdb_jump_pad_buffer != MAP_FAILED)
 	  break;
diff --git a/gdb/gdbserver/tracepoint.h b/gdb/gdbserver/tracepoint.h
index 30d0b58..139894f 100644
--- a/gdb/gdbserver/tracepoint.h
+++ b/gdb/gdbserver/tracepoint.h
@@ -131,6 +131,9 @@ void supply_static_tracepoint_registers (struct regcache *regcache,
 					 CORE_ADDR pc);
 void set_trampoline_buffer_space (CORE_ADDR begin, CORE_ADDR end,
 				  char *errmsg);
+/* Return the address for where to allocate buffer for jump pad.
+   The buffer should be close enough for tracepoints.  */
+uintptr_t jump_pad_area_hint (void);
 
 extern const struct target_desc *ipa_tdesc;
 
-- 
1.9.1



More information about the Gdb-patches mailing list