static struct msp430_prologue * msp430_analyze_frame_prologue (struct frame_info *this_frame, void **this_prologue_cache) { if (!*this_prologue_cache) { CORE_ADDR func_start, stop_addr; *this_prologue_cache = FRAME_OBSTACK_ZALLOC (struct msp430_prologue); func_start = get_frame_func (this_frame); stop_addr = get_frame_pc (this_frame); /* If we couldn't find any function containing the PC, then just initialize the prologue cache, but don't do anything. */ if (!func_start) stop_addr = func_start; msp430_analyze_prologue (get_frame_arch (this_frame), func_start, stop_addr, (struct msp430_prologue *) *this_prologue_cache); }
/* Scroll the source forward or backward vertically. */ void tui_vertical_source_scroll (enum tui_scroll_direction scroll_direction, int num_to_scroll) { if (TUI_SRC_WIN->generic.content != NULL) { struct tui_line_or_address l; struct symtab *s; tui_win_content content = (tui_win_content) TUI_SRC_WIN->generic.content; struct symtab_and_line cursal = get_current_source_symtab_and_line (); if (cursal.symtab == (struct symtab *) NULL) s = find_pc_symtab (get_frame_pc (get_selected_frame (NULL))); else s = cursal.symtab; l.loa = LOA_LINE; if (scroll_direction == FORWARD_SCROLL) { l.u.line_no = content[0]->which_element.source.line_or_addr.u.line_no + num_to_scroll; if (l.u.line_no > s->nlines) /* line = s->nlines - win_info->generic.content_size + 1; */ /* elz: fix for dts 23398. */ l.u.line_no = content[0]->which_element.source.line_or_addr.u.line_no; } else { l.u.line_no = content[0]->which_element.source.line_or_addr.u.line_no - num_to_scroll; if (l.u.line_no <= 0) l.u.line_no = 1; } print_source_lines (s, l.u.line_no, l.u.line_no + 1, 0); } }
static int ppcobsd_sigtramp_frame_sniffer (const struct frame_unwind *self, struct frame_info *this_frame, void **this_cache) { CORE_ADDR pc = get_frame_pc (this_frame); CORE_ADDR start_pc = (pc & ~(ppcobsd_page_size - 1)); const int *offset; char *name; find_pc_partial_function (pc, &name, NULL, NULL); if (name) return 0; for (offset = ppcobsd_sigreturn_offset; *offset != -1; offset++) { gdb_byte buf[2 * PPC_INSN_SIZE]; unsigned long insn; if (!safe_frame_unwind_memory (this_frame, start_pc + *offset, buf, sizeof buf)) continue; /* Check for "li r0,SYS_sigreturn". */ insn = extract_unsigned_integer (buf, PPC_INSN_SIZE); if (insn != 0x38000067) continue; /* Check for "sc". */ insn = extract_unsigned_integer (buf + PPC_INSN_SIZE, PPC_INSN_SIZE); if (insn != 0x44000002) continue; return 1; } return 0; }
static struct trad_frame_cache * frv_linux_sigtramp_frame_cache (struct frame_info *this_frame, void **this_cache) { struct gdbarch *gdbarch = get_frame_arch (this_frame); enum bfd_endian byte_order = gdbarch_byte_order (gdbarch); struct trad_frame_cache *cache; CORE_ADDR addr; gdb_byte buf[4]; int regnum; CORE_ADDR sc_addr_cache_val = 0; struct frame_id this_id; if (*this_cache) return (struct trad_frame_cache *) *this_cache; cache = trad_frame_cache_zalloc (this_frame); /* FIXME: cagney/2004-05-01: This is is long standing broken code. The frame ID's code address should be the start-address of the signal trampoline and not the current PC within that trampoline. */ get_frame_register (this_frame, sp_regnum, buf); addr = extract_unsigned_integer (buf, sizeof buf, byte_order); this_id = frame_id_build (addr, get_frame_pc (this_frame)); trad_frame_set_id (cache, this_id); for (regnum = 0; regnum < frv_num_regs; regnum++) { LONGEST reg_addr = frv_linux_sigcontext_reg_addr (this_frame, regnum, &sc_addr_cache_val); if (reg_addr != -1) trad_frame_set_reg_addr (cache, regnum, reg_addr); } *this_cache = cache; return cache; }
static CORE_ADDR amd64obsd_sigcontext_addr (struct frame_info *this_frame) { CORE_ADDR pc = get_frame_pc (this_frame); ULONGEST offset = (pc & (amd64obsd_page_size - 1)); /* The %rsp register points at `struct sigcontext' upon entry of a signal trampoline. The relevant part of the trampoline is call *%rax movq %rsp, %rdi pushq %rdi movq $SYS_sigreturn,%rax int $0x80 (see /usr/src/sys/arch/amd64/amd64/locore.S). The `pushq' instruction clobbers %rsp, but its value is saved in `%rdi'. */ if (offset > 5) return get_frame_register_unsigned (this_frame, AMD64_RDI_REGNUM); else return get_frame_register_unsigned (this_frame, AMD64_RSP_REGNUM); }
static int tramp_frame_sniffer (const struct frame_unwind *self, struct frame_info *this_frame, void **this_cache) { const struct tramp_frame *tramp = self->unwind_data->tramp_frame; CORE_ADDR pc = get_frame_pc (this_frame); CORE_ADDR func; struct tramp_frame_cache *tramp_cache; /* tausq/2004-12-12: We used to assume if pc has a name or is in a valid section, then this is not a trampoline. However, this assumption is false on HPUX which has a signal trampoline that has a name; it can also be false when using an alternative signal stack. */ func = tramp_frame_start (tramp, this_frame, pc); if (func == 0) return 0; tramp_cache = FRAME_OBSTACK_ZALLOC (struct tramp_frame_cache); tramp_cache->func = func; tramp_cache->tramp_frame = tramp; (*this_cache) = tramp_cache; return 1; }
static CORE_ADDR alphaobsd_sigcontext_addr (struct frame_info *this_frame) { CORE_ADDR pc = get_frame_pc (this_frame); if (alphaobsd_sigtramp_offset (pc) < 3 * ALPHA_INSN_SIZE) { /* On entry, a pointer the `struct sigcontext' is passed in %a2. */ return get_frame_register_unsigned (this_frame, ALPHA_A0_REGNUM + 2); } else if (alphaobsd_sigtramp_offset (pc) < 4 * ALPHA_INSN_SIZE) { /* It is stored on the stack Before calling the signal handler. */ CORE_ADDR sp; sp = get_frame_register_unsigned (this_frame, ALPHA_SP_REGNUM); return get_frame_memory_unsigned (this_frame, sp, 8); } else { /* It is reloaded into %a0 for the sigreturn(2) call. */ return get_frame_register_unsigned (this_frame, ALPHA_A0_REGNUM); } }
/* The selected frame has changed. This is happens after a target stop or when the user explicitly changes the frame (up/down/thread/...). */ static void tui_selected_frame_level_changed_hook (int level) { struct frame_info *fi; /* Negative level means that the selected frame was cleared. */ if (level < 0) return; fi = get_selected_frame (NULL); /* Ensure that symbols for this frame are read in. Also, determine the source language of this frame, and switch to it if desired. */ if (fi) { struct symtab *s; s = find_pc_symtab (get_frame_pc (fi)); /* elz: This if here fixes the problem with the pc not being displayed in the tui asm layout, with no debug symbols. The value of s would be 0 here, and select_source_symtab would abort the command by calling the 'error' function. */ if (s) select_source_symtab (s); /* Display the frame position (even if there is no symbols). */ tui_show_frame_info (fi); /* Refresh the register window if it's visible. */ if (tui_is_window_visible (DATA_WIN)) { tui_refreshing_registers = 1; tui_check_data_values (fi); tui_refreshing_registers = 0; } } }
static int arm_linux_software_single_step (struct frame_info *frame) { struct gdbarch *gdbarch = get_frame_arch (frame); struct address_space *aspace = get_frame_address_space (frame); CORE_ADDR next_pc; if (arm_deal_with_atomic_sequence (frame)) return 1; next_pc = arm_get_next_pc (frame, get_frame_pc (frame)); /* The Linux kernel offers some user-mode helpers in a high page. We can not read this page (as of 2.6.23), and even if we could then we couldn't set breakpoints in it, and even if we could then the atomic operations would fail when interrupted. They are all called as functions and return to the address in LR, so step to there instead. */ if (next_pc > 0xffff0000) next_pc = get_frame_register_unsigned (frame, ARM_LR_REGNUM); arm_insert_single_step_breakpoint (gdbarch, aspace, next_pc); return 1; }
static struct ft32_frame_cache * ft32_frame_cache (struct frame_info *this_frame, void **this_cache) { struct ft32_frame_cache *cache; CORE_ADDR current_pc; int i; if (*this_cache) return (struct ft32_frame_cache *) *this_cache; cache = ft32_alloc_frame_cache (); *this_cache = cache; cache->base = get_frame_register_unsigned (this_frame, FT32_FP_REGNUM); if (cache->base == 0) return cache; cache->pc = get_frame_func (this_frame); current_pc = get_frame_pc (this_frame); if (cache->pc) { struct gdbarch *gdbarch = get_frame_arch (this_frame); ft32_analyze_prologue (cache->pc, current_pc, cache, gdbarch); if (!cache->established) cache->base = get_frame_register_unsigned (this_frame, FT32_SP_REGNUM); } cache->saved_sp = cache->base - 4; for (i = 0; i < FT32_NUM_REGS; ++i) if (cache->saved_regs[i] != REG_UNAVAIL) cache->saved_regs[i] = cache->base + cache->saved_regs[i]; return cache; }
/* Scan an FR-V prologue, starting at PC, until frame->PC. If FRAME is non-zero, fill in its saved_regs with appropriate addresses. We assume FRAME's saved_regs array has already been allocated and cleared. Return the first PC value after the prologue. Note that, for unoptimized code, we almost don't need this function at all; all arguments and locals live on the stack, so we just need the FP to find everything. The catch: structures passed by value have their addresses living in registers; they're never spilled to the stack. So if you ever want to be able to get to these arguments in any frame but the top, you'll need to do this serious prologue analysis. */ static CORE_ADDR frv_analyze_prologue (struct gdbarch *gdbarch, CORE_ADDR pc, struct frame_info *this_frame, struct frv_unwind_cache *info) { enum bfd_endian byte_order = gdbarch_byte_order (gdbarch); /* When writing out instruction bitpatterns, we use the following letters to label instruction fields: P - The parallel bit. We don't use this. J - The register number of GRj in the instruction description. K - The register number of GRk in the instruction description. I - The register number of GRi. S - a signed imediate offset. U - an unsigned immediate offset. The dots below the numbers indicate where hex digit boundaries fall, to make it easier to check the numbers. */ /* Non-zero iff we've seen the instruction that initializes the frame pointer for this function's frame. */ int fp_set = 0; /* If fp_set is non_zero, then this is the distance from the stack pointer to frame pointer: fp = sp + fp_offset. */ int fp_offset = 0; /* Total size of frame prior to any alloca operations. */ int framesize = 0; /* Flag indicating if lr has been saved on the stack. */ int lr_saved_on_stack = 0; /* The number of the general-purpose register we saved the return address ("link register") in, or -1 if we haven't moved it yet. */ int lr_save_reg = -1; /* Offset (from sp) at which lr has been saved on the stack. */ int lr_sp_offset = 0; /* If gr_saved[i] is non-zero, then we've noticed that general register i has been saved at gr_sp_offset[i] from the stack pointer. */ char gr_saved[64]; int gr_sp_offset[64]; /* The address of the most recently scanned prologue instruction. */ CORE_ADDR last_prologue_pc; /* The address of the next instruction. */ CORE_ADDR next_pc; /* The upper bound to of the pc values to scan. */ CORE_ADDR lim_pc; memset (gr_saved, 0, sizeof (gr_saved)); last_prologue_pc = pc; /* Try to compute an upper limit (on how far to scan) based on the line number info. */ lim_pc = skip_prologue_using_sal (gdbarch, pc); /* If there's no line number info, lim_pc will be 0. In that case, set the limit to be 100 instructions away from pc. Hopefully, this will be far enough away to account for the entire prologue. Don't worry about overshooting the end of the function. The scan loop below contains some checks to avoid scanning unreasonably far. */ if (lim_pc == 0) lim_pc = pc + 400; /* If we have a frame, we don't want to scan past the frame's pc. This will catch those cases where the pc is in the prologue. */ if (this_frame) { CORE_ADDR frame_pc = get_frame_pc (this_frame); if (frame_pc < lim_pc) lim_pc = frame_pc; } /* Scan the prologue. */ while (pc < lim_pc) { gdb_byte buf[frv_instr_size]; LONGEST op; if (target_read_memory (pc, buf, sizeof buf) != 0) break; op = extract_signed_integer (buf, sizeof buf, byte_order); next_pc = pc + 4; /* The tests in this chain of ifs should be in order of decreasing selectivity, so that more particular patterns get to fire before less particular patterns. */ /* Some sort of control transfer instruction: stop scanning prologue. Integer Conditional Branch: X XXXX XX 0000110 XX XXXXXXXXXXXXXXXX Floating-point / media Conditional Branch: X XXXX XX 0000111 XX XXXXXXXXXXXXXXXX LCR Conditional Branch to LR X XXXX XX 0001110 XX XX 001 X XXXXXXXXXX Integer conditional Branches to LR X XXXX XX 0001110 XX XX 010 X XXXXXXXXXX X XXXX XX 0001110 XX XX 011 X XXXXXXXXXX Floating-point/Media Branches to LR X XXXX XX 0001110 XX XX 110 X XXXXXXXXXX X XXXX XX 0001110 XX XX 111 X XXXXXXXXXX Jump and Link X XXXXX X 0001100 XXXXXX XXXXXX XXXXXX X XXXXX X 0001101 XXXXXX XXXXXX XXXXXX Call X XXXXXX 0001111 XXXXXXXXXXXXXXXXXX Return from Trap X XXXXX X 0000101 XXXXXX XXXXXX XXXXXX Integer Conditional Trap X XXXX XX 0000100 XXXXXX XXXX 00 XXXXXX X XXXX XX 0011100 XXXXXX XXXXXXXXXXXX Floating-point /media Conditional Trap X XXXX XX 0000100 XXXXXX XXXX 01 XXXXXX X XXXX XX 0011101 XXXXXX XXXXXXXXXXXX Break X XXXX XX 0000100 XXXXXX XXXX 11 XXXXXX Media Trap X XXXX XX 0000100 XXXXXX XXXX 10 XXXXXX */ if ((op & 0x01d80000) == 0x00180000 /* Conditional branches and Call */ || (op & 0x01f80000) == 0x00300000 /* Jump and Link */ || (op & 0x01f80000) == 0x00100000 /* Return from Trap, Trap */ || (op & 0x01f80000) == 0x00700000) /* Trap immediate */ { /* Stop scanning; not in prologue any longer. */ break; } /* Loading something from memory into fp probably means that we're in the epilogue. Stop scanning the prologue. ld @(GRi, GRk), fp X 000010 0000010 XXXXXX 000100 XXXXXX ldi @(GRi, d12), fp X 000010 0110010 XXXXXX XXXXXXXXXXXX */ else if ((op & 0x7ffc0fc0) == 0x04080100 || (op & 0x7ffc0000) == 0x04c80000) { break; } /* Setting the FP from the SP: ori sp, 0, fp P 000010 0100010 000001 000000000000 = 0x04881000 0 111111 1111111 111111 111111111111 = 0x7fffffff . . . . . . . . We treat this as part of the prologue. */ else if ((op & 0x7fffffff) == 0x04881000) { fp_set = 1; fp_offset = 0; last_prologue_pc = next_pc; } /* Move the link register to the scratch register grJ, before saving: movsg lr, grJ P 000100 0000011 010000 000111 JJJJJJ = 0x080d01c0 0 111111 1111111 111111 111111 000000 = 0x7fffffc0 . . . . . . . . We treat this as part of the prologue. */ else if ((op & 0x7fffffc0) == 0x080d01c0) { int gr_j = op & 0x3f; /* If we're moving it to a scratch register, that's fine. */ if (is_caller_saves_reg (gr_j)) { lr_save_reg = gr_j; last_prologue_pc = next_pc; } } /* To save multiple callee-saves registers on the stack, at offset zero: std grK,@(sp,gr0) P KKKKKK 0000011 000001 000011 000000 = 0x000c10c0 0 000000 1111111 111111 111111 111111 = 0x01ffffff stq grK,@(sp,gr0) P KKKKKK 0000011 000001 000100 000000 = 0x000c1100 0 000000 1111111 111111 111111 111111 = 0x01ffffff . . . . . . . . We treat this as part of the prologue, and record the register's saved address in the frame structure. */ else if ((op & 0x01ffffff) == 0x000c10c0 || (op & 0x01ffffff) == 0x000c1100) { int gr_k = ((op >> 25) & 0x3f); int ope = ((op >> 6) & 0x3f); int count; int i; /* Is it an std or an stq? */ if (ope == 0x03) count = 2; else count = 4; /* Is it really a callee-saves register? */ if (is_callee_saves_reg (gr_k)) { for (i = 0; i < count; i++) { gr_saved[gr_k + i] = 1; gr_sp_offset[gr_k + i] = 4 * i; } last_prologue_pc = next_pc; } } /* Adjusting the stack pointer. (The stack pointer is GR1.) addi sp, S, sp P 000001 0010000 000001 SSSSSSSSSSSS = 0x02401000 0 111111 1111111 111111 000000000000 = 0x7ffff000 . . . . . . . . We treat this as part of the prologue. */ else if ((op & 0x7ffff000) == 0x02401000)
static LONGEST frv_linux_sigcontext_reg_addr (struct frame_info *this_frame, int regno, CORE_ADDR *sc_addr_cache_ptr) { struct gdbarch *gdbarch = get_frame_arch (this_frame); enum bfd_endian byte_order = gdbarch_byte_order (gdbarch); CORE_ADDR sc_addr; if (sc_addr_cache_ptr && *sc_addr_cache_ptr) { sc_addr = *sc_addr_cache_ptr; } else { CORE_ADDR pc, sp; gdb_byte buf[4]; int tramp_type; pc = get_frame_pc (this_frame); tramp_type = frv_linux_pc_in_sigtramp (gdbarch, pc, 0); get_frame_register (this_frame, sp_regnum, buf); sp = extract_unsigned_integer (buf, sizeof buf, byte_order); if (tramp_type == NORMAL_SIGTRAMP) { /* For a normal sigtramp frame, the sigcontext struct starts at SP + 8. */ sc_addr = sp + 8; } else if (tramp_type == RT_SIGTRAMP) { /* For a realtime sigtramp frame, SP + 12 contains a pointer to a ucontext struct. The ucontext struct contains a sigcontext struct starting 24 bytes in. (The offset of uc_mcontext within struct ucontext is derived as follows: stack_t is a 12-byte struct and struct sigcontext is 8-byte aligned. This gives an offset of 8 + 12 + 4 (for padding) = 24.) */ if (target_read_memory (sp + 12, buf, sizeof buf) != 0) { warning (_("Can't read realtime sigtramp frame.")); return 0; } sc_addr = extract_unsigned_integer (buf, sizeof buf, byte_order); sc_addr += 24; } else internal_error (__FILE__, __LINE__, _("not a signal trampoline")); if (sc_addr_cache_ptr) *sc_addr_cache_ptr = sc_addr; } switch (regno) { case psr_regnum : return sc_addr + 0; /* sc_addr + 4 has "isr", the Integer Status Register. */ case ccr_regnum : return sc_addr + 8; case cccr_regnum : return sc_addr + 12; case lr_regnum : return sc_addr + 16; case lcr_regnum : return sc_addr + 20; case pc_regnum : return sc_addr + 24; /* sc_addr + 28 is __status, the exception status. sc_addr + 32 is syscallno, the syscall number or -1. sc_addr + 36 is orig_gr8, the original syscall arg #1. sc_addr + 40 is gner[0]. sc_addr + 44 is gner[1]. */ case iacc0h_regnum : return sc_addr + 48; case iacc0l_regnum : return sc_addr + 52; default : if (first_gpr_regnum <= regno && regno <= last_gpr_regnum) return sc_addr + 56 + 4 * (regno - first_gpr_regnum); else if (first_fpr_regnum <= regno && regno <= last_fpr_regnum) return sc_addr + 312 + 4 * (regno - first_fpr_regnum); else return -1; /* not saved. */ } }
static CORE_ADDR mn10300_analyze_prologue (struct frame_info *fi, void **this_cache, CORE_ADDR pc) { CORE_ADDR func_addr, func_end, addr, stop; long stack_size; int imm_size; unsigned char buf[4]; int status, movm_args = 0; char *name; /* Use the PC in the frame if it's provided to look up the start of this function. Note: kevinb/2003-07-16: We used to do the following here: pc = (fi ? get_frame_pc (fi) : pc); But this is (now) badly broken when called from analyze_dummy_frame(). */ if (fi) { pc = (pc ? pc : get_frame_pc (fi)); /* At the start of a function our frame is in the stack pointer. */ my_frame_is_in_sp (fi, this_cache); } /* Find the start of this function. */ status = find_pc_partial_function (pc, &name, &func_addr, &func_end); /* Do nothing if we couldn't find the start of this function MVS: comment went on to say "or if we're stopped at the first instruction in the prologue" -- but code doesn't reflect that, and I don't want to do that anyway. */ if (status == 0) { return pc; } /* If we're in start, then give up. */ if (strcmp (name, "start") == 0) { if (fi != NULL) my_frame_is_last (fi); return pc; } #if 0 /* Get the next two bytes into buf, we need two because rets is a two byte insn and the first isn't enough to uniquely identify it. */ status = deprecated_read_memory_nobpt (pc, buf, 2); if (status != 0) return pc; /* Note: kevinb/2003-07-16: We shouldn't be making these sorts of changes to the frame in prologue examination code. */ /* If we're physically on an "rets" instruction, then our frame has already been deallocated. Note this can also be true for retf and ret if they specify a size of zero. In this case fi->frame is bogus, we need to fix it. */ if (fi && buf[0] == 0xf0 && buf[1] == 0xfc) { if (get_next_frame (fi) == NULL) deprecated_update_frame_base_hack (fi, read_sp ()); return get_frame_pc (fi); } /* Similarly if we're stopped on the first insn of a prologue as our frame hasn't been allocated yet. */ if (fi && get_frame_pc (fi) == func_addr) { if (get_next_frame (fi) == NULL) deprecated_update_frame_base_hack (fi, read_sp ()); return get_frame_pc (fi); } #endif /* NOTE: from here on, we don't want to return without jumping to finish_prologue. */ /* Figure out where to stop scanning. */ stop = fi ? pc : func_end; /* Don't walk off the end of the function. */ stop = stop > func_end ? func_end : stop; /* Start scanning on the first instruction of this function. */ addr = func_addr; /* Suck in two bytes. */ if (addr + 2 >= stop || (status = deprecated_read_memory_nobpt (addr, buf, 2)) != 0) goto finish_prologue; /* First see if this insn sets the stack pointer from a register; if so, it's probably the initialization of the stack pointer in _start, so mark this as the bottom-most frame. */ if (buf[0] == 0xf2 && (buf[1] & 0xf3) == 0xf0) { if (fi) my_frame_is_last (fi); goto finish_prologue; } /* Now look for movm [regs],sp, which saves the callee saved registers. At this time we don't know if fi->frame is valid, so we only note that we encountered a movm instruction. Later, we'll set the entries in fsr.regs as needed. */ if (buf[0] == 0xcf) { /* Extract the register list for the movm instruction. */ movm_args = buf[1]; addr += 2; /* Quit now if we're beyond the stop point. */ if (addr >= stop) goto finish_prologue; /* Get the next two bytes so the prologue scan can continue. */ status = deprecated_read_memory_nobpt (addr, buf, 2); if (status != 0) goto finish_prologue; } /* Now see if we set up a frame pointer via "mov sp,a3" */ if (buf[0] == 0x3f) { addr += 1; /* The frame pointer is now valid. */ if (fi) { my_frame_is_in_fp (fi, this_cache); } /* Quit now if we're beyond the stop point. */ if (addr >= stop) goto finish_prologue; /* Get two more bytes so scanning can continue. */ status = deprecated_read_memory_nobpt (addr, buf, 2); if (status != 0) goto finish_prologue; } /* Next we should allocate the local frame. No more prologue insns are found after allocating the local frame. Search for add imm8,sp (0xf8feXX) or add imm16,sp (0xfafeXXXX) or add imm32,sp (0xfcfeXXXXXXXX). If none of the above was found, then this prologue has no additional stack. */ imm_size = 0; if (buf[0] == 0xf8 && buf[1] == 0xfe) imm_size = 1; else if (buf[0] == 0xfa && buf[1] == 0xfe) imm_size = 2; else if (buf[0] == 0xfc && buf[1] == 0xfe) imm_size = 4; if (imm_size != 0) { /* Suck in imm_size more bytes, they'll hold the size of the current frame. */ status = deprecated_read_memory_nobpt (addr + 2, buf, imm_size); if (status != 0) goto finish_prologue; /* Note the size of the stack in the frame info structure. */ stack_size = extract_signed_integer (buf, imm_size); if (fi) set_my_stack_size (fi, stack_size); /* We just consumed 2 + imm_size bytes. */ addr += 2 + imm_size; /* No more prologue insns follow, so begin preparation to return. */ goto finish_prologue; } /* Do the essentials and get out of here. */ finish_prologue: /* Note if/where callee saved registers were saved. */ if (fi) set_movm_offsets (fi, this_cache, movm_args); return addr; }
static void info_common_command (char *comname, int from_tty) { SAVED_F77_COMMON_PTR the_common; COMMON_ENTRY_PTR entry; struct frame_info *fi; char *funname = 0; struct symbol *func; /* We have been told to display the contents of F77 COMMON block supposedly visible in this function. Let us first make sure that it is visible and if so, let us display its contents */ fi = deprecated_selected_frame; if (fi == NULL) error ("No frame selected"); /* The following is generally ripped off from stack.c's routine print_frame_info() */ func = find_pc_function (get_frame_pc (fi)); if (func) { /* In certain pathological cases, the symtabs give the wrong function (when we are in the first function in a file which is compiled without debugging symbols, the previous function is compiled with debugging symbols, and the "foo.o" symbol that is supposed to tell us where the file with debugging symbols ends has been truncated by ar because it is longer than 15 characters). So look in the minimal symbol tables as well, and if it comes up with a larger address for the function use that instead. I don't think this can ever cause any problems; there shouldn't be any minimal symbols in the middle of a function. FIXME: (Not necessarily true. What about text labels) */ struct minimal_symbol *msymbol = lookup_minimal_symbol_by_pc (get_frame_pc (fi)); if (msymbol != NULL && (SYMBOL_VALUE_ADDRESS (msymbol) > BLOCK_START (SYMBOL_BLOCK_VALUE (func)))) funname = DEPRECATED_SYMBOL_NAME (msymbol); else funname = DEPRECATED_SYMBOL_NAME (func); } else { struct minimal_symbol *msymbol = lookup_minimal_symbol_by_pc (get_frame_pc (fi)); if (msymbol != NULL) funname = DEPRECATED_SYMBOL_NAME (msymbol); } /* If comname is NULL, we assume the user wishes to see the which COMMON blocks are visible here and then return */ if (comname == 0) { list_all_visible_commons (funname); return; } the_common = find_common_for_function (comname, funname); if (the_common) { if (strcmp (comname, BLANK_COMMON_NAME_LOCAL) == 0) printf_filtered ("Contents of blank COMMON block:\n"); else printf_filtered ("Contents of F77 COMMON block '%s':\n", comname); printf_filtered ("\n"); entry = the_common->entries; while (entry != NULL) { printf_filtered ("%s = ", DEPRECATED_SYMBOL_NAME (entry->symbol)); print_variable_value (entry->symbol, fi, gdb_stdout); printf_filtered ("\n"); entry = entry->next; } } else printf_filtered ("Cannot locate the common block %s in function '%s'\n", comname, funname); }
int tui_show_frame_info (struct frame_info *fi) { struct tui_win_info *win_info; int locator_changed_p; int i; if (fi) { int start_line, i; CORE_ADDR low; struct tui_gen_win_info *locator = tui_locator_win_info_ptr (); int source_already_displayed; CORE_ADDR pc; symtab_and_line sal = find_frame_sal (fi); source_already_displayed = sal.symtab != 0 && tui_source_is_displayed (symtab_to_fullname (sal.symtab)); if (get_frame_pc_if_available (fi, &pc)) locator_changed_p = tui_set_locator_info (get_frame_arch (fi), (sal.symtab == 0 ? "??" : symtab_to_fullname (sal.symtab)), tui_get_function_from_frame (fi), sal.line, pc); else locator_changed_p = tui_set_locator_info (get_frame_arch (fi), "??", _("<unavailable>"), sal.line, 0); /* If the locator information has not changed, then frame information has not changed. If frame information has not changed, then the windows' contents will not change. So don't bother refreshing the windows. */ if (!locator_changed_p) return 0; tui_show_locator_content (); start_line = 0; for (i = 0; i < (tui_source_windows ())->count; i++) { union tui_which_element *item; win_info = (tui_source_windows ())->list[i]; item = &locator->content[0]->which_element; if (win_info == TUI_SRC_WIN) { start_line = (item->locator.line_no - (win_info->generic.viewport_height / 2)) + 1; if (start_line <= 0) start_line = 1; } else { if (find_pc_partial_function (get_frame_pc (fi), (const char **) NULL, &low, NULL) == 0) { /* There is no symbol available for current PC. There is no safe way how to "disassemble backwards". */ low = get_frame_pc (fi); } else low = tui_get_low_disassembly_address (get_frame_arch (fi), low, get_frame_pc (fi)); } if (win_info == TUI_SRC_WIN) { struct tui_line_or_address l; l.loa = LOA_LINE; l.u.line_no = start_line; if (!(source_already_displayed && tui_line_is_displayed (item->locator.line_no, win_info, TRUE))) tui_update_source_window (win_info, get_frame_arch (fi), sal.symtab, l, TRUE); else { l.u.line_no = item->locator.line_no; tui_set_is_exec_point_at (l, win_info); } } else { if (win_info == TUI_DISASM_WIN) { struct tui_line_or_address a; a.loa = LOA_ADDRESS; a.u.addr = low; if (!tui_addr_is_displayed (item->locator.addr, win_info, TRUE)) tui_update_source_window (win_info, get_frame_arch (fi), sal.symtab, a, TRUE); else { a.u.addr = item->locator.addr; tui_set_is_exec_point_at (a, win_info); } } } tui_update_exec_info (win_info); } return 1; } else { locator_changed_p = tui_set_locator_info (NULL, NULL, NULL, 0, (CORE_ADDR) 0); if (!locator_changed_p) return 0; tui_show_locator_content (); for (i = 0; i < (tui_source_windows ())->count; i++) { win_info = (tui_source_windows ())->list[i]; tui_clear_source_content (win_info, EMPTY_SOURCE_PROMPT); tui_update_exec_info (win_info); } return 1; } }
static int arm_linux_copy_svc (struct gdbarch *gdbarch, struct regcache *regs, struct displaced_step_closure *dsc) { CORE_ADDR return_to = 0; struct frame_info *frame; unsigned int svc_number = displaced_read_reg (regs, dsc, 7); int is_sigreturn = 0; int is_thumb; frame = get_current_frame (); is_sigreturn = arm_linux_sigreturn_return_addr(frame, svc_number, &return_to, &is_thumb); if (is_sigreturn) { struct symtab_and_line sal; if (debug_displaced) fprintf_unfiltered (gdb_stdlog, "displaced: found " "sigreturn/rt_sigreturn SVC call. PC in frame = %lx\n", (unsigned long) get_frame_pc (frame)); if (debug_displaced) fprintf_unfiltered (gdb_stdlog, "displaced: unwind pc = %lx. " "Setting momentary breakpoint.\n", (unsigned long) return_to); gdb_assert (inferior_thread ()->control.step_resume_breakpoint == NULL); sal = find_pc_line (return_to, 0); sal.pc = return_to; sal.section = find_pc_overlay (return_to); sal.explicit_pc = 1; frame = get_prev_frame (frame); if (frame) { inferior_thread ()->control.step_resume_breakpoint = set_momentary_breakpoint (gdbarch, sal, get_frame_id (frame), bp_step_resume); /* set_momentary_breakpoint invalidates FRAME. */ frame = NULL; /* We need to make sure we actually insert the momentary breakpoint set above. */ insert_breakpoints (); } else if (debug_displaced) fprintf_unfiltered (gdb_stderr, "displaced: couldn't find previous " "frame to set momentary breakpoint for " "sigreturn/rt_sigreturn\n"); } else if (debug_displaced) fprintf_unfiltered (gdb_stdlog, "displaced: sigreturn/rt_sigreturn " "SVC call not in signal trampoline frame\n"); /* Preparation: If we detect sigreturn, set momentary breakpoint at resume location, else nothing. Insn: unmodified svc. Cleanup: if pc lands in scratch space, pc <- insn_addr + 4 else leave pc alone. */ dsc->cleanup = &arm_linux_cleanup_svc; /* Pretend we wrote to the PC, so cleanup doesn't set PC to the next instruction. */ dsc->wrote_to_pc = 1; return 0; }
static int arm_linux_copy_svc (struct gdbarch *gdbarch, uint32_t insn, CORE_ADDR to, struct regcache *regs, struct displaced_step_closure *dsc) { CORE_ADDR from = dsc->insn_addr; struct frame_info *frame; unsigned int svc_number = displaced_read_reg (regs, from, 7); if (debug_displaced) fprintf_unfiltered (gdb_stdlog, "displaced: copying Linux svc insn %.8lx\n", (unsigned long) insn); frame = get_current_frame (); /* Is this a sigreturn or rt_sigreturn syscall? Note: these are only useful for EABI. */ if (svc_number == 119 || svc_number == 173) { if (get_frame_type (frame) == SIGTRAMP_FRAME) { CORE_ADDR return_to; struct symtab_and_line sal; if (debug_displaced) fprintf_unfiltered (gdb_stdlog, "displaced: found " "sigreturn/rt_sigreturn SVC call. PC in frame = %lx\n", (unsigned long) get_frame_pc (frame)); return_to = frame_unwind_caller_pc (frame); if (debug_displaced) fprintf_unfiltered (gdb_stdlog, "displaced: unwind pc = %lx. " "Setting momentary breakpoint.\n", (unsigned long) return_to); gdb_assert (inferior_thread ()->step_resume_breakpoint == NULL); sal = find_pc_line (return_to, 0); sal.pc = return_to; sal.section = find_pc_overlay (return_to); sal.explicit_pc = 1; frame = get_prev_frame (frame); if (frame) { inferior_thread ()->step_resume_breakpoint = set_momentary_breakpoint (gdbarch, sal, get_frame_id (frame), bp_step_resume); /* We need to make sure we actually insert the momentary breakpoint set above. */ insert_breakpoints (); } else if (debug_displaced) fprintf_unfiltered (gdb_stderr, "displaced: couldn't find previous " "frame to set momentary breakpoint for " "sigreturn/rt_sigreturn\n"); } else if (debug_displaced) fprintf_unfiltered (gdb_stdlog, "displaced: sigreturn/rt_sigreturn " "SVC call not in signal trampoline frame\n"); } /* Preparation: If we detect sigreturn, set momentary breakpoint at resume location, else nothing. Insn: unmodified svc. Cleanup: if pc lands in scratch space, pc <- insn_addr + 4 else leave pc alone. */ dsc->modinsn[0] = insn; dsc->cleanup = &arm_linux_cleanup_svc; /* Pretend we wrote to the PC, so cleanup doesn't set PC to the next instruction. */ dsc->wrote_to_pc = 1; return 0; }
static CORE_ADDR mn10300_analyze_prologue (struct frame_info *fi, void **this_cache, CORE_ADDR pc) { CORE_ADDR func_addr, func_end, addr, stop; long stack_extra_size = 0; int imm_size; unsigned char buf[4]; int status; int movm_args = 0; int fpregmask = 0; char *name; int frame_in_fp = 0; /* Use the PC in the frame if it's provided to look up the start of this function. Note: kevinb/2003-07-16: We used to do the following here: pc = (fi ? get_frame_pc (fi) : pc); But this is (now) badly broken when called from analyze_dummy_frame(). */ if (fi) { pc = (pc ? pc : get_frame_pc (fi)); } /* Find the start of this function. */ status = find_pc_partial_function (pc, &name, &func_addr, &func_end); /* Do nothing if we couldn't find the start of this function MVS: comment went on to say "or if we're stopped at the first instruction in the prologue" -- but code doesn't reflect that, and I don't want to do that anyway. */ if (status == 0) { addr = pc; goto finish_prologue; } /* If we're in start, then give up. */ if (strcmp (name, "start") == 0) { addr = pc; goto finish_prologue; } /* Figure out where to stop scanning. */ stop = fi ? pc : func_end; /* Don't walk off the end of the function. */ stop = stop > func_end ? func_end : stop; /* Start scanning on the first instruction of this function. */ addr = func_addr; /* Suck in two bytes. */ if (addr + 2 > stop || !safe_frame_unwind_memory (fi, addr, buf, 2)) goto finish_prologue; /* First see if this insn sets the stack pointer from a register; if so, it's probably the initialization of the stack pointer in _start, so mark this as the bottom-most frame. */ if (buf[0] == 0xf2 && (buf[1] & 0xf3) == 0xf0) { goto finish_prologue; } /* Now look for movm [regs],sp, which saves the callee saved registers. At this time we don't know if fi->frame is valid, so we only note that we encountered a movm instruction. Later, we'll set the entries in fsr.regs as needed. */ if (buf[0] == 0xcf) { /* Extract the register list for the movm instruction. */ movm_args = buf[1]; addr += 2; /* Quit now if we're beyond the stop point. */ if (addr >= stop) goto finish_prologue; /* Get the next two bytes so the prologue scan can continue. */ if (!safe_frame_unwind_memory (fi, addr, buf, 2)) goto finish_prologue; } if (AM33_MODE == 2) { /* Determine if any floating point registers are to be saved. Look for one of the following three prologue formats: [movm [regs],(sp)] [movm [regs],(sp)] [movm [regs],(sp)] add -SIZE,sp add -SIZE,sp add -SIZE,sp fmov fs#,(sp) mov sp,a0/a1 mov sp,a0/a1 fmov fs#,(#,sp) fmov fs#,(a0/a1+) add SIZE2,a0/a1 ... ... fmov fs#,(a0/a1+) ... ... ... fmov fs#,(#,sp) fmov fs#,(a0/a1+) fmov fs#,(a0/a1+) [mov sp,a3] [mov sp,a3] [add -SIZE2,sp] [add -SIZE2,sp] */ /* First, look for add -SIZE,sp (i.e. add imm8,sp (0xf8feXX) or add imm16,sp (0xfafeXXXX) or add imm32,sp (0xfcfeXXXXXXXX)) */ imm_size = 0; if (buf[0] == 0xf8 && buf[1] == 0xfe) imm_size = 1; else if (buf[0] == 0xfa && buf[1] == 0xfe) imm_size = 2; else if (buf[0] == 0xfc && buf[1] == 0xfe) imm_size = 4; if (imm_size != 0) { /* An "add -#,sp" instruction has been found. "addr + 2 + imm_size" is the address of the next instruction. Don't modify "addr" until the next "floating point prologue" instruction is found. If this is not a prologue that saves floating point registers we need to be able to back out of this bit of code and continue with the prologue analysis. */ if (addr + 2 + imm_size < stop) { if (!safe_frame_unwind_memory (fi, addr + 2 + imm_size, buf, 3)) goto finish_prologue; if ((buf[0] & 0xfc) == 0x3c) { /* Occasionally, especially with C++ code, the "fmov" instructions will be preceded by "mov sp,aN" (aN => a0, a1, a2, or a3). This is a one byte instruction: mov sp,aN = 0011 11XX where XX is the register number. Skip this instruction by incrementing addr. (We're committed now.) The "fmov" instructions will have the form "fmov fs#,(aN+)" in this case, but that will not necessitate a change in the "fmov" parsing logic below. */ addr++; if ((buf[1] & 0xfc) == 0x20) { /* Occasionally, especially with C++ code compiled with the -fomit-frame-pointer or -O3 options, the "mov sp,aN" instruction will be followed by an "add #,aN" instruction. This indicates the "stack_size", the size of the portion of the stack containing the arguments. This instruction format is: add #,aN = 0010 00XX YYYY YYYY where XX is the register number YYYY YYYY is the constant. Note the size of the stack (as a negative number) in the frame info structure. */ if (fi) stack_extra_size += -buf[2]; addr += 2; } } if ((buf[0] & 0xfc) == 0x3c || buf[0] == 0xf9 || buf[0] == 0xfb) { /* An "fmov" instruction has been found indicating that this prologue saves floating point registers (or, as described above, a "mov sp,aN" and possible "add #,aN" have been found and we will assume an "fmov" follows). Process the consecutive "fmov" instructions. */ for (addr += 2 + imm_size;;addr += imm_size) { int regnum; /* Read the "fmov" instruction. */ if (addr >= stop || !safe_frame_unwind_memory (fi, addr, buf, 4)) goto finish_prologue; if (buf[0] != 0xf9 && buf[0] != 0xfb) break; /* Get the floating point register number from the 2nd and 3rd bytes of the "fmov" instruction: Machine Code: 0000 00X0 YYYY 0000 => Regnum: 000X YYYY */ regnum = (buf[1] & 0x02) << 3; regnum |= ((buf[2] & 0xf0) >> 4) & 0x0f; /* Add this register number to the bit mask of floating point registers that have been saved. */ fpregmask |= 1 << regnum; /* Determine the length of this "fmov" instruction. fmov fs#,(sp) => 3 byte instruction fmov fs#,(#,sp) => 4 byte instruction */ imm_size = (buf[0] == 0xf9) ? 3 : 4; } } else { /* No "fmov" was found. Reread the two bytes at the original "addr" to reset the state. */ if (!safe_frame_unwind_memory (fi, addr, buf, 2)) goto finish_prologue; } } /* else the prologue consists entirely of an "add -SIZE,sp" instruction. Handle this below. */ }
static void ppc_linux_sigtramp_cache (struct frame_info *this_frame, struct trad_frame_cache *this_cache, CORE_ADDR func, LONGEST offset, int bias) { CORE_ADDR base; CORE_ADDR regs; CORE_ADDR gpregs; CORE_ADDR fpregs; int i; struct gdbarch *gdbarch = get_frame_arch (this_frame); struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch); enum bfd_endian byte_order = gdbarch_byte_order (gdbarch); base = get_frame_register_unsigned (this_frame, gdbarch_sp_regnum (gdbarch)); if (bias > 0 && get_frame_pc (this_frame) != func) /* See below, some signal trampolines increment the stack as their first instruction, need to compensate for that. */ base -= bias; /* Find the address of the register buffer pointer. */ regs = base + offset; /* Use that to find the address of the corresponding register buffers. */ gpregs = read_memory_unsigned_integer (regs, tdep->wordsize, byte_order); fpregs = gpregs + 48 * tdep->wordsize; /* General purpose. */ for (i = 0; i < 32; i++) { int regnum = i + tdep->ppc_gp0_regnum; trad_frame_set_reg_addr (this_cache, regnum, gpregs + i * tdep->wordsize); } trad_frame_set_reg_addr (this_cache, gdbarch_pc_regnum (gdbarch), gpregs + 32 * tdep->wordsize); trad_frame_set_reg_addr (this_cache, tdep->ppc_ctr_regnum, gpregs + 35 * tdep->wordsize); trad_frame_set_reg_addr (this_cache, tdep->ppc_lr_regnum, gpregs + 36 * tdep->wordsize); trad_frame_set_reg_addr (this_cache, tdep->ppc_xer_regnum, gpregs + 37 * tdep->wordsize); trad_frame_set_reg_addr (this_cache, tdep->ppc_cr_regnum, gpregs + 38 * tdep->wordsize); if (ppc_linux_trap_reg_p (gdbarch)) { trad_frame_set_reg_addr (this_cache, PPC_ORIG_R3_REGNUM, gpregs + 34 * tdep->wordsize); trad_frame_set_reg_addr (this_cache, PPC_TRAP_REGNUM, gpregs + 40 * tdep->wordsize); } if (ppc_floating_point_unit_p (gdbarch)) { /* Floating point registers. */ for (i = 0; i < 32; i++) { int regnum = i + gdbarch_fp0_regnum (gdbarch); trad_frame_set_reg_addr (this_cache, regnum, fpregs + i * tdep->wordsize); } trad_frame_set_reg_addr (this_cache, tdep->ppc_fpscr_regnum, fpregs + 32 * tdep->wordsize); } trad_frame_set_id (this_cache, frame_id_build (base, func)); }
static struct libunwind_frame_cache * libunwind_frame_cache (struct frame_info *this_frame, void **this_cache) { unw_accessors_t *acc; unw_addr_space_t as; unw_word_t fp; unw_regnum_t uw_sp_regnum; struct libunwind_frame_cache *cache; struct libunwind_descr *descr; struct gdbarch *gdbarch = get_frame_arch (this_frame); int i, ret; if (*this_cache) return (struct libunwind_frame_cache *) *this_cache; /* Allocate a new cache. */ cache = FRAME_OBSTACK_ZALLOC (struct libunwind_frame_cache); cache->func_addr = get_frame_func (this_frame); if (cache->func_addr == 0) /* This can happen when the frame corresponds to a function for which there is no debugging information nor any entry in the symbol table. This is probably a static function for which an entry in the symbol table was not created when the objfile got linked (observed in libpthread.so on ia64-hpux). The best we can do, in that case, is use the frame PC as the function address. We don't need to give up since we still have the unwind record to help us perform the unwinding. There is also another compelling to continue, because abandonning now means stopping the backtrace, which can never be helpful for the user. */ cache->func_addr = get_frame_pc (this_frame); /* Get a libunwind cursor to the previous frame. We do this by initializing a cursor. Libunwind treats a new cursor as the top of stack and will get the current register set via the libunwind register accessor. Now, we provide the platform-specific accessors and we set up the register accessor to use the frame register unwinding interfaces so that we properly get the registers for the current frame rather than the top. We then use the unw_step function to move the libunwind cursor back one frame. We can later use this cursor to find previous registers via the unw_get_reg interface which will invoke libunwind's special logic. */ descr = libunwind_descr (gdbarch); acc = (unw_accessors_t *) descr->accessors; as = unw_create_addr_space_p (acc, gdbarch_byte_order (gdbarch) == BFD_ENDIAN_BIG ? __BIG_ENDIAN : __LITTLE_ENDIAN); unw_init_remote_p (&cache->cursor, as, this_frame); if (unw_step_p (&cache->cursor) < 0) { unw_destroy_addr_space_p (as); return NULL; } /* To get base address, get sp from previous frame. */ uw_sp_regnum = descr->gdb2uw (gdbarch_sp_regnum (gdbarch)); ret = unw_get_reg_p (&cache->cursor, uw_sp_regnum, &fp); if (ret < 0) { unw_destroy_addr_space_p (as); error (_("Can't get libunwind sp register.")); } cache->base = (CORE_ADDR)fp; cache->as = as; *this_cache = cache; return cache; }
static struct trad_frame_cache * mips_sde_frame_cache (struct frame_info *this_frame, void **this_cache) { struct gdbarch *gdbarch = get_frame_arch (this_frame); const struct mips_regnum *regs = mips_regnum (gdbarch); const int sizeof_reg_t = mips_abi_regsize (gdbarch); enum mips_abi abi = mips_abi (gdbarch); struct trad_frame_cache *cache; CORE_ADDR xcpt_frame; CORE_ADDR start_addr; CORE_ADDR stack_addr; CORE_ADDR pc; int i; if (*this_cache != NULL) return (struct trad_frame_cache *) *this_cache; cache = trad_frame_cache_zalloc (this_frame); *this_cache = cache; /* The previous registers are held in struct xcptcontext which is at $sp+offs struct xcptcontext { reg_t sr; CP0 Status reg_t cr; CP0 Cause reg_t epc; CP0 EPC reg_t vaddr; CP0 BadVAddr reg_t regs[32]; General registers reg_t mdlo; LO reg_t mdhi; HI reg_t mdex; ACX ... }; */ stack_addr = get_frame_register_signed (this_frame, gdbarch_sp_regnum (gdbarch)); switch (abi) { case MIPS_ABI_O32: /* 40: XCPTCONTEXT 24: xcpt_gen() argspace (16 bytes) 16: _xcptcall() saved ra, rounded up ( 8 bytes) 00: _xcptcall() argspace (16 bytes) */ xcpt_frame = stack_addr + 40; break; case MIPS_ABI_N32: case MIPS_ABI_N64: default: /* Wild guess. */ /* 16: XCPTCONTEXT 16: xcpt_gen() argspace ( 0 bytes) 00: _xcptcall() saved ra, rounded up (16 bytes) */ xcpt_frame = stack_addr + 16; break; } trad_frame_set_reg_addr (cache, MIPS_PS_REGNUM + gdbarch_num_regs (gdbarch), xcpt_frame + 0 * sizeof_reg_t); trad_frame_set_reg_addr (cache, regs->cause + gdbarch_num_regs (gdbarch), xcpt_frame + 1 * sizeof_reg_t); trad_frame_set_reg_addr (cache, regs->pc + gdbarch_num_regs (gdbarch), xcpt_frame + 2 * sizeof_reg_t); trad_frame_set_reg_addr (cache, regs->badvaddr + gdbarch_num_regs (gdbarch), xcpt_frame + 3 * sizeof_reg_t); for (i = 0; i < MIPS_NUMREGS; i++) trad_frame_set_reg_addr (cache, i + MIPS_ZERO_REGNUM + gdbarch_num_regs (gdbarch), xcpt_frame + (4 + i) * sizeof_reg_t); trad_frame_set_reg_addr (cache, regs->lo + gdbarch_num_regs (gdbarch), xcpt_frame + 36 * sizeof_reg_t); trad_frame_set_reg_addr (cache, regs->hi + gdbarch_num_regs (gdbarch), xcpt_frame + 37 * sizeof_reg_t); pc = get_frame_pc (this_frame); find_pc_partial_function (pc, NULL, &start_addr, NULL); trad_frame_set_id (cache, frame_id_build (start_addr, stack_addr)); return cache; }
/* Function to print the frame information for the TUI. */ void tui_show_frame_info (struct frame_info *fi) { struct tui_win_info *win_info; int i; if (fi) { int start_line, i; CORE_ADDR low; struct tui_gen_win_info *locator = tui_locator_win_info_ptr (); int source_already_displayed; struct symtab_and_line sal; find_frame_sal (fi, &sal); source_already_displayed = sal.symtab != 0 && tui_source_is_displayed (sal.symtab->filename); tui_set_locator_info (sal.symtab == 0 ? "??" : sal.symtab->filename, tui_get_function_from_frame (fi), sal.line, get_frame_pc (fi)); tui_show_locator_content (); start_line = 0; for (i = 0; i < (tui_source_windows ())->count; i++) { union tui_which_element *item; win_info = (tui_source_windows ())->list[i]; item = &((struct tui_win_element *) locator->content[0])->which_element; if (win_info == TUI_SRC_WIN) { start_line = (item->locator.line_no - (win_info->generic.viewport_height / 2)) + 1; if (start_line <= 0) start_line = 1; } else { if (find_pc_partial_function (get_frame_pc (fi), (char **) NULL, &low, (CORE_ADDR) 0) == 0) error (_("No function contains program counter for selected frame.")); else low = tui_get_low_disassembly_address (low, get_frame_pc (fi)); } if (win_info == TUI_SRC_WIN) { struct tui_line_or_address l; l.loa = LOA_LINE; l.u.line_no = start_line; if (!(source_already_displayed && tui_line_is_displayed (item->locator.line_no, win_info, TRUE))) tui_update_source_window (win_info, sal.symtab, l, TRUE); else { l.u.line_no = item->locator.line_no; tui_set_is_exec_point_at (l, win_info); } } else { if (win_info == TUI_DISASM_WIN) { struct tui_line_or_address a; a.loa = LOA_ADDRESS; a.u.addr = low; if (!tui_addr_is_displayed (item->locator.addr, win_info, TRUE)) tui_update_source_window (win_info, sal.symtab, a, TRUE); else { a.u.addr = item->locator.addr; tui_set_is_exec_point_at (a, win_info); } } } tui_update_exec_info (win_info); } } else { tui_set_locator_info (NULL, NULL, 0, (CORE_ADDR) 0); tui_show_locator_content (); for (i = 0; i < (tui_source_windows ())->count; i++) { win_info = (tui_source_windows ())->list[i]; tui_clear_source_content (win_info, EMPTY_SOURCE_PROMPT); tui_update_exec_info (win_info); } } }