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); }
static int read_archive(int fd, Elf *elf, char *file, char *label, read_cb_f *func, void *arg, int require_ctf) { Elf *melf; Elf_Cmd cmd = ELF_C_READ; Elf_Arhdr *arh; int secnum = 1, found = 0; while ((melf = elf_begin(fd, cmd, elf)) != NULL) { int rc = 0; if ((arh = elf_getarhdr(melf)) == NULL) { elfterminate(file, "Can't get archive header for " "member %d", secnum); } /* skip special sections - their names begin with "/" */ if (*arh->ar_name != '/') { size_t memlen = strlen(file) + 1 + strlen(arh->ar_name) + 1 + 1; char *memname = xmalloc(memlen); snprintf(memname, memlen, "%s(%s)", file, arh->ar_name); switch (elf_kind(melf)) { case ELF_K_AR: rc = read_archive(fd, melf, memname, label, func, arg, require_ctf); break; case ELF_K_ELF: rc = read_file(melf, memname, label, func, arg, require_ctf); break; default: terminate("%s: Unknown elf kind %d\n", memname, elf_kind(melf)); } free(memname); } cmd = elf_next(melf); (void) elf_end(melf); secnum++; if (rc < 0) return (rc); else found += rc; } return (found); }
static int read_file(Elf *elf, char *file, char *label, read_cb_f *func, void *arg, int require_ctf) { Elf_Scn *ctfscn; Elf_Data *ctfdata = NULL; symit_data_t *si = NULL; int ctfscnidx; tdata_t *td; if ((ctfscnidx = findelfsecidx(elf, file, ".SUNW_ctf")) < 0) { if (require_ctf && (built_source_types(elf, file) & SOURCE_C)) { terminate("Input file %s was partially built from " "C sources, but no CTF data was present\n", file); } return (0); } if ((ctfscn = elf_getscn(elf, ctfscnidx)) == NULL || (ctfdata = elf_getdata(ctfscn, NULL)) == NULL) elfterminate(file, "Cannot read CTF section"); /* Reconstruction of type tree */ if ((si = symit_new(elf, file)) == NULL) { warning("%s has no symbol table - skipping", file); return (0); } td = ctf_load(file, ctfdata->d_buf, ctfdata->d_size, si, label); tdata_build_hashes(td); symit_free(si); if (td != NULL) { if (func(td, file, arg) < 0) return (-1); else return (1); } return (0); }
static int read_ctf_common(char *file, char *label, read_cb_f *func, void *arg, int require_ctf) { Elf *elf; int found = 0; int fd; debug(3, "Reading %s (label %s)\n", file, (label ? label : "NONE")); (void) elf_version(EV_CURRENT); if ((fd = open(file, O_RDONLY)) < 0) terminate("%s: Cannot open for reading", file); if ((elf = elf_begin(fd, ELF_C_READ, NULL)) == NULL) elfterminate(file, "Cannot read"); switch (elf_kind(elf)) { case ELF_K_AR: found = read_archive(fd, elf, file, label, func, arg, require_ctf); break; case ELF_K_ELF: found = read_file(elf, file, label, func, arg, require_ctf); break; default: terminate("%s: Unknown elf kind %d\n", file, elf_kind(elf)); } (void) elf_end(elf); (void) close(fd); return (found); }