static void parse_relocs(Elf *elf, Elf_Data *relocs, Elf_Data *symbols, unsigned symbol_sh_link, struct radeon_shader_binary *binary) { unsigned i; if (!relocs || !symbols || !binary->reloc_count) { return; } binary->relocs = CALLOC(binary->reloc_count, sizeof(struct radeon_shader_reloc)); for (i = 0; i < binary->reloc_count; i++) { GElf_Sym symbol; GElf_Rel rel; char *symbol_name; struct radeon_shader_reloc *reloc = &binary->relocs[i]; gelf_getrel(relocs, i, &rel); gelf_getsym(symbols, GELF_R_SYM(rel.r_info), &symbol); symbol_name = elf_strptr(elf, symbol_sh_link, symbol.st_name); reloc->offset = rel.r_offset; reloc->name = strdup(symbol_name); } }
static int parse_relo_and_apply(Elf_Data *data, Elf_Data *symbols, GElf_Shdr *shdr, struct bpf_insn *insn) { int i, nrels; nrels = shdr->sh_size / shdr->sh_entsize; for (i = 0; i < nrels; i++) { GElf_Sym sym; GElf_Rel rel; unsigned int insn_idx; gelf_getrel(data, i, &rel); insn_idx = rel.r_offset / sizeof(struct bpf_insn); gelf_getsym(symbols, GELF_R_SYM(rel.r_info), &sym); if (insn[insn_idx].code != (BPF_LD | BPF_IMM | BPF_DW)) { printf("invalid relo for insn[%d].code 0x%x\n", insn_idx, insn[insn_idx].code); return 1; } insn[insn_idx].src_reg = BPF_PSEUDO_MAP_FD; insn[insn_idx].imm = map_fd[sym.st_value / sizeof(struct bpf_map_def)]; } return 0; }
map_s *elf_set_breakpoints(proc_s *proc) { elf_info_s *elf = elf_symbols(proc->fd); map_s *brkp = map_init(32, cmp_addr); for (size_t i = 0; i < elf->replt_count; ++i) { void *ret; GElf_Rel rel; GElf_Rela rela; const char *name; GElf_Sym sym; GElf_Addr addr; /* local relocation entries */ if (elf->replt->d_type == ELF_T_REL) { ret = gelf_getrel(elf->replt, i, &rel); rela.r_offset = rel.r_offset; rela.r_info = rel.r_info; rela.r_addend = 0; } /* external relocation entries */ else ret = gelf_getrela(elf->replt, i, &rela); gelf_getsym(elf->dynsym, ELF64_R_SYM(rela.r_info), &sym); name = elf->dynstr + sym.st_name; addr = elf->plt_addr + (i + 1) * 16; breakpoint_create(brkp, addr, name, proc->pid); } return brkp; }
static void _dwarf_elf_apply_rel_reloc(Dwarf_Debug dbg, void *buf, Elf_Data *rel_data, Elf_Data *symtab_data, int endian) { GElf_Rel rel; int j; j = 0; while (gelf_getrel(rel_data, j++, &rel) != NULL) _dwarf_elf_write_reloc(dbg, symtab_data, endian, buf, rel.r_offset, rel.r_info, 0, 1); }
static gboolean handle_dwarf2_section (DebuginfoData *data, GHashTable *files, GError **error) { Elf_Data *e_data; int i; debug_section_t *debug_sections; ptr_size = 0; if (data->ehdr.e_ident[EI_DATA] == ELFDATA2LSB) { do_read_16 = buf_read_ule16; do_read_32 = buf_read_ule32; } else if (data->ehdr.e_ident[EI_DATA] == ELFDATA2MSB) { do_read_16 = buf_read_ube16; do_read_32 = buf_read_ube32; } else { return flatpak_fail (error, "%s: Wrong ELF data encoding", data->filename); } debug_sections = data->debug_sections; if (debug_sections[DEBUG_INFO].data != NULL) { unsigned char *ptr, *endcu, *endsec; uint32_t value; struct abbrev_tag *t; g_autofree REL *relbuf = NULL; if (debug_sections[DEBUG_INFO].relsec) { Elf_Scn *scn; int ndx, maxndx; GElf_Rel rel; GElf_Rela rela; GElf_Sym sym; GElf_Addr base = data->shdr[debug_sections[DEBUG_INFO].sec].sh_addr; Elf_Data *symdata = NULL; int rtype; i = debug_sections[DEBUG_INFO].relsec; scn = data->scns[i]; e_data = elf_getdata (scn, NULL); g_assert (e_data != NULL && e_data->d_buf != NULL); g_assert (elf_getdata (scn, e_data) == NULL); g_assert (e_data->d_off == 0); g_assert (e_data->d_size == data->shdr[i].sh_size); maxndx = data->shdr[i].sh_size / data->shdr[i].sh_entsize; relbuf = g_malloc (maxndx * sizeof (REL)); reltype = data->shdr[i].sh_type; symdata = elf_getdata (data->scns[data->shdr[i].sh_link], NULL); g_assert (symdata != NULL && symdata->d_buf != NULL); g_assert (elf_getdata (data->scns[data->shdr[i].sh_link], symdata) == NULL); g_assert (symdata->d_off == 0); g_assert (symdata->d_size == data->shdr[data->shdr[i].sh_link].sh_size); for (ndx = 0, relend = relbuf; ndx < maxndx; ++ndx) { if (data->shdr[i].sh_type == SHT_REL) { gelf_getrel (e_data, ndx, &rel); rela.r_offset = rel.r_offset; rela.r_info = rel.r_info; rela.r_addend = 0; } else { gelf_getrela (e_data, ndx, &rela); } gelf_getsym (symdata, ELF64_R_SYM (rela.r_info), &sym); /* Relocations against section symbols are uninteresting in REL. */ if (data->shdr[i].sh_type == SHT_REL && sym.st_value == 0) continue; /* Only consider relocations against .debug_str, .debug_line and .debug_abbrev. */ if (sym.st_shndx != debug_sections[DEBUG_STR].sec && sym.st_shndx != debug_sections[DEBUG_LINE].sec && sym.st_shndx != debug_sections[DEBUG_ABBREV].sec) continue; rela.r_addend += sym.st_value; rtype = ELF64_R_TYPE (rela.r_info); switch (data->ehdr.e_machine) { case EM_SPARC: case EM_SPARC32PLUS: case EM_SPARCV9: if (rtype != R_SPARC_32 && rtype != R_SPARC_UA32) goto fail; break; case EM_386: if (rtype != R_386_32) goto fail; break; case EM_PPC: case EM_PPC64: if (rtype != R_PPC_ADDR32 && rtype != R_PPC_UADDR32) goto fail; break; case EM_S390: if (rtype != R_390_32) goto fail; break; case EM_IA_64: if (rtype != R_IA64_SECREL32LSB) goto fail; break; case EM_X86_64: if (rtype != R_X86_64_32) goto fail; break; case EM_ALPHA: if (rtype != R_ALPHA_REFLONG) goto fail; break; #if defined(EM_AARCH64) && defined(R_AARCH64_ABS32) case EM_AARCH64: if (rtype != R_AARCH64_ABS32) goto fail; break; #endif case EM_68K: if (rtype != R_68K_32) goto fail; break; default: fail: return flatpak_fail (error, "%s: Unhandled relocation %d in .debug_info section", data->filename, rtype); } relend->ptr = debug_sections[DEBUG_INFO].data + (rela.r_offset - base); relend->addend = rela.r_addend; ++relend; } if (relbuf == relend) { g_free (relbuf); relbuf = NULL; relend = NULL; } else { qsort (relbuf, relend - relbuf, sizeof (REL), rel_cmp); } } ptr = debug_sections[DEBUG_INFO].data; relptr = relbuf; endsec = ptr + debug_sections[DEBUG_INFO].size; while (ptr != NULL && ptr < endsec) { g_autoptr(GHashTable) abbrev = NULL; if (ptr + 11 > endsec) return flatpak_fail (error, "%s: .debug_info CU header too small", data->filename); endcu = ptr + 4; endcu += read_32 (ptr); if (endcu == ptr + 0xffffffff) return flatpak_fail (error, "%s: 64-bit DWARF not supported", data->filename); if (endcu > endsec) return flatpak_fail (error, "%s: .debug_info too small", data->filename); cu_version = read_16 (ptr); if (cu_version != 2 && cu_version != 3 && cu_version != 4) return flatpak_fail (error, "%s: DWARF version %d unhandled", data->filename, cu_version); value = read_32_relocated (ptr); if (value >= debug_sections[DEBUG_ABBREV].size) { if (debug_sections[DEBUG_ABBREV].data == NULL) return flatpak_fail (error, "%s: .debug_abbrev not present", data->filename); else return flatpak_fail (error, "%s: DWARF CU abbrev offset too large", data->filename); } if (ptr_size == 0) { ptr_size = read_1 (ptr); if (ptr_size != 4 && ptr_size != 8) return flatpak_fail (error, "%s: Invalid DWARF pointer size %d", data->filename, ptr_size); } else if (read_1 (ptr) != ptr_size) { return flatpak_fail (error, "%s: DWARF pointer size differs between CUs", data->filename); } abbrev = read_abbrev (data, debug_sections[DEBUG_ABBREV].data + value); while (ptr < endcu) { guint entry = read_uleb128 (ptr); if (entry == 0) continue; t = g_hash_table_lookup (abbrev, GINT_TO_POINTER (entry)); if (t == NULL) { g_warning ("%s: Could not find DWARF abbreviation %d", data->filename, entry); } else { ptr = handle_attributes (data, ptr, t, files, error); if (ptr == NULL) return FALSE; } } } } return TRUE; }
static int bpf_program__collect_reloc(struct bpf_program *prog, size_t nr_maps, GElf_Shdr *shdr, Elf_Data *data, Elf_Data *symbols, int maps_shndx) { int i, nrels; pr_debug("collecting relocating info for: '%s'\n", prog->section_name); nrels = shdr->sh_size / shdr->sh_entsize; prog->reloc_desc = malloc(sizeof(*prog->reloc_desc) * nrels); if (!prog->reloc_desc) { pr_warning("failed to alloc memory in relocation\n"); return -ENOMEM; } prog->nr_reloc = nrels; for (i = 0; i < nrels; i++) { GElf_Sym sym; GElf_Rel rel; unsigned int insn_idx; struct bpf_insn *insns = prog->insns; size_t map_idx; if (!gelf_getrel(data, i, &rel)) { pr_warning("relocation: failed to get %d reloc\n", i); return -LIBBPF_ERRNO__FORMAT; } if (!gelf_getsym(symbols, GELF_R_SYM(rel.r_info), &sym)) { pr_warning("relocation: symbol %"PRIx64" not found\n", GELF_R_SYM(rel.r_info)); return -LIBBPF_ERRNO__FORMAT; } if (sym.st_shndx != maps_shndx) { pr_warning("Program '%s' contains non-map related relo data pointing to section %u\n", prog->section_name, sym.st_shndx); return -LIBBPF_ERRNO__RELOC; } insn_idx = rel.r_offset / sizeof(struct bpf_insn); pr_debug("relocation: insn_idx=%u\n", insn_idx); if (insns[insn_idx].code != (BPF_LD | BPF_IMM | BPF_DW)) { pr_warning("bpf: relocation: invalid relo for insns[%d].code 0x%x\n", insn_idx, insns[insn_idx].code); return -LIBBPF_ERRNO__RELOC; } map_idx = sym.st_value / sizeof(struct bpf_map_def); if (map_idx >= nr_maps) { pr_warning("bpf relocation: map_idx %d large than %d\n", (int)map_idx, (int)nr_maps - 1); return -LIBBPF_ERRNO__RELOC; } prog->reloc_desc[i].insn_idx = insn_idx; prog->reloc_desc[i].map_idx = map_idx; } return 0; }
static Dwfl_Error relocate_section (Dwfl_Module *mod, Elf *relocated, const GElf_Ehdr *ehdr, size_t shstrndx, struct reloc_symtab_cache *reloc_symtab, Elf_Scn *scn, GElf_Shdr *shdr, Elf_Scn *tscn, bool debugscn, bool partial) { /* First, fetch the name of the section these relocations apply to. */ GElf_Shdr tshdr_mem; GElf_Shdr *tshdr = gelf_getshdr (tscn, &tshdr_mem); const char *tname = elf_strptr (relocated, shstrndx, tshdr->sh_name); if (tname == NULL) return DWFL_E_LIBELF; if (unlikely (tshdr->sh_type == SHT_NOBITS) || unlikely (tshdr->sh_size == 0)) /* No contents to relocate. */ return DWFL_E_NOERROR; if (debugscn && ! ebl_debugscn_p (mod->ebl, tname)) /* This relocation section is not for a debugging section. Nothing to do here. */ return DWFL_E_NOERROR; /* Fetch the section data that needs the relocations applied. */ Elf_Data *tdata = elf_rawdata (tscn, NULL); if (tdata == NULL) return DWFL_E_LIBELF; /* Apply one relocation. Returns true for any invalid data. */ Dwfl_Error relocate (GElf_Addr offset, const GElf_Sxword *addend, int rtype, int symndx) { /* First see if this is a reloc we can handle. If we are skipping it, don't bother resolving the symbol. */ if (unlikely (rtype == 0)) /* In some odd situations, the linker can leave R_*_NONE relocs behind. This is probably bogus ld -r behavior, but the only cases it's known to appear in are harmless: DWARF data referring to addresses in a section that has been discarded. So we just pretend it's OK without further relocation. */ return DWFL_E_NOERROR; Elf_Type type = ebl_reloc_simple_type (mod->ebl, rtype); if (unlikely (type == ELF_T_NUM)) return DWFL_E_BADRELTYPE; /* First, resolve the symbol to an absolute value. */ GElf_Addr value; if (symndx == STN_UNDEF) /* When strip removes a section symbol referring to a section moved into the debuginfo file, it replaces that symbol index in relocs with STN_UNDEF. We don't actually need the symbol, because those relocs are always references relative to the nonallocated debugging sections, which start at zero. */ value = 0; else { GElf_Sym sym; GElf_Word shndx; Dwfl_Error error = relocate_getsym (mod, relocated, reloc_symtab, symndx, &sym, &shndx); if (unlikely (error != DWFL_E_NOERROR)) return error; if (shndx == SHN_UNDEF || shndx == SHN_COMMON) { /* Maybe we can figure it out anyway. */ error = resolve_symbol (mod, reloc_symtab, &sym, shndx); if (error != DWFL_E_NOERROR && !(error == DWFL_E_RELUNDEF && shndx == SHN_COMMON)) return error; } value = sym.st_value; } /* These are the types we can relocate. */ #define TYPES DO_TYPE (BYTE, Byte); DO_TYPE (HALF, Half); \ DO_TYPE (WORD, Word); DO_TYPE (SWORD, Sword); \ DO_TYPE (XWORD, Xword); DO_TYPE (SXWORD, Sxword) size_t size; switch (type) { #define DO_TYPE(NAME, Name) \ case ELF_T_##NAME: \ size = sizeof (GElf_##Name); \ break TYPES; #undef DO_TYPE default: return DWFL_E_BADRELTYPE; } if (offset + size > tdata->d_size) return DWFL_E_BADRELOFF; #define DO_TYPE(NAME, Name) GElf_##Name Name; union { TYPES; } tmpbuf; #undef DO_TYPE Elf_Data tmpdata = { .d_type = type, .d_buf = &tmpbuf, .d_size = size, .d_version = EV_CURRENT, }; Elf_Data rdata = { .d_type = type, .d_buf = tdata->d_buf + offset, .d_size = size, .d_version = EV_CURRENT, }; /* XXX check for overflow? */ if (addend) { /* For the addend form, we have the value already. */ value += *addend; switch (type) { #define DO_TYPE(NAME, Name) \ case ELF_T_##NAME: \ tmpbuf.Name = value; \ break TYPES; #undef DO_TYPE default: abort (); } } else { /* Extract the original value and apply the reloc. */ Elf_Data *d = gelf_xlatetom (relocated, &tmpdata, &rdata, ehdr->e_ident[EI_DATA]); if (d == NULL) return DWFL_E_LIBELF; assert (d == &tmpdata); switch (type) { #define DO_TYPE(NAME, Name) \ case ELF_T_##NAME: \ tmpbuf.Name += (GElf_##Name) value; \ break TYPES; #undef DO_TYPE default: abort (); } } /* Now convert the relocated datum back to the target format. This will write into rdata.d_buf, which points into the raw section data being relocated. */ Elf_Data *s = gelf_xlatetof (relocated, &rdata, &tmpdata, ehdr->e_ident[EI_DATA]); if (s == NULL) return DWFL_E_LIBELF; assert (s == &rdata); /* We have applied this relocation! */ return DWFL_E_NOERROR; } /* Fetch the relocation section and apply each reloc in it. */ Elf_Data *reldata = elf_getdata (scn, NULL); if (reldata == NULL) return DWFL_E_LIBELF; Dwfl_Error result = DWFL_E_NOERROR; bool first_badreltype = true; inline void check_badreltype (void) { if (first_badreltype) { first_badreltype = false; if (ebl_get_elfmachine (mod->ebl) == EM_NONE) /* This might be because ebl_openbackend failed to find any libebl_CPU.so library. Diagnose that clearly. */ result = DWFL_E_UNKNOWN_MACHINE; } } size_t nrels = shdr->sh_size / shdr->sh_entsize; size_t complete = 0; if (shdr->sh_type == SHT_REL) for (size_t relidx = 0; !result && relidx < nrels; ++relidx) { GElf_Rel rel_mem, *r = gelf_getrel (reldata, relidx, &rel_mem); if (r == NULL) return DWFL_E_LIBELF; result = relocate (r->r_offset, NULL, GELF_R_TYPE (r->r_info), GELF_R_SYM (r->r_info)); check_badreltype (); if (partial) switch (result) { case DWFL_E_NOERROR: /* We applied the relocation. Elide it. */ memset (&rel_mem, 0, sizeof rel_mem); gelf_update_rel (reldata, relidx, &rel_mem); ++complete; break; case DWFL_E_BADRELTYPE: case DWFL_E_RELUNDEF: /* We couldn't handle this relocation. Skip it. */ result = DWFL_E_NOERROR; break; default: break; } } else for (size_t relidx = 0; !result && relidx < nrels; ++relidx) { GElf_Rela rela_mem, *r = gelf_getrela (reldata, relidx, &rela_mem); if (r == NULL) return DWFL_E_LIBELF; result = relocate (r->r_offset, &r->r_addend, GELF_R_TYPE (r->r_info), GELF_R_SYM (r->r_info)); check_badreltype (); if (partial) switch (result) { case DWFL_E_NOERROR: /* We applied the relocation. Elide it. */ memset (&rela_mem, 0, sizeof rela_mem); gelf_update_rela (reldata, relidx, &rela_mem); ++complete; break; case DWFL_E_BADRELTYPE: case DWFL_E_RELUNDEF: /* We couldn't handle this relocation. Skip it. */ result = DWFL_E_NOERROR; break; default: break; } } if (likely (result == DWFL_E_NOERROR)) { if (!partial || complete == nrels) /* Mark this relocation section as being empty now that we have done its work. This affects unstrip -R, so e.g. it emits an empty .rela.debug_info along with a .debug_info that has already been fully relocated. */ nrels = 0; else if (complete != 0) { /* We handled some of the relocations but not all. We've zeroed out the ones we processed. Now remove them from the section. */ size_t next = 0; if (shdr->sh_type == SHT_REL) for (size_t relidx = 0; relidx < nrels; ++relidx) { GElf_Rel rel_mem; GElf_Rel *r = gelf_getrel (reldata, relidx, &rel_mem); if (r->r_info != 0 || r->r_offset != 0) { if (next != relidx) gelf_update_rel (reldata, next, r); ++next; } } else for (size_t relidx = 0; relidx < nrels; ++relidx) { GElf_Rela rela_mem; GElf_Rela *r = gelf_getrela (reldata, relidx, &rela_mem); if (r->r_info != 0 || r->r_offset != 0 || r->r_addend != 0) { if (next != relidx) gelf_update_rela (reldata, next, r); ++next; } } nrels = next; } shdr->sh_size = reldata->d_size = nrels * shdr->sh_entsize; gelf_update_shdr (scn, shdr); } return result; } Dwfl_Error internal_function __libdwfl_relocate (Dwfl_Module *mod, Elf *debugfile, bool debug) { assert (mod->e_type == ET_REL); GElf_Ehdr ehdr_mem; const GElf_Ehdr *ehdr = gelf_getehdr (debugfile, &ehdr_mem); if (ehdr == NULL) return DWFL_E_LIBELF; size_t d_shstrndx; if (elf_getshdrstrndx (debugfile, &d_shstrndx) < 0) return DWFL_E_LIBELF; RELOC_SYMTAB_CACHE (reloc_symtab); /* Look at each section in the debuginfo file, and process the relocation sections for debugging sections. */ Dwfl_Error result = DWFL_E_NOERROR; Elf_Scn *scn = NULL; while (result == DWFL_E_NOERROR && (scn = elf_nextscn (debugfile, scn)) != NULL) { GElf_Shdr shdr_mem; GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem); if ((shdr->sh_type == SHT_REL || shdr->sh_type == SHT_RELA) && shdr->sh_size != 0) { /* It's a relocation section. */ Elf_Scn *tscn = elf_getscn (debugfile, shdr->sh_info); if (unlikely (tscn == NULL)) result = DWFL_E_LIBELF; else result = relocate_section (mod, debugfile, ehdr, d_shstrndx, &reloc_symtab, scn, shdr, tscn, debug, !debug); } } return result; }
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; }