From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 11164 invoked by alias); 22 Feb 2013 12:15:44 -0000 Mailing-List: contact archer-commits-help@sourceware.org; run by ezmlm Sender: Precedence: bulk List-Post: List-Help: List-Subscribe: Received: (qmail 11126 invoked by uid 9958); 22 Feb 2013 12:15:41 -0000 Date: Fri, 22 Feb 2013 12:15:00 -0000 Message-ID: <20130222121541.11111.qmail@sourceware.org> From: mmetzger@sourceware.org To: archer-commits@sourceware.org Subject: [SCM] archer-mmetzger-btrace: archer: update X-Git-Refname: refs/heads/archer-mmetzger-btrace X-Git-Reftype: branch X-Git-Oldrev: 25be2d9660d4357cf0d08c52fd96f8df29d389b0 X-Git-Newrev: 5dd7aa460b03c158b938fa76ff6c83927d597bd8 X-SW-Source: 2013-q1/txt/msg00057.txt.bz2 List-Id: The branch, archer-mmetzger-btrace has been updated via 5dd7aa460b03c158b938fa76ff6c83927d597bd8 (commit) from 25be2d9660d4357cf0d08c52fd96f8df29d389b0 (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email. - Log ----------------------------------------------------------------- commit 5dd7aa460b03c158b938fa76ff6c83927d597bd8 Author: Markus Metzger Date: Thu Feb 21 14:39:03 2013 +0100 archer: update Add kernel check before cpuid check. Incorporate feedback on command naming. Incorporate feedback on record renaming. Drop the "record list" command. Change-Id: Ife0675a1e30e91c1b28abbdc9b52f05ce6709caf Signed-off-by: Markus Metzger ----------------------------------------------------------------------- Summary of changes: gdb/amd64-linux-tdep.c | 3 +- gdb/arm-tdep.c | 5 +- gdb/btrace.h | 20 +- gdb/common/linux-btrace.c | 120 ++++++++++++- gdb/i386-tdep.c | 28 ++-- gdb/linux-record.c | 4 +- gdb/record-btrace.c | 429 +++++++++++++++++++++++++-------------------- gdb/record-full.c | 51 +++--- gdb/record.c | 325 ++++++++++++++-------------------- gdb/target.c | 47 ++---- gdb/target.h | 45 ++--- 11 files changed, 575 insertions(+), 502 deletions(-) First 500 lines of diff: diff --git a/gdb/amd64-linux-tdep.c b/gdb/amd64-linux-tdep.c index d07f948..88c291d 100644 --- a/gdb/amd64-linux-tdep.c +++ b/gdb/amd64-linux-tdep.c @@ -1204,8 +1204,7 @@ amd64_linux_syscall_record (struct regcache *regcache) amd64_linux_record_tdep.arg2, &addr); if (record_full_arch_list_add_mem - (addr, - amd64_linux_record_tdep.size_ulong)) + (addr, amd64_linux_record_tdep.size_ulong)) return -1; } goto record_regs; diff --git a/gdb/arm-tdep.c b/gdb/arm-tdep.c index 4dbaec7..7c91717 100644 --- a/gdb/arm-tdep.c +++ b/gdb/arm-tdep.c @@ -12607,8 +12607,7 @@ arm_process_record (struct gdbarch *gdbarch, struct regcache *regcache, for (no_of_rec = 0; no_of_rec < arm_record.reg_rec_count; no_of_rec++) { if (record_full_arch_list_add_reg - (arm_record.regcache , - arm_record.arm_regs[no_of_rec])) + (arm_record.regcache , arm_record.arm_regs[no_of_rec])) ret = -1; } } @@ -12619,7 +12618,7 @@ arm_process_record (struct gdbarch *gdbarch, struct regcache *regcache, { if (record_full_arch_list_add_mem ((CORE_ADDR)arm_record.arm_mems[no_of_rec].addr, - arm_record.arm_mems[no_of_rec].len)) + arm_record.arm_mems[no_of_rec].len)) ret = -1; } } diff --git a/gdb/btrace.h b/gdb/btrace.h index 61404e7..d56bfa4 100644 --- a/gdb/btrace.h +++ b/gdb/btrace.h @@ -31,17 +31,17 @@ struct thread_info; struct btrace_thread_info; -/* Branch trace iteration state for the "record disassemble" command. */ -struct btrace_disas_state +/* Branch trace iteration state for "record instruction-history". */ +struct btrace_insn_iterator { - /* The instruction index range [begin; end[ that has been disassembled last. - If end < begin, nothing has been disassembled, yet. */ + /* The instruction index range [begin; end[ that has been covered last time. + If end < begin, the branch trace has just been updated. */ unsigned int begin; unsigned int end; }; -/* Branch trace iteration state for the "record backtrace" command. */ -struct btrace_bt_state +/* Branch trace iteration state for "record function-call-history". */ +struct btrace_function_iterator { /* The instruction index range [begin; end[ that has been covered last time. If end < begin, the branch trace has just been updated. */ @@ -75,11 +75,11 @@ struct btrace_thread_info VEC_length() one after the tail */ int iterator; - /* The iteration state for "record disassemble". */ - struct btrace_disas_state disas; + /* The instruction history iterator. */ + struct btrace_insn_iterator insn_iterator; - /* The iteration state for "record backtrace". */ - struct btrace_bt_state bt; + /* The function call history iterator. */ + struct btrace_function_iterator call_iterator; }; /* Enable branch tracing for a thread. */ diff --git a/gdb/common/linux-btrace.c b/gdb/common/linux-btrace.c index 9db6730..dbb9000 100644 --- a/gdb/common/linux-btrace.c +++ b/gdb/common/linux-btrace.c @@ -38,6 +38,10 @@ #include #include #include +#include +#include +#include +#include #if defined(__GNUC__) # define memory_barrier() asm volatile ("" : : : "memory") @@ -242,11 +246,95 @@ perf_event_read_bts (struct btrace_target_info* tinfo, const uint8_t *begin, return btrace; } +/* Check whether the kernel supports branch tracing. */ + +static int +kernel_supports_btrace (void) +{ + struct perf_event_attr attr; + pid_t child, pid; + int status, file; + + errno = 0; + child = fork (); + switch (child) + { + case -1: + warning (_("test branch tracing: cannot fork: %s."), strerror (errno)); + return 0; + + case 0: + status = ptrace (PTRACE_TRACEME, 0, NULL, NULL); + if (status != 0) + { + warning (_("test branch tracing: cannot PTRACE_TRACEME: %s."), + strerror (errno)); + _exit (1); + } + + status = raise (SIGTRAP); + if (status != 0) + { + warning (_("test branch tracing: cannot raise SIGTRAP: %s."), + strerror (errno)); + _exit (1); + } + + _exit (1); + + default: + pid = waitpid (child, &status, 0); + if (pid != child) + { + warning (_("test branch tracing: bad pid %ld, error: %s."), + (long) pid, strerror (errno)); + return 0; + } + + if (!WIFSTOPPED (status)) + { + warning (_("test branch tracing: expected stop. status: %d."), + status); + return 0; + } + + memset (&attr, 0, sizeof (attr)); + + attr.type = PERF_TYPE_HARDWARE; + attr.config = PERF_COUNT_HW_BRANCH_INSTRUCTIONS; + attr.sample_period = 1; + attr.sample_type = PERF_SAMPLE_IP | PERF_SAMPLE_ADDR; + attr.exclude_kernel = 1; + attr.exclude_hv = 1; + attr.exclude_idle = 1; + + file = syscall (SYS_perf_event_open, &attr, child, -1, -1, 0); + if (file >= 0) + close (file); + + kill (child, SIGKILL); + ptrace (PTRACE_KILL, child, NULL, NULL); + + pid = waitpid (child, &status, 0); + if (pid != child) + { + warning (_("test branch tracing: bad pid %ld, error: %s."), + (long) pid, strerror (errno)); + if (!WIFSIGNALED (status)) + warning (_("test branch tracing: expected killed. status: %d."), + status); + } + + return (file >= 0); + } +} + /* Check whether an Intel cpu supports branch tracing. */ static int intel_supports_btrace (void) { +#if defined __i386__ || defined __x86_64__ unsigned int cpuid, model, family; __asm__ __volatile__ ("movl $1, %%eax;" @@ -283,12 +371,18 @@ intel_supports_btrace (void) } return 1; + +#else /* !defined __i386__ && !defined __x86_64__ */ + + return 0; + +#endif /* !defined __i386__ && !defined __x86_64__ */ } -/* See linux-btrace.h. */ +/* Check whether the cpu supports branch tracing. */ -int -linux_supports_btrace (void) +static int +cpu_supports_btrace (void) { #if defined __i386__ || defined __x86_64__ char vendor[13]; @@ -324,6 +418,26 @@ linux_supports_btrace (void) /* See linux-btrace.h. */ int +linux_supports_btrace (void) +{ + static int cached; + + if (cached == 0) + { + if (!kernel_supports_btrace ()) + cached = -1; + else if (!cpu_supports_btrace ()) + cached = -1; + else + cached = 1; + } + + return cached > 0; +} + +/* See linux-btrace.h. */ + +int linux_btrace_has_changed (struct btrace_target_info *tinfo) { volatile struct perf_event_mmap_page *header = perf_event_header (tinfo); diff --git a/gdb/i386-tdep.c b/gdb/i386-tdep.c index 7a87c42..61ccc3e 100644 --- a/gdb/i386-tdep.c +++ b/gdb/i386-tdep.c @@ -5152,8 +5152,8 @@ Do you want to stop the program?"), case 0xb6: case 0xb7: I386_RECORD_FULL_ARCH_LIST_ADD_REG ((ir.regmap[X86_RECORD_R8_REGNUM]) - ? ((opcode & 0x7) | ir.rex_b) - : ((opcode & 0x7) & 0x3)); + ? ((opcode & 0x7) | ir.rex_b) + : ((opcode & 0x7) & 0x3)); break; case 0xb8: /* mov R, Iv */ @@ -5726,7 +5726,8 @@ Do you want to stop the program?"), case 0xdf: if (0xe0 == ir.modrm) { - if (record_full_arch_list_add_reg (ir.regcache, I386_EAX_REGNUM)) + if (record_full_arch_list_add_reg (ir.regcache, + I386_EAX_REGNUM)) return -1; } else if ((0x0f == ir.modrm >> 4) || (0x0e == ir.modrm >> 4)) @@ -5939,7 +5940,7 @@ Do you want to stop the program?"), return -1; if (ir.mod == 3) I386_RECORD_FULL_ARCH_LIST_ADD_REG (ir.rex_b ? (ir.rm | ir.rex_b) - : (ir.rm & 0x3)); + : (ir.rm & 0x3)); else { if (i386_record_lea_modrm (&ir)) @@ -6490,7 +6491,7 @@ Do you want to stop the program?"), if (ir.mod == 3 || ir.regmap[X86_RECORD_R8_REGNUM]) { I386_RECORD_FULL_ARCH_LIST_ADD_REG (ir.regmap[X86_RECORD_R8_REGNUM] - ? (ir.reg | rex_r) : ir.rm); + ? (ir.reg | rex_r) : ir.rm); } else { @@ -6683,7 +6684,8 @@ no_support_3dnow_data: record_full_arch_list_add_reg (ir.regcache, i); if (i386_mxcsr_regnum_p (gdbarch, I387_MXCSR_REGNUM(tdep))) - record_full_arch_list_add_reg (ir.regcache, I387_MXCSR_REGNUM(tdep)); + record_full_arch_list_add_reg (ir.regcache, + I387_MXCSR_REGNUM(tdep)); for (i = I387_ST0_REGNUM (tdep); i386_fp_regnum_p (gdbarch, i); i++) @@ -7077,7 +7079,7 @@ reswitch_prefix_add: if (!i386_xmm_regnum_p (gdbarch, I387_XMM0_REGNUM (tdep) + ir.reg)) goto no_support; record_full_arch_list_add_reg (ir.regcache, - I387_XMM0_REGNUM (tdep) + ir.reg); + I387_XMM0_REGNUM (tdep) + ir.reg); if ((opcode & 0xfffffffc) == 0x660f3a60) I386_RECORD_FULL_ARCH_LIST_ADD_REG (X86_RECORD_EFLAGS_REGNUM); break; @@ -7110,7 +7112,7 @@ reswitch_prefix_add: I387_XMM0_REGNUM (tdep) + ir.rm)) goto no_support; record_full_arch_list_add_reg (ir.regcache, - I387_XMM0_REGNUM (tdep) + ir.rm); + I387_XMM0_REGNUM (tdep) + ir.rm); } else { @@ -7265,7 +7267,7 @@ reswitch_prefix_add: if (!i386_mmx_regnum_p (gdbarch, I387_MM0_REGNUM (tdep) + ir.reg)) goto no_support; record_full_arch_list_add_reg (ir.regcache, - I387_MM0_REGNUM (tdep) + ir.reg); + I387_MM0_REGNUM (tdep) + ir.reg); break; case 0x0f71: /* psllw */ @@ -7276,7 +7278,7 @@ reswitch_prefix_add: if (!i386_mmx_regnum_p (gdbarch, I387_MM0_REGNUM (tdep) + ir.rm)) goto no_support; record_full_arch_list_add_reg (ir.regcache, - I387_MM0_REGNUM (tdep) + ir.rm); + I387_MM0_REGNUM (tdep) + ir.rm); break; case 0x660f71: /* psllw */ @@ -7288,7 +7290,7 @@ reswitch_prefix_add: if (!i386_xmm_regnum_p (gdbarch, I387_XMM0_REGNUM (tdep) + ir.rm)) goto no_support; record_full_arch_list_add_reg (ir.regcache, - I387_XMM0_REGNUM (tdep) + ir.rm); + I387_XMM0_REGNUM (tdep) + ir.rm); break; case 0x0f7e: /* movd */ @@ -7316,7 +7318,7 @@ reswitch_prefix_add: if (!i386_mmx_regnum_p (gdbarch, I387_MM0_REGNUM (tdep) + ir.rm)) goto no_support; record_full_arch_list_add_reg (ir.regcache, - I387_MM0_REGNUM (tdep) + ir.rm); + I387_MM0_REGNUM (tdep) + ir.rm); } else { @@ -7343,7 +7345,7 @@ reswitch_prefix_add: I387_XMM0_REGNUM (tdep) + ir.rm)) goto no_support; record_full_arch_list_add_reg (ir.regcache, - I387_XMM0_REGNUM (tdep) + ir.rm); + I387_XMM0_REGNUM (tdep) + ir.rm); } else { diff --git a/gdb/linux-record.c b/gdb/linux-record.c index ef32229..e4c1f96 100644 --- a/gdb/linux-record.c +++ b/gdb/linux-record.c @@ -1963,8 +1963,8 @@ Do you want to stop the program?"), regcache_raw_read_unsigned (regcache, tdep->arg3, &maxevents); if (record_full_arch_list_add_mem ((CORE_ADDR) tmpulongest, - maxevents * - tdep->size_epoll_event)) + (maxevents + * tdep->size_epoll_event))) return -1; } break; diff --git a/gdb/record-btrace.c b/gdb/record-btrace.c index 6725f16..68ccf19 100644 --- a/gdb/record-btrace.c +++ b/gdb/record-btrace.c @@ -39,18 +39,17 @@ static struct target_ops record_btrace_ops; /* A new thread observer enabling branch tracing for the new thread. */ static struct observer *record_btrace_thread_observer; -/* The record backtrace state. */ - -struct rec_bt_state +/* A recorded function segment. */ +struct btrace_function { - /* The last function symbol. */ + /* The function symbol. */ struct minimal_symbol *mfun; struct symbol *fun; - /* The name of the last function. */ + /* The name of the function. */ const char *function; - /* The last file name. */ + /* The name of the file in which the function is defined. */ const char *filename; /* The min and max line in the above file. */ @@ -58,19 +57,18 @@ struct rec_bt_state int end; }; -/* A vector of record backtrace states. */ -typedef struct rec_bt_state rec_bt_s; -DEF_VEC_O (rec_bt_s); - -/* Define debug output flags. */ +/* A vector of recorded function segments. */ +typedef struct btrace_function btr_fun_s; +DEF_VEC_O (btr_fun_s); +/* Debug output flags. */ enum record_btrace_debug_flag { /* Print an overview of record-btrace functions. */ debug_functions = 1 << 0, - /* Print details on "record backtrace". */ - debug_backtrace = 1 << 1 + /* Print details on "record function-call-history". */ + debug_call_history = 1 << 1 }; /* Print a record-btrace debug message. Use do ... while (0) to avoid @@ -86,29 +84,30 @@ enum record_btrace_debug_flag while (0) #define DEBUG_FUN(msg, args...) DEBUG (debug_functions, msg, ##args) -#define DEBUG_BT(msg, args...) DEBUG (debug_backtrace, "[bt] " msg, ##args) +#define DEBUG_CALL(msg, args...) \ + DEBUG (debug_call_history, "[hist: call] " msg, ##args) -/* Initialize the "record disassemble" iteration state. */ +/* Initialize the instruction iterator. */ static void -btrace_init_disas_state (struct btrace_thread_info *btinfo) +btrace_init_insn_iterator (struct btrace_thread_info *btinfo) { - DEBUG_FUN ("init disas iterator"); + DEBUG_FUN ("init insn iterator"); - btinfo->disas.begin = 1; - btinfo->disas.end = 0; + btinfo->insn_iterator.begin = 1; + btinfo->insn_iterator.end = 0; } -/* Initialize the "record backtrace" iteration state. */ +/* Initialize the function call iterator. */ static void -btrace_init_bt_state (struct btrace_thread_info *btinfo) +btrace_init_call_iterator (struct btrace_thread_info *btinfo) { - DEBUG_FUN ("init bt iterator"); + DEBUG_FUN ("init call iterator"); - btinfo->bt.begin = 1; - btinfo->bt.end = 0; + btinfo->call_iterator.begin = 1; + btinfo->call_iterator.end = 0; } /* Compute the instruction trace from the block trace. */ @@ -143,7 +142,7 @@ compute_itrace (VEC (btrace_block_s) *btrace) /* We should hit the end of the block. Warn if we went too far. */ if (block->end < ip) { - warning (_("Trace disassembly may be corrupted.")); + warning (_("Recorded trace may be corrupted.")); break; } @@ -159,7 +158,7 @@ compute_itrace (VEC (btrace_block_s) *btrace) /* Make sure we terminate if we fail to compute the size. */ if (size <= 0) { - warning (_("Trace disassembly may be incomplete.")); + warning (_("Recorded trace may be incomplete.")); break; } @@ -205,12 +204,12 @@ fetch_btrace (struct thread_info *tp) btinfo->itrace = compute_itrace (btinfo->btrace); - /* Re-initialize branch trace iterators. */ - btrace_init_disas_state (btinfo); - btrace_init_bt_state (btinfo); + /* Initialize branch trace iterators. */ + btrace_init_insn_iterator (btinfo); + btrace_init_call_iterator (btinfo); } -/* Update the branch trace for the current thread and return a pointer to it's +/* Update the branch trace for the current thread and return a pointer to its hooks/post-receive -- Repository for Project Archer.