diff options
author | emaste <emaste@FreeBSD.org> | 2016-02-12 20:54:02 +0000 |
---|---|---|
committer | emaste <emaste@FreeBSD.org> | 2016-02-12 20:54:02 +0000 |
commit | a6ae90983efabb9784f1e105ffb29eaec3c0573c (patch) | |
tree | cd8537a698afe8dd30dc9c4d04c193e5b3b2e94f /contrib/elftoolchain | |
parent | 0309ab8781484f9cf0561cbbc3cab6df7139d629 (diff) | |
parent | 85217dee0e24c5f3ac285420e843063b4b52c1a0 (diff) | |
download | FreeBSD-src-a6ae90983efabb9784f1e105ffb29eaec3c0573c.zip FreeBSD-src-a6ae90983efabb9784f1e105ffb29eaec3c0573c.tar.gz |
Update ELF Tool Chain to upstream rev 3400
Some notable improvements include:
readelf:
- Add AArch64 relocation definitions.
- Report value of unknown relocation types.
elfcopy:
- Consider symbols with STB_GNU_UNIQUE binding as global symbols.
- Fixed support for VMA adjustment for loadable sections found
in relocatable objects.
- Handle nameless global symbols.
- Improve wildcard matching for !-prefixed symbols.
- Add PE/COFF support.
elfdump:
- Improve section type reporting.
- Add MIPS-specific section types.
This update also includes a significant number of bug fixes.
PR: 207091 [exp-run]
Sponsored by: The FreeBSD Foundation
Diffstat (limited to 'contrib/elftoolchain')
65 files changed, 4894 insertions, 873 deletions
diff --git a/contrib/elftoolchain/addr2line/addr2line.c b/contrib/elftoolchain/addr2line/addr2line.c index 5310576..3cd8cb5 100644 --- a/contrib/elftoolchain/addr2line/addr2line.c +++ b/contrib/elftoolchain/addr2line/addr2line.c @@ -40,7 +40,7 @@ #include "uthash.h" #include "_elftc.h" -ELFTC_VCSID("$Id: addr2line.c 3264 2015-11-30 05:38:14Z kaiwang27 $"); +ELFTC_VCSID("$Id: addr2line.c 3273 2015-12-11 21:38:57Z kaiwang27 $"); struct Func { char *name; @@ -368,7 +368,8 @@ print_inlines(struct CU *cu, struct Func *f, Dwarf_Unsigned call_file, printf("%s\n", f->name); } } - (void) printf("%s:%ju\n", base ? basename(file) : file, call_line); + (void) printf("%s:%ju\n", base ? basename(file) : file, + (uintmax_t) call_line); if (f->inlined_caller != NULL) print_inlines(cu, f->inlined_caller, f->call_file, @@ -562,7 +563,8 @@ out: } } - (void) printf("%s:%ju\n", base ? basename(file) : file, lineno); + (void) printf("%s:%ju\n", base ? basename(file) : file, + (uintmax_t) lineno); if (ret == DW_DLV_OK && inlines && cu != NULL && cu->srcfiles != NULL && f != NULL && f->inlined_caller != NULL) diff --git a/contrib/elftoolchain/addr2line/os.NetBSD.mk b/contrib/elftoolchain/addr2line/os.NetBSD.mk new file mode 100644 index 0000000..ae214e3 --- /dev/null +++ b/contrib/elftoolchain/addr2line/os.NetBSD.mk @@ -0,0 +1,2 @@ +# TODO(#511): Revert after the source tree is -Wconversion clean. +WARNS=5 diff --git a/contrib/elftoolchain/ar/ar.c b/contrib/elftoolchain/ar/ar.c index 62f0e55..1b60a12 100644 --- a/contrib/elftoolchain/ar/ar.c +++ b/contrib/elftoolchain/ar/ar.c @@ -72,7 +72,7 @@ #include "ar.h" -ELFTC_VCSID("$Id: ar.c 3243 2015-08-31 19:28:45Z emaste $"); +ELFTC_VCSID("$Id: ar.c 3319 2016-01-13 21:37:53Z jkoshy $"); enum options { @@ -407,7 +407,7 @@ Usage: %s <command> [options] archive file...\n\ -F FORMAT | --flavor=FORMAT\n\ Create archives with the specified format.\n\ -S Do not generate an archive symbol table.\n\ - -U Use original metadata, for unique archive checksums.\n" + -U Use original metadata for archive members.\n" static void bsdar_usage(void) diff --git a/contrib/elftoolchain/brandelf/brandelf.c b/contrib/elftoolchain/brandelf/brandelf.c index cbe5d6c..22166f7 100644 --- a/contrib/elftoolchain/brandelf/brandelf.c +++ b/contrib/elftoolchain/brandelf/brandelf.c @@ -44,7 +44,7 @@ #include "_elftc.h" -ELFTC_VCSID("$Id: brandelf.c 3234 2015-07-31 12:35:09Z emaste $"); +ELFTC_VCSID("$Id: brandelf.c 3354 2016-01-18 21:50:15Z jkoshy $"); static int elftype(const char *); static const char *iselftype(int); @@ -212,7 +212,7 @@ main(int argc, char **argv) /* * Update the ABI type. */ - ehdr.e_ident[EI_OSABI] = type; + ehdr.e_ident[EI_OSABI] = (unsigned char) type; if (gelf_update_ehdr(elf, &ehdr) == 0) { warnx("gelf_update_ehdr error: %s", elf_errmsg(-1)); diff --git a/contrib/elftoolchain/common/elfdefinitions.h b/contrib/elftoolchain/common/elfdefinitions.h index e953c92..fa6132d 100644 --- a/contrib/elftoolchain/common/elfdefinitions.h +++ b/contrib/elftoolchain/common/elfdefinitions.h @@ -23,7 +23,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $Id: elfdefinitions.h 3253 2015-10-10 18:31:33Z kaiwang27 $ + * $Id: elfdefinitions.h 3392 2016-02-05 19:51:22Z emaste $ */ /* @@ -1228,6 +1228,7 @@ _ELF_DEFINE_STB(STB_GLOBAL, 1, \ _ELF_DEFINE_STB(STB_WEAK, 2, \ "visible across all object files but with low precedence") \ _ELF_DEFINE_STB(STB_LOOS, 10, "start of OS-specific range") \ +_ELF_DEFINE_STB(STB_GNU_UNIQUE, 10, "unique symbol (GNU)") \ _ELF_DEFINE_STB(STB_HIOS, 12, "end of OS-specific range") \ _ELF_DEFINE_STB(STB_LOPROC, 13, \ "start of processor-specific range") \ @@ -1259,6 +1260,7 @@ _ELF_DEFINE_STT(STT_LOPROC, 13, \ "start of processor-specific types") \ _ELF_DEFINE_STT(STT_ARM_TFUNC, 13, "Thumb function (GNU)") \ _ELF_DEFINE_STT(STT_ARM_16BIT, 15, "Thumb label (GNU)") \ +_ELF_DEFINE_STT(STT_SPARC_REGISTER, 13, "SPARC register information") \ _ELF_DEFINE_STT(STT_HIPROC, 15, \ "end of processor-specific types") @@ -1395,7 +1397,7 @@ _ELF_DEFINE_RELOC(R_386_GOT32, 3) \ _ELF_DEFINE_RELOC(R_386_PLT32, 4) \ _ELF_DEFINE_RELOC(R_386_COPY, 5) \ _ELF_DEFINE_RELOC(R_386_GLOB_DAT, 6) \ -_ELF_DEFINE_RELOC(R_386_JMP_SLOT, 7) \ +_ELF_DEFINE_RELOC(R_386_JUMP_SLOT, 7) \ _ELF_DEFINE_RELOC(R_386_RELATIVE, 8) \ _ELF_DEFINE_RELOC(R_386_GOTOFF, 9) \ _ELF_DEFINE_RELOC(R_386_GOTPC, 10) \ @@ -1407,9 +1409,129 @@ _ELF_DEFINE_RELOC(R_386_PC8, 23) /* */ -#define _ELF_DEFINE_AARCH64_RELOCATIONS() \ -_ELF_DEFINE_RELOC(R_AARCH64_ABS64, 257) \ -_ELF_DEFINE_RELOC(R_AARCH64_ABS32, 258) \ +#define _ELF_DEFINE_AARCH64_RELOCATIONS() \ +_ELF_DEFINE_RELOC(R_AARCH64_NONE, 0) \ +_ELF_DEFINE_RELOC(R_AARCH64_ABS64, 257) \ +_ELF_DEFINE_RELOC(R_AARCH64_ABS32, 258) \ +_ELF_DEFINE_RELOC(R_AARCH64_ABS16, 259) \ +_ELF_DEFINE_RELOC(R_AARCH64_PREL64, 260) \ +_ELF_DEFINE_RELOC(R_AARCH64_PREL32, 261) \ +_ELF_DEFINE_RELOC(R_AARCH64_PREL16, 262) \ +_ELF_DEFINE_RELOC(R_AARCH64_MOVW_UABS_G0, 263) \ +_ELF_DEFINE_RELOC(R_AARCH64_MOVW_UABS_G0_NC, 264) \ +_ELF_DEFINE_RELOC(R_AARCH64_MOVW_UABS_G1, 265) \ +_ELF_DEFINE_RELOC(R_AARCH64_MOVW_UABS_G1_NC, 266) \ +_ELF_DEFINE_RELOC(R_AARCH64_MOVW_UABS_G2, 267) \ +_ELF_DEFINE_RELOC(R_AARCH64_MOVW_UABS_G2_NC, 268) \ +_ELF_DEFINE_RELOC(R_AARCH64_MOVW_UABS_G3, 269) \ +_ELF_DEFINE_RELOC(R_AARCH64_MOVW_SABS_G0, 270) \ +_ELF_DEFINE_RELOC(R_AARCH64_MOVW_SABS_G1, 271) \ +_ELF_DEFINE_RELOC(R_AARCH64_MOVW_SABS_G2, 272) \ +_ELF_DEFINE_RELOC(R_AARCH64_LD_PREL_LO19, 273) \ +_ELF_DEFINE_RELOC(R_AARCH64_ADR_PREL_LO21, 274) \ +_ELF_DEFINE_RELOC(R_AARCH64_ADR_PREL_PG_HI21, 275) \ +_ELF_DEFINE_RELOC(R_AARCH64_ADR_PREL_PG_HI21_NC, 276) \ +_ELF_DEFINE_RELOC(R_AARCH64_ADD_ABS_LO12_NC, 277) \ +_ELF_DEFINE_RELOC(R_AARCH64_LDST8_ABS_LO12_NC, 278) \ +_ELF_DEFINE_RELOC(R_AARCH64_TSTBR14, 279) \ +_ELF_DEFINE_RELOC(R_AARCH64_CONDBR19, 280) \ +_ELF_DEFINE_RELOC(R_AARCH64_JUMP26, 282) \ +_ELF_DEFINE_RELOC(R_AARCH64_CALL26, 283) \ +_ELF_DEFINE_RELOC(R_AARCH64_LDST16_ABS_LO12_NC, 284) \ +_ELF_DEFINE_RELOC(R_AARCH64_LDST32_ABS_LO12_NC, 285) \ +_ELF_DEFINE_RELOC(R_AARCH64_LDST64_ABS_LO12_NC, 286) \ +_ELF_DEFINE_RELOC(R_AARCH64_MOVW_PREL_G0, 287) \ +_ELF_DEFINE_RELOC(R_AARCH64_MOVW_PREL_G0_NC, 288) \ +_ELF_DEFINE_RELOC(R_AARCH64_MOVW_PREL_G1, 289) \ +_ELF_DEFINE_RELOC(R_AARCH64_MOVW_PREL_G1_NC, 290) \ +_ELF_DEFINE_RELOC(R_AARCH64_MOVW_PREL_G2, 291) \ +_ELF_DEFINE_RELOC(R_AARCH64_MOVW_PREL_G2_NC, 292) \ +_ELF_DEFINE_RELOC(R_AARCH64_MOVW_PREL_G3, 293) \ +_ELF_DEFINE_RELOC(R_AARCH64_LDST128_ABS_LO12_NC, 299) \ +_ELF_DEFINE_RELOC(R_AARCH64_MOVW_GOTOFF_G0, 300) \ +_ELF_DEFINE_RELOC(R_AARCH64_MOVW_GOTOFF_G0_NC, 301) \ +_ELF_DEFINE_RELOC(R_AARCH64_MOVW_GOTOFF_G1, 302) \ +_ELF_DEFINE_RELOC(R_AARCH64_MOVW_GOTOFF_G1_NC, 303) \ +_ELF_DEFINE_RELOC(R_AARCH64_MOVW_GOTOFF_G2, 304) \ +_ELF_DEFINE_RELOC(R_AARCH64_MOVW_GOTOFF_G2_NC, 305) \ +_ELF_DEFINE_RELOC(R_AARCH64_MOVW_GOTOFF_G3, 306) \ +_ELF_DEFINE_RELOC(R_AARCH64_GOTREL64, 307) \ +_ELF_DEFINE_RELOC(R_AARCH64_GOTREL32, 308) \ +_ELF_DEFINE_RELOC(R_AARCH64_GOT_LD_PREL19, 309) \ +_ELF_DEFINE_RELOC(R_AARCH64_LD64_GOTOFF_LO15, 310) \ +_ELF_DEFINE_RELOC(R_AARCH64_ADR_GOT_PAGE, 311) \ +_ELF_DEFINE_RELOC(R_AARCH64_LD64_GOT_LO12_NC, 312) \ +_ELF_DEFINE_RELOC(R_AARCH64_LD64_GOTPAGE_LO15, 313) \ +_ELF_DEFINE_RELOC(R_AARCH64_TLSGD_ADR_PREL21, 512) \ +_ELF_DEFINE_RELOC(R_AARCH64_TLSGD_ADR_PAGE21, 513) \ +_ELF_DEFINE_RELOC(R_AARCH64_TLSGD_ADD_LO12_NC, 514) \ +_ELF_DEFINE_RELOC(R_AARCH64_TLSGD_MOVW_G1, 515) \ +_ELF_DEFINE_RELOC(R_AARCH64_TLSGD_MOVW_G0_NC, 516) \ +_ELF_DEFINE_RELOC(R_AARCH64_TLSLD_ADR_PREL21, 517) \ +_ELF_DEFINE_RELOC(R_AARCH64_TLSLD_ADR_PAGE21, 518) \ +_ELF_DEFINE_RELOC(R_AARCH64_TLSLD_ADD_LO12_NC, 519) \ +_ELF_DEFINE_RELOC(R_AARCH64_TLSLD_MOVW_G1, 520) \ +_ELF_DEFINE_RELOC(R_AARCH64_TLSLD_MOVW_G0_NC, 521) \ +_ELF_DEFINE_RELOC(R_AARCH64_TLSLD_LD_PREL19, 522) \ +_ELF_DEFINE_RELOC(R_AARCH64_TLSLD_MOVW_DTPREL_G2, 523) \ +_ELF_DEFINE_RELOC(R_AARCH64_TLSLD_MOVW_DTPREL_G1, 524) \ +_ELF_DEFINE_RELOC(R_AARCH64_TLSLD_MOVW_DTPREL_G1_NC, 525) \ +_ELF_DEFINE_RELOC(R_AARCH64_TLSLD_MOVW_DTPREL_G0, 526) \ +_ELF_DEFINE_RELOC(R_AARCH64_TLSLD_MOVW_DTPREL_G0_NC, 527) \ +_ELF_DEFINE_RELOC(R_AARCH64_TLSLD_ADD_DTPREL_HI12, 529) \ +_ELF_DEFINE_RELOC(R_AARCH64_TLSLD_ADD_DTPREL_LO12_NC, 530) \ +_ELF_DEFINE_RELOC(R_AARCH64_TLSLD_LDST8_DTPREL_LO12, 531) \ +_ELF_DEFINE_RELOC(R_AARCH64_TLSLD_LDST8_DTPREL_LO12_NC, 532) \ +_ELF_DEFINE_RELOC(R_AARCH64_TLSLD_LDST16_DTPREL_LO12, 533) \ +_ELF_DEFINE_RELOC(R_AARCH64_TLSLD_LDST16_DTPREL_LO12_NC, 534) \ +_ELF_DEFINE_RELOC(R_AARCH64_TLSLD_LDST32_DTPREL_LO12, 535) \ +_ELF_DEFINE_RELOC(R_AARCH64_TLSLD_LDST32_DTPREL_LO12_NC, 536) \ +_ELF_DEFINE_RELOC(R_AARCH64_TLSLD_LDST64_DTPREL_LO12, 537) \ +_ELF_DEFINE_RELOC(R_AARCH64_TLSLD_LDST64_DTPREL_LO12_NC, 538) \ +_ELF_DEFINE_RELOC(R_AARCH64_TLSIE_MOVW_GOTTPREL_G1, 539) \ +_ELF_DEFINE_RELOC(R_AARCH64_TLSIE_MOVW_GOTTPREL_G0_NC, 540) \ +_ELF_DEFINE_RELOC(R_AARCH64_TLSIE_ADR_GOTTPREL_PAGE21, 541) \ +_ELF_DEFINE_RELOC(R_AARCH64_TLSIE_LD64_GOTTPREL_LO12_NC, 542) \ +_ELF_DEFINE_RELOC(R_AARCH64_TLSIE_LD_GOTTPREL_PREL19, 543) \ +_ELF_DEFINE_RELOC(R_AARCH64_TLSLE_MOVW_TPREL_G2, 544) \ +_ELF_DEFINE_RELOC(R_AARCH64_TLSLE_MOVW_TPREL_G1, 545) \ +_ELF_DEFINE_RELOC(R_AARCH64_TLSLE_MOVW_TPREL_G1_NC, 546) \ +_ELF_DEFINE_RELOC(R_AARCH64_TLSLE_MOVW_TPREL_G0, 547) \ +_ELF_DEFINE_RELOC(R_AARCH64_TLSLE_MOVW_TPREL_G0_NC, 548) \ +_ELF_DEFINE_RELOC(R_AARCH64_TLSLE_ADD_TPREL_HI12, 549) \ +_ELF_DEFINE_RELOC(R_AARCH64_TLSLE_ADD_TPREL_LO12, 550) \ +_ELF_DEFINE_RELOC(R_AARCH64_TLSLE_ADD_TPREL_LO12_NC, 551) \ +_ELF_DEFINE_RELOC(R_AARCH64_TLSLE_LDST8_TPREL_LO12, 552) \ +_ELF_DEFINE_RELOC(R_AARCH64_TLSLE_LDST8_TPREL_LO12_NC, 553) \ +_ELF_DEFINE_RELOC(R_AARCH64_TLSLE_LDST16_TPREL_LO12, 554) \ +_ELF_DEFINE_RELOC(R_AARCH64_TLSLE_LDST16_TPREL_LO12_NC, 555) \ +_ELF_DEFINE_RELOC(R_AARCH64_TLSLE_LDST32_TPREL_LO12, 556) \ +_ELF_DEFINE_RELOC(R_AARCH64_TLSLE_LDST32_TPREL_LO12_NC, 557) \ +_ELF_DEFINE_RELOC(R_AARCH64_TLSLE_LDST64_TPREL_LO12, 558) \ +_ELF_DEFINE_RELOC(R_AARCH64_TLSLE_LDST64_TPREL_LO12_NC, 559) \ +_ELF_DEFINE_RELOC(R_AARCH64_TLSDESC_LD_PREL19, 560) \ +_ELF_DEFINE_RELOC(R_AARCH64_TLSDESC_ADR_PREL21, 561) \ +_ELF_DEFINE_RELOC(R_AARCH64_TLSDESC_ADR_PAGE21, 562) \ +_ELF_DEFINE_RELOC(R_AARCH64_TLSDESC_LD64_LO12, 563) \ +_ELF_DEFINE_RELOC(R_AARCH64_TLSDESC_ADD_LO12, 564) \ +_ELF_DEFINE_RELOC(R_AARCH64_TLSDESC_OFF_G1, 565) \ +_ELF_DEFINE_RELOC(R_AARCH64_TLSDESC_OFF_G0_NC, 566) \ +_ELF_DEFINE_RELOC(R_AARCH64_TLSDESC_LDR, 567) \ +_ELF_DEFINE_RELOC(R_AARCH64_TLSDESC_ADD, 568) \ +_ELF_DEFINE_RELOC(R_AARCH64_TLSDESC_CALL, 569) \ +_ELF_DEFINE_RELOC(R_AARCH64_TLSLE_LDST128_TPREL_LO12, 570) \ +_ELF_DEFINE_RELOC(R_AARCH64_TLSLE_LDST128_TPREL_LO12_NC, 571) \ +_ELF_DEFINE_RELOC(R_AARCH64_TLSLD_LDST128_DTPREL_LO12, 572) \ +_ELF_DEFINE_RELOC(R_AARCH64_TLSLD_LDST128_DTPREL_LO12_NC, 573) \ +_ELF_DEFINE_RELOC(R_AARCH64_COPY, 1024) \ +_ELF_DEFINE_RELOC(R_AARCH64_GLOB_DAT, 1025) \ +_ELF_DEFINE_RELOC(R_AARCH64_JUMP_SLOT, 1026) \ +_ELF_DEFINE_RELOC(R_AARCH64_RELATIVE, 1027) \ +_ELF_DEFINE_RELOC(R_AARCH64_TLS_DTPREL64, 1028) \ +_ELF_DEFINE_RELOC(R_AARCH64_TLS_DTPMOD64, 1029) \ +_ELF_DEFINE_RELOC(R_AARCH64_TLS_TPREL64, 1030) \ +_ELF_DEFINE_RELOC(R_AARCH64_TLSDESC, 1031) \ +_ELF_DEFINE_RELOC(R_AARCH64_IRELATIVE, 1032) /* * These are the symbols used in the Sun ``Linkers and Loaders @@ -1633,7 +1755,7 @@ _ELF_DEFINE_RELOC(R_IA_64_LTV32MSB, 0x74) \ _ELF_DEFINE_RELOC(R_IA_64_LTV32LSB, 0x75) \ _ELF_DEFINE_RELOC(R_IA_64_LTV64MSB, 0x76) \ _ELF_DEFINE_RELOC(R_IA_64_LTV64LSB, 0x77) \ -_ELF_DEFINE_RELOC(R_IA_64_PCREL21BIa, 0x79) \ +_ELF_DEFINE_RELOC(R_IA_64_PCREL21BI, 0x79) \ _ELF_DEFINE_RELOC(R_IA_64_PCREL22, 0x7A) \ _ELF_DEFINE_RELOC(R_IA_64_PCREL64I, 0x7B) \ _ELF_DEFINE_RELOC(R_IA_64_IPLTMSB, 0x80) \ @@ -1723,7 +1845,7 @@ _ELF_DEFINE_RELOC(R_PPC_REL32, 26) \ _ELF_DEFINE_RELOC(R_PPC_PLT32, 27) \ _ELF_DEFINE_RELOC(R_PPC_PLTREL32, 28) \ _ELF_DEFINE_RELOC(R_PPC_PLT16_LO, 29) \ -_ELF_DEFINE_RELOC(R_PPL_PLT16_HI, 30) \ +_ELF_DEFINE_RELOC(R_PPC_PLT16_HI, 30) \ _ELF_DEFINE_RELOC(R_PPC_PLT16_HA, 31) \ _ELF_DEFINE_RELOC(R_PPC_SDAREL16, 32) \ _ELF_DEFINE_RELOC(R_PPC_SECTOFF, 33) \ @@ -1926,7 +2048,7 @@ _ELF_DEFINE_RELOC(R_RISCV_SUB32, 39) \ _ELF_DEFINE_RELOC(R_RISCV_SUB64, 40) \ _ELF_DEFINE_RELOC(R_RISCV_GNU_VTINHERIT, 41) \ _ELF_DEFINE_RELOC(R_RISCV_GNU_VTENTRY, 42) \ -_ELF_DEFINE_RELOC(R_RISCV_ALIGN 43) \ +_ELF_DEFINE_RELOC(R_RISCV_ALIGN, 43) \ _ELF_DEFINE_RELOC(R_RISCV_RVC_BRANCH, 44) \ _ELF_DEFINE_RELOC(R_RISCV_RVC_JUMP, 45) @@ -2042,6 +2164,7 @@ _ELF_DEFINE_IA64_RELOCATIONS() \ _ELF_DEFINE_MIPS_RELOCATIONS() \ _ELF_DEFINE_PPC32_RELOCATIONS() \ _ELF_DEFINE_PPC64_RELOCATIONS() \ +_ELF_DEFINE_RISCV_RELOCATIONS() \ _ELF_DEFINE_SPARC_RELOCATIONS() \ _ELF_DEFINE_X86_64_RELOCATIONS() diff --git a/contrib/elftoolchain/common/native-elf-format b/contrib/elftoolchain/common/native-elf-format index d36ab53..2bdd914 100755 --- a/contrib/elftoolchain/common/native-elf-format +++ b/contrib/elftoolchain/common/native-elf-format @@ -1,6 +1,6 @@ #!/bin/sh # -# $Id: native-elf-format 3186 2015-04-16 22:16:40Z emaste $ +# $Id: native-elf-format 3293 2016-01-07 19:26:27Z emaste $ # # Find the native ELF format for a host platform by compiling a # test object and examining the resulting object. @@ -33,6 +33,8 @@ $1 ~ "Data:" { $1 ~ "Machine:" { if (match($0, "Intel.*386")) { elfarch = "EM_386"; + } else if (match($0, "MIPS")) { + elfarch = "EM_MIPS"; } else if (match($0, ".*[xX]86-64")) { elfarch = "EM_X86_64"; } else { diff --git a/contrib/elftoolchain/cxxfilt/cxxfilt.c b/contrib/elftoolchain/cxxfilt/cxxfilt.c index 4efa45b..9318c64 100644 --- a/contrib/elftoolchain/cxxfilt/cxxfilt.c +++ b/contrib/elftoolchain/cxxfilt/cxxfilt.c @@ -35,7 +35,7 @@ #include "_elftc.h" -ELFTC_VCSID("$Id: cxxfilt.c 3174 2015-03-27 17:13:41Z emaste $"); +ELFTC_VCSID("$Id: cxxfilt.c 3356 2016-01-22 22:31:38Z jkoshy $"); #define STRBUFSZ 8192 @@ -112,11 +112,11 @@ find_format(const char *fstr) } static char * -demangle(char *name, int strict, int *pos) +demangle(char *name, int strict, size_t *pos) { static char dem[STRBUFSZ]; char nb[STRBUFSZ]; - int p, t; + size_t p, t; if (stripus && *name == '_') { strncpy(nb, name + 1, sizeof(nb) - 1); @@ -128,10 +128,10 @@ demangle(char *name, int strict, int *pos) nb[sizeof(nb) - 1] = '\0'; p = strlen(nb); - if (p <= 0) + if (p == 0) return NULL; - while (elftc_demangle(nb, dem, sizeof(dem), format) < 0) { + while (elftc_demangle(nb, dem, sizeof(dem), (unsigned) format) < 0) { if (!strict && p > 1) { nb[--p] = '\0'; continue; @@ -149,7 +149,8 @@ int main(int argc, char **argv) { char *dem, buf[STRBUFSZ]; - int c, i, p, s, opt; + size_t i, p, s; + int c, n, opt; while ((opt = getopt_long(argc, argv, "_nps:V", longopts, NULL)) != -1) { @@ -182,9 +183,9 @@ main(int argc, char **argv) argc -= optind; if (*argv != NULL) { - for (i = 0; i < argc; i++) { - if ((dem = demangle(argv[i], 1, NULL)) == NULL) - fprintf(stderr, "Failed: %s\n", argv[i]); + for (n = 0; n < argc; n++) { + if ((dem = demangle(argv[n], 1, NULL)) == NULL) + fprintf(stderr, "Failed: %s\n", argv[n]); else printf("%s\n", dem); } @@ -213,7 +214,7 @@ main(int argc, char **argv) if ((size_t) p >= sizeof(buf) - 1) warnx("buffer overflowed"); else - buf[p++] = c; + buf[p++] = (char) c; } } diff --git a/contrib/elftoolchain/elfcopy/Makefile b/contrib/elftoolchain/elfcopy/Makefile index cb1a31b..8b208e0 100644 --- a/contrib/elftoolchain/elfcopy/Makefile +++ b/contrib/elftoolchain/elfcopy/Makefile @@ -1,10 +1,13 @@ -# $Id: Makefile 2290 2011-12-04 07:20:46Z jkoshy $ +# $Id: Makefile 3381 2016-01-30 19:39:47Z jkoshy $ TOP= .. +.include "${TOP}/mk/elftoolchain.components.mk" + PROG= elfcopy -SRCS= archive.c ascii.c binary.c main.c sections.c segments.c symbols.c +SRCS= archive.c ascii.c binary.c main.c sections.c segments.c \ + symbols.c WARNS?= 5 @@ -15,14 +18,24 @@ LDADD= -lelf -lelftc LDADD+= -larchive .endif +.if defined(WITH_PE) && ${WITH_PE:tl} == "yes" +SRCS+= pe.c +CFLAGS+= -DWITH_PE=1 + +DPADD+= ${LIBPE} +LDADD+= -lpe +.endif + MAN= elfcopy.1 mcs.1 strip.1 +MLINKS= elfcopy.1 objcopy.1 NO_SHARED?= yes -LINKS= ${BINDIR}/elfcopy ${BINDIR}/strip \ - ${BINDIR}/elfcopy ${BINDIR}/mcs +LINKS= ${BINDIR}/elfcopy ${BINDIR}/mcs \ + ${BINDIR}/elfcopy ${BINDIR}/objcopy \ + ${BINDIR}/elfcopy ${BINDIR}/strip -EXTRA_TARGETS= strip mcs +EXTRA_TARGETS= mcs strip objcopy CLEANFILES+= ${EXTRA_TARGETS} diff --git a/contrib/elftoolchain/elfcopy/archive.c b/contrib/elftoolchain/elfcopy/archive.c index 682a1df..97e2498 100644 --- a/contrib/elftoolchain/elfcopy/archive.c +++ b/contrib/elftoolchain/elfcopy/archive.c @@ -38,7 +38,7 @@ #include "elfcopy.h" -ELFTC_VCSID("$Id: archive.c 3174 2015-03-27 17:13:41Z emaste $"); +ELFTC_VCSID("$Id: archive.c 3287 2015-12-31 16:58:48Z emaste $"); #define _ARMAG_LEN 8 /* length of ar magic string */ #define _ARHDR_LEN 60 /* length of ar header */ @@ -382,7 +382,7 @@ ac_read_objs(struct elfcopy *ecp, int ifd) if (lseek(ifd, 0, SEEK_SET) == -1) err(EXIT_FAILURE, "lseek failed"); if ((a = archive_read_new()) == NULL) - errx(EXIT_FAILURE, "%s", archive_error_string(a)); + errx(EXIT_FAILURE, "archive_read_new failed"); archive_read_support_format_ar(a); AC(archive_read_open_fd(a, ifd, 10240)); for(;;) { @@ -443,7 +443,7 @@ ac_write_objs(struct elfcopy *ecp, int ofd) int nr; if ((a = archive_write_new()) == NULL) - errx(EXIT_FAILURE, "%s", archive_error_string(a)); + errx(EXIT_FAILURE, "archive_write_new failed"); archive_write_set_format_ar_svr4(a); AC(archive_write_open_fd(a, ofd)); diff --git a/contrib/elftoolchain/elfcopy/elfcopy.1 b/contrib/elftoolchain/elfcopy/elfcopy.1 index 83cda5d..b7b0ce4 100644 --- a/contrib/elftoolchain/elfcopy/elfcopy.1 +++ b/contrib/elftoolchain/elfcopy/elfcopy.1 @@ -21,13 +21,14 @@ .\" out of the use of this software, even if advised of the possibility of .\" such damage. .\" -.\" $Id: elfcopy.1 3266 2015-12-07 15:38:26Z emaste $ +.\" $Id: elfcopy.1 3381 2016-01-30 19:39:47Z jkoshy $ .\" -.Dd December 7, 2015 +.Dd January 29, 2016 .Os .Dt ELFCOPY 1 .Sh NAME -.Nm elfcopy +.Nm elfcopy , +.Nm objcopy .Nd copy and translate object files .Sh SYNOPSIS .Nm @@ -85,7 +86,7 @@ .Sh DESCRIPTION The .Nm -utility copies the content of the ELF object named by argument +utility copies the content of the binary object named by argument .Ar infile to that named by argument .Ar outfile , @@ -121,6 +122,10 @@ to the output. .It Fl O Ar objformat | Fl -output-target= Ns Ar objformat Write the output file using the object format specified in argument .Ar objformat . +The argument +.Ar objformat +should be one of the target names recognized by +.Xr elftc_bfd_find_target 3 . .It Fl R Ar sectionname | Fl -remove-section= Ns Ar sectionname Remove any section with name .Ar sectionname @@ -330,8 +335,14 @@ Do not copy symbols that are not needed for relocation processing. .Xr mcs 1 , .Xr strip 1 , .Xr elf 3 , +.Xr elftc_bfd_find_target 3 , .Xr ar 5 , .Xr elf 5 +.Sh COMPATIBILITY +The +.Nm +utility is expected to be option compatible with GNU +.Nm objcopy . .Sh HISTORY .Nm has been implemented by diff --git a/contrib/elftoolchain/elfcopy/elfcopy.h b/contrib/elftoolchain/elfcopy/elfcopy.h index 48574b5..614c0e7 100644 --- a/contrib/elftoolchain/elfcopy/elfcopy.h +++ b/contrib/elftoolchain/elfcopy/elfcopy.h @@ -23,7 +23,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $Id: elfcopy.h 3221 2015-05-24 23:42:43Z kaiwang27 $ + * $Id: elfcopy.h 3310 2016-01-10 09:10:54Z kaiwang27 $ */ #include <sys/queue.h> @@ -287,6 +287,7 @@ struct section *create_external_section(struct elfcopy *_ecp, const char *_name, int _loadable); void create_external_symtab(struct elfcopy *_ecp); void create_ihex(int _ifd, int _ofd); +void create_pe(struct elfcopy *_ecp, int _ifd, int _ofd); void create_scn(struct elfcopy *_ecp); void create_srec(struct elfcopy *_ecp, int _ifd, int _ofd, const char *_ofn); void create_symtab(struct elfcopy *_ecp); diff --git a/contrib/elftoolchain/elfcopy/main.c b/contrib/elftoolchain/elfcopy/main.c index e2685b4..b51ba4e 100644 --- a/contrib/elftoolchain/elfcopy/main.c +++ b/contrib/elftoolchain/elfcopy/main.c @@ -39,7 +39,7 @@ #include "elfcopy.h" -ELFTC_VCSID("$Id: main.c 3268 2015-12-07 20:30:55Z emaste $"); +ELFTC_VCSID("$Id: main.c 3399 2016-02-12 18:07:56Z emaste $"); enum options { @@ -316,6 +316,7 @@ create_elf(struct elfcopy *ecp) oeh.e_entry = ieh.e_entry; oeh.e_version = ieh.e_version; + ecp->flags &= ~(EXECUTABLE | DYNAMIC | RELOCATABLE); if (ieh.e_type == ET_EXEC) ecp->flags |= EXECUTABLE; else if (ieh.e_type == ET_DYN) @@ -722,6 +723,15 @@ create_file(struct elfcopy *ecp, const char *src, const char *dst) create_srec(ecp, ofd, ofd0, dst != NULL ? dst : src); break; + case ETF_PE: + case ETF_EFI: +#if WITH_PE + create_pe(ecp, ofd, ofd0); +#else + errx(EXIT_FAILURE, "PE/EFI support not enabled" + " at compile time"); +#endif + break; default: errx(EXIT_FAILURE, "Internal: unsupported" " output flavour %d", ecp->oec); @@ -1345,6 +1355,9 @@ set_output_target(struct elfcopy *ecp, const char *target_name) ecp->oed = elftc_bfd_target_byteorder(tgt); ecp->oem = elftc_bfd_target_machine(tgt); } + if (ecp->otf == ETF_EFI || ecp->otf == ETF_PE) + ecp->oem = elftc_bfd_target_machine(tgt); + ecp->otgt = target_name; } @@ -1366,7 +1379,7 @@ set_osabi(struct elfcopy *ecp, const char *abi) #define ELFCOPY_USAGE_MESSAGE "\ Usage: %s [options] infile [outfile]\n\ - Transform an ELF object.\n\n\ + Transform object files.\n\n\ Options:\n\ -d | -g | --strip-debug Remove debugging information from the output.\n\ -j SECTION | --only-section=SECTION\n\ @@ -1382,6 +1395,8 @@ Usage: %s [options] infile [outfile]\n\ -N SYM | --strip-symbol=SYM Do not copy symbol SYM to the output.\n\ -O FORMAT | --output-target=FORMAT\n\ Specify object format for the output file.\n\ + FORMAT should be a target name understood by\n\ + elftc_bfd_find_target(3).\n\ -R NAME | --remove-section=NAME\n\ Remove the named section.\n\ -S | --strip-all Remove all symbol and relocation information\n\ @@ -1471,6 +1486,7 @@ Usage: %s [options] file...\n\ Options:\n\ -d | -g | -S | --strip-debug Remove debugging symbols.\n\ -h | --help Print a help message.\n\ + -o FILE | --output-file FILE Write output to FILE.\n\ --only-keep-debug Keep debugging information only.\n\ -p | --preserve-dates Preserve access and modification times.\n\ -s | --strip-all Remove all symbols.\n\ diff --git a/contrib/elftoolchain/elfcopy/pe.c b/contrib/elftoolchain/elfcopy/pe.c new file mode 100644 index 0000000..0d075c5 --- /dev/null +++ b/contrib/elftoolchain/elfcopy/pe.c @@ -0,0 +1,233 @@ +/*- + * Copyright (c) 2016 Kai Wang + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include <sys/param.h> +#include <err.h> +#include <gelf.h> +#include <libpe.h> +#include <stdlib.h> +#include <string.h> +#include <time.h> + +#include "elfcopy.h" + +ELFTC_VCSID("$Id: pe.c 3312 2016-01-10 09:23:51Z kaiwang27 $"); + +/* Convert ELF object to Portable Executable (PE). */ +void +create_pe(struct elfcopy *ecp, int ifd, int ofd) +{ + Elf *e; + Elf_Scn *scn; + Elf_Data *d; + GElf_Ehdr eh; + GElf_Shdr sh; + PE *pe; + PE_Scn *ps; + PE_SecHdr psh; + PE_CoffHdr pch; + PE_OptHdr poh; + PE_Object po; + PE_Buffer *pb; + const char *name; + size_t indx; + int elferr, i; + + if (ecp->otf == ETF_EFI || ecp->oem == EM_X86_64) + po = PE_O_PE32P; + else + po = PE_O_PE32; + + if ((e = elf_begin(ifd, ELF_C_READ, NULL)) == NULL) + errx(EXIT_FAILURE, "elf_begin() failed: %s", + elf_errmsg(-1)); + + if (gelf_getehdr(e, &eh) == NULL) + errx(EXIT_FAILURE, "gelf_getehdr() failed: %s", + elf_errmsg(-1)); + + if (elf_getshstrndx(ecp->ein, &indx) == 0) + errx(EXIT_FAILURE, "elf_getshstrndx() failed: %s", + elf_errmsg(-1)); + + if ((pe = pe_init(ofd, PE_C_WRITE, po)) == NULL) + err(EXIT_FAILURE, "pe_init() failed"); + + /* Setup PE COFF header. */ + memset(&pch, 0, sizeof(pch)); + switch (ecp->oem) { + case EM_386: + pch.ch_machine = IMAGE_FILE_MACHINE_I386; + break; + case EM_X86_64: + pch.ch_machine = IMAGE_FILE_MACHINE_AMD64; + break; + default: + pch.ch_machine = IMAGE_FILE_MACHINE_UNKNOWN; + break; + } + pch.ch_timestamp = (uint32_t) time(NULL); + if (pe_update_coff_header(pe, &pch) < 0) + err(EXIT_FAILURE, "pe_update_coff_header() failed"); + + /* Setup PE optional header. */ + memset(&poh, 0, sizeof(poh)); + if (ecp->otf == ETF_EFI) + poh.oh_subsystem = IMAGE_SUBSYSTEM_EFI_APPLICATION; + poh.oh_entry = (uint32_t) eh.e_entry; + + /* + * Default section alignment and file alignment. (Here the + * section alignment is set to the default page size of the + * archs supported. We should use different section alignment + * for some arch. (e.g. IA64) + */ + poh.oh_secalign = 0x1000; + poh.oh_filealign = 0x200; + + /* Copy sections. */ + scn = NULL; + while ((scn = elf_nextscn(e, scn)) != NULL) { + + /* + * Read in ELF section. + */ + + if (gelf_getshdr(scn, &sh) == NULL) { + warnx("gelf_getshdr() failed: %s", elf_errmsg(-1)); + (void) elf_errno(); + continue; + } + if ((name = elf_strptr(ecp->ein, indx, sh.sh_name)) == + NULL) { + warnx("elf_strptr() failed: %s", elf_errmsg(-1)); + (void) elf_errno(); + continue; + } + + /* Skip sections unneeded. */ + if (strcmp(name, ".shstrtab") == 0 || + strcmp(name, ".symtab") == 0 || + strcmp(name, ".strtab") == 0) + continue; + + if ((d = elf_getdata(scn, NULL)) == NULL) { + warnx("elf_getdata() failed: %s", elf_errmsg(-1)); + (void) elf_errno(); + continue; + } + + if (strcmp(name, ".text") == 0) { + poh.oh_textbase = (uint32_t) sh.sh_addr; + poh.oh_textsize = (uint32_t) roundup(sh.sh_size, + poh.oh_filealign); + } else { + if (po == PE_O_PE32 && strcmp(name, ".data") == 0) + poh.oh_database = sh.sh_addr; + if (sh.sh_type == SHT_NOBITS) + poh.oh_bsssize += (uint32_t) + roundup(sh.sh_size, poh.oh_filealign); + else if (sh.sh_flags & SHF_ALLOC) + poh.oh_datasize += (uint32_t) + roundup(sh.sh_size, poh.oh_filealign); + } + + /* + * Create PE/COFF section. + */ + + if ((ps = pe_newscn(pe)) == NULL) { + warn("pe_newscn() failed"); + continue; + } + + /* + * Setup PE/COFF section header. The section name is not + * NUL-terminated if its length happens to be 8. Long + * section name should be truncated for PE image according + * to the PE/COFF specification. + */ + memset(&psh, 0, sizeof(psh)); + strncpy(psh.sh_name, name, sizeof(psh.sh_name)); + psh.sh_addr = sh.sh_addr; + psh.sh_virtsize = sh.sh_size; + if (sh.sh_type != SHT_NOBITS) + psh.sh_rawsize = sh.sh_size; + else + psh.sh_char |= IMAGE_SCN_CNT_UNINITIALIZED_DATA; + + /* + * Translate ELF section flags to PE/COFF section flags. + */ + psh.sh_char |= IMAGE_SCN_MEM_READ; + if (sh.sh_flags & SHF_WRITE) + psh.sh_char |= IMAGE_SCN_MEM_WRITE; + if (sh.sh_flags & SHF_EXECINSTR) + psh.sh_char |= IMAGE_SCN_MEM_EXECUTE | + IMAGE_SCN_CNT_CODE; + if ((sh.sh_flags & SHF_ALLOC) && (psh.sh_char & 0xF0) == 0) + psh.sh_char |= IMAGE_SCN_CNT_INITIALIZED_DATA; + for (i = 0xE; i > 0; i--) { + if (sh.sh_addralign & (1U << (i - 1))) { + psh.sh_char |= i << 20; + break; + } + } + + /* Mark relocation section "discardable". */ + if (strcmp(name, ".reloc") == 0) + psh.sh_char |= IMAGE_SCN_MEM_DISCARDABLE; + + if (pe_update_section_header(ps, &psh) < 0) { + warn("pe_update_section_header() failed"); + continue; + } + + /* Copy section content. */ + if ((pb = pe_newbuffer(ps)) == NULL) { + warn("pe_newbuffer() failed"); + continue; + } + pb->pb_align = 1; + pb->pb_off = 0; + pb->pb_size = sh.sh_size; + pb->pb_buf = d->d_buf; + } + elferr = elf_errno(); + if (elferr != 0) + warnx("elf_nextscn() failed: %s", elf_errmsg(elferr)); + + /* Update PE optional header. */ + if (pe_update_opt_header(pe, &poh) < 0) + err(EXIT_FAILURE, "pe_update_opt_header() failed"); + + /* Write out PE/COFF object. */ + if (pe_update(pe) < 0) + err(EXIT_FAILURE, "pe_update() failed"); + + pe_finish(pe); + elf_end(e); +} diff --git a/contrib/elftoolchain/elfcopy/sections.c b/contrib/elftoolchain/elfcopy/sections.c index a17c9ab..2ba3d48 100644 --- a/contrib/elftoolchain/elfcopy/sections.c +++ b/contrib/elftoolchain/elfcopy/sections.c @@ -34,7 +34,7 @@ #include "elfcopy.h" -ELFTC_VCSID("$Id: sections.c 3272 2015-12-11 20:00:54Z kaiwang27 $"); +ELFTC_VCSID("$Id: sections.c 3346 2016-01-17 20:09:15Z kaiwang27 $"); static void add_gnu_debuglink(struct elfcopy *ecp); static uint32_t calc_crc32(const char *p, size_t len, uint32_t crc); @@ -223,6 +223,7 @@ static int is_debug_section(const char *name) { const char *dbg_sec[] = { + ".apple_", ".debug", ".gnu.linkonce.wi.", ".line", @@ -369,7 +370,7 @@ create_scn(struct elfcopy *ecp) is = NULL; while ((is = elf_nextscn(ecp->ein, is)) != NULL) { if (gelf_getshdr(is, &ish) == NULL) - errx(EXIT_FAILURE, "219 gelf_getshdr failed: %s", + errx(EXIT_FAILURE, "gelf_getshdr failed: %s", elf_errmsg(-1)); if ((name = elf_strptr(ecp->ein, indx, ish.sh_name)) == NULL) errx(EXIT_FAILURE, "elf_strptr failed: %s", @@ -416,12 +417,19 @@ create_scn(struct elfcopy *ecp) * is loadable, but if user explicitly set section flags * while neither "load" nor "alloc" is set, we make the * section unloadable. + * + * Sections in relocatable object is loadable if + * section flag SHF_ALLOC is set. */ if (sec_flags && (sec_flags & (SF_LOAD | SF_ALLOC)) == 0) s->loadable = 0; - else + else { s->loadable = add_to_inseg_list(ecp, s); + if ((ecp->flags & RELOCATABLE) && + (ish.sh_flags & SHF_ALLOC)) + s->loadable = 1; + } } else { /* Assuming .shstrtab is "unloadable". */ s = ecp->shstrtab; @@ -875,10 +883,10 @@ resync_sections(struct elfcopy *ecp) if (s->align == 0) s->align = 1; if (off <= s->off) { - if (!s->loadable) + if (!s->loadable || (ecp->flags & RELOCATABLE)) s->off = roundup(off, s->align); } else { - if (s->loadable) + if (s->loadable && (ecp->flags & RELOCATABLE) == 0) warnx("moving loadable section %s, " "is this intentional?", s->name); s->off = roundup(off, s->align); @@ -1028,8 +1036,11 @@ print_section(struct section *s) print_data(s->buf, s->sz); } else { id = NULL; - while ((id = elf_getdata(s->is, id)) != NULL) + while ((id = elf_getdata(s->is, id)) != NULL || + (id = elf_rawdata(s->is, id)) != NULL) { + (void) elf_errno(); print_data(id->d_buf, id->d_size); + } elferr = elf_errno(); if (elferr != 0) errx(EXIT_FAILURE, "elf_getdata() failed: %s", @@ -1049,7 +1060,9 @@ read_section(struct section *s, size_t *size) sz = 0; b = NULL; id = NULL; - while ((id = elf_getdata(s->is, id)) != NULL) { + while ((id = elf_getdata(s->is, id)) != NULL || + (id = elf_rawdata(s->is, id)) != NULL) { + (void) elf_errno(); if (b == NULL) b = malloc(id->d_size); else @@ -1077,10 +1090,10 @@ copy_shdr(struct elfcopy *ecp, struct section *s, const char *name, int copy, GElf_Shdr ish, osh; if (gelf_getshdr(s->is, &ish) == NULL) - errx(EXIT_FAILURE, "526 gelf_getshdr() failed: %s", + errx(EXIT_FAILURE, "gelf_getshdr() failed: %s", elf_errmsg(-1)); if (gelf_getshdr(s->os, &osh) == NULL) - errx(EXIT_FAILURE, "529 gelf_getshdr() failed: %s", + errx(EXIT_FAILURE, "gelf_getshdr() failed: %s", elf_errmsg(-1)); if (copy) @@ -1097,19 +1110,32 @@ copy_shdr(struct elfcopy *ecp, struct section *s, const char *name, int copy, if (sec_flags) { osh.sh_flags = 0; - if (sec_flags & SF_ALLOC) { + if (sec_flags & SF_ALLOC) osh.sh_flags |= SHF_ALLOC; - if (!s->loadable) - warnx("set SHF_ALLOC flag for " - "unloadable section %s", - s->name); - } if ((sec_flags & SF_READONLY) == 0) osh.sh_flags |= SHF_WRITE; if (sec_flags & SF_CODE) osh.sh_flags |= SHF_EXECINSTR; + if ((sec_flags & SF_CONTENTS) && + s->type == SHT_NOBITS && s->sz > 0) { + /* + * Convert SHT_NOBITS section to section with + * (zero'ed) content on file. + */ + osh.sh_type = s->type = SHT_PROGBITS; + if ((s->buf = calloc(1, s->sz)) == NULL) + err(EXIT_FAILURE, "malloc failed"); + s->nocopy = 1; + } } else { osh.sh_flags = ish.sh_flags; + /* + * Newer binutils as(1) emits the section flag + * SHF_INFO_LINK for relocation sections. elfcopy + * emits this flag in the output section if it's + * missing in the input section, to remain compatible + * with binutils. + */ if (ish.sh_type == SHT_REL || ish.sh_type == SHT_RELA) osh.sh_flags |= SHF_INFO_LINK; } @@ -1135,11 +1161,14 @@ copy_data(struct section *s) return; if ((id = elf_getdata(s->is, NULL)) == NULL) { - elferr = elf_errno(); - if (elferr != 0) - errx(EXIT_FAILURE, "elf_getdata() failed: %s", - elf_errmsg(elferr)); - return; + (void) elf_errno(); + if ((id = elf_rawdata(s->is, NULL)) == NULL) { + elferr = elf_errno(); + if (elferr != 0) + errx(EXIT_FAILURE, "failed to read section:" + " %s", s->name); + return; + } } if ((od = elf_newdata(s->os)) == NULL) @@ -1245,6 +1274,7 @@ insert_sections(struct elfcopy *ecp) struct sec_add *sa; struct section *s; size_t off; + uint64_t stype; /* Put these sections in the end of current list. */ off = 0; @@ -1259,8 +1289,20 @@ insert_sections(struct elfcopy *ecp) /* TODO: Add section header vma/lma, flag changes here */ + /* + * The default section type for user added section is + * SHT_PROGBITS. If the section name match certain patterns, + * elfcopy will try to set a more appropriate section type. + * However, data type is always set to ELF_T_BYTE and no + * translation is performed by libelf. + */ + stype = SHT_PROGBITS; + if (strcmp(sa->name, ".note") == 0 || + strncmp(sa->name, ".note.", strlen(".note.")) == 0) + stype = SHT_NOTE; + (void) create_external_section(ecp, sa->name, NULL, sa->content, - sa->size, off, SHT_PROGBITS, ELF_T_BYTE, 0, 1, 0, 0); + sa->size, off, stype, ELF_T_BYTE, 0, 1, 0, 0); } } @@ -1285,7 +1327,7 @@ update_shdr(struct elfcopy *ecp, int update_link) continue; if (gelf_getshdr(s->os, &osh) == NULL) - errx(EXIT_FAILURE, "668 gelf_getshdr failed: %s", + errx(EXIT_FAILURE, "gelf_getshdr failed: %s", elf_errmsg(-1)); /* Find section name in string table and set sh_name. */ @@ -1364,7 +1406,7 @@ set_shstrtab(struct elfcopy *ecp) } if (gelf_getshdr(s->os, &sh) == NULL) - errx(EXIT_FAILURE, "692 gelf_getshdr() failed: %s", + errx(EXIT_FAILURE, "gelf_getshdr() failed: %s", elf_errmsg(-1)); sh.sh_addr = 0; sh.sh_addralign = 1; @@ -1431,14 +1473,17 @@ add_section(struct elfcopy *ecp, const char *arg) if (stat(fn, &sb) == -1) err(EXIT_FAILURE, "stat failed"); sa->size = sb.st_size; - if ((sa->content = malloc(sa->size)) == NULL) - err(EXIT_FAILURE, "malloc failed"); - if ((fp = fopen(fn, "r")) == NULL) - err(EXIT_FAILURE, "can not open %s", fn); - if (fread(sa->content, 1, sa->size, fp) == 0 || - ferror(fp)) - err(EXIT_FAILURE, "fread failed"); - fclose(fp); + if (sa->size > 0) { + if ((sa->content = malloc(sa->size)) == NULL) + err(EXIT_FAILURE, "malloc failed"); + if ((fp = fopen(fn, "r")) == NULL) + err(EXIT_FAILURE, "can not open %s", fn); + if (fread(sa->content, 1, sa->size, fp) == 0 || + ferror(fp)) + err(EXIT_FAILURE, "fread failed"); + fclose(fp); + } else + sa->content = NULL; STAILQ_INSERT_TAIL(&ecp->v_sadd, sa, sadd_list); ecp->flags |= SEC_ADD; diff --git a/contrib/elftoolchain/elfcopy/segments.c b/contrib/elftoolchain/elfcopy/segments.c index 837cea5..8ce0b83 100644 --- a/contrib/elftoolchain/elfcopy/segments.c +++ b/contrib/elftoolchain/elfcopy/segments.c @@ -34,7 +34,7 @@ #include "elfcopy.h" -ELFTC_VCSID("$Id: segments.c 3269 2015-12-11 18:38:43Z kaiwang27 $"); +ELFTC_VCSID("$Id: segments.c 3397 2016-02-12 14:35:19Z emaste $"); static void insert_to_inseg_list(struct segment *seg, struct section *sec); @@ -107,11 +107,11 @@ adjust_addr(struct elfcopy *ecp) TAILQ_FOREACH(s, &ecp->v_sec, sec_list) { /* Only adjust loadable section's address. */ - if (!s->loadable || s->seg == NULL) + if (!s->loadable) continue; /* Apply global LMA adjustment. */ - if (ecp->change_addr != 0) + if (ecp->change_addr != 0 && s->seg != NULL) s->lma += ecp->change_addr; if (!s->pseudo) { @@ -135,7 +135,10 @@ adjust_addr(struct elfcopy *ecp) */ TAILQ_FOREACH(s, &ecp->v_sec, sec_list) { - /* Only adjust loadable section's LMA. */ + /* + * Only loadable section that's inside a segment can have + * LMA adjusted. + */ if (!s->loadable || s->seg == NULL) continue; @@ -173,7 +176,7 @@ adjust_addr(struct elfcopy *ecp) if (lma % s->align != 0) errx(EXIT_FAILURE, "The load address %#jx for " "section %s is not aligned to %ju", - (uintmax_t) lma, s->name, s->align); + (uintmax_t) lma, s->name, (uintmax_t) s->align); if (lma < s->lma) { /* Move section to lower address. */ @@ -214,7 +217,8 @@ adjust_addr(struct elfcopy *ecp) continue; errx(EXIT_FAILURE, "The extent of segment containing " "section %s overlaps with segment(%#jx,%#jx)", - s->name, seg->addr, seg->addr + seg->msz); + s->name, (uintmax_t) seg->addr, + (uintmax_t) (seg->addr + seg->msz)); } /* @@ -485,7 +489,7 @@ copy_phdr(struct elfcopy *ecp) ophdr.p_filesz = seg->fsz; ophdr.p_memsz = seg->msz; if (!gelf_update_phdr(ecp->eout, i, &ophdr)) - err(EXIT_FAILURE, "gelf_update_phdr failed :%s", + errx(EXIT_FAILURE, "gelf_update_phdr failed: %s", elf_errmsg(-1)); i++; diff --git a/contrib/elftoolchain/elfcopy/symbols.c b/contrib/elftoolchain/elfcopy/symbols.c index 05bcd7a..4423ca2 100644 --- a/contrib/elftoolchain/elfcopy/symbols.c +++ b/contrib/elftoolchain/elfcopy/symbols.c @@ -25,6 +25,7 @@ */ #include <sys/param.h> +#include <assert.h> #include <err.h> #include <fnmatch.h> #include <stdio.h> @@ -33,7 +34,13 @@ #include "elfcopy.h" -ELFTC_VCSID("$Id: symbols.c 3222 2015-05-24 23:47:23Z kaiwang27 $"); +ELFTC_VCSID("$Id: symbols.c 3376 2016-01-26 18:41:39Z emaste $"); + +/* Backwards compatibility for systems with older ELF definitions. */ +#ifndef STB_GNU_UNIQUE +#define STB_GNU_UNIQUE 10 +#endif + /* Symbol table buffer structure. */ struct symbuf { @@ -79,7 +86,6 @@ static int lookup_exact_string(hash_head *hash, const char *buf, static int generate_symbols(struct elfcopy *ecp); static void mark_reloc_symbols(struct elfcopy *ecp, size_t sc); static void mark_section_group_symbols(struct elfcopy *ecp, size_t sc); -static int match_wildcard(const char *name, const char *pattern); uint32_t str_hash(const char *s); /* Convenient bit vector operation macros. */ @@ -102,7 +108,8 @@ static int is_global_symbol(unsigned char st_info) { - if (GELF_ST_BIND(st_info) == STB_GLOBAL) + if (GELF_ST_BIND(st_info) == STB_GLOBAL || + GELF_ST_BIND(st_info) == STB_GNU_UNIQUE) return (1); return (0); @@ -190,12 +197,6 @@ is_remove_symbol(struct elfcopy *ecp, size_t sc, int i, GElf_Sym *s, SHN_UNDEF, /* st_shndx */ }; - if (lookup_symop_list(ecp, name, SYMOP_KEEP) != NULL) - return (0); - - if (lookup_symop_list(ecp, name, SYMOP_STRIP) != NULL) - return (1); - /* * Keep the first symbol if it is the special reserved symbol. * XXX Should we generate one if it's missing? @@ -208,15 +209,34 @@ is_remove_symbol(struct elfcopy *ecp, size_t sc, int i, GElf_Sym *s, ecp->secndx[s->st_shndx] == 0) return (1); + /* Keep the symbol if specified by command line option -K. */ + if (lookup_symop_list(ecp, name, SYMOP_KEEP) != NULL) + return (0); + if (ecp->strip == STRIP_ALL) return (1); + /* Mark symbols used in relocation. */ if (ecp->v_rel == NULL) mark_reloc_symbols(ecp, sc); + /* Mark symbols used in section groups. */ if (ecp->v_grp == NULL) mark_section_group_symbols(ecp, sc); + /* + * Strip the symbol if specified by command line option -N, + * unless it's used in relocation. + */ + if (lookup_symop_list(ecp, name, SYMOP_STRIP) != NULL) { + if (BIT_ISSET(ecp->v_rel, i)) { + warnx("not stripping symbol `%s' because it is named" + " in a relocation", name); + return (0); + } + return (1); + } + if (is_needed_symbol(ecp, i, s)) return (0); @@ -565,8 +585,11 @@ generate_symbols(struct elfcopy *ecp) * If the symbol is a STT_SECTION symbol, mark the section * it points to. */ - if (GELF_ST_TYPE(sym.st_info) == STT_SECTION) + if (GELF_ST_TYPE(sym.st_info) == STT_SECTION && + sym.st_shndx < SHN_LORESERVE) { + assert(ecp->secndx[sym.st_shndx] < (uint64_t)ecp->nos); BIT_SET(ecp->v_secsym, ecp->secndx[sym.st_shndx]); + } } /* @@ -861,6 +884,8 @@ add_to_symtab(struct elfcopy *ecp, const char *name, uint64_t st_value, * It handles buffer growing, st_name calculating and st_shndx * updating for symbols with non-special section index. */ +#define _ST_NAME_EMPTY_l 0 +#define _ST_NAME_EMPTY_g -1 #define _ADDSYM(B, SZ) do { \ if (sy_buf->B##SZ == NULL) { \ sy_buf->B##SZ = malloc(sy_buf->B##cap * \ @@ -920,7 +945,8 @@ add_to_symtab(struct elfcopy *ecp, const char *name, uint64_t st_value, st_buf->B.sz += strlen(name) + 1; \ } \ } else \ - sy_buf->B##SZ[sy_buf->n##B##s].st_name = 0; \ + sy_buf->B##SZ[sy_buf->n##B##s].st_name = \ + (Elf##SZ##_Word)_ST_NAME_EMPTY_##B; \ sy_buf->n##B##s++; \ } while (0) @@ -945,6 +971,8 @@ add_to_symtab(struct elfcopy *ecp, const char *name, uint64_t st_value, ecp->strtab->sz = st_buf->l.sz + st_buf->g.sz; #undef _ADDSYM +#undef _ST_NAME_EMPTY_l +#undef _ST_NAME_EMPTY_g } void @@ -961,10 +989,17 @@ finalize_external_symtab(struct elfcopy *ecp) sy_buf = ecp->symtab->buf; st_buf = ecp->strtab->buf; for (i = 0; (size_t) i < sy_buf->ngs; i++) { - if (ecp->oec == ELFCLASS32) - sy_buf->g32[i].st_name += st_buf->l.sz; - else - sy_buf->g64[i].st_name += st_buf->l.sz; + if (ecp->oec == ELFCLASS32) { + if (sy_buf->g32[i].st_name == (Elf32_Word)-1) + sy_buf->g32[i].st_name = 0; + else + sy_buf->g32[i].st_name += st_buf->l.sz; + } else { + if (sy_buf->g64[i].st_name == (Elf64_Word)-1) + sy_buf->g64[i].st_name = 0; + else + sy_buf->g64[i].st_name += st_buf->l.sz; + } } } @@ -1105,46 +1140,47 @@ add_to_symop_list(struct elfcopy *ecp, const char *name, const char *newname, { struct symop *s; - if ((s = lookup_symop_list(ecp, name, ~0U)) == NULL) { - if ((s = calloc(1, sizeof(*s))) == NULL) - errx(EXIT_FAILURE, "not enough memory"); - s->name = name; - if (op == SYMOP_REDEF) - s->newname = newname; - } + assert (name != NULL); + STAILQ_FOREACH(s, &ecp->v_symop, symop_list) + if (!strcmp(name, s->name)) + goto found; - s->op |= op; + if ((s = calloc(1, sizeof(*s))) == NULL) + errx(EXIT_FAILURE, "not enough memory"); STAILQ_INSERT_TAIL(&ecp->v_symop, s, symop_list); -} - -static int -match_wildcard(const char *name, const char *pattern) -{ - int reverse, match; - - reverse = 0; - if (*pattern == '!') { - reverse = 1; - pattern++; - } - - match = 0; - if (!fnmatch(pattern, name, 0)) - match = 1; - - return (reverse ? !match : match); + s->name = name; +found: + if (op == SYMOP_REDEF) + s->newname = newname; + s->op |= op; } struct symop * lookup_symop_list(struct elfcopy *ecp, const char *name, unsigned int op) { - struct symop *s; + struct symop *s, *ret; + const char *pattern; STAILQ_FOREACH(s, &ecp->v_symop, symop_list) { - if (name == NULL || !strcmp(name, s->name) || - ((ecp->flags & WILDCARD) && match_wildcard(name, s->name))) - if ((s->op & op) != 0) + if ((s->op & op) == 0) + continue; + if (name == NULL || !strcmp(name, s->name)) return (s); + if ((ecp->flags & WILDCARD) == 0) + continue; + + /* Handle wildcards. */ + pattern = s->name; + if (pattern[0] == '!') { + /* Negative match. */ + pattern++; + ret = NULL; + } else { + /* Regular wildcard match. */ + ret = s; + } + if (!fnmatch(pattern, name, 0)) + return (ret); } return (NULL); diff --git a/contrib/elftoolchain/elfdump/elfdump.c b/contrib/elftoolchain/elfdump/elfdump.c index baf99ee..334d285 100644 --- a/contrib/elftoolchain/elfdump/elfdump.c +++ b/contrib/elftoolchain/elfdump/elfdump.c @@ -50,7 +50,7 @@ #include "_elftc.h" -ELFTC_VCSID("$Id: elfdump.c 3250 2015-10-06 13:56:15Z emaste $"); +ELFTC_VCSID("$Id: elfdump.c 3391 2016-02-05 19:43:01Z emaste $"); #if defined(ELFTC_NEED_ELF_NOTE_DEFINITION) #include "native-elf-format.h" @@ -155,77 +155,82 @@ le32dec(const void *pp) static const char * d_tags(uint64_t tag) { + static char unknown_buf[64]; + switch (tag) { - case 0: return "DT_NULL"; - case 1: return "DT_NEEDED"; - case 2: return "DT_PLTRELSZ"; - case 3: return "DT_PLTGOT"; - case 4: return "DT_HASH"; - case 5: return "DT_STRTAB"; - case 6: return "DT_SYMTAB"; - case 7: return "DT_RELA"; - case 8: return "DT_RELASZ"; - case 9: return "DT_RELAENT"; - case 10: return "DT_STRSZ"; - case 11: return "DT_SYMENT"; - case 12: return "DT_INIT"; - case 13: return "DT_FINI"; - case 14: return "DT_SONAME"; - case 15: return "DT_RPATH"; - case 16: return "DT_SYMBOLIC"; - case 17: return "DT_REL"; - case 18: return "DT_RELSZ"; - case 19: return "DT_RELENT"; - case 20: return "DT_PLTREL"; - case 21: return "DT_DEBUG"; - case 22: return "DT_TEXTREL"; - case 23: return "DT_JMPREL"; - case 24: return "DT_BIND_NOW"; - case 25: return "DT_INIT_ARRAY"; - case 26: return "DT_FINI_ARRAY"; - case 27: return "DT_INIT_ARRAYSZ"; - case 28: return "DT_FINI_ARRAYSZ"; - case 29: return "DT_RUNPATH"; - case 30: return "DT_FLAGS"; - case 32: return "DT_PREINIT_ARRAY"; /* XXX: DT_ENCODING */ - case 33: return "DT_PREINIT_ARRAYSZ"; + case DT_NULL: return "DT_NULL"; + case DT_NEEDED: return "DT_NEEDED"; + case DT_PLTRELSZ: return "DT_PLTRELSZ"; + case DT_PLTGOT: return "DT_PLTGOT"; + case DT_HASH: return "DT_HASH"; + case DT_STRTAB: return "DT_STRTAB"; + case DT_SYMTAB: return "DT_SYMTAB"; + case DT_RELA: return "DT_RELA"; + case DT_RELASZ: return "DT_RELASZ"; + case DT_RELAENT: return "DT_RELAENT"; + case DT_STRSZ: return "DT_STRSZ"; + case DT_SYMENT: return "DT_SYMENT"; + case DT_INIT: return "DT_INIT"; + case DT_FINI: return "DT_FINI"; + case DT_SONAME: return "DT_SONAME"; + case DT_RPATH: return "DT_RPATH"; + case DT_SYMBOLIC: return "DT_SYMBOLIC"; + case DT_REL: return "DT_REL"; + case DT_RELSZ: return "DT_RELSZ"; + case DT_RELENT: return "DT_RELENT"; + case DT_PLTREL: return "DT_PLTREL"; + case DT_DEBUG: return "DT_DEBUG"; + case DT_TEXTREL: return "DT_TEXTREL"; + case DT_JMPREL: return "DT_JMPREL"; + case DT_BIND_NOW: return "DT_BIND_NOW"; + case DT_INIT_ARRAY: return "DT_INIT_ARRAY"; + case DT_FINI_ARRAY: return "DT_FINI_ARRAY"; + case DT_INIT_ARRAYSZ: return "DT_INIT_ARRAYSZ"; + case DT_FINI_ARRAYSZ: return "DT_FINI_ARRAYSZ"; + case DT_RUNPATH: return "DT_RUNPATH"; + case DT_FLAGS: return "DT_FLAGS"; + case DT_PREINIT_ARRAY: return "DT_PREINIT_ARRAY"; /* XXX DT_ENCODING */ + case DT_PREINIT_ARRAYSZ:return "DT_PREINIT_ARRAYSZ"; /* 0x6000000D - 0x6ffff000 operating system-specific semantics */ - case 0x6ffffdf5: return "DT_GNU_PRELINKED"; - case 0x6ffffdf6: return "DT_GNU_CONFLICTSZ"; - case 0x6ffffdf7: return "DT_GNU_LIBLISTSZ"; - case 0x6ffffdf8: return "DT_SUNW_CHECKSUM"; - case 0x6ffffdf9: return "DT_PLTPADSZ"; - case 0x6ffffdfa: return "DT_MOVEENT"; - case 0x6ffffdfb: return "DT_MOVESZ"; - case 0x6ffffdfc: return "DT_FEATURE"; - case 0x6ffffdfd: return "DT_POSFLAG_1"; - case 0x6ffffdfe: return "DT_SYMINSZ"; - case 0x6ffffdff: return "DT_SYMINENT (DT_VALRNGHI)"; - case 0x6ffffe00: return "DT_ADDRRNGLO"; - case 0x6ffffef5: return "DT_GNU_HASH"; - case 0x6ffffef8: return "DT_GNU_CONFLICT"; - case 0x6ffffef9: return "DT_GNU_LIBLIST"; - case 0x6ffffefa: return "DT_CONFIG"; - case 0x6ffffefb: return "DT_DEPAUDIT"; - case 0x6ffffefc: return "DT_AUDIT"; - case 0x6ffffefd: return "DT_PLTPAD"; - case 0x6ffffefe: return "DT_MOVETAB"; - case 0x6ffffeff: return "DT_SYMINFO (DT_ADDRRNGHI)"; - case 0x6ffffff9: return "DT_RELACOUNT"; - case 0x6ffffffa: return "DT_RELCOUNT"; - case 0x6ffffffb: return "DT_FLAGS_1"; - case 0x6ffffffc: return "DT_VERDEF"; - case 0x6ffffffd: return "DT_VERDEFNUM"; - case 0x6ffffffe: return "DT_VERNEED"; - case 0x6fffffff: return "DT_VERNEEDNUM"; - case 0x6ffffff0: return "DT_GNU_VERSYM"; + case 0x6ffffdf5: return "DT_GNU_PRELINKED"; + case 0x6ffffdf6: return "DT_GNU_CONFLICTSZ"; + case 0x6ffffdf7: return "DT_GNU_LIBLISTSZ"; + case 0x6ffffdf8: return "DT_SUNW_CHECKSUM"; + case DT_PLTPADSZ: return "DT_PLTPADSZ"; + case DT_MOVEENT: return "DT_MOVEENT"; + case DT_MOVESZ: return "DT_MOVESZ"; + case 0x6ffffdfc: return "DT_FEATURE"; + case DT_POSFLAG_1: return "DT_POSFLAG_1"; + case DT_SYMINSZ: return "DT_SYMINSZ"; + case DT_SYMINENT: return "DT_SYMINENT (DT_VALRNGHI)"; + case DT_ADDRRNGLO: return "DT_ADDRRNGLO"; + case DT_GNU_HASH: return "DT_GNU_HASH"; + case 0x6ffffef8: return "DT_GNU_CONFLICT"; + case 0x6ffffef9: return "DT_GNU_LIBLIST"; + case 0x6ffffefa: return "DT_CONFIG"; + case 0x6ffffefb: return "DT_DEPAUDIT"; + case 0x6ffffefc: return "DT_AUDIT"; + case 0x6ffffefd: return "DT_PLTPAD"; + case 0x6ffffefe: return "DT_MOVETAB"; + case DT_SYMINFO: return "DT_SYMINFO (DT_ADDRRNGHI)"; + case DT_RELACOUNT: return "DT_RELACOUNT"; + case DT_RELCOUNT: return "DT_RELCOUNT"; + case DT_FLAGS_1: return "DT_FLAGS_1"; + case DT_VERDEF: return "DT_VERDEF"; + case DT_VERDEFNUM: return "DT_VERDEFNUM"; + case DT_VERNEED: return "DT_VERNEED"; + case DT_VERNEEDNUM: return "DT_VERNEEDNUM"; + case 0x6ffffff0: return "DT_GNU_VERSYM"; /* 0x70000000 - 0x7fffffff processor-specific semantics */ - case 0x70000000: return "DT_IA_64_PLT_RESERVE"; - case 0x7ffffffd: return "DT_SUNW_AUXILIARY"; - case 0x7ffffffe: return "DT_SUNW_USED"; - case 0x7fffffff: return "DT_SUNW_FILTER"; - default: return "ERROR: TAG NOT DEFINED"; + case 0x70000000: return "DT_IA_64_PLT_RESERVE"; + case 0x7ffffffd: return "DT_SUNW_AUXILIARY"; + case 0x7ffffffe: return "DT_SUNW_USED"; + case 0x7fffffff: return "DT_SUNW_FILTER"; } + + snprintf(unknown_buf, sizeof(unknown_buf), + "<unknown: %#llx>", (unsigned long long)tag); + return (unknown_buf); } static const char * @@ -313,42 +318,79 @@ sh_name(struct elfdump *ed, int ndx) /* http://www.sco.com/developers/gabi/latest/ch4.sheader.html#sh_type */ static const char * -sh_types(u_int64_t sht) { - switch (sht) { - case 0: return "SHT_NULL"; - case 1: return "SHT_PROGBITS"; - case 2: return "SHT_SYMTAB"; - case 3: return "SHT_STRTAB"; - case 4: return "SHT_RELA"; - case 5: return "SHT_HASH"; - case 6: return "SHT_DYNAMIC"; - case 7: return "SHT_NOTE"; - case 8: return "SHT_NOBITS"; - case 9: return "SHT_REL"; - case 10: return "SHT_SHLIB"; - case 11: return "SHT_DYNSYM"; - case 14: return "SHT_INIT_ARRAY"; - case 15: return "SHT_FINI_ARRAY"; - case 16: return "SHT_PREINIT_ARRAY"; - case 17: return "SHT_GROUP"; - case 18: return "SHT_SYMTAB_SHNDX"; - /* 0x60000000 - 0x6fffffff operating system-specific semantics */ - case 0x6ffffff0: return "XXX:VERSYM"; - case 0x6ffffff4: return "SHT_SUNW_dof"; - case 0x6ffffff6: return "SHT_GNU_HASH"; - case 0x6ffffff7: return "SHT_GNU_LIBLIST"; - case 0x6ffffffc: return "XXX:VERDEF"; - case 0x6ffffffd: return "SHT_SUNW(GNU)_verdef"; - case 0x6ffffffe: return "SHT_SUNW(GNU)_verneed"; - case 0x6fffffff: return "SHT_SUNW(GNU)_versym"; - /* 0x70000000 - 0x7fffffff processor-specific semantics */ - case 0x70000000: return "SHT_IA_64_EXT"; - case 0x70000001: return "SHT_IA_64_UNWIND"; - case 0x7ffffffd: return "XXX:AUXILIARY"; - case 0x7fffffff: return "XXX:FILTER"; - /* 0x80000000 - 0xffffffff application programs */ - default: return "ERROR: SHT NOT DEFINED"; +sh_types(uint64_t mach, uint64_t sht) { + static char unknown_buf[64]; + + if (sht < 0x60000000) { + switch (sht) { + case SHT_NULL: return "SHT_NULL"; + case SHT_PROGBITS: return "SHT_PROGBITS"; + case SHT_SYMTAB: return "SHT_SYMTAB"; + case SHT_STRTAB: return "SHT_STRTAB"; + case SHT_RELA: return "SHT_RELA"; + case SHT_HASH: return "SHT_HASH"; + case SHT_DYNAMIC: return "SHT_DYNAMIC"; + case SHT_NOTE: return "SHT_NOTE"; + case SHT_NOBITS: return "SHT_NOBITS"; + case SHT_REL: return "SHT_REL"; + case SHT_SHLIB: return "SHT_SHLIB"; + case SHT_DYNSYM: return "SHT_DYNSYM"; + case SHT_INIT_ARRAY: return "SHT_INIT_ARRAY"; + case SHT_FINI_ARRAY: return "SHT_FINI_ARRAY"; + case SHT_PREINIT_ARRAY: return "SHT_PREINIT_ARRAY"; + case SHT_GROUP: return "SHT_GROUP"; + case SHT_SYMTAB_SHNDX: return "SHT_SYMTAB_SHNDX"; + } + } else if (sht < 0x70000000) { + /* 0x60000000-0x6fffffff operating system-specific semantics */ + switch (sht) { + case 0x6ffffff0: return "XXX:VERSYM"; + case SHT_SUNW_dof: return "SHT_SUNW_dof"; + case SHT_GNU_HASH: return "SHT_GNU_HASH"; + case 0x6ffffff7: return "SHT_GNU_LIBLIST"; + case 0x6ffffffc: return "XXX:VERDEF"; + case SHT_SUNW_verdef: return "SHT_SUNW(GNU)_verdef"; + case SHT_SUNW_verneed: return "SHT_SUNW(GNU)_verneed"; + case SHT_SUNW_versym: return "SHT_SUNW(GNU)_versym"; + } + } else if (sht < 0x80000000) { + /* 0x70000000 - 0x7fffffff processor-specific semantics */ + switch (mach) { + case EM_ARM: + switch (sht) { + case SHT_ARM_EXIDX: return "SHT_ARM_EXIDX"; + case SHT_ARM_PREEMPTMAP: return "SHT_ARM_PREEMPTMAP"; + case SHT_ARM_ATTRIBUTES: return "SHT_ARM_ATTRIBUTES"; + case SHT_ARM_DEBUGOVERLAY: + return "SHT_ARM_DEBUGOVERLAY"; + case SHT_ARM_OVERLAYSECTION: + return "SHT_ARM_OVERLAYSECTION"; + } + break; + case EM_IA_64: + switch (sht) { + case 0x70000000: return "SHT_IA_64_EXT"; + case 0x70000001: return "SHT_IA_64_UNWIND"; + } + break; + case EM_MIPS: + switch (sht) { + case SHT_MIPS_REGINFO: return "SHT_MIPS_REGINFO"; + case SHT_MIPS_OPTIONS: return "SHT_MIPS_OPTIONS"; + case SHT_MIPS_ABIFLAGS: return "SHT_MIPS_ABIFLAGS"; + } + break; + } + switch (sht) { + case 0x7ffffffd: return "XXX:AUXILIARY"; + case 0x7fffffff: return "XXX:FILTER"; + } } + /* 0x80000000 - 0xffffffff application programs */ + + snprintf(unknown_buf, sizeof(unknown_buf), + "<unknown: %#llx>", (unsigned long long)sht); + return (unknown_buf); } /* @@ -390,22 +432,87 @@ sh_flags(uint64_t shf) return (flg); } -static const char *st_types[] = { - "STT_NOTYPE", "STT_OBJECT", "STT_FUNC", "STT_SECTION", "STT_FILE", - "STT_COMMON", "STT_TLS" -}; +static const char * +st_type(unsigned int mach, unsigned int type) +{ + static char s_type[32]; + + switch (type) { + case STT_NOTYPE: return "STT_NOTYPE"; + case STT_OBJECT: return "STT_OBJECT"; + case STT_FUNC: return "STT_FUNC"; + case STT_SECTION: return "STT_SECTION"; + case STT_FILE: return "STT_FILE"; + case STT_COMMON: return "STT_COMMON"; + case STT_TLS: return "STT_TLS"; + case 13: + if (mach == EM_SPARCV9) + return "STT_SPARC_REGISTER"; + break; + } + snprintf(s_type, sizeof(s_type), "<unknown: %#x>", type); + return (s_type); +} -static const char *st_types_S[] = { - "NOTY", "OBJT", "FUNC", "SECT", "FILE" -}; +static const char * +st_type_S(unsigned int type) +{ + static char s_type[32]; -static const char *st_bindings[] = { - "STB_LOCAL", "STB_GLOBAL", "STB_WEAK" -}; + switch (type) { + case STT_NOTYPE: return "NOTY"; + case STT_OBJECT: return "OBJT"; + case STT_FUNC: return "FUNC"; + case STT_SECTION: return "SECT"; + case STT_FILE: return "FILE"; + } + snprintf(s_type, sizeof(s_type), "<unknown: %#x>", type); + return (s_type); +} -static const char *st_bindings_S[] = { - "LOCL", "GLOB", "WEAK" -}; +static const char * +st_bindings(unsigned int sbind) +{ + static char s_sbind[32]; + + switch (sbind) { + case STB_LOCAL: return "STB_LOCAL"; + case STB_GLOBAL: return "STB_GLOBAL"; + case STB_WEAK: return "STB_WEAK"; + case STB_GNU_UNIQUE: return "STB_GNU_UNIQUE"; + default: + if (sbind >= STB_LOOS && sbind <= STB_HIOS) + return "OS"; + else if (sbind >= STB_LOPROC && sbind <= STB_HIPROC) + return "PROC"; + else + snprintf(s_sbind, sizeof(s_sbind), "<unknown: %#x>", + sbind); + return (s_sbind); + } +} + +static const char * +st_bindings_S(unsigned int sbind) +{ + static char s_sbind[32]; + + switch (sbind) { + case STB_LOCAL: return "LOCL"; + case STB_GLOBAL: return "GLOB"; + case STB_WEAK: return "WEAK"; + case STB_GNU_UNIQUE: return "UNIQ"; + default: + if (sbind >= STB_LOOS && sbind <= STB_HIOS) + return "OS"; + else if (sbind >= STB_LOPROC && sbind <= STB_HIPROC) + return "PROC"; + else + snprintf(s_sbind, sizeof(s_sbind), "<%#x>", + sbind); + return (s_sbind); + } +} static unsigned char st_others[] = { 'D', 'I', 'H', 'P' @@ -426,7 +533,7 @@ r_type(unsigned int mach, unsigned int type) case 4: return "R_386_PLT32"; case 5: return "R_386_COPY"; case 6: return "R_386_GLOB_DAT"; - case 7: return "R_386_JMP_SLOT"; + case 7: return "R_386_JUMP_SLOT"; case 8: return "R_386_RELATIVE"; case 9: return "R_386_GOTOFF"; case 10: return "R_386_GOTPC"; @@ -769,7 +876,7 @@ r_type(unsigned int mach, unsigned int type) case 4: return "R_X86_64_PLT32"; case 5: return "R_X86_64_COPY"; case 6: return "R_X86_64_GLOB_DAT"; - case 7: return "R_X86_64_JMP_SLOT"; + case 7: return "R_X86_64_JUMP_SLOT"; case 8: return "R_X86_64_RELATIVE"; case 9: return "R_X86_64_GOTPCREL"; case 10: return "R_X86_64_32"; @@ -1608,7 +1715,8 @@ elf_print_shdr(struct elfdump *ed) else PRT(" sh_flags: 0\n"); PRT(" sh_size: %#-14jx", (uintmax_t)s->sz); - PRT(" sh_type: [ %s ]\n", sh_types(s->type)); + PRT(" sh_type: [ %s ]\n", + sh_types(ed->ehdr.e_machine, s->type)); PRT(" sh_offset: %#-14jx", (uintmax_t)s->off); PRT(" sh_entsize: %#jx\n", (uintmax_t)s->entsize); PRT(" sh_link: %-14u", s->link); @@ -1618,7 +1726,8 @@ elf_print_shdr(struct elfdump *ed) PRT("\n"); PRT("entry: %ju\n", (uintmax_t)i); PRT("\tsh_name: %s\n", s->name); - PRT("\tsh_type: %s\n", sh_types(s->type)); + PRT("\tsh_type: %s\n", + sh_types(ed->ehdr.e_machine, s->type)); PRT("\tsh_flags: %s\n", sh_flags(s->flags)); PRT("\tsh_addr: %#jx\n", (uintmax_t)s->addr); PRT("\tsh_offset: %ju\n", (uintmax_t)s->off); @@ -1745,8 +1854,8 @@ elf_print_symtab(struct elfdump *ed, int i) PRT("0x%8.8jx ", (uintmax_t)sym.st_size); else PRT("0x%12.12jx ", (uintmax_t)sym.st_size); - PRT("%s ", st_types_S[GELF_ST_TYPE(sym.st_info)]); - PRT("%s ", st_bindings_S[GELF_ST_BIND(sym.st_info)]); + PRT("%s ", st_type_S(GELF_ST_TYPE(sym.st_info))); + PRT("%s ", st_bindings_S(GELF_ST_BIND(sym.st_info))); PRT("%c ", st_others[sym.st_other]); PRT("%3u ", (vs == NULL ? 0 : vs[j])); PRT("%-11.11s ", sh_name(ed, sym.st_shndx)); @@ -1757,8 +1866,9 @@ elf_print_symtab(struct elfdump *ed, int i) PRT("\tst_value: %#jx\n", (uintmax_t)sym.st_value); PRT("\tst_size: %ju\n", (uintmax_t)sym.st_size); PRT("\tst_info: %s %s\n", - st_types[GELF_ST_TYPE(sym.st_info)], - st_bindings[GELF_ST_BIND(sym.st_info)]); + st_type(ed->ehdr.e_machine, + GELF_ST_TYPE(sym.st_info)), + st_bindings(GELF_ST_BIND(sym.st_info))); PRT("\tst_shndx: %ju\n", (uintmax_t)sym.st_shndx); } } @@ -2173,11 +2283,14 @@ elf_print_got_section(struct elfdump *ed, struct section *s) for(i = 0; i < len; i++) { PRT("[%5.5d] ", i); if (ed->ec == ELFCLASS32) { - PRT("%-8.8jx ", s->addr + i * s->entsize); + PRT("%-8.8jx ", + (uintmax_t) (s->addr + i * s->entsize)); PRT("%-8.8x ", *((uint32_t *)dst.d_buf + i)); } else { - PRT("%-16.16jx ", s->addr + i * s->entsize); - PRT("%-16.16jx ", *((uint64_t *)dst.d_buf + i)); + PRT("%-16.16jx ", + (uintmax_t) (s->addr + i * s->entsize)); + PRT("%-16.16jx ", + (uintmax_t) *((uint64_t *)dst.d_buf + i)); } PRT("%-18s ", r_type(ed->ehdr.e_machine, GELF_R_TYPE(got[i].u_r.rel.r_info))); @@ -2198,7 +2311,8 @@ elf_print_got_section(struct elfdump *ed, struct section *s) if (ed->ec == ELFCLASS32) PRT("\t%#x\n", *((uint32_t *)dst.d_buf + i)); else - PRT("\t%#jx\n", *((uint64_t *)dst.d_buf + i)); + PRT("\t%#jx\n", + (uintmax_t) *((uint64_t *)dst.d_buf + i)); } } } diff --git a/contrib/elftoolchain/elfdump/os.NetBSD.mk b/contrib/elftoolchain/elfdump/os.NetBSD.mk new file mode 100644 index 0000000..ae214e3 --- /dev/null +++ b/contrib/elftoolchain/elfdump/os.NetBSD.mk @@ -0,0 +1,2 @@ +# TODO(#511): Revert after the source tree is -Wconversion clean. +WARNS=5 diff --git a/contrib/elftoolchain/libdwarf/_libdwarf.h b/contrib/elftoolchain/libdwarf/_libdwarf.h index e6eb496..6658d2d 100644 --- a/contrib/elftoolchain/libdwarf/_libdwarf.h +++ b/contrib/elftoolchain/libdwarf/_libdwarf.h @@ -24,7 +24,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $Id: _libdwarf.h 3164 2015-02-19 01:20:12Z kaiwang27 $ + * $Id: _libdwarf.h 3298 2016-01-09 15:43:31Z jkoshy $ */ #ifndef __LIBDWARF_H_ @@ -92,8 +92,8 @@ extern struct _libdwarf_globals _libdwarf; typedef struct _Dwarf_CU *Dwarf_CU; struct _Dwarf_AttrDef { - uint64_t ad_attrib; /* DW_AT_XXX */ - uint64_t ad_form; /* DW_FORM_XXX */ + Dwarf_Half ad_attrib; /* DW_AT_XXX */ + Dwarf_Half ad_form; /* DW_FORM_XXX */ uint64_t ad_offset; /* Offset in abbrev section. */ STAILQ_ENTRY(_Dwarf_AttrDef) ad_next; /* Next attribute define. */ }; @@ -102,8 +102,8 @@ struct _Dwarf_Attribute { Dwarf_Die at_die; /* Ptr to containing DIE. */ Dwarf_Die at_refdie; /* Ptr to reference DIE. */ uint64_t at_offset; /* Offset in info section. */ - uint64_t at_attrib; /* DW_AT_XXX */ - uint64_t at_form; /* DW_FORM_XXX */ + Dwarf_Half at_attrib; /* DW_AT_XXX */ + Dwarf_Half at_form; /* DW_FORM_XXX */ int at_indirect; /* Has indirect form. */ union { uint64_t u64; /* Unsigned value. */ diff --git a/contrib/elftoolchain/libdwarf/dwarf.3 b/contrib/elftoolchain/libdwarf/dwarf.3 index dbb4179..863bee6 100644 --- a/contrib/elftoolchain/libdwarf/dwarf.3 +++ b/contrib/elftoolchain/libdwarf/dwarf.3 @@ -21,7 +21,7 @@ .\" out of the use of this software, even if advised of the possibility of .\" such damage. .\" -.\" $Id: dwarf.3 3195 2015-05-12 17:22:19Z emaste $ +.\" $Id: dwarf.3 3295 2016-01-08 22:08:10Z jkoshy $ .\" .Dd December 21, 2014 .Os @@ -110,9 +110,7 @@ A pointer to an error handling function. .It Vt Dwarf_Line A descriptor for a source line. .It Vt Dwarf_Off -An unsigned file offset, corresponding to an -.Vt off_t -type supported by the underlying operating system. +An unsigned file offset. .It Vt Dwarf_P_Expr A descriptor for a location expression. .It Vt Dwarf_Ptr diff --git a/contrib/elftoolchain/libdwarf/dwarf_str.c b/contrib/elftoolchain/libdwarf/dwarf_str.c index 71a7f75..c402f21 100644 --- a/contrib/elftoolchain/libdwarf/dwarf_str.c +++ b/contrib/elftoolchain/libdwarf/dwarf_str.c @@ -26,7 +26,7 @@ #include "_libdwarf.h" -ELFTC_VCSID("$Id: dwarf_str.c 2075 2011-10-27 03:47:28Z jkoshy $"); +ELFTC_VCSID("$Id: dwarf_str.c 3295 2016-01-08 22:08:10Z jkoshy $"); int dwarf_get_str(Dwarf_Debug dbg, Dwarf_Off offset, char **string, @@ -34,7 +34,7 @@ dwarf_get_str(Dwarf_Debug dbg, Dwarf_Off offset, char **string, { Dwarf_Section *ds; - if (dbg == NULL || offset < 0 || string == NULL || ret_strlen == NULL) { + if (dbg == NULL || string == NULL || ret_strlen == NULL) { DWARF_SET_ERROR(dbg, error, DW_DLE_ARGUMENT); return (DW_DLV_ERROR); } @@ -45,12 +45,12 @@ dwarf_get_str(Dwarf_Debug dbg, Dwarf_Off offset, char **string, return (DW_DLV_NO_ENTRY); } - if ((Dwarf_Unsigned) offset > ds->ds_size) { + if (offset > ds->ds_size) { DWARF_SET_ERROR(dbg, error, DW_DLE_ARGUMENT); return (DW_DLV_ERROR); } - if ((Dwarf_Unsigned) offset == ds->ds_size) { + if (offset == ds->ds_size) { DWARF_SET_ERROR(dbg, error, DW_DLE_NO_ENTRY); return (DW_DLV_NO_ENTRY); } diff --git a/contrib/elftoolchain/libdwarf/libdwarf.h b/contrib/elftoolchain/libdwarf/libdwarf.h index 0cb8b1a..02f0ce5 100644 --- a/contrib/elftoolchain/libdwarf/libdwarf.h +++ b/contrib/elftoolchain/libdwarf/libdwarf.h @@ -24,7 +24,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $Id: libdwarf.h 3174 2015-03-27 17:13:41Z emaste $ + * $Id: libdwarf.h 3295 2016-01-08 22:08:10Z jkoshy $ */ #ifndef _LIBDWARF_H_ @@ -33,7 +33,7 @@ #include <libelf.h> typedef int Dwarf_Bool; -typedef off_t Dwarf_Off; +typedef uint64_t Dwarf_Off; typedef uint64_t Dwarf_Unsigned; typedef uint16_t Dwarf_Half; typedef uint8_t Dwarf_Small; diff --git a/contrib/elftoolchain/libdwarf/libdwarf_rw.c b/contrib/elftoolchain/libdwarf/libdwarf_rw.c index 8cb4551..f0286d5 100644 --- a/contrib/elftoolchain/libdwarf/libdwarf_rw.c +++ b/contrib/elftoolchain/libdwarf/libdwarf_rw.c @@ -27,7 +27,7 @@ #include "_libdwarf.h" -ELFTC_VCSID("$Id: libdwarf_rw.c 2952 2013-06-26 19:09:40Z kaiwang27 $"); +ELFTC_VCSID("$Id: libdwarf_rw.c 3286 2015-12-31 16:45:46Z emaste $"); uint64_t _dwarf_read_lsb(uint8_t *data, uint64_t *offsetp, int bytes_to_read) @@ -42,10 +42,13 @@ _dwarf_read_lsb(uint8_t *data, uint64_t *offsetp, int bytes_to_read) case 8: ret |= ((uint64_t) src[4]) << 32 | ((uint64_t) src[5]) << 40; ret |= ((uint64_t) src[6]) << 48 | ((uint64_t) src[7]) << 56; + /* FALLTHROUGH */ case 4: ret |= ((uint64_t) src[2]) << 16 | ((uint64_t) src[3]) << 24; + /* FALLTHROUGH */ case 2: ret |= ((uint64_t) src[1]) << 8; + /* FALLTHROUGH */ case 1: ret |= src[0]; break; @@ -71,10 +74,13 @@ _dwarf_decode_lsb(uint8_t **data, int bytes_to_read) case 8: ret |= ((uint64_t) src[4]) << 32 | ((uint64_t) src[5]) << 40; ret |= ((uint64_t) src[6]) << 48 | ((uint64_t) src[7]) << 56; + /* FALLTHROUGH */ case 4: ret |= ((uint64_t) src[2]) << 16 | ((uint64_t) src[3]) << 24; + /* FALLTHROUGH */ case 2: ret |= ((uint64_t) src[1]) << 8; + /* FALLTHROUGH */ case 1: ret |= src[0]; break; @@ -171,11 +177,14 @@ _dwarf_write_lsb(uint8_t *data, uint64_t *offsetp, uint64_t value, dst[6] = (value >> 48) & 0xff; dst[5] = (value >> 40) & 0xff; dst[4] = (value >> 32) & 0xff; + /* FALLTHROUGH */ case 4: dst[3] = (value >> 24) & 0xff; dst[2] = (value >> 16) & 0xff; + /* FALLTHROUGH */ case 2: dst[1] = (value >> 8) & 0xff; + /* FALLTHROUGH */ case 1: dst[0] = value & 0xff; break; @@ -222,13 +231,16 @@ _dwarf_write_msb(uint8_t *data, uint64_t *offsetp, uint64_t value, dst[5] = (value >> 16) & 0xff; dst[4] = (value >> 24) & 0xff; value >>= 32; + /* FALLTHROUGH */ case 4: dst[3] = value & 0xff; dst[2] = (value >> 8) & 0xff; value >>= 16; + /* FALLTHROUGH */ case 2: dst[1] = value & 0xff; value >>= 8; + /* FALLTHROUGH */ case 1: dst[0] = value & 0xff; break; diff --git a/contrib/elftoolchain/libdwarf/os.NetBSD.mk b/contrib/elftoolchain/libdwarf/os.NetBSD.mk new file mode 100644 index 0000000..ae214e3 --- /dev/null +++ b/contrib/elftoolchain/libdwarf/os.NetBSD.mk @@ -0,0 +1,2 @@ +# TODO(#511): Revert after the source tree is -Wconversion clean. +WARNS=5 diff --git a/contrib/elftoolchain/libelf/_libelf_config.h b/contrib/elftoolchain/libelf/_libelf_config.h index 602eb89..1bcf333 100644 --- a/contrib/elftoolchain/libelf/_libelf_config.h +++ b/contrib/elftoolchain/libelf/_libelf_config.h @@ -23,7 +23,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $Id: _libelf_config.h 3168 2015-02-24 19:17:47Z emaste $ + * $Id: _libelf_config.h 3396 2016-02-10 21:50:05Z emaste $ */ #if defined(__APPLE__) || defined(__DragonFly__) diff --git a/contrib/elftoolchain/libelftc/Makefile b/contrib/elftoolchain/libelftc/Makefile index a5fc297..4af496b 100644 --- a/contrib/elftoolchain/libelftc/Makefile +++ b/contrib/elftoolchain/libelftc/Makefile @@ -1,4 +1,4 @@ -# $Id: Makefile 2859 2013-01-05 09:21:54Z jkoshy $ +# $Id: Makefile 3292 2016-01-06 21:46:32Z jkoshy $ TOP= ${.CURDIR}/.. @@ -45,16 +45,7 @@ MLINKS= elftc_bfd_find_target.3 elftc_bfd_target_byteorder.3 \ elftc_string_table_create.3 elftc_string_table_destroy.3 \ elftc_string_table_create.3 elftc_string_table_image.3 \ elftc_string_table_create.3 elftc_string_table_insert.3 \ - elftc_string_table_create.3 elftc_string_table_lookup.3 \ - elftc_symbol_table_create.3 elftc_symbol_table_create_nested.3 \ - elftc_symbol_table_create.3 elftc_symbol_table_delete_name.3 \ - elftc_symbol_table_create.3 elftc_symbol_table_delete_entry.3 \ - elftc_symbol_table_create.3 elftc_symbol_table_destroy.3 \ - elftc_symbol_table_create.3 elftc_symbol_table_from_section.3 \ - elftc_symbol_table_create.3 elftc_symbol_table_insert.3 \ - elftc_symbol_table_create.3 elftc_symbol_table_iterate.3 \ - elftc_symbol_table_create.3 elftc_symbol_table_lookup.3 \ - elftc_symbol_table_create.3 elftc_symbol_table_to_image.3 + elftc_string_table_create.3 elftc_string_table_lookup.3 .if !make(clean) && !make(clobber) .BEGIN: .SILENT diff --git a/contrib/elftoolchain/libelftc/elftc_bfd_find_target.3 b/contrib/elftoolchain/libelftc/elftc_bfd_find_target.3 index 851ae31..20dea3c 100644 --- a/contrib/elftoolchain/libelftc/elftc_bfd_find_target.3 +++ b/contrib/elftoolchain/libelftc/elftc_bfd_find_target.3 @@ -21,7 +21,7 @@ .\" out of the use of this software, even if advised of the possibility of .\" such damage. .\" -.\" $Id: elftc_bfd_find_target.3 2251 2011-11-30 16:50:06Z jkoshy $ +.\" $Id: elftc_bfd_find_target.3 3348 2016-01-18 14:18:50Z emaste $ .\" .Dd November 30, 2011 .Os @@ -58,9 +58,11 @@ Binary object descriptors encapsulate properties of an object format such as its file representation, ELF class, and byte endianness. .Pp Known descriptor names and their properties include: -.Bl -column -offset "XXXX" ".Li elf32-x86-64-freebsd" "Object format" "Byte Order" "ELF Class" -.It Em Name Ta Em "Object Format" Ta Em "Byte Order" Ta Em "ELF Class" +.Bl -column -offset "XXXX" ".Li elf32-x86-64-freebsd" "Object format" "Byte Order" "Bit Width" +.It Em Name Ta Em "Object Format" Ta Em "Byte Order" Ta Em "Bit Width" .It Li binary Ta Binary Ta - Ta - +.It Li efi-app-ia32 Ta PE Ta LSB Ta 32 +.It Li efi-app-x86_64 Ta PE Ta LSB Ta 64 .It Li elf32-avr Ta ELF Ta LSB Ta 32 .It Li elf32-big Ta ELF Ta MSB Ta 32 .It Li elf32-bigarm Ta ELF Ta MSB Ta 32 @@ -101,6 +103,8 @@ Known descriptor names and their properties include: .It Li elf64-x86-64 Ta ELF Ta LSB Ta 64 .It Li elf64-x86-64-freebsd Ta ELF Ta LSB Ta 64 .It Li ihex Ta IHEX Ta - Ta - +.It Li pei-i386 Ta PE Ta LSB Ta 32 +.It Li pei-x86-64 Ta PE Ta LSB Ta 64 .It Li srec Ta SREC Ta - Ta - .It Li symbolsrec Ta SREC Ta - Ta - .El diff --git a/contrib/elftoolchain/libelftc/elftc_copyfile.c b/contrib/elftoolchain/libelftc/elftc_copyfile.c index 7df1678..dac9c14 100644 --- a/contrib/elftoolchain/libelftc/elftc_copyfile.c +++ b/contrib/elftoolchain/libelftc/elftc_copyfile.c @@ -37,7 +37,7 @@ #include <sys/mman.h> #endif -ELFTC_VCSID("$Id: elftc_copyfile.c 2981 2014-02-01 02:41:13Z jkoshy $"); +ELFTC_VCSID("$Id: elftc_copyfile.c 3297 2016-01-09 15:26:34Z jkoshy $"); /* * Copy the contents referenced by 'ifd' to 'ofd'. Returns 0 on @@ -47,11 +47,11 @@ ELFTC_VCSID("$Id: elftc_copyfile.c 2981 2014-02-01 02:41:13Z jkoshy $"); int elftc_copyfile(int ifd, int ofd) { + size_t file_size, n; int buf_mmapped; struct stat sb; char *b, *buf; - ssize_t nw; - size_t n; + ssize_t nr, nw; /* Determine the input file's size. */ if (fstat(ifd, &sb) < 0) @@ -63,12 +63,13 @@ elftc_copyfile(int ifd, int ofd) buf = NULL; buf_mmapped = 0; + file_size = (size_t) sb.st_size; #if ELFTC_HAVE_MMAP /* * Prefer mmap() if it is available. */ - buf = mmap(NULL, sb.st_size, PROT_READ, MAP_SHARED, ifd, (off_t) 0); + buf = mmap(NULL, file_size, PROT_READ, MAP_SHARED, ifd, (off_t) 0); if (buf != MAP_FAILED) buf_mmapped = 1; else @@ -80,24 +81,27 @@ elftc_copyfile(int ifd, int ofd) * failed, allocate a buffer, and read in input data. */ if (buf_mmapped == false) { - if ((buf = malloc(sb.st_size)) == NULL) - return (-1); - if (read(ifd, buf, sb.st_size) != sb.st_size) { - free(buf); + if ((buf = malloc(file_size)) == NULL) return (-1); + b = buf; + for (n = file_size; n > 0; n -= (size_t) nr, b += nr) { + if ((nr = read(ifd, b, n)) < 0) { + free(buf); + return (-1); + } } } /* * Write data to the output file descriptor. */ - for (n = sb.st_size, b = buf; n > 0; n -= nw, b += nw) + for (n = file_size, b = buf; n > 0; n -= (size_t) nw, b += nw) if ((nw = write(ofd, b, n)) <= 0) break; /* Release the input buffer. */ #if ELFTC_HAVE_MMAP - if (buf_mmapped && munmap(buf, sb.st_size) < 0) + if (buf_mmapped && munmap(buf, file_size) < 0) return (-1); #endif diff --git a/contrib/elftoolchain/libelftc/elftc_demangle.c b/contrib/elftoolchain/libelftc/elftc_demangle.c index ff30955..945f777 100644 --- a/contrib/elftoolchain/libelftc/elftc_demangle.c +++ b/contrib/elftoolchain/libelftc/elftc_demangle.c @@ -33,10 +33,10 @@ #include "_libelftc.h" -ELFTC_VCSID("$Id: elftc_demangle.c 3174 2015-03-27 17:13:41Z emaste $"); +ELFTC_VCSID("$Id: elftc_demangle.c 3296 2016-01-09 14:17:28Z jkoshy $"); -static int -is_mangled(const char *s, int style) +static unsigned int +is_mangled(const char *s, unsigned int style) { switch (style) { @@ -58,7 +58,7 @@ is_mangled(const char *s, int style) } static char * -demangle(const char *s, int style, int rc) +demangle(const char *s, unsigned int style, unsigned int rc) { (void) rc; /* XXX */ @@ -76,7 +76,7 @@ int elftc_demangle(const char *mangledname, char *buffer, size_t bufsize, unsigned int flags) { - int style, rc; + unsigned int style, rc; char *rlt; style = flags & 0xFFFF; diff --git a/contrib/elftoolchain/libelftc/elftc_symbol_table_create.3 b/contrib/elftoolchain/libelftc/elftc_symbol_table_create.3 deleted file mode 100644 index 76f90e9..0000000 --- a/contrib/elftoolchain/libelftc/elftc_symbol_table_create.3 +++ /dev/null @@ -1,529 +0,0 @@ -.\" Copyright (c) 2012 Joseph Koshy. All rights reserved. -.\" -.\" Redistribution and use in source and binary forms, with or without -.\" modification, are permitted provided that the following conditions -.\" are met: -.\" 1. Redistributions of source code must retain the above copyright -.\" notice, this list of conditions and the following disclaimer. -.\" 2. Redistributions in binary form must reproduce the above copyright -.\" notice, this list of conditions and the following disclaimer in the -.\" documentation and/or other materials provided with the distribution. -.\" -.\" This software is provided by Joseph Koshy ``as is'' and -.\" any express or implied warranties, including, but not limited to, the -.\" implied warranties of merchantability and fitness for a particular purpose -.\" are disclaimed. in no event shall Joseph Koshy be liable -.\" for any direct, indirect, incidental, special, exemplary, or consequential -.\" damages (including, but not limited to, procurement of substitute goods -.\" or services; loss of use, data, or profits; or business interruption) -.\" however caused and on any theory of liability, whether in contract, strict -.\" liability, or tort (including negligence or otherwise) arising in any way -.\" out of the use of this software, even if advised of the possibility of -.\" such damage. -.\" -.\" $Id: elftc_symbol_table_create.3 3182 2015-04-10 16:08:10Z emaste $ -.\" -.Dd December 29, 2012 -.Os -.Dt ELFTC_SYMBOL_TABLE_CREATE 3 -.Sh NAME -.Nm elftc_elf_symbol_table_from_section , -.Nm elftc_symbol_table_count , -.Nm elftc_symbol_table_create , -.Nm elftc_symbol_table_create_nested , -.Nm elftc_symbol_table_delete_name , -.Nm elftc_symbol_table_delete_entry , -.Nm elftc_symbol_table_destroy , -.Nm elftc_symbol_table_insert , -.Nm elftc_symbol_table_iterate , -.Nm elftc_symbol_table_lookup , -.Nm elftc_symbol_table_lookup_value , -.Nm elftc_symbol_table_replace , -.Nm elftc_symbol_table_sort , -.Nm elftc_symbol_table_step -.Nd symbol table management routines -.Sh SYNOPSIS -.In libelftc.h -.Bd -literal -typedef struct _Elftc_Symbol_Table Elftc_Symbol_Table; - -typedef struct _Elftc_Symbol { - ... library private fields ... - const char *sym_name; - uintptr_t sym_value; -} Elftc_Symbol; -.Ed -.Ft size_t -.Fn elftc_symbol_table_count "Elftc_Symbol_Table *table" -.Ft "Elftc_Symbol_Table *" -.Fo elftc_symbol_table_create -.Fa "size_t entrysize" -.Fa "int sizehint" -.Fc -.Ft "Elftc_Symbol_Table *" -.Fo elftc_symbol_table_create_nested -.Fa "Elftc_Symbol_Table *table" -.Fa "int sizehint" -.Fc -.Ft int -.Fo elftc_symbol_table_delete_name -.Fa "Elftc_Symbol_Table *table" -.Fa "const char *name" -.Fc -.Ft int -.Fo elftc_symbol_table_delete_entry -.Fa "Elftc_Symbol_Table *table" -.Fa "Elftc_Symbol *entry" -.Fc -.Ft int -.Fn elftc_symbol_table_destroy "Elftc_Symbol_Table *table" -.Ft "Elftc_Symbol *entry" -.Fo elftc_symbol_table_insert -.Fa "Elftc_Symbol_Table *table" -.Fa "const char *symbolname" -.Fa "int *status" -.Fc -.Ft int -.Fo elftc_symbol_table_iterate -.Fa "Elftc_Symbol_Table *table" -.Fa "int (*iterfn)(Elftc_Symbol *entry, void *cookie)" -.Fa "void *cookie" -.Fc -.Ft "Elftc_Symbol *" -.Fo elftc_symbol_table_lookup -.Fa "Elftc_Symbol_Table *table" -.Fa "const char *symbolname" -.Fc -.Ft "Elftc_Elf_Symbol *" -.Fo elftc_symbol_table_lookup_value -.Fa "Elftc_Symbol_Table *table" -.Fa "uintptr_t value" -.Fa "int searchflags" -.Fc -.Ft int -.Fo elftc_symbol_table_replace -.Fa "Elftc_Symbol_Table *table" -.Fa "Elftc_Symbol *sym1" -.Fa "Elftc_Symbol *sym2" -.Fc -.Ft int -.Fo elftc_symbol_table_sort -.Fa "Elftc_Symbol_Table *table" -.Fa "int (*cmpfn)(Elftc_Symbol *s1, Elftc_Symbol *s2)" -.Fc -.Ft "Elftc_Symbol *" -.Fo elftc_symbol_table_step -.Fa "Elftc_Symbol_Table *table" -.Fa "Elftc_Symbol *cursym" -.Fa "int direction" -.Fc -.Bd -literal -typedef struct _Elftc_Elf_Symbol { - ... library private fields ... - const char *sym_name; - Gelf_Sym sym_elf; -} Elftc_Elf_Symbol; -.Ed -.Ft "Elftc_Symbol_Table *" -.Fo elftc_elf_symbol_table_from_section -.Fa "Elf_Scn *symscn" -.Fa "Elf_Scn *strscn" -.Fc -.Sh DESCRIPTION -This manual page documents convenience routines for handling symbol -tables. -Two flavors of symbol tables are supported: -.Bl -bullet -compact -.It -.Dq Regular -symbol tables supporting insertion, deletion and lookup of entries by -name or by value, sorting of entries, and stepping through entries in -the table's current traversal order. -.It -.Dq ELF-centric -symbol tables support additional operations for conversions to and -from the symbol table format understood by -.Lb libelf . -.El -The default traversal order for a symbol table is the order in which -entries were inserted into it. -This traversal order may be changed using function -.Fn elftc_symbol_table_sort . -.Ss Operations on Regular Symbol Tables -Regular symbol tables use symbols that are subtypes of -.Vt Elftc_Symbol , -as described in the section -.Sx "Structure of a Symbol Table Entry" -below. -.Pp -Function -.Fn elftc_symbol_table_count -returns the number of entries currently in the symbol table. -.Pp -Function -.Fn elftc_symbol_table_create -creates a new, empty symbol table. -The argument -.Ar entrysize -specifies the size of each symbol table entry, as described -in the section -.Sx "Structure of a Symbol Table Entry" -below. -The argument -.Ar sizehint -specifies the expected number of symbol table entries. -If -.Ar sizehint -is zero, an implementation-defined default will be used. -.Pp -Function -.Fn elftc_symbol_table_create_nested -creates a symbol table whose search scope nests inside that of a -parent symbol table. -The argument -.Ar parent -specifies the parent symbol table to nest under. -The argument -.Ar sizehint -specifies the expected number of symbol table entries. -If -.Ar sizehint -is zero, an implementation-defined default will be used instead. -.Pp -The function -.Fn elftc_symbol_table_delete_name -removes the symbol entry named by the argument -.Ar name -from the symbol table specified by argument -.Ar table , -according to the rules described in section -.Sx "Symbol Search Rules" . -.Pp -The function -.Fn elftc_symbol_table_delete_entry -removes the symbol table entry specified by argument -.Ar entry -from the symbol table specified by argument -.Ar table . -.Pp -Function -.Fn elftc_symbol_table_destroy -is used to destroy a symbol table and free up its internal -resources. -.Pp -The function -.Fn elftc_symbol_table_insert -inserts a symbol entry for the name specified by argument -.Ar symbolname -into the symbol table specified by argument -.Ar table , -returning a pointer to a symbol table entry. -The argument -.Ar status -should point to a location that will be updated with one of -the following values: -.Bl -tag -width indent -compact -offset indent -.It Dv ELFTC_INSERT_ERROR -An error occurred during insertion of the symbol. -.It Dv ELFTC_INSERT_EXISTING -The name in argument -.Ar symbolname -was already in the symbol table, and a pointer to the existing -symbol table entry is being returned. -.It Dv ELFTC_INSERT_NEW -A new symbol table entry was allocated for the symbol name -in -.Ar symbolname . -The application will need to initialize the application-specific -fields of the symbol table entry. -.El -Insertion obeys the scoping rules described in section -.Sx "Symbol Search Rules" . -.Pp -The function -.Fn elftc_symbol_table_iterate -iterates over the symbol table specifed by argument -.Ar table , -applying the function pointed to by argument -.Ar iterfn -to each symbol table entry. -The return value from the function -.Ar iterfn -controls progress of the iteration: -.Bl -tag -width indent -compact -offset indent -.It Dv ELFTC_ITERATE_ABORT -Terminates the iteration. -.It Dv ELFTC_ITERATE_CONTINUE -Iteration will continue on to the next element in the symbol table. -.El -Argument -.Ar cookie -will be passed to each invocation of -.Ar iterfn , -and may be used to track persistent state. -The ordering of symbol table entries presented to function -.Ar iterfn -is not defined. -The behavior of the iteration is undefined if -.Ar iterfn -adds or deletes symbol entries from a symbol table that currently -being iterated through. -.Pp -Function -.Fn elftc_symbol_table_lookup -returns the symbol entry corresponding to the name of the symbol -in argument -.Ar symbolname . -.Pp -Function -.Fn elftc_symbol_table_lookup_value -returns the symbol entry that has a -.Va sym_value -field that is closest to the value specified in argument -.Ar value . -The argument -.Ar table -should point to a symbol table, that has been sorted -by a prior call to -.Fn elftc_symbol_table_sort . -The argument -.Ar searchflags -can be a combination of the following flags: -.Bl -tag -width indent -compact -offset indent -.It Dv ELFTC_SEARCH_FORWARD -Find the symbol entry with the next higher value in its -.Va sym_value -field. -.It Dv ELFTC_SEARCH_BACKWARD -Find the symbol entry with next lower value in its -.Va sym_value -field. -.El -If both -.Dv ELFTC_SEARCH_FORWARD -and -.Dv ELFTC_SEARCH_BACKWARD -are specified, then this function will return the symbol that is -closest to the argument -.Ar value . -.Pp -Function -.Fn elftc_symbol_table_replace -moves the symbol table entry pointed to by argument -.Ar sym2 -into the traversal position for the entry pointed to by -.Ar sym1 , -and implicitly deletes the entry pointed to by argument -.Ar sym1 . -Argument -.Ar table -should point to a valid symbol table. -.Pp -Function -.Fn elftc_symbol_table_sort -is used to define an ordering of symbol entries in a symbol -table. -This ordering will be associated with the symbol table till the next -call to function -.Fn elftc_symbol_table_insert , -.Fn elftc_symbol_table_delete_name -or -.Fn elftc_symbol_table_delete_entry . -The argument -.Ar cmpfn -should point to a function that compares two symbol entries pointed -to by -.Ar s1 -and -.Ar s2 -and returns -1, 0, or 1, depending whether -.Ar s1 -is less, equal to, or greater than -.Ar s2 -respectively. -.Pp -Function -.Fn elftc_symbol_table_step -is used to step to the next symbol in a sorted symbol table. -Argument -.Ar table -should point to a symbol table. -The argument -.Ar cursym -specifies the current symbol. -The argument -.Ar direction -specifies the direction to step: -.Bl -tag -width indent -compact -offset ident -.It Dv ELFTC_STEP_NEXT -Return the symbol which follows the argument -.Ar cursym -in the current traversal order. -If argument -.Ar cursym -is NULL, return the first symbol in the current -traversal order. -.It Dv ELFTC_STEP_PREVIOUS -Return the symbol which precedes the argument -.Ar cursym -in the current traversal order. -If argument -.Ar cursym -is NULL, return the last symbol in the current -traversal order. -.El -.Ss Operations on ELF-centric symbol tables -ELF-centric symbol tables use symbols that are subtypes of -.Vt Elftc_Elf_Symbol , -as described in the section -.Sx "Structure of a Symbol Table Entry" -below. -.Pp -In addition to the operations on regular symbol tables listed above, -these symbol tables may be used with the following additional -functions. -.Pp -The function -.Fn elftc_elf_symbol_table_from_section -builds a symbol table from the contents of an ELF section. -The argument -.Ar symscn -should reference an ELF section of type -.Dv SHT_SYMTAB -or -.Dv SHT_DYNSYM . -The argument -.Ar strscn -should reference an ELF section of type -.Dv SHT_STRTAB -containing the string table associated wit section -.Ar symscn . -.Ss Structure of a Symbol Table Entry -The symbol tables managed by -.Lb libelftc -are collections of symbol table entries. -Each entry should be a subtype of one of the -.Vt Elftc_Symbol -or -.Vt Elftc_Elf_Symbol -types. -In other words, each entry should have an -.Vt Elftc_Symbol -or -.Vt Elftc_Elf_Symbol -structure as its first member, before any application specific -fields. -For example: -.Bd -literal -offset indent -struct _MySymbol { - Elftc_Symbol sym_base; - ... other application-specific fields ... -}; -.Ed -.Pp -The size of the combined entry is indicated to the library -at the time of creating a new symbol table. -Applications may then cast the returned pointers from these -routines to the appropriate type: -.Bd -literal -offset indent -struct _MySymbol *mysym; - -mysym = (struct _MySymbol *) elftc_symbol_table_lookup(table, - name); -.Ed -.Pp -The -.Vt Elftc_Symbol -type has two public fields: -.Bl -tag -width ".Va sym_value" -compact -offset indent -.It Va sym_name -Points to a NUL-terminated string containing the symbol's name. -The application should not change the value of this field. -.It Va sym_value -The value associated with this symbol. -This field is entirely under the application's control. -.El -.Pp -The -.Vt Elftc_Elf_Symbol -type has two public fields: -.Bl -tag -width ".Va sym_value" -compact -offset indent -.It Va sym_name -Points to a NUL-terminated string containing the symbol's name. -The application should not change the value of this field. -.It Va sym_elf -A structure of type -.Vt Gelf_Sym -containing ELF symbol information. -This field is entirely under the application's control. -.El -.Ss Symbol Search Rules -During lookups, symbols are looked up first in the symbol table passed in -to the -.Fn elftc_symbol_table_lookup -function. -If the specified symbol is not found, and if the symbol table has a -parent, then the search continues recursively up the chain of parent -symbol tables till either a matching symbol is found or till there are -no more parent symbol tables to search in. -.Pp -Insertions and deletion only work on the specified symbol table and -do not recurse into parent symbol tables. -.Ss Memory Management -The -.Lb libelftc -manages its memory allocations. -Applications should not free the pointers returned by the -API documented in this manual page. -.Sh RETURN VALUES -Function -.Fn elftc_symbol_table_count -returns a count of the number of symbol table entries as an unsigned -value. -.Pp -Functions -.Fn elftc_symbol_table_create , -.Fn elftc_symbol_table_create_nested -and -.Fn elftc_symbol_table_from_section -return a pointer to an opaque structure of type -.Vt Elftc_Symbol_Table -on success, or return NULL in case of an error. -.Pp -Functions -.Fn elftc_symbol_table_delete_name , -.Fn elftc_symbol_table_delete_name -.Fn elftc_symbol_table_destroy , -.Fn elftc_symbol_table_replace -and -.Fn elftc_symbol_table_sort -return a non-zero value on success, or return zero in case of an error. -.Pp -Functions -.Fn elftc_symbol_table_insert , -.Fn elftc_symbol_table_lookup -and -.Fn elftc_symbol_table_lookup_value -return a pointer to a structure that is a subtype of -.Vt Elftc_Symbol -on success, or return NULL in case of an error. -.Pp -The function -.Fn elftc_symbol_table_step -return a pointer to a structure that is a subtype of -.Vt Elftc_Symbol -on success. -The function returns NULL if there are no more elements in the -specified traversal direction. -.Pp -The function -.Fn elftc_symbol_table_iterate -returns -.Dv ELFTC_ITERATE_SUCCESS -if the symbol table was successfully traversed, or -.Dv ELFTC_ITERATE_ABORT -in case the iteration function aborted the traversal. -.Sh SEE ALSO -.Xr dwarf 3 , -.Xr elf 3 , -.Xr elftc 3 diff --git a/contrib/elftoolchain/libelftc/libelftc.h b/contrib/elftoolchain/libelftc/libelftc.h index 062db31..e3adaf2 100644 --- a/contrib/elftoolchain/libelftc/libelftc.h +++ b/contrib/elftoolchain/libelftc/libelftc.h @@ -24,7 +24,7 @@ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * $FreeBSD: users/kaiwang27/elftc/libelftc.h 392 2009-05-31 19:17:46Z kaiwang27 $ - * $Id: libelftc.h 3174 2015-03-27 17:13:41Z emaste $ + * $Id: libelftc.h 3309 2016-01-10 09:10:51Z kaiwang27 $ */ #ifndef _LIBELFTC_H_ @@ -46,7 +46,9 @@ typedef enum { ETF_ELF, ETF_BINARY, ETF_SREC, - ETF_IHEX + ETF_IHEX, + ETF_PE, + ETF_EFI, } Elftc_Bfd_Target_Flavor; /* diff --git a/contrib/elftoolchain/libelftc/libelftc_bfdtarget.c b/contrib/elftoolchain/libelftc/libelftc_bfdtarget.c index 00ba225..88f3220 100644 --- a/contrib/elftoolchain/libelftc/libelftc_bfdtarget.c +++ b/contrib/elftoolchain/libelftc/libelftc_bfdtarget.c @@ -30,7 +30,7 @@ #include "_libelftc.h" -ELFTC_VCSID("$Id: libelftc_bfdtarget.c 3174 2015-03-27 17:13:41Z emaste $"); +ELFTC_VCSID("$Id: libelftc_bfdtarget.c 3309 2016-01-10 09:10:51Z kaiwang27 $"); struct _Elftc_Bfd_Target _libelftc_targets[] = { @@ -375,6 +375,30 @@ struct _Elftc_Bfd_Target _libelftc_targets[] = { }, { + .bt_name = "efi-app-ia32", + .bt_type = ETF_EFI, + .bt_machine = EM_386, + }, + + { + .bt_name = "efi-app-x86_64", + .bt_type = ETF_EFI, + .bt_machine = EM_X86_64, + }, + + { + .bt_name = "pei-i386", + .bt_type = ETF_PE, + .bt_machine = EM_386, + }, + + { + .bt_name = "pei-x86-64", + .bt_type = ETF_PE, + .bt_machine = EM_X86_64, + }, + + { .bt_name = NULL, .bt_type = ETF_NONE, }, diff --git a/contrib/elftoolchain/libelftc/libelftc_dem_gnu3.c b/contrib/elftoolchain/libelftc/libelftc_dem_gnu3.c index e8fd78f..f5ca7b3 100644 --- a/contrib/elftoolchain/libelftc/libelftc_dem_gnu3.c +++ b/contrib/elftoolchain/libelftc/libelftc_dem_gnu3.c @@ -36,7 +36,7 @@ #include "_libelftc.h" -ELFTC_VCSID("$Id: libelftc_dem_gnu3.c 3212 2015-05-17 13:40:55Z kaiwang27 $"); +ELFTC_VCSID("$Id: libelftc_dem_gnu3.c 3291 2016-01-04 02:36:38Z emaste $"); /** * @file cpp_demangle.c @@ -1262,11 +1262,13 @@ cpp_demangle_read_encoding(struct cpp_demangle_data *ddata) if (!cpp_demangle_push_str(ddata, "non-transaction clone for ", 26)) return (0); + break; case 't': default: if (!cpp_demangle_push_str(ddata, "transaction clone for ", 22)) return (0); + break; } ++ddata->cur; return (cpp_demangle_read_encoding(ddata)); @@ -1895,35 +1897,35 @@ cpp_demangle_read_subst(struct cpp_demangle_data *ddata) case SIMPLE_HASH('S', 'd'): /* std::basic_iostream<char, std::char_traits<char> > */ - if (!cpp_demangle_push_str(ddata, "std::iostream", 19)) + if (!cpp_demangle_push_str(ddata, "std::basic_iostream", 19)) return (0); - ddata->last_sname = "iostream"; + ddata->last_sname = "basic_iostream"; ddata->cur += 2; if (*ddata->cur == 'I') return (cpp_demangle_read_subst_stdtmpl(ddata, - "std::iostream", 19)); + "std::basic_iostream", 19)); return (1); case SIMPLE_HASH('S', 'i'): /* std::basic_istream<char, std::char_traits<char> > */ - if (!cpp_demangle_push_str(ddata, "std::istream", 18)) + if (!cpp_demangle_push_str(ddata, "std::basic_istream", 18)) return (0); - ddata->last_sname = "istream"; + ddata->last_sname = "basic_istream"; ddata->cur += 2; if (*ddata->cur == 'I') return (cpp_demangle_read_subst_stdtmpl(ddata, - "std::istream", 18)); + "std::basic_istream", 18)); return (1); case SIMPLE_HASH('S', 'o'): /* std::basic_ostream<char, std::char_traits<char> > */ - if (!cpp_demangle_push_str(ddata, "std::ostream", 18)) + if (!cpp_demangle_push_str(ddata, "std::basic_ostream", 18)) return (0); - ddata->last_sname = "istream"; + ddata->last_sname = "basic_ostream"; ddata->cur += 2; if (*ddata->cur == 'I') return (cpp_demangle_read_subst_stdtmpl(ddata, - "std::ostream", 18)); + "std::basic_ostream", 18)); return (1); case SIMPLE_HASH('S', 's'): diff --git a/contrib/elftoolchain/libelftc/make-toolchain-version b/contrib/elftoolchain/libelftc/make-toolchain-version index ac6155a..8891258 100755 --- a/contrib/elftoolchain/libelftc/make-toolchain-version +++ b/contrib/elftoolchain/libelftc/make-toolchain-version @@ -3,7 +3,7 @@ # This script generates a project-wide version identifier for use by # the `elftc_version()' API. # -# $Id: make-toolchain-version 2583 2012-09-14 09:49:25Z jkoshy $ +# $Id: make-toolchain-version 3299 2016-01-09 19:58:46Z jkoshy $ # # Defaults. @@ -64,7 +64,7 @@ done curdir=`pwd` cd ${top} || usage "ERROR: Cannot change directory to \"${top}\"." -if [ -d .svn ]; then # FreeBSD and SF.Net sources. +if [ -d .svn -o -d ../.svn ]; then # FreeBSD and SF.Net sources. versionstring=" svn:"$(svnversion) elif [ -d CVS ]; then # NetBSD. versionstring=" cvs:unknown" diff --git a/contrib/elftoolchain/libelftc/os.NetBSD.mk b/contrib/elftoolchain/libelftc/os.NetBSD.mk new file mode 100644 index 0000000..ae214e3 --- /dev/null +++ b/contrib/elftoolchain/libelftc/os.NetBSD.mk @@ -0,0 +1,2 @@ +# TODO(#511): Revert after the source tree is -Wconversion clean. +WARNS=5 diff --git a/contrib/elftoolchain/libpe/Makefile b/contrib/elftoolchain/libpe/Makefile new file mode 100644 index 0000000..d02fb50 --- /dev/null +++ b/contrib/elftoolchain/libpe/Makefile @@ -0,0 +1,32 @@ +# $Id: Makefile 3349 2016-01-18 21:09:16Z jkoshy $ + +TOP= ${.CURDIR}/.. + +LIB= pe + +SRCS= libpe_buffer.c \ + libpe_coff.c \ + libpe_dos.c \ + libpe_init.c \ + libpe_rich.c \ + libpe_section.c \ + libpe_utils.c \ + pe_buffer.c \ + pe_cntl.c \ + pe_coff.c \ + pe_dos.c \ + pe_flag.c \ + pe_init.c \ + pe_rich.c \ + pe_section.c \ + pe_symtab.c \ + pe_update.c + +INCS= libpe.h pe.h +INCSDIR= /usr/include + +SHLIB_MAJOR= 1 + +WARNS?= 6 + +.include "${TOP}/mk/elftoolchain.lib.mk" diff --git a/contrib/elftoolchain/libpe/_libpe.h b/contrib/elftoolchain/libpe/_libpe.h new file mode 100644 index 0000000..1a83a67 --- /dev/null +++ b/contrib/elftoolchain/libpe/_libpe.h @@ -0,0 +1,213 @@ +/*- + * Copyright (c) 2015 Kai Wang + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $Id: _libpe.h 3312 2016-01-10 09:23:51Z kaiwang27 $ + */ + +#ifndef __LIBPE_H_ +#define __LIBPE_H_ + +#include <sys/types.h> +#include <sys/queue.h> + +#include "libpe.h" + +#include "_elftc.h" + +typedef struct _PE_SecBuf { + PE_Buffer sb_pb; /* application buffer */ + PE_Scn *sb_ps; /* PE_Scn pointer */ + unsigned int sb_flags; /* buffer flags */ + STAILQ_ENTRY(_PE_SecBuf) sb_next; +} PE_SecBuf; + +struct _PE_Scn { + PE *ps_pe; /* PE descriptor */ + PE_SecHdr ps_sh; /* section header */ + unsigned int ps_ndx; /* 1-based section index */ + unsigned int ps_flags; /* section flags */ + unsigned int ps_falign; /* section file alignment */ + STAILQ_HEAD(, _PE_SecBuf) ps_b; /* buffer list */ + STAILQ_ENTRY(_PE_Scn) ps_next; +}; + +struct _PE { + int pe_fd; /* file descriptor */ + PE_Cmd pe_cmd; /* open mode */ + PE_Object pe_obj; /* PE32/PE32+/COFF */ + size_t pe_fsize; /* file size */ + unsigned int pe_flags; /* library flags */ + PE_DosHdr *pe_dh; /* MS-DOS header */ + char *pe_stub; /* MS-DOS stub */ + size_t pe_stub_ex; /* MS-DOS stub len (exclude hdr) */ + char *pe_stub_app; /* MS-DOS stub (app supplied) */ + size_t pe_stub_app_sz; /* MS-DOS stub len (app supplied) */ + PE_RichHdr *pe_rh; /* rich header */ + char *pe_rh_start; /* pointer to rich header */ + PE_CoffHdr *pe_ch; /* COFF header */ + PE_OptHdr *pe_oh; /* optional header */ + PE_DataDir *pe_dd; /* data directories */ + unsigned int pe_nscn; /* num. of sections */ + char *pe_symtab; /* COFF symbol table */ + size_t pe_symbtab_sz; /* size of symbol table */ + unsigned int pe_nsym; /* num. of symbols */ + unsigned int pe_rvamax; /* maximum RVA */ + STAILQ_HEAD(, _PE_Scn) pe_scn; /* section list */ +}; + +/* Library internal flags */ +#define LIBPE_F_API_MASK 0x000FFFU +#define LIBPE_F_SPECIAL_FILE 0x001000U +#define LIBPE_F_BAD_DOS_HEADER 0x002000U +#define LIBPE_F_BAD_PE_HEADER 0x004000U +#define LIBPE_F_BAD_COFF_HEADER 0x008000U +#define LIBPE_F_BAD_OPT_HEADER 0x010000U +#define LIBPE_F_BAD_SEC_HEADER 0x020000U +#define LIBPE_F_LOAD_DOS_STUB 0x040000U +#define LIBPE_F_FD_DONE 0x080000U +#define LIBPE_F_DIRTY_DOS_HEADER 0x100000U +#define LIBPE_F_DIRTY_COFF_HEADER 0x200000U +#define LIBPE_F_DIRTY_OPT_HEADER 0x400000U +#define LIBPE_F_DIRTY_SEC_HEADER 0x800000U + +/* Internal section flags */ +#define LIBPE_F_LOAD_SECTION 0x1000U +#define LIBPE_F_STRIP_SECTION 0x2000U + +/* Internal buffer flags */ +#define LIBPE_F_BUFFER_MALLOCED 0x1000U + +/* Library internal defines */ +#define PE_DOS_MAGIC 0x5a4dU +#define PE_RICH_TEXT "Rich" +#define PE_RICH_HIDDEN 0x536e6144U /* DanS */ +#define PE_SIGNATURE 0x4550U /* PE\0\0 */ +#define PE_COFF_OPT_SIZE_32 224 +#define PE_COFF_OPT_SIZE_32P 240 +#define PE_SYM_ENTRY_SIZE 18 + +/* Encode/Decode macros */ +#if defined(ELFTC_NEED_BYTEORDER_EXTENSIONS) +static __inline uint16_t +le16dec(const void *pp) +{ + unsigned char const *p = (unsigned char const *)pp; + + return ((p[1] << 8) | p[0]); +} + +static __inline uint32_t +le32dec(const void *pp) +{ + unsigned char const *p = (unsigned char const *)pp; + + return ((p[3] << 24) | (p[2] << 16) | (p[1] << 8) | p[0]); +} + +static __inline uint64_t +le64dec(const void *pp) +{ + unsigned char const *p = (unsigned char const *)pp; + + return (((uint64_t)le32dec(p + 4) << 32) | le32dec(p)); +} + +static __inline void +le16enc(void *pp, uint16_t u) +{ + unsigned char *p = (unsigned char *)pp; + + p[0] = u & 0xff; + p[1] = (u >> 8) & 0xff; +} + +static __inline void +le32enc(void *pp, uint32_t u) +{ + unsigned char *p = (unsigned char *)pp; + + p[0] = u & 0xff; + p[1] = (u >> 8) & 0xff; + p[2] = (u >> 16) & 0xff; + p[3] = (u >> 24) & 0xff; +} + +static __inline void +le64enc(void *pp, uint64_t u) +{ + unsigned char *p = (unsigned char *)pp; + + le32enc(p, (uint32_t)(u & 0xffffffffU)); + le32enc(p + 4, (uint32_t)(u >> 32)); +} +#endif /* ELFTC_NEED_BYTEORDER_EXTENSIONS */ + +#define PE_READ16(p,v) do { \ + (v) = le16dec((p)); \ + (p) += 2; \ +} while(0) + +#define PE_READ32(p,v) do { \ + (v) = le32dec((p)); \ + (p) += 4; \ +} while(0) + +#define PE_WRITE16(p,v) do { \ + le16enc((p), (v)); \ + (p) += 2; \ +} while(0) + +#define PE_WRITE32(p,v) do { \ + le32enc((p), (v)); \ + (p) += 4; \ +} while(0) + + +/* Internal function declarations */ +off_t libpe_align(PE *, off_t, size_t); +PE_SecBuf *libpe_alloc_buffer(PE_Scn *, size_t); +PE_Scn *libpe_alloc_scn(PE *); +int libpe_load_all_sections(PE *); +int libpe_load_section(PE *, PE_Scn *); +int libpe_open_object(PE *); +int libpe_pad(PE *, size_t); +int libpe_parse_msdos_header(PE *, char *); +int libpe_parse_coff_header(PE *, char *); +int libpe_parse_rich_header(PE *); +int libpe_parse_section_headers(PE *); +int libpe_read_msdos_stub(PE *); +void libpe_release_buffer(PE_SecBuf *); +void libpe_release_object(PE *); +void libpe_release_scn(PE_Scn *); +size_t libpe_resync_buffers(PE_Scn *); +int libpe_resync_sections(PE *, off_t); +int libpe_write_buffers(PE_Scn *); +off_t libpe_write_coff_header(PE *, off_t); +off_t libpe_write_msdos_stub(PE *, off_t); +off_t libpe_write_pe_header(PE *, off_t); +off_t libpe_write_sections(PE *, off_t); +off_t libpe_write_section_headers(PE *, off_t); + +#endif /* !__LIBPE_H_ */ diff --git a/contrib/elftoolchain/libpe/libpe.h b/contrib/elftoolchain/libpe/libpe.h new file mode 100644 index 0000000..3cec39a --- /dev/null +++ b/contrib/elftoolchain/libpe/libpe.h @@ -0,0 +1,121 @@ +/*- + * Copyright (c) 2015 Kai Wang + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $Id: libpe.h 3312 2016-01-10 09:23:51Z kaiwang27 $ + */ + +#ifndef _LIBPE_H_ +#define _LIBPE_H_ + +#include <sys/types.h> + +#include "pe.h" + +/* Library private data structures */ +typedef struct _PE PE; +typedef struct _PE_Scn PE_Scn; + +/* Section buffers */ +typedef struct PE_Buffer { + unsigned int pb_align; + off_t pb_off; + size_t pb_size; + void *pb_buf; +} PE_Buffer; + +/* Object types */ +typedef enum { + PE_O_UNKNOWN = 0, + PE_O_PE32, + PE_O_PE32P, + PE_O_COFF, +} PE_Object; + +/* Commands */ +typedef enum { + PE_C_NULL = 0, + PE_C_CLR, + PE_C_FDDONE, + PE_C_FDREAD, + PE_C_RDWR, + PE_C_READ, + PE_C_SET, + PE_C_WRITE, + PE_C_NUM +} PE_Cmd; + +/* Flags defined by the API. */ +#define PE_F_DIRTY 0x001U +#define PE_F_STRIP_DOS_STUB 0x002U +#define PE_F_STRIP_RICH_HEADER 0x004U +#define PE_F_STRIP_SYMTAB 0x008U +#define PE_F_STRIP_DEBUG 0x010U +#define PE_F_STRIP_SECTION 0x020U + +#ifdef __cplusplus +extern "C" { +#endif + +PE_CoffHdr *pe_coff_header(PE *); +int pe_cntl(PE *, PE_Cmd); +PE_DataDir *pe_data_dir(PE *); +void pe_finish(PE *); +int pe_flag(PE *, PE_Cmd, unsigned int); +int pe_flag_buffer(PE_Buffer *, PE_Cmd, unsigned int); +int pe_flag_coff_header(PE *, PE_Cmd, unsigned int); +int pe_flag_data_dir(PE *, PE_Cmd, unsigned int); +int pe_flag_dos_header(PE *, PE_Cmd, unsigned int); +int pe_flag_opt_header(PE *, PE_Cmd, unsigned int); +int pe_flag_section_header(PE_Scn *, PE_Cmd, unsigned int); +int pe_flag_scn(PE_Scn *, PE_Cmd, unsigned int); +PE_Buffer *pe_getbuffer(PE_Scn *, PE_Buffer *); +PE_Scn *pe_getscn(PE *, size_t); +PE *pe_init(int, PE_Cmd, PE_Object); +PE_Scn *pe_insertscn(PE *, size_t); +PE_DosHdr *pe_msdos_header(PE *); +char *pe_msdos_stub(PE *, size_t *); +size_t pe_ndxscn(PE_Scn *); +PE_Buffer *pe_newbuffer(PE_Scn *); +PE_Scn *pe_newscn(PE *); +PE_Scn *pe_nextscn(PE *, PE_Scn *); +PE_Object pe_object(PE *); +PE_OptHdr *pe_opt_header(PE *); +PE_RichHdr *pe_rich_header(PE *); +int pe_rich_header_validate(PE *); +PE_SecHdr *pe_section_header(PE_Scn *); +off_t pe_update(PE *); +int pe_update_coff_header(PE *, PE_CoffHdr *); +int pe_update_opt_header(PE *, PE_OptHdr *); +int pe_update_data_dir(PE *, PE_DataDir *); +int ps_update_msdos_header(PE *, PE_DosHdr *); +int ps_update_msdos_stub(PE *, char *, size_t); +int pe_update_section_header(PE_Scn *, PE_SecHdr *); +int pe_update_symtab(PE *, char *, size_t, unsigned int); + +#ifdef __cplusplus +} +#endif + +#endif /* !_LIBPE_H_ */ diff --git a/contrib/elftoolchain/libpe/libpe_buffer.c b/contrib/elftoolchain/libpe/libpe_buffer.c new file mode 100644 index 0000000..cc633dd --- /dev/null +++ b/contrib/elftoolchain/libpe/libpe_buffer.c @@ -0,0 +1,185 @@ +/*- + * Copyright (c) 2016 Kai Wang + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include <sys/param.h> +#include <assert.h> +#include <errno.h> +#include <stdlib.h> +#include <unistd.h> + +#include "_libpe.h" + +ELFTC_VCSID("$Id: libpe_buffer.c 3312 2016-01-10 09:23:51Z kaiwang27 $"); + +PE_SecBuf * +libpe_alloc_buffer(PE_Scn *ps, size_t sz) +{ + PE_SecBuf *sb; + + if ((sb = malloc(sizeof(PE_SecBuf))) == NULL) { + errno = ENOMEM; + return (NULL); + } + + sb->sb_ps = ps; + sb->sb_flags = 0; + sb->sb_pb.pb_align = 1; + sb->sb_pb.pb_off = 0; + sb->sb_pb.pb_size = sz; + if (sz > 0) { + if ((sb->sb_pb.pb_buf = malloc(sz)) == NULL) { + free(sb); + errno = ENOMEM; + return (NULL); + } + sb->sb_flags |= LIBPE_F_BUFFER_MALLOCED; + } else + sb->sb_pb.pb_buf = NULL; + + STAILQ_INSERT_TAIL(&ps->ps_b, sb, sb_next); + + return (sb); +} + +void +libpe_release_buffer(PE_SecBuf *sb) +{ + PE_Scn *ps; + + assert(sb != NULL); + + ps = sb->sb_ps; + + STAILQ_REMOVE(&ps->ps_b, sb, _PE_SecBuf, sb_next); + + if (sb->sb_flags & LIBPE_F_BUFFER_MALLOCED) + free(sb->sb_pb.pb_buf); + + free(sb); +} + +static int +cmp_sb(PE_SecBuf *a, PE_SecBuf *b) +{ + + if (a->sb_pb.pb_off < b->sb_pb.pb_off) + return (-1); + else if (a->sb_pb.pb_off == b->sb_pb.pb_off) + return (0); + else + return (1); +} + +static void +sort_buffers(PE_Scn *ps) +{ + + if (STAILQ_EMPTY(&ps->ps_b)) + return; + + STAILQ_SORT(&ps->ps_b, _PE_SecBuf, sb_next, cmp_sb); +} + +size_t +libpe_resync_buffers(PE_Scn *ps) +{ + PE_SecBuf *sb; + PE_Buffer *pb; + size_t sz; + + assert(ps->ps_flags & LIBPE_F_LOAD_SECTION); + + sort_buffers(ps); + + sz = 0; + STAILQ_FOREACH(sb, &ps->ps_b, sb_next) { + if (ps->ps_flags & PE_F_DIRTY) + sb->sb_flags |= PE_F_DIRTY; + + pb = (PE_Buffer *) sb; + if (pb->pb_align > ps->ps_falign) + pb->pb_align = ps->ps_falign; + if (pb->pb_buf == NULL || pb->pb_size == 0) + continue; + + sz = roundup(sz, pb->pb_align); + + if (pb->pb_off != (off_t) sz) { + pb->pb_off = sz; + sb->sb_flags |= PE_F_DIRTY; + } + sz += pb->pb_size; + } + + return (sz); +} + +int +libpe_write_buffers(PE_Scn *ps) +{ + PE *pe; + PE_SecBuf *sb; + PE_Buffer *pb; + off_t off; + + assert(ps->ps_flags & LIBPE_F_LOAD_SECTION); + + pe = ps->ps_pe; + + off = 0; + STAILQ_FOREACH(sb, &ps->ps_b, sb_next) { + pb = &sb->sb_pb; + if (pb->pb_buf == NULL || pb->pb_size == 0) + continue; + + if ((sb->sb_flags & PE_F_DIRTY) == 0) { + assert((pe->pe_flags & LIBPE_F_SPECIAL_FILE) == 0); + if (lseek(pe->pe_fd, (off_t) pb->pb_size, SEEK_CUR) < + 0) { + errno = EIO; + return (-1); + } + goto next_buf; + } + + if (pb->pb_off > off) { + if (libpe_pad(pe, pb->pb_off - off) < 0) + return (-1); + off = pb->pb_off; + } + + if (write(pe->pe_fd, pb->pb_buf, pb->pb_size) != + (ssize_t) pb->pb_size) { + errno = EIO; + return (-1); + } + + next_buf: + off += pb->pb_size; + } + + return (0); +} diff --git a/contrib/elftoolchain/libpe/libpe_coff.c b/contrib/elftoolchain/libpe/libpe_coff.c new file mode 100644 index 0000000..e161f7c --- /dev/null +++ b/contrib/elftoolchain/libpe/libpe_coff.c @@ -0,0 +1,535 @@ +/*- + * Copyright (c) 2015 Kai Wang + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include <sys/param.h> +#include <assert.h> +#include <errno.h> +#include <stdlib.h> +#include <string.h> +#include <time.h> +#include <unistd.h> + +#include "_libpe.h" + +ELFTC_VCSID("$Id: libpe_coff.c 3326 2016-01-16 17:46:17Z kaiwang27 $"); + +int +libpe_parse_coff_header(PE *pe, char *hdr) +{ + char tmp[128]; + PE_CoffHdr *ch; + PE_OptHdr *oh; + PE_DataDir *dd; + unsigned p, r, s; + int i; + + if ((ch = malloc(sizeof(PE_CoffHdr))) == NULL) { + errno = ENOMEM; + return (-1); + } + + PE_READ16(hdr, ch->ch_machine); + PE_READ16(hdr, ch->ch_nsec); + PE_READ32(hdr, ch->ch_timestamp); + PE_READ32(hdr, ch->ch_symptr); + PE_READ32(hdr, ch->ch_nsym); + PE_READ16(hdr, ch->ch_optsize); + PE_READ16(hdr, ch->ch_char); + + pe->pe_ch = ch; + + /* + * The Optional header is omitted for object files. + */ + if (ch->ch_optsize == 0) + return (libpe_parse_section_headers(pe)); + + if ((oh = calloc(1, sizeof(PE_OptHdr))) == NULL) { + errno = ENOMEM; + return (-1); + } + pe->pe_oh = oh; + +#define READ_OPT(n) \ + do { \ + /* \ + * Since the Optional Header size is variable, we must \ + * check if the requested read size will overrun the \ + * remaining header bytes. \ + */ \ + if (p + (n) > ch->ch_optsize) { \ + /* Consume the "extra" bytes */ \ + r = ch->ch_optsize - p; \ + if (read(pe->pe_fd, tmp, r) != (ssize_t) r) { \ + pe->pe_flags |= LIBPE_F_BAD_SEC_HEADER;\ + return (0); \ + } \ + return (libpe_parse_section_headers(pe)); \ + } \ + if (read(pe->pe_fd, tmp, (n)) != (ssize_t) (n)) { \ + pe->pe_flags |= LIBPE_F_BAD_OPT_HEADER; \ + return (0); \ + } \ + p += (n); \ + } while (0) +#define READ_OPT8(v) do { READ_OPT(1); (v) = *tmp; } while(0) +#define READ_OPT16(v) do { READ_OPT(2); (v) = le16dec(tmp); } while(0) +#define READ_OPT32(v) do { READ_OPT(4); (v) = le32dec(tmp); } while(0) +#define READ_OPT64(v) do { READ_OPT(8); (v) = le64dec(tmp); } while(0) + + /* + * Read in the Optional header. Size of some fields are depending + * on the PE format specified by the oh_magic field. (PE32 or PE32+) + */ + + p = 0; + READ_OPT16(oh->oh_magic); + if (oh->oh_magic == PE_FORMAT_32P) + pe->pe_obj = PE_O_PE32P; + READ_OPT8(oh->oh_ldvermajor); + READ_OPT8(oh->oh_ldverminor); + READ_OPT32(oh->oh_textsize); + READ_OPT32(oh->oh_datasize); + READ_OPT32(oh->oh_bsssize); + READ_OPT32(oh->oh_entry); + READ_OPT32(oh->oh_textbase); + if (oh->oh_magic != PE_FORMAT_32P) { + READ_OPT32(oh->oh_database); + READ_OPT32(oh->oh_imgbase); + } else + READ_OPT64(oh->oh_imgbase); + READ_OPT32(oh->oh_secalign); + READ_OPT32(oh->oh_filealign); + READ_OPT16(oh->oh_osvermajor); + READ_OPT16(oh->oh_osverminor); + READ_OPT16(oh->oh_imgvermajor); + READ_OPT16(oh->oh_imgverminor); + READ_OPT16(oh->oh_subvermajor); + READ_OPT16(oh->oh_subverminor); + READ_OPT32(oh->oh_win32ver); + READ_OPT32(oh->oh_imgsize); + READ_OPT32(oh->oh_hdrsize); + READ_OPT32(oh->oh_checksum); + READ_OPT16(oh->oh_subsystem); + READ_OPT16(oh->oh_dllchar); + if (oh->oh_magic != PE_FORMAT_32P) { + READ_OPT32(oh->oh_stacksizer); + READ_OPT32(oh->oh_stacksizec); + READ_OPT32(oh->oh_heapsizer); + READ_OPT32(oh->oh_heapsizec); + } else { + READ_OPT64(oh->oh_stacksizer); + READ_OPT64(oh->oh_stacksizec); + READ_OPT64(oh->oh_heapsizer); + READ_OPT64(oh->oh_heapsizec); + } + READ_OPT32(oh->oh_ldrflags); + READ_OPT32(oh->oh_ndatadir); + + /* + * Read in the Data Directories. + */ + + if (oh->oh_ndatadir > 0) { + if ((dd = calloc(1, sizeof(PE_DataDir))) == NULL) { + errno = ENOMEM; + return (-1); + } + pe->pe_dd = dd; + + dd->dd_total = oh->oh_ndatadir < PE_DD_MAX ? oh->oh_ndatadir : + PE_DD_MAX; + + for (i = 0; (uint32_t) i < dd->dd_total; i++) { + READ_OPT32(dd->dd_e[i].de_addr); + READ_OPT32(dd->dd_e[i].de_size); + } + } + + /* Consume the remaining bytes in the Optional header, if any. */ + if (ch->ch_optsize > p) { + r = ch->ch_optsize - p; + for (; r > 0; r -= s) { + s = r > sizeof(tmp) ? sizeof(tmp) : r; + if (read(pe->pe_fd, tmp, s) != (ssize_t) s) { + pe->pe_flags |= LIBPE_F_BAD_SEC_HEADER; + return (0); + } + } + } + + return (libpe_parse_section_headers(pe)); +} + +off_t +libpe_write_pe_header(PE *pe, off_t off) +{ + char tmp[4]; + + if (pe->pe_cmd == PE_C_RDWR && + (pe->pe_flags & LIBPE_F_BAD_PE_HEADER) == 0) { + assert(pe->pe_dh != NULL); + off = lseek(pe->pe_fd, (off_t) pe->pe_dh->dh_lfanew + 4, + SEEK_SET); + return (off); + } + + /* + * PE Header should to be aligned on 8-byte boundary according to + * the PE/COFF specification. + */ + if ((off = libpe_align(pe, off, 8)) < 0) + return (-1); + + le32enc(tmp, PE_SIGNATURE); + if (write(pe->pe_fd, tmp, sizeof(tmp)) != (ssize_t) sizeof(tmp)) { + errno = EIO; + return (-1); + } + + off += 4; + + pe->pe_flags &= ~LIBPE_F_BAD_PE_HEADER; + + /* Trigger rewrite for the following headers. */ + pe->pe_flags |= LIBPE_F_DIRTY_COFF_HEADER; + pe->pe_flags |= LIBPE_F_DIRTY_OPT_HEADER; + + return (off); +} + +off_t +libpe_write_coff_header(PE *pe, off_t off) +{ + char tmp[128], *hdr; + PE_CoffHdr *ch; + PE_DataDir *dd; + PE_OptHdr *oh; + PE_Scn *ps; + PE_SecHdr *sh; + unsigned p; + uint32_t reloc_rva, reloc_sz; + int i, reloc; + + reloc = 0; + reloc_rva = reloc_sz = 0; + + if (pe->pe_cmd == PE_C_RDWR) { + assert((pe->pe_flags & LIBPE_F_SPECIAL_FILE) == 0); + + if ((pe->pe_flags & LIBPE_F_DIRTY_COFF_HEADER) == 0 && + (pe->pe_flags & LIBPE_F_BAD_COFF_HEADER) == 0) { + if (lseek(pe->pe_fd, (off_t) sizeof(PE_CoffHdr), + SEEK_CUR) < 0) { + errno = EIO; + return (-1); + } + off += sizeof(PE_CoffHdr); + assert(pe->pe_ch != NULL); + ch = pe->pe_ch; + goto coff_done; + } + + /* lseek(2) to the offset of the COFF header. */ + if (lseek(pe->pe_fd, off, SEEK_SET) < 0) { + errno = EIO; + return (-1); + } + } + + if (pe->pe_ch == NULL) { + if ((ch = calloc(1, sizeof(PE_CoffHdr))) == NULL) { + errno = ENOMEM; + return (-1); + } + pe->pe_ch = ch; + + /* + * Default value for ch_machine if not provided by the + * application. + */ + if (pe->pe_obj == PE_O_PE32P) + ch->ch_machine = IMAGE_FILE_MACHINE_AMD64; + else + ch->ch_machine = IMAGE_FILE_MACHINE_I386; + + } else + ch = pe->pe_ch; + + if (!ch->ch_timestamp) + ch->ch_timestamp = time(NULL); + + if (pe->pe_obj == PE_O_PE32) { + if (!ch->ch_optsize) + ch->ch_optsize = PE_COFF_OPT_SIZE_32; + ch->ch_char |= IMAGE_FILE_EXECUTABLE_IMAGE | + IMAGE_FILE_32BIT_MACHINE; + } else if (pe->pe_obj == PE_O_PE32P) { + if (!ch->ch_optsize) + ch->ch_optsize = PE_COFF_OPT_SIZE_32P; + ch->ch_char |= IMAGE_FILE_EXECUTABLE_IMAGE | + IMAGE_FILE_LARGE_ADDRESS_AWARE; + } else + ch->ch_optsize = 0; + + /* + * COFF line number is deprecated by the PE/COFF + * specification. COFF symbol table is deprecated + * for executables. + */ + ch->ch_char |= IMAGE_FILE_LINE_NUMS_STRIPPED; + if (pe->pe_obj == PE_O_PE32 || pe->pe_obj == PE_O_PE32P) + ch->ch_char |= IMAGE_FILE_LOCAL_SYMS_STRIPPED; + + ch->ch_nsec = pe->pe_nscn; + + STAILQ_FOREACH(ps, &pe->pe_scn, ps_next) { + sh = &ps->ps_sh; + + if (ps->ps_ndx == 0xFFFFFFFFU) { + ch->ch_symptr = sh->sh_rawptr; + ch->ch_nsym = pe->pe_nsym; + } + + if (pe->pe_obj == PE_O_PE32 || pe->pe_obj == PE_O_PE32P) { + if (ps->ps_ndx == (0xFFFF0000 | PE_DD_BASERELOC) || + strncmp(sh->sh_name, ".reloc", strlen(".reloc")) == + 0) { + reloc = 1; + reloc_rva = sh->sh_addr; + reloc_sz = sh->sh_virtsize; + } + } + } + + if (!reloc) + ch->ch_char |= IMAGE_FILE_RELOCS_STRIPPED; + + if (pe->pe_flags & LIBPE_F_BAD_OPT_HEADER) { + if (pe->pe_obj == PE_O_PE32) + ch->ch_optsize = PE_COFF_OPT_SIZE_32; + else if (pe->pe_obj == PE_O_PE32P) + ch->ch_optsize = PE_COFF_OPT_SIZE_32P; + else + ch->ch_optsize = 0; + } + + /* + * Write the COFF header. + */ + hdr = tmp; + PE_WRITE16(hdr, ch->ch_machine); + PE_WRITE16(hdr, ch->ch_nsec); + PE_WRITE32(hdr, ch->ch_timestamp); + PE_WRITE32(hdr, ch->ch_symptr); + PE_WRITE32(hdr, ch->ch_nsym); + PE_WRITE16(hdr, ch->ch_optsize); + PE_WRITE16(hdr, ch->ch_char); + if (write(pe->pe_fd, tmp, sizeof(PE_CoffHdr)) != + (ssize_t) sizeof(PE_CoffHdr)) { + errno = EIO; + return (-1); + } + +coff_done: + off += sizeof(PE_CoffHdr); + pe->pe_flags &= ~LIBPE_F_DIRTY_COFF_HEADER; + pe->pe_flags &= ~LIBPE_F_BAD_COFF_HEADER; + pe->pe_flags |= LIBPE_F_DIRTY_SEC_HEADER; + + if (ch->ch_optsize == 0) + return (off); + + /* + * Write the Optional header. + */ + + if (pe->pe_cmd == PE_C_RDWR) { + if ((pe->pe_flags & LIBPE_F_DIRTY_OPT_HEADER) == 0 && + (pe->pe_flags & LIBPE_F_BAD_OPT_HEADER) == 0) { + if (lseek(pe->pe_fd, (off_t) ch->ch_optsize, + SEEK_CUR) < 0) { + errno = EIO; + return (-1); + } + off += ch->ch_optsize; + return (off); + } + + } + + if (pe->pe_oh == NULL) { + if ((oh = calloc(1, sizeof(PE_OptHdr))) == NULL) { + errno = ENOMEM; + return (-1); + } + pe->pe_oh = oh; + } else + oh = pe->pe_oh; + + if (pe->pe_obj == PE_O_PE32) + oh->oh_magic = PE_FORMAT_32; + else + oh->oh_magic = PE_FORMAT_32P; + + /* + * LinkerVersion should not be less than 2.5, which will cause + * Windows to complain the executable is invalid in some case. + * By default we set LinkerVersion to 2.22 (binutils 2.22) + */ + if (!oh->oh_ldvermajor && !oh->oh_ldverminor) { + oh->oh_ldvermajor = 2; + oh->oh_ldverminor = 22; + } + + /* + * The library always tries to write out all 16 data directories + * but the actual data dir written will depend on ch_optsize. + */ + oh->oh_ndatadir = PE_DD_MAX; + + if (!oh->oh_filealign) + oh->oh_filealign = 0x200; + if (!oh->oh_secalign) + oh->oh_secalign = 0x1000; + oh->oh_hdrsize = roundup(off + ch->ch_optsize + pe->pe_nscn * + sizeof(PE_SecHdr), oh->oh_filealign); + oh->oh_imgsize = roundup(pe->pe_rvamax, oh->oh_secalign); + +#define WRITE_OPT(n) \ + do { \ + /* \ + * Since the Optional Header size is variable, we must \ + * check if the requested write size will overrun the \ + * remaining header bytes. \ + */ \ + if (p + (n) > ch->ch_optsize) { \ + /* Pad the "extra" bytes */ \ + if (libpe_pad(pe, ch->ch_optsize - p) < 0) { \ + errno = EIO; \ + return (-1); \ + } \ + goto opt_done; \ + } \ + if (write(pe->pe_fd, tmp, (n)) != (ssize_t) (n)) { \ + errno = EIO; \ + return (-1); \ + } \ + p += (n); \ + } while (0) +#define WRITE_OPT8(v) do { *tmp = (v); WRITE_OPT(1); } while(0) +#define WRITE_OPT16(v) do { le16enc(tmp, (v)); WRITE_OPT(2); } while(0) +#define WRITE_OPT32(v) do { le32enc(tmp, (v)); WRITE_OPT(4); } while(0) +#define WRITE_OPT64(v) do { le64enc(tmp, (v)); WRITE_OPT(8); } while(0) + + p = 0; + WRITE_OPT16(oh->oh_magic); + if (oh->oh_magic == PE_FORMAT_32P) + pe->pe_obj = PE_O_PE32P; + WRITE_OPT8(oh->oh_ldvermajor); + WRITE_OPT8(oh->oh_ldverminor); + WRITE_OPT32(oh->oh_textsize); + WRITE_OPT32(oh->oh_datasize); + WRITE_OPT32(oh->oh_bsssize); + WRITE_OPT32(oh->oh_entry); + WRITE_OPT32(oh->oh_textbase); + if (oh->oh_magic != PE_FORMAT_32P) { + WRITE_OPT32(oh->oh_database); + WRITE_OPT32(oh->oh_imgbase); + } else + WRITE_OPT64(oh->oh_imgbase); + WRITE_OPT32(oh->oh_secalign); + WRITE_OPT32(oh->oh_filealign); + WRITE_OPT16(oh->oh_osvermajor); + WRITE_OPT16(oh->oh_osverminor); + WRITE_OPT16(oh->oh_imgvermajor); + WRITE_OPT16(oh->oh_imgverminor); + WRITE_OPT16(oh->oh_subvermajor); + WRITE_OPT16(oh->oh_subverminor); + WRITE_OPT32(oh->oh_win32ver); + WRITE_OPT32(oh->oh_imgsize); + WRITE_OPT32(oh->oh_hdrsize); + WRITE_OPT32(oh->oh_checksum); + WRITE_OPT16(oh->oh_subsystem); + WRITE_OPT16(oh->oh_dllchar); + if (oh->oh_magic != PE_FORMAT_32P) { + WRITE_OPT32(oh->oh_stacksizer); + WRITE_OPT32(oh->oh_stacksizec); + WRITE_OPT32(oh->oh_heapsizer); + WRITE_OPT32(oh->oh_heapsizec); + } else { + WRITE_OPT64(oh->oh_stacksizer); + WRITE_OPT64(oh->oh_stacksizec); + WRITE_OPT64(oh->oh_heapsizer); + WRITE_OPT64(oh->oh_heapsizec); + } + WRITE_OPT32(oh->oh_ldrflags); + WRITE_OPT32(oh->oh_ndatadir); + + /* + * Write the Data Directories. + */ + + if (oh->oh_ndatadir > 0) { + if (pe->pe_dd == NULL) { + if ((dd = calloc(1, sizeof(PE_DataDir))) == NULL) { + errno = ENOMEM; + return (-1); + } + pe->pe_dd = dd; + dd->dd_total = PE_DD_MAX; + } else + dd = pe->pe_dd; + + assert(oh->oh_ndatadir <= PE_DD_MAX); + + if (reloc) { + dd->dd_e[PE_DD_BASERELOC].de_addr = reloc_rva; + dd->dd_e[PE_DD_BASERELOC].de_size = reloc_sz; + } + + for (i = 0; (uint32_t) i < dd->dd_total; i++) { + WRITE_OPT32(dd->dd_e[i].de_addr); + WRITE_OPT32(dd->dd_e[i].de_size); + } + } + + /* Pad the remaining bytes in the Optional header, if any. */ + if (ch->ch_optsize > p) { + if (libpe_pad(pe, ch->ch_optsize - p) < 0) { + errno = EIO; + return (-1); + } + } + +opt_done: + off += ch->ch_optsize; + pe->pe_flags &= ~LIBPE_F_DIRTY_OPT_HEADER; + pe->pe_flags &= ~LIBPE_F_BAD_OPT_HEADER; + pe->pe_flags |= LIBPE_F_DIRTY_SEC_HEADER; + + return (off); +} diff --git a/contrib/elftoolchain/libpe/libpe_dos.c b/contrib/elftoolchain/libpe/libpe_dos.c new file mode 100644 index 0000000..a48ad12 --- /dev/null +++ b/contrib/elftoolchain/libpe/libpe_dos.c @@ -0,0 +1,403 @@ +/*- + * Copyright (c) 2015 Kai Wang + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include <sys/param.h> +#include <sys/types.h> +#include <assert.h> +#include <errno.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> + +#include "_libpe.h" + +ELFTC_VCSID("$Id: libpe_dos.c 3312 2016-01-10 09:23:51Z kaiwang27 $"); + +int +libpe_parse_msdos_header(PE *pe, char *hdr) +{ + PE_DosHdr *dh; + char coff[sizeof(PE_CoffHdr)]; + uint32_t pe_magic; + int i; + + if ((pe->pe_stub = malloc(sizeof(PE_DosHdr))) == NULL) { + errno = ENOMEM; + return (-1); + } + memcpy(pe->pe_stub, hdr, sizeof(PE_DosHdr)); + + if ((dh = malloc(sizeof(*dh))) == NULL) { + errno = ENOMEM; + return (-1); + } + pe->pe_dh = dh; + + /* Read the conventional MS-DOS EXE header. */ + memcpy(dh->dh_magic, hdr, 2); + hdr += 2; + PE_READ16(hdr, dh->dh_lastsize); + PE_READ16(hdr, dh->dh_nblock); + PE_READ16(hdr, dh->dh_nreloc); + PE_READ16(hdr, dh->dh_hdrsize); + PE_READ16(hdr, dh->dh_minalloc); + PE_READ16(hdr, dh->dh_maxalloc); + PE_READ16(hdr, dh->dh_ss); + PE_READ16(hdr, dh->dh_sp); + PE_READ16(hdr, dh->dh_checksum); + PE_READ16(hdr, dh->dh_ip); + PE_READ16(hdr, dh->dh_cs); + PE_READ16(hdr, dh->dh_relocpos); + PE_READ16(hdr, dh->dh_noverlay); + + /* Do not continue if the EXE is not a PE/NE/... (new executable) */ + if (dh->dh_relocpos != 0x40) { + pe->pe_flags |= LIBPE_F_BAD_DOS_HEADER; + return (0); + } + + for (i = 0; i < 4; i++) + PE_READ16(hdr, dh->dh_reserved1[i]); + PE_READ16(hdr, dh->dh_oemid); + PE_READ16(hdr, dh->dh_oeminfo); + for (i = 0; i < 10; i++) + PE_READ16(hdr, dh->dh_reserved2[i]); + PE_READ32(hdr, dh->dh_lfanew); + + /* Check if the e_lfanew pointer is valid. */ + if (dh->dh_lfanew > pe->pe_fsize - 4) { + pe->pe_flags |= LIBPE_F_BAD_DOS_HEADER; + return (0); + } + + if (dh->dh_lfanew < sizeof(PE_DosHdr) && + (pe->pe_flags & LIBPE_F_SPECIAL_FILE)) { + pe->pe_flags |= LIBPE_F_BAD_DOS_HEADER; + return (0); + } + + if (dh->dh_lfanew > sizeof(PE_DosHdr)) { + pe->pe_stub_ex = dh->dh_lfanew - sizeof(PE_DosHdr); + if (pe->pe_flags & LIBPE_F_SPECIAL_FILE) { + /* Read in DOS stub now. */ + if (libpe_read_msdos_stub(pe) < 0) { + pe->pe_flags |= LIBPE_F_BAD_DOS_HEADER; + return (0); + } + } + } + + if ((pe->pe_flags & LIBPE_F_SPECIAL_FILE) == 0) { + /* Jump to the PE header. */ + if (lseek(pe->pe_fd, (off_t) dh->dh_lfanew, SEEK_SET) < 0) { + pe->pe_flags |= LIBPE_F_BAD_PE_HEADER; + return (0); + } + } + + if (read(pe->pe_fd, &pe_magic, 4) != 4 || + htole32(pe_magic) != PE_SIGNATURE) { + pe->pe_flags |= LIBPE_F_BAD_PE_HEADER; + return (0); + } + + if (read(pe->pe_fd, coff, sizeof(coff)) != (ssize_t) sizeof(coff)) { + pe->pe_flags |= LIBPE_F_BAD_COFF_HEADER; + return (0); + } + + return (libpe_parse_coff_header(pe, coff)); +} + +int +libpe_read_msdos_stub(PE *pe) +{ + void *m; + + assert(pe->pe_stub_ex > 0 && + (pe->pe_flags & LIBPE_F_LOAD_DOS_STUB) == 0); + + if ((pe->pe_flags & LIBPE_F_SPECIAL_FILE) == 0) { + if (lseek(pe->pe_fd, (off_t) sizeof(PE_DosHdr), SEEK_SET) < + 0) { + errno = EIO; + goto fail; + } + } + + if ((m = realloc(pe->pe_stub, sizeof(PE_DosHdr) + pe->pe_stub_ex)) == + NULL) { + errno = ENOMEM; + goto fail; + } + pe->pe_stub = m; + + if (read(pe->pe_fd, pe->pe_stub + sizeof(PE_DosHdr), pe->pe_stub_ex) != + (ssize_t) pe->pe_stub_ex) { + errno = EIO; + goto fail; + } + + pe->pe_flags |= LIBPE_F_LOAD_DOS_STUB; + + /* Search for the Rich header embedded just before the PE header. */ + (void) libpe_parse_rich_header(pe); + + return (0); + +fail: + pe->pe_stub_ex = 0; + + return (-1); +} + +/* + * The "standard" MS-DOS stub displaying "This program cannot be run in + * DOS mode". + */ +static const char msdos_stub[] = { + '\x0e','\x1f','\xba','\x0e','\x00','\xb4','\x09','\xcd', + '\x21','\xb8','\x01','\x4c','\xcd','\x21','\x54','\x68', + '\x69','\x73','\x20','\x70','\x72','\x6f','\x67','\x72', + '\x61','\x6d','\x20','\x63','\x61','\x6e','\x6e','\x6f', + '\x74','\x20','\x62','\x65','\x20','\x72','\x75','\x6e', + '\x20','\x69','\x6e','\x20','\x44','\x4f','\x53','\x20', + '\x6d','\x6f','\x64','\x65','\x2e','\x0d','\x0d','\x0a', + '\x24','\x00','\x00','\x00','\x00','\x00','\x00','\x00', +}; + +static void +init_dos_header(PE_DosHdr *dh) +{ + + dh->dh_magic[0] = 'M'; + dh->dh_magic[1] = 'Z'; + dh->dh_lastsize = 144; + dh->dh_nblock = 3; + dh->dh_hdrsize = 4; + dh->dh_maxalloc = 65535; + dh->dh_sp = 184; + dh->dh_relocpos = 0x40; + dh->dh_lfanew = 0x80; +} + +off_t +libpe_write_msdos_stub(PE *pe, off_t off) +{ + PE_DosHdr *dh; + char tmp[sizeof(PE_DosHdr)], *hdr; + off_t d; + int i, strip_rich; + + strip_rich = 0; + + if (pe->pe_cmd == PE_C_RDWR) { + assert((pe->pe_flags & LIBPE_F_SPECIAL_FILE) == 0); + + if (pe->pe_dh != NULL && + (pe->pe_flags & PE_F_STRIP_DOS_STUB)) { + /* + * If we strip MS-DOS stub, everything after it + * needs rewritten. + */ + pe->pe_flags |= LIBPE_F_BAD_PE_HEADER; + goto done; + } + + /* + * lseek(2) to the PE signature if MS-DOS stub is not + * modified. + */ + if (pe->pe_dh != NULL && + (pe->pe_flags & LIBPE_F_DIRTY_DOS_HEADER) == 0 && + (pe->pe_flags & LIBPE_F_BAD_DOS_HEADER) == 0 && + (pe->pe_flags & PE_F_STRIP_RICH_HEADER) == 0) { + if (lseek(pe->pe_fd, + (off_t) (sizeof(PE_DosHdr) + pe->pe_stub_ex), + SEEK_CUR) < 0) { + errno = EIO; + return (-1); + } + off = sizeof(PE_DosHdr) + pe->pe_stub_ex; + goto done; + } + + /* Check if we should strip the Rich header. */ + if (pe->pe_dh != NULL && pe->pe_stub_app == NULL && + (pe->pe_flags & LIBPE_F_BAD_DOS_HEADER) == 0 && + (pe->pe_flags & PE_F_STRIP_RICH_HEADER)) { + if ((pe->pe_flags & LIBPE_F_LOAD_DOS_STUB) == 0) { + (void) libpe_read_msdos_stub(pe); + if (lseek(pe->pe_fd, off, SEEK_SET) < 0) { + errno = EIO; + return (-1); + } + } + if (pe->pe_rh != NULL) { + strip_rich = 1; + pe->pe_flags |= LIBPE_F_DIRTY_DOS_HEADER; + } + } + + /* + * If length of MS-DOS stub will change, Mark the PE + * signature is broken so that the PE signature and the + * headers follow it will be rewritten. + * + * The sections should be loaded now since the stub might + * overwrite the section data. + */ + if ((pe->pe_flags & LIBPE_F_BAD_DOS_HEADER) || + (pe->pe_stub_app != NULL && pe->pe_stub_app_sz != + sizeof(PE_DosHdr) + pe->pe_stub_ex) || strip_rich) { + if (libpe_load_all_sections(pe) < 0) + return (-1); + if (lseek(pe->pe_fd, off, SEEK_SET) < 0) { + errno = EIO; + return (-1); + } + pe->pe_flags |= LIBPE_F_BAD_PE_HEADER; + } + } + + if (pe->pe_flags & PE_F_STRIP_DOS_STUB) + goto done; + + /* Always use application supplied MS-DOS stub, if exists. */ + if (pe->pe_stub_app != NULL && pe->pe_stub_app_sz > 0) { + if (write(pe->pe_fd, pe->pe_stub_app, pe->pe_stub_app_sz) != + (ssize_t) pe->pe_stub_app_sz) { + errno = EIO; + return (-1); + } + off = pe->pe_stub_app_sz; + goto done; + } + + /* + * Write MS-DOS header. + */ + + if (pe->pe_dh == NULL) { + if ((dh = calloc(1, sizeof(PE_DosHdr))) == NULL) { + errno = ENOMEM; + return (-1); + } + pe->pe_dh = dh; + + init_dos_header(dh); + + pe->pe_flags |= LIBPE_F_DIRTY_DOS_HEADER; + } else + dh = pe->pe_dh; + + if (pe->pe_flags & LIBPE_F_BAD_DOS_HEADER) + init_dos_header(dh); + + if (strip_rich) { + d = pe->pe_rh_start - pe->pe_stub; + dh->dh_lfanew = roundup(d, 8); + } + + if ((pe->pe_flags & LIBPE_F_DIRTY_DOS_HEADER) || + (pe->pe_flags & LIBPE_F_BAD_DOS_HEADER)) { + memcpy(tmp, dh->dh_magic, 2); + hdr = tmp + 2; + PE_WRITE16(hdr, dh->dh_lastsize); + PE_WRITE16(hdr, dh->dh_nblock); + PE_WRITE16(hdr, dh->dh_nreloc); + PE_WRITE16(hdr, dh->dh_hdrsize); + PE_WRITE16(hdr, dh->dh_minalloc); + PE_WRITE16(hdr, dh->dh_maxalloc); + PE_WRITE16(hdr, dh->dh_ss); + PE_WRITE16(hdr, dh->dh_sp); + PE_WRITE16(hdr, dh->dh_checksum); + PE_WRITE16(hdr, dh->dh_ip); + PE_WRITE16(hdr, dh->dh_cs); + PE_WRITE16(hdr, dh->dh_relocpos); + PE_WRITE16(hdr, dh->dh_noverlay); + for (i = 0; i < 4; i++) + PE_WRITE16(hdr, dh->dh_reserved1[i]); + PE_WRITE16(hdr, dh->dh_oemid); + PE_WRITE16(hdr, dh->dh_oeminfo); + for (i = 0; i < 10; i++) + PE_WRITE16(hdr, dh->dh_reserved2[i]); + PE_WRITE32(hdr, dh->dh_lfanew); + + if (write(pe->pe_fd, tmp, sizeof(tmp)) != + (ssize_t) sizeof(tmp)) { + errno = EIO; + return (-1); + } + } else { + assert((pe->pe_flags & LIBPE_F_SPECIAL_FILE) == 0); + if (lseek(pe->pe_fd, (off_t) sizeof(PE_DosHdr), SEEK_CUR) < + 0) { + errno = EIO; + return (-1); + } + } + + off = sizeof(PE_DosHdr); + + /* + * Write the MS-DOS stub. + */ + + if (strip_rich) { + assert((pe->pe_flags & LIBPE_F_SPECIAL_FILE) == 0); + assert(pe->pe_stub != NULL && pe->pe_rh_start != NULL); + d = pe->pe_rh_start - pe->pe_stub; + if (lseek(pe->pe_fd, d, SEEK_SET) < 0) { + errno = EIO; + return (-1); + } + off = d; + goto done; + } + + if (pe->pe_cmd == PE_C_RDWR) { + if (lseek(pe->pe_fd, (off_t) pe->pe_stub_ex, SEEK_CUR) < 0) { + errno = EIO; + return (-1); + } + off += pe->pe_stub_ex; + goto done; + } + + if (write(pe->pe_fd, msdos_stub, sizeof(msdos_stub)) != + (ssize_t) sizeof(msdos_stub)) { + errno = EIO; + return (-1); + } + off += sizeof(msdos_stub); + +done: + pe->pe_flags &= ~LIBPE_F_DIRTY_DOS_HEADER; + pe->pe_flags &= ~LIBPE_F_BAD_DOS_HEADER; + + return (off); +} diff --git a/contrib/elftoolchain/libpe/libpe_init.c b/contrib/elftoolchain/libpe/libpe_init.c new file mode 100644 index 0000000..2579774 --- /dev/null +++ b/contrib/elftoolchain/libpe/libpe_init.c @@ -0,0 +1,145 @@ +/*- + * Copyright (c) 2015 Kai Wang + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include <sys/stat.h> +#include <assert.h> +#include <errno.h> +#include <stdlib.h> +#include <unistd.h> + +#include "_libpe.h" + +ELFTC_VCSID("$Id: libpe_init.c 3312 2016-01-10 09:23:51Z kaiwang27 $"); + +int +libpe_open_object(PE *pe) +{ + struct stat sb; + mode_t mode; + char magic[sizeof(PE_DosHdr)]; + + if (fstat(pe->pe_fd, &sb) < 0) + return (-1); + + mode = sb.st_mode; + pe->pe_fsize = (size_t) sb.st_size; + + /* Reject unsupported file types. */ + if (!S_ISREG(mode) && !S_ISCHR(mode) && !S_ISFIFO(mode) && + !S_ISSOCK(mode)) { + errno = EINVAL; + return (-1); + } + + /* Read/Write mode is not supported for non-regular file. */ + if (pe->pe_cmd == PE_C_RDWR && !S_ISREG(mode)) { + errno = EINVAL; + return (-1); + } + + /* The minimal file should at least contain a COFF header. */ + if (S_ISREG(mode) && pe->pe_fsize < sizeof(PE_CoffHdr)) { + errno = ENOENT; + return (-1); + } + + /* + * Search for MS-DOS header or COFF header. + */ + + if (read(pe->pe_fd, magic, 2) != 2) { + errno = EIO; + return (-1); + } + + if (magic[0] == 'M' && magic[1] == 'Z') { + pe->pe_obj = PE_O_PE32; + if (read(pe->pe_fd, &magic[2], sizeof(PE_DosHdr) - 2) != + (ssize_t) sizeof(PE_DosHdr) - 2) { + errno = EIO; + return (-1); + } + return (libpe_parse_msdos_header(pe, magic)); + + } else if (magic[0] == 'P' && magic[1] == 'E') { + if (read(pe->pe_fd, magic, 2) != 2) { + errno = EIO; + return (-1); + } + if (magic[0] == '\0' && magic[1] == '\0') { + pe->pe_obj = PE_O_PE32; + if (read(pe->pe_fd, magic, sizeof(PE_CoffHdr)) != + (ssize_t) sizeof(PE_CoffHdr)) { + errno = EIO; + return (-1); + } + return (libpe_parse_coff_header(pe, magic)); + } + errno = ENOENT; + return (-1); + + } else { + pe->pe_obj = PE_O_COFF; + if (read(pe->pe_fd, &magic[2], sizeof(PE_CoffHdr) - 2) != + (ssize_t) sizeof(PE_CoffHdr) - 2) { + errno = EIO; + return (-1); + } + return (libpe_parse_coff_header(pe, magic)); + } +} + +void +libpe_release_object(PE *pe) +{ + PE_Scn *ps, *_ps; + + if (pe->pe_dh) + free(pe->pe_dh); + + if (pe->pe_rh) { + free(pe->pe_rh->rh_compid); + free(pe->pe_rh->rh_cnt); + free(pe->pe_rh); + } + + if (pe->pe_ch) + free(pe->pe_ch); + + if (pe->pe_oh) + free(pe->pe_oh); + + if (pe->pe_dd) + free(pe->pe_dd); + + if (pe->pe_stub) + free(pe->pe_stub); + + STAILQ_FOREACH_SAFE(ps, &pe->pe_scn, ps_next, _ps) + libpe_release_scn(ps); + + free(pe); +} diff --git a/contrib/elftoolchain/libpe/libpe_rich.c b/contrib/elftoolchain/libpe/libpe_rich.c new file mode 100644 index 0000000..4669a22 --- /dev/null +++ b/contrib/elftoolchain/libpe/libpe_rich.c @@ -0,0 +1,128 @@ +/*- + * Copyright (c) 2015 Kai Wang + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include <assert.h> +#include <errno.h> +#include <stdlib.h> +#include <string.h> + +#include "_libpe.h" + +ELFTC_VCSID("$Id: libpe_rich.c 3312 2016-01-10 09:23:51Z kaiwang27 $"); + +static char * +memfind(char *s, const char *find, size_t slen, size_t flen) +{ + int i; + + if (slen == 0 || flen == 0 || flen > slen) + return (NULL); + + for (i = 0; (size_t) i <= slen - flen; i++) { + if (s[i] != find[0]) + continue; + if (flen == 1) + return (&s[i]); + if (memcmp(&s[i + 1], &find[1], flen - 1) == 0) + return (&s[i]); + } + + return (NULL); +} + +int +libpe_parse_rich_header(PE *pe) +{ + PE_RichHdr *rh; + char *p, *r, *s; + uint32_t x; + int found, i; + + assert(pe->pe_stub != NULL && pe->pe_stub_ex > 0); + + /* Search for the "Rich" keyword to locate the Rich header. */ + s = pe->pe_stub + sizeof(PE_DosHdr); + r = memfind(s, PE_RICH_TEXT, pe->pe_stub_ex, 4); + if (r == NULL || r + 8 > s + pe->pe_stub_ex) { + errno = ENOENT; + return (-1); + } + + if ((rh = calloc(1, sizeof(*rh))) == NULL) { + errno = ENOMEM; + return (-1); + } + + rh->rh_xor = le32dec(r + 4); /* Retrieve the "XOR mask" */ + + /* + * Search for the hidden keyword "DanS" by XOR the dwords before + * the "Rich" keyword with the XOR mask. + */ + found = 0; + for (p = r - 4; p >= s; p -= 4) { + x = le32dec(p) ^ rh->rh_xor; + if (x == PE_RICH_HIDDEN) { + found = 1; + break; + } + } + if (!found) { + free(rh); + errno = ENOENT; + return (-1); + } + + /* + * Found the "DanS" keyword, which is the start of the Rich header. + * The next step is to skip the first 16 bytes (DanS, XOR mask, + * XOR mask, XOR mask) and read the (compid,cnt) tuples. + */ + pe->pe_rh_start = p; + p += 16; + rh->rh_total = (r - p) / 8; + if ((rh->rh_compid = malloc(rh->rh_total * sizeof(*rh->rh_compid))) == + NULL) { + free(rh); + errno = ENOMEM; + return (-1); + } + if ((rh->rh_cnt = malloc(rh->rh_total * sizeof(*rh->rh_cnt))) == + NULL) { + free(rh->rh_compid); + free(rh); + errno = ENOMEM; + return (-1); + } + for (i = 0; (uint32_t) i < rh->rh_total; i++, p += 8) { + rh->rh_compid[i] = le32dec(p) ^ rh->rh_xor; + rh->rh_cnt[i] = le32dec(p + 4) ^ rh->rh_xor; + } + + pe->pe_rh = rh; + + return (0); +} diff --git a/contrib/elftoolchain/libpe/libpe_section.c b/contrib/elftoolchain/libpe/libpe_section.c new file mode 100644 index 0000000..7ff63fb --- /dev/null +++ b/contrib/elftoolchain/libpe/libpe_section.c @@ -0,0 +1,518 @@ +/*- + * Copyright (c) 2016 Kai Wang + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include <sys/param.h> +#include <assert.h> +#include <errno.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> + +#include "_libpe.h" + +ELFTC_VCSID("$Id: libpe_section.c 3312 2016-01-10 09:23:51Z kaiwang27 $"); + +PE_Scn * +libpe_alloc_scn(PE *pe) +{ + PE_Scn *ps; + + if ((ps = calloc(1, sizeof(PE_Scn))) == NULL) { + errno = ENOMEM; + return (NULL); + } + STAILQ_INIT(&ps->ps_b); + ps->ps_pe = pe; + + return (ps); +} + +void +libpe_release_scn(PE_Scn *ps) +{ + PE *pe; + PE_SecBuf *sb, *_sb; + + assert(ps != NULL); + + pe = ps->ps_pe; + + STAILQ_REMOVE(&pe->pe_scn, ps, _PE_Scn, ps_next); + + STAILQ_FOREACH_SAFE(sb, &ps->ps_b, sb_next, _sb) + libpe_release_buffer(sb); + + free(ps); +} + +static int +cmp_scn(PE_Scn *a, PE_Scn *b) +{ + + if (a->ps_sh.sh_addr < b->ps_sh.sh_addr) + return (-1); + else if (a->ps_sh.sh_addr == b->ps_sh.sh_addr) + return (0); + else + return (1); +} + +static void +sort_sections(PE *pe) +{ + + if (STAILQ_EMPTY(&pe->pe_scn)) + return; + + /* Sort the list of Scn by RVA in ascending order. */ + STAILQ_SORT(&pe->pe_scn, _PE_Scn, ps_next, cmp_scn); +} + +int +libpe_parse_section_headers(PE *pe) +{ + char tmp[sizeof(PE_SecHdr)], *hdr; + PE_Scn *ps; + PE_SecHdr *sh; + PE_CoffHdr *ch; + PE_DataDir *dd; + int found, i; + + assert(pe->pe_ch != NULL); + + for (i = 0; (uint16_t) i < pe->pe_ch->ch_nsec; i++) { + if (read(pe->pe_fd, tmp, sizeof(PE_SecHdr)) != + (ssize_t) sizeof(PE_SecHdr)) { + pe->pe_flags |= LIBPE_F_BAD_SEC_HEADER; + return (0); + } + + if ((ps = libpe_alloc_scn(pe)) == NULL) + return (-1); + STAILQ_INSERT_TAIL(&pe->pe_scn, ps, ps_next); + ps->ps_ndx = ++pe->pe_nscn; /* Setion index is 1-based */ + sh = &ps->ps_sh; + + /* + * Note that the section name won't be NUL-terminated if + * its length happens to be 8. + */ + memcpy(sh->sh_name, tmp, sizeof(sh->sh_name)); + hdr = tmp + 8; + PE_READ32(hdr, sh->sh_virtsize); + PE_READ32(hdr, sh->sh_addr); + PE_READ32(hdr, sh->sh_rawsize); + PE_READ32(hdr, sh->sh_rawptr); + PE_READ32(hdr, sh->sh_relocptr); + PE_READ32(hdr, sh->sh_lineptr); + PE_READ16(hdr, sh->sh_nreloc); + PE_READ16(hdr, sh->sh_nline); + PE_READ32(hdr, sh->sh_char); + } + + /* + * For all the data directories that don't belong to any section, + * we create pseudo sections for them to make layout easier. + */ + dd = pe->pe_dd; + if (dd != NULL && dd->dd_total > 0) { + for (i = 0; (uint32_t) i < pe->pe_dd->dd_total; i++) { + if (dd->dd_e[i].de_size == 0) + continue; + found = 0; + STAILQ_FOREACH(ps, &pe->pe_scn, ps_next) { + sh = &ps->ps_sh; + if (dd->dd_e[i].de_addr >= sh->sh_addr && + dd->dd_e[i].de_addr + dd->dd_e[i].de_size <= + sh->sh_addr + sh->sh_virtsize) { + found = 1; + break; + } + } + if (found) + continue; + + if ((ps = libpe_alloc_scn(pe)) == NULL) + return (-1); + STAILQ_INSERT_TAIL(&pe->pe_scn, ps, ps_next); + ps->ps_ndx = 0xFFFF0000U | i; + sh = &ps->ps_sh; + sh->sh_rawptr = dd->dd_e[i].de_addr; /* FIXME */ + sh->sh_rawsize = dd->dd_e[i].de_size; + } + } + + /* + * Also consider the COFF symbol table as a pseudo section. + */ + ch = pe->pe_ch; + if (ch->ch_nsym > 0) { + if ((ps = libpe_alloc_scn(pe)) == NULL) + return (-1); + STAILQ_INSERT_TAIL(&pe->pe_scn, ps, ps_next); + ps->ps_ndx = 0xFFFFFFFFU; + sh = &ps->ps_sh; + sh->sh_rawptr = ch->ch_symptr; + sh->sh_rawsize = ch->ch_nsym * PE_SYM_ENTRY_SIZE; + pe->pe_nsym = ch->ch_nsym; + } + + /* PE file headers initialization is complete if we reach here. */ + return (0); +} + +int +libpe_load_section(PE *pe, PE_Scn *ps) +{ + PE_SecHdr *sh; + PE_SecBuf *sb; + size_t sz; + char tmp[4]; + + assert(pe != NULL && ps != NULL); + assert((ps->ps_flags & LIBPE_F_LOAD_SECTION) == 0); + + sh = &ps->ps_sh; + + /* Allocate a PE_SecBuf struct without buffer for empty sections. */ + if (sh->sh_rawsize == 0) { + (void) libpe_alloc_buffer(ps, 0); + ps->ps_flags |= LIBPE_F_LOAD_SECTION; + return (0); + } + + if ((pe->pe_flags & LIBPE_F_SPECIAL_FILE) == 0) { + if (lseek(pe->pe_fd, (off_t) sh->sh_rawptr, SEEK_SET) < 0) { + errno = EIO; + return (-1); + } + } + + if ((sb = libpe_alloc_buffer(ps, sh->sh_rawsize)) == NULL) + return (-1); + + if (read(pe->pe_fd, sb->sb_pb.pb_buf, sh->sh_rawsize) != + (ssize_t) sh->sh_rawsize) { + errno = EIO; + return (-1); + } + + if (ps->ps_ndx == 0xFFFFFFFFU) { + /* + * Index 0xFFFFFFFF indicates this section is a pseudo + * section that contains the COFF symbol table. We should + * read in the string table right after it. + */ + if (read(pe->pe_fd, tmp, sizeof(tmp)) != + (ssize_t) sizeof(tmp)) { + errno = EIO; + return (-1); + } + sz = le32dec(tmp); + + /* + * The minimum value for the size field is 4, which indicates + * there is no string table. + */ + if (sz > 4) { + sz -= 4; + if ((sb = libpe_alloc_buffer(ps, sz)) == NULL) + return (-1); + if (read(pe->pe_fd, sb->sb_pb.pb_buf, sz) != + (ssize_t) sz) { + errno = EIO; + return (-1); + } + } + } + + ps->ps_flags |= LIBPE_F_LOAD_SECTION; + + return (0); +} + +int +libpe_load_all_sections(PE *pe) +{ + PE_Scn *ps; + PE_SecHdr *sh; + unsigned r, s; + off_t off; + char tmp[256]; + + /* Calculate the current offset into the file. */ + off = 0; + if (pe->pe_dh != NULL) + off += pe->pe_dh->dh_lfanew + 4; + if (pe->pe_ch != NULL) + off += sizeof(PE_CoffHdr) + pe->pe_ch->ch_optsize; + + STAILQ_FOREACH(ps, &pe->pe_scn, ps_next) { + if (ps->ps_flags & LIBPE_F_LOAD_SECTION) + continue; + sh = &ps->ps_sh; + + /* + * For special files, we consume the padding in between + * and advance to the section offset. + */ + if (pe->pe_flags & LIBPE_F_SPECIAL_FILE) { + /* Can't go backwards. */ + if (off > sh->sh_rawptr) { + errno = EIO; + return (-1); + } + if (off < sh->sh_rawptr) { + r = sh->sh_rawptr - off; + for (; r > 0; r -= s) { + s = r > sizeof(tmp) ? sizeof(tmp) : r; + if (read(pe->pe_fd, tmp, s) != + (ssize_t) s) { + errno = EIO; + return (-1); + } + } + } + } + + /* Load the section content. */ + if (libpe_load_section(pe, ps) < 0) + return (-1); + } + + return (0); +} + +int +libpe_resync_sections(PE *pe, off_t off) +{ + PE_Scn *ps; + PE_SecHdr *sh; + size_t falign, nsec; + + /* Firstly, sort all sections by their file offsets. */ + sort_sections(pe); + + /* Count the number of sections. */ + nsec = 0; + STAILQ_FOREACH(ps, &pe->pe_scn, ps_next) { + if (ps->ps_flags & LIBPE_F_STRIP_SECTION) + continue; + if (ps->ps_ndx & 0xFFFF0000U) + continue; + nsec++; + } + pe->pe_nscn = nsec; + + /* + * Calculate the file offset for the first section. (`off' is + * currently pointing to the COFF header.) + */ + off += sizeof(PE_CoffHdr); + if (pe->pe_ch != NULL && pe->pe_ch->ch_optsize > 0) + off += pe->pe_ch->ch_optsize; + else { + switch (pe->pe_obj) { + case PE_O_PE32: + off += PE_COFF_OPT_SIZE_32; + break; + case PE_O_PE32P: + off += PE_COFF_OPT_SIZE_32P; + break; + case PE_O_COFF: + default: + break; + } + } + off += nsec * sizeof(PE_SecHdr); + + /* + * Determine the file alignment for sections. + */ + if (pe->pe_oh != NULL && pe->pe_oh->oh_filealign > 0) + falign = pe->pe_oh->oh_filealign; + else { + /* + * Use the default file alignment defined by the + * PE/COFF specification. + */ + if (pe->pe_obj == PE_O_COFF) + falign = 4; + else + falign = 512; + } + + /* + * Step through each section (and pseduo section) and verify + * alignment constraint and overlapping, make adjustment if need. + */ + pe->pe_rvamax = 0; + STAILQ_FOREACH(ps, &pe->pe_scn, ps_next) { + if (ps->ps_flags & LIBPE_F_STRIP_SECTION) + continue; + + sh = &ps->ps_sh; + + if (sh->sh_addr + sh->sh_virtsize > pe->pe_rvamax) + pe->pe_rvamax = sh->sh_addr + sh->sh_virtsize; + + if (ps->ps_ndx & 0xFFFF0000U) + ps->ps_falign = 4; + else + ps->ps_falign = falign; + + off = roundup(off, ps->ps_falign); + + if (off != sh->sh_rawptr) + ps->ps_flags |= PE_F_DIRTY; + + if (ps->ps_flags & PE_F_DIRTY) { + if ((ps->ps_flags & LIBPE_F_LOAD_SECTION) == 0) { + if (libpe_load_section(pe, ps) < 0) + return (-1); + } + sh->sh_rawsize = libpe_resync_buffers(ps); + } + + /* + * Sections only contains uninitialized data should set + * PointerToRawData to zero according to the PE/COFF + * specification. + */ + if (sh->sh_rawsize == 0) + sh->sh_rawptr = 0; + else + sh->sh_rawptr = off; + + off += sh->sh_rawsize; + } + + return (0); +} + +off_t +libpe_write_section_headers(PE *pe, off_t off) +{ + char tmp[sizeof(PE_SecHdr)], *hdr; + PE_Scn *ps; + PE_SecHdr *sh; + + if (pe->pe_flags & LIBPE_F_BAD_SEC_HEADER || pe->pe_nscn == 0) + return (off); + + if ((pe->pe_flags & LIBPE_F_DIRTY_SEC_HEADER) == 0) { + off += sizeof(PE_SecHdr) * pe->pe_ch->ch_nsec; + return (off); + } + + STAILQ_FOREACH(ps, &pe->pe_scn, ps_next) { + if (ps->ps_flags & LIBPE_F_STRIP_SECTION) + continue; + if (ps->ps_ndx & 0xFFFF0000U) + continue; + if ((pe->pe_flags & LIBPE_F_DIRTY_SEC_HEADER) == 0 && + (ps->ps_flags & PE_F_DIRTY) == 0) + goto next_header; + + sh = &ps->ps_sh; + + memcpy(tmp, sh->sh_name, sizeof(sh->sh_name)); + hdr = tmp + 8; + PE_WRITE32(hdr, sh->sh_virtsize); + PE_WRITE32(hdr, sh->sh_addr); + PE_WRITE32(hdr, sh->sh_rawsize); + PE_WRITE32(hdr, sh->sh_rawptr); + PE_WRITE32(hdr, sh->sh_relocptr); + PE_WRITE32(hdr, sh->sh_lineptr); + PE_WRITE16(hdr, sh->sh_nreloc); + PE_WRITE16(hdr, sh->sh_nline); + PE_WRITE32(hdr, sh->sh_char); + + if (write(pe->pe_fd, tmp, sizeof(PE_SecHdr)) != + (ssize_t) sizeof(PE_SecHdr)) { + errno = EIO; + return (-1); + } + + next_header: + off += sizeof(PE_SecHdr); + } + + return (off); +} + +off_t +libpe_write_sections(PE *pe, off_t off) +{ + PE_Scn *ps; + PE_SecHdr *sh; + + if (pe->pe_flags & LIBPE_F_BAD_SEC_HEADER) + return (off); + + STAILQ_FOREACH(ps, &pe->pe_scn, ps_next) { + sh = &ps->ps_sh; + + if (ps->ps_flags & LIBPE_F_STRIP_SECTION) + continue; + + /* Skip empty sections. */ + if (sh->sh_rawptr == 0 || sh->sh_rawsize == 0) + continue; + + /* + * Padding between sections. (padding always written + * in case the the section headers or sections are + * moved or shrinked.) + */ + assert(off <= sh->sh_rawptr); + if (off < sh->sh_rawptr) + libpe_pad(pe, sh->sh_rawptr - off); + + if ((ps->ps_flags & PE_F_DIRTY) == 0) { + assert((pe->pe_flags & LIBPE_F_SPECIAL_FILE) == 0); + if (lseek(pe->pe_fd, + (off_t) (sh->sh_rawptr + sh->sh_rawsize), + SEEK_SET) < 0) { + errno = EIO; + return (-1); + } + off = sh->sh_rawptr + sh->sh_rawsize; + continue; + } + + off = sh->sh_rawptr; + + if (libpe_write_buffers(ps) < 0) + return (-1); + + off += sh->sh_rawsize; + + ps->ps_flags &= ~PE_F_DIRTY; + } + + return (off); +} diff --git a/contrib/elftoolchain/libpe/libpe_utils.c b/contrib/elftoolchain/libpe/libpe_utils.c new file mode 100644 index 0000000..9bc9a54 --- /dev/null +++ b/contrib/elftoolchain/libpe/libpe_utils.c @@ -0,0 +1,69 @@ +/*- + * Copyright (c) 2016 Kai Wang + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include <sys/param.h> +#include <assert.h> +#include <errno.h> +#include <string.h> +#include <unistd.h> + +#include "_libpe.h" + +ELFTC_VCSID("$Id: libpe_utils.c 3312 2016-01-10 09:23:51Z kaiwang27 $"); + +off_t +libpe_align(PE *pe, off_t off, size_t align) +{ + off_t n; + + assert(align > 0 && (align & (align - 1)) == 0); + + n = roundup(off, align); + if (n > off) { + if (libpe_pad(pe, n - off) < 0) + return (-1); + } + + return (n); +} + +int +libpe_pad(PE *pe, size_t pad) +{ + char tmp[128]; + size_t s; + + memset(tmp, 0, sizeof(tmp)); + for (; pad > 0; pad -= s) { + s = pad > sizeof(tmp) ? sizeof(tmp) : pad; + if (write(pe->pe_fd, tmp, s) != (ssize_t) s) { + errno = EIO; + return (-1); + } + } + + return (0); +} diff --git a/contrib/elftoolchain/libpe/os.Linux.mk b/contrib/elftoolchain/libpe/os.Linux.mk new file mode 100644 index 0000000..ed5bdf0 --- /dev/null +++ b/contrib/elftoolchain/libpe/os.Linux.mk @@ -0,0 +1,6 @@ +# $Id: os.Linux.mk 3312 2016-01-10 09:23:51Z kaiwang27 $ + +CFLAGS+= -Wall -Wno-unused-parameter -Wstrict-prototypes \ + -Wmissing-prototypes -Wpointer-arith -Wreturn-type \ + -Wcast-qual -Wwrite-strings -Wswitch -Wshadow \ + -Wcast-align -Wunused-parameter diff --git a/contrib/elftoolchain/libpe/os.NetBSD.mk b/contrib/elftoolchain/libpe/os.NetBSD.mk new file mode 100644 index 0000000..ae214e3 --- /dev/null +++ b/contrib/elftoolchain/libpe/os.NetBSD.mk @@ -0,0 +1,2 @@ +# TODO(#511): Revert after the source tree is -Wconversion clean. +WARNS=5 diff --git a/contrib/elftoolchain/libpe/pe.h b/contrib/elftoolchain/libpe/pe.h new file mode 100644 index 0000000..5b6130e --- /dev/null +++ b/contrib/elftoolchain/libpe/pe.h @@ -0,0 +1,292 @@ +/*- + * Copyright (c) 2015 Kai Wang + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $Id: pe.h 3312 2016-01-10 09:23:51Z kaiwang27 $ + */ + +#ifndef _PE_H_ +#define _PE_H_ + +#include <stdint.h> + +/* + * MS-DOS header. + */ + +typedef struct _PE_DosHdr { + char dh_magic[2]; + uint16_t dh_lastsize; + uint16_t dh_nblock; + uint16_t dh_nreloc; + uint16_t dh_hdrsize; + uint16_t dh_minalloc; + uint16_t dh_maxalloc; + uint16_t dh_ss; + uint16_t dh_sp; + uint16_t dh_checksum; + uint16_t dh_ip; + uint16_t dh_cs; + uint16_t dh_relocpos; + uint16_t dh_noverlay; + uint16_t dh_reserved1[4]; + uint16_t dh_oemid; + uint16_t dh_oeminfo; + uint16_t dh_reserved2[10]; + uint32_t dh_lfanew; +} PE_DosHdr; + +/* + * Rich header. + */ + +typedef struct _PE_RichHdr { + uint32_t rh_xor; + uint32_t rh_total; + uint32_t *rh_compid; + uint32_t *rh_cnt; +} PE_RichHdr; + +/* + * COFF header: Machine Types. + */ + +#define IMAGE_FILE_MACHINE_UNKNOWN 0x0 /* not specified */ +#define IMAGE_FILE_MACHINE_AM33 0x1d3 /* Matsushita AM33 */ +#define IMAGE_FILE_MACHINE_AMD64 0x8664 /* x86-64 */ +#define IMAGE_FILE_MACHINE_ARM 0x1c0 /* ARM LE */ +#define IMAGE_FILE_MACHINE_ARMNT 0x1c4 /* ARMv7(or higher) Thumb */ +#define IMAGE_FILE_MACHINE_ARM64 0xaa64 /* ARMv8 64-bit */ +#define IMAGE_FILE_MACHINE_EBC 0xebc /* EFI byte code */ +#define IMAGE_FILE_MACHINE_I386 0x14c /* x86 */ +#define IMAGE_FILE_MACHINE_IA64 0x200 /* IA64 */ +#define IMAGE_FILE_MACHINE_M32R 0x9041 /* Mitsubishi M32R LE */ +#define IMAGE_FILE_MACHINE_MIPS16 0x266 /* MIPS16 */ +#define IMAGE_FILE_MACHINE_MIPSFPU 0x366 /* MIPS with FPU */ +#define IMAGE_FILE_MACHINE_MIPSFPU16 0x466 /* MIPS16 with FPU */ +#define IMAGE_FILE_MACHINE_POWERPC 0x1f0 /* Power PC LE */ +#define IMAGE_FILE_MACHINE_POWERPCFP 0x1f1 /* Power PC floating point */ +#define IMAGE_FILE_MACHINE_R4000 0x166 /* MIPS R4000 LE */ +#define IMAGE_FILE_MACHINE_SH3 0x1a2 /* Hitachi SH3 */ +#define IMAGE_FILE_MACHINE_SH3DSP 0x1a3 /* Hitachi SH3 DSP */ +#define IMAGE_FILE_MACHINE_SH4 0x1a6 /* Hitachi SH4 */ +#define IMAGE_FILE_MACHINE_SH5 0x1a8 /* Hitachi SH5 */ +#define IMAGE_FILE_MACHINE_THUMB 0x1c2 /* ARM or Thumb interworking */ +#define IMAGE_FILE_MACHINE_WCEMIPSV2 0x169 /* MIPS LE WCE v2 */ + +/* + * COFF header: Characteristics + */ + +#define IMAGE_FILE_RELOCS_STRIPPED 0x0001 +#define IMAGE_FILE_EXECUTABLE_IMAGE 0x0002 +#define IMAGE_FILE_LINE_NUMS_STRIPPED 0x0004 +#define IMAGE_FILE_LOCAL_SYMS_STRIPPED 0x0008 +#define IMAGE_FILE_AGGRESSIVE_WS_TRIM 0x0010 +#define IMAGE_FILE_LARGE_ADDRESS_AWARE 0x0020 +#define IMAGE_FILE_BYTES_REVERSED_LO 0x0080 +#define IMAGE_FILE_32BIT_MACHINE 0x0100 +#define IMAGE_FILE_DEBUG_STRIPPED 0x0200 +#define IMAGE_FILE_REMOVABLE_RUN_FROM_SWAP 0x0400 +#define IMAGE_FILE_NET_RUN_FROM_SWAP 0x0800 +#define IMAGE_FILE_SYSTEM 0x1000 +#define IMAGE_FILE_DLL 0x2000 +#define IMAGE_FILE_UP_SYSTEM_ONLY 0x4000 +#define IMAGE_FILE_BYTES_REVERSED_HI 0x8000 + +/* + * COFF Header. + */ + +typedef struct _PE_CoffHdr { + uint16_t ch_machine; + uint16_t ch_nsec; + uint32_t ch_timestamp; + uint32_t ch_symptr; + uint32_t ch_nsym; + uint16_t ch_optsize; + uint16_t ch_char; +} PE_CoffHdr; + + +/* + * Optional Header: Subsystem. + */ + +#define IMAGE_SUBSYSTEM_UNKNOWN 0 +#define IMAGE_SUBSYSTEM_NATIVE 1 +#define IMAGE_SUBSYSTEM_WINDOWS_GUI 2 +#define IMAGE_SUBSYSTEM_WINDOWS_CUI 3 +#define IMAGE_SUBSYSTEM_POSIX_CUI 7 +#define IMAGE_SUBSYSTEM_WINDOWS_CE_GUI 9 +#define IMAGE_SUBSYSTEM_EFI_APPLICATION 10 +#define IMAGE_SUBSYSTEM_EFI_BOOT_SERVICE_DRIVER 11 +#define IMAGE_SUBSYSTEM_EFI_RUNTIME_DRIVER 12 +#define IMAGE_SUBSYSTEM_EFI_ROM 13 +#define IMAGE_SUBSYSTEM_XBOX 14 + +/* + * Optional Header: DLL Characteristics + */ + +#define IMAGE_DLL_CHARACTERISTICS_DYNAMIC_BASE 0x0040 +#define IMAGE_DLL_CHARACTERISTICS_FORCE_INTEGRITY 0x0080 +#define IMAGE_DLL_CHARACTERISTICS_NX_COMPAT 0x0100 +#define IMAGE_DLL_CHARACTERISTICS_NO_ISOLATION 0x0200 +#define IMAGE_DLL_CHARACTERISTICS_NO_SEH 0x0400 +#define IMAGE_DLL_CHARACTERISTICS_NO_BIND 0x0800 +#define IMAGE_DLL_CHARACTERISTICS_WDM_DRIVER 0x2000 +#define IMAGE_DLL_CHARACTERISTICS_TERMINAL_SERVER_AWARE 0x8000 + +/* + * Optional Header. + */ + +#define PE_FORMAT_ROM 0x107 +#define PE_FORMAT_32 0x10b +#define PE_FORMAT_32P 0x20b + +typedef struct _PE_OptHdr { + uint16_t oh_magic; + uint8_t oh_ldvermajor; + uint8_t oh_ldverminor; + uint32_t oh_textsize; + uint32_t oh_datasize; + uint32_t oh_bsssize; + uint32_t oh_entry; + uint32_t oh_textbase; + uint32_t oh_database; + uint64_t oh_imgbase; + uint32_t oh_secalign; + uint32_t oh_filealign; + uint16_t oh_osvermajor; + uint16_t oh_osverminor; + uint16_t oh_imgvermajor; + uint16_t oh_imgverminor; + uint16_t oh_subvermajor; + uint16_t oh_subverminor; + uint32_t oh_win32ver; + uint32_t oh_imgsize; + uint32_t oh_hdrsize; + uint32_t oh_checksum; + uint16_t oh_subsystem; + uint16_t oh_dllchar; + uint64_t oh_stacksizer; + uint64_t oh_stacksizec; + uint64_t oh_heapsizer; + uint64_t oh_heapsizec; + uint32_t oh_ldrflags; + uint32_t oh_ndatadir; +} PE_OptHdr; + +/* + * Optional Header: Data Directories. + */ + +#define PE_DD_EXPORT 0 +#define PE_DD_IMPORT 1 +#define PE_DD_RESROUCE 2 +#define PE_DD_EXCEPTION 3 +#define PE_DD_CERTIFICATE 4 +#define PE_DD_BASERELOC 5 +#define PE_DD_DEBUG 6 +#define PE_DD_ARCH 7 +#define PE_DD_GLOBALPTR 8 +#define PE_DD_TLS 9 +#define PE_DD_LOADCONFIG 10 +#define PE_DD_BOUNDIMPORT 11 +#define PE_DD_IAT 12 +#define PE_DD_DELAYIMPORT 13 +#define PE_DD_CLRRUNTIME 14 +#define PE_DD_RESERVED 15 +#define PE_DD_MAX 16 + +typedef struct _PE_DataDirEntry { + uint32_t de_addr; + uint32_t de_size; +} PE_DataDirEntry; + +typedef struct _PE_DataDir { + PE_DataDirEntry dd_e[PE_DD_MAX]; + uint32_t dd_total; +} PE_DataDir; + +/* + * Section Headers: Section flags. + */ + +#define IMAGE_SCN_TYPE_NO_PAD 0x00000008 +#define IMAGE_SCN_CNT_CODE 0x00000020 +#define IMAGE_SCN_CNT_INITIALIZED_DATA 0x00000040 +#define IMAGE_SCN_CNT_UNINITIALIZED_DATA 0x00000080 +#define IMAGE_SCN_LNK_OTHER 0x00000100 +#define IMAGE_SCN_LNK_INFO 0x00000200 +#define IMAGE_SCN_LNK_REMOVE 0x00000800 +#define IMAGE_SCN_LNK_COMDAT 0x00001000 +#define IMAGE_SCN_GPREL 0x00008000 +#define IMAGE_SCN_MEM_PURGEABLE 0x00020000 +#define IMAGE_SCN_MEM_16BIT 0x00020000 +#define IMAGE_SCN_MEM_LOCKED 0x00040000 +#define IMAGE_SCN_MEM_PRELOAD 0x00080000 +#define IMAGE_SCN_ALIGN_1BYTES 0x00100000 +#define IMAGE_SCN_ALIGN_2BYTES 0x00200000 +#define IMAGE_SCN_ALIGN_4BYTES 0x00300000 +#define IMAGE_SCN_ALIGN_8BYTES 0x00400000 +#define IMAGE_SCN_ALIGN_16BYTES 0x00500000 +#define IMAGE_SCN_ALIGN_32BYTES 0x00600000 +#define IMAGE_SCN_ALIGN_64BYTES 0x00700000 +#define IMAGE_SCN_ALIGN_128BYTES 0x00800000 +#define IMAGE_SCN_ALIGN_256BYTES 0x00900000 +#define IMAGE_SCN_ALIGN_512BYTES 0x00A00000 +#define IMAGE_SCN_ALIGN_1024BYTES 0x00B00000 +#define IMAGE_SCN_ALIGN_2048BYTES 0x00C00000 +#define IMAGE_SCN_ALIGN_4096BYTES 0x00D00000 +#define IMAGE_SCN_ALIGN_8192BYTES 0x00E00000 +#define IMAGE_SCN_LNK_NRELOC_OVFL 0x01000000 +#define IMAGE_SCN_MEM_DISCARDABLE 0x02000000 +#define IMAGE_SCN_MEM_NOT_CACHED 0x04000000 +#define IMAGE_SCN_MEM_NOT_PAGED 0x08000000 +#define IMAGE_SCN_MEM_SHARED 0x10000000 +#define IMAGE_SCN_MEM_EXECUTE 0x20000000 +#define IMAGE_SCN_MEM_READ 0x40000000 +#define IMAGE_SCN_MEM_WRITE 0x80000000 + +/* + * Section Headers. + */ + +typedef struct _PE_SecHdr { + char sh_name[8]; + uint32_t sh_virtsize; + uint32_t sh_addr; + uint32_t sh_rawsize; + uint32_t sh_rawptr; + uint32_t sh_relocptr; + uint32_t sh_lineptr; + uint16_t sh_nreloc; + uint16_t sh_nline; + uint32_t sh_char; +} PE_SecHdr; + +#endif /* !_PE_H_ */ diff --git a/contrib/elftoolchain/libpe/pe_buffer.c b/contrib/elftoolchain/libpe/pe_buffer.c new file mode 100644 index 0000000..e4ac19f --- /dev/null +++ b/contrib/elftoolchain/libpe/pe_buffer.c @@ -0,0 +1,100 @@ +/*- + * Copyright (c) 2016 Kai Wang + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include <errno.h> + +#include "_libpe.h" + +ELFTC_VCSID("$Id: pe_buffer.c 3312 2016-01-10 09:23:51Z kaiwang27 $"); + +PE_Buffer * +pe_getbuffer(PE_Scn *ps, PE_Buffer *pb) +{ + PE *pe; + PE_SecBuf *sb; + + if (ps == NULL) { + errno = EINVAL; + return (NULL); + } + + pe = ps->ps_pe; + + if ((ps->ps_flags & LIBPE_F_LOAD_SECTION) == 0) { + if (pe->pe_flags & LIBPE_F_FD_DONE) { + errno = EACCES; + return (NULL); + } + if (pe->pe_flags & LIBPE_F_SPECIAL_FILE) { + if (libpe_load_all_sections(pe) < 0) + return (NULL); + } else { + if (libpe_load_section(pe, ps) < 0) + return (NULL); + } + } + + sb = (PE_SecBuf *) pb; + + if (sb == NULL) + sb = STAILQ_FIRST(&ps->ps_b); + else + sb = STAILQ_NEXT(sb, sb_next); + + return ((PE_Buffer *) sb); +} + +PE_Buffer * +pe_newbuffer(PE_Scn *ps) +{ + PE *pe; + PE_SecBuf *sb; + + if (ps == NULL) { + errno = EINVAL; + return (NULL); + } + + pe = ps->ps_pe; + + if (pe->pe_flags & LIBPE_F_FD_DONE) { + errno = EACCES; + return (NULL); + } + + if ((ps->ps_flags & LIBPE_F_LOAD_SECTION) == 0) { + if (libpe_load_section(pe, ps) < 0) + return (NULL); + } + + if ((sb = libpe_alloc_buffer(ps, 0)) == NULL) + return (NULL); + + sb->sb_flags |= PE_F_DIRTY; + ps->ps_flags |= PE_F_DIRTY; + + return ((PE_Buffer *) sb); +} diff --git a/contrib/elftoolchain/libpe/pe_cntl.c b/contrib/elftoolchain/libpe/pe_cntl.c new file mode 100644 index 0000000..1fc8c47 --- /dev/null +++ b/contrib/elftoolchain/libpe/pe_cntl.c @@ -0,0 +1,62 @@ +/*- + * Copyright (c) 2016 Kai Wang + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include <errno.h> + +#include "_libpe.h" + +ELFTC_VCSID("$Id: pe_cntl.c 3312 2016-01-10 09:23:51Z kaiwang27 $"); + +int +pe_cntl(PE *pe, PE_Cmd cmd) +{ + + if (pe == NULL) { + errno = EINVAL; + return (-1); + } + + switch (cmd) { + case PE_C_FDDONE: + pe->pe_flags |= LIBPE_F_FD_DONE; + break; + + case PE_C_FDREAD: + if (pe->pe_cmd == PE_C_WRITE) { + errno = EACCES; + return (-1); + } + if (libpe_load_all_sections(pe) < 0) + return (-1); + break; + + default: + errno = EINVAL; + return (-1); + } + + return (0); +} diff --git a/contrib/elftoolchain/libpe/pe_coff.c b/contrib/elftoolchain/libpe/pe_coff.c new file mode 100644 index 0000000..d5cd833 --- /dev/null +++ b/contrib/elftoolchain/libpe/pe_coff.c @@ -0,0 +1,157 @@ +/*- + * Copyright (c) 2015 Kai Wang + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include <errno.h> +#include <stdlib.h> +#include <string.h> + +#include "_libpe.h" + +ELFTC_VCSID("$Id: pe_coff.c 3312 2016-01-10 09:23:51Z kaiwang27 $"); + +PE_CoffHdr * +pe_coff_header(PE *pe) +{ + + if (pe->pe_ch == NULL) { + errno = ENOENT; + return (NULL); + } + + return (pe->pe_ch); +} + +PE_OptHdr * +pe_opt_header(PE *pe) +{ + + if (pe->pe_oh == NULL) { + errno = ENOENT; + return (NULL); + } + + return (pe->pe_oh); +} + +PE_DataDir * +pe_data_dir(PE *pe) +{ + + if (pe->pe_dd == NULL) { + errno = ENOENT; + return (NULL); + } + + return (pe->pe_dd); +} + +int +pe_update_coff_header(PE *pe, PE_CoffHdr *ch) +{ + + if (pe == NULL || ch == NULL) { + errno = EINVAL; + return (-1); + } + + if (pe->pe_cmd == PE_C_READ || pe->pe_flags & LIBPE_F_FD_DONE) { + errno = EACCES; + return (-1); + } + + if (pe->pe_ch == NULL) { + if ((pe->pe_ch = malloc(sizeof(PE_CoffHdr))) == NULL) { + errno = ENOMEM; + return (-1); + } + } else { + /* Rewrite optional header if `optsize' field changed. */ + if (pe->pe_ch->ch_optsize != ch->ch_optsize) + pe->pe_flags |= LIBPE_F_DIRTY_OPT_HEADER; + } + + *pe->pe_ch = *ch; + + pe->pe_flags |= LIBPE_F_DIRTY_COFF_HEADER; + + return (0); +} + +int +pe_update_opt_header(PE *pe, PE_OptHdr *oh) +{ + + if (pe == NULL || oh == NULL) { + errno = EINVAL; + return (-1); + } + + if (pe->pe_cmd == PE_C_READ || pe->pe_flags & LIBPE_F_FD_DONE) { + errno = EACCES; + return (-1); + } + + if (pe->pe_oh == NULL) { + if ((pe->pe_oh = malloc(sizeof(PE_OptHdr))) == NULL) { + errno = ENOMEM; + return (-1); + } + } + + *pe->pe_oh = *oh; + + pe->pe_flags |= LIBPE_F_DIRTY_OPT_HEADER; + + return (0); +} + +int +pe_update_data_dir(PE *pe, PE_DataDir *dd) +{ + + if (pe == NULL || dd == NULL) { + errno = EINVAL; + return (-1); + } + + if (pe->pe_cmd == PE_C_READ || pe->pe_flags & LIBPE_F_FD_DONE) { + errno = EACCES; + return (-1); + } + + if (pe->pe_dd == NULL) { + if ((pe->pe_dd = malloc(sizeof(PE_DataDir))) == NULL) { + errno = ENOMEM; + return (-1); + } + } + + *pe->pe_dd = *dd; + + pe->pe_flags |= LIBPE_F_DIRTY_OPT_HEADER; + + return (0); +} diff --git a/contrib/elftoolchain/libpe/pe_dos.c b/contrib/elftoolchain/libpe/pe_dos.c new file mode 100644 index 0000000..01ba42f --- /dev/null +++ b/contrib/elftoolchain/libpe/pe_dos.c @@ -0,0 +1,119 @@ +/*- + * Copyright (c) 2015 Kai Wang + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include <assert.h> +#include <errno.h> +#include <stdlib.h> +#include <string.h> + +#include "_libpe.h" + +ELFTC_VCSID("$Id: pe_dos.c 3312 2016-01-10 09:23:51Z kaiwang27 $"); + +PE_DosHdr * +pe_msdos_header(PE *pe) +{ + + if (pe == NULL) { + errno = EINVAL; + return (NULL); + } + + if (pe->pe_dh == NULL) { + errno = ENOENT; + return (NULL); + } + + return (pe->pe_dh); +} + +char * +pe_msdos_stub(PE *pe, size_t *len) +{ + + if (pe == NULL || len == NULL) { + errno = EINVAL; + return (NULL); + } + + if (pe->pe_stub_ex > 0 && + (pe->pe_flags & LIBPE_F_LOAD_DOS_STUB) == 0) { + assert((pe->pe_flags & LIBPE_F_SPECIAL_FILE) == 0); + (void) libpe_read_msdos_stub(pe); + } + + *len = sizeof(PE_DosHdr) + pe->pe_stub_ex; + + return (pe->pe_stub); +} + +int +ps_update_msdos_header(PE *pe, PE_DosHdr *dh) +{ + + if (pe == NULL || dh == NULL) { + errno = EINVAL; + return (-1); + } + + if (pe->pe_cmd == PE_C_READ || pe->pe_flags & LIBPE_F_FD_DONE) { + errno = EACCES; + return (-1); + } + + if (pe->pe_dh == NULL) { + if ((pe->pe_dh = malloc(sizeof(PE_DosHdr))) == NULL) { + errno = ENOMEM; + return (-1); + } + } + + *pe->pe_dh = *dh; + + pe->pe_flags |= LIBPE_F_DIRTY_DOS_HEADER; + + return (0); +} + +int +ps_update_msdos_stub(PE *pe, char *dos_stub, size_t sz) +{ + + if (pe == NULL || dos_stub == NULL || sz == 0) { + errno = EINVAL; + return (-1); + } + + if (pe->pe_cmd == PE_C_READ || pe->pe_flags & LIBPE_F_FD_DONE) { + errno = EACCES; + return (-1); + } + + pe->pe_stub_app = dos_stub; + pe->pe_stub_app_sz = sz; + + return (0); +} diff --git a/contrib/elftoolchain/libpe/pe_flag.c b/contrib/elftoolchain/libpe/pe_flag.c new file mode 100644 index 0000000..c392a4d --- /dev/null +++ b/contrib/elftoolchain/libpe/pe_flag.c @@ -0,0 +1,187 @@ +/*- + * Copyright (c) 2016 Kai Wang + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include <errno.h> + +#include "_libpe.h" + +ELFTC_VCSID("$Id: pe_flag.c 3312 2016-01-10 09:23:51Z kaiwang27 $"); + +int +pe_flag(PE *pe, PE_Cmd c, unsigned int flags) +{ + + if (pe == NULL || (c != PE_C_SET && c != PE_C_CLR)) { + errno = EINVAL; + return (-1); + } + + if ((flags & ~(PE_F_STRIP_DOS_STUB | PE_F_STRIP_RICH_HEADER | + PE_F_STRIP_SYMTAB | PE_F_STRIP_DEBUG)) != 0) { + errno = EINVAL; + return (-1); + } + + if (c == PE_C_SET) + pe->pe_flags |= flags; + else + pe->pe_flags &= ~flags; + + return (0); +} + +int +pe_flag_dos_header(PE *pe, PE_Cmd c, unsigned int flags) +{ + + if (pe == NULL || (c != PE_C_SET && c != PE_C_CLR) || + (flags & ~PE_F_DIRTY) != 0) { + errno = EINVAL; + return (-1); + } + + if (c == PE_C_SET) + pe->pe_flags |= LIBPE_F_DIRTY_DOS_HEADER; + else + pe->pe_flags &= ~LIBPE_F_DIRTY_DOS_HEADER; + + return (0); +} + +int +pe_flag_coff_header(PE *pe, PE_Cmd c, unsigned int flags) +{ + + if (pe == NULL || (c != PE_C_SET && c != PE_C_CLR) || + (flags & ~PE_F_DIRTY) != 0) { + errno = EINVAL; + return (-1); + } + + if (c == PE_C_SET) + pe->pe_flags |= LIBPE_F_DIRTY_COFF_HEADER; + else + pe->pe_flags &= ~LIBPE_F_DIRTY_COFF_HEADER; + + return (0); +} + +int +pe_flag_opt_header(PE *pe, PE_Cmd c, unsigned int flags) +{ + + if (pe == NULL || (c != PE_C_SET && c != PE_C_CLR) || + (flags & ~PE_F_DIRTY) != 0) { + errno = EINVAL; + return (-1); + } + + if (c == PE_C_SET) + pe->pe_flags |= LIBPE_F_DIRTY_OPT_HEADER; + else + pe->pe_flags &= ~LIBPE_F_DIRTY_OPT_HEADER; + + return (0); +} + +int +pe_flag_data_dir(PE *pe, PE_Cmd c, unsigned int flags) +{ + + if (pe == NULL || (c != PE_C_SET && c != PE_C_CLR) || + (flags & ~PE_F_DIRTY) != 0) { + errno = EINVAL; + return (-1); + } + + if (c == PE_C_SET) + pe->pe_flags |= LIBPE_F_DIRTY_OPT_HEADER; + else + pe->pe_flags &= ~LIBPE_F_DIRTY_OPT_HEADER; + + return (0); +} + +int +pe_flag_scn(PE_Scn *ps, PE_Cmd c, unsigned int flags) +{ + + if (ps == NULL || (c != PE_C_SET && c != PE_C_CLR) || + (flags & ~(PE_F_DIRTY | PE_F_STRIP_SECTION)) == 0) { + errno = EINVAL; + return (-1); + } + + if (c == PE_C_SET) + ps->ps_flags |= flags; + else + ps->ps_flags &= ~flags; + + return (0); +} + +int +pe_flag_section_header(PE_Scn *ps, PE_Cmd c, unsigned int flags) +{ + PE *pe; + + if (ps == NULL || (c != PE_C_SET && c != PE_C_CLR) || + (flags & ~PE_F_DIRTY) != 0) { + errno = EINVAL; + return (-1); + } + + pe = ps->ps_pe; + + /* The library doesn't support per section header dirty flag. */ + if (c == PE_C_SET) + pe->pe_flags |= LIBPE_F_DIRTY_SEC_HEADER; + else + pe->pe_flags &= ~LIBPE_F_DIRTY_SEC_HEADER; + + return (0); +} + +int +pe_flag_buffer(PE_Buffer *pb, PE_Cmd c, unsigned int flags) +{ + PE_SecBuf *sb; + + if (pb == NULL || (c != PE_C_SET && c != PE_C_CLR) || + (flags & ~PE_F_DIRTY) != 0) { + errno = EINVAL; + return (-1); + } + + sb = (PE_SecBuf *) pb; + + if (c == PE_C_SET) + sb->sb_flags |= flags; + else + sb->sb_flags &= ~flags; + + return (0); +} diff --git a/contrib/elftoolchain/libpe/pe_init.c b/contrib/elftoolchain/libpe/pe_init.c new file mode 100644 index 0000000..4e2f22a --- /dev/null +++ b/contrib/elftoolchain/libpe/pe_init.c @@ -0,0 +1,95 @@ +/*- + * Copyright (c) 2015 Kai Wang + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include <sys/queue.h> +#include <errno.h> +#include <stdlib.h> + +#include "_libpe.h" + +ELFTC_VCSID("$Id: pe_init.c 3312 2016-01-10 09:23:51Z kaiwang27 $"); + +PE * +pe_init(int fd, PE_Cmd c, PE_Object o) +{ + PE *pe; + + if ((pe = calloc(1, sizeof(*pe))) == NULL) { + errno = ENOMEM; + return (NULL); + } + pe->pe_fd = fd; + pe->pe_cmd = c; + pe->pe_obj = o; + STAILQ_INIT(&pe->pe_scn); + + switch (c) { + case PE_C_READ: + case PE_C_RDWR: + if (libpe_open_object(pe) < 0) + goto init_fail; + break; + + case PE_C_WRITE: + if (o < PE_O_PE32 || o > PE_O_COFF) { + errno = EINVAL; + goto init_fail; + } + break; + + default: + errno = EINVAL; + goto init_fail; + } + + return (pe); + +init_fail: + pe_finish(pe); + return (NULL); +} + +void +pe_finish(PE *pe) +{ + + if (pe == NULL) + return; + + libpe_release_object(pe); +} + +PE_Object +pe_object(PE *pe) +{ + + if (pe == NULL) { + errno = EINVAL; + return (PE_O_UNKNOWN); + } + + return (pe->pe_obj); +} diff --git a/contrib/elftoolchain/libpe/pe_rich.c b/contrib/elftoolchain/libpe/pe_rich.c new file mode 100644 index 0000000..ea1029e --- /dev/null +++ b/contrib/elftoolchain/libpe/pe_rich.c @@ -0,0 +1,107 @@ +/*- + * Copyright (c) 2016 Kai Wang + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include <assert.h> +#include <errno.h> + +#include "_libpe.h" + +ELFTC_VCSID("$Id: pe_rich.c 3312 2016-01-10 09:23:51Z kaiwang27 $"); + +PE_RichHdr * +pe_rich_header(PE *pe) +{ + + if (pe == NULL) { + errno = EINVAL; + return (NULL); + } + + if (pe->pe_rh == NULL && pe->pe_stub_ex > 0 && + (pe->pe_flags & LIBPE_F_LOAD_DOS_STUB) == 0) { + assert((pe->pe_flags & LIBPE_F_SPECIAL_FILE) == 0); + (void) libpe_read_msdos_stub(pe); + } + + if (pe->pe_rh == NULL) { + errno = ENOENT; + return (NULL); + } + + return (pe->pe_rh); +} + +static uint32_t +rol32(uint32_t n, int c) +{ + + c &= 0x1f; + + return ((n << c) | (n >> (0x20 - c))); +} + +int +pe_rich_header_validate(PE *pe) +{ + PE_RichHdr *rh; + uint32_t cksum; + char *p; + int i, off; + + if (pe_rich_header(pe) == NULL) + return (-1); + + assert(pe->pe_rh_start != NULL); + + /* + * Initial value of the checksum is the offset to the begin of + * the Rich header. + */ + cksum = pe->pe_rh_start - pe->pe_stub; + + /* + * Add the bytes before the Rich header to the checksum, rotated + * left by the offset. + */ + for (p = pe->pe_stub; p < pe->pe_rh_start; p++) { + /* Skip dh_lfanew. */ + off = p - pe->pe_stub; + if (off >= 0x3c && off < 0x40) + continue; + cksum += rol32((unsigned char) *p, off); + } + + /* Add each compid rotated left by its count to the checksum. */ + rh = pe->pe_rh; + for (i = 0; (uint32_t) i < rh->rh_total; i++) + cksum += rol32(rh->rh_compid[i], rh->rh_cnt[i]); + + /* Validate the checksum with the XOR mask stored after "Rich". */ + if (cksum == rh->rh_xor) + return (1); + + return (0); +} diff --git a/contrib/elftoolchain/libpe/pe_section.c b/contrib/elftoolchain/libpe/pe_section.c new file mode 100644 index 0000000..3e82d84 --- /dev/null +++ b/contrib/elftoolchain/libpe/pe_section.c @@ -0,0 +1,213 @@ +/*- + * Copyright (c) 2016 Kai Wang + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include <errno.h> +#include <string.h> + +#include "_libpe.h" + +ELFTC_VCSID("$Id: pe_section.c 3312 2016-01-10 09:23:51Z kaiwang27 $"); + +PE_Scn * +pe_getscn(PE *pe, size_t ndx) +{ + PE_Scn *ps; + + if (pe == NULL || ndx < 1 || ndx > 0xFFFFU) { + errno = EINVAL; + return (NULL); + } + + STAILQ_FOREACH(ps, &pe->pe_scn, ps_next) { + if (ps->ps_ndx == ndx) + return (ps); + } + + errno = ENOENT; + + return (NULL); +} + +size_t +pe_ndxscn(PE_Scn *ps) +{ + + if (ps == NULL) { + errno = EINVAL; + return (0); + } + + return (ps->ps_ndx); +} + +PE_Scn * +pe_nextscn(PE *pe, PE_Scn *ps) +{ + + if (pe == NULL) { + errno = EINVAL; + return (NULL); + } + + if (ps == NULL) + ps = STAILQ_FIRST(&pe->pe_scn); + else + ps = STAILQ_NEXT(ps, ps_next); + + while (ps != NULL) { + if (ps->ps_ndx >= 1 && ps->ps_ndx <= 0xFFFFU) + return (ps); + ps = STAILQ_NEXT(ps, ps_next); + } + + return (NULL); +} + +PE_Scn * +pe_newscn(PE *pe) +{ + PE_Scn *ps, *tps, *_tps; + + if (pe == NULL) { + errno = EINVAL; + return (NULL); + } + + if (pe->pe_cmd == PE_C_READ || pe->pe_flags & LIBPE_F_FD_DONE) { + errno = EACCES; + return (NULL); + } + + if ((ps = libpe_alloc_scn(pe)) == NULL) + return (NULL); + + if (pe->pe_flags & LIBPE_F_BAD_SEC_HEADER) { + STAILQ_FOREACH_SAFE(tps, &pe->pe_scn, ps_next, _tps) + libpe_release_scn(tps); + pe->pe_flags &= ~LIBPE_F_BAD_SEC_HEADER; + } + + STAILQ_INSERT_TAIL(&pe->pe_scn, ps, ps_next); + + ps->ps_flags |= PE_F_DIRTY | LIBPE_F_LOAD_SECTION; + pe->pe_flags |= LIBPE_F_DIRTY_SEC_HEADER; + + return (ps); +} + +PE_Scn * +pe_insertscn(PE *pe, size_t ndx) +{ + PE_Scn *ps, *a, *b; + + if (pe == NULL || ndx < 1 || ndx > 0xFFFFU) { + errno = EINVAL; + return (NULL); + } + + if (pe->pe_cmd == PE_C_READ || pe->pe_flags & LIBPE_F_FD_DONE) { + errno = EACCES; + return (NULL); + } + + if ((ps = libpe_alloc_scn(pe)) == NULL) + return (NULL); + + if (pe->pe_flags & LIBPE_F_BAD_SEC_HEADER) { + STAILQ_FOREACH_SAFE(a, &pe->pe_scn, ps_next, b) + libpe_release_scn(a); + pe->pe_flags &= ~LIBPE_F_BAD_SEC_HEADER; + } + + b = NULL; + STAILQ_FOREACH(a, &pe->pe_scn, ps_next) { + if (a->ps_ndx & 0xFFFF0000U) + continue; + if (a->ps_ndx == ndx) + break; + b = a; + } + + if (a == NULL) { + STAILQ_INSERT_TAIL(&pe->pe_scn, ps, ps_next); + if (b == NULL) + ps->ps_ndx = 1; + else + ps->ps_ndx = b->ps_ndx + 1; + } else if (b == NULL) { + STAILQ_INSERT_HEAD(&pe->pe_scn, ps, ps_next); + ps->ps_ndx = 1; + } else { + STAILQ_INSERT_AFTER(&pe->pe_scn, b, ps, ps_next); + ps->ps_ndx = ndx; + } + + a = ps; + while ((a = STAILQ_NEXT(a, ps_next)) != NULL) { + if ((a->ps_ndx & 0xFFFF0000U) == 0) + a->ps_ndx++; + } + + ps->ps_flags |= PE_F_DIRTY | LIBPE_F_LOAD_SECTION; + pe->pe_flags |= LIBPE_F_DIRTY_SEC_HEADER; + + return (ps); +} + +PE_SecHdr * +pe_section_header(PE_Scn *ps) +{ + + if (ps == NULL) { + errno = EINVAL; + return (NULL); + } + + return (&ps->ps_sh); +} + +int +pe_update_section_header(PE_Scn *ps, PE_SecHdr *sh) +{ + PE *pe; + + if (ps == NULL || sh == NULL) { + errno = EINVAL; + return (-1); + } + + pe = ps->ps_pe; + + if (pe->pe_cmd == PE_C_READ || pe->pe_flags & LIBPE_F_FD_DONE) { + errno = EACCES; + return (-1); + } + + ps->ps_sh = *sh; + pe->pe_flags |= LIBPE_F_DIRTY_SEC_HEADER; + + return (0); +} diff --git a/contrib/elftoolchain/libpe/pe_symtab.c b/contrib/elftoolchain/libpe/pe_symtab.c new file mode 100644 index 0000000..d0e90d1 --- /dev/null +++ b/contrib/elftoolchain/libpe/pe_symtab.c @@ -0,0 +1,86 @@ +/*- + * Copyright (c) 2016 Kai Wang + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include <errno.h> + +#include "_libpe.h" + +ELFTC_VCSID("$Id: pe_symtab.c 3312 2016-01-10 09:23:51Z kaiwang27 $"); + +int +pe_update_symtab(PE *pe, char *symtab, size_t sz, unsigned int nsym) +{ + PE_Scn *ps; + PE_SecBuf *sb; + PE_SecHdr *sh; + + if (pe == NULL || symtab == NULL || sz == 0) { + errno = EINVAL; + return (-1); + } + + if (pe->pe_cmd == PE_C_READ || pe->pe_flags & LIBPE_F_FD_DONE) { + errno = EACCES; + return (-1); + } + + /* Remove the old symbol table. */ + STAILQ_FOREACH(ps, &pe->pe_scn, ps_next) { + if (ps->ps_ndx == 0xFFFFFFFFU) + libpe_release_scn(ps); + } + + /* + * Insert the new symbol table. + */ + + if ((ps = libpe_alloc_scn(pe)) == NULL) + return (-1); + + STAILQ_INSERT_TAIL(&pe->pe_scn, ps, ps_next); + ps->ps_ndx = 0xFFFFFFFFU; + ps->ps_flags |= PE_F_DIRTY; + + /* + * Set the symbol table section offset to the maximum to make sure + * that it will be placed in the end of the file during section + * layout. + */ + sh = &ps->ps_sh; + sh->sh_rawptr = 0xFFFFFFFFU; + sh->sh_rawsize = sz; + + /* Allocate the buffer. */ + if ((sb = libpe_alloc_buffer(ps, 0)) == NULL) + return (-1); + sb->sb_flags |= PE_F_DIRTY; + sb->sb_pb.pb_size = sz; + sb->sb_pb.pb_buf = symtab; + + pe->pe_nsym = nsym; + + return (0); +} diff --git a/contrib/elftoolchain/libpe/pe_update.c b/contrib/elftoolchain/libpe/pe_update.c new file mode 100644 index 0000000..ec2b2e5 --- /dev/null +++ b/contrib/elftoolchain/libpe/pe_update.c @@ -0,0 +1,86 @@ +/*- + * Copyright (c) 2016 Kai Wang + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include <assert.h> +#include <errno.h> +#include <unistd.h> + +#include "_libpe.h" + +ELFTC_VCSID("$Id: pe_update.c 3312 2016-01-10 09:23:51Z kaiwang27 $"); + +off_t +pe_update(PE *pe) +{ + off_t off; + + if (pe == NULL) { + errno = EINVAL; + return (-1); + } + + if (pe->pe_cmd == PE_C_READ || pe->pe_flags & LIBPE_F_FD_DONE) { + errno = EACCES; + return (-1); + } + + if (pe->pe_cmd == PE_C_RDWR || (pe->pe_cmd == PE_C_WRITE && + (pe->pe_flags & LIBPE_F_SPECIAL_FILE) == 0)) { + if (lseek(pe->pe_fd, 0, SEEK_SET) < 0) { + errno = EIO; + return (-1); + } + } + + off = 0; + + if (pe->pe_obj == PE_O_PE32 || pe->pe_obj == PE_O_PE32P) { + if ((off = libpe_write_msdos_stub(pe, off)) < 0) + return (-1); + + if ((off = libpe_write_pe_header(pe, off)) < 0) + return (-1); + } + + if (libpe_resync_sections(pe, off) < 0) + return (-1); + + if ((off = libpe_write_coff_header(pe, off)) < 0) + return (-1); + + if ((off = libpe_write_section_headers(pe, off)) < 0) + return (-1); + + if ((off = libpe_write_sections(pe, off)) < 0) + return (-1); + + if (ftruncate(pe->pe_fd, off) < 0) { + errno = EIO; + return (-1); + } + + return (off); +} diff --git a/contrib/elftoolchain/nm/os.NetBSD.mk b/contrib/elftoolchain/nm/os.NetBSD.mk new file mode 100644 index 0000000..ae214e3 --- /dev/null +++ b/contrib/elftoolchain/nm/os.NetBSD.mk @@ -0,0 +1,2 @@ +# TODO(#511): Revert after the source tree is -Wconversion clean. +WARNS=5 diff --git a/contrib/elftoolchain/readelf/os.NetBSD.mk b/contrib/elftoolchain/readelf/os.NetBSD.mk new file mode 100644 index 0000000..ae214e3 --- /dev/null +++ b/contrib/elftoolchain/readelf/os.NetBSD.mk @@ -0,0 +1,2 @@ +# TODO(#511): Revert after the source tree is -Wconversion clean. +WARNS=5 diff --git a/contrib/elftoolchain/readelf/readelf.c b/contrib/elftoolchain/readelf/readelf.c index a017023..d8e44dd 100644 --- a/contrib/elftoolchain/readelf/readelf.c +++ b/contrib/elftoolchain/readelf/readelf.c @@ -47,7 +47,16 @@ #include "_elftc.h" -ELFTC_VCSID("$Id: readelf.c 3271 2015-12-11 18:53:08Z kaiwang27 $"); +ELFTC_VCSID("$Id: readelf.c 3395 2016-02-10 16:29:44Z emaste $"); + +/* Backwards compatability for older FreeBSD releases. */ +#ifndef STB_GNU_UNIQUE +#define STB_GNU_UNIQUE 10 +#endif +#ifndef STT_SPARC_REGISTER +#define STT_SPARC_REGISTER 13 +#endif + /* * readelf(1) options. @@ -338,7 +347,7 @@ static const char *phdr_type(unsigned int ptype); static const char *ppc_abi_fp(uint64_t fp); static const char *ppc_abi_vector(uint64_t vec); static const char *r_type(unsigned int mach, unsigned int type); -static void readelf_usage(void); +static void readelf_usage(int status); static void readelf_version(void); static void search_loclist_at(struct readelf *re, Dwarf_Die die, Dwarf_Unsigned lowpc); @@ -348,7 +357,7 @@ static void set_cu_context(struct readelf *re, Dwarf_Half psize, Dwarf_Half osize, Dwarf_Half ver); static const char *st_bind(unsigned int sbind); static const char *st_shndx(unsigned int shndx); -static const char *st_type(unsigned int stype); +static const char *st_type(unsigned int mach, unsigned int stype); static const char *st_vis(unsigned int svis); static const char *top_tag(unsigned int tag); static void unload_sections(struct readelf *re); @@ -958,6 +967,7 @@ st_bind(unsigned int sbind) case STB_LOCAL: return "LOCAL"; case STB_GLOBAL: return "GLOBAL"; case STB_WEAK: return "WEAK"; + case STB_GNU_UNIQUE: return "UNIQUE"; default: if (sbind >= STB_LOOS && sbind <= STB_HIOS) return "OS"; @@ -971,7 +981,7 @@ st_bind(unsigned int sbind) } static const char * -st_type(unsigned int stype) +st_type(unsigned int mach, unsigned int stype) { static char s_stype[32]; @@ -987,10 +997,12 @@ st_type(unsigned int stype) if (stype >= STT_LOOS && stype <= STT_HIOS) snprintf(s_stype, sizeof(s_stype), "OS+%#x", stype - STT_LOOS); - else if (stype >= STT_LOPROC && stype <= STT_HIPROC) + else if (stype >= STT_LOPROC && stype <= STT_HIPROC) { + if (mach == EM_SPARCV9 && stype == STT_SPARC_REGISTER) + return "REGISTER"; snprintf(s_stype, sizeof(s_stype), "PROC+%#x", stype - STT_LOPROC); - else + } else snprintf(s_stype, sizeof(s_stype), "<unknown: %#x>", stype); return (s_stype); @@ -1066,7 +1078,7 @@ r_type(unsigned int mach, unsigned int type) case 4: return "R_386_PLT32"; case 5: return "R_386_COPY"; case 6: return "R_386_GLOB_DAT"; - case 7: return "R_386_JMP_SLOT"; + case 7: return "R_386_JUMP_SLOT"; case 8: return "R_386_RELATIVE"; case 9: return "R_386_GOTOFF"; case 10: return "R_386_GOTPC"; @@ -1558,7 +1570,7 @@ r_type(unsigned int mach, unsigned int type) case 4: return "R_X86_64_PLT32"; case 5: return "R_X86_64_COPY"; case 6: return "R_X86_64_GLOB_DAT"; - case 7: return "R_X86_64_JMP_SLOT"; + case 7: return "R_X86_64_JUMP_SLOT"; case 8: return "R_X86_64_RELATIVE"; case 9: return "R_X86_64_GOTPCREL"; case 10: return "R_X86_64_32"; @@ -3465,9 +3477,10 @@ dump_symtab(struct readelf *re, int i) continue; } printf("%6d:", j); - printf(" %16.16jx", (uintmax_t)sym.st_value); - printf(" %5ju", sym.st_size); - printf(" %-7s", st_type(GELF_ST_TYPE(sym.st_info))); + printf(" %16.16jx", (uintmax_t) sym.st_value); + printf(" %5ju", (uintmax_t) sym.st_size); + printf(" %-7s", st_type(re->ehdr.e_machine, + GELF_ST_TYPE(sym.st_info))); printf(" %-6s", st_bind(GELF_ST_BIND(sym.st_info))); printf(" %-8s", st_vis(GELF_ST_VISIBILITY(sym.st_other))); printf(" %3s", st_shndx(sym.st_shndx)); @@ -4303,7 +4316,7 @@ dump_compatibility_tag(uint8_t *p, uint8_t *pe) uint64_t val; val = _decode_uleb128(&p, pe); - printf("flag = %ju, vendor = %s\n", val, p); + printf("flag = %ju, vendor = %s\n", (uintmax_t) val, p); p += strlen((char *) p) + 1; return (p); @@ -4997,7 +5010,8 @@ dump_dwarf_line(struct readelf *re) break; case DW_LNS_set_isa: isa = _decode_uleb128(&p, pe); - printf(" Set isa to %ju\n", isa); + printf(" Set isa to %ju\n", + (uintmax_t) isa); break; default: /* Unrecognized extended opcodes. */ @@ -5749,12 +5763,12 @@ dump_dwarf_ranges_foreach(struct readelf *re, Dwarf_Die die, Dwarf_Addr base) } if (re->ec == ELFCLASS32) printf("%08jx %08jx\n", - ranges[j].dwr_addr1 + base0, - ranges[j].dwr_addr2 + base0); + (uintmax_t) (ranges[j].dwr_addr1 + base0), + (uintmax_t) (ranges[j].dwr_addr2 + base0)); else printf("%016jx %016jx\n", - ranges[j].dwr_addr1 + base0, - ranges[j].dwr_addr2 + base0); + (uintmax_t) (ranges[j].dwr_addr1 + base0), + (uintmax_t) (ranges[j].dwr_addr2 + base0)); } } @@ -6728,7 +6742,7 @@ dump_dwarf_loclist(struct readelf *re) set_cu_context(re, la->la_cu_psize, la->la_cu_osize, la->la_cu_ver); for (i = 0; i < lcnt; i++) { - printf(" %8.8jx ", la->la_off); + printf(" %8.8jx ", (uintmax_t) la->la_off); if (llbuf[i]->ld_lopc == 0 && llbuf[i]->ld_hipc == 0) { printf("<End of list>\n"); continue; @@ -6850,13 +6864,15 @@ hex_dump(struct readelf *re) if (find_dumpop(re, (size_t) i, s->name, HEX_DUMP, -1) == NULL) continue; (void) elf_errno(); - if ((d = elf_getdata(s->scn, NULL)) == NULL) { + if ((d = elf_getdata(s->scn, NULL)) == NULL && + (d = elf_rawdata(s->scn, NULL)) == NULL) { elferr = elf_errno(); if (elferr != 0) warnx("elf_getdata failed: %s", elf_errmsg(elferr)); continue; } + (void) elf_errno(); if (d->d_size <= 0 || d->d_buf == NULL) { printf("\nSection '%s' has no data to dump.\n", s->name); @@ -6905,13 +6921,15 @@ str_dump(struct readelf *re) if (find_dumpop(re, (size_t) i, s->name, STR_DUMP, -1) == NULL) continue; (void) elf_errno(); - if ((d = elf_getdata(s->scn, NULL)) == NULL) { + if ((d = elf_getdata(s->scn, NULL)) == NULL && + (d = elf_rawdata(s->scn, NULL)) == NULL) { elferr = elf_errno(); if (elferr != 0) warnx("elf_getdata failed: %s", elf_errmsg(elferr)); continue; } + (void) elf_errno(); if (d->d_size <= 0 || d->d_buf == NULL) { printf("\nSection '%s' has no data to dump.\n", s->name); @@ -7370,10 +7388,13 @@ _read_lsb(Elf_Data *d, uint64_t *offsetp, int bytes_to_read) case 8: ret |= ((uint64_t) src[4]) << 32 | ((uint64_t) src[5]) << 40; ret |= ((uint64_t) src[6]) << 48 | ((uint64_t) src[7]) << 56; + /* FALLTHROUGH */ case 4: ret |= ((uint64_t) src[2]) << 16 | ((uint64_t) src[3]) << 24; + /* FALLTHROUGH */ case 2: ret |= ((uint64_t) src[1]) << 8; + /* FALLTHROUGH */ case 1: ret |= src[0]; break; @@ -7433,10 +7454,13 @@ _decode_lsb(uint8_t **data, int bytes_to_read) case 8: ret |= ((uint64_t) src[4]) << 32 | ((uint64_t) src[5]) << 40; ret |= ((uint64_t) src[6]) << 48 | ((uint64_t) src[7]) << 56; + /* FALLTHROUGH */ case 4: ret |= ((uint64_t) src[2]) << 16 | ((uint64_t) src[3]) << 24; + /* FALLTHROUGH */ case 2: ret |= ((uint64_t) src[1]) << 8; + /* FALLTHROUGH */ case 1: ret |= src[0]; break; @@ -7558,6 +7582,10 @@ Usage: %s [options] file...\n\ -s | --syms | --symbols Print symbol tables.\n\ -t | --section-details Print additional information about sections.\n\ -v | --version Print a version identifier and exit.\n\ + -w[afilmoprsFLR] | --debug-dump={abbrev,aranges,decodedline,frames,\n\ + frames-interp,info,loc,macro,pubnames,\n\ + ranges,Ranges,rawline,str}\n\ + Display DWARF information.\n\ -x INDEX | --hex-dump=INDEX\n\ Display contents of a section as hexadecimal.\n\ -A | --arch-specific (accepted, but ignored)\n\ @@ -7574,10 +7602,10 @@ Usage: %s [options] file...\n\ static void -readelf_usage(void) +readelf_usage(int status) { fprintf(stderr, USAGE_MESSAGE, ELFTC_GETPROGNAME()); - exit(EXIT_FAILURE); + exit(status); } int @@ -7596,7 +7624,7 @@ main(int argc, char **argv) longopts, NULL)) != -1) { switch(opt) { case '?': - readelf_usage(); + readelf_usage(EXIT_SUCCESS); break; case 'A': re->options |= RE_AA; @@ -7621,7 +7649,7 @@ main(int argc, char **argv) re->options |= RE_G; break; case 'H': - readelf_usage(); + readelf_usage(EXIT_SUCCESS); break; case 'h': re->options |= RE_H; @@ -7699,7 +7727,7 @@ main(int argc, char **argv) argc -= optind; if (argc == 0 || re->options == 0) - readelf_usage(); + readelf_usage(EXIT_FAILURE); if (argc > 1) re->flags |= DISPLAY_FILENAME; diff --git a/contrib/elftoolchain/size/os.NetBSD.mk b/contrib/elftoolchain/size/os.NetBSD.mk new file mode 100644 index 0000000..ae214e3 --- /dev/null +++ b/contrib/elftoolchain/size/os.NetBSD.mk @@ -0,0 +1,2 @@ +# TODO(#511): Revert after the source tree is -Wconversion clean. +WARNS=5 diff --git a/contrib/elftoolchain/strings/os.NetBSD.mk b/contrib/elftoolchain/strings/os.NetBSD.mk new file mode 100644 index 0000000..ae214e3 --- /dev/null +++ b/contrib/elftoolchain/strings/os.NetBSD.mk @@ -0,0 +1,2 @@ +# TODO(#511): Revert after the source tree is -Wconversion clean. +WARNS=5 diff --git a/contrib/elftoolchain/strings/strings.1 b/contrib/elftoolchain/strings/strings.1 index 15ad7a7..205afdf 100644 --- a/contrib/elftoolchain/strings/strings.1 +++ b/contrib/elftoolchain/strings/strings.1 @@ -22,9 +22,9 @@ .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF .\" SUCH DAMAGE. .\" -.\" $Id: strings.1 3195 2015-05-12 17:22:19Z emaste $ +.\" $Id: strings.1 3360 2016-01-24 18:34:06Z jkoshy $ .\" -.Dd December 19, 2011 +.Dd January 24, 2016 .Dt STRINGS 1 .Os .Sh NAME @@ -100,6 +100,9 @@ Print a usage summary and exit. Print the contiguous character sequence of at least .Ar number characters long, instead of the default of 4 characters. +Argument +.Ar number +should specify a positive decimal integer. .It Fl o Equivalent to specifying .Fl t Ar o . diff --git a/contrib/elftoolchain/strings/strings.c b/contrib/elftoolchain/strings/strings.c index 6eab165..f122eba 100644 --- a/contrib/elftoolchain/strings/strings.c +++ b/contrib/elftoolchain/strings/strings.c @@ -37,6 +37,7 @@ #include <stdio.h> #include <stdlib.h> #include <string.h> +#include <sysexits.h> #include <unistd.h> #include <libelf.h> @@ -45,7 +46,7 @@ #include "_elftc.h" -ELFTC_VCSID("$Id: strings.c 3174 2015-03-27 17:13:41Z emaste $"); +ELFTC_VCSID("$Id: strings.c 3360 2016-01-24 18:34:06Z jkoshy $"); enum return_code { RETURN_OK, @@ -73,10 +74,10 @@ enum encoding_style { ((c) == '\t' || isprint((c)) || \ (encoding == ENCODING_8BIT && (c) > 127))) - -static int encoding_size, entire_file, min_len, show_filename, show_loc; +static int encoding_size, entire_file, show_filename, show_loc; static enum encoding_style encoding; static enum radix_style radix; +static intmax_t min_len; static struct option strings_longopts[] = { { "all", no_argument, NULL, 'a'}, @@ -144,7 +145,10 @@ main(int argc, char **argv) show_filename = 1; break; case 'n': - min_len = (int)strtoimax(optarg, (char**)NULL, 10); + min_len = strtoimax(optarg, (char**)NULL, 10); + if (min_len <= 0) + errx(EX_USAGE, "option -n should specify a " + "positive decimal integer."); break; case 'o': show_loc = 1; |