[PATCH v2] trace: look up start to cope with ASLR

Johannes Berg johannes at sipsolutions.net
Mon Feb 27 15:04:14 PST 2017


When ASLR is enabled, like it is by default on many distros now,
the trace code doesn't work right.

Fix this by looking up the start of the executable mapping and
subtracing it from all the lookups.

Signed-off-by: Johannes Berg <johannes at sipsolutions.net>
---
 src/utils/trace.c | 35 ++++++++++++++++++++++++++++++++---
 1 file changed, 32 insertions(+), 3 deletions(-)

diff --git a/src/utils/trace.c b/src/utils/trace.c
index d72cf604f8e9..5d85e8572871 100644
--- a/src/utils/trace.c
+++ b/src/utils/trace.c
@@ -5,6 +5,10 @@
  * This software may be distributed under the terms of the BSD license.
  * See README for more details.
  */
+#ifdef WPA_TRACE_BFD
+#define _GNU_SOURCE
+#include <link.h>
+#endif
 
 #include "includes.h"
 
@@ -25,6 +29,26 @@ static struct dl_list active_references =
 static char *prg_fname = NULL;
 static bfd *cached_abfd = NULL;
 static asymbol **syms = NULL;
+static unsigned long start_offset;
+static int start_offset_looked_up;
+
+static int callback(struct dl_phdr_info *info, size_t size, void *data)
+{
+	/*
+	 * dl_iterate_phdr(3):
+	 * "The first object visited by callback is the main program."
+	 */
+	start_offset = info->dlpi_addr;
+
+	/*
+	 * dl_iterate_phdr(3):
+	 * "The dl_iterate_phdr() function walks through the list of an
+	 *  application's shared objects and calls the function callback
+	 *  once for each object, until either all shared objects have
+	 *  been processed or callback returns a nonzero value."
+	 */
+	return 1;
+}
 
 static void get_prg_fname(void)
 {
@@ -160,7 +184,7 @@ static void wpa_trace_bfd_addr(void *pc)
 	if (abfd == NULL)
 		return;
 
-	data.pc = (bfd_hostptr_t) pc;
+	data.pc = (bfd_hostptr_t) (pc - start_offset);
 	data.found = FALSE;
 	bfd_map_over_sections(abfd, find_addr_sect, &data);
 
@@ -201,7 +225,7 @@ static const char * wpa_trace_bfd_addr2func(void *pc)
 	if (abfd == NULL)
 		return NULL;
 
-	data.pc = (bfd_hostptr_t) pc;
+	data.pc = (bfd_hostptr_t) (pc - start_offset);
 	data.found = FALSE;
 	bfd_map_over_sections(abfd, find_addr_sect, &data);
 
@@ -233,6 +257,11 @@ static void wpa_trace_bfd_init(void)
 		wpa_printf(MSG_INFO, "Failed to read symbols");
 		return;
 	}
+
+	if (!start_offset_looked_up) {
+		dl_iterate_phdr(callback, NULL);
+		start_offset_looked_up = 1;
+	}
 }
 
 
@@ -268,7 +297,7 @@ size_t wpa_trace_calling_func(const char *buf[], size_t len)
 	for (i = 0; i < btrace_num; i++) {
 		struct bfd_data data;
 
-		data.pc = (bfd_hostptr_t) btrace_res[i];
+		data.pc = (bfd_hostptr_t)(btrace_res[i] - start_offset);
 		data.found = FALSE;
 		bfd_map_over_sections(abfd, find_addr_sect, &data);
 
-- 
2.11.0




More information about the Hostap mailing list