From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from lists.gentoo.org (pigeon.gentoo.org [208.92.234.80]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by finch.gentoo.org (Postfix) with ESMTPS id 282C6139082 for ; Sun, 22 Jan 2017 17:59:37 +0000 (UTC) Received: from pigeon.gentoo.org (localhost [127.0.0.1]) by pigeon.gentoo.org (Postfix) with SMTP id 7FFDAE0EF5; Sun, 22 Jan 2017 17:59:36 +0000 (UTC) Received: from smtp.gentoo.org (smtp.gentoo.org [140.211.166.183]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by pigeon.gentoo.org (Postfix) with ESMTPS id 4CCACE0EF5 for ; Sun, 22 Jan 2017 17:59:36 +0000 (UTC) Received: from oystercatcher.gentoo.org (unknown [IPv6:2a01:4f8:202:4333:225:90ff:fed9:fc84]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.gentoo.org (Postfix) with ESMTPS id 478D8340EDA for ; Sun, 22 Jan 2017 17:59:35 +0000 (UTC) Received: from localhost.localdomain (localhost [127.0.0.1]) by oystercatcher.gentoo.org (Postfix) with ESMTP id 949E22CBA for ; Sun, 22 Jan 2017 17:59:32 +0000 (UTC) From: "Mike Frysinger" To: gentoo-commits@lists.gentoo.org Content-Transfer-Encoding: 8bit Content-type: text/plain; charset=UTF-8 Reply-To: gentoo-dev@lists.gentoo.org, "Mike Frysinger" Message-ID: <1480055432.2eb852129394f97dae89c0ff1f9f48637edcb0e9.vapier@gentoo> Subject: [gentoo-commits] proj/pax-utils:master commit in: / X-VCS-Repository: proj/pax-utils X-VCS-Files: scanelf.c X-VCS-Directories: / X-VCS-Committer: vapier X-VCS-Committer-Name: Mike Frysinger X-VCS-Revision: 2eb852129394f97dae89c0ff1f9f48637edcb0e9 X-VCS-Branch: master Date: Sun, 22 Jan 2017 17:59:32 +0000 (UTC) Precedence: bulk List-Post: List-Help: List-Unsubscribe: List-Subscribe: List-Id: Gentoo Linux mail X-BeenThere: gentoo-commits@lists.gentoo.org X-Archives-Salt: 868d4559-05de-4da1-a533-69af98bbb13f X-Archives-Hash: cde6cf170978d478e4442ed12e6bd6c5 commit: 2eb852129394f97dae89c0ff1f9f48637edcb0e9 Author: Mike Frysinger gentoo org> AuthorDate: Fri Nov 25 06:30:32 2016 +0000 Commit: Mike Frysinger gentoo org> CommitDate: Fri Nov 25 06:30:32 2016 +0000 URL: https://gitweb.gentoo.org/proj/pax-utils.git/commit/?id=2eb85212 scanelf: rewrite textrels decoder to use program segments Previously, we only looked at the section name ".text". This fails when other names are used, or when the section headers are incomplete. Since the runtime only looks at program headers, change the code to match. scanelf.c | 116 +++++++++++++++++++++++++++++++++++++++++++++++--------------- 1 file changed, 88 insertions(+), 28 deletions(-) diff --git a/scanelf.c b/scanelf.c index 2a7c0ce..9c52ced 100644 --- a/scanelf.c +++ b/scanelf.c @@ -572,8 +572,8 @@ static const char *scanelf_file_textrel(elfobj *elf, char *found_textrel) */ static char *scanelf_file_textrels(elfobj *elf, char *found_textrels, char *found_textrel) { - unsigned long s, r, rmax; - void *symtab_void, *strtab_void, *text_void; + unsigned long r, rmax; + void *symtab_void, *strtab_void; if (!show_textrels) return NULL; @@ -582,32 +582,87 @@ static char *scanelf_file_textrels(elfobj *elf, char *found_textrels, char *foun if (!*found_textrel) return NULL; scanelf_file_get_symtabs(elf, &symtab_void, &strtab_void); - text_void = elf_findsecbyname(elf, ".text"); #define SHOW_TEXTRELS(B) \ + size_t i; \ Elf ## B ## _Ehdr *ehdr = EHDR ## B (elf->ehdr); \ - Elf ## B ## _Shdr *shdr = SHDR ## B (elf->shdr); \ + Elf ## B ## _Phdr *phdr; \ + Elf ## B ## _Off offset; \ Elf ## B ## _Shdr *symtab = SHDR ## B (symtab_void); \ Elf ## B ## _Shdr *strtab = SHDR ## B (strtab_void); \ - Elf ## B ## _Shdr *text = SHDR ## B (text_void); \ - Elf ## B ## _Addr vaddr = EGET(text->sh_addr); \ - uint ## B ## _t memsz = EGET(text->sh_size); \ Elf ## B ## _Rel *rel; \ Elf ## B ## _Rela *rela; \ - /* search the section headers for relocations */ \ - for (s = 0; s < EGET(ehdr->e_shnum); ++s) { \ - uint32_t sh_type = EGET(shdr[s].sh_type); \ - if (sh_type == SHT_REL) { \ - rel = REL ## B (elf->vdata + EGET(shdr[s].sh_offset)); \ - rela = NULL; \ - rmax = EGET(shdr[s].sh_size) / sizeof(*rel); \ - } else if (sh_type == SHT_RELA) { \ - rel = NULL; \ - rela = RELA ## B (elf->vdata + EGET(shdr[s].sh_offset)); \ - rmax = EGET(shdr[s].sh_size) / sizeof(*rela); \ - } else \ + Elf ## B ## _Dyn *dyn, *drel, *drelsz, *drelent, *dpltrel; \ + uint32_t pltrel; \ + \ + /* Find the dynamic headers */ \ + phdr = scanelf_file_get_pt_dynamic(elf); \ + if (phdr == NULL) \ + break; \ + offset = EGET(phdr->p_offset); \ + \ + /* Walk all the dynamic tags to find relocation info */ \ + dyn = DYN ## B (elf->vdata + offset); \ + drel = drelsz = drelent = dpltrel = NULL; \ + while (EGET(dyn->d_tag) != DT_NULL) { \ + switch (EGET(dyn->d_tag)) { \ + case DT_REL: \ + case DT_RELA: \ + drel = dyn; \ + break; \ + case DT_RELSZ: \ + case DT_RELASZ: \ + drelsz = dyn; \ + break; \ + case DT_RELENT: \ + case DT_RELAENT: \ + drelent = dyn; \ + break; \ + case DT_PLTREL: \ + dpltrel = dyn; \ + break; \ + } \ + ++dyn; \ + } \ + if (!drel || !drelsz || !drelent || !dpltrel) { \ + warnf("ELF is missing relocation information"); \ + break; \ + } \ + switch (EGET(dpltrel->d_un.d_val)) { \ + case DT_REL: \ + rel = REL##B(elf->vdata + EGET(drel->d_un.d_val)); \ + rela = NULL; \ + pltrel = DT_REL; \ + break; \ + case DT_RELA: \ + rel = NULL; \ + rela = RELA##B(elf->vdata + EGET(drel->d_un.d_val)); \ + pltrel = DT_RELA; \ + break; \ + default: \ + warn("Unknown relocation type"); \ + rel = NULL; \ + rela = NULL; \ + break; \ + } \ + if (!rel && !rela) \ + break; \ + rmax = EGET(drelsz->d_un.d_val) / EGET(drelent->d_un.d_val); \ + \ + /* search the program segments for relocations */ \ + phdr = PHDR ## B(elf->phdr); \ + for (i = 0; i < EGET(ehdr->e_phnum); ++i) { \ + Elf ## B ## _Addr vaddr = EGET(phdr[i].p_vaddr); \ + uint ## B ## _t memsz = EGET(phdr[i].p_memsz); \ + \ + /* Only care about loadable segments. */ \ + if (EGET(phdr[i].p_type) != PT_LOAD) \ continue; \ - /* now see if any of the relocs are in the .text */ \ + /* Only care about executable segments. */ \ + if ((EGET(phdr[i].p_flags) & PF_X) != PF_X) \ + continue; \ + \ + /* now see if any of the relocs touch this segment */ \ for (r = 0; r < rmax; ++r) { \ unsigned long sym_max; \ Elf ## B ## _Addr offset_tmp; \ @@ -615,7 +670,7 @@ static char *scanelf_file_textrels(elfobj *elf, char *found_textrels, char *foun Elf ## B ## _Sym *sym; \ Elf ## B ## _Addr r_offset; \ uint ## B ## _t r_info; \ - if (sh_type == SHT_REL) { \ + if (pltrel == DT_REL) { \ r_offset = EGET(rel[r].r_offset); \ r_info = EGET(rel[r].r_info); \ } else { \ @@ -641,7 +696,9 @@ static char *scanelf_file_textrels(elfobj *elf, char *found_textrels, char *foun sym_max = EGET(symtab->sh_size) / EGET(symtab->sh_entsize); \ /* show the raw details about this reloc */ \ printf(" %s: ", elf->base_filename); \ - if (sym && sym->st_name) \ + if (!strtab) \ + printf("(missing symbols)"); \ + else if (sym && sym->st_name) \ printf("%s", elf->data + EGET(strtab->sh_offset) + EGET(sym->st_name)); \ else \ printf("(memory/data?)"); \ @@ -659,11 +716,14 @@ static char *scanelf_file_textrels(elfobj *elf, char *found_textrels, char *foun } \ printf(" in "); \ if (func && func->st_name) { \ - const char *func_name = elf->data + EGET(strtab->sh_offset) + EGET(func->st_name); \ - if (r_offset > EGET(func->st_size)) \ - printf("(optimized out: previous %s)", func_name); \ - else \ - printf("%s", func_name); \ + if (strtab) { \ + const char *func_name = elf->data + EGET(strtab->sh_offset) + EGET(func->st_name); \ + if (r_offset > EGET(func->st_size)) \ + printf("(optimized out: previous %s)", func_name); \ + else \ + printf("%s", func_name); \ + } else \ + printf("(missing symbols)"); \ } else \ printf("(optimized out)"); \ printf(" [0x%lX]\n", (unsigned long)offset_tmp); \ @@ -690,7 +750,7 @@ static char *scanelf_file_textrels(elfobj *elf, char *found_textrels, char *foun } \ } \ } - if (symtab_void && strtab_void && text_void && elf->shdr) + if (symtab_void && elf->phdr) SCANELF_ELF_SIZED(SHOW_TEXTRELS); if (!*found_textrels) warnf("ELF %s has TEXTREL markings but doesnt appear to have any real TEXTREL's !?", elf->filename);