static CORE_ADDR skip_hurd_resolver (CORE_ADDR pc) { /* The HURD dynamic linker is part of the GNU C library, so many GNU/Linux distributions use it. (All ELF versions, as far as I know.) An unresolved PLT entry points to "_dl_runtime_resolve", which calls "fixup" to patch the PLT, and then passes control to the function. We look for the symbol `_dl_runtime_resolve', and find `fixup' in the same objfile. If we are at the entry point of `fixup', then we set a breakpoint at the return address (at the top of the stack), and continue. It's kind of gross to do all these checks every time we're called, since they don't change once the executable has gotten started. But this is only a temporary hack --- upcoming versions of GNU/Linux will provide a portable, efficient interface for debugging programs that use shared libraries. */ struct objfile *objfile; struct minimal_symbol *resolver = find_minsym_and_objfile ("_dl_runtime_resolve", &objfile); if (resolver) { struct minimal_symbol *fixup = lookup_minimal_symbol ("fixup", NULL, objfile); if (fixup && SYMBOL_VALUE_ADDRESS (fixup) == pc) return (SAVED_PC_AFTER_CALL (get_current_frame ())); } return 0; }
void init_frame_pc_default (int fromleaf, struct frame_info *prev) { if (fromleaf) prev->pc = SAVED_PC_AFTER_CALL (prev->next); else if (prev->next != NULL) prev->pc = FRAME_SAVED_PC (prev->next); else prev->pc = read_pc (); }
int frame_num_args (struct frame_info *fi) { CORE_ADDR enter_addr; CORE_ADDR argp; int inst; int args; int i; if (read_memory_integer (fi->frame, 4) == 0 && fi->pc < 0x10000) { /* main is always called with three args */ return (3); } enter_addr = ns32k_get_enter_addr (fi->pc); if (enter_addr = 0) return (-1); argp = enter_addr == 1 ? SAVED_PC_AFTER_CALL (fi) : FRAME_SAVED_PC (fi); for (i = 0; i < 16; i++) { /* * After a bsr gcc may emit the following instructions * to remove the arguments from the stack: * cmpqd 0,tos - to remove 4 bytes from the stack * cmpd tos,tos - to remove 8 bytes from the stack * adjsp[bwd] -n - to remove n bytes from the stack * Gcc sometimes delays emitting these instructions and * may even throw a branch between our feet. */ inst = read_memory_integer (argp, 4); args = read_memory_integer (argp + 2, 4); if ((inst & 0xff) == 0xea) { /* br */ args = ((inst >> 8) & 0xffffff) | (args << 24); if (args & 0x80) { if (args & 0x40) { args = ntohl (args); } else { args = ntohs (args & 0xffff); if (args & 0x2000) args |= 0xc000; } } else { args = args & 0xff; if (args & 0x40) args |= 0x80; } argp += args; continue; } if ((inst & 0xffff) == 0xb81f) /* cmpqd 0,tos */ return (1); else if ((inst & 0xffff) == 0xbdc7) /* cmpd tos,tos */ return (2); else if ((inst & 0xfffc) == 0xa57c) { /* adjsp[bwd] */ switch (inst & 3) { case 0: args = ((args & 0xff) + 0x80); break; case 1: args = ((ntohs (args) & 0xffff) + 0x8000); break; case 3: args = -ntohl (args); break; default: return (-1); } if (args / 4 > 10 || (args & 3) != 0) continue; return (args / 4); } argp += 1; }