static void entry_breakpoint_on_hit(struct breakpoint *a, struct process *proc) { struct entry_breakpoint *bp = (void *)a; if (proc == NULL || proc->leader == NULL) return; arch_addr_t dyn_addr = bp->dyn_addr; delete_breakpoint(proc, bp->super.addr); linkmap_init(proc, dyn_addr); arch_dynlink_done(proc); }
static int entry_breakpoint_on_hit(struct task *task, struct breakpoint *a) { struct entry_breakpoint *entry_bp = (void *)a; if (!task) return 0; breakpoint_delete(task, &entry_bp->breakpoint); linkmap_init(task, entry_bp->dyn_addr); return 1; }
int main(int argc, char *argv[]) { printf("sysconfig v%s %s/%s %s " __TIME__ " " __DATE__ "\n", PACKAGE_VERSION, CONFIG_PLATFORM, CONFIG_SRCARCH, CONFIG_ARCH); info_cpu(); info_sys(); linkmap_init(); linkmap_fini(); return 0; }
struct library_symbol * read_elf(Process *proc) { struct ltelf lte[MAX_LIBRARIES + 1]; size_t i; struct opt_x_t *xptr; struct opt_x_t *opt_x_loc = opt_x; struct library_symbol **lib_tail = NULL; int exit_out = 0; int count = 0; debug(DEBUG_FUNCTION, "read_elf(file=%s)", proc->filename); memset(lte, 0, sizeof(lte)); library_symbols = NULL; library_num = 0; proc->libdl_hooked = 0; if (do_init_elf(lte, proc->filename)) return NULL; memcpy(&main_lte, lte, sizeof(struct ltelf)); if (opt_p && opt_p->pid > 0) { linkmap_init(proc, lte); proc->libdl_hooked = 1; } proc->e_machine = lte->ehdr.e_machine; for (i = 0; i < library_num; ++i) { if (do_init_elf(<e[i + 1], library[i])) error(EXIT_FAILURE, errno, "Can't open \"%s\"", library[i]); } if (!options.no_plt) { #ifdef __mips__ // MIPS doesn't use the PLT and the GOT entries get changed // on startup. proc->need_to_reinitialize_breakpoints = 1; for(i=lte->mips_gotsym; i<lte->dynsym_count;i++){ GElf_Sym sym; const char *name; GElf_Addr addr = arch_plt_sym_val(lte, i, 0); if (gelf_getsym(lte->dynsym, i, &sym) == NULL){ error(EXIT_FAILURE, 0, "Couldn't get relocation from \"%s\"", proc->filename); } name=lte->dynstr+sym.st_name; if(ELF64_ST_TYPE(sym.st_info) != STT_FUNC){ debug(2,"sym %s not a function",name); continue; } add_library_symbol(addr, name, &library_symbols, 0, ELF64_ST_BIND(sym.st_info) != 0); if (!lib_tail) lib_tail = &(library_symbols->next); } #else for (i = 0; i < lte->relplt_count; ++i) { GElf_Rel rel; GElf_Rela rela; GElf_Sym sym; GElf_Addr addr; void *ret; const char *name; if (lte->relplt->d_type == ELF_T_REL) { ret = gelf_getrel(lte->relplt, i, &rel); rela.r_offset = rel.r_offset; rela.r_info = rel.r_info; rela.r_addend = 0; } else ret = gelf_getrela(lte->relplt, i, &rela); if (ret == NULL || ELF64_R_SYM(rela.r_info) >= lte->dynsym_count || gelf_getsym(lte->dynsym, ELF64_R_SYM(rela.r_info), &sym) == NULL) error(EXIT_FAILURE, 0, "Couldn't get relocation from \"%s\"", proc->filename); #ifdef PLT_REINITALISATION_BP if (!sym.st_value && PLTs_initialized_by_here) proc->need_to_reinitialize_breakpoints = 1; #endif name = lte->dynstr + sym.st_name; count = library_num ? library_num+1 : 0; if (in_load_libraries(name, lte, count, NULL)) { enum toplt pltt; if (sym.st_value == 0 && lte->plt_stub_vma != 0) { pltt = LS_TOPLT_EXEC; addr = lte->plt_stub_vma + PPC_PLT_STUB_SIZE * i; } else { pltt = PLTS_ARE_EXECUTABLE(lte) ? LS_TOPLT_EXEC : LS_TOPLT_POINT; addr = arch_plt_sym_val(lte, i, &rela); } add_library_symbol(addr, name, &library_symbols, pltt, ELF64_ST_BIND(sym.st_info) == STB_WEAK); if (!lib_tail) lib_tail = &(library_symbols->next); } } #endif // !__mips__ #ifdef PLT_REINITALISATION_BP struct opt_x_t *main_cheat; if (proc->need_to_reinitialize_breakpoints) { /* Add "PLTs_initialized_by_here" to opt_x list, if not already there. */ main_cheat = (struct opt_x_t *)malloc(sizeof(struct opt_x_t)); if (main_cheat == NULL) error(EXIT_FAILURE, 0, "Couldn't allocate memory"); main_cheat->next = opt_x_loc; main_cheat->found = 0; main_cheat->name = PLTs_initialized_by_here; for (xptr = opt_x_loc; xptr; xptr = xptr->next) if (strcmp(xptr->name, PLTs_initialized_by_here) == 0 && main_cheat) { free(main_cheat); main_cheat = NULL; break; } if (main_cheat) opt_x_loc = main_cheat; } #endif } else { lib_tail = &library_symbols; } for (i = 0; i < lte->symtab_count; ++i) { GElf_Sym sym; GElf_Addr addr; const char *name; if (gelf_getsym(lte->symtab, i, &sym) == NULL) error(EXIT_FAILURE, 0, "Couldn't get symbol from \"%s\"", proc->filename); name = lte->strtab + sym.st_name; addr = sym.st_value; if (!addr) continue; for (xptr = opt_x_loc; xptr; xptr = xptr->next) if (xptr->name && strcmp(xptr->name, name) == 0) { /* FIXME: Should be able to use &library_symbols as above. But when you do, none of the real library symbols cause breaks. */ add_library_symbol(opd2addr(lte, addr), name, lib_tail, LS_TOPLT_NONE, 0); xptr->found = 1; break; } } unsigned found_count = 0; for (xptr = opt_x_loc; xptr; xptr = xptr->next) { if (xptr->found) continue; GElf_Sym sym; GElf_Addr addr; if (in_load_libraries(xptr->name, lte, library_num+1, &sym)) { debug(2, "found symbol %s @ %#" PRIx64 ", adding it.", xptr->name, sym.st_value); addr = sym.st_value; if (ELF32_ST_TYPE (sym.st_info) == STT_FUNC) { add_library_symbol(addr, xptr->name, lib_tail, LS_TOPLT_NONE, 0); xptr->found = 1; found_count++; } } if (found_count == opt_x_cnt){ debug(2, "done, found everything: %d\n", found_count); break; } } for (xptr = opt_x_loc; xptr; xptr = xptr->next) if ( ! xptr->found) { char *badthing = "WARNING"; #ifdef PLT_REINITALISATION_BP if (strcmp(xptr->name, PLTs_initialized_by_here) == 0) { if (lte->ehdr.e_entry) { add_library_symbol ( opd2addr (lte, lte->ehdr.e_entry), PLTs_initialized_by_here, lib_tail, 1, 0); fprintf (stderr, "WARNING: Using e_ent" "ry from elf header (%p) for " "address of \"%s\"\n", (void*) (long) lte->ehdr.e_entry, PLTs_initialized_by_here); continue; } badthing = "ERROR"; exit_out = 1; } #endif fprintf (stderr, "%s: Couldn't find symbol \"%s\" in file \"%s\" assuming it will be loaded by libdl!" "\n", badthing, xptr->name, proc->filename); } if (exit_out) { exit (1); } for (i = 0; i < library_num + 1; ++i) do_close_elf(<e[i]); return library_symbols; }
struct libref *elf_read_main_binary(struct task *task, int was_attached) { char fname[PATH_MAX]; int ret; char *filename; struct mt_elf mte = { }; unsigned long entry; unsigned long base; struct libref *libref; filename = pid2name(task->pid); if (!filename) return NULL; libref = libref_new(LIBTYPE_MAIN); if (libref == NULL) goto fail1; ret = readlink(filename, fname, sizeof(fname) - 1); if (ret == -1) goto fail2; fname[ret] = 0; free(filename); libref_set_filename(libref, fname); if (elf_read(&mte, task, fname) == -1) goto fail3; task->is_64bit = is_64bit(&mte); if (process_get_entry(task, &entry, &base) < 0) { fprintf(stderr, "Couldn't find process entry of %s\n", filename); goto fail3; } mte.bias = entry - mte.ehdr.e_entry - mte.vstart; mte.entry_addr = entry; if (elf_lib_init(&mte, task, libref)) goto fail3; close_elf(&mte); report_attach(task, was_attached); library_add(task, libref); if (!mte.interp) return libref; struct mt_elf mte_ld = { }; if (copy_str_from_proc(task, ARCH_ADDR_T(mte.bias + mte.interp - mte.vstart), fname, sizeof(fname)) == -1) { fprintf(stderr, "fatal error: cannot get loader name for pid=%d\n", task->pid); abort(); } if (!elf_read(&mte_ld, task, fname)) { struct libref *libref; libref = libref_new(LIBTYPE_LOADER); if (libref == NULL) goto fail4; libref_set_filename(libref, fname); mte_ld.bias = base; mte_ld.entry_addr = base + mte_ld.ehdr.e_entry - mte.vstart; ret = elf_lib_init(&mte_ld, task, libref); if (!ret) { library_add(task, libref); if (linkmap_init(task, ARCH_ADDR_T(mte.bias + mte.dyn - mte.vstart))) { arch_addr_t addr = find_solib_break(&mte_ld); if (!addr) addr = ARCH_ADDR_T(entry); struct entry_breakpoint *entry_bp = (void *)breakpoint_new_ext(task, addr, NULL, 0, sizeof(*entry_bp) - sizeof(entry_bp->breakpoint)); if (!entry_bp) fprintf(stderr, "Couldn't initialize entry breakpoint for PID %d.\n" "Tracing events may be missed.\n", task->pid ); else { entry_bp->breakpoint.on_hit = entry_breakpoint_on_hit; entry_bp->breakpoint.locked = 1; entry_bp->dyn_addr = ARCH_ADDR_T(mte.bias + mte.dyn - mte.vstart); breakpoint_enable(task, &entry_bp->breakpoint); } } } else { fprintf(stderr, "Couldn't read dynamic loader `%s` for PID %d.\n" "Tracing events may be missed.\n", fname, task->pid ); } fail4: close_elf(&mte_ld); } else { fprintf(stderr, "Couldn't open dynamic loader `%s` for PID %d.\n" "Tracing events may be missed.\n", fname, task->pid ); } return libref; fail3: close_elf(&mte); fail2: libref_delete(libref); fail1: free(filename); return libref; }