CORE_ADDR h8500_frame_chain (struct frame_info *thisframe) { if (!inside_entry_file (thisframe->pc)) return (read_memory_integer (FRAME_FP (thisframe), PTR_SIZE)); else return 0; }
void microblaze_pop_frame (struct frame_info *fi) { int rn; CORE_ADDR func_addr, func_end, addr; enum microblaze_instr op; int insn, rd, ra, rb, imm; int status; char *name; int offset = 0; /* offset that the return instruction specifies */ /* Find the start and end of this function. */ /* siva/9/19/05: pop frame was not computing this offset. copied code from microblaze_fix_call_dummy to find the return insn & the offset */ status = find_pc_partial_function (fi->pc, &name, &func_addr, &func_end); for (addr = func_addr; addr < func_end; addr += INST_WORD_SIZE) { /* Start decoding the function looking for rtsd */ insn = get_insn (addr); op = microblaze_decode_insn (insn, &rd, &ra, &rb, &imm); /* Check for return. */ if (IS_RETURN(op)) { offset = imm; break; } } if (PC_IN_CALL_DUMMY (fi->pc, fi->frame, fi->frame)) generic_pop_dummy_frame (); else { /* Write out the PC we saved. */ write_register (PC_REGNUM, FRAME_SAVED_PC (fi) + offset); /* Restore any saved registers. */ for (rn = 0; rn < NUM_REGS; rn++) { if (fi->saved_regs[rn] != 0) { ULONGEST value; value = read_memory_unsigned_integer (fi->saved_regs[rn], REGISTER_SIZE); write_register (rn, value); } } /* Actually cut back the stack. */ write_register (SP_REGNUM, FRAME_FP (fi)); } /* Finally, throw away any cached frame information. */ flush_cached_frames (); }
static void metrowerks_step (CORE_ADDR range_start, CORE_ADDR range_stop, int step_into) { struct frame_info *frame = NULL; CORE_ADDR pc = 0; /* When single stepping in assembly, the plugin passes (start + 1) as the stop address. Round the stop address up to the next valid instruction */ if ((range_stop & ~0x3) != range_stop) range_stop = ((range_stop + 4) & ~0x3); pc = read_pc(); if (range_start >= range_stop) error ("invalid step range (the stop address must be greater than the start address)"); if (pc < range_start) error ("invalid step range ($pc is 0x%lx, less than the stop address of 0x%lx)", (unsigned long) pc, (unsigned long) range_start); if (pc == range_stop) error ("invalid step range ($pc is 0x%lx, equal to the stop address of 0x%lx)", (unsigned long) pc, (unsigned long) range_stop); if (pc > range_stop) error ("invalid step range ($pc is 0x%lx, greater than the stop address of 0x%lx)", (unsigned long) pc, (unsigned long) range_stop); clear_proceed_status (); frame = get_current_frame (); if (frame == NULL) error ("No current frame"); step_frame_address = FRAME_FP (frame); step_sp = read_sp (); step_range_start = range_start; step_range_end = range_stop; step_over_calls = step_into ? STEP_OVER_NONE : STEP_OVER_ALL; step_multi = 0; metrowerks_stepping = 1; proceed ((CORE_ADDR) -1, TARGET_SIGNAL_DEFAULT, 1); make_exec_cleanup (metrowerks_stepping_cleanup, NULL); }
struct frame_info * find_frame_addr_in_frame_chain (CORE_ADDR frame_addr) { struct frame_info *frame = NULL; if (frame_addr == (CORE_ADDR) 0) return NULL; while (1) { frame = get_prev_frame (frame); if (frame == NULL) return NULL; if (FRAME_FP (frame) == frame_addr) return frame; } }
/* generic_pop_current_frame calls this function if the current frame isn't a dummy frame. */ static void mn10300_pop_frame_regular (struct frame_info *frame) { int regnum; write_register (PC_REGNUM, FRAME_SAVED_PC (frame)); /* Restore any saved registers. */ for (regnum = 0; regnum < NUM_REGS; regnum++) if (frame->saved_regs[regnum] != 0) { ULONGEST value; value = read_memory_unsigned_integer (frame->saved_regs[regnum], REGISTER_RAW_SIZE (regnum)); write_register (regnum, value); } /* Actually cut back the stack. */ write_register (SP_REGNUM, FRAME_FP (frame)); /* Don't we need to set the PC?!? XXX FIXME. */ }
CORE_ADDR frame_saved_pc (struct frame_info *frame) { return read_memory_integer (FRAME_FP (frame) + 2, PTR_SIZE); }
struct frame_info * get_prev_frame (struct frame_info *next_frame) { CORE_ADDR address = 0; struct frame_info *prev; int fromleaf = 0; char *name; /* If the requested entry is in the cache, return it. Otherwise, figure out what the address should be for the entry we're about to add to the cache. */ if (!next_frame) { #if 0 /* This screws value_of_variable, which just wants a nice clean NULL return from block_innermost_frame if there are no frames. I don't think I've ever seen this message happen otherwise. And returning NULL here is a perfectly legitimate thing to do. */ if (!current_frame) { error ("You haven't set up a process's stack to examine."); } #endif return current_frame; } /* If we have the prev one, return it */ if (next_frame->prev) return next_frame->prev; /* On some machines it is possible to call a function without setting up a stack frame for it. On these machines, we define this macro to take two args; a frameinfo pointer identifying a frame and a variable to set or clear if it is or isn't leafless. */ /* Still don't want to worry about this except on the innermost frame. This macro will set FROMLEAF if NEXT_FRAME is a frameless function invocation. */ if (!(next_frame->next)) { fromleaf = FRAMELESS_FUNCTION_INVOCATION (next_frame); if (fromleaf) address = FRAME_FP (next_frame); } if (!fromleaf) { /* Two macros defined in tm.h specify the machine-dependent actions to be performed here. First, get the frame's chain-pointer. If that is zero, the frame is the outermost frame or a leaf called by the outermost frame. This means that if start calls main without a frame, we'll return 0 (which is fine anyway). Nope; there's a problem. This also returns when the current routine is a leaf of main. This is unacceptable. We move this to after the ffi test; I'd rather have backtraces from start go curfluy than have an abort called from main not show main. */ address = FRAME_CHAIN (next_frame); if (!FRAME_CHAIN_VALID (address, next_frame)) return 0; address = FRAME_CHAIN_COMBINE (address, next_frame); } if (address == 0) return 0; prev = (struct frame_info *) obstack_alloc (&frame_cache_obstack, sizeof (struct frame_info)); /* Zero all fields by default. */ memset (prev, 0, sizeof (struct frame_info)); if (next_frame) next_frame->prev = prev; prev->next = next_frame; prev->frame = address; /* This change should not be needed, FIXME! We should determine whether any targets *need* INIT_FRAME_PC to happen after INIT_EXTRA_FRAME_INFO and come up with a simple way to express what goes on here. INIT_EXTRA_FRAME_INFO is called from two places: create_new_frame (where the PC is already set up) and here (where it isn't). INIT_FRAME_PC is only called from here, always after INIT_EXTRA_FRAME_INFO. The catch is the MIPS, where INIT_EXTRA_FRAME_INFO requires the PC value (which hasn't been set yet). Some other machines appear to require INIT_EXTRA_FRAME_INFO before they can do INIT_FRAME_PC. Phoo. We shouldn't need INIT_FRAME_PC_FIRST to add more complication to an already overcomplicated part of GDB. [email protected], 15Sep92. Assuming that some machines need INIT_FRAME_PC after INIT_EXTRA_FRAME_INFO, one possible scheme: SETUP_INNERMOST_FRAME() Default version is just create_new_frame (read_fp ()), read_pc ()). Machines with extra frame info would do that (or the local equivalent) and then set the extra fields. SETUP_ARBITRARY_FRAME(argc, argv) Only change here is that create_new_frame would no longer init extra frame info; SETUP_ARBITRARY_FRAME would have to do that. INIT_PREV_FRAME(fromleaf, prev) Replace INIT_EXTRA_FRAME_INFO and INIT_FRAME_PC. This should also return a flag saying whether to keep the new frame, or whether to discard it, because on some machines (e.g. mips) it is really awkward to have FRAME_CHAIN_VALID called *before* INIT_EXTRA_FRAME_INFO (there is no good way to get information deduced in FRAME_CHAIN_VALID into the extra fields of the new frame). std_frame_pc(fromleaf, prev) This is the default setting for INIT_PREV_FRAME. It just does what the default INIT_FRAME_PC does. Some machines will call it from INIT_PREV_FRAME (either at the beginning, the end, or in the middle). Some machines won't use it. [email protected], 13Apr93, 31Jan94, 14Dec94. */ INIT_FRAME_PC_FIRST (fromleaf, prev); #ifdef INIT_EXTRA_FRAME_INFO INIT_EXTRA_FRAME_INFO (fromleaf, prev); #endif /* This entry is in the frame queue now, which is good since FRAME_SAVED_PC may use that queue to figure out its value (see tm-sparc.h). We want the pc saved in the inferior frame. */ INIT_FRAME_PC (fromleaf, prev); /* If ->frame and ->pc are unchanged, we are in the process of getting ourselves into an infinite backtrace. Some architectures check this in FRAME_CHAIN or thereabouts, but it seems like there is no reason this can't be an architecture-independent check. */ if (next_frame != NULL) { if (prev->frame == next_frame->frame && prev->pc == next_frame->pc) { next_frame->prev = NULL; obstack_free (&frame_cache_obstack, prev); return NULL; } } find_pc_partial_function (prev->pc, &name, (CORE_ADDR *) NULL, (CORE_ADDR *) NULL); if (IN_SIGTRAMP (prev->pc, name)) prev->signal_handler_caller = 1; return prev; }