int find_symbol(char *fn, struct lsym *lsym, unsigned long baseaddr) { struct lsym *ls; int num = 0; for (ls = lsym; ls->name; ls++) num++; elf_version(EV_CURRENT); int fd = open(fn, O_RDONLY); if (fd < 0) return -1; long ret = -1; Elf *elf = elf_begin(fd, ELF_C_READ, NULL); if (elf == NULL) goto out; GElf_Ehdr header; if (!gelf_getehdr(elf, &header)) goto out_elf; Elf_Scn *section = NULL; int found = 0; while (found < num && (section = elf_nextscn(elf, section)) != 0) { GElf_Shdr shdr, *sh; sh = gelf_getshdr(section, &shdr); if (sh->sh_type == SHT_SYMTAB || sh->sh_type == SHT_DYNSYM) { Elf_Data *data = elf_getdata(section, NULL); GElf_Sym *sym, symbol; int j; unsigned numsym = sh->sh_size / sh->sh_entsize; for (j = 0; j < numsym; j++) { sym = gelf_getsymshndx(data, NULL, j, &symbol, NULL); char *symname = elf_strptr(elf, shdr.sh_link, sym->st_name); for (ls = lsym; ls->name; ls++) { if (!strcmp(symname, ls->name)) { Elf_Scn *oscn = elf_getscn(elf, sym->st_shndx); GElf_Shdr oshdr, *osh; osh = gelf_getshdr(oscn, &oshdr); ls->addr = (sym->st_value - osh->sh_addr) + osh->sh_offset + baseaddr; found++; if (found == num) break; } } } } } if (found == num) ret = 0; out_elf: elf_end(elf); out: close(fd); return ret; }
std::string get_embedded_repo() { GElf_Shdr shdr; size_t shstrndx; char *name; Elf_Scn *scn; if (elf_version(EV_CURRENT) == EV_NONE) return ""; int fd = open("/proc/self/exe", O_RDONLY, 0); if (fd < 0) return ""; Elf* e = elf_begin(fd, ELF_C_READ, nullptr); if (!e || elf_kind(e) != ELF_K_ELF || !elf_getshstrndx(e, &shstrndx)) { return ""; } scn = nullptr; while ((scn = elf_nextscn(e, scn)) != nullptr) { if (gelf_getshdr(scn, &shdr) != &shdr || !(name = elf_strptr(e, shstrndx , shdr.sh_name))) { return ""; } if (!strcmp("repo", name)) { GElf_Shdr ghdr; if (gelf_getshdr(scn, &ghdr) != &ghdr) return ""; char buf[512]; sprintf(buf, "/proc/self/exe:%lu:%lu", ghdr.sh_offset, ghdr.sh_size); sqlite3_embedded_initialize(nullptr, true); return buf; } } return ""; }
Elf_Scn *elf_utils_new_scn_with_name(Elf *e, const char *scn_name) { Elf_Scn *scn; GElf_Shdr shdr; size_t shstrndx, index, namelen; Elf_Data *shstrdata; void *ptr; ELF_ASSERT(elf_getshdrstrndx(e, &shstrndx) == 0); ELF_ASSERT(scn = elf_getscn(e, shstrndx)); ELF_ASSERT(shstrdata = elf_getdata(scn, NULL)); namelen = strlen(scn_name) + 1; ELF_ASSERT(gelf_getshdr(scn, &shdr)); if (!elf_utils_shift_contents(e, shdr.sh_offset + shdr.sh_size, namelen)) goto failure; ASSERT(ptr = realloc(shstrdata->d_buf, shstrdata->d_size + namelen)); index = shstrdata->d_size; strcpy(ptr+index, scn_name); shstrdata->d_buf = ptr; shstrdata->d_size += namelen; shdr.sh_size += namelen; ELF_ASSERT(gelf_update_shdr(scn, &shdr)); ELF_ASSERT(scn = elf_newscn(e)); ELF_ASSERT(gelf_getshdr(scn, &shdr)); shdr.sh_name = index; ELF_ASSERT(gelf_update_shdr(scn, &shdr)); return scn; failure: return NULL; }
static int init_scns() { Elf* e = g.e; size_t shstrndx = g.shstrndx; size_t shdrnum = g.shdrnum; int i = 0; GElf_Shdr shdr; Elf_Scn** buf = (Elf_Scn**)malloc(shdrnum * sizeof(Elf_Scn*)); GElf_Shdr* buf2 = (GElf_Shdr*)malloc(shdrnum * sizeof(GElf_Shdr)); if (buf == NULL) { errx (EXIT_FAILURE , "malloc failed"); return -1; } Elf_Scn *scn = NULL; while ((scn = elf_nextscn(e, scn)) != NULL && i < shdrnum) { if (gelf_getshdr (scn , & shdr ) != & shdr) { errx ( EXIT_FAILURE , " getshdr () failed : %s.", elf_errmsg ( -1)); free(buf); return -1; } buf[i] = scn; buf2[i] = shdr; i++; } if (i < shdrnum) { /* the .shstrtab section*/ /* size_t shstrndx; */ /* if (elf_getshdrstrndx (e, &shstrndx) != 0) */ /* errx (EXIT_FAILURE, " getshdrstrndx () failed : %s.", */ /* elf_errmsg (-1)); */ if ((scn = elf_getscn (e, shstrndx)) == NULL ) errx ( EXIT_FAILURE , " getscn () failed : %s.", elf_errmsg ( -1)); if (gelf_getshdr(scn , &shdr) != & shdr ) errx ( EXIT_FAILURE , " getshdr ( shstrndx ) failed : %s.", elf_errmsg ( -1)); buf[i] = scn; buf2[i] = shdr; } // printf("[D] No. of sections:%d\n", i-1); g.scns = buf; g.shdrs = buf2; return 0; }
int ELF_build_symtbl(PROC_SYMTBL* symtbl){ uint32_t sym_num; Elf32_Sym * sym; int strtab_index = 0; scn = NULL; data = NULL; while((scn = elf_nextscn(e, scn)) != NULL){ if(gelf_getshdr(scn, &shdr) != &shdr){ fprintf(stderr, "getshdr() failed.\n"); exit(1); } strtab_index ++; char* name = elf_strptr(e, ehdr.e_shstrndx, shdr.sh_name); if(strcmp(name, ".strtab")==0) break; } scn = NULL; while((scn = elf_nextscn(e, scn)) != NULL){ if(gelf_getshdr(scn, &shdr) != &shdr){ fprintf(stderr, "getshdr() failed.\n"); exit(1); } char* name = elf_strptr(e, ehdr.e_shstrndx, shdr.sh_name); if(strcmp(name, ".symtab")==0){ data = elf_getdata(scn, data); sym_num = data->d_size/sizeof(Elf32_Sym); symtbl->sym_num = sym_num; // initial symtbl->name symtbl->name = malloc(sizeof(char*) * sym_num); int i; for(i=0; i<sym_num; i++) (symtbl->name)[i] = malloc(sizeof(char) * 100); // initial symtbl addr symtbl->addr = malloc(sizeof(uint32_t) * sym_num); // initial symtbl st_info symtbl->st_info = malloc(sizeof(unsigned char) * sym_num); sym = (Elf32_Sym*)data->d_buf; for(i=0; i<sym_num; i++){ name = elf_strptr(e, strtab_index, sym[i].st_name); strcpy(symtbl->name[i], name); symtbl->addr[i] = sym[i].st_value; symtbl->st_info[i] = sym[i].st_info; } } } return 1; }
static void handle_dynamic_section(elf_info_s *elf, Elf_Scn *scn, GElf_Shdr shdr) { Elf_Data *data; GElf_Addr replt_addr; size_t replt_count; /* get data of .dynamic */ data = elf_getdata(scn, NULL); /* iterate through .dynamic */ for (size_t i = 0; i < shdr.sh_size / shdr.sh_entsize; ++i) { GElf_Dyn dyn; // get entries i gelf_getdyn(data, i, &dyn); // if replt if (dyn.d_tag == DT_JMPREL) replt_addr = dyn.d_un.d_ptr; // if replt_size if (dyn.d_tag == DT_PLTRELSZ) replt_count = dyn.d_un.d_val; } LOG(INFO, "Section relplt at 0x%lx (%zu)", replt_addr, replt_count); for (size_t i = 1; i < elf->hdr.e_shnum; ++i) { Elf_Scn *scn; GElf_Shdr shdr; scn = elf_getscn(elf->elf, i); gelf_getshdr(scn, &shdr); if (shdr.sh_addr == replt_addr && shdr.sh_size == replt_count) { elf->replt = elf_getdata(scn, NULL); elf->replt_count = shdr.sh_size / shdr.sh_entsize; break; } } }
static elf_info_s *elf_symbols(int fd) { /* Open Elf */ elf_version(EV_CURRENT); elf_info_s *elf = calloc(1, sizeof (elf_info_s)); elf->elf = elf_begin(fd, ELF_C_READ, NULL); gelf_getehdr(elf->elf, &elf->hdr); /* Iterate through the sections */ Elf_Scn *scn = NULL; while ((scn = elf_nextscn(elf->elf, scn)) != 0) { GElf_Shdr shdr; const char *name; /* get section header */ gelf_getshdr(scn, &shdr); /* get section name */ name = elf_strptr(elf->elf, elf->hdr.e_shstrndx, shdr.sh_name); //LOG(INFO, "Iter on %s", name); if (shdr.sh_type == SHT_DYNSYM) handle_dynsym_section(elf, scn, shdr); else if (shdr.sh_type == SHT_DYNAMIC) handle_dynamic_section(elf, scn, shdr); else if ((shdr.sh_type == SHT_PROGBITS || shdr.sh_type == SHT_NOBITS) && !strcmp(name, ".plt")) handle_plt_section(elf, shdr); else if (!strcmp(name, ".got.plt")) handle_gotplt_section(elf, shdr); } return elf; }
/* Below code adapted from libelf tutorial example */ static u32 extract_functions_internal (const char *str, func_entry *func_list) { Elf *e; Elf_Kind ek; Elf_Scn *scn; Elf_Data *edata; u32 fd, i, symbol_count; GElf_Sym sym; GElf_Shdr shdr; u32 func_count = 0; if(elf_version(EV_CURRENT) == EV_NONE) { printf("Error initializing ELF: %s\n", elf_errmsg(-1)); return -1; } if ((fd = open(str, O_RDONLY, 0)) < 0) { printf("Unable to open %s\n", str); return -1; } if ((e = elf_begin(fd, ELF_C_READ, NULL)) == NULL) { printf("elf_begin failed: %s\n", elf_errmsg(-1)); } ek = elf_kind(e); if(ek != ELF_K_ELF) { printf("not an ELF object"); } else { scn = NULL; edata = NULL; while((scn = elf_nextscn(e, scn)) != NULL) { gelf_getshdr(scn, &shdr); if(shdr.sh_type == SHT_SYMTAB) { edata = elf_getdata(scn, edata); symbol_count = shdr.sh_size / shdr.sh_entsize; for(i = 0; i < symbol_count; i++) { gelf_getsym(edata, i, &sym); if(ELF32_ST_TYPE(sym.st_info) != STT_FUNC) { check_for_end_marker(elf_strptr(e, shdr.sh_link, sym.st_name), sym.st_value); continue; } if(sym.st_size == 0) continue; func_list[func_count].offset = sym.st_value; func_list[func_count++].func_name = strdup(elf_strptr(e, shdr.sh_link, sym.st_name)); if(func_count >= MAXFNS) { printf("Func limit (%"PRId32") reached, please increase MAXFNS & rebuild\n", MAXFNS); raise(SIGABRT); } // printf("%08x %08x\t%s\n", sym.st_value, sym.st_size, elf_strptr(e, shdr.sh_link, sym.st_name)); } } } } elf_end(e); close(fd); return func_count; }
/* Check if Symbol Table exists */ static _Bool check_symbol_table(void) { Elf_Scn *section = 0; int number = 0; while ((section = elf_nextscn(elf, section)) != 0) { char *name = 0; if (gelf_getshdr (section, &symtab_shdr) != 0) { if (symtab_shdr.sh_type == SHT_SYMTAB) { /* Change SHT_SYMTAB to SHT_DYNSYM * to access the dynamic symbol table */ printf("Found Symbol Table\n"); symtab_section = section; /* You can use the function given below to pri nt * out the symbol table * print_symbols(elf, section, shdr); */ return TRUE; } } } /* no symtab */ printf("No symbol table found.\n"); return FALSE; }
int findelfsecidx(Elf *elf, const char *file, const char *tofind) { Elf_Scn *scn = NULL; GElf_Ehdr ehdr; GElf_Shdr shdr; if (gelf_getehdr(elf, &ehdr) == NULL) elfterminate(file, "Couldn't read ehdr"); while ((scn = elf_nextscn(elf, scn)) != NULL) { char *name; if (gelf_getshdr(scn, &shdr) == NULL) { elfterminate(file, "Couldn't read header for section %d", elf_ndxscn(scn)); } if ((name = elf_strptr(elf, ehdr.e_shstrndx, (size_t)shdr.sh_name)) == NULL) { elfterminate(file, "Couldn't get name for section %d", elf_ndxscn(scn)); } if (strcmp(name, tofind) == 0) return (elf_ndxscn(scn)); } return (-1); }
int find_injected_secaddr(elf_data_t *elf, inject_data_t *inject) { Elf_Scn *scn; GElf_Shdr shdr; uint64_t max_inject_addr = 0; char* s; size_t shstrndx; if(elf_getshdrstrndx(elf->e, &shstrndx) < 0) { return -1; } scn = NULL; while((scn = elf_nextscn(elf->e, scn))) { if(!gelf_getshdr(scn, &shdr)) { return -1; } s = elf_strptr(elf->e, shstrndx, shdr.sh_name); if(!s) { return -1; } if(!strcmp(s, DYNINST_NAME)) fprintf(finfo,"dyninst end=%lx\n",shdr.sh_addr + shdr.sh_size); if (shdr.sh_addr + shdr.sh_offset > max_inject_addr) max_inject_addr = shdr.sh_addr + shdr.sh_size; } inject->secaddr = max_inject_addr + inject->len + 0x4000; return 0; }
int elf_getphnum(Elf *elf, size_t *phnum) { GElf_Ehdr ehdr; Elf_Scn *scn; GElf_Shdr shdr0; if (gelf_getehdr(elf, &ehdr) == NULL) return (0); if (ehdr.e_phnum != PN_XNUM) { *phnum = ehdr.e_phnum; return (1); } if ((scn = elf_getscn(elf, 0)) == NULL || gelf_getshdr(scn, &shdr0) == NULL) return (0); if (shdr0.sh_info == 0) *phnum = ehdr.e_phnum; else *phnum = shdr0.sh_info; return (1); }
Elf_Scn *elf_utils_new_scn_with_data(Elf *e, const char *scn_name, void *buf, int len) { Elf_Scn *scn; GElf_Ehdr ehdr; GElf_Shdr shdr; Elf_Data *data; int offset; scn = elf_utils_new_scn_with_name(e, scn_name); if (scn == NULL) goto failure; ELF_ASSERT(gelf_getehdr(e, &ehdr)); offset = ehdr.e_shoff; if (!elf_utils_shift_contents(e, offset, len)) goto failure; ELF_ASSERT(gelf_getshdr(scn, &shdr)); shdr.sh_offset = offset; shdr.sh_size = len; shdr.sh_addralign = 1; ELF_ASSERT(gelf_update_shdr(scn, &shdr)); ELF_ASSERT(data = elf_newdata(scn)); data->d_buf = buf; data->d_type = ELF_T_BYTE; data->d_version = EV_CURRENT; data->d_size = len; data->d_off = 0; data->d_align = 1; return scn; failure: return NULL; }
/** * @brief Search a single, particular ELF symbol table for a named symbol * * @param elf The open ELF object * @param symtab The ELF symbol table section * @param name The symbol name to find * * @returns The address to which the symbol points, 0 otherwise. */ static GElf_Addr elf_scn_getsymaddr_byname(Elf *elf, Elf_Scn *symtab, const char * name) { GElf_Shdr shdr; Elf_Data *data; uint32_t syms, i; GElf_Sym sym; if (gelf_getshdr(symtab, &shdr) == NULL || shdr.sh_type != SHT_SYMTAB) { return 0; } data = elf_getdata(symtab, NULL); if (data == NULL) { return 0; } syms = shdr.sh_size / shdr.sh_entsize; for(i=0; i<syms; i++) { gelf_getsym(data, i, &sym); if (strcmp(elf_strptr(elf, shdr.sh_link, sym.st_name), name) == 0) { return sym.st_value; } } return 0; }
/** * @brief Search an elf for a named section * * @param elf The open elf object * @param name The section name to find * * @returns A pointer to the section if successful, NULL otherwise. */ static Elf_Scn * elf_getscn_byname(Elf *elf, const char * name) { Elf_Scn *scn = NULL; size_t shstrndx; GElf_Shdr shdr; char *section_name; if (elf_getshdrstrndx(elf, &shstrndx) != 0) { fprintf(stderr, "elf_getshdrstrndx() failed: %s\n", elf_errmsg(-1)); } else { /** * Iterate over the sections in the ELF descriptor to get the indices * of the .text and .data descriptors */ while ((scn = elf_nextscn(elf, scn)) != NULL) { if (gelf_getshdr(scn, &shdr) != &shdr) { fprintf(stderr, "getshdr() failed: %s\n", elf_errmsg(-1)); } else { section_name = elf_strptr(elf, shstrndx, shdr.sh_name); if (section_name == NULL) { fprintf(stderr, "elf_strptr() failed: %s\n", elf_errmsg(-1)); } else if (strcmp(section_name, name) == 0) { break; } } } } return scn; }
static Elf_Scn *elf_section_by_name(Elf *elf, GElf_Ehdr *ep, GElf_Shdr *shp, const char *name, size_t *idx) { Elf_Scn *sec = NULL; size_t cnt = 1; /* Elf is corrupted/truncated, avoid calling elf_strptr. */ if (!elf_rawdata(elf_getscn(elf, ep->e_shstrndx), NULL)) return NULL; while ((sec = elf_nextscn(elf, sec)) != NULL) { char *str; gelf_getshdr(sec, shp); str = elf_strptr(elf, ep->e_shstrndx, shp->sh_name); if (!strcmp(name, str)) { if (idx) *idx = cnt; break; } ++cnt; } return sec; }
int rewrite_section_name(elf_data_t *elf, inject_data_t *inject, char **err) { Elf_Scn *scn; GElf_Shdr shdr; char *s; size_t shstrndx, stroff, strbase; if(strlen(inject->secname) > strlen(ABITAG_NAME)) { (*err) = "section name too long"; return -1; } if(elf_getshdrstrndx(elf->e, &shstrndx) < 0) { (*err) = "failed to get string table section index"; return -1; } stroff = 0; strbase = 0; scn = NULL; while((scn = elf_nextscn(elf->e, scn))) { if(!gelf_getshdr(scn, &shdr)) { (*err) = "failed to get section header"; return -1; } s = elf_strptr(elf->e, shstrndx, shdr.sh_name); if(!s) { (*err) = "failed to get section name"; return -1; } if(!strcmp(s, ABITAG_NAME)) { stroff = shdr.sh_name; /* offset into shstrtab */ } else if(!strcmp(s, SHSTRTAB_NAME)) { strbase = shdr.sh_offset; /* offset to start of shstrtab */ } } if(stroff == 0) { (*err) = "cannot find shstrtab entry for injected section"; return -1; } else if(strbase == 0) { (*err) = "cannot find shstrtab"; return -1; } inject->shstroff = strbase + stroff; verbose("renaming rewritten section to \"%s\"", inject->secname); verbose("writing section string table to file"); if(write_secname(elf, inject, err) < 0) { return -1; } return 0; }
/* Try to find a symbol table in FILE. Returns DWFL_E_NOERROR if a proper one is found. Returns DWFL_E_NO_SYMTAB if not, but still sets results for SHT_DYNSYM. */ static Dwfl_Error load_symtab (struct dwfl_file *file, struct dwfl_file **symfile, Elf_Scn **symscn, Elf_Scn **xndxscn, size_t *syments, int *first_global, GElf_Word *strshndx) { bool symtab = false; Elf_Scn *scn = NULL; while ((scn = elf_nextscn (file->elf, scn)) != NULL) { GElf_Shdr shdr_mem, *shdr = gelf_getshdr (scn, &shdr_mem); if (shdr != NULL) switch (shdr->sh_type) { case SHT_SYMTAB: if (shdr->sh_entsize == 0) break; symtab = true; *symscn = scn; *symfile = file; *strshndx = shdr->sh_link; *syments = shdr->sh_size / shdr->sh_entsize; *first_global = shdr->sh_info; if (*xndxscn != NULL) return DWFL_E_NOERROR; break; case SHT_DYNSYM: if (symtab) break; /* Use this if need be, but keep looking for SHT_SYMTAB. */ if (shdr->sh_entsize == 0) break; *symscn = scn; *symfile = file; *strshndx = shdr->sh_link; *syments = shdr->sh_size / shdr->sh_entsize; *first_global = shdr->sh_info; break; case SHT_SYMTAB_SHNDX: *xndxscn = scn; if (symtab) return DWFL_E_NOERROR; break; default: break; } } if (symtab) /* We found one, though no SHT_SYMTAB_SHNDX to go with it. */ return DWFL_E_NOERROR; /* We found no SHT_SYMTAB, so any SHT_SYMTAB_SHNDX was bogus. We might have found an SHT_DYNSYM and set *SYMSCN et al though. */ *xndxscn = NULL; return DWFL_E_NO_SYMTAB; }
bool addr_in_section (Elf *elf, GElf_Word shndx, GElf_Addr addr) { GElf_Shdr shdr; Elf_Scn *scn = elf_getscn (elf, shndx); gelf_getshdr (scn, &shdr); return addr >= shdr.sh_addr && addr < shdr.sh_addr + shdr.sh_size; }
/** * Finds a section by its name in an ELF file. * @param elf * A libelf handle representing the file. * @param section_name * Name of section to be found. * @param data_dest * Save the resulting elf data pointer here. Cannot be NULL. * @param shdr_dest * Save the section header here. Cannot be NULL. * @param error_message * Will be filled by an error message if the function fails (returns * zero). Caller is responsible for calling free() on the string * pointer. If function succeeds, the pointer is not touched by the * function. * @returns * Zero on error, index of the section on success. */ static unsigned find_elf_section_by_name(Elf *elf, const char *section_name, Elf_Data **data_dest, GElf_Shdr *shdr_dest, char **error_message) { /* Find the string table index */ size_t shdr_string_index; if (0 != elf_getshdrstrndx(elf, &shdr_string_index)) { *error_message = sr_asprintf("elf_getshdrstrndx failed"); return 0; } unsigned section_index = 0; Elf_Scn *section = NULL; while ((section = elf_nextscn(elf, section)) != NULL) { /* Starting index is 1. */ ++section_index; GElf_Shdr shdr; if (gelf_getshdr(section, &shdr) != &shdr) { *error_message = sr_asprintf("gelf_getshdr failed"); return 0; } const char *current_section_name = elf_strptr(elf, shdr_string_index, shdr.sh_name); if (!current_section_name) { *error_message = sr_asprintf("elf_strptr failed"); return 0; } if (0 == strcmp(current_section_name, section_name)) { /* We found the right section! Save the data. */ *data_dest = elf_getdata(section, NULL); if (!*data_dest) { *error_message = sr_asprintf("elf_getdata failed"); return 0; } /* Save the section header. */ *shdr_dest = shdr; return section_index; } } *error_message = sr_asprintf("Section %s not found", section_name); return 0; }
static void find_section_base(const char *exe, Elf *e, const char *section) { Dwarf_Addr off; Elf_Scn *scn; GElf_Ehdr eh; GElf_Shdr sh; size_t shstrndx; int elferr; const char *name; if (gelf_getehdr(e, &eh) != &eh) { warnx("gelf_getehdr failed: %s", elf_errmsg(-1)); return; } if (!elf_getshstrndx(e, &shstrndx)) { warnx("elf_getshstrndx failed: %s", elf_errmsg(-1)); return; } (void) elf_errno(); off = 0; scn = NULL; while ((scn = elf_nextscn(e, scn)) != NULL) { if (gelf_getshdr(scn, &sh) == NULL) { warnx("gelf_getshdr failed: %s", elf_errmsg(-1)); continue; } if ((name = elf_strptr(e, shstrndx, sh.sh_name)) == NULL) goto next; if (!strcmp(section, name)) { if (eh.e_type == ET_EXEC || eh.e_type == ET_DYN) { /* * For executables, section base is the virtual * address of the specified section. */ section_base = sh.sh_addr; } else if (eh.e_type == ET_REL) { /* * For relocatables, section base is the * relative offset of the specified section * to the start of the first section. */ section_base = off; } else warnx("unknown e_type %u", eh.e_type); return; } next: off += sh.sh_size; } elferr = elf_errno(); if (elferr != 0) warnx("elf_nextscn failed: %s", elf_errmsg(elferr)); errx(EXIT_FAILURE, "%s: cannot find section %s", exe, section); }
const char *get_scn_name(vita_elf_t *ve, Elf_Scn *scn) { size_t shstrndx; GElf_Shdr shdr; elf_getshdrstrndx(ve->elf, &shstrndx); gelf_getshdr(scn, &shdr); return elf_strptr(ve->elf, shstrndx, shdr.sh_name); }
/* * @param e elf handle * @param name name of section to be found * @param filename filename for logging messages * @param dest save the resulting elf data pointer here (can be NULL) * @param shdr_dest save the section header here (can be NULL) * @returns zero on error, index of the section on success */ static unsigned xelf_section_by_name(Elf *e, const char *name, const char *filename, Elf_Data **dest, GElf_Shdr *shdr_dest) { Elf_Scn *scn = NULL; GElf_Shdr shdr; unsigned section_index = 0; size_t shstrndx; /* Find the string table index */ if (elf_getshdrstrndx(e, &shstrndx) != 0) { VERB1 log_elf_error("elf_getshdrstrndx", filename); return 0; } while ((scn = elf_nextscn(e, scn)) != NULL) { section_index++; /* starting index is 1 */ if (gelf_getshdr(scn, &shdr) != &shdr) { VERB1 log_elf_error("gelf_getshdr", filename); continue; } const char *scnname = elf_strptr(e, shstrndx, shdr.sh_name); if (scnname == NULL) { VERB1 log_elf_error("elf_strptr", filename); continue; } if (strcmp(scnname, name) == 0) { /* Found, save data */ if (dest) { *dest = elf_getdata(scn, NULL); if (*dest == NULL) { VERB1 log_elf_error("elf_getdata", filename); break; } } /* save shdr */ if (shdr_dest) { *shdr_dest = shdr; } return section_index; } } VERB1 log("Section %s not found in %s\n", name, filename); return 0; }
static void check_section (Dwarf *result, GElf_Ehdr *ehdr, Elf_Scn *scn, bool inscngrp) { GElf_Shdr shdr_mem; GElf_Shdr *shdr; /* Get the section header data. */ shdr = gelf_getshdr (scn, &shdr_mem); if (shdr == NULL) /* This should never happen. If it does something is wrong in the libelf library. */ abort (); /* Make sure the section is part of a section group only iff we really need it. If we are looking for the global (= non-section group debug info) we have to ignore all the info in section groups. If we are looking into a section group we cannot look at a section which isn't part of the section group. */ if (! inscngrp && (shdr->sh_flags & SHF_GROUP) != 0) /* Ignore the section. */ return; /* We recognize the DWARF section by their names. This is not very safe and stable but the best we can do. */ const char *scnname = elf_strptr (result->elf, ehdr->e_shstrndx, shdr->sh_name); if (scnname == NULL) { /* The section name must be valid. Otherwise is the ELF file invalid. */ __libdw_seterrno (DWARF_E_INVALID_ELF); free (result); return; } /* Recognize the various sections. Most names start with .debug_. */ size_t cnt; for (cnt = 0; cnt < ndwarf_scnnames; ++cnt) if (strcmp (scnname, dwarf_scnnames[cnt]) == 0) { /* Found it. Remember where the data is. */ if (unlikely (result->sectiondata[cnt] != NULL)) /* A section appears twice. That's bad. We ignore the section. */ break; /* Get the section data. */ Elf_Data *data = elf_getdata (scn, NULL); if (data != NULL && data->d_size != 0) /* Yep, there is actually data available. */ result->sectiondata[cnt] = data; break; } }
static void update_dyn_cache(ElfCreator *ctor) { ctor->dynscn = get_scn_by_type(ctor, SHT_DYNAMIC); if (ctor->dynscn == NULL) return; ctor->dynshdr = gelf_getshdr(ctor->dynscn, &ctor->dynshdr_mem); ctor->dyndata = elf_getdata(ctor->dynscn, NULL); }
int internal_function __libdwfl_find_build_id (Dwfl_Module *mod, bool set, Elf *elf) { size_t shstrndx = SHN_UNDEF; int result = 0; Elf_Scn *scn = elf_nextscn (elf, NULL); if (scn == NULL) { /* No sections, have to look for phdrs. */ GElf_Ehdr ehdr_mem; GElf_Ehdr *ehdr = gelf_getehdr (elf, &ehdr_mem); size_t phnum; if (unlikely (ehdr == NULL) || unlikely (elf_getphdrnum (elf, &phnum) != 0)) { __libdwfl_seterrno (DWFL_E_LIBELF); return -1; } for (size_t i = 0; result == 0 && i < phnum; ++i) { GElf_Phdr phdr_mem; GElf_Phdr *phdr = gelf_getphdr (elf, i, &phdr_mem); if (likely (phdr != NULL) && phdr->p_type == PT_NOTE) result = check_notes (mod, set, elf_getdata_rawchunk (elf, phdr->p_offset, phdr->p_filesz, ELF_T_NHDR), phdr->p_vaddr + mod->main.bias); } } else do { GElf_Shdr shdr_mem; GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem); if (likely (shdr != NULL) && shdr->sh_type == SHT_NOTE) { /* Determine the right sh_addr in this module. */ GElf_Addr vaddr = 0; if (!(shdr->sh_flags & SHF_ALLOC)) vaddr = NO_VADDR; else if (mod->e_type != ET_REL) vaddr = shdr->sh_addr + mod->main.bias; else if (__libdwfl_relocate_value (mod, elf, &shstrndx, elf_ndxscn (scn), &vaddr)) vaddr = NO_VADDR; result = check_notes (mod, set, elf_getdata (scn, NULL), vaddr); } } while (result == 0 && (scn = elf_nextscn (elf, scn)) != NULL); return result; }
static void set_flag(char *ifile, ulong_t flval) { Elf *elf; Elf_Scn *scn; Elf_Data *data; GElf_Shdr shdr; GElf_Dyn dyn; int fd, secidx, nent, i; (void) elf_version(EV_CURRENT); if ((fd = open(ifile, O_RDWR)) < 0) die("Can't open %s", ifile); if ((elf = elf_begin(fd, ELF_C_RDWR, NULL)) == NULL) elfdie("Can't start ELF for %s", ifile); if ((secidx = findelfsecidx(elf, ".dynamic")) == -1) die("Can't find .dynamic section in %s\n", ifile); if ((scn = elf_getscn(elf, secidx)) == NULL) elfdie("elf_getscn (%d)", secidx); if (gelf_getshdr(scn, &shdr) == NULL) elfdie("gelf_shdr"); if ((data = elf_getdata(scn, NULL)) == NULL) elfdie("elf_getdata"); nent = shdr.sh_size / shdr.sh_entsize; for (i = 0; i < nent; i++) { if (gelf_getdyn(data, i, &dyn) == NULL) elfdie("gelf_getdyn"); if (dyn.d_tag == DT_FLAGS_1) { dyn.d_un.d_val |= (Elf64_Xword)flval; if (gelf_update_dyn(data, i, &dyn) == 0) elfdie("gelf_update_dyn"); break; } } if (i == nent) { die("%s's .dynamic section doesn't have a DT_FLAGS_1 " "field\n", ifile); } if (elf_update(elf, ELF_C_WRITE) == -1) elfdie("Couldn't update %s with changes", ifile); (void) elf_end(elf); (void) close(fd); }
uint8_t *dump_section_data(Elf *elf_object, int *size) { uint8_t *buffer = NULL; Elf_Data *data = NULL; size_t shdr_num; size_t max_saddr = 0; GElf_Shdr shdr; size_t shstrndx; char *name = NULL; *size = 0; int ret = elf_getshdrnum(elf_object, &shdr_num); if (ret) { printf("Problem during ELF parsing\n"); return NULL; } if (shdr_num == 0) return NULL; Elf_Scn *cur_section = NULL; ret = elf_getshdrstrndx(elf_object, &shstrndx); if (ret) printf("No string table found\n"); while ((cur_section = elf_nextscn(elf_object, cur_section)) != NULL ) { if (gelf_getshdr(cur_section, &shdr) != &shdr) { printf("Problem during ELF parsing\n"); return NULL; } if ((shdr.sh_type == SHT_PROGBITS) && (shdr.sh_flags & SHF_ALLOC) && shdr.sh_size != 0) { name = elf_strptr(elf_object, shstrndx , shdr.sh_name); printf("Loading section %s, size 0x%08X lma 0x%08X\n", name ? name : "??", (unsigned int)shdr.sh_size, (unsigned int)shdr.sh_addr); if (shdr.sh_addr + shdr.sh_size >= max_saddr) { max_saddr = shdr.sh_addr + shdr.sh_size; buffer = realloc(buffer, max_saddr); } data = elf_getdata(cur_section, data); if (data != NULL) memcpy(buffer + shdr.sh_addr, data->d_buf, data->d_size); else { printf("Couldn't load section data chunk\n"); return NULL; } } } *size = max_saddr; return buffer; }
static const char * elf_section_name (Elf *elf, GElf_Word shndx) { GElf_Ehdr ehdr; GElf_Shdr shdr; Elf_Scn *scn = elf_getscn (elf, shndx); gelf_getshdr (scn, &shdr); gelf_getehdr (elf, &ehdr); return elf_strptr (elf, ehdr.e_shstrndx, shdr.sh_name); }
/* * Print the symbol table. This function does not print the contents * of the symbol table but sets up the parameters and then calls * print_symtab to print the symbols. This function does not assume * that there is only one section of type SYMTAB. Input is an opened * ELF file, a pointer to the ELF header, and the filename. */ static void get_symtab(Elf *elf_file, char *filename) { Elf_Scn *scn, *scnfd; Elf_Data *data; GElf_Word symtabtype; size_t shstrndx; if (elf_getshdrstrndx(elf_file, &shstrndx) == -1) { (void) fprintf(stderr, gettext( "%s: %s: cannot get e_shstrndx\n"), prog_name, filename); return; } /* get section header string table */ scnfd = get_scnfd(elf_file, shstrndx, SHT_STRTAB); if (scnfd == NULL) { (void) fprintf(stderr, gettext( "%s: %s: cannot get string table\n"), prog_name, filename); return; } data = elf_getdata(scnfd, NULL); if (data->d_size == 0) { (void) fprintf(stderr, gettext( "%s: %s: no data in string table\n"), prog_name, filename); return; } if (D_flag) symtabtype = SHT_DYNSYM; else if (L_flag) symtabtype = SHT_SUNW_LDYNSYM; else symtabtype = SHT_SYMTAB; scn = 0; while ((scn = elf_nextscn(elf_file, scn)) != 0) { GElf_Shdr shdr; if (gelf_getshdr(scn, &shdr) == NULL) { (void) fprintf(stderr, "%s: %s: %s:\n", prog_name, filename, elf_errmsg(-1)); return; } if (shdr.sh_type == symtabtype) { print_symtab(elf_file, shstrndx, scn, &shdr, filename); } } /* end while */ }