X-Git-Url: http://git.efficios.com/?a=blobdiff_plain;f=gdb%2Farm-tdep.c;h=88ed391729813dc4ef8e4dccb6698fa798e0de08;hb=d7e747318f4d04af033f16325f9b6d74f67079ec;hp=ad6983402cb42188924446209013ae1636895287;hpb=c55978a67a2e23999c3359a13bb807b665fcb33e;p=deliverable%2Fbinutils-gdb.git diff --git a/gdb/arm-tdep.c b/gdb/arm-tdep.c index ad6983402c..88ed391729 100644 --- a/gdb/arm-tdep.c +++ b/gdb/arm-tdep.c @@ -1,6 +1,6 @@ /* Common target dependent code for GDB on ARM systems. - Copyright (C) 1988-2016 Free Software Foundation, Inc. + Copyright (C) 1988-2017 Free Software Foundation, Inc. This file is part of GDB. @@ -27,6 +27,7 @@ #include "gdbcmd.h" #include "gdbcore.h" #include "dis-asm.h" /* For register styles. */ +#include "disasm.h" #include "regcache.h" #include "reggroups.h" #include "doublest.h" @@ -58,14 +59,15 @@ #include "record.h" #include "record-full.h" +#include -#include "features/arm-with-m.c" -#include "features/arm-with-m-fpa-layout.c" -#include "features/arm-with-m-vfp-d16.c" -#include "features/arm-with-iwmmxt.c" -#include "features/arm-with-vfpv2.c" -#include "features/arm-with-vfpv3.c" -#include "features/arm-with-neon.c" +#include "features/arm/arm-with-m.c" +#include "features/arm/arm-with-m-fpa-layout.c" +#include "features/arm/arm-with-m-vfp-d16.c" +#include "features/arm/arm-with-iwmmxt.c" +#include "features/arm/arm-with-vfpv2.c" +#include "features/arm/arm-with-vfpv3.c" +#include "features/arm/arm-with-neon.c" static int arm_debug; @@ -143,13 +145,6 @@ static const char *const arm_mode_strings[] = static const char *arm_fallback_mode_string = "auto"; static const char *arm_force_mode_string = "auto"; -/* Internal override of the execution mode. -1 means no override, - 0 means override to ARM mode, 1 means override to Thumb mode. - The effect is the same as if arm_force_mode has been set by the - user (except the internal override has precedence over a user's - arm_force_mode override). */ -static int arm_override_mode = -1; - /* Number of different reg name sets (options). */ static int num_disassembly_options; @@ -422,10 +417,6 @@ arm_pc_is_thumb (struct gdbarch *gdbarch, CORE_ADDR memaddr) if (IS_THUMB_ADDR (memaddr)) return 1; - /* Respect internal mode override if active. */ - if (arm_override_mode != -1) - return arm_override_mode; - /* If the user wants to override the symbol table, let him. */ if (strcmp (arm_force_mode_string, "arm") == 0) return 0; @@ -464,6 +455,62 @@ arm_pc_is_thumb (struct gdbarch *gdbarch, CORE_ADDR memaddr) return 0; } +/* Determine if the address specified equals any of these magic return + values, called EXC_RETURN, defined by the ARM v6-M and v7-M + architectures. + + From ARMv6-M Reference Manual B1.5.8 + Table B1-5 Exception return behavior + + EXC_RETURN Return To Return Stack + 0xFFFFFFF1 Handler mode Main + 0xFFFFFFF9 Thread mode Main + 0xFFFFFFFD Thread mode Process + + From ARMv7-M Reference Manual B1.5.8 + Table B1-8 EXC_RETURN definition of exception return behavior, no FP + + EXC_RETURN Return To Return Stack + 0xFFFFFFF1 Handler mode Main + 0xFFFFFFF9 Thread mode Main + 0xFFFFFFFD Thread mode Process + + Table B1-9 EXC_RETURN definition of exception return behavior, with + FP + + EXC_RETURN Return To Return Stack Frame Type + 0xFFFFFFE1 Handler mode Main Extended + 0xFFFFFFE9 Thread mode Main Extended + 0xFFFFFFED Thread mode Process Extended + 0xFFFFFFF1 Handler mode Main Basic + 0xFFFFFFF9 Thread mode Main Basic + 0xFFFFFFFD Thread mode Process Basic + + For more details see "B1.5.8 Exception return behavior" + in both ARMv6-M and ARMv7-M Architecture Reference Manuals. */ + +static int +arm_m_addr_is_magic (CORE_ADDR addr) +{ + switch (addr) + { + /* Values from Tables in B1.5.8 the EXC_RETURN definitions of + the exception return behavior. */ + case 0xffffffe1: + case 0xffffffe9: + case 0xffffffed: + case 0xfffffff1: + case 0xfffffff9: + case 0xfffffffd: + /* Address is magic. */ + return 1; + + default: + /* Address is not magic. */ + return 0; + } +} + /* Remove useless bits from addresses in a running program. */ static CORE_ADDR arm_addr_bits_remove (struct gdbarch *gdbarch, CORE_ADDR val) @@ -471,7 +518,7 @@ arm_addr_bits_remove (struct gdbarch *gdbarch, CORE_ADDR val) /* On M-profile devices, do not strip the low bit from EXC_RETURN (the magic exception return address). */ if (gdbarch_tdep (gdbarch)->is_m - && (val & 0xfffffff0) == 0xfffffff0) + && arm_m_addr_is_magic (val)) return val; if (arm_apcs_32) @@ -524,9 +571,9 @@ skip_prologue_function (struct gdbarch *gdbarch, CORE_ADDR pc, int is_thumb) implementation (this is hand-written ARM assembler in glibc). */ if (!is_thumb - && read_memory_unsigned_integer (pc, 4, byte_order_for_code) + && read_code_unsigned_integer (pc, 4, byte_order_for_code) == 0xe3e00a0f /* mov r0, #0xffff0fff */ - && read_memory_unsigned_integer (pc + 4, 4, byte_order_for_code) + && read_code_unsigned_integer (pc + 4, 4, byte_order_for_code) == 0xe240f01f) /* sub pc, r0, #31 */ return 1; } @@ -613,7 +660,7 @@ thumb_analyze_prologue (struct gdbarch *gdbarch, { unsigned short insn; - insn = read_memory_unsigned_integer (start, 2, byte_order_for_code); + insn = read_code_unsigned_integer (start, 2, byte_order_for_code); if ((insn & 0xfe00) == 0xb400) /* push { rlist } */ { @@ -744,8 +791,8 @@ thumb_analyze_prologue (struct gdbarch *gdbarch, { unsigned short inst2; - inst2 = read_memory_unsigned_integer (start + 2, 2, - byte_order_for_code); + inst2 = read_code_unsigned_integer (start + 2, 2, + byte_order_for_code); if ((insn & 0xf800) == 0xf000 && (inst2 & 0xe800) == 0xe800) { @@ -1088,7 +1135,7 @@ arm_analyze_load_stack_chk_guard(CORE_ADDR pc, struct gdbarch *gdbarch, if (is_thumb) { unsigned short insn1 - = read_memory_unsigned_integer (pc, 2, byte_order_for_code); + = read_code_unsigned_integer (pc, 2, byte_order_for_code); if ((insn1 & 0xf800) == 0x4800) /* ldr Rd, #immed */ { @@ -1101,14 +1148,14 @@ arm_analyze_load_stack_chk_guard(CORE_ADDR pc, struct gdbarch *gdbarch, else if ((insn1 & 0xfbf0) == 0xf240) /* movw Rd, #const */ { unsigned short insn2 - = read_memory_unsigned_integer (pc + 2, 2, byte_order_for_code); + = read_code_unsigned_integer (pc + 2, 2, byte_order_for_code); low = EXTRACT_MOVW_MOVT_IMM_T (insn1, insn2); insn1 - = read_memory_unsigned_integer (pc + 4, 2, byte_order_for_code); + = read_code_unsigned_integer (pc + 4, 2, byte_order_for_code); insn2 - = read_memory_unsigned_integer (pc + 6, 2, byte_order_for_code); + = read_code_unsigned_integer (pc + 6, 2, byte_order_for_code); /* movt Rd, #const */ if ((insn1 & 0xfbc0) == 0xf2c0) @@ -1123,7 +1170,7 @@ arm_analyze_load_stack_chk_guard(CORE_ADDR pc, struct gdbarch *gdbarch, else { unsigned int insn - = read_memory_unsigned_integer (pc, 4, byte_order_for_code); + = read_code_unsigned_integer (pc, 4, byte_order_for_code); if ((insn & 0x0e5f0000) == 0x041f0000) /* ldr Rd, [PC, #immed] */ { @@ -1139,7 +1186,7 @@ arm_analyze_load_stack_chk_guard(CORE_ADDR pc, struct gdbarch *gdbarch, low = EXTRACT_MOVW_MOVT_IMM_A (insn); insn - = read_memory_unsigned_integer (pc + 4, 4, byte_order_for_code); + = read_code_unsigned_integer (pc + 4, 4, byte_order_for_code); if ((insn & 0x0ff00000) == 0x03400000) /* movt Rd, #const */ { @@ -1211,7 +1258,7 @@ arm_skip_stack_protector(CORE_ADDR pc, struct gdbarch *gdbarch) { unsigned int destreg; unsigned short insn - = read_memory_unsigned_integer (pc + offset, 2, byte_order_for_code); + = read_code_unsigned_integer (pc + offset, 2, byte_order_for_code); /* Step 2: ldr Rd, [Rn, #immed], encoding T1. */ if ((insn & 0xf800) != 0x6800) @@ -1220,8 +1267,8 @@ arm_skip_stack_protector(CORE_ADDR pc, struct gdbarch *gdbarch) return pc; destreg = bits (insn, 0, 2); - insn = read_memory_unsigned_integer (pc + offset + 2, 2, - byte_order_for_code); + insn = read_code_unsigned_integer (pc + offset + 2, 2, + byte_order_for_code); /* Step 3: str Rd, [Rn, #immed], encoding T1. */ if ((insn & 0xf800) != 0x6000) return pc; @@ -1232,7 +1279,7 @@ arm_skip_stack_protector(CORE_ADDR pc, struct gdbarch *gdbarch) { unsigned int destreg; unsigned int insn - = read_memory_unsigned_integer (pc + offset, 4, byte_order_for_code); + = read_code_unsigned_integer (pc + offset, 4, byte_order_for_code); /* Step 2: ldr Rd, [Rn, #immed], encoding A1. */ if ((insn & 0x0e500000) != 0x04100000) @@ -1241,7 +1288,7 @@ arm_skip_stack_protector(CORE_ADDR pc, struct gdbarch *gdbarch) return pc; destreg = bits (insn, 12, 15); /* Step 3: str Rd, [Rn, #immed], encoding A1. */ - insn = read_memory_unsigned_integer (pc + offset + 4, + insn = read_code_unsigned_integer (pc + offset + 4, 4, byte_order_for_code); if ((insn & 0x0e500000) != 0x04000000) return pc; @@ -1393,7 +1440,7 @@ thumb_scan_prologue (struct gdbarch *gdbarch, CORE_ADDR prev_pc, function is. */ return; - prologue_end = min (prologue_end, prev_pc); + prologue_end = std::min (prologue_end, prev_pc); thumb_analyze_prologue (gdbarch, prologue_start, prologue_end, cache); } @@ -1465,7 +1512,7 @@ arm_analyze_prologue (struct gdbarch *gdbarch, current_pc += 4) { unsigned int insn - = read_memory_unsigned_integer (current_pc, 4, byte_order_for_code); + = read_code_unsigned_integer (current_pc, 4, byte_order_for_code); if (insn == 0xe1a0c00d) /* mov ip, sp */ { @@ -1761,10 +1808,11 @@ arm_scan_prologue (struct frame_info *this_frame, the callee (or at the present moment if this is the innermost frame). The value stored there should be the address of the stmfd + 8. */ CORE_ADDR frame_loc; - LONGEST return_value; + ULONGEST return_value; frame_loc = get_frame_register_unsigned (this_frame, ARM_FP_REGNUM); - if (!safe_read_memory_integer (frame_loc, 4, byte_order, &return_value)) + if (!safe_read_memory_unsigned_integer (frame_loc, 4, byte_order, + &return_value)) return; else { @@ -2613,19 +2661,19 @@ arm_exidx_unwind_sniffer (const struct frame_unwind *self, ensure this, so that e.g. pthread cancellation works. */ if (arm_frame_is_thumb (this_frame)) { - LONGEST insn; + ULONGEST insn; - if (safe_read_memory_integer (get_frame_pc (this_frame) - 2, 2, - byte_order_for_code, &insn) + if (safe_read_memory_unsigned_integer (get_frame_pc (this_frame) - 2, + 2, byte_order_for_code, &insn) && (insn & 0xff00) == 0xdf00 /* svc */) exc_valid = 1; } else { - LONGEST insn; + ULONGEST insn; - if (safe_read_memory_integer (get_frame_pc (this_frame) - 4, 4, - byte_order_for_code, &insn) + if (safe_read_memory_unsigned_integer (get_frame_pc (this_frame) - 4, + 4, byte_order_for_code, &insn) && (insn & 0x0f000000) == 0x0f000000 /* svc */) exc_valid = 1; } @@ -2669,6 +2717,108 @@ struct frame_unwind arm_exidx_unwind = { arm_exidx_unwind_sniffer }; +static struct arm_prologue_cache * +arm_make_epilogue_frame_cache (struct frame_info *this_frame) +{ + struct arm_prologue_cache *cache; + int reg; + + cache = FRAME_OBSTACK_ZALLOC (struct arm_prologue_cache); + cache->saved_regs = trad_frame_alloc_saved_regs (this_frame); + + /* Still rely on the offset calculated from prologue. */ + arm_scan_prologue (this_frame, cache); + + /* Since we are in epilogue, the SP has been restored. */ + cache->prev_sp = get_frame_register_unsigned (this_frame, ARM_SP_REGNUM); + + /* Calculate actual addresses of saved registers using offsets + determined by arm_scan_prologue. */ + for (reg = 0; reg < gdbarch_num_regs (get_frame_arch (this_frame)); reg++) + if (trad_frame_addr_p (cache->saved_regs, reg)) + cache->saved_regs[reg].addr += cache->prev_sp; + + return cache; +} + +/* Implementation of function hook 'this_id' in + 'struct frame_uwnind' for epilogue unwinder. */ + +static void +arm_epilogue_frame_this_id (struct frame_info *this_frame, + void **this_cache, + struct frame_id *this_id) +{ + struct arm_prologue_cache *cache; + CORE_ADDR pc, func; + + if (*this_cache == NULL) + *this_cache = arm_make_epilogue_frame_cache (this_frame); + cache = (struct arm_prologue_cache *) *this_cache; + + /* Use function start address as part of the frame ID. If we cannot + identify the start address (due to missing symbol information), + fall back to just using the current PC. */ + pc = get_frame_pc (this_frame); + func = get_frame_func (this_frame); + if (func == 0) + func = pc; + + (*this_id) = frame_id_build (cache->prev_sp, pc); +} + +/* Implementation of function hook 'prev_register' in + 'struct frame_uwnind' for epilogue unwinder. */ + +static struct value * +arm_epilogue_frame_prev_register (struct frame_info *this_frame, + void **this_cache, int regnum) +{ + if (*this_cache == NULL) + *this_cache = arm_make_epilogue_frame_cache (this_frame); + + return arm_prologue_prev_register (this_frame, this_cache, regnum); +} + +static int arm_stack_frame_destroyed_p_1 (struct gdbarch *gdbarch, + CORE_ADDR pc); +static int thumb_stack_frame_destroyed_p (struct gdbarch *gdbarch, + CORE_ADDR pc); + +/* Implementation of function hook 'sniffer' in + 'struct frame_uwnind' for epilogue unwinder. */ + +static int +arm_epilogue_frame_sniffer (const struct frame_unwind *self, + struct frame_info *this_frame, + void **this_prologue_cache) +{ + if (frame_relative_level (this_frame) == 0) + { + struct gdbarch *gdbarch = get_frame_arch (this_frame); + CORE_ADDR pc = get_frame_pc (this_frame); + + if (arm_frame_is_thumb (this_frame)) + return thumb_stack_frame_destroyed_p (gdbarch, pc); + else + return arm_stack_frame_destroyed_p_1 (gdbarch, pc); + } + else + return 0; +} + +/* Frame unwinder from epilogue. */ + +static const struct frame_unwind arm_epilogue_frame_unwind = +{ + NORMAL_FRAME, + default_frame_unwind_stop_reason, + arm_epilogue_frame_this_id, + arm_epilogue_frame_prev_register, + NULL, + arm_epilogue_frame_sniffer, +}; + /* Recognize GCC's trampoline for thumb call-indirect. If we are in a trampoline, return the target PC. Otherwise return 0. @@ -2888,14 +3038,8 @@ arm_m_exception_unwind_sniffer (const struct frame_unwind *self, /* No need to check is_m; this sniffer is only registered for M-profile architectures. */ - /* Exception frames return to one of these magic PCs. Other values - are not defined as of v7-M. See details in "B1.5.8 Exception - return behavior" in "ARMv7-M Architecture Reference Manual". */ - if (this_pc == 0xfffffff1 || this_pc == 0xfffffff9 - || this_pc == 0xfffffffd) - return 1; - - return 0; + /* Check if exception frame returns to a magic PC value. */ + return arm_m_addr_is_magic (this_pc); } /* Frame unwinder for M-profile exceptions. */ @@ -3124,19 +3268,14 @@ thumb_stack_frame_destroyed_p (struct gdbarch *gdbarch, CORE_ADDR pc) return found_stack_adjust; } -/* Implement the stack_frame_destroyed_p gdbarch method. */ - static int -arm_stack_frame_destroyed_p (struct gdbarch *gdbarch, CORE_ADDR pc) +arm_stack_frame_destroyed_p_1 (struct gdbarch *gdbarch, CORE_ADDR pc) { enum bfd_endian byte_order_for_code = gdbarch_byte_order_for_code (gdbarch); unsigned int insn; int found_return; CORE_ADDR func_start, func_end; - if (arm_pc_is_thumb (gdbarch, pc)) - return thumb_stack_frame_destroyed_p (gdbarch, pc); - if (!find_pc_partial_function (pc, NULL, &func_start, &func_end)) return 0; @@ -3178,6 +3317,16 @@ arm_stack_frame_destroyed_p (struct gdbarch *gdbarch, CORE_ADDR pc) return 0; } +/* Implement the stack_frame_destroyed_p gdbarch method. */ + +static int +arm_stack_frame_destroyed_p (struct gdbarch *gdbarch, CORE_ADDR pc) +{ + if (arm_pc_is_thumb (gdbarch, pc)) + return thumb_stack_frame_destroyed_p (gdbarch, pc); + else + return arm_stack_frame_destroyed_p_1 (gdbarch, pc); +} /* When arguments must be pushed onto the stack, they go on in reverse order. The code below implements a FILO (stack) to do this. */ @@ -3447,8 +3596,11 @@ arm_vfp_cprc_sub_candidate (struct type *t, int i; for (i = 0; i < TYPE_NFIELDS (t); i++) { - int sub_count = arm_vfp_cprc_sub_candidate (TYPE_FIELD_TYPE (t, i), - base_type); + int sub_count = 0; + + if (!field_is_static (&TYPE_FIELD (t, i))) + sub_count = arm_vfp_cprc_sub_candidate (TYPE_FIELD_TYPE (t, i), + base_type); if (sub_count == -1) return -1; count += sub_count; @@ -4085,26 +4237,6 @@ convert_to_extended (const struct floatformat *fmt, void *dbl, const void *ptr, &d, dbl); } -/* Like insert_single_step_breakpoint, but make sure we use a breakpoint - of the appropriate mode (as encoded in the PC value), even if this - differs from what would be expected according to the symbol tables. */ - -void -arm_insert_single_step_breakpoint (struct gdbarch *gdbarch, - struct address_space *aspace, - CORE_ADDR pc) -{ - struct cleanup *old_chain - = make_cleanup_restore_integer (&arm_override_mode); - - arm_override_mode = IS_THUMB_ADDR (pc); - pc = gdbarch_addr_bits_remove (gdbarch, pc); - - insert_single_step_breakpoint (gdbarch, aspace, pc); - - do_cleanups (old_chain); -} - /* Given BUF, which is OLD_LEN bytes ending at ENDADDR, expand the buffer to be NEW_LEN bytes ending at ENDADDR. Return NULL if an error occurs. BUF is freed. */ @@ -4119,7 +4251,7 @@ extend_buffer_earlier (gdb_byte *buf, CORE_ADDR endaddr, new_buf = (gdb_byte *) xmalloc (new_len); memcpy (new_buf + bytes_to_read, buf, old_len); xfree (buf); - if (target_read_memory (endaddr - new_len, new_buf, bytes_to_read) != 0) + if (target_read_code (endaddr - new_len, new_buf, bytes_to_read) != 0) { xfree (new_buf); return NULL; @@ -4177,13 +4309,13 @@ arm_adjust_breakpoint_address (struct gdbarch *gdbarch, CORE_ADDR bpaddr) footwork to distinguish a real IT instruction from the second half of a 32-bit instruction, but there is no need for that if there's no candidate. */ - buf_len = min (bpaddr - boundary, MAX_IT_BLOCK_PREFIX); + buf_len = std::min (bpaddr - boundary, (CORE_ADDR) MAX_IT_BLOCK_PREFIX); if (buf_len == 0) /* No room for an IT instruction. */ return bpaddr; buf = (gdb_byte *) xmalloc (buf_len); - if (target_read_memory (bpaddr - buf_len, buf, buf_len) != 0) + if (target_read_code (bpaddr - buf_len, buf, buf_len) != 0) return bpaddr; any = 0; for (i = 0; i < buf_len; i += 2) @@ -6156,12 +6288,10 @@ arm_get_next_pcs_is_thumb (struct arm_get_next_pcs *self) single-step support. We find the target of the coming instructions and breakpoint them. */ -int -arm_software_single_step (struct frame_info *frame) +VEC (CORE_ADDR) * +arm_software_single_step (struct regcache *regcache) { - struct regcache *regcache = get_current_regcache (); struct gdbarch *gdbarch = get_regcache_arch (regcache); - struct address_space *aspace = get_regcache_aspace (regcache); struct arm_get_next_pcs next_pcs_ctx; CORE_ADDR pc; int i; @@ -6178,11 +6308,14 @@ arm_software_single_step (struct frame_info *frame) next_pcs = arm_get_next_pcs (&next_pcs_ctx); for (i = 0; VEC_iterate (CORE_ADDR, next_pcs, i, pc); i++) - arm_insert_single_step_breakpoint (gdbarch, aspace, pc); + { + pc = gdbarch_addr_bits_remove (gdbarch, pc); + VEC_replace (CORE_ADDR, next_pcs, i, pc); + } - do_cleanups (old_chain); + discard_cleanups (old_chain); - return 1; + return next_pcs; } /* Cleanup/copy SVC (SWI) instructions. These two functions are overridden @@ -7607,7 +7740,9 @@ arm_displaced_step_fixup (struct gdbarch *gdbarch, static int gdb_print_insn_arm (bfd_vma memaddr, disassemble_info *info) { - struct gdbarch *gdbarch = (struct gdbarch *) info->application_data; + gdb_disassembler *di + = static_cast(info->application_data); + struct gdbarch *gdbarch = di->arch (); if (arm_pc_is_thumb (gdbarch, memaddr)) { @@ -7685,16 +7820,10 @@ static const gdb_byte arm_default_arm_be_breakpoint[] = ARM_BE_BREAKPOINT; static const gdb_byte arm_default_thumb_le_breakpoint[] = THUMB_LE_BREAKPOINT; static const gdb_byte arm_default_thumb_be_breakpoint[] = THUMB_BE_BREAKPOINT; -/* Determine the type and size of breakpoint to insert at PCPTR. Uses - the program counter value to determine whether a 16-bit or 32-bit - breakpoint should be used. It returns a pointer to a string of - bytes that encode a breakpoint instruction, stores the length of - the string to *lenptr, and adjusts the program counter (if - necessary) to point to the actual memory location where the - breakpoint should be inserted. */ +/* Implement the breakpoint_kind_from_pc gdbarch method. */ -static const unsigned char * -arm_breakpoint_from_pc (struct gdbarch *gdbarch, CORE_ADDR *pcptr, int *lenptr) +static int +arm_breakpoint_kind_from_pc (struct gdbarch *gdbarch, CORE_ADDR *pcptr) { struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch); enum bfd_endian byte_order_for_code = gdbarch_byte_order_for_code (gdbarch); @@ -7708,38 +7837,98 @@ arm_breakpoint_from_pc (struct gdbarch *gdbarch, CORE_ADDR *pcptr, int *lenptr) if (tdep->thumb2_breakpoint != NULL) { gdb_byte buf[2]; + if (target_read_memory (*pcptr, buf, 2) == 0) { unsigned short inst1; + inst1 = extract_unsigned_integer (buf, 2, byte_order_for_code); if (thumb_insn_size (inst1) == 4) - { - *lenptr = tdep->thumb2_breakpoint_size; - return tdep->thumb2_breakpoint; - } + return ARM_BP_KIND_THUMB2; } } - *lenptr = tdep->thumb_breakpoint_size; - return tdep->thumb_breakpoint; + return ARM_BP_KIND_THUMB; } else + return ARM_BP_KIND_ARM; + +} + +/* Implement the sw_breakpoint_from_kind gdbarch method. */ + +static const gdb_byte * +arm_sw_breakpoint_from_kind (struct gdbarch *gdbarch, int kind, int *size) +{ + struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch); + + switch (kind) { - *lenptr = tdep->arm_breakpoint_size; + case ARM_BP_KIND_ARM: + *size = tdep->arm_breakpoint_size; return tdep->arm_breakpoint; + case ARM_BP_KIND_THUMB: + *size = tdep->thumb_breakpoint_size; + return tdep->thumb_breakpoint; + case ARM_BP_KIND_THUMB2: + *size = tdep->thumb2_breakpoint_size; + return tdep->thumb2_breakpoint; + default: + gdb_assert_not_reached ("unexpected arm breakpoint kind"); } } -static void -arm_remote_breakpoint_from_pc (struct gdbarch *gdbarch, CORE_ADDR *pcptr, - int *kindptr) +/* Implement the breakpoint_kind_from_current_state gdbarch method. */ + +static int +arm_breakpoint_kind_from_current_state (struct gdbarch *gdbarch, + struct regcache *regcache, + CORE_ADDR *pcptr) { - arm_breakpoint_from_pc (gdbarch, pcptr, kindptr); + gdb_byte buf[4]; + + /* Check the memory pointed by PC is readable. */ + if (target_read_memory (regcache_read_pc (regcache), buf, 4) == 0) + { + struct arm_get_next_pcs next_pcs_ctx; + CORE_ADDR pc; + int i; + VEC (CORE_ADDR) *next_pcs = NULL; + struct cleanup *old_chain + = make_cleanup (VEC_cleanup (CORE_ADDR), &next_pcs); + + arm_get_next_pcs_ctor (&next_pcs_ctx, + &arm_get_next_pcs_ops, + gdbarch_byte_order (gdbarch), + gdbarch_byte_order_for_code (gdbarch), + 0, + regcache); + + next_pcs = arm_get_next_pcs (&next_pcs_ctx); + + /* If MEMADDR is the next instruction of current pc, do the + software single step computation, and get the thumb mode by + the destination address. */ + for (i = 0; VEC_iterate (CORE_ADDR, next_pcs, i, pc); i++) + { + if (UNMAKE_THUMB_ADDR (pc) == *pcptr) + { + do_cleanups (old_chain); - if (arm_pc_is_thumb (gdbarch, *pcptr) && *kindptr == 4) - /* The documented magic value for a 32-bit Thumb-2 breakpoint, so - that this is not confused with a 32-bit ARM breakpoint. */ - *kindptr = 3; + if (IS_THUMB_ADDR (pc)) + { + *pcptr = MAKE_THUMB_ADDR (*pcptr); + return arm_breakpoint_kind_from_pc (gdbarch, pcptr); + } + else + return ARM_BP_KIND_ARM; + } + } + + do_cleanups (old_chain); + } + + return arm_breakpoint_kind_from_pc (gdbarch, pcptr); } /* Extract from an array REGBUF containing the (raw) register state a @@ -8431,7 +8620,9 @@ coff_sym_is_thumb (int val) static void arm_elf_make_msymbol_special(asymbol *sym, struct minimal_symbol *msym) { - if (ARM_SYM_BRANCH_TYPE (&((elf_symbol_type *)sym)->internal_elf_sym) + elf_symbol_type *elfsym = (elf_symbol_type *) sym; + + if (ARM_GET_SYM_BRANCH_TYPE (elfsym->internal_elf_sym.st_target_internal) == ST_BRANCH_TO_THUMB) MSYMBOL_SET_SPECIAL (msym); } @@ -8753,6 +8944,22 @@ arm_register_g_packet_guesses (struct gdbarch *gdbarch) /* Otherwise we don't have a useful guess. */ } +/* Implement the code_of_frame_writable gdbarch method. */ + +static int +arm_code_of_frame_writable (struct gdbarch *gdbarch, struct frame_info *frame) +{ + if (gdbarch_tdep (gdbarch)->is_m + && get_frame_type (frame) == SIGTRAMP_FRAME) + { + /* M-profile exception frames return to some magic PCs, where + isn't writable at all. */ + return 0; + } + else + return 1; +} + /* Initialize the current architecture based on INFO. If possible, re-use an architecture from ARCHES, which is a list of @@ -8786,11 +8993,6 @@ arm_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches) switch (bfd_get_flavour (info.abfd)) { - case bfd_target_aout_flavour: - /* Assume it's an old APCS-style ABI. */ - arm_abi = ARM_ABI_APCS; - break; - case bfd_target_coff_flavour: /* Assume it's an old APCS-style ABI. */ /* XXX WinCE? */ @@ -9203,6 +9405,9 @@ arm_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches) set_gdbarch_push_dummy_call (gdbarch, arm_push_dummy_call); set_gdbarch_frame_align (gdbarch, arm_frame_align); + if (is_m) + set_gdbarch_code_of_frame_writable (gdbarch, arm_code_of_frame_writable); + set_gdbarch_write_pc (gdbarch, arm_write_pc); /* Frame handling. */ @@ -9228,9 +9433,10 @@ arm_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches) set_gdbarch_inner_than (gdbarch, core_addr_lessthan); /* Breakpoint manipulation. */ - set_gdbarch_breakpoint_from_pc (gdbarch, arm_breakpoint_from_pc); - set_gdbarch_remote_breakpoint_from_pc (gdbarch, - arm_remote_breakpoint_from_pc); + set_gdbarch_breakpoint_kind_from_pc (gdbarch, arm_breakpoint_kind_from_pc); + set_gdbarch_sw_breakpoint_from_kind (gdbarch, arm_sw_breakpoint_from_kind); + set_gdbarch_breakpoint_kind_from_current_state (gdbarch, + arm_breakpoint_kind_from_current_state); /* Information about registers, etc. */ set_gdbarch_sp_regnum (gdbarch, ARM_SP_REGNUM); @@ -9280,6 +9486,7 @@ arm_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches) frame_unwind_append_unwinder (gdbarch, &arm_stub_unwind); dwarf2_append_unwinders (gdbarch); frame_unwind_append_unwinder (gdbarch, &arm_exidx_unwind); + frame_unwind_append_unwinder (gdbarch, &arm_epilogue_frame_unwind); frame_unwind_append_unwinder (gdbarch, &arm_prologue_unwind); /* Now we have tuned the configuration, set a few final things, @@ -9369,13 +9576,11 @@ extern initialize_file_ftype _initialize_arm_tdep; /* -Wmissing-prototypes */ void _initialize_arm_tdep (void) { - struct ui_file *stb; long length; const char *setname; const char *setdesc; const char *const *regnames; int i; - static char *helptext; char regdesc[1024], *rdptr = regdesc; size_t rest = sizeof (regdesc); @@ -9441,19 +9646,16 @@ _initialize_arm_tdep (void) valid_disassembly_styles[num_disassembly_options] = NULL; /* Create the help text. */ - stb = mem_fileopen (); - fprintf_unfiltered (stb, "%s%s%s", - _("The valid values are:\n"), - regdesc, - _("The default is \"std\".")); - helptext = ui_file_xstrdup (stb, NULL); - ui_file_delete (stb); + std::string helptext = string_printf ("%s%s%s", + _("The valid values are:\n"), + regdesc, + _("The default is \"std\".")); add_setshow_enum_cmd("disassembler", no_class, valid_disassembly_styles, &disassembly_style, _("Set the disassembly style."), _("Show the disassembly style."), - helptext, + helptext.c_str (), set_disassembly_style_sfunc, NULL, /* FIXME: i18n: The disassembly style is \"%s\". */ @@ -10867,7 +11069,6 @@ arm_record_vdata_transfer_insn (insn_decode_record *arm_insn_r) uint32_t bits_a, bit_c, bit_l, reg_t, reg_v; uint32_t record_buf[4]; - const int num_regs = gdbarch_num_regs (arm_insn_r->gdbarch); reg_t = bits (arm_insn_r->arm_insn, 12, 15); reg_v = bits (arm_insn_r->arm_insn, 21, 23); bits_a = bits (arm_insn_r->arm_insn, 21, 23); @@ -10957,7 +11158,6 @@ arm_record_exreg_ld_st_insn (insn_decode_record *arm_insn_r) ULONGEST u_regval = 0; struct regcache *reg_cache = arm_insn_r->regcache; - const int num_regs = gdbarch_num_regs (arm_insn_r->gdbarch); opcode = bits (arm_insn_r->arm_insn, 20, 24); single_reg = !bit (arm_insn_r->arm_insn, 8);