X-Git-Url: http://git.efficios.com/?a=blobdiff_plain;f=gdb%2Favr-tdep.c;h=381c7903fc6088bba1e04aba8d998891ec541069;hb=78f2c40a12179d26d3065c09f054b7e751b2732f;hp=20e7fcad33e3a725c517562864763c0c4f9c9d1f;hpb=8fbca658f0643a6c3d5b61840351ae70e5bf2db6;p=deliverable%2Fbinutils-gdb.git diff --git a/gdb/avr-tdep.c b/gdb/avr-tdep.c index 20e7fcad33..381c7903fc 100644 --- a/gdb/avr-tdep.c +++ b/gdb/avr-tdep.c @@ -1,7 +1,6 @@ /* Target-dependent code for Atmel AVR, for GDB. - Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, - 2006, 2007, 2008, 2009, 2010, 2011 Free Software Foundation, Inc. + Copyright (C) 1996-2020 Free Software Foundation, Inc. This file is part of GDB. @@ -35,8 +34,9 @@ #include "symfile.h" #include "arch-utils.h" #include "regcache.h" -#include "gdb_string.h" #include "dis-asm.h" +#include "objfiles.h" +#include /* AVR Background: @@ -69,11 +69,18 @@ via the remote serial protocol. The extra bits are the MSBs and are used to decode which memory space the address is referring to. */ -#undef XMALLOC -#define XMALLOC(TYPE) ((TYPE*) xmalloc (sizeof (TYPE))) - /* Constants: prefixed with AVR_ to avoid name space clashes */ +/* Address space flags */ + +/* We are assigning the TYPE_INSTANCE_FLAG_ADDRESS_CLASS_1 to the flash address + space. */ + +#define AVR_TYPE_ADDRESS_CLASS_FLASH TYPE_ADDRESS_CLASS_1 +#define AVR_TYPE_INSTANCE_FLAG_ADDRESS_CLASS_FLASH \ + TYPE_INSTANCE_FLAG_ADDRESS_CLASS_1 + + enum { AVR_REG_W = 24, @@ -105,6 +112,7 @@ enum AVR_ARG1_REGNUM = 24, /* Single byte argument */ AVR_ARGN_REGNUM = 25, /* Multi byte argments */ + AVR_LAST_ARG_REGNUM = 8, /* Last argument register */ AVR_RET1_REGNUM = 24, /* Single byte return value */ AVR_RETN_REGNUM = 25, /* Multi byte return value */ @@ -183,7 +191,7 @@ struct avr_unwind_cache struct gdbarch_tdep { /* Number of bytes stored to the stack by call instructions. - 2 bytes for avr1-5, 3 bytes for avr6. */ + 2 bytes for avr1-5 and avrxmega1-5, 3 bytes for avr6 and avrxmega6-7. */ int call_length; /* Type for void. */ @@ -298,10 +306,19 @@ avr_address_to_pointer (struct gdbarch *gdbarch, { enum bfd_endian byte_order = gdbarch_byte_order (gdbarch); + /* Is it a data address in flash? */ + if (AVR_TYPE_ADDRESS_CLASS_FLASH (type)) + { + /* A data pointer in flash is byte addressed. */ + store_unsigned_integer (buf, TYPE_LENGTH (type), byte_order, + avr_convert_iaddr_to_raw (addr)); + } /* Is it a code address? */ - if (TYPE_CODE (TYPE_TARGET_TYPE (type)) == TYPE_CODE_FUNC - || TYPE_CODE (TYPE_TARGET_TYPE (type)) == TYPE_CODE_METHOD) + else if (TYPE_CODE (TYPE_TARGET_TYPE (type)) == TYPE_CODE_FUNC + || TYPE_CODE (TYPE_TARGET_TYPE (type)) == TYPE_CODE_METHOD) { + /* A code pointer is word (16 bits) addressed. We shift the address down + by 1 bit to convert it to a pointer. */ store_unsigned_integer (buf, TYPE_LENGTH (type), byte_order, avr_convert_iaddr_to_raw (addr >> 1)); } @@ -321,11 +338,21 @@ avr_pointer_to_address (struct gdbarch *gdbarch, CORE_ADDR addr = extract_unsigned_integer (buf, TYPE_LENGTH (type), byte_order); + /* Is it a data address in flash? */ + if (AVR_TYPE_ADDRESS_CLASS_FLASH (type)) + { + /* A data pointer in flash is already byte addressed. */ + return avr_make_iaddr (addr); + } /* Is it a code address? */ - if (TYPE_CODE (TYPE_TARGET_TYPE (type)) == TYPE_CODE_FUNC - || TYPE_CODE (TYPE_TARGET_TYPE (type)) == TYPE_CODE_METHOD - || TYPE_CODE_SPACE (TYPE_TARGET_TYPE (type))) - return avr_make_iaddr (addr << 1); + else if (TYPE_CODE (TYPE_TARGET_TYPE (type)) == TYPE_CODE_FUNC + || TYPE_CODE (TYPE_TARGET_TYPE (type)) == TYPE_CODE_METHOD + || TYPE_CODE_SPACE (TYPE_TARGET_TYPE (type))) + { + /* A code pointer is word (16 bits) addressed so we shift it up + by 1 bit to convert it to an address. */ + return avr_make_iaddr (addr << 1); + } else return avr_make_saddr (addr); } @@ -340,10 +367,11 @@ avr_integer_to_address (struct gdbarch *gdbarch, } static CORE_ADDR -avr_read_pc (struct regcache *regcache) +avr_read_pc (readable_regcache *regcache) { ULONGEST pc; - regcache_cooked_read_unsigned (regcache, AVR_PC_REGNUM, &pc); + + regcache->cooked_read (AVR_PC_REGNUM, &pc); return avr_make_iaddr (pc); } @@ -355,7 +383,7 @@ avr_write_pc (struct regcache *regcache, CORE_ADDR val) } static enum register_status -avr_pseudo_register_read (struct gdbarch *gdbarch, struct regcache *regcache, +avr_pseudo_register_read (struct gdbarch *gdbarch, readable_regcache *regcache, int regnum, gdb_byte *buf) { ULONGEST val; @@ -364,7 +392,7 @@ avr_pseudo_register_read (struct gdbarch *gdbarch, struct regcache *regcache, switch (regnum) { case AVR_PSEUDO_PC_REGNUM: - status = regcache_raw_read_unsigned (regcache, AVR_PC_REGNUM, &val); + status = regcache->raw_read (AVR_PC_REGNUM, &val); if (status != REG_VALID) return status; val >>= 1; @@ -496,7 +524,7 @@ avr_scan_prologue (struct gdbarch *gdbarch, CORE_ADDR pc_beg, CORE_ADDR pc_end, int i; unsigned short insn; int scan_stage = 0; - struct minimal_symbol *msymbol; + struct bound_minimal_symbol msymbol; unsigned char prologue[AVR_MAX_PROLOGUE_SIZE]; int vpc = 0; int len; @@ -590,7 +618,7 @@ avr_scan_prologue (struct gdbarch *gdbarch, CORE_ADDR pc_beg, CORE_ADDR pc_end, pc_offset += 2; msymbol = lookup_minimal_symbol ("__prologue_saves__", NULL, NULL); - if (!msymbol) + if (!msymbol.minsym) break; insn = extract_unsigned_integer (&prologue[vpc + 8], 2, byte_order); @@ -628,7 +656,7 @@ avr_scan_prologue (struct gdbarch *gdbarch, CORE_ADDR pc_beg, CORE_ADDR pc_end, /* Resolve offset (in words) from __prologue_saves__ symbol. Which is a pushes count in `-mcall-prologues' mode */ - num_pushes = AVR_MAX_PUSHES - (i - SYMBOL_VALUE_ADDRESS (msymbol)) / 2; + num_pushes = AVR_MAX_PUSHES - (i - BMSYMBOL_VALUE_ADDRESS (msymbol)) / 2; if (num_pushes > AVR_MAX_PUSHES) { @@ -723,7 +751,7 @@ avr_scan_prologue (struct gdbarch *gdbarch, CORE_ADDR pc_beg, CORE_ADDR pc_end, info->size += gdbarch_tdep (gdbarch)->call_length; vpc += 2; } - else if (insn == 0x920f) /* push r0 */ + else if (insn == 0x920f || insn == 0x921f) /* push r0 or push r1 */ { info->size += 1; vpc += 2; @@ -743,7 +771,6 @@ avr_scan_prologue (struct gdbarch *gdbarch, CORE_ADDR pc_beg, CORE_ADDR pc_end, 0xcd, 0xb7, /* in r28,__SP_L__ */ 0xde, 0xb7 /* in r29,__SP_H__ */ }; - unsigned short insn1; if (vpc + sizeof (img) < len && memcmp (prologue + vpc, img, sizeof (img)) == 0) @@ -857,7 +884,7 @@ avr_skip_prologue (struct gdbarch *gdbarch, CORE_ADDR pc) post_prologue_pc = skip_prologue_using_sal (gdbarch, func_addr); if (post_prologue_pc != 0) - return max (pc, post_prologue_pc); + return std::max (pc, post_prologue_pc); { CORE_ADDR prologue_end = pc; @@ -887,14 +914,9 @@ avr_skip_prologue (struct gdbarch *gdbarch, CORE_ADDR pc) it as a NOP. Thus, it should be ok. Since the avr is currently a remote only target, this shouldn't be a problem (I hope). TRoth/2003-05-14 */ -static const unsigned char * -avr_breakpoint_from_pc (struct gdbarch *gdbarch, - CORE_ADDR *pcptr, int *lenptr) -{ - static const unsigned char avr_break_insn [] = { 0x98, 0x95 }; - *lenptr = sizeof (avr_break_insn); - return avr_break_insn; -} +constexpr gdb_byte avr_break_insn [] = { 0x98, 0x95 }; + +typedef BP_MANIPULATION (avr_break_insn) avr_breakpoint; /* Determine, for architecture GDBARCH, how a return value of TYPE should be returned. If it is supposed to be returned in registers, @@ -903,7 +925,7 @@ avr_breakpoint_from_pc (struct gdbarch *gdbarch, from WRITEBUF into REGCACHE. */ static enum return_value_convention -avr_return_value (struct gdbarch *gdbarch, struct type *func_type, +avr_return_value (struct gdbarch *gdbarch, struct value *function, struct type *valtype, struct regcache *regcache, gdb_byte *readbuf, const gdb_byte *writebuf) { @@ -931,13 +953,13 @@ avr_return_value (struct gdbarch *gdbarch, struct type *func_type, if (writebuf != NULL) { for (i = 0; i < TYPE_LENGTH (valtype); i++) - regcache_cooked_write (regcache, lsb_reg + i, writebuf + i); + regcache->cooked_write (lsb_reg + i, writebuf + i); } if (readbuf != NULL) { for (i = 0; i < TYPE_LENGTH (valtype); i++) - regcache_cooked_read (regcache, lsb_reg + i, readbuf + i); + regcache->cooked_read (lsb_reg + i, readbuf + i); } return RETURN_VALUE_REGISTER_CONVENTION; @@ -963,7 +985,7 @@ avr_frame_unwind_cache (struct frame_info *this_frame, int i; if (*this_prologue_cache) - return *this_prologue_cache; + return (struct avr_unwind_cache *) *this_prologue_cache; info = FRAME_OBSTACK_ZALLOC (struct avr_unwind_cache); *this_prologue_cache = info; @@ -1082,8 +1104,6 @@ static struct value * avr_frame_prev_register (struct frame_info *this_frame, void **this_prologue_cache, int regnum) { - struct gdbarch *gdbarch = get_frame_arch (this_frame); - enum bfd_endian byte_order = gdbarch_byte_order (gdbarch); struct avr_unwind_cache *info = avr_frame_unwind_cache (this_frame, this_prologue_cache); @@ -1105,7 +1125,7 @@ avr_frame_prev_register (struct frame_info *this_frame, everything else about the avr is little endian. Ick! */ ULONGEST pc; int i; - unsigned char buf[3]; + gdb_byte buf[3]; struct gdbarch *gdbarch = get_frame_arch (this_frame); struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch); @@ -1174,15 +1194,15 @@ struct stack_item { int len; struct stack_item *prev; - void *data; + gdb_byte *data; }; static struct stack_item * push_stack_item (struct stack_item *prev, const bfd_byte *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); @@ -1243,17 +1263,17 @@ static CORE_ADDR avr_push_dummy_call (struct gdbarch *gdbarch, struct value *function, struct regcache *regcache, CORE_ADDR bp_addr, int nargs, struct value **args, CORE_ADDR sp, - int struct_return, CORE_ADDR struct_addr) + function_call_return_method return_method, + CORE_ADDR struct_addr) { - enum bfd_endian byte_order = gdbarch_byte_order (gdbarch); int i; - unsigned char buf[3]; + gdb_byte buf[3]; int call_length = gdbarch_tdep (gdbarch)->call_length; CORE_ADDR return_pc = avr_convert_iaddr_to_raw (bp_addr); int regnum = AVR_ARGN_REGNUM; struct stack_item *si = NULL; - if (struct_return) + if (return_method == return_method_struct) { regcache_cooked_write_unsigned (regcache, regnum--, (struct_addr >> 8) & 0xff); @@ -1274,23 +1294,24 @@ avr_push_dummy_call (struct gdbarch *gdbarch, struct value *function, const bfd_byte *contents = value_contents (arg); int len = TYPE_LENGTH (type); - /* Calculate the potential last register needed. */ - last_regnum = regnum - (len + (len & 1)); + /* Calculate the potential last register needed. + E.g. For length 2, registers regnum and regnum-1 (say 25 and 24) + shall be used. So, last needed register will be regnum-1(24). */ + last_regnum = regnum - (len + (len & 1)) + 1; /* If there are registers available, use them. Once we start putting stuff on the stack, all subsequent args go on stack. */ - if ((si == NULL) && (last_regnum >= 8)) + if ((si == NULL) && (last_regnum >= AVR_LAST_ARG_REGNUM)) { - ULONGEST val; - /* Skip a register for odd length args. */ if (len & 1) regnum--; - val = extract_unsigned_integer (contents, len, byte_order); + /* Write MSB of argument into register and subsequent bytes in + decreasing register numbers. */ for (j = 0; j < len; j++) regcache_cooked_write_unsigned - (regcache, regnum--, val >> (8 * (len - j - 1))); + (regcache, regnum--, contents[len - j - 1]); } /* No registers available, push the args onto the stack. */ else @@ -1340,10 +1361,55 @@ avr_dwarf_reg_to_regnum (struct gdbarch *gdbarch, int reg) return reg; if (reg == 32) return AVR_SP_REGNUM; + return -1; +} - warning (_("Unmapped DWARF Register #%d encountered."), reg); +/* Implementation of `address_class_type_flags' gdbarch method. - return -1; + This method maps DW_AT_address_class attributes to a + type_instance_flag_value. */ + +static int +avr_address_class_type_flags (int byte_size, int dwarf2_addr_class) +{ + /* The value 1 of the DW_AT_address_class attribute corresponds to the + __flash qualifier. Note that this attribute is only valid with + pointer types and therefore the flag is set to the pointer type and + not its target type. */ + if (dwarf2_addr_class == 1 && byte_size == 2) + return AVR_TYPE_INSTANCE_FLAG_ADDRESS_CLASS_FLASH; + return 0; +} + +/* Implementation of `address_class_type_flags_to_name' gdbarch method. + + Convert a type_instance_flag_value to an address space qualifier. */ + +static const char* +avr_address_class_type_flags_to_name (struct gdbarch *gdbarch, int type_flags) +{ + if (type_flags & AVR_TYPE_INSTANCE_FLAG_ADDRESS_CLASS_FLASH) + return "flash"; + else + return NULL; +} + +/* Implementation of `address_class_name_to_type_flags' gdbarch method. + + Convert an address space qualifier to a type_instance_flag_value. */ + +static int +avr_address_class_name_to_type_flags (struct gdbarch *gdbarch, + const char* name, + int *type_flags_ptr) +{ + if (strcmp (name, "flash") == 0) + { + *type_flags_ptr = AVR_TYPE_INSTANCE_FLAG_ADDRESS_CLASS_FLASH; + return 1; + } + else + return 0; } /* Initialize the gdbarch structure for the AVR's. */ @@ -1360,14 +1426,21 @@ avr_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches) switch (info.bfd_arch_info->mach) { case bfd_mach_avr1: + case bfd_mach_avrxmega1: case bfd_mach_avr2: + case bfd_mach_avrxmega2: case bfd_mach_avr3: + case bfd_mach_avrxmega3: case bfd_mach_avr4: + case bfd_mach_avrxmega4: case bfd_mach_avr5: + case bfd_mach_avrxmega5: default: call_length = 2; break; case bfd_mach_avr6: + case bfd_mach_avrxmega6: + case bfd_mach_avrxmega7: call_length = 3; break; } @@ -1382,18 +1455,18 @@ avr_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches) } /* None found, create a new architecture from the information provided. */ - tdep = XMALLOC (struct gdbarch_tdep); + tdep = XCNEW (struct gdbarch_tdep); gdbarch = gdbarch_alloc (&info, tdep); tdep->call_length = call_length; /* Create a type for PC. We can't use builtin types here, as they may not be defined. */ - tdep->void_type = arch_type (gdbarch, TYPE_CODE_VOID, 1, "void"); + tdep->void_type = arch_type (gdbarch, TYPE_CODE_VOID, TARGET_CHAR_BIT, + "void"); tdep->func_void_type = make_function_type (tdep->void_type, NULL); - tdep->pc_type = arch_type (gdbarch, TYPE_CODE_PTR, 4, NULL); - TYPE_TARGET_TYPE (tdep->pc_type) = tdep->func_void_type; - TYPE_UNSIGNED (tdep->pc_type) = 1; + tdep->pc_type = arch_pointer_type (gdbarch, 4 * TARGET_CHAR_BIT, NULL, + tdep->func_void_type); set_gdbarch_short_bit (gdbarch, 2 * TARGET_CHAR_BIT); set_gdbarch_int_bit (gdbarch, 2 * TARGET_CHAR_BIT); @@ -1402,6 +1475,9 @@ avr_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches) set_gdbarch_ptr_bit (gdbarch, 2 * TARGET_CHAR_BIT); set_gdbarch_addr_bit (gdbarch, 32); + set_gdbarch_wchar_bit (gdbarch, 2 * TARGET_CHAR_BIT); + set_gdbarch_wchar_signed (gdbarch, 1); + set_gdbarch_float_bit (gdbarch, 4 * TARGET_CHAR_BIT); set_gdbarch_double_bit (gdbarch, 4 * TARGET_CHAR_BIT); set_gdbarch_long_double_bit (gdbarch, 4 * TARGET_CHAR_BIT); @@ -1426,7 +1502,6 @@ avr_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches) set_gdbarch_pseudo_register_write (gdbarch, avr_pseudo_register_write); set_gdbarch_return_value (gdbarch, avr_return_value); - set_gdbarch_print_insn (gdbarch, print_insn_avr); set_gdbarch_push_dummy_call (gdbarch, avr_push_dummy_call); @@ -1439,7 +1514,8 @@ avr_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches) set_gdbarch_skip_prologue (gdbarch, avr_skip_prologue); set_gdbarch_inner_than (gdbarch, core_addr_lessthan); - set_gdbarch_breakpoint_from_pc (gdbarch, avr_breakpoint_from_pc); + set_gdbarch_breakpoint_kind_from_pc (gdbarch, avr_breakpoint::kind_from_pc); + set_gdbarch_sw_breakpoint_from_kind (gdbarch, avr_breakpoint::bp_from_kind); frame_unwind_append_unwinder (gdbarch, &avr_frame_unwind); frame_base_set_default (gdbarch, &avr_frame_base); @@ -1449,6 +1525,12 @@ avr_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches) set_gdbarch_unwind_pc (gdbarch, avr_unwind_pc); set_gdbarch_unwind_sp (gdbarch, avr_unwind_sp); + set_gdbarch_address_class_type_flags (gdbarch, avr_address_class_type_flags); + set_gdbarch_address_class_name_to_type_flags + (gdbarch, avr_address_class_name_to_type_flags); + set_gdbarch_address_class_type_flags_to_name + (gdbarch, avr_address_class_type_flags_to_name); + return gdbarch; } @@ -1466,21 +1548,17 @@ avr_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches) All io registers are 8-bit. */ static void -avr_io_reg_read_command (char *args, int from_tty) +avr_io_reg_read_command (const char *args, int from_tty) { - LONGEST bufsiz = 0; - gdb_byte *buf; char query[400]; - char *p; unsigned int nreg = 0; unsigned int val; - int i, j, k, step; /* Find out how many io registers the target has. */ - bufsiz = target_read_alloc (¤t_target, TARGET_OBJECT_AVR, - "avr.io_reg", &buf); + gdb::optional buf + = target_read_alloc (current_top_target (), TARGET_OBJECT_AVR, "avr.io_reg"); - if (bufsiz <= 0) + if (!buf) { fprintf_unfiltered (gdb_stderr, _("ERR: info io_registers NOT supported " @@ -1488,36 +1566,42 @@ avr_io_reg_read_command (char *args, int from_tty) return; } - if (sscanf (buf, "%x", &nreg) != 1) + const char *bufstr = (const char *) buf->data (); + + if (sscanf (bufstr, "%x", &nreg) != 1) { fprintf_unfiltered (gdb_stderr, _("Error fetching number of io registers\n")); - xfree (buf); return; } - xfree (buf); - reinitialize_more_filter (); printf_unfiltered (_("Target has %u io registers:\n\n"), nreg); /* only fetch up to 8 registers at a time to keep the buffer small */ - step = 8; + int step = 8; - for (i = 0; i < nreg; i += step) + for (int i = 0; i < nreg; i += step) { /* how many registers this round? */ - j = step; + int j = step; if ((i+j) >= nreg) j = nreg - i; /* last block is less than 8 registers */ snprintf (query, sizeof (query) - 1, "avr.io_reg:%x,%x", i, j); - bufsiz = target_read_alloc (¤t_target, TARGET_OBJECT_AVR, - query, &buf); + buf = target_read_alloc (current_top_target (), TARGET_OBJECT_AVR, query); + + if (!buf) + { + fprintf_unfiltered (gdb_stderr, + _("ERR: error reading avr.io_reg:%x,%x\n"), + i, j); + return; + } - p = buf; - for (k = i; k < (i + j); k++) + const char *p = (const char *) buf->data (); + for (int k = i; k < (i + j); k++) { if (sscanf (p, "%[^,],%x;", query, &val) == 2) { @@ -1529,13 +1613,9 @@ avr_io_reg_read_command (char *args, int from_tty) break; } } - - xfree (buf); } } -extern initialize_file_ftype _initialize_avr_tdep; /* -Wmissing-prototypes */ - void _initialize_avr_tdep (void) { @@ -1548,7 +1628,6 @@ _initialize_avr_tdep (void) /* FIXME: TRoth/2002-02-18: This should probably be changed to 'info avr io_registers' to signify it is not available on other platforms. */ - add_cmd ("io_registers", class_info, avr_io_reg_read_command, - _("query remote avr target for io space register values"), - &infolist); + add_info ("io_registers", avr_io_reg_read_command, + _("Query remote AVR target for I/O space register values.")); }