aboutsummaryrefslogtreecommitdiff
path: root/gdb/nat/linux-btrace.c
diff options
context:
space:
mode:
authorMarkus Metzger <markus.t.metzger@intel.com>2015-01-29 10:43:05 +0100
committerMarkus Metzger <markus.t.metzger@intel.com>2015-03-03 12:47:41 +0100
commitd68e53f47932eb7c374df9b90faed7aca2eed9d7 (patch)
tree47015cbfe454f85ccfb6c95577800d86767712ad /gdb/nat/linux-btrace.c
parent986b66010c684a871f5606cb4f074d4e3d829e2f (diff)
downloadgdb-d68e53f47932eb7c374df9b90faed7aca2eed9d7.zip
gdb-d68e53f47932eb7c374df9b90faed7aca2eed9d7.tar.gz
gdb-d68e53f47932eb7c374df9b90faed7aca2eed9d7.tar.bz2
btrace: support 32-bit inferior on 64-bit host
The heuristic for filtering out kernel addressess in BTS trace checks the most significant bit in each address. This works fine for 32-bit and 64-bit mode. For 32-bit compatibility mode, i.e. a 32-bit inferior running on 64-bit host, we need to check bit 63 (or any bit bigger than 31), not bit 31. Use the machine field in struct utsname provided by a uname call to determine whether we are running on a 64-bit host. Thanks to Jan Kratochvil for reporting the issue. gdb/ * nat/linux-btrace.c: Include sys/utsname.h. (linux_determine_kernel_ptr_bits): New. (linux_enable_bts): Call linux_determine_kernel_ptr_bits. * x86-linux-nat.c (x86_linux_enable_btrace): Do not overwrite non-zero ptr_bits. gdbserver/ * linux-low.c (linux_low_enable_btrace): Do not overwrite non-zero ptr_bits.
Diffstat (limited to 'gdb/nat/linux-btrace.c')
-rw-r--r--gdb/nat/linux-btrace.c28
1 files changed, 27 insertions, 1 deletions
diff --git a/gdb/nat/linux-btrace.c b/gdb/nat/linux-btrace.c
index 3093a5c..e7aff5e 100644
--- a/gdb/nat/linux-btrace.c
+++ b/gdb/nat/linux-btrace.c
@@ -38,6 +38,7 @@
#include <sys/ptrace.h>
#include <sys/types.h>
#include <signal.h>
+#include <sys/utsname.h>
/* A branch trace record in perf_event. */
struct perf_event_bts
@@ -102,6 +103,31 @@ perf_event_new_data (const struct perf_event_buffer *pev)
return *pev->data_head != pev->last_head;
}
+/* Try to determine the size of a pointer in bits for the OS.
+
+ This is the same as the size of a pointer for the inferior process
+ except when a 32-bit inferior is running on a 64-bit OS. */
+
+static int
+linux_determine_kernel_ptr_bits (void)
+{
+ struct utsname utsn;
+ int errcode;
+
+ memset (&utsn, 0, sizeof (utsn));
+
+ errcode = uname (&utsn);
+ if (errcode < 0)
+ return 0;
+
+ /* We only need to handle the 64-bit host case, here. For 32-bit host,
+ the pointer size can be filled in later based on the inferior. */
+ if (strcmp (utsn.machine, "x86_64") == 0)
+ return 64;
+
+ return 0;
+}
+
/* Check whether an address is in the kernel. */
static inline int
@@ -434,7 +460,7 @@ linux_enable_bts (ptid_t ptid, const struct btrace_config_bts *conf)
tinfo = xzalloc (sizeof (*tinfo));
tinfo->ptid = ptid;
- tinfo->ptr_bits = 0;
+ tinfo->ptr_bits = linux_determine_kernel_ptr_bits ();
tinfo->conf.format = BTRACE_FORMAT_BTS;
bts = &tinfo->variant.bts;