trace: Look up start to cope with ASLR
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@sipsolutions.net>
This commit is contained in:
parent
069daec4ee
commit
5118319831
1 changed files with 34 additions and 3 deletions
|
@ -6,6 +6,10 @@
|
||||||
* See README for more details.
|
* See README for more details.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#ifdef WPA_TRACE_BFD
|
||||||
|
#define _GNU_SOURCE
|
||||||
|
#include <link.h>
|
||||||
|
#endif /* WPA_TRACE_BCD */
|
||||||
#include "includes.h"
|
#include "includes.h"
|
||||||
|
|
||||||
#include "common.h"
|
#include "common.h"
|
||||||
|
@ -25,6 +29,28 @@ static struct dl_list active_references =
|
||||||
static char *prg_fname = NULL;
|
static char *prg_fname = NULL;
|
||||||
static bfd *cached_abfd = NULL;
|
static bfd *cached_abfd = NULL;
|
||||||
static asymbol **syms = 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)
|
static void get_prg_fname(void)
|
||||||
{
|
{
|
||||||
|
@ -160,7 +186,7 @@ static void wpa_trace_bfd_addr(void *pc)
|
||||||
if (abfd == NULL)
|
if (abfd == NULL)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
data.pc = (bfd_hostptr_t) pc;
|
data.pc = (bfd_hostptr_t) (pc - start_offset);
|
||||||
data.found = FALSE;
|
data.found = FALSE;
|
||||||
bfd_map_over_sections(abfd, find_addr_sect, &data);
|
bfd_map_over_sections(abfd, find_addr_sect, &data);
|
||||||
|
|
||||||
|
@ -201,7 +227,7 @@ static const char * wpa_trace_bfd_addr2func(void *pc)
|
||||||
if (abfd == NULL)
|
if (abfd == NULL)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
data.pc = (bfd_hostptr_t) pc;
|
data.pc = (bfd_hostptr_t) (pc - start_offset);
|
||||||
data.found = FALSE;
|
data.found = FALSE;
|
||||||
bfd_map_over_sections(abfd, find_addr_sect, &data);
|
bfd_map_over_sections(abfd, find_addr_sect, &data);
|
||||||
|
|
||||||
|
@ -233,6 +259,11 @@ static void wpa_trace_bfd_init(void)
|
||||||
wpa_printf(MSG_INFO, "Failed to read symbols");
|
wpa_printf(MSG_INFO, "Failed to read symbols");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!start_offset_looked_up) {
|
||||||
|
dl_iterate_phdr(callback, NULL);
|
||||||
|
start_offset_looked_up = 1;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -268,7 +299,7 @@ size_t wpa_trace_calling_func(const char *buf[], size_t len)
|
||||||
for (i = 0; i < btrace_num; i++) {
|
for (i = 0; i < btrace_num; i++) {
|
||||||
struct bfd_data data;
|
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;
|
data.found = FALSE;
|
||||||
bfd_map_over_sections(abfd, find_addr_sect, &data);
|
bfd_map_over_sections(abfd, find_addr_sect, &data);
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue