/* Common target dependent code for GDB on ARM systems.
- Copyright (C) 1988-2014 Free Software Foundation, Inc.
+ Copyright (C) 1988-2015 Free Software Foundation, Inc.
This file is part of GDB.
#include "user-regs.h"
#include "observer.h"
+#include "arch/arm.h"
#include "arm-tdep.h"
#include "gdb/sim-arm.h"
struct regcache *regcache,
int regnum, const gdb_byte *buf);
-static int thumb_insn_size (unsigned short inst1);
-
struct arm_prologue_cache
{
/* The stack pointer at the time this frame was created; i.e. the
#define DISPLACED_STEPPING_ARCH_VERSION 5
-/* Addresses for calling Thumb functions have the bit 0 set.
- Here are some macros to test, set, or clear bit 0 of addresses. */
-#define IS_THUMB_ADDR(addr) ((addr) & 1)
-#define MAKE_THUMB_ADDR(addr) ((addr) | 1)
-#define UNMAKE_THUMB_ADDR(addr) ((addr) & ~1)
-
/* Set to true if the 32-bit mode is in use. */
int arm_apcs_32 = 1;
0 };
unsigned int idx;
- data = objfile_data (sec->objfile, arm_objfile_data_key);
+ data = (struct arm_per_objfile *) objfile_data (sec->objfile,
+ arm_objfile_data_key);
if (data != NULL)
{
map = data->section_maps[sec->the_bfd_section->index];
/* On soft-float targets, __truncdfsf2 is called to convert promoted
arguments to their argument types in non-prototyped
functions. */
- if (strncmp (name, "__truncdfsf2", strlen ("__truncdfsf2")) == 0)
+ if (startswith (name, "__truncdfsf2"))
return 1;
- if (strncmp (name, "__aeabi_d2f", strlen ("__aeabi_d2f")) == 0)
+ if (startswith (name, "__aeabi_d2f"))
return 1;
/* Internal functions related to thread-local storage. */
- if (strncmp (name, "__tls_get_addr", strlen ("__tls_get_addr")) == 0)
+ if (startswith (name, "__tls_get_addr"))
return 1;
- if (strncmp (name, "__aeabi_read_tp", strlen ("__aeabi_read_tp")) == 0)
+ if (startswith (name, "__aeabi_read_tp"))
return 1;
}
else
{
*destreg = bits (insn1, 8, 10);
*offset = 2;
- address = bits (insn1, 0, 7);
+ address = (pc & 0xfffffffc) + 4 + (bits (insn1, 0, 7) << 2);
+ address = read_memory_unsigned_integer (address, 4,
+ byte_order_for_code);
}
else if ((insn1 & 0xfbf0) == 0xf240) /* movw Rd, #const */
{
unsigned int insn
= read_memory_unsigned_integer (pc, 4, byte_order_for_code);
- if ((insn & 0x0e5f0000) == 0x041f0000) /* ldr Rd, #immed */
+ if ((insn & 0x0e5f0000) == 0x041f0000) /* ldr Rd, [PC, #immed] */
{
- address = bits (insn, 0, 11);
+ address = bits (insn, 0, 11) + pc + 8;
+ address = read_memory_unsigned_integer (address, 4,
+ byte_order_for_code);
+
*destreg = bits (insn, 12, 15);
*offset = 4;
}
return pc;
stack_chk_guard = lookup_minimal_symbol_by_pc (addr);
- /* If name of symbol doesn't start with '__stack_chk_guard', this
- instruction sequence is not for stack protector. If symbol is
- removed, we conservatively think this sequence is for stack protector. */
- if (stack_chk_guard.minsym
- && strncmp (MSYMBOL_LINKAGE_NAME (stack_chk_guard.minsym),
- "__stack_chk_guard",
- strlen ("__stack_chk_guard")) != 0)
+ /* ADDR must correspond to a symbol whose name is __stack_chk_guard.
+ Otherwise, this sequence cannot be for stack protector. */
+ if (stack_chk_guard.minsym == NULL
+ || !startswith (MSYMBOL_LINKAGE_NAME (stack_chk_guard.minsym), "__stack_chk_guard"))
return pc;
if (is_thumb)
{
enum bfd_endian byte_order_for_code = gdbarch_byte_order_for_code (gdbarch);
unsigned long inst;
- CORE_ADDR skip_pc;
CORE_ADDR func_addr, limit_pc;
/* See if we can determine the end of the prologue via the symbol table.
{
CORE_ADDR post_prologue_pc
= skip_prologue_using_sal (gdbarch, func_addr);
- struct symtab *s = find_pc_symtab (func_addr);
+ struct compunit_symtab *cust = find_pc_compunit_symtab (func_addr);
if (post_prologue_pc)
post_prologue_pc
will have producer information for most binaries; if it is
missing (e.g. for -gstabs), assuming the GNU tools. */
if (post_prologue_pc
- && (s == NULL
- || s->producer == NULL
- || strncmp (s->producer, "GNU ", sizeof ("GNU ") - 1) == 0
- || strncmp (s->producer, "clang ", sizeof ("clang ") - 1) == 0))
+ && (cust == NULL
+ || COMPUNIT_PRODUCER (cust) == NULL
+ || startswith (COMPUNIT_PRODUCER (cust), "GNU ")
+ || startswith (COMPUNIT_PRODUCER (cust), "clang ")))
return post_prologue_pc;
if (post_prologue_pc != 0)
/* Check if this is Thumb code. */
if (arm_pc_is_thumb (gdbarch, pc))
return thumb_analyze_prologue (gdbarch, pc, limit_pc, NULL);
-
- for (skip_pc = pc; skip_pc < limit_pc; skip_pc += 4)
- {
- inst = read_memory_unsigned_integer (skip_pc, 4, byte_order_for_code);
-
- /* "mov ip, sp" is no longer a required part of the prologue. */
- if (inst == 0xe1a0c00d) /* mov ip, sp */
- continue;
-
- if ((inst & 0xfffff000) == 0xe28dc000) /* add ip, sp #n */
- continue;
-
- if ((inst & 0xfffff000) == 0xe24dc000) /* sub ip, sp #n */
- continue;
-
- /* Some prologues begin with "str lr, [sp, #-4]!". */
- if (inst == 0xe52de004) /* str lr, [sp, #-4]! */
- continue;
-
- if ((inst & 0xfffffff0) == 0xe92d0000) /* stmfd sp!,{a1,a2,a3,a4} */
- continue;
-
- if ((inst & 0xfffff800) == 0xe92dd800) /* stmfd sp!,{fp,ip,lr,pc} */
- continue;
-
- /* Any insns after this point may float into the code, if it makes
- for better instruction scheduling, so we skip them only if we
- find them, but still consider the function to be frame-ful. */
-
- /* We may have either one sfmfd instruction here, or several stfe
- insns, depending on the version of floating point code we
- support. */
- if ((inst & 0xffbf0fff) == 0xec2d0200) /* sfmfd fn, <cnt>, [sp]! */
- continue;
-
- if ((inst & 0xffff8fff) == 0xed6d0103) /* stfe fn, [sp, #-12]! */
- continue;
-
- if ((inst & 0xfffff000) == 0xe24cb000) /* sub fp, ip, #nn */
- continue;
-
- if ((inst & 0xfffff000) == 0xe24dd000) /* sub sp, sp, #nn */
- continue;
-
- if ((inst & 0xffffc000) == 0xe54b0000 /* strb r(0123),[r11,#-nn] */
- || (inst & 0xffffc0f0) == 0xe14b00b0 /* strh r(0123),[r11,#-nn] */
- || (inst & 0xffffc000) == 0xe50b0000) /* str r(0123),[r11,#-nn] */
- continue;
-
- if ((inst & 0xffffc000) == 0xe5cd0000 /* strb r(0123),[sp,#nn] */
- || (inst & 0xffffc0f0) == 0xe1cd00b0 /* strh r(0123),[sp,#nn] */
- || (inst & 0xffffc000) == 0xe58d0000) /* str r(0123),[sp,#nn] */
- continue;
-
- /* Un-recognized instruction; stop scanning. */
- break;
- }
-
- return skip_pc; /* End of prologue. */
+ else
+ return arm_analyze_prologue (gdbarch, pc, limit_pc, NULL);
}
/* *INDENT-OFF* */
}
}
+/* Return 1 if the ARM instruction INSN restores SP in epilogue, 0
+ otherwise. */
+
+static int
+arm_instruction_restores_sp (unsigned int insn)
+{
+ if (bits (insn, 28, 31) != INST_NV)
+ {
+ if ((insn & 0x0df0f000) == 0x0080d000
+ /* ADD SP (register or immediate). */
+ || (insn & 0x0df0f000) == 0x0040d000
+ /* SUB SP (register or immediate). */
+ || (insn & 0x0ffffff0) == 0x01a0d000
+ /* MOV SP. */
+ || (insn & 0x0fff0000) == 0x08bd0000
+ /* POP (LDMIA). */
+ || (insn & 0x0fff0000) == 0x049d0000)
+ /* POP of a single register. */
+ return 1;
+ }
+
+ return 0;
+}
+
/* Analyze an ARM mode prologue starting at PROLOGUE_START and
continuing no further than PROLOGUE_END. If CACHE is non-NULL,
fill it in. Return the first address not recognized as a prologue
pv_t regs[ARM_FPS_REGNUM];
struct pv_area *stack;
struct cleanup *back_to;
- int framereg, framesize;
CORE_ADDR unrecognized_pc = 0;
/* Search the prologue looking for instructions that set up the
else if (arm_instruction_changes_pc (insn))
/* Don't scan past anything that might change control flow. */
break;
+ else if (arm_instruction_restores_sp (insn))
+ {
+ /* Don't scan past the epilogue. */
+ break;
+ }
else if ((insn & 0xfe500000) == 0xe8100000 /* ldm */
&& pv_is_register (regs[bits (insn, 16, 19)], ARM_SP_REGNUM))
/* Ignore block loads from the stack, potentially copying
continue;
else
{
- /* The optimizer might shove anything into the prologue,
- so we just skip what we don't recognize. */
+ /* The optimizer might shove anything into the prologue, if
+ we build up cache (cache != NULL) from scanning prologue,
+ we just skip what we don't recognize and scan further to
+ make cache as complete as possible. However, if we skip
+ prologue, we'll stop immediately on unrecognized
+ instruction. */
unrecognized_pc = current_pc;
- continue;
+ if (cache != NULL)
+ continue;
+ else
+ break;
}
}
if (unrecognized_pc == 0)
unrecognized_pc = current_pc;
- /* The frame size is just the distance from the frame register
- to the original stack pointer. */
- if (pv_is_register (regs[ARM_FP_REGNUM], ARM_SP_REGNUM))
- {
- /* Frame pointer is fp. */
- framereg = ARM_FP_REGNUM;
- framesize = -regs[ARM_FP_REGNUM].k;
- }
- else
- {
- /* Try the stack pointer... this is a bit desperate. */
- framereg = ARM_SP_REGNUM;
- framesize = -regs[ARM_SP_REGNUM].k;
- }
-
if (cache)
{
+ int framereg, framesize;
+
+ /* The frame size is just the distance from the frame register
+ to the original stack pointer. */
+ if (pv_is_register (regs[ARM_FP_REGNUM], ARM_SP_REGNUM))
+ {
+ /* Frame pointer is fp. */
+ framereg = ARM_FP_REGNUM;
+ framesize = -regs[ARM_FP_REGNUM].k;
+ }
+ else
+ {
+ /* Try the stack pointer... this is a bit desperate. */
+ framereg = ARM_SP_REGNUM;
+ framesize = -regs[ARM_SP_REGNUM].k;
+ }
+
cache->framereg = framereg;
cache->framesize = framesize;
return cache;
}
+/* Implementation of the stop_reason hook for arm_prologue frames. */
+
+static enum unwind_stop_reason
+arm_prologue_unwind_stop_reason (struct frame_info *this_frame,
+ void **this_cache)
+{
+ struct arm_prologue_cache *cache;
+ CORE_ADDR pc;
+
+ if (*this_cache == NULL)
+ *this_cache = arm_make_prologue_cache (this_frame);
+ cache = (struct arm_prologue_cache *) *this_cache;
+
+ /* This is meant to halt the backtrace at "_start". */
+ pc = get_frame_pc (this_frame);
+ if (pc <= gdbarch_tdep (get_frame_arch (this_frame))->lowest_pc)
+ return UNWIND_OUTERMOST;
+
+ /* If we've hit a wall, stop. */
+ if (cache->prev_sp == 0)
+ return UNWIND_OUTERMOST;
+
+ return UNWIND_NO_REASON;
+}
+
/* Our frame ID for a normal frame is the current function's starting PC
and the caller's SP when we were called. */
if (*this_cache == NULL)
*this_cache = arm_make_prologue_cache (this_frame);
- cache = *this_cache;
-
- /* This is meant to halt the backtrace at "_start". */
- pc = get_frame_pc (this_frame);
- if (pc <= gdbarch_tdep (get_frame_arch (this_frame))->lowest_pc)
- return;
-
- /* If we've hit a wall, stop. */
- if (cache->prev_sp == 0)
- return;
+ 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)
func = pc;
if (*this_cache == NULL)
*this_cache = arm_make_prologue_cache (this_frame);
- cache = *this_cache;
+ cache = (struct arm_prologue_cache *) *this_cache;
/* If we are asked to unwind the PC, then we need to return the LR
instead. The prologue may save PC, but it will point into this
struct frame_unwind arm_prologue_unwind = {
NORMAL_FRAME,
- default_frame_unwind_stop_reason,
+ arm_prologue_unwind_stop_reason,
arm_prologue_this_id,
arm_prologue_prev_register,
NULL,
static void
arm_exidx_data_free (struct objfile *objfile, void *arg)
{
- struct arm_exidx_data *data = arg;
+ struct arm_exidx_data *data = (struct arm_exidx_data *) arg;
unsigned int i;
for (i = 0; i < objfile->obfd->section_count; i++)
{
exidx_vma = bfd_section_vma (objfile->obfd, exidx);
exidx_size = bfd_get_section_size (exidx);
- exidx_data = xmalloc (exidx_size);
+ exidx_data = (gdb_byte *) xmalloc (exidx_size);
make_cleanup (xfree, exidx_data);
if (!bfd_get_section_contents (objfile->obfd, exidx,
{
extab_vma = bfd_section_vma (objfile->obfd, extab);
extab_size = bfd_get_section_size (extab);
- extab_data = xmalloc (extab_size);
+ extab_data = (gdb_byte *) xmalloc (extab_size);
make_cleanup (xfree, extab_data);
if (!bfd_get_section_contents (objfile->obfd, extab,
extab section starting at ADDR. */
if (n_bytes || n_words)
{
- gdb_byte *p = entry = obstack_alloc (&objfile->objfile_obstack,
- n_bytes + n_words * 4 + 1);
+ gdb_byte *p = entry
+ = (gdb_byte *) obstack_alloc (&objfile->objfile_obstack,
+ n_bytes + n_words * 4 + 1);
while (n_bytes--)
*p++ = (gdb_byte) ((word >> (8 * n_bytes)) & 0xff);
struct arm_exidx_entry map_key = { memaddr - obj_section_addr (sec), 0 };
unsigned int idx;
- data = objfile_data (sec->objfile, arm_exidx_data_key);
+ data = ((struct arm_exidx_data *)
+ objfile_data (sec->objfile, arm_exidx_data_key));
if (data != NULL)
{
map = data->section_maps[sec->the_bfd_section->index];
if (*this_cache == NULL)
*this_cache = arm_make_stub_cache (this_frame);
- cache = *this_cache;
+ cache = (struct arm_prologue_cache *) *this_cache;
*this_id = frame_id_build (cache->prev_sp, get_frame_pc (this_frame));
}
if (*this_cache == NULL)
*this_cache = arm_m_exception_cache (this_frame);
- cache = *this_cache;
+ cache = (struct arm_prologue_cache *) *this_cache;
/* Our frame ID for a stub frame is the current SP and LR. */
*this_id = frame_id_build (cache->prev_sp,
if (*this_cache == NULL)
*this_cache = arm_m_exception_cache (this_frame);
- cache = *this_cache;
+ cache = (struct arm_prologue_cache *) *this_cache;
/* The value was already reconstructed into PREV_SP. */
if (prev_regnum == ARM_SP_REGNUM)
if (*this_cache == NULL)
*this_cache = arm_make_prologue_cache (this_frame);
- cache = *this_cache;
+ cache = (struct arm_prologue_cache *) *this_cache;
return cache->prev_sp - cache->framesize;
}
}
}
-/* Return true if we are in the function's epilogue, i.e. after the
- instruction that destroyed the function's stack frame. */
+/* Implement the stack_frame_destroyed_p gdbarch method. */
static int
-thumb_in_function_epilogue_p (struct gdbarch *gdbarch, CORE_ADDR pc)
+thumb_stack_frame_destroyed_p (struct gdbarch *gdbarch, CORE_ADDR pc)
{
enum bfd_endian byte_order_for_code = gdbarch_byte_order_for_code (gdbarch);
unsigned int insn, insn2;
return found_stack_adjust;
}
-/* Return true if we are in the function's epilogue, i.e. after the
- instruction that destroyed the function's stack frame. */
+/* Implement the stack_frame_destroyed_p gdbarch method. */
static int
-arm_in_function_epilogue_p (struct gdbarch *gdbarch, CORE_ADDR pc)
+arm_stack_frame_destroyed_p (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, found_stack_adjust;
+ int found_return;
CORE_ADDR func_start, func_end;
if (arm_pc_is_thumb (gdbarch, pc))
- return thumb_in_function_epilogue_p (gdbarch, pc);
+ return thumb_stack_frame_destroyed_p (gdbarch, pc);
if (!find_pc_partial_function (pc, NULL, &func_start, &func_end))
return 0;
if (pc < func_start + 4)
return 0;
- found_stack_adjust = 0;
insn = read_memory_unsigned_integer (pc - 4, 4, byte_order_for_code);
- if (bits (insn, 28, 31) != INST_NV)
- {
- if ((insn & 0x0df0f000) == 0x0080d000)
- /* ADD SP (register or immediate). */
- found_stack_adjust = 1;
- else if ((insn & 0x0df0f000) == 0x0040d000)
- /* SUB SP (register or immediate). */
- found_stack_adjust = 1;
- else if ((insn & 0x0ffffff0) == 0x01a0d000)
- /* MOV SP. */
- found_stack_adjust = 1;
- else if ((insn & 0x0fff0000) == 0x08bd0000)
- /* POP (LDMIA). */
- found_stack_adjust = 1;
- else if ((insn & 0x0fff0000) == 0x049d0000)
- /* POP of a single register. */
- found_stack_adjust = 1;
- }
-
- if (found_stack_adjust)
+ if (arm_instruction_restores_sp (insn))
return 1;
return 0;
{
int len;
struct stack_item *prev;
- void *data;
+ gdb_byte *data;
};
static struct stack_item *
push_stack_item (struct stack_item *prev, const void *contents, int len)
{
struct stack_item *si;
- si = xmalloc (sizeof (struct stack_item));
- si->data = xmalloc (len);
+ si = XNEW (struct stack_item);
+ si->data = (gdb_byte *) xmalloc (len);
si->len = len;
si->prev = prev;
memcpy (si->data, contents, len);
CORE_ADDR regval = extract_unsigned_integer (val, len, byte_order);
if (arm_pc_is_thumb (gdbarch, regval))
{
- bfd_byte *copy = alloca (len);
+ bfd_byte *copy = (bfd_byte *) alloca (len);
store_unsigned_integer (copy, len, byte_order,
MAKE_THUMB_ADDR (regval));
val = copy;
return nbits;
}
-/* Return the size in bytes of the complete Thumb instruction whose
- first halfword is INST1. */
-
-static int
-thumb_insn_size (unsigned short inst1)
-{
- if ((inst1 & 0xe000) == 0xe000 && (inst1 & 0x1800) != 0)
- return 4;
- else
- return 2;
-}
-
static int
thumb_advance_itstate (unsigned int itstate)
{
case 0x5: /* data transfer */
case 0x6:
case 0x7:
+ if (bits (this_instr, 25, 27) == 0x3 && bit (this_instr, 4) == 1)
+ {
+ /* Media instructions and architecturally undefined
+ instructions. */
+ break;
+ }
+
if (bit (this_instr, 20))
{
/* load */
gdb_byte *new_buf;
int bytes_to_read = new_len - old_len;
- new_buf = xmalloc (new_len);
+ 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)
/* No room for an IT instruction. */
return bpaddr;
- buf = xmalloc (buf_len);
+ buf = (gdb_byte *) xmalloc (buf_len);
if (target_read_memory (bpaddr - buf_len, buf, buf_len) != 0)
return bpaddr;
any = 0;
Preparation: tmp1, tmp2, tmp3 <- r0, r1, r2;
r0, r1, r2 <- rd, rn, rm
- Insn: <op><cond> r0, r1, r2 [, <shift>]
+ Insn: <op><cond> r0, [r1,] r2 [, <shift>]
Cleanup: rd <- r0; r0, r1, r2 <- tmp1, tmp2, tmp3
*/
struct regcache *regs,
struct displaced_step_closure *dsc)
{
- unsigned rn, rm, rd;
+ unsigned rm, rd;
- rd = bits (insn, 3, 6);
- rn = (bit (insn, 7) << 3) | bits (insn, 0, 2);
- rm = 2;
+ rm = bits (insn, 3, 6);
+ rd = (bit (insn, 7) << 3) | bits (insn, 0, 2);
- if (rd != ARM_PC_REGNUM && rn != ARM_PC_REGNUM)
+ if (rd != ARM_PC_REGNUM && rm != ARM_PC_REGNUM)
return thumb_copy_unmodified_16bit (gdbarch, insn, "ALU reg", dsc);
if (debug_displaced)
- fprintf_unfiltered (gdb_stdlog, "displaced: copying reg %s insn %.4x\n",
- "ALU", (unsigned short) insn);
+ fprintf_unfiltered (gdb_stdlog, "displaced: copying ALU reg insn %.4x\n",
+ (unsigned short) insn);
- dsc->modinsn[0] = ((insn & 0xff00) | 0x08);
+ dsc->modinsn[0] = ((insn & 0xff00) | 0x10);
- install_alu_reg (gdbarch, regs, dsc, rd, rn, rm);
+ install_alu_reg (gdbarch, regs, dsc, rd, rd, rm);
return 0;
}
CORE_ADDR from, CORE_ADDR to,
struct regcache *regs)
{
- struct displaced_step_closure *dsc
- = xmalloc (sizeof (struct displaced_step_closure));
+ struct displaced_step_closure *dsc = XNEW (struct displaced_step_closure);
+
arm_process_displaced_insn (gdbarch, from, to, regs, dsc);
arm_displaced_init_closure (gdbarch, from, to, dsc);
static int
gdb_print_insn_arm (bfd_vma memaddr, disassemble_info *info)
{
- struct gdbarch *gdbarch = info->application_data;
+ struct gdbarch *gdbarch = (struct gdbarch *) info->application_data;
if (arm_pc_is_thumb (gdbarch, memaddr))
{
int nRc;
enum type_code code;
- CHECK_TYPEDEF (type);
+ type = check_typedef (type);
/* In the ARM ABI, "integer" like aggregate types are returned in
registers. For an aggregate type to be integer like, its size
_call_via_xx, where x is the register name. The possible names
are r0-r9, sl, fp, ip, sp, and lr. ARM RealView has similar
functions, named __ARM_call_via_r[0-7]. */
- if (strncmp (name, "_call_via_", 10) == 0
- || strncmp (name, "__ARM_call_via_", strlen ("__ARM_call_via_")) == 0)
+ if (startswith (name, "_call_via_")
+ || startswith (name, "__ARM_call_via_"))
{
/* Use the name suffix to determine which register contains the
target PC. */
namelen = strlen (name);
if (name[0] == '_' && name[1] == '_'
&& ((namelen > 2 + strlen ("_from_thumb")
- && strncmp (name + namelen - strlen ("_from_thumb"), "_from_thumb",
- strlen ("_from_thumb")) == 0)
+ && startswith (name + namelen - strlen ("_from_thumb"), "_from_thumb"))
|| (namelen > 2 + strlen ("_from_arm")
- && strncmp (name + namelen - strlen ("_from_arm"), "_from_arm",
- strlen ("_from_arm")) == 0)))
+ && startswith (name + namelen - strlen ("_from_arm"), "_from_arm"))))
{
char *target_name;
int target_len = namelen - 2;
else
target_len -= strlen ("_from_arm");
- target_name = alloca (target_len + 1);
+ target_name = (char *) alloca (target_len + 1);
memcpy (target_name, name + 2, target_len);
target_name[target_len] = '\0';
set_fp_model_sfunc (char *args, int from_tty,
struct cmd_list_element *c)
{
- enum arm_float_model fp_model;
+ int fp_model;
for (fp_model = ARM_FLOAT_AUTO; fp_model != ARM_FLOAT_LAST; fp_model++)
if (strcmp (current_fp_model, fp_model_strings[fp_model]) == 0)
{
- arm_fp_model = fp_model;
+ arm_fp_model = (enum arm_float_model) fp_model;
break;
}
arm_set_abi (char *args, int from_tty,
struct cmd_list_element *c)
{
- enum arm_abi_kind arm_abi;
+ int arm_abi;
for (arm_abi = ARM_ABI_AUTO; arm_abi != ARM_ABI_LAST; arm_abi++)
if (strcmp (arm_abi_string, arm_abi_strings[arm_abi]) == 0)
{
- arm_abi_global = arm_abi;
+ arm_abi_global = (enum arm_abi_kind) arm_abi;
break;
}
static void
arm_objfile_data_free (struct objfile *objfile, void *arg)
{
- struct arm_per_objfile *data = arg;
+ struct arm_per_objfile *data = (struct arm_per_objfile *) arg;
unsigned int i;
for (i = 0; i < objfile->obfd->section_count; i++)
if (name[1] != 'a' && name[1] != 't' && name[1] != 'd')
return;
- data = objfile_data (objfile, arm_objfile_data_key);
+ data = (struct arm_per_objfile *) objfile_data (objfile,
+ arm_objfile_data_key);
if (data == NULL)
{
data = OBSTACK_ZALLOC (&objfile->objfile_obstack,
static struct value *
value_of_arm_user_reg (struct frame_info *frame, const void *baton)
{
- const int *reg_p = baton;
+ const int *reg_p = (const int *) baton;
return value_of_register (*reg_p, frame);
}
\f
enum arm_float_model fp_model = arm_fp_model;
struct tdesc_arch_data *tdesc_data = NULL;
int i, is_m = 0;
- int have_vfp_registers = 0, have_vfp_pseudos = 0, have_neon_pseudos = 0;
+ int vfp_register_count = 0, have_vfp_pseudos = 0, have_neon_pseudos = 0;
+ int have_wmmx_registers = 0;
int have_neon = 0;
int have_fpa_registers = 1;
const struct target_desc *tdesc = info.target_desc;
anyway, so assume APCS. */
arm_abi = ARM_ABI_APCS;
}
- else if (ei_osabi == ELFOSABI_NONE)
+ else if (ei_osabi == ELFOSABI_NONE || ei_osabi == ELFOSABI_GNU)
{
int eabi_ver = EF_ARM_EABI_VERSION (e_flags);
int attr_arch, attr_profile;
OBJ_ATTR_PROC,
Tag_ABI_VFP_args))
{
- case 0:
+ case AEABI_VFP_args_base:
/* "The user intended FP parameter/result
passing to conform to AAPCS, base
variant". */
fp_model = ARM_FLOAT_SOFT_VFP;
break;
- case 1:
+ case AEABI_VFP_args_vfp:
/* "The user intended FP parameter/result
passing to conform to AAPCS, VFP
variant". */
fp_model = ARM_FLOAT_VFP;
break;
- case 2:
+ case AEABI_VFP_args_toolchain:
/* "The user intended FP parameter/result
passing to conform to tool chain-specific
conventions" - we don't know any such
conventions, so leave it as "auto". */
break;
+ case AEABI_VFP_args_compatible:
+ /* "Code is compatible with both the base
+ and VFP variants; the user did not permit
+ non-variadic functions to pass FP
+ parameters/results" - leave it as
+ "auto". */
+ break;
default:
/* Attribute value not mentioned in the
- October 2008 ABI, so leave it as
+ November 2012 ABI, so leave it as
"auto". */
break;
}
tdesc_data_cleanup (tdesc_data);
return NULL;
}
+
+ have_wmmx_registers = 1;
}
/* If we have a VFP unit, check whether the single precision registers
if (tdesc_unnumbered_register (feature, "s0") == 0)
have_vfp_pseudos = 1;
- have_vfp_registers = 1;
+ vfp_register_count = i;
/* If we have VFP, also check for NEON. The architecture allows
NEON without VFP (integer vector operations only), but GDB
return best_arch->gdbarch;
}
- tdep = xcalloc (1, sizeof (struct gdbarch_tdep));
+ tdep = XCNEW (struct gdbarch_tdep);
gdbarch = gdbarch_alloc (&info, tdep);
/* Record additional information about the architecture we are defining.
tdep->fp_model = fp_model;
tdep->is_m = is_m;
tdep->have_fpa_registers = have_fpa_registers;
- tdep->have_vfp_registers = have_vfp_registers;
+ tdep->have_wmmx_registers = have_wmmx_registers;
+ gdb_assert (vfp_register_count == 0
+ || vfp_register_count == 16
+ || vfp_register_count == 32);
+ tdep->vfp_register_count = vfp_register_count;
tdep->have_vfp_pseudos = have_vfp_pseudos;
tdep->have_neon_pseudos = have_neon_pseudos;
tdep->have_neon = have_neon;
/* Advance PC across function entry code. */
set_gdbarch_skip_prologue (gdbarch, arm_skip_prologue);
- /* Detect whether PC is in function epilogue. */
- set_gdbarch_in_function_epilogue_p (gdbarch, arm_in_function_epilogue_p);
+ /* Detect whether PC is at a point where the stack has been destroyed. */
+ set_gdbarch_stack_frame_destroyed_p (gdbarch, arm_stack_frame_destroyed_p);
/* Skip trampolines. */
set_gdbarch_skip_trampoline_code (gdbarch, arm_skip_stub);
/* Initialize the array that will be passed to
add_setshow_enum_cmd(). */
- valid_disassembly_styles
- = xmalloc ((num_disassembly_options + 1) * sizeof (char *));
+ valid_disassembly_styles = XNEWVEC (const char *,
+ num_disassembly_options + 1);
for (i = 0; i < num_disassembly_options; i++)
{
numregs = get_arm_regnames (i, &setname, &setdesc, ®names);
return 1;
insn_record->arm_insn = (uint32_t) extract_unsigned_integer (&buf[0],
insn_size,
- gdbarch_byte_order (insn_record->gdbarch));
+ gdbarch_byte_order_for_code (insn_record->gdbarch));
return 0;
}
{
/* (Starting from numerical 0); bits 25, 26, 27 decodes type of arm instruction. */
- static const sti_arm_hdl_fp_t const arm_handle_insn[8] =
+ static const sti_arm_hdl_fp_t arm_handle_insn[8] =
{
arm_record_data_proc_misc_ld_str, /* 000. */
arm_record_data_proc_imm, /* 001. */
};
/* (Starting from numerical 0); bits 13,14,15 decodes type of thumb instruction. */
- static const sti_arm_hdl_fp_t const thumb_handle_insn[8] =
+ static const sti_arm_hdl_fp_t thumb_handle_insn[8] =
{ \
thumb_record_shift_add_sub, /* 000. */
thumb_record_add_sub_cmp_mov, /* 001. */