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); }
void ld_dynamic_load_dso_dynamic(struct ld *ld, struct ld_input *li, Elf *e, Elf_Scn *scn, size_t strndx) { GElf_Shdr shdr; GElf_Dyn dyn; Elf_Data *d; int elferr, i, len; const char *name; if (strndx == SHN_UNDEF) return; if (gelf_getshdr(scn, &shdr) != &shdr) { ld_warn(ld, "%s: gelf_getshdr failed: %s", li->li_name, elf_errmsg(-1)); return; } (void) elf_errno(); if ((d = elf_getdata(scn, NULL)) == NULL) { elferr = elf_errno(); if (elferr != 0) ld_warn(ld, "%s: elf_getdata failed: %s", li->li_name, elf_errmsg(elferr)); return; } len = d->d_size / shdr.sh_entsize; for (i = 0; i < len; i++) { if (gelf_getdyn(d, i, &dyn) != &dyn) { ld_warn(ld, "%s: gelf_getdyn failed: %s", li->li_name, elf_errmsg(-1)); continue; } switch (dyn.d_tag) { case DT_SONAME: name = elf_strptr(e, strndx, dyn.d_un.d_ptr); if (name != NULL && (li->li_soname = strdup(name)) == NULL) ld_fatal_std(ld, "strdup"); break; case DT_NEEDED: name = elf_strptr(e, strndx, dyn.d_un.d_ptr); if (name != NULL) ld_path_search_dso_needed(ld, li->li_file, name); break; default: break; } } }
void elferr() { fprintf(stderr, "%s: %s\n", prog, elf_errmsg(elf_errno())); exit(1); }
void tcBadElf_tpElf(void) { int err; Elf *e; TS_PHDR *ph; char badelf[sizeof(badelftemplate)]; TP_CHECK_INITIALIZATION(); tet_infoline("assertion: " TS_ICNAME "() on a malformed ELF file " "fails with ELF_E_HEADER."); (void) memcpy(badelf, badelftemplate, sizeof(badelf)); badelf[EI_VERSION] = EV_CURRENT; badelf[EI_CLASS] = TS_ELFCLASS; TS_OPEN_MEMORY(e, badelf); if ((ph = TS_ICFUNC(e)) != NULL || (err = elf_errno()) != ELF_E_HEADER) { tet_printf("fail: error=%d ph=%p.", err, (void *) ph); tet_result(TET_FAIL); } else tet_result(TET_PASS); (void) elf_end(e); }
static inline int canonicalize (Dwfl_Error error) { unsigned int value; switch (error) { default: value = error; if ((value &~ 0xffff) != 0) break; assert (value < nmsgidx); break; case DWFL_E_ERRNO: value = DWFL_E (ERRNO, errno); break; case DWFL_E_LIBELF: value = DWFL_E (LIBELF, elf_errno ()); break; case DWFL_E_LIBDW: value = DWFL_E (LIBDW, INTUSE(dwarf_errno) ()); break; #if 0 DWFL_E_LIBEBL: value = DWFL_E (LIBEBL, ebl_errno ()); break; #endif } return value; }
/* Open libelf FILE->fd and compute the load base of ELF as loaded in MOD. When we return success, FILE->elf and FILE->bias are set up. */ static inline Dwfl_Error open_elf (Dwfl_Module *mod, struct dwfl_file *file) { if (file->elf == NULL) { /* If there was a pre-primed file name left that the callback left behind, try to open that file name. */ if (file->fd < 0 && file->name != NULL) file->fd = TEMP_FAILURE_RETRY (open64 (file->name, O_RDONLY)); if (file->fd < 0) return CBFAIL; file->elf = elf_begin (file->fd, ELF_C_READ_MMAP_PRIVATE, NULL); } if (unlikely (elf_kind (file->elf) != ELF_K_ELF)) { close (file->fd); file->fd = -1; return DWFL_E_BADELF; } GElf_Ehdr ehdr_mem, *ehdr = gelf_getehdr (file->elf, &ehdr_mem); if (ehdr == NULL) { elf_error: close (file->fd); file->fd = -1; return DWFL_E (LIBELF, elf_errno ()); } /* The addresses in an ET_EXEC file are absolute. The lowest p_vaddr of the main file can differ from that of the debug file due to prelink. But that doesn't not change addresses that symbols, debuginfo, or sh_addr of any program sections refer to. */ file->bias = 0; if (mod->e_type != ET_EXEC) for (uint_fast16_t i = 0; i < ehdr->e_phnum; ++i) { GElf_Phdr ph_mem; GElf_Phdr *ph = gelf_getphdr (file->elf, i, &ph_mem); if (ph == NULL) goto elf_error; if (ph->p_type == PT_LOAD) { file->bias = ((mod->low_addr & -ph->p_align) - (ph->p_vaddr & -ph->p_align)); break; } } mod->e_type = ehdr->e_type; /* Relocatable Linux kernels are ET_EXEC but act like ET_DYN. */ if (mod->e_type == ET_EXEC && file->bias != 0) mod->e_type = ET_DYN; return DWFL_E_NOERROR; }
static void check_libelf_version() { if (elf_version(EV_CURRENT) == EV_NONE) { fprintf(stderr, "elf initialization failed: %s\n", elf_errmsg(elf_errno())); exit(1); } }
void tcElf_tpCorruptEhdr(void) { int err, fd, result; char *fn; Elf *e; TS_PHDR *ph; TP_CHECK_INITIALIZATION(); tet_infoline("assertion: " TS_ICNAME "(E) with corrupt phdr values " "the header returns E_HEADER."); fn = "ehdr.msb" __XSTRING(TS_PHDRSZ); TS_OPEN_FILE(e, fn, ELF_C_READ, fd); result = TET_PASS; if ((ph = TS_ICFUNC(e)) != NULL || (err = (elf_errno() != ELF_E_HEADER))) { tet_printf("fail: \"%s\" (ph %p, error %d)", fn, (void *) ph, err); result = TET_FAIL; } (void) elf_end(e); (void) close(fd); if (result != TET_PASS) { tet_result(result); return; } fn = "ehdr.lsb" __XSTRING(TS_PHDRSZ); TS_OPEN_FILE(e, fn, ELF_C_READ, fd); if ((ph = TS_ICFUNC(e)) != NULL || (err = (elf_errno() != ELF_E_HEADER))) { tet_printf("fail: \"%s\" (ph %p, error %d)", fn, (void *) ph, err); result = TET_FAIL; } (void) elf_end(e); (void) close(fd); tet_result(result); }
/* * Wrapper on msg_fatal() that issues an error that results from * a call to libelf. * * entry: * file - Name of ELF object * libelf_rtn_name - Name of routine that was called * * exit: * An error has been issued that shows the routine called * and the libelf error string for it from elf_errmsg(). * This routine does not return to the caller. */ static void msg_elf(const char *libelf_rtn_name) { const char *errstr = elf_errmsg(elf_errno()); msg_fatal("%s: %s failed: %s\n", file, libelf_rtn_name, errstr ? errstr : "<unknown>"); }
void tcElf_tpElfWrongSize(void) { int error, fd, result; Elf *e; char *fn; TS_PHDR *ph; TP_CHECK_INITIALIZATION(); tet_infoline("assertion: a call to " TS_ICNAME "() and a mismatched " "ELF class fails with ELF_E_CLASS."); result = TET_PASS; fn = "phdr.msb" __XSTRING(TS_OTHERSIZE); TS_OPEN_FILE(e,fn,ELF_C_READ,fd); if ((ph = TS_ICFUNC(e)) != NULL || (error = elf_errno()) != ELF_E_CLASS) { tet_printf("fail: \"%s\" opened (error %d).", fn, error); result = TET_FAIL; } (void) elf_end(e); (void) close(fd); if (result != TET_PASS) { tet_result(result); return; } fn = "phdr.lsb" __XSTRING(TS_OTHERSIZE); TS_OPEN_FILE(e,fn,ELF_C_READ,fd); if ((ph = TS_ICFUNC(e)) != NULL || (error = elf_errno()) != ELF_E_CLASS) { tet_printf("fail: \"%s\" opened (error %d).", fn, error); result = TET_FAIL; } (void) elf_end(e); (void) close(fd); tet_result(result); }
void print_elf_errno(int line_number) { int err; if ((err = elf_errno()) != 0) { fprintf(stderr, "%s (line %i): %s\n", PROGRAM_NAME, line_number, elf_errmsg(err)); exit(3); } }
/* * Create an archive descriptor. By maintaining a list of archives any * duplicate occurrences of the same archive specified by the user enable us to * pick off where the last processing finished. */ Ar_desc * ld_ar_setup(const char *name, Elf *elf, Ofl_desc *ofl) { Ar_desc * adp; size_t number; Elf_Arsym * start; /* * Unless, -z allextract is specified, get the archive symbol table * if one exists, and ignore the file with a warning message otherwise. */ if (ofl->ofl_flags1 & FLG_OF1_ALLEXRT) { start = NULL; } else if ((start = elf_getarsym(elf, &number)) == NULL) { if (elf_errno()) ld_eprintf(ofl, ERR_ELF, MSG_INTL(MSG_ELF_GETARSYM), name); else ld_eprintf(ofl, ERR_WARNING, MSG_INTL(MSG_ELF_ARSYM), name); return (0); } /* * As this is a new archive reference establish a new descriptor. */ if ((adp = libld_malloc(sizeof (Ar_desc))) == NULL) return ((Ar_desc *)S_ERROR); adp->ad_name = name; adp->ad_elf = elf; adp->ad_start = start; if (start) { adp->ad_aux = libld_calloc(sizeof (Ar_aux), number); if (adp->ad_aux == NULL) return ((Ar_desc *)S_ERROR); } else { adp->ad_aux = NULL; } /* * Retain any command line options that are applicable to archive * extraction in case we have to rescan this archive later. */ adp->ad_flags = ofl->ofl_flags1 & MSK_OF1_ARCHIVE; ofl->ofl_arscnt++; /* * Add this new descriptor to the list of archives. */ if (aplist_append(&ofl->ofl_ars, adp, AL_CNT_OFL_LIBS) == NULL) return ((Ar_desc *)S_ERROR); else return (adp); }
void tcNull_tpGet(void) { TP_CHECK_INITIALIZATION(); tet_infoline("assertion: " TS_ICNAME "(NULL) fails with " "ELF_E_ARGUMENT."); if (TS_ICFUNC(NULL) != NULL || elf_errno() != ELF_E_ARGUMENT) tet_result(TET_FAIL); else tet_result(TET_PASS); }
void tcData_tpElf(void) { Elf *e; TP_CHECK_INITIALIZATION(); tet_infoline("assertion: " TS_ICNAME "(E) for non-ELF (E) fails with " "ELF_E_ARGUMENT."); TS_OPEN_MEMORY(e, data); if (TS_ICFUNC(e) != NULL || elf_errno() != ELF_E_ARGUMENT) tet_result(TET_FAIL); else tet_result(TET_PASS); (void) elf_end(e); }
static int read_phdr(struct elf32_info *info, FILE *in) { int i; if (info->file_ehdr.e_phnum > MAX_PHDRS) { printc_err("elf32: too many program headers: %d\n", info->file_ehdr.e_phnum); return -1; } for (i = 0; i < info->file_ehdr.e_phnum; i++) { GElf_Phdr *phdr = &info->file_phdrs[i]; if (gelf_getphdr(info->elf, i, phdr) != phdr) { printc_err("elf32: can't read phdr %d: %s\n", i, elf_errmsg(elf_errno())); } } return 0; }
/* Given Elf header, Elf_Scn, and Elf32_Shdr * print out the symbol table */ static _Bool print_symbols(Elf *elf, Elf_Scn *scn, GElf_Shdr *shdr) { Elf_Data *data; char *name; char *stringName; data = 0; int number = 0; if ((data = elf_getdata(scn, data)) == 0 || data->d_size == 0) { /* error or no data */ fprintf(stderr, "Section had no data!\n"); exit(-1); } /*now print the symbols*/ unsigned count = symtab_shdr.sh_size / symtab_shdr.sh_entsize; //fprintf(stderr, "Total symbols count: %u\n", count); /* now loop through the symbol table and print it*/ for (unsigned i = 0; i < count; ++i) { //fprintf(stderr, "Index is %u\n", i); GElf_Sym esym; GElf_Sym *ret = gelf_getsym(data, i, &esym); if (ret == 0) { fprintf(stderr, "Error!\n"); return FALSE; } if ((esym.st_value == 0) || (GELF_ST_BIND(esym.st_info)== STB_WEAK) || (GELF_ST_BIND(esym.st_info)== STB_NUM)) continue; //fprintf(stderr, "Symbol has strtab offset %zu\n", (size_t)esym.st_name); name = elf_strptr(elf, shdr->sh_link, (size_t)esym.st_name); if(!name) { fprintf(stderr,"%s\n",elf_errmsg(elf_errno())); exit(-1); } printf("%d: %s\n", number++, name); } return TRUE; }
void elfdie(char *format, ...) { va_list ap; #ifndef illumos const char *progname = getprogname(); #endif (void) fprintf(stderr, "%s: ", progname); va_start(ap, format); /* LINTED - variable format specifier */ (void) vfprintf(stderr, format, ap); va_end(ap); if (format[strlen(format) - 1] != '\n') (void) fprintf(stderr, ": %s\n", elf_errmsg(elf_errno())); #ifndef illumos exit(0); #else exit(1); #endif }
int main (void) { size_t cnt; int result = EXIT_SUCCESS; /* Clear the error state. */ (void) elf_errno (); /* Check all the messages of libelf. */ for (cnt = 1; cnt < ELF_E_NUM; ++cnt) { const char *str = elf_errmsg (libelf_msgs[cnt].id); if (strcmp (str, libelf_msgs[cnt].expected) != 0) { printf ("libelf msg %zu: expected \"%s\", got \"%s\"\n", cnt, libelf_msgs[cnt].expected, str); result = EXIT_FAILURE; } } return result; }