X-Git-Url: http://drtracing.org/?a=blobdiff_plain;f=gdb%2Ftilegx-tdep.c;h=9cc2c2c5f558564a06e159f33cdbf392294eba5c;hb=e8b24d9ff5b9419fc079f5fe975fac6f499f8bfb;hp=5d2e3ee4ba0984e834e9dce5427c09291ed282b0;hpb=4aaf25031b9372b24fa813709dd310724696a5bf;p=deliverable%2Fbinutils-gdb.git diff --git a/gdb/tilegx-tdep.c b/gdb/tilegx-tdep.c index 5d2e3ee4ba..9cc2c2c5f5 100644 --- a/gdb/tilegx-tdep.c +++ b/gdb/tilegx-tdep.c @@ -1,6 +1,6 @@ /* Target-dependent code for the Tilera TILE-Gx processor. - Copyright (C) 2012-2013 Free Software Foundation, Inc. + Copyright (C) 2012-2016 Free Software Foundation, Inc. This file is part of GDB. @@ -30,8 +30,6 @@ #include "value.h" #include "dis-asm.h" #include "inferior.h" -#include "gdb_string.h" -#include "gdb_assert.h" #include "arch-utils.h" #include "floatformat.h" #include "regcache.h" @@ -41,9 +39,9 @@ #include "linux-tdep.h" #include "objfiles.h" #include "solib-svr4.h" -#include "symtab.h" #include "tilegx-tdep.h" #include "opcode/tilegx.h" +#include struct tilegx_frame_cache { @@ -291,7 +289,7 @@ tilegx_push_dummy_call (struct gdbarch *gdbarch, CORE_ADDR stack_dest = sp; int argreg = TILEGX_R0_REGNUM; int i, j; - int typelen, slacklen, alignlen; + int typelen, slacklen; static const gdb_byte four_zero_words[16] = { 0 }; /* If struct_return is 1, then the struct return address will @@ -336,7 +334,7 @@ tilegx_push_dummy_call (struct gdbarch *gdbarch, typelen = TYPE_LENGTH (value_enclosing_type (args[j])); slacklen = align_up (typelen, 8) - typelen; - val = xmalloc (typelen + slacklen); + val = (gdb_byte *) xmalloc (typelen + slacklen); back_to = make_cleanup (xfree, val); memcpy (val, contents, typelen); memset (val + typelen, 0, slacklen); @@ -378,9 +376,6 @@ tilegx_analyze_prologue (struct gdbarch* gdbarch, enum bfd_endian byte_order = gdbarch_byte_order (gdbarch); CORE_ADDR next_addr; CORE_ADDR prolog_end = end_addr; - ULONGEST inst, inst2; - LONGEST offset; - int regnum; gdb_byte instbuf[32 * TILEGX_BUNDLE_SIZE_IN_BYTES]; CORE_ADDR instbuf_start; unsigned int instbuf_size; @@ -393,7 +388,7 @@ tilegx_analyze_prologue (struct gdbarch* gdbarch, struct tilegx_reverse_regs new_reverse_frame[TILEGX_MAX_INSTRUCTIONS_PER_BUNDLE]; int dest_regs[TILEGX_MAX_INSTRUCTIONS_PER_BUNDLE]; - int reverse_frame_valid, prolog_done, branch_seen; + int reverse_frame_valid, prolog_done, branch_seen, lr_saved_on_stack_p; LONGEST prev_sp_value; int i, j; @@ -409,6 +404,7 @@ tilegx_analyze_prologue (struct gdbarch* gdbarch, prolog_done = 0; branch_seen = 0; prev_sp_value = 0; + lr_saved_on_stack_p = 0; /* To cut down on round-trip overhead, we fetch multiple bundles at once. These variables describe the range of memory we have @@ -432,12 +428,15 @@ tilegx_analyze_prologue (struct gdbarch* gdbarch, if (instbuf_size > size_on_same_page) instbuf_size = size_on_same_page; + + instbuf_size = std::min ((CORE_ADDR) instbuf_size, + (end_addr - next_addr)); instbuf_start = next_addr; status = safe_frame_unwind_memory (next_frame, instbuf_start, instbuf, instbuf_size); if (status == 0) - memory_error (status, next_addr); + memory_error (TARGET_XFER_E_IO, next_addr); } reverse_frame_valid = 0; @@ -450,7 +449,7 @@ tilegx_analyze_prologue (struct gdbarch* gdbarch, for (i = 0; i < num_insns; i++) { struct tilegx_decoded_instruction *this_insn = &decoded[i]; - int64_t *operands = (int64_t *) this_insn->operand_values; + long long *operands = this_insn->operand_values; const struct tilegx_opcode *opcode = this_insn->opcode; switch (opcode->mnemonic) @@ -472,7 +471,11 @@ tilegx_analyze_prologue (struct gdbarch* gdbarch, See trad-frame.h. */ cache->saved_regs[saved_register].realreg = saved_register; cache->saved_regs[saved_register].addr = saved_address; - } + } + else if (cache + && (operands[0] == TILEGX_SP_REGNUM) + && (operands[1] == TILEGX_LR_REGNUM)) + lr_saved_on_stack_p = 1; break; case TILEGX_OPC_ADDI: case TILEGX_OPC_ADDLI: @@ -725,43 +728,57 @@ tilegx_analyze_prologue (struct gdbarch* gdbarch, } } + if (lr_saved_on_stack_p) + { + cache->saved_regs[TILEGX_LR_REGNUM].realreg = TILEGX_LR_REGNUM; + cache->saved_regs[TILEGX_LR_REGNUM].addr = + cache->saved_regs[TILEGX_SP_REGNUM].addr; + } + return prolog_end; } /* This is the implementation of gdbarch method skip_prologue. */ static CORE_ADDR -tilegx_skip_prologue (struct gdbarch *gdbarch, CORE_ADDR pc) +tilegx_skip_prologue (struct gdbarch *gdbarch, CORE_ADDR start_pc) { - struct symtab_and_line sal; - CORE_ADDR func_start, func_end; + CORE_ADDR func_start, end_pc; + struct obj_section *s; /* This is the preferred method, find the end of the prologue by using the debugging information. */ - if (find_pc_partial_function (pc, NULL, &func_start, &func_end)) + if (find_pc_partial_function (start_pc, NULL, &func_start, NULL)) { - sal = find_pc_line (func_start, 0); + CORE_ADDR post_prologue_pc + = skip_prologue_using_sal (gdbarch, func_start); - if (sal.end < func_end && pc <= sal.end) - return sal.end; + if (post_prologue_pc != 0) + return std::max (start_pc, post_prologue_pc); } + /* Don't straddle a section boundary. */ + s = find_pc_section (start_pc); + end_pc = start_pc + 8 * TILEGX_BUNDLE_SIZE_IN_BYTES; + if (s != NULL) + end_pc = std::min (end_pc, obj_section_endaddr (s)); + /* Otherwise, try to skip prologue the hard way. */ return tilegx_analyze_prologue (gdbarch, - pc, pc + 8 * TILEGX_BUNDLE_SIZE_IN_BYTES, + start_pc, + end_pc, NULL, NULL); } -/* This is the implementation of gdbarch method in_function_epilogue_p. */ +/* This is the implementation of gdbarch method stack_frame_destroyed_p. */ static int -tilegx_in_function_epilogue_p (struct gdbarch *gdbarch, CORE_ADDR pc) +tilegx_stack_frame_destroyed_p (struct gdbarch *gdbarch, CORE_ADDR pc) { CORE_ADDR func_addr = 0, func_end = 0; if (find_pc_partial_function (pc, NULL, &func_addr, &func_end)) { - ULONGEST inst, inst2; CORE_ADDR addr = func_end - TILEGX_BUNDLE_SIZE_IN_BYTES; /* FIXME: Find the actual epilogue. */ @@ -772,6 +789,29 @@ tilegx_in_function_epilogue_p (struct gdbarch *gdbarch, CORE_ADDR pc) return 0; } +/* This is the implementation of gdbarch method get_longjmp_target. */ + +static int +tilegx_get_longjmp_target (struct frame_info *frame, CORE_ADDR *pc) +{ + struct gdbarch *gdbarch = get_frame_arch (frame); + enum bfd_endian byte_order = gdbarch_byte_order (gdbarch); + CORE_ADDR jb_addr; + gdb_byte buf[8]; + + jb_addr = get_frame_register_unsigned (frame, TILEGX_R0_REGNUM); + + /* TileGX jmp_buf contains 32 elements of type __uint_reg_t which + has a size of 8 bytes. The return address is stored in the 25th + slot. */ + if (target_read_memory (jb_addr + 25 * 8, buf, 8)) + return 0; + + *pc = extract_unsigned_integer (buf, 8, byte_order); + + return 1; +} + /* by assigning the 'faultnum' reg in kernel pt_regs with this value, kernel do_signal will not check r0. see tilegx kernel/signal.c for details. */ @@ -802,19 +842,11 @@ tilegx_write_pc (struct regcache *regcache, CORE_ADDR pc) INT_SWINT_1_SIGRETURN); } -/* This is the implementation of gdbarch method breakpoint_from_pc. */ +/* 64-bit pattern for a { bpt ; nop } bundle. */ +constexpr gdb_byte tilegx_break_insn[] = + { 0x00, 0x50, 0x48, 0x51, 0xae, 0x44, 0x6a, 0x28 }; -static const unsigned char * -tilegx_breakpoint_from_pc (struct gdbarch *gdbarch, - CORE_ADDR *pcptr, int *lenptr) -{ - /* 64-bit pattern for a { bpt ; nop } bundle. */ - static const unsigned char breakpoint[] = - { 0x00, 0x50, 0x48, 0x51, 0xae, 0x44, 0x6a, 0x28 }; - - *lenptr = sizeof (breakpoint); - return breakpoint; -} +typedef BP_MANIPULATION (tilegx_break_insn) tilegx_breakpoint; /* Normal frames. */ @@ -824,10 +856,9 @@ tilegx_frame_cache (struct frame_info *this_frame, void **this_cache) struct gdbarch *gdbarch = get_frame_arch (this_frame); struct tilegx_frame_cache *cache; CORE_ADDR current_pc; - int i; if (*this_cache) - return *this_cache; + return (struct tilegx_frame_cache *) *this_cache; cache = FRAME_OBSTACK_ZALLOC (struct tilegx_frame_cache); *this_cache = cache; @@ -839,11 +870,12 @@ tilegx_frame_cache (struct frame_info *this_frame, void **this_cache) cache->base = get_frame_register_unsigned (this_frame, TILEGX_SP_REGNUM); trad_frame_set_value (cache->saved_regs, TILEGX_SP_REGNUM, cache->base); - cache->saved_regs[TILEGX_PC_REGNUM] = cache->saved_regs[TILEGX_LR_REGNUM]; if (cache->start_pc) tilegx_analyze_prologue (gdbarch, cache->start_pc, current_pc, cache, this_frame); + cache->saved_regs[TILEGX_PC_REGNUM] = cache->saved_regs[TILEGX_LR_REGNUM]; + return cache; } @@ -979,7 +1011,6 @@ tilegx_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches) set_gdbarch_register_name (gdbarch, tilegx_register_name); set_gdbarch_register_type (gdbarch, tilegx_register_type); - set_gdbarch_char_signed (gdbarch, 0); set_gdbarch_short_bit (gdbarch, 2 * TARGET_CHAR_BIT); set_gdbarch_int_bit (gdbarch, 4 * TARGET_CHAR_BIT); set_gdbarch_long_bit (gdbarch, arch_size); @@ -1009,16 +1040,19 @@ tilegx_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches) set_gdbarch_skip_prologue (gdbarch, tilegx_skip_prologue); - set_gdbarch_in_function_epilogue_p (gdbarch, - tilegx_in_function_epilogue_p); + set_gdbarch_stack_frame_destroyed_p (gdbarch, tilegx_stack_frame_destroyed_p); /* Map debug registers into internal register numbers. */ set_gdbarch_dwarf2_reg_to_regnum (gdbarch, tilegx_dwarf2_reg_to_regnum); /* These values and methods are used when gdb calls a target function. */ set_gdbarch_push_dummy_call (gdbarch, tilegx_push_dummy_call); + set_gdbarch_get_longjmp_target (gdbarch, tilegx_get_longjmp_target); set_gdbarch_write_pc (gdbarch, tilegx_write_pc); - set_gdbarch_breakpoint_from_pc (gdbarch, tilegx_breakpoint_from_pc); + set_gdbarch_breakpoint_kind_from_pc (gdbarch, + tilegx_breakpoint::kind_from_pc); + set_gdbarch_sw_breakpoint_from_kind (gdbarch, + tilegx_breakpoint::bp_from_kind); set_gdbarch_return_value (gdbarch, tilegx_return_value); set_gdbarch_print_insn (gdbarch, print_insn_tilegx);