int deprecated_pc_in_call_dummy_at_entry_point (CORE_ADDR pc, CORE_ADDR sp, CORE_ADDR frame_address) { CORE_ADDR addr = entry_point_address (); return ((pc) >= addr && (pc) <= (addr + DECR_PC_AFTER_BREAK)); }
CORE_ADDR displaced_step_at_entry_point (struct gdbarch *gdbarch) { CORE_ADDR addr; int bp_len; addr = entry_point_address (); /* Inferior calls also use the entry point as a breakpoint location. We don't want displaced stepping to interfere with those breakpoints, so leave space. */ gdbarch_breakpoint_from_pc (gdbarch, &addr, &bp_len); addr += bp_len * 2; return addr; }
char * generic_find_dummy_frame (CORE_ADDR pc, CORE_ADDR fp) { struct dummy_frame *dummyframe; if (pc != entry_point_address ()) return 0; for (dummyframe = dummy_frame_stack; dummyframe != NULL; dummyframe = dummyframe->next) if (fp == dummyframe->fp || fp == dummyframe->sp || fp == dummyframe->top) /* The frame in question lies between the saved fp and sp, inclusive */ return dummyframe->registers; return 0; }
static CORE_ADDR microblaze_analyze_prologue (struct frame_info *fi, CORE_ADDR pc ) { CORE_ADDR func_addr, func_end, addr, stop, prologue_end_addr; CORE_ADDR stack_size; int insn, rn, rd, ra, rb, imm; enum microblaze_instr op; int status, fp_regnum, flags; int framesize; int register_offsets[NUM_REGS]; char *name; boolean save_hidden_pointer_found = false; boolean non_stack_instruction_found = false; /* If provided, use the PC in the frame to look up the start of this function. */ pc = (fi == NULL ? pc : fi->pc); /* Find the start of this function. */ status = find_pc_partial_function (pc, &name, &func_addr, &func_end); /* If the start of this function could not be found or if the debbuger is stopped at the first instruction of the prologue, do nothing. */ if (status == 0) return pc; /* If the debugger is entry function, give up. */ if (func_addr == entry_point_address ()) { if (fi != NULL) fi->extra_info->status |= NO_MORE_FRAMES; return pc; } /* At the start of a function, our frame is in the stack pointer. */ flags = MY_FRAME_IN_SP; /* Start decoding the prologue. We start by checking two special cases: 1. We're about to return 2. We're at the first insn of the prologue. If we're about to return, our frame has already been deallocated. If we are stopped at the first instruction of a prologue, then our frame has not yet been set up. */ /* Get the first insn from memory */ microblaze_insn_debug (("MICROBLAZE: starting prologue decoding\n")); insn = get_insn (pc); microblaze_dump_insn ("got 1: ", pc, insn); op = microblaze_decode_insn (insn, &rd, &ra, &rb, &imm); /* Check for return. */ if (fi != NULL && IS_RETURN(op)) { microblaze_insn_debug (("MICROBLAZE: got return")); if (fi->next == NULL) fi->frame = read_sp (); fi->extra_info->status = flags; return fi->pc; } /* Check for first insn of prologue */ if (fi != NULL && fi->pc == func_addr) { if (fi->next == NULL) fi->frame = read_sp (); fi->extra_info->status = flags; return fi->pc; } /* Figure out where to stop scanning */ stop = (fi ? fi->pc : func_end); /* Don't walk off the end of the function */ stop = (stop > func_end ? func_end : stop); /* REGISTER_OFFSETS will contain offsets, from the top of the frame (NOT the frame pointer), for the various saved registers or -1 if the register is not saved. */ for (rn = 0; rn < NUM_REGS; rn++) register_offsets[rn] = -1; /* Analyze the prologue. Things we determine from analyzing the prologue include: * the size of the frame * where saved registers are located (and which are saved) * FP used? */ microblaze_insn_debug (("MICROBLAZE: Scanning prologue: func_addr=0x%x, stop=0x%x\n", (unsigned int) func_addr, (unsigned int) stop)); framesize = 0; for (prologue_end_addr = addr = func_addr; addr < stop; addr += INST_WORD_SIZE) { /* Get next insn */ insn = get_insn (addr); microblaze_dump_insn ("got 2: ", addr, insn); op = microblaze_decode_insn (insn, &rd, &ra, &rb, &imm); /* This code is very sensitive to what functions are present in the prologue. It assumes that the (addi, addik, swi, sw) can be the only instructions in the prologue. */ if (IS_UPDATE_SP(op, rd, ra)) { microblaze_insn_debug (("MICROBLAZE: got addi r1,r1,%d; contnuing\n", imm)); framesize = -1 * imm; /* Since stack grows towards low memory */ save_hidden_pointer_found = false; continue; } else if (IS_SPILL_SP(op, rd, ra)) { /* Spill stack pointer */ register_offsets[rd] = imm; /* SP spilled before updating */ microblaze_insn_debug (("MICROBLAZE: swi r1 r1 %d, continuing\n", imm)); save_hidden_pointer_found = false; continue; } else if (IS_SPILL_REG(op, rd, ra)) { /* Spill register */ register_offsets[rd] = imm - framesize; /* reg spilled after updating */ microblaze_insn_debug (("MICROBLAZE: swi %d r1 %d, continuing\n", rd, imm)); save_hidden_pointer_found = false; continue; } else if (IS_ALSO_SPILL_REG(op, rd, ra, rb)) { /* Spill register */ register_offsets[rd] = 0 - framesize; /* reg spilled after updating */ microblaze_insn_debug (("MICROBLAZE: sw %d r0 r1, continuing\n", rd)); save_hidden_pointer_found = false; continue; } else if (IS_SETUP_FP(op, ra, rb)) { /* We have a frame pointer. Note the register which is acting as the frame pointer. */ flags |= MY_FRAME_IN_FP; flags &= ~MY_FRAME_IN_SP; fp_regnum = rd; microblaze_insn_debug (("MICROBLAZE: Found a frame pointer: r%d\n", fp_regnum)); save_hidden_pointer_found = false; continue; } else if (IS_SPILL_REG_FP(op, rd, ra, fp_regnum)) { register_offsets[rd] = imm - framesize; /* reg spilled after updating */ microblaze_insn_debug (("MICROBLAZE: swi %d %d %d, continuing\n", rd, ra, imm)); save_hidden_pointer_found = false; continue; } else if (IS_SAVE_HIDDEN_PTR(op, rd, ra, rb)) { /* If the first argument is a hidden pointer to the area where the return structure is to be saved, then it is saved as part of the prologue */ microblaze_insn_debug (("MICROBLAZE: add %d %d %d, continuing\n", rd, ra, rb)); save_hidden_pointer_found = true; continue; } /* as a result of the modification in the next step where we continue to analyze the prologue till we reach a control flow instruction, we need another variable to store when exactly a non-stack instruction was encountered, which is the current definition of a prologue */ if (!non_stack_instruction_found) prologue_end_addr = addr; non_stack_instruction_found = true; /* When optimizations are enabled, it is not guaranteed that prologue instructions are not mixed in with other instructions from the program. Some programs show this behavior at -O2. This can be avoided by adding -fno-schedule-insns2 switch as of now (edk 8.1) In such cases, we scan the function until we see the first control instruction. */ { unsigned op = (unsigned)insn >> 26; if (!(op == 0x26 || op == 0x27 || op == 0x2d || op == 0x2e || op == 0x2f)) continue; /* continue if not control flow (branch, return) */ else if (op == 0x2c) continue; /* continue if imm */ } /* This is not a prologue insn, so stop here. */ microblaze_insn_debug (("microblaze: insn is not a prologue insn -- ending scan\n")); break; } microblaze_insn_debug (("microblaze: done analyzing prologue\n")); microblaze_insn_debug (("microblaze: prologue end = 0x%x\n", addr)); /* If the last instruction was an add rd, r5, r0 then don't count it as part of the prologue */ if (save_hidden_pointer_found) { addr -= INST_WORD_SIZE; prologue_end_addr -= INST_WORD_SIZE; } /* Save everything we have learned about this frame into FI. */ if (fi != NULL) { fi->extra_info->framesize = framesize; fi->extra_info->fp_regnum = fp_regnum; fi->extra_info->status = flags; /* Fix the frame pointer. When gcc uses r8 as a frame pointer, it is really an arg ptr. We adjust fi->frame to be a "real" frame pointer. */ if (fi->next == NULL) { if (fi->extra_info->status & MY_FRAME_IN_SP) fi->frame = read_sp () + framesize; else fi->frame = read_register (fp_regnum) + framesize; } /* Note where saved registers are stored. The offsets in REGISTER_OFFSETS are computed relative to the top of the frame. */ for (rn = 0; rn < NUM_REGS; rn++) { if (register_offsets[rn] != -1) { fi->saved_regs[rn] = fi->frame + register_offsets[rn]; microblaze_insn_debug (("Saved register %s stored at 0x%08x, value=0x%08x\n", microblaze_register_names[rn], fi->saved_regs[rn], microblaze_read_memory_integer (fi->saved_regs[rn]))); } } } /* Return addr of first non-prologue insn. */ return prologue_end_addr; }
int inside_entry_func (struct frame_info *this_frame) { return (get_frame_func (this_frame) == entry_point_address ()); }