/* Target dependent code for ARC processor family, for GDB, the GNU debugger. Copyright 2005, 2008, 2009 Free Software Foundation, Inc. Contributed by Codito Technologies Pvt. Ltd. (www.codito.com) Authors: Soam Vasani Ramana Radhakrishnan Richard Stuckey This file is part of GDB. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . */ /******************************************************************************/ /* */ /* Outline: */ /* This module provides support for the ARC processor family's target */ /* dependencies. In particular, it has knowledge of the processor ABI. */ /* */ /* See */ /* ARCompact Instruction Set Architecture */ /* Programmer's Reference */ /* (5115-018) */ /* */ /* for a description of ARC processor architecture, and */ /* */ /* System V ABI Supplement */ /* 4093-004 */ /* */ /* for a complete definition of the ABI. */ /* */ /* */ /* Stack Frame Layout: */ /* This shows the layout of the stack frame for the general case of a */ /* function call; a given function might not have a variable number of */ /* arguments or local variables, or might not save any registers, so it */ /* would not have the corresponding frame areas. Additionally, a leaf */ /* function (i.e. one which calls no other functions) does not need to */ /* save the contents of the BLINK register (which holds its return */ /* address), and a function might not have a frame pointer. */ /* */ /* N.B. the stack grows downward, so SP points below FP in memory; SP */ /* always points to the last used word on the stack, not the first */ /* one. */ /* */ /* | | | */ /* | arg word N | | caller's */ /* | : | | frame */ /* | arg word 10 | | */ /* | arg word 9 | | */ /* old SP ---> |-----------------------| -- */ /* | var arg word 8 | | */ /* | : | | */ /* | var arg word P+1 | | */ /* |-----------------------| | */ /* | | | */ /* | callee-saved | | */ /* | registers | | */ /* | | | */ /* |-----------------------| | */ /* | saved blink (*) | | */ /* |-----------------------| | callee's */ /* | saved FP | | frame */ /* FP ---> |-----------------------| | */ /* | | | */ /* | local | | */ /* | variables | | */ /* | | | */ /* | register | | */ /* | spill area | | */ /* | | | */ /* | outgoing args | | */ /* | | | */ /* SP ---> |-----------------------| -- */ /* | | */ /* | unused | */ /* | | */ /* | */ /* | */ /* V */ /* downwards */ /* */ /* The list of arguments to be passed to a function is considered to be a */ /* sequence of N words (as though all the parameters were stored in order */ /* in memory with each parameter occupying an integral number of words). */ /* Words 1 .. 8 are passed in registers 0 .. 7; if the function has more */ /* than 8 words of arguments then words 9 .. N are passed on the stack in */ /* the caller's frame. */ /* */ /* If the function has a variable number of arguments, e.g. it has a form */ /* such as */ /* function(p1, p2, ...); */ /* */ /* and P words are required to hold the values of the named parameters */ /* (which are passed in registers 0 .. P-1), then the remaining 8 - P */ /* words passed in registers P .. 7 are spilled into the top of the frame */ /* so that the anonymous parameter words occupy a continous region. */ /* */ /* (*) if saved. */ /* */ /* Usage: */ /* The module exports a function _initialize_arc_tdep: the call to this */ /* function is generated by the gdb build mechanism, so this function */ /* should not be explicitly called. */ /* */ /* The operations provided by this module are registered with gdb during */ /* initialization; gdb then calls them via function pointers, rather than */ /* by name (this allows gdb to handle multiple target architectures): */ /* */ /* set_gdbarch_XXX (gdbarch, ); */ /* */ /* */ /* Build Configuration: */ /* The ARC gdb may be built in two different configurations, according to */ /* the nature of the target that it is to debug: */ /* */ /* 1) arc-elf32: */ /* for debugging 'bare-metal' builds of user code (i.e. built with */ /* newlib) */ /* */ /* ARC-specific modules: */ /* arc-tdep */ /* arc-elf32-tdep */ /* arc-xiss */ /* arc-jtag */ /* arc-jtag-ops */ /* arc-jtag-actionpoints */ /* arc-gpio */ /* arc-remote-fileio */ /* arc-registers */ /* arc-architecture */ /* arc-board */ /* arc-arguments */ /* arc-memory */ /* arc-inst-tracing */ /* */ /* 2) arc-linux-uclibc: */ /* for deugging user mode Linux applications, via communication to */ /* the remote gdbserver process, running on Linux for ARC700 */ /* */ /* ARC-specific modules: */ /* arc-tdep */ /* arc-linux-tdep */ /* */ /* This module provides operations which are common to both; operations */ /* which are specific to one, or which have different variants in each */ /* configuration, are provided by the other modules. */ /* */ /* */ /* Debug Targets: */ /* The ARC gdb supports a number of debug targets. These are: */ /* */ /* arc-elf32-gdb */ /* built-in simulator 'target sim' */ /* ARCangel 4 h/w emulator 'target arcjtag' */ /* dynamically loaded xISS simulator 'target arcxiss' */ /* separately executing xISS simulator 'target remote' */ /* */ /* arc-linux-uclibc-gdb */ /* gdbserver running on ARC Linux 'target remote' */ /* */ /* It should, in theory, be possible for either debugger to connect to */ /* any remote target which supports the gdb Remote Serial Protocol. */ /* However, any such target MUST agree with the debugger on the register */ /* numbering scheme that is used, as this controls the order of register */ /* contents held in the RSP 'G' (set all registers) packet and the 'g' */ /* (get all registers) response packet, as well as the register numbers */ /* used in the 'P' (set one register) and 'p' (get one register) packets, */ /* and in the 'T' stop reply packet. The schemes used by each debugger */ /* are defined in the arc-elf32-tdep and arc-linux-tdep modules. */ /* */ /******************************************************************************/ /* system header files */ #include #include #include #include /* gdb header files */ #include "defs.h" #include "config.h" #include "arch-utils.h" #include "dis-asm.h" #include "frame.h" #include "frame-unwind.h" #include "inferior.h" #include "regcache.h" #include "reggroups.h" #include "trad-frame.h" #include "dwarf2-frame.h" #include "gdbcore.h" #include "observer.h" #include "osabi.h" #include "gdbcmd.h" #include "block.h" #include "dictionary.h" #include "language.h" #include "demangle.h" #include "objfiles.h" #include "gdb_assert.h" /* ARC header files */ /* N.B. one and only one of ARC_ELF32_TARGET and ARC_LINUX_TARGET must be defined! */ #ifdef ARC_ELF32_TARGET #ifdef ARC_LINUX_TARGET #error ARC build is not correctly configured (both flags set) #else #include "config/arc/tm-embed.h" #endif #else #ifdef ARC_LINUX_TARGET #include "config/arc/tm-linux.h" #else #error ARC build is not correctly configured (no flag set) #endif #endif #include "opcode/arc.h" #include "opcodes/arc-dis.h" #include "opcodes/arc-ext.h" #include "opcodes/arcompact-dis.h" #include "arc-support.h" #include "arc-tdep.h" /* -------------------------------------------------------------------------- */ /* local types */ /* -------------------------------------------------------------------------- */ typedef struct { const char *name; CORE_ADDR address; Boolean is_argument; Boolean is_callee; Boolean is_array; unsigned int size; unsigned int element_size; } LocalVariable; /* The frame unwind cache for the ARC. */ typedef struct { /* BLINK save location offset from previous SP (-ve value). */ int blink_save_offset_from_prev_sp; /* The stack pointer at the time this frame was created; i.e. the caller's stack pointer when this function was called. It is used to identify this frame. */ CORE_ADDR prev_sp; /* The frame base (as held in FP). N.B. this is NOT the address of the lowest word in the frame! */ CORE_ADDR frame_base; /* Change in SP from previous SP (-ve value) - this is computed by scanning the prologue of the function: initially 0, it is updated for each instruction which changes SP (either explicitly by a subtraction from SP or implicitly by a push operation), so at each point in the prologue it gives the difference between the previous SP (i.e. before the function was called) and the current SP at that point; at the end of the prologue it holds the total change in SP, i.e. the size of the frame. */ LONGEST delta_sp; /* Offset of old stack pointer from frame base (+ve value). */ LONGEST old_sp_offset_from_fp; /* Is this a leaf function? */ Boolean is_leaf; /* Is there a frame pointer? */ Boolean uses_fp; /* Offsets for each register in the stack frame. */ struct trad_frame_saved_reg *saved_regs; unsigned int saved_regs_mask; } UnwindCache; /* -------------------------------------------------------------------------- */ /* local data */ /* -------------------------------------------------------------------------- */ #define DEBUG_COMMAND "arc-debug" #define SHOW_FRAME_COMMAND "arc-show-frame" #define SHOW_FRAME_COMMAND_USAGE "Usage: " SHOW_FRAME_COMMAND " [ ]\n" #define NEW_LINE _("\n") /* -------------------------------------------------------------------------- */ /* externally visible data */ /* -------------------------------------------------------------------------- */ /* Global debug flag. */ Boolean arc_debug_target; /* -------------------------------------------------------------------------- */ /* local macros */ /* -------------------------------------------------------------------------- */ #define WORD_ALIGNED(addr) ((addr) & ~(BYTES_IN_WORD - 1)) #define WORDS_OCCUPIED(bytes) (((bytes) + BYTES_IN_WORD - 1) / BYTES_IN_WORD) #define ROUND_UP_TO_WORDS(bytes) (WORDS_OCCUPIED(bytes) * BYTES_IN_WORD) /* Macros to be used with disassembling the prologue and update the frame info. The *FI macros are to update the frame info and the ACT macros are to actually do the action on a corresponding match. */ #define IS_INSTRUCTION(insn_name, search_string) !strcmp(insn_name, search_string) #define CHECK_OPERAND_STRING_AND_ACT(target_check, search_string, action) \ if (strstr(target_check, search_string) == target_check) \ { \ action; \ return TRUE; \ } /* The frame info changes by changing the decrementing the delta_sp and setting the leaf function flag to be False (if this function prologue is saving blink then it must be going to call another function - so it can not be a leaf!); also the offset of the blink register save location from the previous value of sp is recorded. This will eventually used to compute the address of the save location: = + The addition (+=) below is because the sp offset and the instruction offset are negative - so incrementing the sp offset by the instruction offset is actually making the sp offset more negative, correctly reflecting that SP is moving further down the downwards-growing stack. */ #define PUSH_BLINK(offset) \ { \ info->delta_sp += offset; \ info->blink_save_offset_from_prev_sp = (int) info->delta_sp; \ info->is_leaf = FALSE; \ } #define PUSH_BLINK_ACT \ do { \ if (info) PUSH_BLINK(instr->_offset) \ } while (0); #define IS_PUSH_BLINK_FI(state) CHECK_OPERAND_STRING_AND_ACT(state->operandBuffer, "blink", PUSH_BLINK_ACT) /* At the point that that FP is pushed onto the stack (so saving the dynamic link chain pointer to the previous frame), at the address that will be the base of the new frame, we know the offset of SP from the previous SP - so the offset of the old SP from the new frame base is known (the -ve delta_sp is negated to give the +ve old_sp_offset_from_fp). */ #define PUSH_FP_ACT do { \ if (info) \ { \ info->delta_sp += instr->_offset; \ info->old_sp_offset_from_fp = -info->delta_sp; \ }} while (0); #define IS_PUSH_FP_FI(state) CHECK_OPERAND_STRING_AND_ACT(state->operandBuffer, "fp", PUSH_FP_ACT) #define UPDATE_FP_ACT do { \ if (info) \ info->uses_fp = TRUE; \ } while (0); #define IS_UPDATE_FP_FI(state) \ if (IS_INSTRUCTION(state->instrBuffer, "mov")) \ { \ CHECK_OPERAND_STRING_AND_ACT(state->operandBuffer, "fp,sp", UPDATE_FP_ACT); \ } #define UPDATE_STACK_SPACE(state) do { \ if (info) { \ /* Eat up sp,sp. */ \ int immediate = atoi(state->operandBuffer + 6); \ info->delta_sp -= immediate; \ }} while (0); #define IS_SUB_SP_FI(state) \ if (IS_INSTRUCTION(state->instrBuffer, "sub") || \ IS_INSTRUCTION(state->instrBuffer, "sub_s")) \ { \ CHECK_OPERAND_STRING_AND_ACT(state->operandBuffer, "sp,sp", UPDATE_STACK_SPACE(state)) \ } /* -------------------------------------------------------------------------- */ /* forward declarations */ /* -------------------------------------------------------------------------- */ static CORE_ADDR scan_prologue (CORE_ADDR entrypoint, struct frame_info *next_frame, UnwindCache *info); /* -------------------------------------------------------------------------- */ /* local debug functions */ /* -------------------------------------------------------------------------- */ /* Print information for a frame. */ static void printFrameInfo (const char *message, UnwindCache *info, Boolean addresses_known) { unsigned int i; DEBUG("-------------------\n"); DEBUG("%s (info = %p)\n", message, info); DEBUG("prev_sp = %lx\n", (long unsigned int) info->prev_sp); DEBUG("frame_base = %lx\n", (long unsigned int) info->frame_base); DEBUG("blink offset = %d\n", info->blink_save_offset_from_prev_sp); DEBUG("delta_sp = %d\n", (int) info->delta_sp); DEBUG("old_sp_offset_from_fp = %d\n", (int) info->old_sp_offset_from_fp); DEBUG("is_leaf = %d, uses_fp = %d\n", info->is_leaf, info->uses_fp); for (i = ARC_ABI_FIRST_CALLEE_SAVED_REGISTER; i < ARC_ABI_LAST_CALLEE_SAVED_REGISTER; i++) { if (info->saved_regs_mask & (1 << i)) DEBUG("saved register R%02d %s 0x%lx\n", i, (addresses_known) ? "address" : "offset", (unsigned long) info->saved_regs[i].addr); } DEBUG("-------------------\n"); } static const char* ARC_Debugger_OperandType_Image (enum ARC_Debugger_OperandType value) { switch (value) { case ARC_LIMM : return "LIMM"; case ARC_SHIMM : return "SHIMM"; case ARC_REGISTER : return "REGISTER"; case ARCOMPACT_REGISTER: return "COMPACT REGISTER"; case ARC_UNDEFINED : return "UNDEFINED"; } return "?"; } /* Print the instruction state returned by the disassembler. Used for internal debugging only. */ static void printInsnState (struct arcDisState state) { DEBUG("---------------------------------\n"); DEBUG("Instruction Length %d\n", state.instructionLen); DEBUG("Opcode [0x%x] : Cond [%x]\n", state._opcode, state._cond); DEBUG("Words 1 [%lx] : 2 [%lx]\n", state.words[0], state.words[1]); DEBUG("Ea present [%x] : memload [%x]\n", state._ea_present, state._mem_load); DEBUG("Load Length [%d]:\n", state._load_len); DEBUG("Address Writeback [%d]\n", state._addrWriteBack); DEBUG("EA reg1 is [%x] offset [%x]\n", state.ea_reg1, state._offset); DEBUG("EA reg2 is [%x]\n", state.ea_reg2); DEBUG("Instr buffer is %s\n", state.instrBuffer); DEBUG("Operand buffer is %s\n", state.operandBuffer); DEBUG("SourceType is %s\n", ARC_Debugger_OperandType_Image(state.sourceType)); DEBUG("Source operand is %u\n", state.source_operand.registerNum); /* All fields of the union have same type. */ DEBUG("Flow is %d\n", state.flow); DEBUG("Branch is %d\n", state.isBranch); DEBUG("---------------------------------\n"); } /* -------------------------------------------------------------------------- */ /* local functions for the disassembler */ /* -------------------------------------------------------------------------- */ /* Wrapper for the target_read_memory function. */ static int read_memory_for_disassembler (bfd_vma memaddr, bfd_byte *myaddr, unsigned int length, struct disassemble_info *info) // unused { return target_read_memory((CORE_ADDR) memaddr, (gdb_byte*) myaddr, (int) length); } /* This is a callback function which gets called by gdb whenever the current object file changes. */ static void set_disassembler (struct objfile *objfile) { if (objfile) { /* The ARC libopcodes wants obfd so that it can find out what CPU extensions are defined in the file. */ set_gdbarch_print_insn(current_gdbarch, arcompact_get_disassembler(objfile->obfd)); // dump_ARC_extmap(); } } /* This function is supplied to gdb as the disassembler until such time as we do have a disassembler available. */ static int dummy_disassembler (bfd_vma address, disassemble_info *info) { error(_("No disassembly operation yet available (no executable file loaded)")); return 0; } /* -------------------------------------------------------------------------- */ /* local functions for decoding call chains */ /* -------------------------------------------------------------------------- */ /* Simple utility function to create a new frame cache structure. */ static UnwindCache* create_cache (struct frame_info *next_frame) { UnwindCache *cache = FRAME_OBSTACK_ZALLOC (UnwindCache); /* Zero all fields. */ cache->blink_save_offset_from_prev_sp = 0; cache->prev_sp = 0; cache->frame_base = 0; cache->delta_sp = 0; cache->old_sp_offset_from_fp = 0; cache->is_leaf = FALSE; cache->uses_fp = FALSE; /* Allocate space for saved register info. */ cache->saved_regs = trad_frame_alloc_saved_regs (next_frame); return cache; } /* Compute the previous frame's stack pointer (which is also the frame's ID's stack address), and this frame's base pointer. */ static void find_previous_stack_pointer (UnwindCache *info, struct frame_info *next_frame) { ENTERARGS("next_frame = %p", next_frame); /* If the frame has a frame pointer. */ if (info->uses_fp) { ULONGEST this_base; unsigned int i; /* The SP was moved to the FP. This indicates that a new frame was created. Get THIS frame's FP value by unwinding it from the next frame. The old contents of FP were saved in the location at the base of this frame, so this also gives us the address of the FP save location. */ this_base = frame_unwind_register_unsigned(next_frame, ARC_FP_REGNUM); info->frame_base = (CORE_ADDR) this_base; info->saved_regs[ARC_FP_REGNUM].addr = (long long) this_base; /* The previous SP is the current frame base + the difference between that frame base and the previous SP. */ info->prev_sp = info->frame_base + (CORE_ADDR) info->old_sp_offset_from_fp; for (i = ARC_ABI_FIRST_CALLEE_SAVED_REGISTER; i < ARC_ABI_LAST_CALLEE_SAVED_REGISTER; i++) { /* If this register has been saved, add the previous stack pointer to the offset from the previous stack pointer at which the register was saved, so giving the address at which it was saved. */ if (info->saved_regs_mask & (1 << i)) { info->saved_regs[i].addr += info->prev_sp; #ifdef DUMP_SAVED_REGISTERS /* This is a really useful debugging aid: we can debug a test program which loads known values into the callee-saved registers, then calls another function which uses those registers (and hence must save them) then hits a breakpoint; traversing the stack chain (e.g. with the 'where' command) should then execute this code, and we should see those known values being dumped, so showing that we have got the right addresses for the save locations! */ { unsigned int contents; DEBUG("saved R%02d is at 0x%lx\n", i, (long unsigned int) info->saved_regs[i].addr); if (target_read_memory((CORE_ADDR) info->saved_regs[i].addr, (gdb_byte*) &contents, BYTES_IN_REGISTER) == 0) { DEBUG("saved R%02d contents: 0x%0x\n", i, contents); } } #endif } } } else { ULONGEST this_sp; /* Get the stack pointer for this frame by getting the saved SP from the next frame. */ this_sp = frame_unwind_register_unsigned (next_frame, ARC_SP_REGNUM); /* The previous SP is this frame's SP plus the known difference between the previous SP and this frame's SP (the delta_sp is negated as it is a negative quantity). */ info->prev_sp = (CORE_ADDR) (this_sp + (ULONGEST) (-info->delta_sp)); /* Assume that the FP is this frame's SP. */ info->frame_base = (CORE_ADDR) this_sp; } /* If the function owning this frame is not a leaf function. */ if (!info->is_leaf) { /* Usually blink is saved above the callee save registers and below the space created for variable arguments. The quantity info->blink_save_offset_from_prev_sp is negative, so adding it to the the previous SP gives the address of a location further down the stack from that SP. */ info->saved_regs[ARC_BLINK_REGNUM].addr = (LONGEST) (info->prev_sp + info->blink_save_offset_from_prev_sp); } } /* The workhorse : frame_unwind_cache for the ARC700 target. */ static UnwindCache * frame_unwind_cache (struct frame_info *next_frame, void **this_prologue_cache) { ENTERMSG; if ((*this_prologue_cache) == NULL) { CORE_ADDR entrypoint = frame_func_unwind(next_frame, NORMAL_FRAME); UnwindCache *cache = create_cache(next_frame); /* Return the newly-created cache. */ *this_prologue_cache = cache; /* Prologue analysis does the rest... */ /* Currently our scan prologue does not support getting input for the frame unwinder. */ (void) scan_prologue(entrypoint, next_frame, cache); } return *this_prologue_cache; } /* -------------------------------------------------------------------------- */ /* local functions for decoding function prologues */ /* -------------------------------------------------------------------------- */ /* This function determines whether the given register, which is being saved by a function prologue on the stack at a known offset from the current SP, is a callee-saved register. If it is, the information in the frame unwind cache is updated. */ static Boolean is_callee_saved_register (unsigned int reg, int offset, UnwindCache * info) { if (ARC_ABI_FIRST_CALLEE_SAVED_REGISTER <= reg && reg <= ARC_ABI_LAST_CALLEE_SAVED_REGISTER) { DEBUG("register R%02u saved\n", reg); if (info) { /* We can not determine the address of the location in the stack frame in which the register was saved, as we do not (yet) know the frame or stack pointers for the frame; so the most we can do is to record the offset from the old SP of that location, which we can compute as we know the offset of SP from the old SP, and the offset of the location from SP (which is the offset in the store instruction). N.B. the stack grows downward, so the store offset is positive, but the delta-SP is negative, so the save offset is also negative. | | old sp ------> |------------| / | | \ : | | : : | | : -ve : | | : save offset : |------------| : -ve : | save loc | / delta sp : |------------| <--- store address : / | | : +ve : | | : store : | | : offset : | | \ \ | | sp' ---------> | | | | | | |------------| <---- frame base | | | | | | | | | | V downwards where sp' is the stack pointer at the current point in the code */ info->saved_regs[reg].addr = info->delta_sp + offset; /* We now know that this register has been saved, so set the corresponding bit in the save mask. */ info->saved_regs_mask |= (1 << reg); printFrameInfo("after callee register save", info, FALSE); return TRUE; } } return FALSE; } /* This function determines whether the given disassembled instruction may be part of a function prologue. If it is, the information in the frame unwind cache may be updated. */ static Boolean is_in_prologue (UnwindCache *info, struct arcDisState *instr) { /* Might be a push or a pop */ if (instr->_opcode == 0x3) { if (instr->_addrWriteBack != (char) 0) { /* This is a st.a instruction. */ if (instr->ea_reg1 == ARC_ABI_STACK_POINTER) { if (instr->_offset == -4) { /* This is a push something at SP. */ /* Is it a push of the blink? */ IS_PUSH_BLINK_FI(instr); /* Is it a push for fp? */ IS_PUSH_FP_FI(instr); } else { if (instr->sourceType == ARC_REGISTER ) { /* st.a , [sp,] */ if (is_callee_saved_register(instr->source_operand.registerNum, instr->_offset, info)) { /* This is a push onto the stack, so change delta_sp. */ info->delta_sp += instr->_offset; return TRUE; } } } } } else { if (instr->sourceType == ARC_REGISTER ) { /* Is this a store of some register onto the stack using the stack pointer? */ if (instr->ea_reg1 == ARC_ABI_STACK_POINTER) { /* st , [sp,offset] */ if (is_callee_saved_register(instr->source_operand.registerNum, instr->_offset, info)) /* This is NOT a push onto the stack, so do not change delta_sp. */ return TRUE; } /* Is this the store of some register on the stack using the frame pointer? We check for argument registers getting saved and restored. */ if (instr->ea_reg1 == ARC_ABI_FRAME_POINTER) { if (IS_ARGUMENT_REGISTER(instr->source_operand.registerNum)) { /* Saving argument registers. Don't set the bits in the saved mask, just skip. */ return TRUE; } } } } } else if (instr->_opcode == 0x4) { /* A major opcode 0x4 instruction. */ /* We are usually interested in a mov or a sub. */ IS_UPDATE_FP_FI(instr); IS_SUB_SP_FI(instr); } else if (instr->_opcode == 0x18) { /* sub_s sp,sp,constant */ IS_SUB_SP_FI(instr); /* push_s blink */ if (strcmp(instr->instrBuffer, "push_s") == 0) { if (strcmp(instr->operandBuffer, "blink") == 0) { if (info) { /* SP is decremented by the push_s instruction (before it stores blink at the stack location addressed by SP). */ PUSH_BLINK(-BYTES_IN_REGISTER) } return TRUE; } } else if (strcmp(instr->instrBuffer, "st_s") == 0) { unsigned int reg; int offset; if (sscanf(instr->operandBuffer, "r%u,[sp,%d]", ®, &offset) == 2) { /* st_s ,[sp,] */ if (is_callee_saved_register(reg, offset, info)) /* This is NOT a push onto the stack, so do not change delta_sp. */ return TRUE; } } } return FALSE; } /* Scan the prologue and update the corresponding frame cache for the frame unwinder for unwinding frames without debug info. In such a situation GDB attempts to parse the prologue for this purpose. This currently would attempt to parse the prologue generated by our gcc 2.95 compiler (we should support Metaware generated binaries at some suitable point of time). This function is called with: entrypoint : the address of the functon entry point next_frame : the next frame to be filled in (if need be) info : the existing cached info. Returns: the address of the first instruction after the prologue. This function is called by our unwinder as well as from arc_skip_prologue in the case that it cannot detect the end of the prologue. 'next_frame' and 'info' are NULL if this function is called from arc_skip_prologue in an attempt to discover the end of the prologue. In this case we don't fill in the 'info' structure that is passed in. TODOs: 1. Support 32 bit normal frames generated by GCC 2.95 2. Support 16 and 32 bit mixed frames generated by GCC 2.95 3. Support 32 bit normal variadic function frames by GCC 2.95 4. Support 32 bit normal frames from GCC 3.4.x with variadic args 5. Support 16 and 32 bit normal frames from GCC 3.4.x with variadic args 6. Support 16 and 32 bit mixed frames generated by GCC 3.4.x 7. Support Metaware generated prologues (The difference is in the use of thunks to identify the saving and restoring of callee saves: may have to do some hackery even in next_pc, since the call is going to create its own set of problems with our stack setup). We attempt to use the disassembler interface from the opcodes library to do our disassembling. The usual 32 bit normal gcc -O0 prologue looks like this: Complete Prologue for all GCC frames (Cases #1 to #6 in TODOs above): sub sp, sp, limm ; space for variadic arguments st.a blink, [sp,-4] ; push blink (if not a leaf function) - decrements sp sub sp, sp , limm ; (optional space creation for callee saves) st r13, [sp] ; push of first callee saved register st r14, [sp,4] ; push of next callee saved register ... st.a fp , [sp,-4] ; push fp (if fp has to be saved) - decrements sp mov fp , sp ; set the current frame up correctly sub sp , sp , #immediate ; create space for local vars on the stack */ /* 3 instructions before and after callee saves, and max number of saves; assume each is 4-byte inst. */ #define MAX_PROLOGUE_LENGTH ((6 + (ARC_ABI_LAST_CALLEE_SAVED_REGISTER - ARC_ABI_FIRST_CALLEE_SAVED_REGISTER + 1)) * 4) static CORE_ADDR scan_prologue (CORE_ADDR entrypoint, struct frame_info *next_frame, UnwindCache *info) { ENTERARGS("next_frame = %p, info = %p", next_frame, info); { /* Will be set to end of prologue. */ CORE_ADDR prologue_ends_pc = entrypoint; struct disassemble_info di; /* An arbitrary limit on the length of the prologue. If next_frame is NULL this means that there was no debug info and we are called from arc_skip_prologue; otherwise, if we know the frame, we can find the pc within the function. N.B. that pc will usually be after the end of the prologue, but it could actually be within the prologue (i.e. execution has halted within the prologue, e.g. at a breakpoint); in that case, do NOT go beyond that pc, as the instructions at the pc and after have not been executed yet, so have had no effect! */ CORE_ADDR final_pc = (next_frame) ? frame_pc_unwind(next_frame) : entrypoint + MAX_PROLOGUE_LENGTH; if (info) { /* Assume that the function is a leaf function until we find out that it is not (i.e. when we find the 'push blink' instruction in the prologue). */ info->is_leaf = TRUE; /* No registers known to be saved, as yet. */ info->saved_regs_mask = 0; } /* Initializations to use the opcodes library. */ arc_initialize_disassembler(&di); DEBUG("Prologue PC: %lx\n", (unsigned long) prologue_ends_pc); DEBUG("Final PC: %lx\n", (unsigned long) final_pc); /* Look at each instruction in the prologue. */ while (prologue_ends_pc < final_pc) { struct arcDisState current_instr = arcAnalyzeInstr(prologue_ends_pc, &di); printInsnState(current_instr); /* If this instruction is in the prologue, fields in the info will be updated, and the saved registers mask may be updated. */ if (!is_in_prologue(info, ¤t_instr)) { /* Found a instruction that is not in the prologue. */ DEBUG("End of Prologue reached \n"); break; } prologue_ends_pc += current_instr.instructionLen; } /* Means we were not called from arc_skip_prologue. */ if (!((next_frame == NULL) && (info == NULL))) { printFrameInfo("after prologue", info, FALSE); find_previous_stack_pointer(info, next_frame); /* The PC is found in blink (the actual register or located on the stack). */ info->saved_regs[ARC_PC_REGNUM] = info->saved_regs[ARC_BLINK_REGNUM]; printFrameInfo("after previous SP found", info, TRUE); } return prologue_ends_pc; } } /* -------------------------------------------------------------------------- */ /* local functions for handling function return values */ /* -------------------------------------------------------------------------- */ /* This function gets the return value of a function from the registers used to return it, according to the convention used by the ABI. Parameters: type : the information for the return type of the function regcache : the register cache holding the register contents valbuf : a buffer to be filled with the return value */ static void extract_return_value (struct type *type, struct regcache *regcache, gdb_byte *valbuf) { unsigned int len = TYPE_LENGTH (type); ENTERMSG; if (len <= BYTES_IN_REGISTER) { ULONGEST val; /* Get the return value from one register. */ regcache_cooked_read_unsigned (regcache, ARC_ABI_RETURN_REGNUM, &val); store_unsigned_integer (valbuf, (int) len, val); DEBUG("returning 0x%08lX\n", (unsigned long) val); } else if (len <= BYTES_IN_REGISTER * 2) { ULONGEST low, high; /* Get the return value from two registers. */ regcache_cooked_read_unsigned (regcache, ARC_ABI_RETURN_LOW_REGNUM, &low); regcache_cooked_read_unsigned (regcache, ARC_ABI_RETURN_HIGH_REGNUM, &high); store_unsigned_integer (valbuf, BYTES_IN_REGISTER, low); store_unsigned_integer (valbuf + BYTES_IN_REGISTER, (int) len - BYTES_IN_REGISTER, high); DEBUG("returning 0x%08lX%08lX\n", (unsigned long) high, (unsigned long) low); } else error(_("%s: type length %u too large"), __FUNCTION__, len); } /* This function loads the return value of a function into the registers used to return it, according to the convention used by the ABI. Parameters: type : the information for the return type of the function regcache : the register cache holding the register contents valbuf : a buffer holding the return value */ static void store_return_value (struct type *type, struct regcache *regcache, const gdb_byte *valbuf) { unsigned int len = TYPE_LENGTH (type); ENTERMSG; if (len <= BYTES_IN_REGISTER) { ULONGEST val; /* Put the return value into one register. */ val = extract_unsigned_integer (valbuf, (int) len); regcache_cooked_write_unsigned (regcache, ARC_ABI_RETURN_REGNUM, val); DEBUG("storing 0x%08lX\n", (unsigned long) val); } else if (len <= BYTES_IN_REGISTER * 2) { ULONGEST low, high; /* Put the return value into two registers. */ low = extract_unsigned_integer (valbuf, BYTES_IN_REGISTER); high = extract_unsigned_integer (valbuf + BYTES_IN_REGISTER, (int) len - BYTES_IN_REGISTER); regcache_cooked_write_unsigned (regcache, ARC_ABI_RETURN_LOW_REGNUM, low); regcache_cooked_write_unsigned (regcache, ARC_ABI_RETURN_HIGH_REGNUM, high); DEBUG("storing 0x%08lX%08lX\n", (unsigned long) high, (unsigned long) low); } else error(_("arc_store_return_value: type length too large.")); } /* -------------------------------------------------------------------------- */ /* local functions for handling the stack frame */ /* -------------------------------------------------------------------------- */ /* This is copied from file stack.c in the gdb sources. It identifies a frame from information (such as frame number) given by the user (in the frame_exp parameter). */ static struct frame_info* parse_frame_specification_1 (const char *frame_exp, const char *message, int *selected_frame_p) { int numargs = 0; struct value *args[4]; CORE_ADDR addrs[ARRAY_SIZE (args)]; if (frame_exp) { while (TRUE) { char *addr_string; struct cleanup *cleanup; const char *p; /* Skip leading white space. */ while (isspace (*frame_exp)) frame_exp++; if (*frame_exp == '\0') break; /* Parse the argument, extract it, save it. */ for (p = frame_exp; (*p != '\0') && !isspace (*p); p++); addr_string = savestring (frame_exp, (size_t) (p - frame_exp)); frame_exp = p; cleanup = make_cleanup (xfree, addr_string); /* NOTE: Parse and evaluate expression, but do not use functions such as parse_and_eval_long or parse_and_eval_address to also extract the value. Instead value_as_long and value_as_address are used. This avoids problems with expressions that contain side-effects. */ if (numargs >= (int) ARRAY_SIZE (args)) error (_("Too many args in frame specification")); args[numargs++] = parse_and_eval (addr_string); do_cleanups (cleanup); } } /* If no args, default to the selected frame. */ if (numargs == 0) { if (selected_frame_p != NULL) (*selected_frame_p) = 1; return get_selected_frame (message); } /* None of the remaining use the selected frame. */ if (selected_frame_p != NULL) (*selected_frame_p) = 0; /* Assume the single arg[0] is an integer, and try using that to select a frame relative to current. */ if (numargs == 1) { int level = (int) value_as_long (args[0]); struct frame_info *fid = find_relative_frame (get_current_frame (), &level); if (level == 0) /* find_relative_frame was successful. */ return fid; } /* Convert each value into a corresponding address. */ { int i; for (i = 0; i < numargs; i++) addrs[i] = value_as_address (args[i]); } /* Assume that the single arg[0] is an address, use that to identify a frame with a matching ID. Should this also accept stack/pc or stack/pc/special. */ if (numargs == 1) { struct frame_id id = frame_id_build_wild (addrs[0]); struct frame_info *fid; /* If (s)he specifies the frame with an address, he deserves what (s)he gets. Still, give the highest one that matches. (NOTE: cagney/2004-10-29: Why highest, or outer-most, I don't know). */ for (fid = get_current_frame (); fid != NULL; fid = get_prev_frame (fid)) { if (frame_id_eq (id, get_frame_id (fid))) { while (frame_id_eq (id, frame_unwind_id (fid))) fid = get_prev_frame (fid); return fid; } } } /* We couldn't identify the frame as an existing frame, but perhaps we can create one with a single argument. */ if (numargs == 1) return create_new_frame (addrs[0], 0); else if (numargs == 2) return create_new_frame (addrs[0], addrs[1]); else error (_("Too many args in frame specification")); } /* Return an array (and count) of the local variables and parameters declared in the function which owns the given frame. Parameters: frame : the frame information for the function variables: a pointer to an existing array of variable information (may be NULL) count : (IN/OUT) the total number of variables found callee : TRUE if the function is a callee of another function Result: A pointer to an array containing one element for each parameter, and, if 'callee' is FALSE, each local variable, of the function. */ static LocalVariable* find_variables (struct frame_info *frame, LocalVariable *variables, unsigned int *count, Boolean callee) { struct block *block = get_frame_block (frame, 0); unsigned int vars = *count; while (block) { struct dict_iterator iter; struct symbol *sym; ALL_BLOCK_SYMBOLS (block, iter, sym) { Boolean is_arg = (SYMBOL_CLASS(sym) == LOC_COMPUTED_ARG); CORE_ADDR addr; switch (SYMBOL_CLASS (sym)) { case LOC_COMPUTED: case LOC_COMPUTED_ARG: addr = SYMBOL_OPS (sym)->get_variable_address(sym, frame); /* For callees, we are only interested in the arguments. */ if ((addr != 0) && (!callee || is_arg)) { struct type *type = SYMBOL_TYPE (sym); vars++; variables = xrealloc(variables, sizeof(LocalVariable) * vars); if (variables) { LocalVariable *var = &variables[vars - 1]; var->name = SYMBOL_PRINT_NAME (sym); var->address = addr; var->is_callee = callee; var->is_argument = is_arg; var->is_array = (TYPE_CODE (type) == TYPE_CODE_ARRAY); var->size = SYMBOL_OPS (sym)->get_variable_size(sym, frame); if (var->is_array) var->element_size = TYPE_LENGTH (TYPE_TARGET_TYPE (type)); } else { *count = 0; return NULL; } } break; default: /* Ignore symbols which are not locals. */ break; } } /* After handling the function's top-level block, stop. Don't continue to its superblock, the block of per-file symbols. */ if (BLOCK_FUNCTION (block)) break; block = BLOCK_SUPERBLOCK (block); } *count = vars; return variables; } /* Return an array (and count) of the local variables declared in the function which owns the given frame, and also those declared in the function which is the callee (if any) of that function in the current call chain. */ static LocalVariable* find_local_variables (struct frame_info *frame, unsigned int *count) { struct frame_info *callee = get_next_frame(frame); LocalVariable *variables; *count = 0; variables = find_variables(frame, NULL, count, FALSE); if (callee) variables = find_variables(callee, variables, count, TRUE); return variables; } /* Try to add the name of a local variable or function parameter to a line of output, if a given address lies within the range of locations occupied by that data item. Parameters: line : the line in which any output is to be placed location : the address of a location on the stack variables : an array of local variables and parameters num_variables : the number of elements in the array is_following_element : set to TRUE if the location lies within an array element, and it is not the 0th element elements_are_word_sized: set to TRUE if the array element is word-sized Returns TRUE if the given location holds a local variable or parameter (i.e. information has been added to the line of output). */ static Boolean add_local_name (char *line, CORE_ADDR location, LocalVariable *variables, unsigned int num_variables, Boolean *is_following_element, Boolean *elements_are_word_sized) { unsigned int i; *is_following_element = FALSE; *elements_are_word_sized = FALSE; /* Look at each of the local variables / parameters in the array. */ for (i = 0; i < num_variables; i++) { LocalVariable *var = &variables[i]; int index = -1; /* is the variable an array? */ if (var->is_array) { /* If we know the size of the array, and the size of its elements. */ if (var->size > 0 && var->element_size > 0) { /* What is the offset of the given stack location from the start of the array? */ int offset = (int) ((long int) location - (long int) var->address); /* Does that offset actually lie within the array? */ if (0 <= offset && offset < (int) var->size) { /* Compute the index of the array element which contains the location. */ index = offset / var->element_size; } if (var->element_size == BYTES_IN_WORD) *elements_are_word_sized = FALSE; } } /* If the variable starts in the given location, or the variable is an array and one of its elements contains the location. */ if (var->address == location || index >= 0) { int n; /* What is the variable? */ if (var->is_callee) n = sprintf(line, _("callee parameter")); else if (var->is_argument) n = sprintf(line, _("parameter")); else n = sprintf(line, _("local variable")); line[n] = ' '; n++; n += sprintf(line + n, _("'%s'"), var->name); line[n] = ' '; /* If it is an array element. */ if (index >= 0) { /* Add the array element index to the output. */ (void) sprintf(line + n, _("[%u]"), index); /* Is it an element which follows another element? */ *is_following_element = (index > 0); } else if (var->size > BYTES_IN_WORD) { /* It occupies more than one word. */ (void) sprintf(line + n + 1, _("(%u words)"), WORDS_OCCUPIED(var->size)); } return TRUE; } } return FALSE; } /* Try to identify the given frame, and output that identification. */ static void identify_frame (struct frame_info *frame) { enum language func_lang = language_unknown; char *func_name = NULL; char *demangled = NULL; struct symbol *func; struct symtab_and_line sal; find_frame_sal (frame, &sal); func = get_frame_function (frame); /* Have we found the function owning the frame? */ if (func) { func_name = DEPRECATED_SYMBOL_NAME (func); func_lang = SYMBOL_LANGUAGE (func); } else { struct minimal_symbol *msymbol; /* Try to find the symbol most closely associated with the PC corresponding to the frame. */ msymbol = lookup_minimal_symbol_by_pc (get_frame_pc (frame)); if (msymbol != NULL) { func_name = DEPRECATED_SYMBOL_NAME (msymbol); func_lang = SYMBOL_LANGUAGE (msymbol); } } /* Have we found a name? */ if (func_name) { /* If user wants to see raw output, no problem. (demangle is a global flag which can be set by user command). */ if (demangle) { demangled = language_demangle (language_def (func_lang), func_name, DMGL_ANSI | DMGL_PARAMS); /* If the demangler fails, try the demangled name from the symbol table. That'll have parameters, but that's preferable to displaying a mangled name. */ if (demangled == NULL) { if (func == NULL) func_name = _(""); else func_name = SYMBOL_PRINT_NAME (func); } else func_name = demangled; } } else func_name = _(""); printf_filtered(_("Frame of function: %s"), func_name); if (sal.symtab) printf_filtered(_(" (%s:%d)"), sal.symtab->filename, sal.line); printf_filtered(NEW_LINE); if (demangled != NULL) xfree (demangled); } /* -------------------------------------------------------------------------- */ /* local functions called from gdb */ /* -------------------------------------------------------------------------- */ /* Standard register type for the ARC platform. It would be builtin_type_uint32 until we consider the DSP extensions. */ static struct type * arc_register_type (struct gdbarch *gdbarch, int regnum) { return builtin_type_uint32; } /* Skip the prologue for the function at pc. Returns the address of the first instruction after the prologue. */ static CORE_ADDR arc_skip_prologue (struct gdbarch *gdbarch, CORE_ADDR pc) { CORE_ADDR function_addr, function_end = 0; char *function_name; /* This is done by checking from the line information read from the DWARF, if possible; otherwise, we scan the function prologue to find its end. */ ENTERMSG; /* If we're in a dummy frame, don't even try to skip the prologue. */ if (deprecated_pc_in_call_dummy (pc)) return pc; /* See what the symbol table says. */ if (find_pc_partial_function (pc, &function_name, &function_addr, &function_end)) { /* Found a function. */ struct symbol *sym = lookup_symbol (function_name, NULL, VAR_DOMAIN, NULL, NULL); if ((sym != NULL) && SYMBOL_LANGUAGE (sym) != language_asm) { /* Don't use this trick for assembly source files. */ struct symtab_and_line sal = find_pc_line (function_addr, 0); if ((sal.line != 0) && (sal.end < function_end)) return sal.end; } } /* Find the address of the first instruction after the prologue by scanning through it - no other information is needed, so pass NULL for the other parameters. */ return scan_prologue(pc, NULL, NULL); } /* Construct frame id for the normal frame. */ static void arc_frame_this_id (struct frame_info *next_frame, void **this_prologue_cache, struct frame_id *this_id) { ENTERMSG; /* FIXME: to what should *this_id be set if the frame base can not be found? */ { /* Find the entry point of the function which owns the frame. */ CORE_ADDR entrypoint = frame_func_unwind (next_frame, NORMAL_FRAME); /* This is meant to halt the backtrace at the entry point (_start) (it assumes that there is no code at a lower address). */ if (entrypoint > gdbarch_tdep (current_gdbarch)->lowest_pc) { UnwindCache *info = frame_unwind_cache (next_frame, this_prologue_cache); CORE_ADDR base = info->prev_sp; /* Hopefully the prologue analysis either correctly determined the frame's base (which is the SP from the previous frame), or set that base to "NULL". */ if (base != 0) { /* Build the ID from the frame base address. */ *this_id = frame_id_build (base, entrypoint); #if 0 printf("*** Frame ID: %x ==> (%x %x %x)\n", base, this_id->stack_addr, this_id->code_addr, this_id->special_addr); #endif } } } } /* Unwind and obtain the register information. */ static void arc_frame_prev_register (struct frame_info *next_frame, void **this_prologue_cache, int regnum, int *optimized, enum lval_type *lval, CORE_ADDR *addr, int *realnum, gdb_byte *buffer) { ENTERARGS("regnum %d ", regnum); { UnwindCache *info = frame_unwind_cache (next_frame, this_prologue_cache); /* If we are asked to unwind the PC, then we need to return blink instead: the saved value of PC points into this frame's function's prologue, not the next frame's function's resume location. */ if (regnum == ARC_PC_REGNUM) regnum = ARC_BLINK_REGNUM; /* SP is generally not saved to the stack, but this frame is identified by next_frame's stack pointer at the time of the call. The value was already reconstructed into prev_sp. */ if (regnum == ARC_SP_REGNUM) { /* This value is not an L-value, i.e. it can not be changed, because it is implicit in the structure of the call-chain. */ *lval = not_lval; if (buffer) store_unsigned_integer (buffer, BYTES_IN_REGISTER, info->prev_sp); return; } trad_frame_get_prev_register (next_frame, info->saved_regs, regnum, optimized, lval, addr, realnum, buffer); DEBUG("-*-*-*\n Regnum = %d, buffer = %p\n", regnum, buffer); } } /* This function is passed to gdb to enable it to unwind frames. */ static const struct frame_unwind * arc_frame_sniffer (struct frame_info *next_frame) { static const struct frame_unwind arc_frame_unwind = { NORMAL_FRAME, // type arc_frame_this_id, // this_id arc_frame_prev_register, // prev_register NULL, // unwind_data NULL, // sniffer NULL, // prev_pc NULL // dealloc_cache }; return &arc_frame_unwind; } /* Get the breakpoint which is appropriate for address at which it is to be set. Return whatever is in the ARC-private tdep structure (this has been set up according to the correct target / architecture chosen). Fortunately, the ARC processor does not have separate instruction sets (like the ARM's normal 32-bit and 16-bit Thumb instructions), so the bp instruction to be used does not depend on the address (although the ARC does have both 16- and 32-bit instructions, they may be freely intermixed). */ static const unsigned char * arc_breakpoint_from_pc (struct gdbarch *gdbarch, CORE_ADDR *pcptr, int *lenptr) { struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch); int end = gdbarch_byte_order (gdbarch); /* Return the breakpoint instruction length. */ *lenptr = (int) tdep->breakpoint_size; /* Return the breakpoint instruction code. */ if (end == BFD_ENDIAN_LITTLE) return tdep->le_breakpoint_instruction; if (end == BFD_ENDIAN_BIG) return tdep->be_breakpoint_instruction; internal_error (__FILE__, __LINE__, "target endianness is not known"); } /* Determine whether the given register is a member of the given group. Returns 0, 1, or -1: 0 means the register is not in the group. 1 means the register is in the group. -1 means the tdep has nothing to say about this register and group. */ static int arc_register_reggroup_p (struct gdbarch *gdbarch, int regnum, struct reggroup *group) { struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch); int tdep_answer = tdep->register_reggroup_p (regnum, group); /* If the configuration-specific tdep knows about this register. */ if (tdep_answer != -1) return tdep_answer; if (group == all_reggroup) return 1; if (group == save_reggroup || group == restore_reggroup) { /* Don't save/restore read-only registers. */ return (!gdbarch_cannot_store_register(current_gdbarch, regnum)); } if (group == system_reggroup) { if (regnum == ARC_ILINK1_REGNUM || regnum == ARC_ILINK2_REGNUM) return 1; return 0; } internal_error(__FILE__, __LINE__, _("bad register group")); return 0; } /* This function is used by the DWARF-2 frame sniffer. It is the architecture-specific register state initialization function: it tells gdb how to find certain registers in the DWARF-2 Call Frame Information. */ static void arc_dwarf2_frame_init_reg (struct gdbarch *gdbarch, int regnum, struct dwarf2_frame_state_reg *reg, struct frame_info *info) { // ENTERARGS("Regno no:%d, 0x%x", regnum, (unsigned int) regnum); /* Make sure that we know the number of the PC! */ arc_check_pc_defined(gdbarch); /* The return address column. */ if (regnum == ARC_PC_REGNUM) reg->how = DWARF2_FRAME_REG_RA; /* The call frame address. */ if (regnum == ARC_SP_REGNUM) reg->how = DWARF2_FRAME_REG_CFA; } /* Unwind the frame to find the previous frame's PC. */ static CORE_ADDR arc_unwind_pc (struct gdbarch *gdbarch, struct frame_info *next_frame) { ULONGEST pc; /* Make sure that we know the number of the PC! */ arc_check_pc_defined(gdbarch); pc = frame_unwind_register_unsigned (next_frame, ARC_PC_REGNUM); DEBUG("unwind PC: 0x%08lx\n", (unsigned long) pc); return (CORE_ADDR) pc; } /* Unwind the frame to find the previous frame's SP. */ static CORE_ADDR arc_unwind_sp (struct gdbarch *gdbarch, struct frame_info *next_frame) { ULONGEST sp; sp = frame_unwind_register_unsigned (next_frame, ARC_SP_REGNUM); DEBUG("unwind SP: 0x%08lx\n", (unsigned long) sp); return (CORE_ADDR) sp; } /* This function returns the convention used by the ABI for returning a result of the given type from a function; it may also be required to: a) set the return value (this is for the situation where the debugger user has issued a "return " command to request immediate return from the current function with the given result; or b) get the return value ((this is for the situation where the debugger user has executed a "call " command to execute the specified function in the target program, and that function has a non-void result which must be returned to the user. Parameters: gdbarch : gdbarch structure for the backend to use if needed valtype : the information for the return type of the function regcache: the register cache to be used for altered register values readbuf : if non-NULL, read the return value into this buffer writebuf: if non-NULL, write the return value from this buffer */ static enum return_value_convention arc_return_value (struct gdbarch *gdbarch, struct type *valtype, struct regcache *regcache, gdb_byte *readbuf, const gdb_byte *writebuf) { ENTERARGS("readbuf = %p, writebuf = %p", readbuf, writebuf); { /* If the return type is a struct, or a union, or would occupy more than two registers, the ABI uses the "struct return convention": the calling function passes a hidden first parameter to the callee (in R0). That parameter is the address at which the value being returned should be stored. Otherwise, the result is returned in registers. */ Boolean is_struct_return = (TYPE_CODE (valtype) == TYPE_CODE_STRUCT || TYPE_CODE (valtype) == TYPE_CODE_UNION || TYPE_LENGTH (valtype) > 2 * BYTES_IN_REGISTER); /* case a) */ if (writebuf != NULL) { /* gdb should not ask us to set a struct return value: it should know the struct return location and write the value there itself. */ gdb_assert (!is_struct_return); store_return_value (valtype, regcache, writebuf); } /* case b) */ if (readbuf != NULL) { /* gdb should not ask us to get a struct return value: it should know the struct return location and read the value from there itself. */ gdb_assert (!is_struct_return); extract_return_value (valtype, regcache, readbuf); } return (is_struct_return) ? RETURN_VALUE_STRUCT_CONVENTION : RETURN_VALUE_REGISTER_CONVENTION; } } /* Assuming that next_frame->prev is a dummy, return the frame ID of that dummy frame. The frame ID's base needs to match the TOS value saved by save_dummy_frame_tos() (!!!! WHAT IS THIS???), and the PC to match the dummy frame's breakpoint. */ static struct frame_id arc_unwind_dummy_id (struct gdbarch *gdbarch, struct frame_info *next_frame) { return frame_id_build (arc_unwind_sp (gdbarch, next_frame), frame_pc_unwind (next_frame)); } /* Signal Trampoline Frame Unwinder. These unwinders allow frame unwinding to happen from within signal handlers. */ static UnwindCache * arc_sigtramp_frame_cache (struct frame_info *next_frame, void **this_cache) { ENTERMSG; if (*this_cache == NULL) { struct gdbarch_tdep *tdep = gdbarch_tdep (current_gdbarch); UnwindCache *cache = create_cache(next_frame); gdb_byte buf[BYTES_IN_REGISTER]; *this_cache = cache; /* Get the stack pointer and use it as the frame base. */ frame_unwind_register (next_frame, ARC_SP_REGNUM, buf); cache->frame_base = (CORE_ADDR) extract_unsigned_integer (buf, BYTES_IN_REGISTER); /* If the ARC-private target-dependent info has a table of offsets of saved register contents within a O/S signal context structure. */ if (tdep->sc_reg_offset) { /* Find the address of the sigcontext structure. */ CORE_ADDR addr = tdep->sigcontext_addr (next_frame); unsigned int i; /* For each register, if its contents have been saved within the sigcontext structure, determine the address of those contents. */ for (i = 0; i < tdep->sc_num_regs; i++) if (tdep->sc_reg_offset[i] != REGISTER_NOT_PRESENT) cache->saved_regs[i].addr = (LONGEST) (addr + tdep->sc_reg_offset[i]); } } return *this_cache; } /* Construct id for the given frame. */ static void arc_sigtramp_frame_this_id (struct frame_info *next_frame, void **this_cache, struct frame_id *this_id) { UnwindCache *cache; ENTERMSG; cache = arc_sigtramp_frame_cache (next_frame, this_cache); *this_id = frame_id_build (cache->frame_base, frame_pc_unwind (next_frame)); } /* Retrieve the value of the register in the frame. */ static void arc_sigtramp_frame_prev_register (struct frame_info *next_frame, void **this_cache, int regnum, int *optimizedp, enum lval_type *lvalp, CORE_ADDR *addrp, int *realnump, gdb_byte *valuep) { ENTERMSG; { struct gdbarch_tdep *tdep = gdbarch_tdep (current_gdbarch); /* Make sure we've initialized the cache. */ UnwindCache *cache = arc_sigtramp_frame_cache (next_frame, this_cache); /* On a signal, the PC is in ret. */ if (regnum == ARC_PC_REGNUM) regnum = tdep->pc_regnum_in_sigcontext; trad_frame_get_prev_register (next_frame, cache->saved_regs, regnum, optimizedp, lvalp, addrp, realnump, valuep); } } static const struct frame_unwind * arc_sigtramp_frame_sniffer (struct frame_info *next_frame) { ENTERMSG; { struct gdbarch_tdep *tdep = gdbarch_tdep (get_frame_arch (next_frame)); /* We don't even bother if we don't have a sigcontext_addr handler. */ if ((tdep->sigcontext_addr != NULL) && (tdep->is_sigtramp != NULL) && tdep->is_sigtramp (next_frame)) { static const struct frame_unwind arc_sigtramp_frame_unwind = { SIGTRAMP_FRAME, // type arc_sigtramp_frame_this_id, // this_id arc_sigtramp_frame_prev_register, // prev_register NULL, // unwind_data NULL, // sniffer NULL, // prev_pc NULL // dealloc_cache }; return &arc_sigtramp_frame_unwind; } return NULL; } } /* Allow calls to be made to functions defined in the debuggee (A.K.A dummy calls). Parameters: gdbarch : gdbarch structure for the backend to use if needed. function : the function to be called regcache : the register cache to be used for altered register values bp_addr : return address for the breakpoint. nargs : the number of arguments to the function args : the arguments to be passed to the function sp : current value of SP. struct_return: 1 if structures are returned by the function. struct_addr : hidden address for returning a struct. */ static CORE_ADDR arc_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) { int arg_reg = ARC_ABI_FIRST_ARGUMENT_REGISTER; ENTERARGS("nargs = %d, struct_return = %d", nargs, struct_return); /* Push the return address. */ regcache_cooked_write_unsigned (regcache, ARC_BLINK_REGNUM, bp_addr); DEBUG("set BLINK = %X\n", (unsigned int) bp_addr); /* Are we returning a value using a structure return instead of a normal value return? If so, struct_addr is the address of the reserved space for the return structure to be written on the stack, and that address is passed to that function as a hidden first argument. */ if (struct_return) { /* Pass the return address in the first argument register. */ regcache_cooked_write_unsigned (regcache, arg_reg, struct_addr); DEBUG("struct return address 0x%08lX passed in R%d", struct_addr, arg_reg); arg_reg++; } /* If the function has arguments. */ if (nargs > 0) { Boolean big_endian = gdbarch_byte_order (gdbarch) == BFD_ENDIAN_BIG; unsigned int total_space = 0; gdb_byte *memory_image; gdb_byte *data; int i; /* How much space do the arguments occupy in total? N.B. must round each argument's size up to an integral number of words. */ for (i = 0; i < nargs; i++) { unsigned int len = TYPE_LENGTH (value_type (args[i])); unsigned int space = ROUND_UP_TO_WORDS(len); total_space += space; DEBUG("function arg[%d]: %d bytes -> %d\n", i, len, space); } /* Allocate a buffer to hold a memory image of the arguments. */ memory_image = XCALLOC((size_t) total_space, gdb_byte); if (memory_image == NULL) { /* could not do the call! */ return 0; } /* Now copy all of the arguments into the buffer, correctly aligned. */ data = memory_image; for (i = 0; i < nargs; i++) { unsigned int len = TYPE_LENGTH (value_type (args[i])); unsigned int space = ROUND_UP_TO_WORDS(len); gdb_byte* actual = data; unsigned int w; /* Parameters smaller than a word are normally aligned by gcc to the least significant byte, so if we have a big-endian target we put the data at the end of the word rather than at the start. */ if ((len < BYTES_IN_WORD) && big_endian) actual += BYTES_IN_WORD - len; (void) memcpy(actual, value_contents (args[i]), (size_t) len); DEBUG("function arg[%d] =", i); for (w = 0; w < space / BYTES_IN_WORD; w++) DEBUG(" 0x%08X", *((int*) data + w)); DEBUG("\n"); data += space; } /* Now load as much as possible of the memory image into registers. */ data = memory_image; while (arg_reg <= ARC_ABI_LAST_ARGUMENT_REGISTER) { ARC_RegisterContents contents = *(ARC_RegisterContents*) data; DEBUG("passing 0x%08X in register R%d\n", (unsigned int) contents, arg_reg); /* Convert to target byte order if necessary. */ if (HOST_AND_TARGET_ENDIANNESS_DIFFER(gdbarch)) { contents = __bswap_32(contents); DEBUG("byte-swapped to 0x%08X\n", contents); } regcache_cooked_write_unsigned (regcache, arg_reg, (ULONGEST) contents); data += BYTES_IN_REGISTER; total_space -= BYTES_IN_REGISTER; /* If all the data is now in registers. */ if (total_space == 0) break; arg_reg++; } /* If there is any data left, push it onto the stack (in a single write operation). */ if (total_space > 0) { DEBUG("passing %d bytes on stack\n", total_space); sp -= total_space; write_memory (sp, data, (int) total_space); } xfree(memory_image); } /* Finally, update the SP register. */ regcache_cooked_write_unsigned (regcache, ARC_SP_REGNUM, sp); DEBUG("set SP = %X\n", (unsigned int) sp); return sp; } /* Align frame. */ static CORE_ADDR arc_frame_align (struct gdbarch *gdbarch, CORE_ADDR sp) { /* Align to the normal alignment on the stack). */ return WORD_ALIGNED(sp); } /* Print interesting information about the floating point processor (if present) or emulator. */ static void arc_print_float_info (struct gdbarch *gdbarch, struct ui_file *file, struct frame_info *frame, const char *args) { printf(_("Software FPU\n")); } /* Set the main_name to "_main" if required. This is set as an observer of inferior_created. */ static void arc_set_main_name (struct target_ops *objfile, int from_tty) { /* Old ARC toolchains prepend an underscore to symbol names. If there is an _main but no main, then we're probably debugging a binary that was made with the old toolchain. */ struct minimal_symbol *umainsym = lookup_minimal_symbol ("_main", NULL, NULL); struct minimal_symbol *mainsym = lookup_minimal_symbol ("main", NULL, NULL); if ((umainsym != NULL) && (mainsym == NULL)) { set_main_name ("_main"); } /* If we don't have any symbols, the default, i.e. "main", will get used. */ } /* This initialization function is called by gdb. See gdbarch.h for a description of its parameters. */ static struct gdbarch* arc_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches) { /* Allocate the ARC-private target-dependent information structure, and the gdb target-independent information structure. */ struct gdbarch_tdep *tdep = xmalloc (sizeof (struct gdbarch_tdep)); struct gdbarch *gdbarch = gdbarch_alloc (&info, tdep); memset(tdep, 0, sizeof(*tdep)); /* Put stuff in gdbarch. */ /* Breakpoint manipulation. */ set_gdbarch_breakpoint_from_pc (gdbarch, arc_breakpoint_from_pc); set_gdbarch_decr_pc_after_break (gdbarch, 0); info.osabi = CONFIG_OSABI; gdbarch_init_osabi(info, gdbarch); /* Characters are unsigned by default. */ set_gdbarch_char_signed (gdbarch, 0); set_gdbarch_sp_regnum (gdbarch, ARC_SP_REGNUM); set_gdbarch_register_type (gdbarch, arc_register_type); set_gdbarch_print_float_info (gdbarch, arc_print_float_info); /* Advance PC across function entry code. */ set_gdbarch_skip_prologue (gdbarch, arc_skip_prologue); /* Hook in the Dwarf-2 frame sniffer. */ dwarf2_frame_set_init_reg (gdbarch, arc_dwarf2_frame_init_reg); frame_unwind_append_sniffer (gdbarch, dwarf2_frame_sniffer); /* Signal frames. */ frame_unwind_append_sniffer (gdbarch, arc_sigtramp_frame_sniffer); /* The stack grows downward. */ set_gdbarch_inner_than (gdbarch, core_addr_lessthan); set_gdbarch_unwind_pc (gdbarch, arc_unwind_pc); set_gdbarch_unwind_sp (gdbarch, arc_unwind_sp); set_gdbarch_unwind_dummy_id (gdbarch, arc_unwind_dummy_id); frame_unwind_append_sniffer (gdbarch, arc_frame_sniffer); set_gdbarch_return_value (gdbarch, arc_return_value); /* Add the ARC register groups. */ reggroup_add (gdbarch, general_reggroup); reggroup_add (gdbarch, all_reggroup); reggroup_add (gdbarch, system_reggroup); set_gdbarch_register_reggroup_p (gdbarch, arc_register_reggroup_p); set_gdbarch_cannot_step_breakpoint (gdbarch, 1); set_gdbarch_frame_align(gdbarch, arc_frame_align); /* Dummy Frame handling. */ set_gdbarch_push_dummy_call (gdbarch, arc_push_dummy_call); set_gdbarch_call_dummy_location (gdbarch, AT_ENTRY_POINT); /* N.B. we do not want to call arcompact_get_disassembler at this point, as we do not as yet have an executable file, so do not know whether we want the disassembler for the A4 architecture (still supported by the opcodes library!) or the one for the ARCompact architecture; also, it is better to pass the arcompact_get_disassembler function a valid bfd structure, rather than a faked one, so that it can read the ARC- specific sections in the ELF file (for whatever reason...). So just set up a dummy disassembler at this point (gdb requires that *some* disassembler is defined for an architecture), and set up a callback which will set up the appropriate disassembler once an executable file has been selected for debugging. */ #if 0 { /* The arc libopcodes wants abfd so that it can find out what CPU extensions are there. */ bfd abfd; abfd.sections = NULL; set_gdbarch_print_insn(gdbarch, arcompact_get_disassembler(&abfd)); } #endif set_gdbarch_print_insn(gdbarch, dummy_disassembler); (void) observer_attach_new_objfile(set_disassembler); /* Set main_name to _main if necessary. Ideally we'd want a hook that gets called when symbols are loaded, but it seems there isn't one; so we'll use this. This will not work if the user does "target remote ..." and then "add-symbol-file ...". */ (void) observer_attach_inferior_created (arc_set_main_name); /* Initialize the target-dependent modules (if any). */ CONFIG_INIT_TDEP /* Return a pointer to the new object - indicates that a new architecture has been created. */ return gdbarch; } static void arc_dump_tdep (struct gdbarch *current_gdbarch, struct ui_file *file) { /* Do nothing. */ } /* -------------------------------------------------------------------------- */ /* local functions implementing commands */ /* -------------------------------------------------------------------------- */ /* [ ] Display annotated stack frame. */ static void arc_show_stack_frame_command (char *arg, int from_tty) { struct frame_info *fi; gdb_byte value[MAX_REGISTER_SIZE]; CORE_ADDR pc, fp, sp, old_sp; CORE_ADDR addr; enum lval_type lval; int optimized; int realnum; int frame_size; unsigned int *frame_contents; LocalVariable *variables; unsigned int num_variables; /* Find the frame. */ fi = parse_frame_specification_1 (arg, _("No stack."), NULL); gdb_assert(fi != NULL); /* Find out PC, FP and SP for the frame. */ pc = get_frame_pc(fi); sp = get_frame_sp(fi); get_frame_register(fi, ARC_FP_REGNUM, value); fp = (CORE_ADDR) extract_unsigned_integer (value, BYTES_IN_REGISTER); DEBUG("*** PC = %x, FP = %x, SP = %x\n", (unsigned int) pc, (unsigned int) fp, (unsigned int) sp); if (pc == 0) { warning(_("invalid frame")); return; } frame_register_unwind (fi, ARC_SP_REGNUM, &optimized, &lval, &addr, &realnum, value); old_sp = (CORE_ADDR) extract_unsigned_integer (value, BYTES_IN_REGISTER); /* Find the local variables and parameters. */ variables = find_local_variables(fi, &num_variables); printf_filtered(NEW_LINE); identify_frame(fi); DEBUG(_("\n\n*** FRAME: 0x%x .. 0x%x\n\n"), (unsigned int) sp, (unsigned int) (old_sp - 1)); frame_size = (int) (old_sp - sp); frame_contents = xmalloc((size_t) frame_size); if (frame_contents) { /* Read all of the frame's contents from target memory. */ if (target_read_memory(sp, (gdb_byte*) frame_contents, frame_size) == 0) { int numregs = ARC_TOTAL_REGS; int i = frame_size / BYTES_IN_WORD - 1; unsigned int the_same = 0; unsigned int previous_word = 0; Boolean first_word = TRUE; Boolean is_following_element; Boolean elements_are_word_sized; addr = old_sp - BYTES_IN_WORD; printf_filtered(NEW_LINE); /* Traverse the frame from high address to low address, one word at a time. */ while (i >= 0) { unsigned int this_word = frame_contents[i]; Boolean print = first_word; /* Always print the first word. */ char line[256]; int n; /* Start with a blank line. */ (void) memset(line, (int) ' ', sizeof(line)); /* Does FP and/or SP address this particular stack location? */ if (addr == sp && fp == sp) { (void) strcpy(line + 14, _("SP/FP ===> ")); line[25] = ' '; print = TRUE; } else if (addr == sp) { (void) strcpy(line + 17, _("SP ===> ")); line[25] = ' '; print = TRUE; } else if (addr == fp) { (void) strcpy(line + 17, _("FP ===> ")); line[25] = ' '; print = TRUE; } /* Does this stack location hold a local variable or parameter? */ if ((add_local_name(line + 38, addr, variables, num_variables, &is_following_element, &elements_are_word_sized))) { /* Yes - so we want to print it (but this may be revised below!). */ print = TRUE; } else { int r; /* Does this location hold a saved register? */ for (r = 0; r < numregs; r++) { if (r != ARC_SP_REGNUM && gdbarch_register_reggroup_p (current_gdbarch, r, all_reggroup)) { CORE_ADDR saved_addr; /* Find out the location of the saved register without fetching the corresponding value. */ frame_register_unwind (fi, r, &optimized, &lval, &saved_addr, &realnum, NULL); if (!optimized && lval == lval_memory && saved_addr == addr) { (void) sprintf(line + 38, _("saved register '%s'"), gdbarch_register_name(current_gdbarch, r)); print = TRUE; break; } } } } /* Do we think we need to print out the line? */ if (print) { /* If the location is a non-zeroth word-sized array element, and this word is the same as the previous word. */ if (is_following_element && elements_are_word_sized && (this_word == previous_word)) { /* No need to print it - one more word the same! */ the_same++; print = FALSE; } } else { /* N.B. this will not be the first word (since print is FALSE) */ /* This location does not hold anything "interesting", but if this word is not the same as the previous word, we want to print it. */ if (this_word == previous_word) the_same++; else print = TRUE; } /* OK, now we really know whether we need to print out the line. */ if (print) { n = sprintf(line, _("0x%08X:"), (unsigned int) addr); line[n] = ' '; n = sprintf(line + 25, "%08X", this_word); line[25 + n] = ' '; n = (int) sizeof(line) - 1; while (line[n] == ' ') n--; line[n + 1] = '\0'; /* If we did not print the previous word because it was the same as the word before, but not the same as any preceding words, print it now (there is no point in outputting a message which says simply "... 1 words omitted" - we might just as well print out the word! */ if (the_same == 1) printf_filtered(_("0x%08X: %08X\n"), (unsigned int) addr + BYTES_IN_WORD, previous_word); else if (the_same != 0) /* 2 or more words the same... */ printf_filtered(_("... %u words omitted\n"), the_same); /* Now print out the line with the current word (and other information). */ printf_filtered(_("%s\n"), line); /* No words omitted. */ the_same = 0; } first_word = FALSE; previous_word = this_word; addr -= BYTES_IN_WORD; i--; } printf_filtered(NEW_LINE); } xfree(frame_contents); } xfree(variables); } /* -------------------------------------------------------------------------- */ /* externally visible functions */ /* -------------------------------------------------------------------------- */ /* Initialize the module. This function is called from the gdb core on start-up. */ void _initialize_arc_tdep (void) { /* Register the ARC processor architecture with gdb, providing an initialization function and a dump function; 'bfd_arch_arc' is an enumeration value specifically denoting the ARC architecture. */ gdbarch_register(bfd_arch_arc, arc_gdbarch_init, arc_dump_tdep); /* Register ARC-specific commands with gdb. */ add_setshow_boolean_cmd(DEBUG_COMMAND, no_class, &arc_debug_target, _("Set whether to print ARC debug messages.\n"), _("Show whether to print ARC debug messages.\n"), _("If set debug messages are printed.\n"), NULL, NULL, &setlist, &showlist); (void) add_cmd(SHOW_FRAME_COMMAND, class_obscure, arc_show_stack_frame_command, _("Display the stack frame with annotation.\n" SHOW_FRAME_COMMAND_USAGE " may be the number or address of a frame.\n"), &cmdlist); } /* Initialize the info structure to enable the disassembler to be used. */ void arc_initialize_disassembler (struct disassemble_info *info) { /* N.B. this type cast is not strictly correct: the return types differ! */ init_disassemble_info(info, gdb_stdout, (fprintf_ftype) fprintf_filtered); info->arch = gdbarch_bfd_arch_info(current_gdbarch)->arch; info->mach = gdbarch_bfd_arch_info(current_gdbarch)->mach; info->endian = gdbarch_byte_order (current_gdbarch); info->read_memory_func = read_memory_for_disassembler; } /******************************************************************************/