static ExportTrampolineVector FindExportTrampolines(Elf *e, const ElfSectionInfo &xptramp_info) { auto sym_scn = FindSectionByType(e, SHT_DYNSYM); auto sym_data = elf_getdata(sym_scn.first, nullptr); auto syms = reinterpret_cast<Elf_Sym*>(sym_data->d_buf); ExportTrampolineVector res; // FIXME: this assumes that the whole section // is inside a single Elf_Data object auto xptramp_data = elf_getdata(xptramp_info.first, nullptr); auto xptramp_start = reinterpret_cast<uint8_t*>(xptramp_data->d_buf); auto xptramp_end = xptramp_start + xptramp_data->d_size; for (auto ptr = xptramp_start; ptr < xptramp_end;) { auto addr = xptramp_info.second.sh_addr + xptramp_data->d_off + (ptr - xptramp_start); auto ofs = xptramp_info.second.sh_offset + xptramp_data->d_off + (ptr - xptramp_start); auto arg = *reinterpret_cast<uint32_t*>(ptr + 1); switch(ptr[0]) { case 0x01: res.emplace_back(addr, ofs, syms[arg].st_value); break; case 0xE9: break; default: errx(EX_SOFTWARE, ".xptramp section has invalid byte: %hhd\n", ptr[0]); } ptr += 5; } return res; }
unsigned char * get_data_from_iterator (struct data_iterator *it, GElf_Addr size) { unsigned char *ptr; /* If we're at the end of a data block, move onto the next. */ if (it->data && it->data->d_off + it->data->d_size == it->sec_offset) it->data = elf_getdata (it->dso->scn[it->sec], it->data); if (it->data == NULL) { /* Find out which section contains the next byte. */ it->sec = addr_to_sec (it->dso, it->addr); if (it->sec < 0) return NULL; /* Fast-forward to the block that contains ADDR, if any. */ it->sec_offset = it->addr - it->dso->shdr[it->sec].sh_addr; do it->data = elf_getdata (it->dso->scn[it->sec], it->data); while (it->data && it->data->d_off + it->data->d_size <= it->sec_offset); } /* Make sure that all the data we want is included in this block. */ if (it->data == NULL || it->data->d_off > it->sec_offset || it->data->d_off + it->data->d_size < it->sec_offset + size) return NULL; ptr = (unsigned char *) it->data->d_buf + (it->sec_offset - it->data->d_off); it->sec_offset += size; it->addr += size; return ptr; }
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 void resolve_relocations(sym_strtab **list) { Elf_Scn *scn; Elf64_Shdr *shdr; scn = NULL; while ((scn = elf_nextscn(e, scn))) { if ((shdr = elf64_getshdr(scn)) == NULL) exit_error("gelf_getshdr() fail"); if (shdr->sh_type == SHT_DYNSYM) { Elf_Data *data; data = elf_getdata(scn, NULL); dynsym_tab = (Elf64_Sym*)data->d_buf; } if (shdr->sh_type == SHT_STRTAB && shdr->sh_flags == SHF_ALLOC) { Elf_Data *data; data = elf_getdata(scn, NULL); dynsym_strtab = (char*)data->d_buf; } } if (!dynsym_tab) return; scn = NULL; while ((scn = elf_nextscn(e, scn))) { if ((shdr = elf64_getshdr(scn)) == NULL) exit_error("gelf_getshdr() fail"); if (shdr->sh_type == SHT_RELA) reloc_treatment(scn, shdr, list); } }
static Elf_Data *loaddata(Elf_Scn *scn, GElf_Shdr *shdr) { Elf_Data *data = elf_getdata(scn, NULL); if (data == NULL || elf_getdata(scn, data) != NULL || data->d_off || data->d_size != shdr->sh_size) return NULL; return data; }
void radeon_elf_read(const char *elf_data, unsigned elf_size, struct radeon_shader_binary *binary, unsigned debug) { char *elf_buffer; Elf *elf; Elf_Scn *section = NULL; size_t section_str_index; /* One of the libelf implementations * (http://www.mr511.de/software/english.htm) requires calling * elf_version() before elf_memory(). */ elf_version(EV_CURRENT); elf_buffer = MALLOC(elf_size); memcpy(elf_buffer, elf_data, elf_size); elf = elf_memory(elf_buffer, elf_size); elf_getshdrstrndx(elf, §ion_str_index); binary->disassembled = 0; while ((section = elf_nextscn(elf, section))) { const char *name; Elf_Data *section_data = NULL; GElf_Shdr section_header; if (gelf_getshdr(section, §ion_header) != §ion_header) { fprintf(stderr, "Failed to read ELF section header\n"); return; } name = elf_strptr(elf, section_str_index, section_header.sh_name); if (!strcmp(name, ".text")) { section_data = elf_getdata(section, section_data); binary->code_size = section_data->d_size; binary->code = MALLOC(binary->code_size * sizeof(unsigned char)); memcpy(binary->code, section_data->d_buf, binary->code_size); } else if (!strcmp(name, ".AMDGPU.config")) { section_data = elf_getdata(section, section_data); binary->config_size = section_data->d_size; binary->config = MALLOC(binary->config_size * sizeof(unsigned char)); memcpy(binary->config, section_data->d_buf, binary->config_size); } else if (debug && !strcmp(name, ".AMDGPU.disasm")) { binary->disassembled = 1; section_data = elf_getdata(section, section_data); fprintf(stderr, "\nShader Disassembly:\n\n"); fprintf(stderr, "%.*s\n", (int)section_data->d_size, (char *)section_data->d_buf); } } if (elf){ elf_end(elf); } FREE(elf_buffer); }
struct trap_data_t read_trap_data(struct trap_file_t *file) { struct trap_data_t res = { TRAP_PLATFORM_UNKNOWN, 0, 0, NULL, 0 }; Elf_Scn *txtrp_scn = find_section(file->elf, ".txtrp"); if (txtrp_scn == NULL) return res; GElf_Shdr shdr; if (gelf_getshdr(txtrp_scn, &shdr) == NULL) errx(EXIT_FAILURE, "Cannot get section header"); res.txtrp_address = shdr.sh_addr; // Get the platform GElf_Ehdr ehdr; if (gelf_getehdr(file->elf, &ehdr) == NULL) errx(EXIT_FAILURE, "Cannot get ELF header"); switch (ehdr.e_machine) { case EM_386: res.trap_platform = TRAP_PLATFORM_POSIX_X86; break; case EM_X86_64: res.trap_platform = TRAP_PLATFORM_POSIX_X86_64; break; case EM_ARM: res.trap_platform = TRAP_PLATFORM_POSIX_ARM; break; case 183: // EM_AARCH64 res.trap_platform = TRAP_PLATFORM_POSIX_ARM64; break; default: errx(EXIT_FAILURE, "Unknown ELF machine"); break; } Elf_Data *data = elf_getdata(txtrp_scn, NULL); for (data = elf_getdata(txtrp_scn, NULL); data != NULL; data = elf_getdata(txtrp_scn, data)) res.size += data->d_size; res.data = malloc(res.size); uint8_t *ptr = res.data; for (data = elf_getdata(txtrp_scn, NULL); data != NULL; data = elf_getdata(txtrp_scn, data)) { memcpy(ptr, data->d_buf, data->d_size); ptr += data->d_size; } return res; }
static void handle_dynsym_section(elf_info_s *elf, Elf_Scn *scn, GElf_Shdr shdr) { Elf_Data *data; /* get .dynsym data and size */ elf->dynsym = elf_getdata(scn, NULL); elf->dynsym_count = shdr.sh_size / shdr.sh_entsize; /* retrieve the header table index link which point to .dynstr */ scn = elf_getscn(elf->elf, shdr.sh_link); gelf_getshdr(scn, &shdr); /* get the data of .dynstr */ data = elf_getdata(scn, NULL); elf->dynstr = data->d_buf; }
/* 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; }
/* if this function encounters an error it never returns */ static Elf_Data *exec_getdata( Elf_Scn *scn, int line ) #define exec_getdata(a) \ exec_getdata(a,__LINE__) { Elf_Data *data; char *location; location = NULL; data = elf_getdata(scn, NULL); if ( data != NULL ) { if ( data->d_buf != NULL ) { return data; } else { location = "d_buf"; } } else { location = "elf_data"; } fprintf( stderr, "exec_getdata: %s@%d - %s\n", location, line, elf_errmsg( -1 ) ); exit( 1 ); }
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; }
static int dump_dynamic(struct file_state *f, Elf_Scn *scn, GElf_Shdr *shdr) { struct dyn_state d; GElf_Dyn needed_dyn; char *needed_name; int i; d.f = f; d.dyn_data = elf_getdata(scn, NULL); if (!d.dyn_data) { elf_err("elf_getdata failed"); return -1; } d.count = shdr->sh_size / shdr->sh_entsize; for (i = 0; i < d.count; i++) { if (!gelf_getdyn(d.dyn_data, i, &needed_dyn)) continue; if (needed_dyn.d_tag != DT_NEEDED) continue; needed_name = (char *)f->strtab_data->d_buf + needed_dyn.d_un.d_val; dump_needed(f->t, needed_name); } return 0; }
Elf_Scn * get_scnbyname(Elf *elf, char *name, int *num) { Elf32_Ehdr * ehdr; Elf_Scn * scn; Elf32_Shdr * shdr; Elf_Data * data; int cnt, tmp; if (!num) num = &tmp; *num = 0; if ((ehdr = elf32_getehdr(elf))==NULL) return NULL; if (((scn = elf_getscn(elf, ehdr->e_shstrndx)) == NULL) || ((data = elf_getdata(scn, NULL)) == NULL)) return NULL; for (cnt = 1, scn = NULL; (scn = elf_nextscn(elf, scn)); cnt++) { if ((shdr = elf32_getshdr(scn)) == NULL) return NULL; if (! strcmp(name, (char *)data->d_buf + shdr->sh_name)) { *num = cnt; return scn; } } return NULL; }
/** * Read a script from it's elf section and store it * @param script In output, contains the lua script loaded * @param scn section containing the script * @param shdr section header * @param name name of the script */ static void load_script(struct lua_script *script, Elf_Scn *scn, GElf_Shdr *shdr, const char *name) { unsigned i; Elf_Data *data; char *p; script->name = strdup(name + strlen(LUA_WRAPPER_SECTION_PREFIX)); if (script->name == NULL) exit(101); script->code = calloc(shdr->sh_size + 1, 1); if (script->name == NULL) exit(102); script->code[shdr->sh_size] = '\0'; data = NULL; i = 0; while (i < shdr->sh_size && (data = elf_getdata(scn, data)) != NULL) { p = data->d_buf; while (p < (char *)data->d_buf + data->d_size) { script->code[i] = *p; i++; p++; } } remove_shebang(script->code); }
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; }
/** * @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; }
/* Extract section and copy into HsaBrig */ static status_t extract_section_and_copy (Elf *elfP, Elf_Data *secHdr, const SectionDesc* desc, hsa_ext_brig_module_t* brig_module, hsa_ext_brig_section_id_t section_id) { Elf_Scn* scn = NULL; Elf_Data* data = NULL; void* address_to_copy; size_t section_size=0; scn = extract_elf_section(elfP, secHdr, desc); if (scn) { if ((data = elf_getdata(scn, NULL)) == NULL) { return STATUS_UNKNOWN; } section_size = data->d_size; if (section_size > 0) { address_to_copy = malloc(section_size); memcpy(address_to_copy, data->d_buf, section_size); } } if ((!scn || section_size == 0)) { return STATUS_UNKNOWN; } /* Create a section header */ brig_module->section[section_id] = (hsa_ext_brig_section_header_t*) address_to_copy; return STATUS_SUCCESS; }
char* elf_strptr(Elf *elf, size_t section, size_t offset) { Elf_Scn *scn; Elf_Data *sd; if (!elf) { return NULL; } elf_assert(elf->e_magic == ELF_MAGIC); if (!(scn = elf_getscn(elf, section))) { return NULL; } if (scn->s_type != SHT_STRTAB) { seterr(ERROR_NOSTRTAB); return NULL; } if (offset >= 0 && offset < scn->s_size) { sd = NULL; while ((sd = elf_getdata(scn, sd))) { if (sd->d_buf && offset >= (size_t)sd->d_off && offset < (size_t)sd->d_off + sd->d_size) { return (char*)sd->d_buf + (offset - sd->d_off); } } } seterr(ERROR_BADSTROFF); return NULL; }
//--------------------------------------------------------------------- int getELFSymbolTableNdx(Elf* elf, char* symName) { Elf_Scn *scn; Elf32_Shdr *shdr; Elf_Data *edata; Elf32_Sym *esym; scn = NULL; while ((scn = elf_nextscn(elf, scn)) != NULL){ if ((shdr = elf32_getshdr(scn)) != NULL){ if (SHT_SYMTAB == shdr->sh_type){ edata = NULL; while ((edata = elf_getdata(scn, edata)) != NULL){ if (ELF_T_SYM == edata->d_type){ int numSymbols, i; char* symNameRead; esym = (Elf32_Sym*)(edata->d_buf); numSymbols = (int)(edata->d_size/shdr->sh_entsize); for (i = 0; i < numSymbols; i++){ symNameRead = elf_strptr(elf, shdr->sh_link, esym[i].st_name); if (strcmp(symNameRead, symName) == 0){ return i; } } } } } } } fprintf(stderr, "getElfSymbolTableNdx: Could not locate symbol in the symbol table.\n"); return -1; }
static Dwarf * scngrp_read (Dwarf *result, Elf *elf, GElf_Ehdr *ehdr, Dwarf_Cmd cmd, Elf_Scn *scngrp) { /* SCNGRP is the section descriptor for a section group which might contain debug sections. */ Elf_Data *data = elf_getdata (scngrp, NULL); if (data == NULL) { /* We cannot read the section content. Fail! */ free (result); return NULL; } /* The content of the section is a number of 32-bit words which represent section indices. The first word is a flag word. */ Elf32_Word *scnidx = (Elf32_Word *) data->d_buf; size_t cnt; for (cnt = 1; cnt * sizeof (Elf32_Word) <= data->d_size; ++cnt) { Elf_Scn *scn = elf_getscn (elf, scnidx[cnt]); if (scn == NULL) { /* A section group refers to a non-existing section. Should never happen. */ __libdw_seterrno (DWARF_E_INVALID_ELF); free (result); return NULL; } check_section (result, ehdr, scn, true); } return valid_p (result); }
/* * Look up the symbol at addr, returning a copy of the symbol and its name. */ static int lookup_addr(Elf *e, Elf_Scn *scn, u_long stridx, uintptr_t off, uintptr_t addr, const char **name, GElf_Sym *symcopy) { GElf_Sym sym; Elf_Data *data; const char *s; uint64_t rsym; int i; if ((data = elf_getdata(scn, NULL)) == NULL) { DPRINTFX("ERROR: elf_getdata() failed: %s", elf_errmsg(-1)); return (1); } for (i = 0; gelf_getsym(data, i, &sym) != NULL; i++) { rsym = off + sym.st_value; if (addr >= rsym && addr < rsym + sym.st_size) { s = elf_strptr(e, stridx, sym.st_name); if (s != NULL) { *name = s; memcpy(symcopy, &sym, sizeof(*symcopy)); /* * DTrace expects the st_value to contain * only the address relative to the start of * the function. */ symcopy->st_value = rsym; return (0); } } } return (1); }
scn_hdr_t* get_scn_hdr(int idx) { Elf_Scn* scn = g.scns[idx]; GElf_Shdr shdr = g.shdrs[idx]; Elf_Data* data; size_t n; // if ( gelf_getshdr(scn , &shdr) != &shdr ) { // errx ( EXIT_FAILURE, // " getshdr( shstrndx ) failed : %s.", // elf_errmsg ( -1)); // return NULL; // } // data = NULL; size_t buf_sz = 0; // while ((data=elf_getdata(scn, data)) != NULL) { // printf("+%d", data->d_size); // buf_sz += data->d_size; // } uint8_t* buf = (uint8_t*) malloc(shdr.sh_size); if (buf == NULL) { errx (EXIT_FAILURE, "malloc failed"); return NULL; } data = NULL; n = 0; while (n < shdr.sh_size && (data = elf_getdata(scn, data)) != NULL) { uint8_t* p = (uint8_t*)data->d_buf; size_t dsize = data->d_size; if(p != NULL) memcpy(buf+n, p, dsize); else //FIXME: seems some sections are empty in file memset(buf+n, 0, dsize); n += dsize; } // get the name string char* name; if ((name = elf_strptr(g.e, g.shstrndx, shdr.sh_name)) == NULL) errx(EXIT_FAILURE , " elf_strptr() failed : %s.", elf_errmsg (-1)); scn_hdr_t* scn_hdr_p = (scn_hdr_t*)malloc(sizeof(scn_hdr_t)); if (scn_hdr_p == NULL) { errx (EXIT_FAILURE , "scn_hdr_t malloc failed"); return NULL; } scn_hdr_p->sh_idx = idx; scn_hdr_p->name = name; scn_hdr_p->sh_addr = shdr.sh_addr; scn_hdr_p->sh_size = n; scn_hdr_p->data = buf; return scn_hdr_p; }
static void readSymbols(Elf *e, Elf_Scn *scn, const GElf_Shdr &shdr, unsigned low, unsigned high, std::auto_ptr<CoreSymbolInfo> &SI) { Elf_Data *data = elf_getdata(scn, NULL); if (data == NULL) { return; } unsigned count = shdr.sh_size / shdr.sh_entsize; CoreSymbolInfoBuilder builder; for (unsigned i = 0; i < count; i++) { GElf_Sym sym; if (gelf_getsym(data, i, &sym) == NULL) { continue; } if (sym.st_shndx == SHN_ABS) continue; if (sym.st_value < low || sym.st_value >= high) continue; builder.addSymbol(elf_strptr(e, shdr.sh_link, sym.st_name), sym.st_value, sym.st_info); } SI = builder.getSymbolInfo(); }
/** * 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 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; } }
/* * @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 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; }
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 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); }