Mirror of the gdb-patches mailing list
 help / color / mirror / Atom feed
From: "Marcin Kościelnicki" <koriakin@0x04.net>
To: gdb-patches@sourceware.org
Cc: "Marcin Kościelnicki" <koriakin@0x04.net>
Subject: [PATCH 2/4 v2] IPA: Add alloc_jump_pad_buffer target hook.
Date: Fri, 18 Mar 2016 15:08:00 -0000	[thread overview]
Message-ID: <1458313693-5679-1-git-send-email-koriakin@0x04.net> (raw)
In-Reply-To: <1457836296-29974-3-git-send-email-koriakin@0x04.net>

Targets may have various requirements on the required location of the jump
pad area.  Currently IPA allocates it at the lowest possible address,
so that it is reachable by branches from the executable.  However, this
fails on powerpc, which has executable link address (0x10000000) much
larger than branch reach (+/- 32MiB).

This makes jump pad buffer allocation a target hook instead.  The current
implementations are as follows:

- i386: Branches can reach anywhere, so just mmap it.  This avoids
  the linear search dance.
- x86_64: Branches have +/-2GiB of reach, and executable is loaded low,
  so just call mmap with MAP_32BIT.  Likewise avoids the linear search.
- aarch64: Branches have +-128MiB of reach, executable loaded at 4MiB.
  Do a linear search from 4MiB-size downwards to page_size.

gdb/gdbserver/ChangeLog:

	* 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 (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.
---
This version changes aarch64 to use getauxval(AT_PHDR) instead of
hardcoded default load address.

Note: this patch will need testing on aarch64, I don't have a machine
for that.  The code works for powerpc64 though.

 gdb/gdbserver/ChangeLog           | 12 +++++++++
 gdb/gdbserver/linux-aarch64-ipa.c | 50 ++++++++++++++++++++++++++++++++++++
 gdb/gdbserver/linux-amd64-ipa.c   | 18 +++++++++++++
 gdb/gdbserver/linux-i386-ipa.c    | 15 +++++++++++
 gdb/gdbserver/tracepoint.c        | 53 +++++++++++++++++++++++++--------------
 gdb/gdbserver/tracepoint.h        |  4 +++
 6 files changed, 133 insertions(+), 19 deletions(-)

diff --git a/gdb/gdbserver/ChangeLog b/gdb/gdbserver/ChangeLog
index 31120c5..46e9ac2 100644
--- a/gdb/gdbserver/ChangeLog
+++ b/gdb/gdbserver/ChangeLog
@@ -1,3 +1,15 @@
+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 (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-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 00cbf3e..50caeae 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 70889d2..9ee0fe8 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 7159eee..52c0581 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 061e161..f90f19e 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 df815ef..3712881 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);
+#ifdef HAVE_GETAUXVAL
+unsigned long getauxval (unsigned long type);
+#endif
 #else
 void stop_tracing (void);
 
-- 
2.7.3


  reply	other threads:[~2016-03-18 15:08 UTC|newest]

Thread overview: 56+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2016-03-13  2:31 [PATCH 0/3] gdbserver: Add powerpc fast tracepoint support Marcin Kościelnicki
2016-03-13  2:32 ` [PATCH 3/3] " Marcin Kościelnicki
2016-03-14 22:10   ` [PATCH 3/4 v2] " Marcin Kościelnicki
2016-03-16 16:58     ` Ulrich Weigand
2016-03-16 17:55       ` Marcin Kościelnicki
2016-03-17  6:30         ` Ulrich Weigand
2016-03-18 15:09           ` [PATCH v2 3/4] " Marcin Kościelnicki
2016-03-29 18:23             ` Ulrich Weigand
2016-03-30 14:52             ` Simon Marchi
2016-03-30 14:57               ` Ulrich Weigand
2016-03-30 15:24                 ` Simon Marchi
2016-03-30 15:28                   ` Simon Marchi
2016-03-30 15:35                     ` Ulrich Weigand
2016-03-31  1:31                       ` Marcin Kościelnicki
2016-03-31 11:39                         ` Ulrich Weigand
2016-03-31 13:45                           ` Marcin Kościelnicki
2016-03-13  2:32 ` [PATCH 1/3] gdbserver/IPA: Export some functions via global function pointers Marcin Kościelnicki
2016-03-14 14:41   ` Ulrich Weigand
2016-03-14 14:53     ` Marcin Kościelnicki
2016-03-14 17:49       ` Ulrich Weigand
2016-03-22  9:19         ` Marcin Kościelnicki
2016-03-29 18:08           ` Ulrich Weigand
2016-03-29 21:51             ` Pedro Alves
2016-03-30 11:30               ` Ulrich Weigand
2016-03-29 21:52             ` Marcin Kościelnicki
2016-03-30 11:32               ` Ulrich Weigand
2016-03-30 22:02                 ` Marcin Kościelnicki
2016-03-31 18:22                   ` Sergio Durigan Junior
2016-03-31 21:42                     ` [PATCH obv] gdbserver: Fix C++ build errors in tracepoint.c Marcin Kościelnicki
2016-03-14 17:08     ` [PATCH 1/3] gdbserver/IPA: Export some functions via global function pointers Simon Marchi
2016-03-14 17:40       ` Ulrich Weigand
2016-03-13  2:32 ` [PATCH 2/3] IPA: Add alloc_jump_pad_buffer target hook Marcin Kościelnicki
2016-03-18 15:08   ` Marcin Kościelnicki [this message]
2016-03-29 18:18     ` [PATCH 2/4 v2] " Ulrich Weigand
2016-03-29 22:04       ` Marcin Kościelnicki
2016-03-30 11:38         ` Ulrich Weigand
2016-03-30 14:50           ` Yao Qi
2016-03-30 14:58             ` Ulrich Weigand
2016-03-31  7:34               ` Yao Qi
2016-03-31 11:37                 ` Ulrich Weigand
2016-03-31  1:16       ` [PATCH 2/4 v3] " Marcin Kościelnicki
2016-03-31 11:38         ` Ulrich Weigand
2016-03-31 13:42           ` Marcin Kościelnicki
2016-04-01 14:43         ` Ulrich Weigand
2016-04-03 12:31           ` [PATCH] IPA: Fix build problem on !HAVE_GETAUXVAL Marcin Kościelnicki
2016-04-03 16:26             ` Ulrich Weigand
2016-04-03 16:28               ` Marcin Kościelnicki
2016-04-04 14:41                 ` Ulrich Weigand
2016-04-05 13:33                   ` [PATCH] IPA: Move getauxval out of #ifndef IN_PROCESS_AGENT Marcin Kościelnicki
2016-04-05 15:04                     ` Ulrich Weigand
2016-04-05 16:55                       ` Marcin Kościelnicki
2016-03-14 22:25 ` [PATCH 4/4] gdbserver: Add emit_ops for powerpc Marcin Kościelnicki
2016-03-16 17:16   ` Ulrich Weigand
2016-03-18 15:10     ` [PATCH v2 " Marcin Kościelnicki
2016-03-29 18:25       ` Ulrich Weigand
2016-03-31 13:45         ` Marcin Kościelnicki

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=1458313693-5679-1-git-send-email-koriakin@0x04.net \
    --to=koriakin@0x04.net \
    --cc=gdb-patches@sourceware.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox