X-Git-Url: http://drtracing.org/?a=blobdiff_plain;f=gdb%2Fscore-tdep.c;h=9cd50380e8e7d0f2a911c473478f09b284476520;hb=32b40af94e919e235c21486110311647cbeecf2e;hp=cf22b83d630e41fdb4effd12a2652c8c63842b72;hpb=4c38e0a4fcb69f8586d8db0b9cdb8dbab5980811;p=deliverable%2Fbinutils-gdb.git diff --git a/gdb/score-tdep.c b/gdb/score-tdep.c index cf22b83d63..9cd50380e8 100644 --- a/gdb/score-tdep.c +++ b/gdb/score-tdep.c @@ -1,7 +1,7 @@ /* Target-dependent code for the S+core architecture, for GDB, the GNU Debugger. - Copyright (C) 2006, 2007, 2008, 2009, 2010 Free Software Foundation, Inc. + Copyright (C) 2006-2015 Free Software Foundation, Inc. Contributed by Qinwei (qinwei@sunnorth.com.cn) Contributed by Ching-Peng Lin (cplin@sunplus.com) @@ -22,7 +22,6 @@ along with this program. If not, see . */ #include "defs.h" -#include "gdb_assert.h" #include "inferior.h" #include "symtab.h" #include "objfiles.h" @@ -42,9 +41,9 @@ ((unsigned)((_i) << (31 - (_ms))) >> (31 - (_ms) + (_ls))) typedef struct{ - unsigned long long v; - unsigned long long raw; - unsigned int len; + unsigned long long v; + unsigned long long raw; + unsigned int len; }inst_t; struct score_frame_cache @@ -60,7 +59,8 @@ static struct type * score_register_type (struct gdbarch *gdbarch, int regnum) { gdb_assert (regnum >= 0 - && regnum < ((target_mach == bfd_mach_score7) ? SCORE7_NUM_REGS : SCORE3_NUM_REGS)); + && regnum < ((target_mach == bfd_mach_score7) + ? SCORE7_NUM_REGS : SCORE3_NUM_REGS)); return builtin_type (gdbarch)->builtin_uint32; } @@ -120,7 +120,8 @@ static int score_register_sim_regno (struct gdbarch *gdbarch, int regnum) { gdb_assert (regnum >= 0 - && regnum < ((target_mach == bfd_mach_score7) ? SCORE7_NUM_REGS : SCORE3_NUM_REGS)); + && regnum < ((target_mach == bfd_mach_score7) + ? SCORE7_NUM_REGS : SCORE3_NUM_REGS)); return regnum; } #endif @@ -135,11 +136,11 @@ score_print_insn (bfd_vma memaddr, struct disassemble_info *info) } static inst_t * -score7_fetch_inst (struct gdbarch *gdbarch, CORE_ADDR addr, char *memblock) +score7_fetch_inst (struct gdbarch *gdbarch, CORE_ADDR addr, gdb_byte *memblock) { enum bfd_endian byte_order = gdbarch_byte_order (gdbarch); static inst_t inst = { 0, 0, 0 }; - char buf[SCORE_INSTLEN] = { 0 }; + gdb_byte buf[SCORE_INSTLEN] = { 0 }; int big; int ret; @@ -154,7 +155,7 @@ score7_fetch_inst (struct gdbarch *gdbarch, CORE_ADDR addr, char *memblock) ret = target_read_memory (addr & ~0x3, buf, SCORE_INSTLEN); if (ret) { - error ("Error: target_read_memory in file:%s, line:%d!", + error (_("Error: target_read_memory in file:%s, line:%d!"), __FILE__, __LINE__); return 0; } @@ -219,7 +220,6 @@ score3_adjust_pc_and_fetch_inst (CORE_ADDR *pcptr, int *lenptr, #define EXTRACT_LEN 2 CORE_ADDR adjust_pc = *pcptr & ~0x1; - int inst_len; gdb_byte buf[5][EXTRACT_LEN] = { {'\0', '\0'}, @@ -247,7 +247,7 @@ score3_adjust_pc_and_fetch_inst (CORE_ADDR *pcptr, int *lenptr, buf[i][0] = '\0'; buf[i][1] = '\0'; if (i == 2) - error ("Error: target_read_memory in file:%s, line:%d!", + error (_("Error: target_read_memory in file:%s, line:%d!"), __FILE__, __LINE__); } @@ -317,7 +317,7 @@ score7_breakpoint_from_pc (struct gdbarch *gdbarch, CORE_ADDR *pcptr, if ((ret = target_read_memory (*pcptr & ~0x3, buf, SCORE_INSTLEN)) != 0) { - error ("Error: target_read_memory in file:%s, line:%d!", + error (_("Error: target_read_memory in file:%s, line:%d!"), __FILE__, __LINE__); } raw = extract_unsigned_integer (buf, SCORE_INSTLEN, byte_order); @@ -420,7 +420,8 @@ score_xfer_register (struct regcache *regcache, int regnum, int length, { int reg_offset = 0; gdb_assert (regnum >= 0 - && regnum < ((target_mach == bfd_mach_score7) ? SCORE7_NUM_REGS : SCORE3_NUM_REGS)); + && regnum < ((target_mach == bfd_mach_score7) + ? SCORE7_NUM_REGS : SCORE3_NUM_REGS)); switch (endian) { @@ -434,7 +435,7 @@ score_xfer_register (struct regcache *regcache, int regnum, int length, reg_offset = 0; break; default: - error ("Error: score_xfer_register in file:%s, line:%d!", + error (_("Error: score_xfer_register in file:%s, line:%d!"), __FILE__, __LINE__); } @@ -447,7 +448,7 @@ score_xfer_register (struct regcache *regcache, int regnum, int length, } static enum return_value_convention -score_return_value (struct gdbarch *gdbarch, struct type *func_type, +score_return_value (struct gdbarch *gdbarch, struct value *function, struct type *type, struct regcache *regcache, gdb_byte * readbuf, const gdb_byte * writebuf) { @@ -464,6 +465,7 @@ score_return_value (struct gdbarch *gdbarch, struct type *func_type, offset += SCORE_REGSIZE, regnum++) { int xfer = SCORE_REGSIZE; + if (offset + xfer > TYPE_LENGTH (type)) xfer = TYPE_LENGTH (type) - offset; score_xfer_register (regcache, regnum, xfer, @@ -477,9 +479,9 @@ score_return_value (struct gdbarch *gdbarch, struct type *func_type, static struct frame_id score_dummy_id (struct gdbarch *gdbarch, struct frame_info *this_frame) { - return frame_id_build ( - get_frame_register_unsigned (this_frame, SCORE_SP_REGNUM), - get_frame_pc (this_frame)); + return frame_id_build (get_frame_register_unsigned (this_frame, + SCORE_SP_REGNUM), + get_frame_pc (this_frame)); } static int @@ -686,7 +688,8 @@ score3_skip_prologue (struct gdbarch *gdbarch, CORE_ADDR pc) while (iscan-- > 0) { inst_t *inst - = score3_adjust_pc_and_fetch_inst (&cpc, NULL, gdbarch_byte_order (gdbarch)); + = score3_adjust_pc_and_fetch_inst (&cpc, NULL, + gdbarch_byte_order (gdbarch)); if (!inst) break; @@ -763,7 +766,8 @@ score3_in_function_epilogue_p (struct gdbarch *gdbarch, CORE_ADDR cur_pc) { CORE_ADDR pc = cur_pc; inst_t *inst - = score3_adjust_pc_and_fetch_inst (&pc, NULL, gdbarch_byte_order (gdbarch)); + = score3_adjust_pc_and_fetch_inst (&pc, NULL, + gdbarch_byte_order (gdbarch)); if (inst->len == 2 && (G_FLD (inst->v, 14, 10) == 0x10) @@ -802,27 +806,27 @@ score3_in_function_epilogue_p (struct gdbarch *gdbarch, CORE_ADDR cur_pc) return 0; } -static char * +static gdb_byte * score7_malloc_and_get_memblock (CORE_ADDR addr, CORE_ADDR size) { int ret; - char *memblock = NULL; + gdb_byte *memblock = NULL; if (size < 0) { - error ("Error: malloc size < 0 in file:%s, line:%d!", + error (_("Error: malloc size < 0 in file:%s, line:%d!"), __FILE__, __LINE__); return NULL; } else if (size == 0) return NULL; - memblock = (char *) xmalloc (size); + memblock = xmalloc (size); memset (memblock, 0, size); ret = target_read_memory (addr & ~0x3, memblock, size); if (ret) { - error ("Error: target_read_memory in file:%s, line:%d!", + error (_("Error: target_read_memory in file:%s, line:%d!"), __FILE__, __LINE__); return NULL; } @@ -830,13 +834,13 @@ score7_malloc_and_get_memblock (CORE_ADDR addr, CORE_ADDR size) } static void -score7_free_memblock (char *memblock) +score7_free_memblock (gdb_byte *memblock) { xfree (memblock); } static void -score7_adjust_memblock_ptr (char **memblock, CORE_ADDR prev_pc, +score7_adjust_memblock_ptr (gdb_byte **memblock, CORE_ADDR prev_pc, CORE_ADDR cur_pc) { if (prev_pc == -1) @@ -872,8 +876,8 @@ score7_analyze_prologue (CORE_ADDR startaddr, CORE_ADDR pc, int fp_offset_p = 0; int inst_len = 0; - char *memblock = NULL; - char *memblock_ptr = NULL; + gdb_byte *memblock = NULL; + gdb_byte *memblock_ptr = NULL; CORE_ADDR prev_pc = -1; /* Allocate MEMBLOCK if PC - STARTADDR > 0. */ @@ -900,7 +904,7 @@ score7_analyze_prologue (CORE_ADDR startaddr, CORE_ADDR pc, inst = score7_fetch_inst (gdbarch, cur_pc, NULL); } - /* FIXME: make a full-power prologue analyzer */ + /* FIXME: make a full-power prologue analyzer. */ if (inst->len == 2) { inst_len = SCORE16_INSTLEN; @@ -1070,7 +1074,8 @@ score3_analyze_prologue (CORE_ADDR startaddr, CORE_ADDR pc, CORE_ADDR sp; CORE_ADDR fp; CORE_ADDR cur_pc = startaddr; - enum bfd_endian byte_order = gdbarch_byte_order (get_frame_arch (this_frame)); + enum bfd_endian byte_order + = gdbarch_byte_order (get_frame_arch (this_frame)); int sp_offset = 0; int ra_offset = 0; @@ -1090,7 +1095,7 @@ score3_analyze_prologue (CORE_ADDR startaddr, CORE_ADDR pc, inst = score3_adjust_pc_and_fetch_inst (&cur_pc, &inst_len, byte_order); - /* FIXME: make a full-power prologue analyzer */ + /* FIXME: make a full-power prologue analyzer. */ if (inst->len == 2) { if (G_FLD (inst->v, 14, 12) == 0x0 @@ -1176,7 +1181,8 @@ score3_analyze_prologue (CORE_ADDR startaddr, CORE_ADDR pc, inst_t *inst2; cur_pc += inst->len; - inst2 = score3_adjust_pc_and_fetch_inst (&cur_pc, NULL, byte_order); + inst2 = score3_adjust_pc_and_fetch_inst (&cur_pc, NULL, + byte_order); if (inst2->len == 2 && G_FLD (inst2->v, 14, 10) == 0x10 @@ -1261,7 +1267,8 @@ score3_analyze_prologue (CORE_ADDR startaddr, CORE_ADDR pc, inst_t *inst2; cur_pc += inst->len; - inst2 = score3_adjust_pc_and_fetch_inst (&cur_pc, NULL, byte_order); + inst2 = score3_adjust_pc_and_fetch_inst (&cur_pc, NULL, + byte_order); if (inst2->len == 2 && G_FLD (inst2->v, 14, 10) == 0x10 @@ -1359,6 +1366,7 @@ score_prologue_prev_register (struct frame_info *this_frame, static const struct frame_unwind score_prologue_unwind = { NORMAL_FRAME, + default_frame_unwind_stop_reason, score_prologue_this_id, score_prologue_prev_register, NULL, @@ -1389,83 +1397,70 @@ score_prologue_frame_base_sniffer (struct frame_info *this_frame) return &score_prologue_frame_base; } -/* Core file support (dirty hack) - - The core file MUST be generated by GNU/Linux on S+core */ +/* Core file support. */ + +static const struct regcache_map_entry score7_linux_gregmap[] = + { + /* FIXME: According to the current Linux kernel, r0 is preceded by + 9 rather than 7 words. */ + { 7, REGCACHE_MAP_SKIP, 4 }, + { 32, 0, 4 }, /* r0 ... r31 */ + { 1, 55, 4 }, /* CEL */ + { 1, 54, 4 }, /* CEH */ + { 1, 53, 4 }, /* sr0, i.e. cnt or COUNTER */ + { 1, 52, 4 }, /* sr1, i.e. lcr or LDCR */ + { 1, 51, 4 }, /* sr2, i.e. scr or STCR */ + { 1, 49, 4 }, /* PC (same slot as EPC) */ + { 1, 38, 4 }, /* EMA */ + { 1, 32, 4 }, /* PSR */ + { 1, 34, 4 }, /* ECR */ + { 1, 33, 4 }, /* COND */ + { 0 } + }; + +#define SCORE7_LINUX_EPC_OFFSET (44 * 4) +#define SCORE7_LINUX_SIZEOF_GREGSET (49 * 4) static void score7_linux_supply_gregset(const struct regset *regset, - struct regcache *regcache, - int regnum, const void *gregs_buf, size_t len) + struct regcache *regcache, + int regnum, const void *buf, + size_t size) { - int regno; - elf_gregset_t *gregs; - - gdb_assert (regset != NULL); - gdb_assert ((regcache != NULL) && (gregs_buf != NULL)); - - gregs = (elf_gregset_t *) gregs_buf; - - for (regno = 0; regno < 32; regno++) - if (regnum == -1 || regnum == regno) - regcache_raw_supply (regcache, regno, gregs->regs + regno); - - { - struct sreg { - int regnum; - void *buf; - } sregs [] = { - { 55, &(gregs->cel) }, /* CEL */ - { 54, &(gregs->ceh) }, /* CEH */ - { 53, &(gregs->sr0) }, /* sr0, i.e. cnt or COUNTER */ - { 52, &(gregs->sr1) }, /* sr1, i.e. lcr or LDCR */ - { 51, &(gregs->sr1) }, /* sr2, i.e. scr or STCR */ - - /* Exception occured at this address, exactly the PC we want */ - { 49, &(gregs->cp0_epc) }, /* PC */ - - { 38, &(gregs->cp0_ema) }, /* EMA */ - { 37, &(gregs->cp0_epc) }, /* EPC */ - { 34, &(gregs->cp0_ecr) }, /* ECR */ - { 33, &(gregs->cp0_condition) }, /* COND */ - { 32, &(gregs->cp0_psr) }, /* PSR */ - }; - - for (regno = 0; regno < sizeof(sregs)/sizeof(sregs[0]); regno++) - if (regnum == -1 || regnum == sregs[regno].regnum) - regcache_raw_supply (regcache, sregs[regno].regnum, sregs[regno].buf); - } + regcache_supply_regset (regset, regcache, regnum, buf, size); + + /* Supply the EPC from the same slot as the PC. Note that the + collect function will store the PC in that slot. */ + if ((regnum == -1 || regnum == SCORE_EPC_REGNUM) + && size >= SCORE7_LINUX_EPC_OFFSET + 4) + regcache_raw_supply (regcache, SCORE_EPC_REGNUM, + (const gdb_byte *) buf + + SCORE7_LINUX_EPC_OFFSET); } -/* Return the appropriate register set from the core section identified - by SECT_NAME and SECT_SIZE. */ - -static const struct regset * -score7_linux_regset_from_core_section(struct gdbarch *gdbarch, - const char *sect_name, size_t sect_size) -{ - struct gdbarch_tdep *tdep; - - gdb_assert (gdbarch != NULL); - gdb_assert (sect_name != NULL); - - tdep = gdbarch_tdep (gdbarch); +static const struct regset score7_linux_gregset = + { + score7_linux_gregmap, + score7_linux_supply_gregset, + regcache_collect_regset + }; - if (strcmp(sect_name, ".reg") == 0 && sect_size == sizeof(elf_gregset_t)) - { - if (tdep->gregset == NULL) - tdep->gregset = regset_alloc (gdbarch, score7_linux_supply_gregset, NULL); - return tdep->gregset; - } +/* Iterate over core file register note sections. */ - return NULL; +static void +score7_linux_iterate_over_regset_sections (struct gdbarch *gdbarch, + iterate_over_regset_sections_cb *cb, + void *cb_data, + const struct regcache *regcache) +{ + cb (".reg", SCORE7_LINUX_SIZEOF_GREGSET, &score7_linux_gregset, + NULL, cb_data); } static struct gdbarch * score_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches) { struct gdbarch *gdbarch; - struct gdbarch_tdep *tdep; target_mach = info.bfd_arch_info->mach; arches = gdbarch_list_lookup_by_info (arches, &info); @@ -1473,8 +1468,7 @@ score_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches) { return (arches->gdbarch); } - tdep = xcalloc(1, sizeof(struct gdbarch_tdep)); - gdbarch = gdbarch_alloc (&info, tdep); + gdbarch = gdbarch_alloc (&info, NULL); set_gdbarch_short_bit (gdbarch, 16); set_gdbarch_int_bit (gdbarch, 32); @@ -1486,7 +1480,8 @@ score_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches) #endif set_gdbarch_pc_regnum (gdbarch, SCORE_PC_REGNUM); set_gdbarch_sp_regnum (gdbarch, SCORE_SP_REGNUM); - set_gdbarch_adjust_breakpoint_address (gdbarch, score_adjust_breakpoint_address); + set_gdbarch_adjust_breakpoint_address (gdbarch, + score_adjust_breakpoint_address); set_gdbarch_register_type (gdbarch, score_register_type); set_gdbarch_frame_align (gdbarch, score_frame_align); set_gdbarch_inner_than (gdbarch, core_addr_lessthan); @@ -1499,17 +1494,20 @@ score_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches) case bfd_mach_score7: set_gdbarch_breakpoint_from_pc (gdbarch, score7_breakpoint_from_pc); set_gdbarch_skip_prologue (gdbarch, score7_skip_prologue); - set_gdbarch_in_function_epilogue_p (gdbarch, score7_in_function_epilogue_p); + set_gdbarch_in_function_epilogue_p (gdbarch, + score7_in_function_epilogue_p); set_gdbarch_register_name (gdbarch, score7_register_name); set_gdbarch_num_regs (gdbarch, SCORE7_NUM_REGS); - /* Core file support. */ - set_gdbarch_regset_from_core_section (gdbarch, score7_linux_regset_from_core_section); + /* Core file support. */ + set_gdbarch_iterate_over_regset_sections + (gdbarch, score7_linux_iterate_over_regset_sections); break; case bfd_mach_score3: set_gdbarch_breakpoint_from_pc (gdbarch, score3_breakpoint_from_pc); set_gdbarch_skip_prologue (gdbarch, score3_skip_prologue); - set_gdbarch_in_function_epilogue_p (gdbarch, score3_in_function_epilogue_p); + set_gdbarch_in_function_epilogue_p (gdbarch, + score3_in_function_epilogue_p); set_gdbarch_register_name (gdbarch, score3_register_name); set_gdbarch_num_regs (gdbarch, SCORE3_NUM_REGS); break;