Merge ^/head r295544 through r295600.
This commit is contained in:
commit
90a4726375
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/projects/clang380-import/; revision=295601
@ -1638,6 +1638,7 @@ _binutils= gnu/usr.bin/binutils
|
||||
.endif
|
||||
.if ${MK_ELFTOOLCHAIN_BOOTSTRAP} != "no"
|
||||
_elftctools= lib/libelftc \
|
||||
lib/libpe \
|
||||
usr.bin/elfcopy \
|
||||
usr.bin/nm \
|
||||
usr.bin/size \
|
||||
@ -1650,6 +1651,7 @@ _elftctools+= usr.bin/addr2line
|
||||
# If cross-building with an external binutils we still need to build strip for
|
||||
# the target (for at least crunchide).
|
||||
_elftctools= lib/libelftc \
|
||||
lib/libpe \
|
||||
usr.bin/elfcopy
|
||||
.endif
|
||||
|
||||
|
@ -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 @@ translate(Dwarf_Debug dbg, Elf *e, const char* addrstr)
|
||||
}
|
||||
}
|
||||
|
||||
(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)
|
||||
|
2
contrib/elftoolchain/addr2line/os.NetBSD.mk
Normal file
2
contrib/elftoolchain/addr2line/os.NetBSD.mk
Normal file
@ -0,0 +1,2 @@
|
||||
# TODO(#511): Revert after the source tree is -Wconversion clean.
|
||||
WARNS=5
|
@ -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)
|
||||
|
@ -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));
|
||||
|
@ -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) \
|
||||
@ -1408,8 +1410,128 @@ _ELF_DEFINE_RELOC(R_386_PC8, 23)
|
||||
/*
|
||||
*/
|
||||
#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()
|
||||
|
||||
|
@ -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 {
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -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}
|
||||
|
||||
|
@ -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));
|
||||
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
|
@ -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\
|
||||
|
233
contrib/elftoolchain/elfcopy/pe.c
Normal file
233
contrib/elftoolchain/elfcopy/pe.c
Normal file
@ -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);
|
||||
}
|
@ -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,12 +1161,15 @@ copy_data(struct section *s)
|
||||
return;
|
||||
|
||||
if ((id = elf_getdata(s->is, NULL)) == NULL) {
|
||||
(void) elf_errno();
|
||||
if ((id = elf_rawdata(s->is, NULL)) == NULL) {
|
||||
elferr = elf_errno();
|
||||
if (elferr != 0)
|
||||
errx(EXIT_FAILURE, "elf_getdata() failed: %s",
|
||||
elf_errmsg(elferr));
|
||||
errx(EXIT_FAILURE, "failed to read section:"
|
||||
" %s", s->name);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if ((od = elf_newdata(s->os)) == NULL)
|
||||
errx(EXIT_FAILURE, "elf_newdata() failed: %s",
|
||||
@ -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,6 +1473,7 @@ 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->size > 0) {
|
||||
if ((sa->content = malloc(sa->size)) == NULL)
|
||||
err(EXIT_FAILURE, "malloc failed");
|
||||
if ((fp = fopen(fn, "r")) == NULL)
|
||||
@ -1439,6 +1482,8 @@ add_section(struct elfcopy *ecp, const char *arg)
|
||||
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;
|
||||
|
@ -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++;
|
||||
|
@ -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,9 +585,12 @@ 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]);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Give up if there is no real symbols inside the table.
|
||||
@ -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,11 +989,18 @@ 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)
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
@ -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) {
|
||||
assert (name != NULL);
|
||||
STAILQ_FOREACH(s, &ecp->v_symop, symop_list)
|
||||
if (!strcmp(name, s->name))
|
||||
goto found;
|
||||
|
||||
if ((s = calloc(1, sizeof(*s))) == NULL)
|
||||
errx(EXIT_FAILURE, "not enough memory");
|
||||
STAILQ_INSERT_TAIL(&ecp->v_symop, s, symop_list);
|
||||
s->name = name;
|
||||
found:
|
||||
if (op == SYMOP_REDEF)
|
||||
s->newname = newname;
|
||||
}
|
||||
|
||||
s->op |= op;
|
||||
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);
|
||||
}
|
||||
|
||||
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);
|
||||
|
@ -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,54 +155,56 @@ 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 DT_PLTPADSZ: return "DT_PLTPADSZ";
|
||||
case DT_MOVEENT: return "DT_MOVEENT";
|
||||
case DT_MOVESZ: 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 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";
|
||||
@ -210,22 +212,25 @@ d_tags(uint64_t tag)
|
||||
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 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";
|
||||
}
|
||||
|
||||
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) {
|
||||
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 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 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 0x6ffffffd: return "SHT_SUNW(GNU)_verdef";
|
||||
case 0x6ffffffe: return "SHT_SUNW(GNU)_verneed";
|
||||
case 0x6fffffff: return "SHT_SUNW(GNU)_versym";
|
||||
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 */
|
||||
default: return "ERROR: SHT NOT DEFINED";
|
||||
}
|
||||
}
|
||||
/* 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];
|
||||
|
||||
static const char *st_types_S[] = {
|
||||
"NOTY", "OBJT", "FUNC", "SECT", "FILE"
|
||||
};
|
||||
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_bindings[] = {
|
||||
"STB_LOCAL", "STB_GLOBAL", "STB_WEAK"
|
||||
};
|
||||
static const char *
|
||||
st_type_S(unsigned int type)
|
||||
{
|
||||
static char s_type[32];
|
||||
|
||||
static const char *st_bindings_S[] = {
|
||||
"LOCL", "GLOB", "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(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));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
2
contrib/elftoolchain/elfdump/os.NetBSD.mk
Normal file
2
contrib/elftoolchain/elfdump/os.NetBSD.mk
Normal file
@ -0,0 +1,2 @@
|
||||
# TODO(#511): Revert after the source tree is -Wconversion clean.
|
||||
WARNS=5
|
@ -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. */
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
2
contrib/elftoolchain/libdwarf/os.NetBSD.mk
Normal file
2
contrib/elftoolchain/libdwarf/os.NetBSD.mk
Normal file
@ -0,0 +1,2 @@
|
||||
# TODO(#511): Revert after the source tree is -Wconversion clean.
|
||||
WARNS=5
|
@ -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__)
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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)
|
||||
if ((buf = malloc(file_size)) == NULL)
|
||||
return (-1);
|
||||
if (read(ifd, buf, sb.st_size) != sb.st_size) {
|
||||
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
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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
|
@ -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;
|
||||
|
||||
/*
|
||||
|
@ -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[] = {
|
||||
|
||||
@ -374,6 +374,30 @@ struct _Elftc_Bfd_Target _libelftc_targets[] = {
|
||||
.bt_type = ETF_SREC,
|
||||
},
|
||||
|
||||
{
|
||||
.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,
|
||||
|
@ -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'):
|
||||
|
@ -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"
|
||||
|
2
contrib/elftoolchain/libelftc/os.NetBSD.mk
Normal file
2
contrib/elftoolchain/libelftc/os.NetBSD.mk
Normal file
@ -0,0 +1,2 @@
|
||||
# TODO(#511): Revert after the source tree is -Wconversion clean.
|
||||
WARNS=5
|
32
contrib/elftoolchain/libpe/Makefile
Normal file
32
contrib/elftoolchain/libpe/Makefile
Normal file
@ -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"
|
213
contrib/elftoolchain/libpe/_libpe.h
Normal file
213
contrib/elftoolchain/libpe/_libpe.h
Normal file
@ -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_ */
|
121
contrib/elftoolchain/libpe/libpe.h
Normal file
121
contrib/elftoolchain/libpe/libpe.h
Normal file
@ -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_ */
|
185
contrib/elftoolchain/libpe/libpe_buffer.c
Normal file
185
contrib/elftoolchain/libpe/libpe_buffer.c
Normal file
@ -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);
|
||||
}
|
535
contrib/elftoolchain/libpe/libpe_coff.c
Normal file
535
contrib/elftoolchain/libpe/libpe_coff.c
Normal file
@ -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);
|
||||
}
|
403
contrib/elftoolchain/libpe/libpe_dos.c
Normal file
403
contrib/elftoolchain/libpe/libpe_dos.c
Normal file
@ -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);
|
||||
}
|
145
contrib/elftoolchain/libpe/libpe_init.c
Normal file
145
contrib/elftoolchain/libpe/libpe_init.c
Normal file
@ -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);
|
||||
}
|
128
contrib/elftoolchain/libpe/libpe_rich.c
Normal file
128
contrib/elftoolchain/libpe/libpe_rich.c
Normal file
@ -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);
|
||||
}
|
518
contrib/elftoolchain/libpe/libpe_section.c
Normal file
518
contrib/elftoolchain/libpe/libpe_section.c
Normal file
@ -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);
|
||||
}
|
69
contrib/elftoolchain/libpe/libpe_utils.c
Normal file
69
contrib/elftoolchain/libpe/libpe_utils.c
Normal file
@ -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);
|
||||
}
|
6
contrib/elftoolchain/libpe/os.Linux.mk
Normal file
6
contrib/elftoolchain/libpe/os.Linux.mk
Normal file
@ -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
|
2
contrib/elftoolchain/libpe/os.NetBSD.mk
Normal file
2
contrib/elftoolchain/libpe/os.NetBSD.mk
Normal file
@ -0,0 +1,2 @@
|
||||
# TODO(#511): Revert after the source tree is -Wconversion clean.
|
||||
WARNS=5
|
292
contrib/elftoolchain/libpe/pe.h
Normal file
292
contrib/elftoolchain/libpe/pe.h
Normal file
@ -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_ */
|
100
contrib/elftoolchain/libpe/pe_buffer.c
Normal file
100
contrib/elftoolchain/libpe/pe_buffer.c
Normal file
@ -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);
|
||||
}
|
62
contrib/elftoolchain/libpe/pe_cntl.c
Normal file
62
contrib/elftoolchain/libpe/pe_cntl.c
Normal file
@ -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);
|
||||
}
|
157
contrib/elftoolchain/libpe/pe_coff.c
Normal file
157
contrib/elftoolchain/libpe/pe_coff.c
Normal file
@ -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);
|
||||
}
|
119
contrib/elftoolchain/libpe/pe_dos.c
Normal file
119
contrib/elftoolchain/libpe/pe_dos.c
Normal file
@ -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);
|
||||
}
|
187
contrib/elftoolchain/libpe/pe_flag.c
Normal file
187
contrib/elftoolchain/libpe/pe_flag.c
Normal file
@ -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);
|
||||
}
|
95
contrib/elftoolchain/libpe/pe_init.c
Normal file
95
contrib/elftoolchain/libpe/pe_init.c
Normal file
@ -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);
|
||||
}
|
107
contrib/elftoolchain/libpe/pe_rich.c
Normal file
107
contrib/elftoolchain/libpe/pe_rich.c
Normal file
@ -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);
|
||||
}
|
213
contrib/elftoolchain/libpe/pe_section.c
Normal file
213
contrib/elftoolchain/libpe/pe_section.c
Normal file
@ -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);
|
||||
}
|
86
contrib/elftoolchain/libpe/pe_symtab.c
Normal file
86
contrib/elftoolchain/libpe/pe_symtab.c
Normal file
@ -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);
|
||||
}
|
86
contrib/elftoolchain/libpe/pe_update.c
Normal file
86
contrib/elftoolchain/libpe/pe_update.c
Normal file
@ -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);
|
||||
}
|
2
contrib/elftoolchain/nm/os.NetBSD.mk
Normal file
2
contrib/elftoolchain/nm/os.NetBSD.mk
Normal file
@ -0,0 +1,2 @@
|
||||
# TODO(#511): Revert after the source tree is -Wconversion clean.
|
||||
WARNS=5
|
2
contrib/elftoolchain/readelf/os.NetBSD.mk
Normal file
2
contrib/elftoolchain/readelf/os.NetBSD.mk
Normal file
@ -0,0 +1,2 @@
|
||||
# TODO(#511): Revert after the source tree is -Wconversion clean.
|
||||
WARNS=5
|
@ -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;
|
||||
|
2
contrib/elftoolchain/size/os.NetBSD.mk
Normal file
2
contrib/elftoolchain/size/os.NetBSD.mk
Normal file
@ -0,0 +1,2 @@
|
||||
# TODO(#511): Revert after the source tree is -Wconversion clean.
|
||||
WARNS=5
|
2
contrib/elftoolchain/strings/os.NetBSD.mk
Normal file
2
contrib/elftoolchain/strings/os.NetBSD.mk
Normal file
@ -0,0 +1,2 @@
|
||||
# TODO(#511): Revert after the source tree is -Wconversion clean.
|
||||
WARNS=5
|
@ -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 .
|
||||
|
@ -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;
|
||||
|
@ -33,7 +33,8 @@ need_dad_wait=
|
||||
# set it to $param. If not defined, $defval is used.
|
||||
# When $num is [0-9]*, ${jail_$jv_$name$num} are looked up and
|
||||
# $param is set by using +=. $num=0 is optional (params may start at 1).
|
||||
# When $num is YN or NY, the value is interpret as boolean.
|
||||
# When $num is YN or NY, the value is interpreted as boolean.
|
||||
# When $num is @, the value is interpreted as an array separted by IFS.
|
||||
extract_var()
|
||||
{
|
||||
local i _jv _name _param _num _def _name1 _name2
|
||||
@ -78,6 +79,20 @@ extract_var()
|
||||
i=$(($i + 1))
|
||||
done
|
||||
;;
|
||||
@)
|
||||
_name1=jail_${_jv}_${_name}
|
||||
_name2=jail_${_name}
|
||||
eval _tmpargs=\"\${$_name1:-\${$_name2:-$_def}}\"
|
||||
set -- $_tmpargs
|
||||
if [ $# -gt 0 ]; then
|
||||
echo -n " $_param = "
|
||||
while [ $# -gt 1 ]; do
|
||||
echo -n "\"$1\", "
|
||||
shift
|
||||
done
|
||||
echo "\"$1\";"
|
||||
fi
|
||||
;;
|
||||
*)
|
||||
_name1=jail_${_jv}_${_name}
|
||||
_name2=jail_${_name}
|
||||
@ -190,7 +205,7 @@ parse_options()
|
||||
allow.raw_sockets NY YES
|
||||
else
|
||||
echo " vnet;"
|
||||
extract_var $_jv vnet_interface vnet.interface - ""
|
||||
extract_var $_jv vnet_interface vnet.interface @ ""
|
||||
fi
|
||||
|
||||
echo " exec.clean;"
|
||||
|
@ -36,6 +36,8 @@
|
||||
#include <sys/cdefs.h>
|
||||
#include <sys/_types.h>
|
||||
#include <sys/signal.h>
|
||||
#include <machine/ucontext.h>
|
||||
#include <sys/_ucontext.h>
|
||||
|
||||
#if __BSD_VISIBLE
|
||||
/*
|
||||
@ -114,7 +116,6 @@ void psignal(unsigned int, const char *);
|
||||
|
||||
#if __BSD_VISIBLE
|
||||
int sigblock(int);
|
||||
struct __ucontext; /* XXX spec requires a complete declaration. */
|
||||
int sigreturn(const struct __ucontext *);
|
||||
int sigsetmask(int);
|
||||
int sigstack(const struct sigstack *, struct sigstack *);
|
||||
|
@ -80,6 +80,7 @@ SUBDIR= ${SUBDIR_ORDERED} \
|
||||
libopie \
|
||||
libpam \
|
||||
libpcap \
|
||||
${_libpe} \
|
||||
libpjdlog \
|
||||
${_libpmc} \
|
||||
${_libproc} \
|
||||
@ -184,6 +185,7 @@ _cuse= libcuse
|
||||
|
||||
.if ${MK_TOOLCHAIN} != "no"
|
||||
_libelftc= libelftc
|
||||
_libpe= libpe
|
||||
.endif
|
||||
|
||||
.if ${MK_FILE} != "no"
|
||||
|
@ -6,5 +6,5 @@
|
||||
const char *
|
||||
elftc_version(void)
|
||||
{
|
||||
return "elftoolchain r3272M";
|
||||
return "elftoolchain r3400M";
|
||||
}
|
||||
|
34
lib/libpe/Makefile
Normal file
34
lib/libpe/Makefile
Normal file
@ -0,0 +1,34 @@
|
||||
# $FreeBSD$
|
||||
.include <bsd.own.mk>
|
||||
|
||||
INTERNALLIB=
|
||||
|
||||
ELFTCDIR= ${.CURDIR}/../../contrib/elftoolchain
|
||||
|
||||
.PATH: ${ELFTCDIR}/libpe
|
||||
|
||||
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
|
||||
|
||||
CFLAGS+=-I${ELFTCDIR}/libpe -I${ELFTCDIR}/common
|
||||
|
||||
MAN=
|
||||
|
||||
.include <bsd.lib.mk>
|
@ -164,12 +164,93 @@ usage()
|
||||
|
||||
action_usage()
|
||||
{
|
||||
local usage action="$1"
|
||||
local usage descr action="$1"
|
||||
eval usage=\"\$jib_${action}_usage\"
|
||||
echo "Usage: $pgm $usage" >&2
|
||||
eval descr=\"\$jib_${action}_descr\"
|
||||
printf "\t%s\n" "$descr"
|
||||
exit $FAILURE
|
||||
}
|
||||
|
||||
derive_mac()
|
||||
{
|
||||
local OPTIND=1 OPTARG __flag
|
||||
local __mac_num= __make_pair=
|
||||
while getopts 2n: __flag; do
|
||||
case "$__flag" in
|
||||
2) __make_pair=1 ;;
|
||||
n) __mac_num=${OPTARG%%[^0-9]*} ;;
|
||||
esac
|
||||
done
|
||||
shift $(( $OPTIND - 1 ))
|
||||
|
||||
if [ ! "$__mac_num" ]; then
|
||||
eval __mac_num=\${_${iface}_num:--1}
|
||||
__mac_num=$(( $__mac_num + 1 ))
|
||||
eval _${iface}_num=\$__mac_num
|
||||
fi
|
||||
|
||||
local __iface="$1" __name="$2" __var_to_set="$3" __var_to_set_b="$4"
|
||||
local __iface_devid __new_devid __num __new_devid_b
|
||||
#
|
||||
# Calculate MAC address derived from given iface.
|
||||
#
|
||||
# The formula I'm using is ``NP:SS:SS:II:II:II'' where:
|
||||
# + N denotes 4 bits used as a counter to support branching
|
||||
# each parent interface up to 15 times under the same jail
|
||||
# name (see S below).
|
||||
# + P denotes the special nibble whose value, if one of
|
||||
# 2, 6, A, or E (but usually 2) denotes a privately
|
||||
# administered MAC address (while remaining routable).
|
||||
# + S denotes 16 bits, the sum(1) value of the jail name.
|
||||
# + I denotes bits that are inherited from parent interface.
|
||||
#
|
||||
# The S bits are a CRC-16 checksum of NAME, allowing the jail
|
||||
# to change link numbers in ng_bridge(4) without affecting the
|
||||
# MAC address. Meanwhile, if...
|
||||
# + the jail NAME changes (e.g., it was duplicated and given
|
||||
# a new name with no other changes)
|
||||
# + the underlying network interface changes
|
||||
# + the jail is moved to another host
|
||||
# the MAC address will be recalculated to a new, similarly
|
||||
# unique value preventing conflict.
|
||||
#
|
||||
__iface_devid=$( ifconfig $__iface ether | awk '/ether/,$0=$2' )
|
||||
# ??:??:??:II:II:II
|
||||
__new_devid=${__iface_devid#??:??:??} # => :II:II:II
|
||||
# => :SS:SS:II:II:II
|
||||
__num=$( set -- `echo -n "$__name" | sum` && echo $1 )
|
||||
__new_devid=$( printf :%02x:%02x \
|
||||
$(( $__num >> 8 & 255 )) $(( $__num & 255 )) )$__new_devid
|
||||
# => P:SS:SS:II:II:II
|
||||
case "$__iface_devid" in
|
||||
?2:*) __new_devid=a$__new_devid __new_devid_b=e$__new_devid ;;
|
||||
?[Ee]:*) __new_devid=2$__new_devid __new_devid_b=6$__new_devid ;;
|
||||
*) __new_devid=2$__new_devid __new_devid_b=e$__new_devid
|
||||
esac
|
||||
# => NP:SS:SS:II:II:II
|
||||
__new_devid=$( printf %x $(( $__mac_num & 15 )) )$__new_devid
|
||||
__new_devid_b=$( printf %x $(( $__mac_num & 15 )) )$__new_devid_b
|
||||
|
||||
#
|
||||
# Return derivative MAC address(es)
|
||||
#
|
||||
if [ "$__make_pair" ]; then
|
||||
if [ "$__var_to_set" -a "$__var_to_set_b" ]; then
|
||||
eval $__var_to_set=\$__new_devid
|
||||
eval $__var_to_set_b=\$__new_devid_b
|
||||
else
|
||||
echo $__new_devid $__new_devid_b
|
||||
fi
|
||||
else
|
||||
if [ "$__var_to_set" ]; then
|
||||
eval $__var_to_set=\$__new_devid
|
||||
else
|
||||
echo $__new_devid
|
||||
fi
|
||||
fi
|
||||
}
|
||||
|
||||
mustberoot_to_continue()
|
||||
{
|
||||
if [ "$( id -u )" -ne 0 ]; then
|
||||
@ -178,7 +259,7 @@ mustberoot_to_continue()
|
||||
fi
|
||||
}
|
||||
|
||||
jib_addm_usage="addm [-b BRIDGE_NAME] NAME interface0 [interface1 ...]"
|
||||
jib_addm_usage="addm [-b BRIDGE_NAME] NAME [!]iface0 [[!]iface1 ...]"
|
||||
jib_addm_descr="Creates e0b_NAME [e1b_NAME ...]"
|
||||
jib_addm()
|
||||
{
|
||||
@ -198,18 +279,25 @@ jib_addm()
|
||||
|
||||
mustberoot_to_continue
|
||||
|
||||
local iface iface_devid eiface_devid
|
||||
local eiface_devid_a eiface_devid_b
|
||||
local new num quad i=0
|
||||
local iface eiface_devid_a eiface_devid_b
|
||||
local new no_derive num quad i=0
|
||||
for iface in $*; do
|
||||
|
||||
# 1. Make sure the interface doesn't exist already
|
||||
ifconfig "e${i}a_$name" > /dev/null 2>&1 && continue
|
||||
no_derive=
|
||||
case "$iface" in
|
||||
!*) iface=${iface#!} no_derive=1 ;;
|
||||
esac
|
||||
|
||||
# 2. Bring the interface up
|
||||
# Make sure the interface doesn't exist already
|
||||
if ifconfig "e${i}a_$name" > /dev/null 2>&1; then
|
||||
i=$(( $i + 1 ))
|
||||
continue
|
||||
fi
|
||||
|
||||
# Bring the interface up
|
||||
ifconfig $iface up || return
|
||||
|
||||
# 3. Make sure the interface has been bridged
|
||||
# Make sure the interface has been bridged
|
||||
if ! ifconfig "$iface$bridge" > /dev/null 2>&1; then
|
||||
new=$( ifconfig bridge create ) || return
|
||||
ifconfig $new addm $iface || return
|
||||
@ -217,97 +305,29 @@ jib_addm()
|
||||
ifconfig "$iface$bridge" up || return
|
||||
fi
|
||||
|
||||
# 4. Create a new interface to the bridge
|
||||
# Create a new interface to the bridge
|
||||
new=$( ifconfig epair create ) || return
|
||||
ifconfig "$iface$bridge" addm $new || return
|
||||
|
||||
# 5. Rename the new interface
|
||||
# Rename the new interface
|
||||
ifconfig $new name "e${i}a_$name" || return
|
||||
ifconfig ${new%a}b name "e${i}b_$name" || return
|
||||
ifconfig "e${i}a_$name" up || return
|
||||
ifconfig "e${i}b_$name" up || return
|
||||
|
||||
#
|
||||
# 6. Set the MAC address of the new interface using a sensible
|
||||
# Set the MAC address of the new interface using a sensible
|
||||
# algorithm to prevent conflicts on the network.
|
||||
#
|
||||
# The formula I'm using is ``NP:SS:SS:II:II:II'' where:
|
||||
# + N denotes 4 bits used as a counter to support branching
|
||||
# each parent interface up to 15 times under the same jail
|
||||
# name (see S below).
|
||||
# + P denotes the special nibble whose value, if one of
|
||||
# 2, 6, A, or E (but usually 2) denotes a privately
|
||||
# administered MAC address (while remaining routable).
|
||||
# + S denotes 16 bits, the sum(1) value of the jail name.
|
||||
# + I denotes bits that are inherited from parent interface.
|
||||
#
|
||||
# The S bits are a CRC-16 checksum of NAME, allowing the jail
|
||||
# to change the epair(4) generation order without affecting the
|
||||
# MAC address. Meanwhile, if...
|
||||
# + the jail NAME changes (e.g., it was duplicated and given
|
||||
# a new name with no other changes)
|
||||
# + the underlying network interface changes
|
||||
# + the jail is moved to another host
|
||||
# the MAC address will be recalculated to a new, similarly
|
||||
# unique value preventing conflict.
|
||||
#
|
||||
iface_devid=$( ifconfig $iface ether | awk '/ether/,$0=$2' )
|
||||
eiface_devid=${iface_devid#??:??:??}
|
||||
num=$( set -- `echo -n $name | sum` && echo $1 )
|
||||
quad=$(( $num & 15 ))
|
||||
case "$quad" in
|
||||
10) quad=a ;; 11) quad=b ;; 12) quad=c ;;
|
||||
13) quad=d ;; 14) quad=e ;; 15) quad=f ;;
|
||||
esac
|
||||
eiface_devid=$quad$eiface_devid
|
||||
num=$(( $num >> 4 ))
|
||||
quad=$(( $num & 15 ))
|
||||
case "$quad" in
|
||||
10) quad=a ;; 11) quad=b ;; 12) quad=c ;;
|
||||
13) quad=d ;; 14) quad=e ;; 15) quad=f ;;
|
||||
esac
|
||||
eiface_devid=$quad$eiface_devid
|
||||
num=$(( $num >> 4 ))
|
||||
quad=$(( $num & 15 ))
|
||||
case "$quad" in
|
||||
10) quad=a ;; 11) quad=b ;; 12) quad=c ;;
|
||||
13) quad=d ;; 14) quad=e ;; 15) quad=f ;;
|
||||
esac
|
||||
eiface_devid=$quad:$eiface_devid
|
||||
num=$(( $num >> 4 ))
|
||||
quad=$(( $num & 15 ))
|
||||
case "$quad" in
|
||||
10) quad=a ;; 11) quad=b ;; 12) quad=c ;;
|
||||
13) quad=d ;; 14) quad=e ;; 15) quad=f ;;
|
||||
esac
|
||||
case "$iface_devid" in
|
||||
?[Ee]:*)
|
||||
eiface_devid_a=2:$quad$eiface_devid
|
||||
eiface_devid_b=6:$quad$eiface_devid
|
||||
;;
|
||||
*)
|
||||
eiface_devid_a=2:$quad$eiface_devid
|
||||
eiface_devid_b=e:$quad$eiface_devid
|
||||
esac
|
||||
eval num=\$_${iface}_num
|
||||
if [ "$num" ]; then
|
||||
num=$(( $num + 1 ))
|
||||
eval _${iface}_num=$num
|
||||
else
|
||||
num=0
|
||||
local _${iface}_num=$num
|
||||
fi
|
||||
quad=$(( $num & 15 ))
|
||||
case "$quad" in
|
||||
10) quad=a ;; 11) quad=b ;; 12) quad=c ;;
|
||||
13) quad=d ;; 14) quad=e ;; 15) quad=f ;;
|
||||
esac
|
||||
eiface_devid_a=$quad$eiface_devid_a
|
||||
eiface_devid_b=$quad$eiface_devid_b
|
||||
ifconfig "e${i}a_$name" ether $eiface_devid_a > /dev/null 2>&1
|
||||
ifconfig "e${i}b_$name" ether $eiface_devid_b > /dev/null 2>&1
|
||||
eiface_devid_a= eiface_devid_b=
|
||||
[ "$no_derive" ] || derive_mac -2 $iface "$name" \
|
||||
eiface_devid_a eiface_devid_b
|
||||
if [ "$eiface_devid_a" -a "$eiface_devid_b" ]; then
|
||||
ifconfig "e${i}a_$name" ether $eiface_devid_a
|
||||
ifconfig "e${i}b_$name" ether $eiface_devid_b
|
||||
fi > /dev/null 2>&1
|
||||
|
||||
i=$(( $i + 1 )) # on to next e{i}b_name
|
||||
i=$(( $i + 1 ))
|
||||
done # for iface
|
||||
}
|
||||
|
||||
|
@ -166,101 +166,36 @@ usage()
|
||||
|
||||
action_usage()
|
||||
{
|
||||
local usage action="$1"
|
||||
local usage descr action="$1"
|
||||
eval usage=\"\$jng_${action}_usage\"
|
||||
echo "Usage: $pgm $usage" >&2
|
||||
eval descr=\"\$jng_${action}_descr\"
|
||||
printf "\t%s\n" "$descr"
|
||||
exit $FAILURE
|
||||
}
|
||||
|
||||
mustberoot_to_continue()
|
||||
derive_mac()
|
||||
{
|
||||
if [ "$( id -u )" -ne 0 ]; then
|
||||
echo "Must run as root!" >&2
|
||||
exit $FAILURE
|
||||
fi
|
||||
}
|
||||
|
||||
jng_bridge_usage="bridge [-b BRIDGE_NAME] NAME interface0 [interface1 ...]"
|
||||
jng_bridge_descr="Create ng0_NAME [ng1_NAME ...]"
|
||||
jng_bridge()
|
||||
{
|
||||
local OPTIND=1 OPTARG flag bridge=bridge
|
||||
while getopts b: flag; do
|
||||
case "$flag" in
|
||||
b) bridge="$OPTARG"
|
||||
[ "$bridge" ] || action_usage bridge ;; # NOTREACHED
|
||||
*) action_usage bridge # NOTREACHED
|
||||
local OPTIND=1 OPTARG __flag
|
||||
local __mac_num= __make_pair=
|
||||
while getopts 2n: __flag; do
|
||||
case "$__flag" in
|
||||
2) __make_pair=1 ;;
|
||||
n) __mac_num=${OPTARG%%[^0-9]*} ;;
|
||||
esac
|
||||
done
|
||||
shift $(( $OPTIND - 1 ))
|
||||
|
||||
local name="$1"
|
||||
[ "${name:-x}" = "${name#*[!0-9a-zA-Z_]}" -a $# -gt 1 ] ||
|
||||
action_usage bridge # NOTREACHED
|
||||
shift 1 # name
|
||||
|
||||
mustberoot_to_continue
|
||||
|
||||
local iface iface_devid eiface eiface_devid
|
||||
local new num quad i=0
|
||||
for iface in $*; do
|
||||
|
||||
# 0. Make sure the interface doesn't exist already
|
||||
eiface=ng${i}_$name
|
||||
ngctl msg "$eiface:" getifname > /dev/null 2>&1 && continue
|
||||
|
||||
# 1. Bring the interface up
|
||||
ifconfig $iface up || return
|
||||
|
||||
# 2. Set promiscuous mode and don't overwrite src addr
|
||||
ngctl msg $iface: setpromisc 1 || return
|
||||
ngctl msg $iface: setautosrc 0 || return
|
||||
|
||||
# 3. Make sure the interface has been bridged
|
||||
if ! ngctl info ${iface}bridge: > /dev/null 2>&1; then
|
||||
ngctl mkpeer $iface: bridge lower link0 || return
|
||||
ngctl connect $iface: $iface:lower upper link1 ||
|
||||
return
|
||||
ngctl name $iface:lower ${iface}bridge || return
|
||||
if [ ! "$__mac_num" ]; then
|
||||
eval __mac_num=\${_${iface}_num:--1}
|
||||
__mac_num=$(( $__mac_num + 1 ))
|
||||
eval _${iface}_num=\$__mac_num
|
||||
fi
|
||||
|
||||
# 3.5. Optionally create a secondary bridge
|
||||
if [ "$bridge" != "bridge" ] &&
|
||||
! ngctl info "$iface$bridge:" > /dev/null 2>&1
|
||||
then
|
||||
num=2
|
||||
while ngctl msg ${iface}bridge: getstats $num \
|
||||
> /dev/null 2>&1
|
||||
do
|
||||
num=$(( $num + 1 ))
|
||||
done
|
||||
ngctl mkpeer $iface:lower bridge link$num link1 ||
|
||||
return
|
||||
ngctl name ${iface}bridge:link$num "$iface$bridge" ||
|
||||
return
|
||||
fi
|
||||
|
||||
# 4. Create a new interface to the bridge
|
||||
num=2
|
||||
while ngctl msg "$iface$bridge:" getstats $num > /dev/null 2>&1
|
||||
do
|
||||
num=$(( $num + 1 ))
|
||||
done
|
||||
ngctl mkpeer "$iface$bridge:" eiface link$num ether || return
|
||||
|
||||
# 5. Rename the new interface
|
||||
while [ ${#eiface} -gt 15 ]; do # OS limitation
|
||||
eiface=${eiface%?}
|
||||
done
|
||||
new=$( set -- `ngctl show -n "$iface$bridge:link$num"` &&
|
||||
echo $2 ) || return
|
||||
ngctl name "$iface$bridge:link$num" $eiface || return
|
||||
ifconfig $new name $eiface || return
|
||||
ifconfig $eiface up || return
|
||||
|
||||
local __iface="$1" __name="$2" __var_to_set="$3" __var_to_set_b="$4"
|
||||
local __iface_devid __new_devid __num __new_devid_b
|
||||
#
|
||||
# 6. Set the MAC address of the new interface using a sensible
|
||||
# algorithm to prevent conflicts on the network.
|
||||
# Calculate MAC address derived from given iface.
|
||||
#
|
||||
# The formula I'm using is ``NP:SS:SS:II:II:II'' where:
|
||||
# + N denotes 4 bits used as a counter to support branching
|
||||
@ -282,56 +217,153 @@ jng_bridge()
|
||||
# the MAC address will be recalculated to a new, similarly
|
||||
# unique value preventing conflict.
|
||||
#
|
||||
iface_devid=$( ifconfig $iface ether | awk '/ether/,$0=$2' )
|
||||
eiface_devid=${iface_devid#??:??:??}
|
||||
num=$( set -- `echo -n $name | sum` && echo $1 )
|
||||
quad=$(( $num & 15 ))
|
||||
case "$quad" in
|
||||
10) quad=a ;; 11) quad=b ;; 12) quad=c ;;
|
||||
13) quad=d ;; 14) quad=e ;; 15) quad=f ;;
|
||||
__iface_devid=$( ifconfig $__iface ether | awk '/ether/,$0=$2' )
|
||||
# ??:??:??:II:II:II
|
||||
__new_devid=${__iface_devid#??:??:??} # => :II:II:II
|
||||
# => :SS:SS:II:II:II
|
||||
__num=$( set -- `echo -n "$__name" | sum` && echo $1 )
|
||||
__new_devid=$( printf :%02x:%02x \
|
||||
$(( $__num >> 8 & 255 )) $(( $__num & 255 )) )$__new_devid
|
||||
# => P:SS:SS:II:II:II
|
||||
case "$__iface_devid" in
|
||||
?2:*) __new_devid=a$__new_devid __new_devid_b=e$__new_devid ;;
|
||||
?[Ee]:*) __new_devid=2$__new_devid __new_devid_b=6$__new_devid ;;
|
||||
*) __new_devid=2$__new_devid __new_devid_b=e$__new_devid
|
||||
esac
|
||||
eiface_devid=$quad$eiface_devid
|
||||
num=$(( $num >> 4 ))
|
||||
quad=$(( $num & 15 ))
|
||||
case "$quad" in
|
||||
10) quad=a ;; 11) quad=b ;; 12) quad=c ;;
|
||||
13) quad=d ;; 14) quad=e ;; 15) quad=f ;;
|
||||
esac
|
||||
eiface_devid=$quad$eiface_devid
|
||||
num=$(( $num >> 4 ))
|
||||
quad=$(( $num & 15 ))
|
||||
case "$quad" in
|
||||
10) quad=a ;; 11) quad=b ;; 12) quad=c ;;
|
||||
13) quad=d ;; 14) quad=e ;; 15) quad=f ;;
|
||||
esac
|
||||
eiface_devid=$quad:$eiface_devid
|
||||
num=$(( $num >> 4 ))
|
||||
quad=$(( $num & 15 ))
|
||||
case "$quad" in
|
||||
10) quad=a ;; 11) quad=b ;; 12) quad=c ;;
|
||||
13) quad=d ;; 14) quad=e ;; 15) quad=f ;;
|
||||
esac
|
||||
case "$iface_devid" in
|
||||
?2:*) eiface_devid=a:$quad$eiface_devid ;;
|
||||
*) eiface_devid=2:$quad$eiface_devid
|
||||
esac
|
||||
eval num=\$_${iface}_num
|
||||
if [ "$num" ]; then
|
||||
num=$(( $num + 1 ))
|
||||
eval _${iface}_num=$num
|
||||
# => NP:SS:SS:II:II:II
|
||||
__new_devid=$( printf %x $(( $__mac_num & 15 )) )$__new_devid
|
||||
__new_devid_b=$( printf %x $(( $__mac_num & 15 )) )$__new_devid_b
|
||||
|
||||
#
|
||||
# Return derivative MAC address(es)
|
||||
#
|
||||
if [ "$__make_pair" ]; then
|
||||
if [ "$__var_to_set" -a "$__var_to_set_b" ]; then
|
||||
eval $__var_to_set=\$__new_devid
|
||||
eval $__var_to_set_b=\$__new_devid_b
|
||||
else
|
||||
num=0
|
||||
local _${iface}_num=$num
|
||||
echo $__new_devid $__new_devid_b
|
||||
fi
|
||||
quad=$(( $num & 15 ))
|
||||
case "$quad" in
|
||||
10) quad=a ;; 11) quad=b ;; 12) quad=c ;;
|
||||
13) quad=d ;; 14) quad=e ;; 15) quad=f ;;
|
||||
else
|
||||
if [ "$__var_to_set" ]; then
|
||||
eval $__var_to_set=\$__new_devid
|
||||
else
|
||||
echo $__new_devid
|
||||
fi
|
||||
fi
|
||||
}
|
||||
|
||||
mustberoot_to_continue()
|
||||
{
|
||||
if [ "$( id -u )" -ne 0 ]; then
|
||||
echo "Must run as root!" >&2
|
||||
exit $FAILURE
|
||||
fi
|
||||
}
|
||||
|
||||
jng_bridge_usage="bridge [-b BRIDGE_NAME] NAME [!|=]iface0 [[!|=]iface1 ...]"
|
||||
jng_bridge_descr="Create ng0_NAME [ng1_NAME ...]"
|
||||
jng_bridge()
|
||||
{
|
||||
local OPTIND=1 OPTARG flag bridge=bridge
|
||||
while getopts b: flag; do
|
||||
case "$flag" in
|
||||
b) bridge="$OPTARG"
|
||||
[ "$bridge" ] || action_usage bridge ;; # NOTREACHED
|
||||
*) action_usage bridge # NOTREACHED
|
||||
esac
|
||||
eiface_devid=$quad$eiface_devid
|
||||
done
|
||||
shift $(( $OPTIND - 1 ))
|
||||
|
||||
local name="$1"
|
||||
[ "${name:-x}" = "${name#*[!0-9a-zA-Z_]}" -a $# -gt 1 ] ||
|
||||
action_usage bridge # NOTREACHED
|
||||
shift 1 # name
|
||||
|
||||
mustberoot_to_continue
|
||||
|
||||
local iface parent eiface eiface_devid
|
||||
local new clone_mac no_derive num quad i=0
|
||||
for iface in $*; do
|
||||
|
||||
clone_mac=
|
||||
no_derive=
|
||||
case "$iface" in
|
||||
=*) iface=${iface#=} clone_mac=1 ;;
|
||||
!*) iface=${iface#!} no_derive=1 ;;
|
||||
esac
|
||||
|
||||
# Make sure the interface doesn't exist already
|
||||
eiface=ng${i}_$name
|
||||
if ngctl msg "$eiface:" getifname > /dev/null 2>&1; then
|
||||
i=$(( $i + 1 ))
|
||||
continue
|
||||
fi
|
||||
|
||||
# Bring the interface up
|
||||
ifconfig $iface up || return
|
||||
|
||||
# Set promiscuous mode and don't overwrite src addr
|
||||
ngctl msg $iface: setpromisc 1 || return
|
||||
ngctl msg $iface: setautosrc 0 || return
|
||||
|
||||
# Make sure the interface has been bridged
|
||||
if ! ngctl info ${iface}bridge: > /dev/null 2>&1; then
|
||||
ngctl mkpeer $iface: bridge lower link0 || return
|
||||
ngctl connect $iface: $iface:lower upper link1 ||
|
||||
return
|
||||
ngctl name $iface:lower ${iface}bridge || return
|
||||
fi
|
||||
|
||||
# Optionally create a secondary bridge
|
||||
if [ "$bridge" != "bridge" ] &&
|
||||
! ngctl info "$iface$bridge:" > /dev/null 2>&1
|
||||
then
|
||||
num=2
|
||||
while ngctl msg ${iface}bridge: getstats $num \
|
||||
> /dev/null 2>&1
|
||||
do
|
||||
num=$(( $num + 1 ))
|
||||
done
|
||||
ngctl mkpeer $iface:lower bridge link$num link1 ||
|
||||
return
|
||||
ngctl name ${iface}bridge:link$num "$iface$bridge" ||
|
||||
return
|
||||
fi
|
||||
|
||||
# Create a new interface to the bridge
|
||||
num=2
|
||||
while ngctl msg "$iface$bridge:" getstats $num > /dev/null 2>&1
|
||||
do
|
||||
num=$(( $num + 1 ))
|
||||
done
|
||||
ngctl mkpeer "$iface$bridge:" eiface link$num ether || return
|
||||
|
||||
# Rename the new interface
|
||||
while [ ${#eiface} -gt 15 ]; do # OS limitation
|
||||
eiface=${eiface%?}
|
||||
done
|
||||
new=$( set -- `ngctl show -n "$iface$bridge:link$num"` &&
|
||||
echo $2 ) || return
|
||||
ngctl name "$iface$bridge:link$num" $eiface || return
|
||||
ifconfig $new name $eiface || return
|
||||
ifconfig $eiface up || return
|
||||
|
||||
#
|
||||
# Set the MAC address of the new interface using a sensible
|
||||
# algorithm to prevent conflicts on the network.
|
||||
#
|
||||
eiface_devid=
|
||||
if [ "$clone_mac" ]; then
|
||||
eiface_devid=$( ifconfig $iface ether |
|
||||
awk '/ether/,$0=$2' )
|
||||
elif [ ! "$no_derive" ]; then
|
||||
derive_mac $iface "$name" eiface_devid
|
||||
fi
|
||||
[ "$eiface_devid" ] &&
|
||||
ifconfig $eiface ether $eiface_devid > /dev/null 2>&1
|
||||
|
||||
i=$(( $i + 1 )) # on to next ng{i}_name
|
||||
i=$(( $i + 1 ))
|
||||
done # for iface
|
||||
}
|
||||
|
||||
|
@ -24,7 +24,7 @@
|
||||
.\"
|
||||
.\" $FreeBSD$
|
||||
.\"
|
||||
.Dd March 6, 2015
|
||||
.Dd February 12, 2016
|
||||
.Dt DS3231 4
|
||||
.Os
|
||||
.Sh NAME
|
||||
@ -110,8 +110,11 @@ that the
|
||||
.Nm
|
||||
is connected to.
|
||||
.It Va hint.ds3231.%d.addr
|
||||
The i2c address of
|
||||
The 8-bit i2c address of
|
||||
.Nm .
|
||||
The default 8-bit address for
|
||||
.Nm
|
||||
is 0xd0.
|
||||
.El
|
||||
.Pp
|
||||
On a
|
||||
@ -121,11 +124,11 @@ based system the following properties must be set:
|
||||
.It Va compatible
|
||||
Must always be set to "maxim,ds3231".
|
||||
.It Va reg
|
||||
The i2c address of
|
||||
The 7-bit i2c address of
|
||||
.Nm .
|
||||
The default address for
|
||||
The default 7-bit address for
|
||||
.Nm
|
||||
is 0xd0.
|
||||
is 0x68.
|
||||
.El
|
||||
.Sh SEE ALSO
|
||||
.Xr fdt 4 ,
|
||||
|
@ -24,7 +24,7 @@
|
||||
.\"
|
||||
.\" $FreeBSD$
|
||||
.\"
|
||||
.Dd October 9, 2015
|
||||
.Dd February 12, 2016
|
||||
.Dt RC.CONF 5
|
||||
.Os
|
||||
.Sh NAME
|
||||
@ -3853,20 +3853,22 @@ for every jail in
|
||||
.Va jail_list .
|
||||
.It Va jail_list
|
||||
.Pq Vt str
|
||||
A space separated list of names for jails.
|
||||
If this variable is empty,
|
||||
all of
|
||||
A space-delimited list of jail names.
|
||||
When left empty, all of the
|
||||
.Xr jail 8
|
||||
instances in the configuration file will be configured.
|
||||
This is purely a configuration aid to help identify and
|
||||
configure multiple jails.
|
||||
The names specified in this list will be used to
|
||||
identify settings common to an instance of a jail,
|
||||
and should contain alphanumeric characters only.
|
||||
The literal jail name of
|
||||
.Dq Li 0
|
||||
.Pq zero
|
||||
is not allowed.
|
||||
instances defined in the configuration file are started.
|
||||
The names specified in this list control the jail startup order.
|
||||
.Xr jail 8
|
||||
instances missing from
|
||||
.Va jail_list
|
||||
must be started manually.
|
||||
.It Va jail_reverse_stop
|
||||
.Pq Vt bool
|
||||
When set to
|
||||
.Dq Li YES ,
|
||||
all configured jails in
|
||||
.Va jail_list
|
||||
are stopped in reverse order.
|
||||
.It Va jail_* variables
|
||||
Note that older releases supported per-jail configuration via
|
||||
.Xr rc.conf 5
|
||||
|
@ -39,6 +39,7 @@ _INTERNALLIBS= \
|
||||
openbsd \
|
||||
opts \
|
||||
parse \
|
||||
pe \
|
||||
readline \
|
||||
sl \
|
||||
sm \
|
||||
@ -367,6 +368,9 @@ LDADD+= ${LDADD_${_l}}
|
||||
LIBELFTCDIR= ${OBJTOP}/lib/libelftc
|
||||
LIBELFTC?= ${LIBELFTCDIR}/libelftc.a
|
||||
|
||||
LIBPEDIR= ${OBJTOP}/lib/libpe
|
||||
LIBPE?= ${LIBPEDIR}/libpe.a
|
||||
|
||||
LIBREADLINEDIR= ${OBJTOP}/gnu/lib/libreadline/readline
|
||||
LIBREADLINE?= ${LIBREADLINEDIR}/libreadline.a
|
||||
|
||||
|
@ -401,10 +401,9 @@ mv_twsi_attach(device_t dev)
|
||||
for (child = OF_child(ofw_bus_get_node(dev)); child != 0;
|
||||
child = OF_peer(child)) {
|
||||
len = OF_getproplen(child, "model");
|
||||
if (len <= 0 || len > sizeof(dname) - 1)
|
||||
if (len <= 0 || len > sizeof(dname))
|
||||
continue;
|
||||
error = OF_getprop(child, "model", &dname, len);
|
||||
dname[len + 1] = '\0';
|
||||
if (error == -1)
|
||||
continue;
|
||||
len = strlen(dname);
|
||||
@ -428,10 +427,9 @@ mv_twsi_attach(device_t dev)
|
||||
|
||||
/* Get device driver name. */
|
||||
len = OF_getproplen(child, "model");
|
||||
if (len <= 0 || len > sizeof(dname) - 1)
|
||||
if (len <= 0 || len > sizeof(dname))
|
||||
continue;
|
||||
OF_getprop(child, "model", &dname, len);
|
||||
dname[len + 1] = '\0';
|
||||
|
||||
if (bootverbose)
|
||||
device_printf(dev, "adding a device %s at %d.\n",
|
||||
|
@ -129,12 +129,6 @@ END(cpu_throw)
|
||||
* x3 to x7, x16 and x17 are caller saved
|
||||
*/
|
||||
ENTRY(cpu_switch)
|
||||
/* Store the new curthread */
|
||||
str x1, [x18, #PC_CURTHREAD]
|
||||
/* And the new pcb */
|
||||
ldr x4, [x1, #TD_PCB]
|
||||
str x4, [x18, #PC_CURPCB]
|
||||
|
||||
/*
|
||||
* Save the old context.
|
||||
*/
|
||||
@ -174,10 +168,14 @@ ENTRY(cpu_switch)
|
||||
mov x0, x19
|
||||
#endif
|
||||
|
||||
/* Store the new curthread */
|
||||
str x1, [x18, #PC_CURTHREAD]
|
||||
|
||||
/*
|
||||
* Restore the saved context.
|
||||
* Restore the saved context and set it as curpcb.
|
||||
*/
|
||||
ldr x4, [x1, #TD_PCB]
|
||||
str x4, [x18, #PC_CURPCB]
|
||||
|
||||
/*
|
||||
* TODO: We may need to flush the cache here if switching
|
||||
|
@ -126,7 +126,6 @@ enum {
|
||||
CPL_RDMA_IMM_DATA_SE = 0xAD,
|
||||
|
||||
CPL_TRACE_PKT = 0xB0,
|
||||
CPL_TRACE_PKT_T5 = 0x48,
|
||||
CPL_RX2TX_DATA = 0xB1,
|
||||
CPL_ISCSI_DATA = 0xB2,
|
||||
CPL_FCOE_DATA = 0xB3,
|
||||
|
@ -708,7 +708,7 @@ t4_attach(device_t dev)
|
||||
sc->fw_msg_handler[i] = fw_msg_not_handled;
|
||||
t4_register_cpl_handler(sc, CPL_SET_TCB_RPL, t4_filter_rpl);
|
||||
t4_register_cpl_handler(sc, CPL_TRACE_PKT, t4_trace_pkt);
|
||||
t4_register_cpl_handler(sc, CPL_TRACE_PKT_T5, t5_trace_pkt);
|
||||
t4_register_cpl_handler(sc, CPL_T5_TRACE_PKT, t5_trace_pkt);
|
||||
t4_init_sge_cpl_handlers(sc);
|
||||
|
||||
/* Prepare the adapter for operation */
|
||||
|
@ -103,6 +103,7 @@ static int core_iaf_npmc;
|
||||
|
||||
static int core_iap_width;
|
||||
static int core_iap_npmc;
|
||||
static int core_iap_wroffset;
|
||||
|
||||
static int
|
||||
core_pcpu_noop(struct pmc_mdep *md, int cpu)
|
||||
@ -2473,7 +2474,7 @@ iap_read_pmc(int cpu, int ri, pmc_value_t *v)
|
||||
*v = tmp & ((1ULL << core_iap_width) - 1);
|
||||
|
||||
PMCDBG4(MDP,REA,1, "iap-read cpu=%d ri=%d msr=0x%x -> v=%jx", cpu, ri,
|
||||
ri, *v);
|
||||
IAP_PMC0 + ri, *v);
|
||||
|
||||
return (0);
|
||||
}
|
||||
@ -2605,19 +2606,20 @@ iap_write_pmc(int cpu, int ri, pmc_value_t v)
|
||||
("[core,%d] cpu%d ri%d no configured PMC to stop", __LINE__,
|
||||
cpu, ri));
|
||||
|
||||
PMCDBG4(MDP,WRI,1, "iap-write cpu=%d ri=%d msr=0x%x v=%jx", cpu, ri,
|
||||
IAP_PMC0 + ri, v);
|
||||
|
||||
if (PMC_IS_SAMPLING_MODE(PMC_TO_MODE(pm)))
|
||||
v = iap_reload_count_to_perfctr_value(v);
|
||||
|
||||
v &= (1ULL << core_iap_width) - 1;
|
||||
|
||||
PMCDBG4(MDP,WRI,1, "iap-write cpu=%d ri=%d msr=0x%x v=%jx", cpu, ri,
|
||||
IAP_PMC0 + ri, v);
|
||||
|
||||
/*
|
||||
* Write the new value to the counter. The counter will be in
|
||||
* a stopped state when the pcd_write() entry point is called.
|
||||
* Write the new value to the counter (or it's alias). The
|
||||
* counter will be in a stopped state when the pcd_write()
|
||||
* entry point is called.
|
||||
*/
|
||||
|
||||
wrmsr(IAP_PMC0 + ri, v & ((1ULL << core_iap_width) - 1));
|
||||
|
||||
wrmsr(core_iap_wroffset + IAP_PMC0 + ri, v);
|
||||
return (0);
|
||||
}
|
||||
|
||||
@ -2700,7 +2702,7 @@ core_intr(int cpu, struct trapframe *tf)
|
||||
*/
|
||||
msr = rdmsr(IAP_EVSEL0 + ri) & ~IAP_EVSEL_MASK;
|
||||
wrmsr(IAP_EVSEL0 + ri, msr);
|
||||
wrmsr(IAP_PMC0 + ri, v);
|
||||
wrmsr(core_iap_wroffset + IAP_PMC0 + ri, v);
|
||||
|
||||
if (error)
|
||||
continue;
|
||||
@ -2814,7 +2816,7 @@ core2_intr(int cpu, struct trapframe *tf)
|
||||
(uintmax_t) v);
|
||||
|
||||
/* Reload sampling count. */
|
||||
wrmsr(IAP_PMC0 + n, v);
|
||||
wrmsr(core_iap_wroffset + IAP_PMC0 + n, v);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -2865,6 +2867,18 @@ pmc_core_initialize(struct pmc_mdep *md, int maxcpu, int version_override)
|
||||
return (EPROGMISMATCH);
|
||||
}
|
||||
|
||||
core_iap_wroffset = 0;
|
||||
if (cpu_feature2 & CPUID2_PDCM) {
|
||||
if (rdmsr(IA32_PERF_CAPABILITIES) & PERFCAP_FW_WRITE) {
|
||||
PMCDBG0(MDP, INI, 1,
|
||||
"core-init full-width write supported");
|
||||
core_iap_wroffset = IAP_A_PMC0 - IAP_PMC0;
|
||||
} else
|
||||
PMCDBG0(MDP, INI, 1,
|
||||
"core-init full-width write NOT supported");
|
||||
} else
|
||||
PMCDBG0(MDP, INI, 1, "core-init pdcm not supported");
|
||||
|
||||
core_pmcmask = 0;
|
||||
|
||||
/*
|
||||
|
@ -29,6 +29,14 @@
|
||||
#ifndef _DEV_HWPMC_CORE_H_
|
||||
#define _DEV_HWPMC_CORE_H_ 1
|
||||
|
||||
#define IA32_PERF_CAPABILITIES 0x345
|
||||
#define PERFCAP_LBR_FORMAT 0x003f
|
||||
#define PERFCAP_PEBS_TRAP 0x0040
|
||||
#define PERFCAP_PEBS_SAVEARCH 0x0080
|
||||
#define PERFCAP_PEBS_RECFORMAT 0x0f00
|
||||
#define PERFCAP_SMM_FREEZE 0x1000
|
||||
#define PERFCAP_FW_WRITE 0x2000 /* full width write aliases */
|
||||
|
||||
/*
|
||||
* Fixed-function PMCs.
|
||||
*/
|
||||
@ -101,6 +109,7 @@ struct pmc_md_iap_op_pmcallocate {
|
||||
*/
|
||||
|
||||
#define IAP_PMC0 0x0C1
|
||||
#define IAP_A_PMC0 0x4C1
|
||||
|
||||
/*
|
||||
* IAP_EVSEL(n) is laid out in the following way.
|
||||
|
@ -1483,7 +1483,7 @@ pmc_process_csw_out(struct thread *td)
|
||||
* increasing monotonically, modulo a 64
|
||||
* bit wraparound.
|
||||
*/
|
||||
KASSERT((int64_t) tmp >= 0,
|
||||
KASSERT(tmp >= 0,
|
||||
("[pmc,%d] negative increment cpu=%d "
|
||||
"ri=%d newvalue=%jx saved=%jx "
|
||||
"incr=%jx", __LINE__, cpu, ri,
|
||||
|
@ -630,8 +630,14 @@ ioat_process_events(struct ioat_softc *ioat)
|
||||
|
||||
CTR0(KTR_IOAT, __func__);
|
||||
|
||||
if (status == ioat->last_seen)
|
||||
if (status == ioat->last_seen) {
|
||||
/*
|
||||
* If we landed in process_events and nothing has been
|
||||
* completed, check for a timeout due to channel halt.
|
||||
*/
|
||||
comp_update = ioat_get_chansts(ioat);
|
||||
goto out;
|
||||
}
|
||||
|
||||
while (1) {
|
||||
desc = ioat_get_ring_entry(ioat, ioat->tail);
|
||||
@ -661,8 +667,10 @@ ioat_process_events(struct ioat_softc *ioat)
|
||||
ioat_write_chanctrl(ioat, IOAT_CHANCTRL_RUN);
|
||||
mtx_unlock(&ioat->cleanup_lock);
|
||||
|
||||
if (completed != 0) {
|
||||
ioat_putn(ioat, completed, IOAT_ACTIVE_DESCR_REF);
|
||||
wakeup(&ioat->tail);
|
||||
}
|
||||
|
||||
if (!is_ioat_halted(comp_update))
|
||||
return;
|
||||
|
@ -659,6 +659,7 @@ lpc_ns8250_bus_ipend(struct uart_softc *sc)
|
||||
if (iir & IIR_TXRDY) {
|
||||
ipend |= SER_INT_TXIDLE;
|
||||
uart_setreg(bas, REG_IER, lpc_ns8250->ier);
|
||||
uart_barrier(bas);
|
||||
} else
|
||||
ipend |= SER_INT_SIGCHG;
|
||||
}
|
||||
@ -892,12 +893,12 @@ lpc_ns8250_bus_transmit(struct uart_softc *sc)
|
||||
uart_lock(sc->sc_hwmtx);
|
||||
while ((uart_getreg(bas, REG_LSR) & LSR_THRE) == 0)
|
||||
;
|
||||
uart_setreg(bas, REG_IER, lpc_ns8250->ier | IER_ETXRDY);
|
||||
uart_barrier(bas);
|
||||
for (i = 0; i < sc->sc_txdatasz; i++) {
|
||||
uart_setreg(bas, REG_DATA, sc->sc_txbuf[i]);
|
||||
uart_barrier(bas);
|
||||
}
|
||||
uart_setreg(bas, REG_IER, lpc_ns8250->ier | IER_ETXRDY);
|
||||
uart_barrier(bas);
|
||||
sc->sc_txbusy = 1;
|
||||
uart_unlock(sc->sc_hwmtx);
|
||||
return (0);
|
||||
|
@ -708,6 +708,7 @@ ns8250_bus_ipend(struct uart_softc *sc)
|
||||
if (iir & IIR_TXRDY) {
|
||||
ipend |= SER_INT_TXIDLE;
|
||||
uart_setreg(bas, REG_IER, ns8250->ier);
|
||||
uart_barrier(bas);
|
||||
} else
|
||||
ipend |= SER_INT_SIGCHG;
|
||||
}
|
||||
@ -979,12 +980,12 @@ ns8250_bus_transmit(struct uart_softc *sc)
|
||||
uart_lock(sc->sc_hwmtx);
|
||||
while ((uart_getreg(bas, REG_LSR) & LSR_THRE) == 0)
|
||||
;
|
||||
uart_setreg(bas, REG_IER, ns8250->ier | IER_ETXRDY);
|
||||
uart_barrier(bas);
|
||||
for (i = 0; i < sc->sc_txdatasz; i++) {
|
||||
uart_setreg(bas, REG_DATA, sc->sc_txbuf[i]);
|
||||
uart_barrier(bas);
|
||||
}
|
||||
uart_setreg(bas, REG_IER, ns8250->ier | IER_ETXRDY);
|
||||
uart_barrier(bas);
|
||||
if (broken_txfifo)
|
||||
ns8250_drain(bas, UART_DRAIN_TRANSMITTER);
|
||||
else
|
||||
|
@ -309,13 +309,13 @@ iso_mountfs(devvp, mp)
|
||||
default:
|
||||
break;
|
||||
}
|
||||
if (bp) {
|
||||
if (bp != NULL) {
|
||||
brelse(bp);
|
||||
bp = NULL;
|
||||
}
|
||||
}
|
||||
vd_end:
|
||||
if (bp) {
|
||||
if (bp != NULL) {
|
||||
brelse(bp);
|
||||
bp = NULL;
|
||||
}
|
||||
@ -474,11 +474,11 @@ iso_mountfs(devvp, mp)
|
||||
|
||||
return 0;
|
||||
out:
|
||||
if (bp)
|
||||
if (bp != NULL)
|
||||
brelse(bp);
|
||||
if (pribp)
|
||||
if (pribp != NULL)
|
||||
brelse(pribp);
|
||||
if (supbp)
|
||||
if (supbp != NULL)
|
||||
brelse(supbp);
|
||||
if (cp != NULL) {
|
||||
DROP_GIANT();
|
||||
@ -751,7 +751,6 @@ cd9660_vget_internal(mp, ino, flags, vpp, relocated, isodir)
|
||||
#if 0
|
||||
if (isonum_733(isodir->extent) +
|
||||
isonum_711(isodir->ext_attr_length) != ifhp->ifid_start) {
|
||||
if (bp != 0)
|
||||
brelse(bp);
|
||||
printf("fhtovp: file start miss %d vs %d\n",
|
||||
isonum_733(isodir->extent) + isonum_711(isodir->ext_attr_length),
|
||||
@ -770,7 +769,7 @@ cd9660_vget_internal(mp, ino, flags, vpp, relocated, isodir)
|
||||
* read the `.' entry out of a dir.
|
||||
*/
|
||||
ip->iso_start = ino >> imp->im_bshift;
|
||||
if (bp != 0)
|
||||
if (bp != NULL)
|
||||
brelse(bp);
|
||||
if ((error = cd9660_blkatoff(vp, (off_t)0, NULL, &bp)) != 0) {
|
||||
vput(vp);
|
||||
@ -809,7 +808,6 @@ cd9660_vget_internal(mp, ino, flags, vpp, relocated, isodir)
|
||||
break;
|
||||
}
|
||||
|
||||
if (bp != 0)
|
||||
brelse(bp);
|
||||
|
||||
/*
|
||||
|
@ -1191,8 +1191,11 @@ tmpfs_readdir(struct vop_readdir_args *v)
|
||||
if (error == EJUSTRETURN)
|
||||
error = (uio->uio_resid != startresid) ? 0 : EINVAL;
|
||||
|
||||
if (error != 0 && cookies != NULL)
|
||||
if (error != 0 && cookies != NULL && ncookies != NULL) {
|
||||
free(*cookies, M_TEMP);
|
||||
*cookies = NULL;
|
||||
*ncookies = 0;
|
||||
}
|
||||
|
||||
if (eofflag != NULL)
|
||||
*eofflag =
|
||||
|
@ -44,8 +44,6 @@ __FBSDID("$FreeBSD$");
|
||||
#include <sys/smp.h>
|
||||
#include <sys/sysctl.h>
|
||||
|
||||
#include <security/mac/mac_framework.h>
|
||||
|
||||
#include <vm/vm.h>
|
||||
#include <vm/vm_extern.h>
|
||||
#include <vm/vm_kern.h>
|
||||
@ -284,7 +282,6 @@ static void mb_dtor_clust(void *, int, void *);
|
||||
static void mb_dtor_pack(void *, int, void *);
|
||||
static int mb_zinit_pack(void *, int, int);
|
||||
static void mb_zfini_pack(void *, int);
|
||||
|
||||
static void mb_reclaim(uma_zone_t, int);
|
||||
static void *mbuf_jumbo_alloc(uma_zone_t, vm_size_t, uint8_t *, int);
|
||||
|
||||
@ -644,24 +641,6 @@ mb_ctor_pack(void *mem, int size, void *arg, int how)
|
||||
return (error);
|
||||
}
|
||||
|
||||
int
|
||||
m_pkthdr_init(struct mbuf *m, int how)
|
||||
{
|
||||
#ifdef MAC
|
||||
int error;
|
||||
#endif
|
||||
m->m_data = m->m_pktdat;
|
||||
bzero(&m->m_pkthdr, sizeof(m->m_pkthdr));
|
||||
#ifdef MAC
|
||||
/* If the label init fails, fail the alloc */
|
||||
error = mac_mbuf_init(m, how);
|
||||
if (error)
|
||||
return (error);
|
||||
#endif
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
/*
|
||||
* This is the protocol drain routine. Called by UMA whenever any of the
|
||||
* mbuf zones is closed to its limit.
|
||||
@ -683,3 +662,323 @@ mb_reclaim(uma_zone_t zone __unused, int pending __unused)
|
||||
if (pr->pr_drain != NULL)
|
||||
(*pr->pr_drain)();
|
||||
}
|
||||
|
||||
/*
|
||||
* Clean up after mbufs with M_EXT storage attached to them if the
|
||||
* reference count hits 1.
|
||||
*/
|
||||
void
|
||||
mb_free_ext(struct mbuf *m)
|
||||
{
|
||||
int freembuf;
|
||||
|
||||
KASSERT(m->m_flags & M_EXT, ("%s: M_EXT not set on %p", __func__, m));
|
||||
|
||||
/*
|
||||
* Check if the header is embedded in the cluster.
|
||||
*/
|
||||
freembuf = (m->m_flags & M_NOFREE) ? 0 : 1;
|
||||
|
||||
switch (m->m_ext.ext_type) {
|
||||
case EXT_SFBUF:
|
||||
sf_ext_free(m->m_ext.ext_arg1, m->m_ext.ext_arg2);
|
||||
break;
|
||||
case EXT_SFBUF_NOCACHE:
|
||||
sf_ext_free_nocache(m->m_ext.ext_arg1, m->m_ext.ext_arg2);
|
||||
break;
|
||||
default:
|
||||
KASSERT(m->m_ext.ext_cnt != NULL,
|
||||
("%s: no refcounting pointer on %p", __func__, m));
|
||||
/*
|
||||
* Free attached storage if this mbuf is the only
|
||||
* reference to it.
|
||||
*/
|
||||
if (*(m->m_ext.ext_cnt) != 1) {
|
||||
if (atomic_fetchadd_int(m->m_ext.ext_cnt, -1) != 1)
|
||||
break;
|
||||
}
|
||||
|
||||
switch (m->m_ext.ext_type) {
|
||||
case EXT_PACKET: /* The packet zone is special. */
|
||||
if (*(m->m_ext.ext_cnt) == 0)
|
||||
*(m->m_ext.ext_cnt) = 1;
|
||||
uma_zfree(zone_pack, m);
|
||||
return; /* Job done. */
|
||||
case EXT_CLUSTER:
|
||||
uma_zfree(zone_clust, m->m_ext.ext_buf);
|
||||
break;
|
||||
case EXT_JUMBOP:
|
||||
uma_zfree(zone_jumbop, m->m_ext.ext_buf);
|
||||
break;
|
||||
case EXT_JUMBO9:
|
||||
uma_zfree(zone_jumbo9, m->m_ext.ext_buf);
|
||||
break;
|
||||
case EXT_JUMBO16:
|
||||
uma_zfree(zone_jumbo16, m->m_ext.ext_buf);
|
||||
break;
|
||||
case EXT_NET_DRV:
|
||||
case EXT_MOD_TYPE:
|
||||
case EXT_DISPOSABLE:
|
||||
*(m->m_ext.ext_cnt) = 0;
|
||||
uma_zfree(zone_ext_refcnt, __DEVOLATILE(u_int *,
|
||||
m->m_ext.ext_cnt));
|
||||
/* FALLTHROUGH */
|
||||
case EXT_EXTREF:
|
||||
KASSERT(m->m_ext.ext_free != NULL,
|
||||
("%s: ext_free not set", __func__));
|
||||
(*(m->m_ext.ext_free))(m, m->m_ext.ext_arg1,
|
||||
m->m_ext.ext_arg2);
|
||||
break;
|
||||
default:
|
||||
KASSERT(m->m_ext.ext_type == 0,
|
||||
("%s: unknown ext_type", __func__));
|
||||
}
|
||||
}
|
||||
|
||||
if (freembuf)
|
||||
uma_zfree(zone_mbuf, m);
|
||||
}
|
||||
|
||||
/*
|
||||
* Official mbuf(9) allocation KPI for stack and drivers:
|
||||
*
|
||||
* m_get() - a single mbuf without any attachments, sys/mbuf.h.
|
||||
* m_gethdr() - a single mbuf initialized as M_PKTHDR, sys/mbuf.h.
|
||||
* m_getcl() - an mbuf + 2k cluster, sys/mbuf.h.
|
||||
* m_clget() - attach cluster to already allocated mbuf.
|
||||
* m_cljget() - attach jumbo cluster to already allocated mbuf.
|
||||
* m_get2() - allocate minimum mbuf that would fit size argument.
|
||||
* m_getm2() - allocate a chain of mbufs/clusters.
|
||||
* m_extadd() - attach external cluster to mbuf.
|
||||
*
|
||||
* m_free() - free single mbuf with its tags and ext, sys/mbuf.h.
|
||||
* m_freem() - free chain of mbufs.
|
||||
*/
|
||||
|
||||
int
|
||||
m_clget(struct mbuf *m, int how)
|
||||
{
|
||||
|
||||
KASSERT((m->m_flags & M_EXT) == 0, ("%s: mbuf %p has M_EXT",
|
||||
__func__, m));
|
||||
m->m_ext.ext_buf = (char *)NULL;
|
||||
uma_zalloc_arg(zone_clust, m, how);
|
||||
/*
|
||||
* On a cluster allocation failure, drain the packet zone and retry,
|
||||
* we might be able to loosen a few clusters up on the drain.
|
||||
*/
|
||||
if ((how & M_NOWAIT) && (m->m_ext.ext_buf == NULL)) {
|
||||
zone_drain(zone_pack);
|
||||
uma_zalloc_arg(zone_clust, m, how);
|
||||
}
|
||||
return (m->m_flags & M_EXT);
|
||||
}
|
||||
|
||||
/*
|
||||
* m_cljget() is different from m_clget() as it can allocate clusters without
|
||||
* attaching them to an mbuf. In that case the return value is the pointer
|
||||
* to the cluster of the requested size. If an mbuf was specified, it gets
|
||||
* the cluster attached to it and the return value can be safely ignored.
|
||||
* For size it takes MCLBYTES, MJUMPAGESIZE, MJUM9BYTES, MJUM16BYTES.
|
||||
*/
|
||||
void *
|
||||
m_cljget(struct mbuf *m, int how, int size)
|
||||
{
|
||||
uma_zone_t zone;
|
||||
|
||||
if (m != NULL) {
|
||||
KASSERT((m->m_flags & M_EXT) == 0, ("%s: mbuf %p has M_EXT",
|
||||
__func__, m));
|
||||
m->m_ext.ext_buf = NULL;
|
||||
}
|
||||
|
||||
zone = m_getzone(size);
|
||||
return (uma_zalloc_arg(zone, m, how));
|
||||
}
|
||||
|
||||
/*
|
||||
* m_get2() allocates minimum mbuf that would fit "size" argument.
|
||||
*/
|
||||
struct mbuf *
|
||||
m_get2(int size, int how, short type, int flags)
|
||||
{
|
||||
struct mb_args args;
|
||||
struct mbuf *m, *n;
|
||||
|
||||
args.flags = flags;
|
||||
args.type = type;
|
||||
|
||||
if (size <= MHLEN || (size <= MLEN && (flags & M_PKTHDR) == 0))
|
||||
return (uma_zalloc_arg(zone_mbuf, &args, how));
|
||||
if (size <= MCLBYTES)
|
||||
return (uma_zalloc_arg(zone_pack, &args, how));
|
||||
|
||||
if (size > MJUMPAGESIZE)
|
||||
return (NULL);
|
||||
|
||||
m = uma_zalloc_arg(zone_mbuf, &args, how);
|
||||
if (m == NULL)
|
||||
return (NULL);
|
||||
|
||||
n = uma_zalloc_arg(zone_jumbop, m, how);
|
||||
if (n == NULL) {
|
||||
uma_zfree(zone_mbuf, m);
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
return (m);
|
||||
}
|
||||
|
||||
/*
|
||||
* m_getjcl() returns an mbuf with a cluster of the specified size attached.
|
||||
* For size it takes MCLBYTES, MJUMPAGESIZE, MJUM9BYTES, MJUM16BYTES.
|
||||
*/
|
||||
struct mbuf *
|
||||
m_getjcl(int how, short type, int flags, int size)
|
||||
{
|
||||
struct mb_args args;
|
||||
struct mbuf *m, *n;
|
||||
uma_zone_t zone;
|
||||
|
||||
if (size == MCLBYTES)
|
||||
return m_getcl(how, type, flags);
|
||||
|
||||
args.flags = flags;
|
||||
args.type = type;
|
||||
|
||||
m = uma_zalloc_arg(zone_mbuf, &args, how);
|
||||
if (m == NULL)
|
||||
return (NULL);
|
||||
|
||||
zone = m_getzone(size);
|
||||
n = uma_zalloc_arg(zone, m, how);
|
||||
if (n == NULL) {
|
||||
uma_zfree(zone_mbuf, m);
|
||||
return (NULL);
|
||||
}
|
||||
return (m);
|
||||
}
|
||||
|
||||
/*
|
||||
* Allocate a given length worth of mbufs and/or clusters (whatever fits
|
||||
* best) and return a pointer to the top of the allocated chain. If an
|
||||
* existing mbuf chain is provided, then we will append the new chain
|
||||
* to the existing one but still return the top of the newly allocated
|
||||
* chain.
|
||||
*/
|
||||
struct mbuf *
|
||||
m_getm2(struct mbuf *m, int len, int how, short type, int flags)
|
||||
{
|
||||
struct mbuf *mb, *nm = NULL, *mtail = NULL;
|
||||
|
||||
KASSERT(len >= 0, ("%s: len is < 0", __func__));
|
||||
|
||||
/* Validate flags. */
|
||||
flags &= (M_PKTHDR | M_EOR);
|
||||
|
||||
/* Packet header mbuf must be first in chain. */
|
||||
if ((flags & M_PKTHDR) && m != NULL)
|
||||
flags &= ~M_PKTHDR;
|
||||
|
||||
/* Loop and append maximum sized mbufs to the chain tail. */
|
||||
while (len > 0) {
|
||||
if (len > MCLBYTES)
|
||||
mb = m_getjcl(how, type, (flags & M_PKTHDR),
|
||||
MJUMPAGESIZE);
|
||||
else if (len >= MINCLSIZE)
|
||||
mb = m_getcl(how, type, (flags & M_PKTHDR));
|
||||
else if (flags & M_PKTHDR)
|
||||
mb = m_gethdr(how, type);
|
||||
else
|
||||
mb = m_get(how, type);
|
||||
|
||||
/* Fail the whole operation if one mbuf can't be allocated. */
|
||||
if (mb == NULL) {
|
||||
if (nm != NULL)
|
||||
m_freem(nm);
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
/* Book keeping. */
|
||||
len -= M_SIZE(mb);
|
||||
if (mtail != NULL)
|
||||
mtail->m_next = mb;
|
||||
else
|
||||
nm = mb;
|
||||
mtail = mb;
|
||||
flags &= ~M_PKTHDR; /* Only valid on the first mbuf. */
|
||||
}
|
||||
if (flags & M_EOR)
|
||||
mtail->m_flags |= M_EOR; /* Only valid on the last mbuf. */
|
||||
|
||||
/* If mbuf was supplied, append new chain to the end of it. */
|
||||
if (m != NULL) {
|
||||
for (mtail = m; mtail->m_next != NULL; mtail = mtail->m_next)
|
||||
;
|
||||
mtail->m_next = nm;
|
||||
mtail->m_flags &= ~M_EOR;
|
||||
} else
|
||||
m = nm;
|
||||
|
||||
return (m);
|
||||
}
|
||||
|
||||
/*-
|
||||
* Configure a provided mbuf to refer to the provided external storage
|
||||
* buffer and setup a reference count for said buffer. If the setting
|
||||
* up of the reference count fails, the M_EXT bit will not be set. If
|
||||
* successfull, the M_EXT bit is set in the mbuf's flags.
|
||||
*
|
||||
* Arguments:
|
||||
* mb The existing mbuf to which to attach the provided buffer.
|
||||
* buf The address of the provided external storage buffer.
|
||||
* size The size of the provided buffer.
|
||||
* freef A pointer to a routine that is responsible for freeing the
|
||||
* provided external storage buffer.
|
||||
* args A pointer to an argument structure (of any type) to be passed
|
||||
* to the provided freef routine (may be NULL).
|
||||
* flags Any other flags to be passed to the provided mbuf.
|
||||
* type The type that the external storage buffer should be
|
||||
* labeled with.
|
||||
*
|
||||
* Returns:
|
||||
* Nothing.
|
||||
*/
|
||||
int
|
||||
m_extadd(struct mbuf *mb, caddr_t buf, u_int size,
|
||||
void (*freef)(struct mbuf *, void *, void *), void *arg1, void *arg2,
|
||||
int flags, int type, int wait)
|
||||
{
|
||||
KASSERT(type != EXT_CLUSTER, ("%s: EXT_CLUSTER not allowed", __func__));
|
||||
|
||||
if (type != EXT_EXTREF)
|
||||
mb->m_ext.ext_cnt = uma_zalloc(zone_ext_refcnt, wait);
|
||||
|
||||
if (mb->m_ext.ext_cnt == NULL)
|
||||
return (ENOMEM);
|
||||
|
||||
*(mb->m_ext.ext_cnt) = 1;
|
||||
mb->m_flags |= (M_EXT | flags);
|
||||
mb->m_ext.ext_buf = buf;
|
||||
mb->m_data = mb->m_ext.ext_buf;
|
||||
mb->m_ext.ext_size = size;
|
||||
mb->m_ext.ext_free = freef;
|
||||
mb->m_ext.ext_arg1 = arg1;
|
||||
mb->m_ext.ext_arg2 = arg2;
|
||||
mb->m_ext.ext_type = type;
|
||||
mb->m_ext.ext_flags = 0;
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
/*
|
||||
* Free an entire chain of mbufs and associated external buffers, if
|
||||
* applicable.
|
||||
*/
|
||||
void
|
||||
m_freem(struct mbuf *mb)
|
||||
{
|
||||
|
||||
while (mb != NULL)
|
||||
mb = m_free(mb);
|
||||
}
|
||||
|
@ -48,6 +48,8 @@ __FBSDID("$FreeBSD$");
|
||||
#include <sys/protosw.h>
|
||||
#include <sys/uio.h>
|
||||
|
||||
#include <security/mac/mac_framework.h>
|
||||
|
||||
int max_linkhdr;
|
||||
int max_protohdr;
|
||||
int max_hdr;
|
||||
@ -131,269 +133,6 @@ CTASSERT(sizeof(m_assertbuf.m_slistpkt) == sizeof(m_assertbuf.m_nextpkt));
|
||||
CTASSERT(sizeof(m_assertbuf.m_stailqpkt) == sizeof(m_assertbuf.m_nextpkt));
|
||||
#endif
|
||||
|
||||
/*
|
||||
* m_get2() allocates minimum mbuf that would fit "size" argument.
|
||||
*/
|
||||
struct mbuf *
|
||||
m_get2(int size, int how, short type, int flags)
|
||||
{
|
||||
struct mb_args args;
|
||||
struct mbuf *m, *n;
|
||||
|
||||
args.flags = flags;
|
||||
args.type = type;
|
||||
|
||||
if (size <= MHLEN || (size <= MLEN && (flags & M_PKTHDR) == 0))
|
||||
return (uma_zalloc_arg(zone_mbuf, &args, how));
|
||||
if (size <= MCLBYTES)
|
||||
return (uma_zalloc_arg(zone_pack, &args, how));
|
||||
|
||||
if (size > MJUMPAGESIZE)
|
||||
return (NULL);
|
||||
|
||||
m = uma_zalloc_arg(zone_mbuf, &args, how);
|
||||
if (m == NULL)
|
||||
return (NULL);
|
||||
|
||||
n = uma_zalloc_arg(zone_jumbop, m, how);
|
||||
if (n == NULL) {
|
||||
uma_zfree(zone_mbuf, m);
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
return (m);
|
||||
}
|
||||
|
||||
/*
|
||||
* m_getjcl() returns an mbuf with a cluster of the specified size attached.
|
||||
* For size it takes MCLBYTES, MJUMPAGESIZE, MJUM9BYTES, MJUM16BYTES.
|
||||
*/
|
||||
struct mbuf *
|
||||
m_getjcl(int how, short type, int flags, int size)
|
||||
{
|
||||
struct mb_args args;
|
||||
struct mbuf *m, *n;
|
||||
uma_zone_t zone;
|
||||
|
||||
if (size == MCLBYTES)
|
||||
return m_getcl(how, type, flags);
|
||||
|
||||
args.flags = flags;
|
||||
args.type = type;
|
||||
|
||||
m = uma_zalloc_arg(zone_mbuf, &args, how);
|
||||
if (m == NULL)
|
||||
return (NULL);
|
||||
|
||||
zone = m_getzone(size);
|
||||
n = uma_zalloc_arg(zone, m, how);
|
||||
if (n == NULL) {
|
||||
uma_zfree(zone_mbuf, m);
|
||||
return (NULL);
|
||||
}
|
||||
return (m);
|
||||
}
|
||||
|
||||
/*
|
||||
* Allocate a given length worth of mbufs and/or clusters (whatever fits
|
||||
* best) and return a pointer to the top of the allocated chain. If an
|
||||
* existing mbuf chain is provided, then we will append the new chain
|
||||
* to the existing one but still return the top of the newly allocated
|
||||
* chain.
|
||||
*/
|
||||
struct mbuf *
|
||||
m_getm2(struct mbuf *m, int len, int how, short type, int flags)
|
||||
{
|
||||
struct mbuf *mb, *nm = NULL, *mtail = NULL;
|
||||
|
||||
KASSERT(len >= 0, ("%s: len is < 0", __func__));
|
||||
|
||||
/* Validate flags. */
|
||||
flags &= (M_PKTHDR | M_EOR);
|
||||
|
||||
/* Packet header mbuf must be first in chain. */
|
||||
if ((flags & M_PKTHDR) && m != NULL)
|
||||
flags &= ~M_PKTHDR;
|
||||
|
||||
/* Loop and append maximum sized mbufs to the chain tail. */
|
||||
while (len > 0) {
|
||||
if (len > MCLBYTES)
|
||||
mb = m_getjcl(how, type, (flags & M_PKTHDR),
|
||||
MJUMPAGESIZE);
|
||||
else if (len >= MINCLSIZE)
|
||||
mb = m_getcl(how, type, (flags & M_PKTHDR));
|
||||
else if (flags & M_PKTHDR)
|
||||
mb = m_gethdr(how, type);
|
||||
else
|
||||
mb = m_get(how, type);
|
||||
|
||||
/* Fail the whole operation if one mbuf can't be allocated. */
|
||||
if (mb == NULL) {
|
||||
if (nm != NULL)
|
||||
m_freem(nm);
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
/* Book keeping. */
|
||||
len -= M_SIZE(mb);
|
||||
if (mtail != NULL)
|
||||
mtail->m_next = mb;
|
||||
else
|
||||
nm = mb;
|
||||
mtail = mb;
|
||||
flags &= ~M_PKTHDR; /* Only valid on the first mbuf. */
|
||||
}
|
||||
if (flags & M_EOR)
|
||||
mtail->m_flags |= M_EOR; /* Only valid on the last mbuf. */
|
||||
|
||||
/* If mbuf was supplied, append new chain to the end of it. */
|
||||
if (m != NULL) {
|
||||
for (mtail = m; mtail->m_next != NULL; mtail = mtail->m_next)
|
||||
;
|
||||
mtail->m_next = nm;
|
||||
mtail->m_flags &= ~M_EOR;
|
||||
} else
|
||||
m = nm;
|
||||
|
||||
return (m);
|
||||
}
|
||||
|
||||
/*
|
||||
* Free an entire chain of mbufs and associated external buffers, if
|
||||
* applicable.
|
||||
*/
|
||||
void
|
||||
m_freem(struct mbuf *mb)
|
||||
{
|
||||
|
||||
while (mb != NULL)
|
||||
mb = m_free(mb);
|
||||
}
|
||||
|
||||
/*-
|
||||
* Configure a provided mbuf to refer to the provided external storage
|
||||
* buffer and setup a reference count for said buffer. If the setting
|
||||
* up of the reference count fails, the M_EXT bit will not be set. If
|
||||
* successfull, the M_EXT bit is set in the mbuf's flags.
|
||||
*
|
||||
* Arguments:
|
||||
* mb The existing mbuf to which to attach the provided buffer.
|
||||
* buf The address of the provided external storage buffer.
|
||||
* size The size of the provided buffer.
|
||||
* freef A pointer to a routine that is responsible for freeing the
|
||||
* provided external storage buffer.
|
||||
* args A pointer to an argument structure (of any type) to be passed
|
||||
* to the provided freef routine (may be NULL).
|
||||
* flags Any other flags to be passed to the provided mbuf.
|
||||
* type The type that the external storage buffer should be
|
||||
* labeled with.
|
||||
*
|
||||
* Returns:
|
||||
* Nothing.
|
||||
*/
|
||||
int
|
||||
m_extadd(struct mbuf *mb, caddr_t buf, u_int size,
|
||||
void (*freef)(struct mbuf *, void *, void *), void *arg1, void *arg2,
|
||||
int flags, int type, int wait)
|
||||
{
|
||||
KASSERT(type != EXT_CLUSTER, ("%s: EXT_CLUSTER not allowed", __func__));
|
||||
|
||||
if (type != EXT_EXTREF)
|
||||
mb->m_ext.ext_cnt = uma_zalloc(zone_ext_refcnt, wait);
|
||||
|
||||
if (mb->m_ext.ext_cnt == NULL)
|
||||
return (ENOMEM);
|
||||
|
||||
*(mb->m_ext.ext_cnt) = 1;
|
||||
mb->m_flags |= (M_EXT | flags);
|
||||
mb->m_ext.ext_buf = buf;
|
||||
mb->m_data = mb->m_ext.ext_buf;
|
||||
mb->m_ext.ext_size = size;
|
||||
mb->m_ext.ext_free = freef;
|
||||
mb->m_ext.ext_arg1 = arg1;
|
||||
mb->m_ext.ext_arg2 = arg2;
|
||||
mb->m_ext.ext_type = type;
|
||||
mb->m_ext.ext_flags = 0;
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
/*
|
||||
* Non-directly-exported function to clean up after mbufs with M_EXT
|
||||
* storage attached to them if the reference count hits 1.
|
||||
*/
|
||||
void
|
||||
mb_free_ext(struct mbuf *m)
|
||||
{
|
||||
int freembuf;
|
||||
|
||||
KASSERT(m->m_flags & M_EXT, ("%s: M_EXT not set on %p", __func__, m));
|
||||
|
||||
/*
|
||||
* Check if the header is embedded in the cluster.
|
||||
*/
|
||||
freembuf = (m->m_flags & M_NOFREE) ? 0 : 1;
|
||||
|
||||
switch (m->m_ext.ext_type) {
|
||||
case EXT_SFBUF:
|
||||
sf_ext_free(m->m_ext.ext_arg1, m->m_ext.ext_arg2);
|
||||
break;
|
||||
case EXT_SFBUF_NOCACHE:
|
||||
sf_ext_free_nocache(m->m_ext.ext_arg1, m->m_ext.ext_arg2);
|
||||
break;
|
||||
default:
|
||||
KASSERT(m->m_ext.ext_cnt != NULL,
|
||||
("%s: no refcounting pointer on %p", __func__, m));
|
||||
/*
|
||||
* Free attached storage if this mbuf is the only
|
||||
* reference to it.
|
||||
*/
|
||||
if (*(m->m_ext.ext_cnt) != 1) {
|
||||
if (atomic_fetchadd_int(m->m_ext.ext_cnt, -1) != 1)
|
||||
break;
|
||||
}
|
||||
|
||||
switch (m->m_ext.ext_type) {
|
||||
case EXT_PACKET: /* The packet zone is special. */
|
||||
if (*(m->m_ext.ext_cnt) == 0)
|
||||
*(m->m_ext.ext_cnt) = 1;
|
||||
uma_zfree(zone_pack, m);
|
||||
return; /* Job done. */
|
||||
case EXT_CLUSTER:
|
||||
uma_zfree(zone_clust, m->m_ext.ext_buf);
|
||||
break;
|
||||
case EXT_JUMBOP:
|
||||
uma_zfree(zone_jumbop, m->m_ext.ext_buf);
|
||||
break;
|
||||
case EXT_JUMBO9:
|
||||
uma_zfree(zone_jumbo9, m->m_ext.ext_buf);
|
||||
break;
|
||||
case EXT_JUMBO16:
|
||||
uma_zfree(zone_jumbo16, m->m_ext.ext_buf);
|
||||
break;
|
||||
case EXT_NET_DRV:
|
||||
case EXT_MOD_TYPE:
|
||||
case EXT_DISPOSABLE:
|
||||
*(m->m_ext.ext_cnt) = 0;
|
||||
uma_zfree(zone_ext_refcnt, __DEVOLATILE(u_int *,
|
||||
m->m_ext.ext_cnt));
|
||||
/* FALLTHROUGH */
|
||||
case EXT_EXTREF:
|
||||
KASSERT(m->m_ext.ext_free != NULL,
|
||||
("%s: ext_free not set", __func__));
|
||||
(*(m->m_ext.ext_free))(m, m->m_ext.ext_arg1,
|
||||
m->m_ext.ext_arg2);
|
||||
break;
|
||||
default:
|
||||
KASSERT(m->m_ext.ext_type == 0,
|
||||
("%s: unknown ext_type", __func__));
|
||||
}
|
||||
}
|
||||
|
||||
if (freembuf)
|
||||
uma_zfree(zone_mbuf, m);
|
||||
}
|
||||
|
||||
/*
|
||||
* Attach the cluster from *m to *n, set up m_ext in *n
|
||||
* and bump the refcount of the cluster.
|
||||
@ -534,6 +273,26 @@ m_sanity(struct mbuf *m0, int sanitize)
|
||||
#undef M_SANITY_ACTION
|
||||
}
|
||||
|
||||
/*
|
||||
* Non-inlined part of m_init().
|
||||
*/
|
||||
int
|
||||
m_pkthdr_init(struct mbuf *m, int how)
|
||||
{
|
||||
#ifdef MAC
|
||||
int error;
|
||||
#endif
|
||||
m->m_data = m->m_pktdat;
|
||||
bzero(&m->m_pkthdr, sizeof(m->m_pkthdr));
|
||||
#ifdef MAC
|
||||
/* If the label init fails, fail the alloc */
|
||||
error = mac_mbuf_init(m, how);
|
||||
if (error)
|
||||
return (error);
|
||||
#endif
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
/*
|
||||
* "Move" mbuf pkthdr from "from" to "to".
|
||||
|
@ -50,13 +50,13 @@ typedef struct __mcontext {
|
||||
* struct sigcontext and ucontext_t at the same time.
|
||||
*/
|
||||
int mc_onstack; /* sigstack state to restore */
|
||||
register_t mc_pc; /* pc at time of signal */
|
||||
register_t mc_regs[32]; /* processor regs 0 to 31 */
|
||||
register_t sr; /* status register */
|
||||
register_t mullo, mulhi; /* mullo and mulhi registers... */
|
||||
__register_t mc_pc; /* pc at time of signal */
|
||||
__register_t mc_regs[32]; /* processor regs 0 to 31 */
|
||||
__register_t sr; /* status register */
|
||||
__register_t mullo, mulhi; /* mullo and mulhi registers... */
|
||||
int mc_fpused; /* fp has been used */
|
||||
f_register_t mc_fpregs[33]; /* fp regs 0 to 31 and csr */
|
||||
register_t mc_fpc_eir; /* fp exception instruction reg */
|
||||
__register_t mc_fpc_eir; /* fp exception instruction reg */
|
||||
void *mc_tls; /* pointer to TLS area */
|
||||
int __spare__[8]; /* XXX reserved */
|
||||
} mcontext_t;
|
||||
|
@ -978,10 +978,7 @@ __FBSDID("$FreeBSD$");
|
||||
(((uint8_t *)&(a)->s_addr)[1] == 168)))
|
||||
|
||||
#define IN4_ISLOOPBACK_ADDRESS(a) \
|
||||
((((uint8_t *)&(a)->s_addr)[0] == 127) && \
|
||||
(((uint8_t *)&(a)->s_addr)[1] == 0) && \
|
||||
(((uint8_t *)&(a)->s_addr)[2] == 0) && \
|
||||
(((uint8_t *)&(a)->s_addr)[3] == 1))
|
||||
(((uint8_t *)&(a)->s_addr)[0] == 127)
|
||||
|
||||
#define IN4_ISLINKLOCAL_ADDRESS(a) \
|
||||
((((uint8_t *)&(a)->s_addr)[0] == 169) && \
|
||||
|
@ -113,11 +113,6 @@ VNET_DEFINE(int, nd6_debug) = 0;
|
||||
|
||||
static eventhandler_tag lle_event_eh, iflladdr_event_eh;
|
||||
|
||||
/* for debugging? */
|
||||
#if 0
|
||||
static int nd6_inuse, nd6_allocated;
|
||||
#endif
|
||||
|
||||
VNET_DEFINE(struct nd_drhead, nd_defrouter);
|
||||
VNET_DEFINE(struct nd_prhead, nd_prefix);
|
||||
|
||||
@ -248,7 +243,7 @@ nd6_ifattach(struct ifnet *ifp)
|
||||
{
|
||||
struct nd_ifinfo *nd;
|
||||
|
||||
nd = (struct nd_ifinfo *)malloc(sizeof(*nd), M_IP6NDP, M_WAITOK|M_ZERO);
|
||||
nd = malloc(sizeof(*nd), M_IP6NDP, M_WAITOK | M_ZERO);
|
||||
nd->initialized = 1;
|
||||
|
||||
nd->chlim = IPV6_DEFHLIM;
|
||||
@ -2517,7 +2512,6 @@ clear_llinfo_pqueue(struct llentry *ln)
|
||||
}
|
||||
|
||||
ln->la_hold = NULL;
|
||||
return;
|
||||
}
|
||||
|
||||
static int nd6_sysctl_drlist(SYSCTL_HANDLER_ARGS);
|
||||
@ -2556,7 +2550,7 @@ nd6_sysctl_drlist(SYSCTL_HANDLER_ARGS)
|
||||
error = sa6_recoverscope(&d.rtaddr);
|
||||
if (error != 0)
|
||||
return (error);
|
||||
d.flags = dr->flags;
|
||||
d.flags = dr->raflags;
|
||||
d.rtlifetime = dr->rtlifetime;
|
||||
d.expire = dr->expire + (time_second - time_uptime);
|
||||
d.if_index = dr->ifp->if_index;
|
||||
|
@ -235,7 +235,7 @@ TAILQ_HEAD(nd_drhead, nd_defrouter);
|
||||
struct nd_defrouter {
|
||||
TAILQ_ENTRY(nd_defrouter) dr_entry;
|
||||
struct in6_addr rtaddr;
|
||||
u_char flags; /* flags on RA message */
|
||||
u_char raflags; /* flags on RA message */
|
||||
u_short rtlifetime;
|
||||
u_long expire;
|
||||
struct ifnet *ifp;
|
||||
|
@ -584,7 +584,6 @@ nd6_ns_output_fib(struct ifnet *ifp, const struct in6_addr *saddr6,
|
||||
|
||||
bad:
|
||||
m_freem(m);
|
||||
return;
|
||||
}
|
||||
|
||||
#ifndef BURN_BRIDGES
|
||||
@ -864,12 +863,6 @@ nd6_na_input(struct mbuf *m, int off, int icmp6len)
|
||||
|
||||
in6 = &ln->r_l3addr.addr6;
|
||||
|
||||
/*
|
||||
* Lock to protect the default router list.
|
||||
* XXX: this might be unnecessary, since this function
|
||||
* is only called under the network software interrupt
|
||||
* context. However, we keep it just for safety.
|
||||
*/
|
||||
nd6_ifp = lltable_get_ifp(ln->lle_tbl);
|
||||
dr = defrouter_lookup(in6, nd6_ifp);
|
||||
if (dr)
|
||||
@ -1078,7 +1071,6 @@ nd6_na_output_fib(struct ifnet *ifp, const struct in6_addr *daddr6_0,
|
||||
|
||||
bad:
|
||||
m_freem(m);
|
||||
return;
|
||||
}
|
||||
|
||||
#ifndef BURN_BRIDGES
|
||||
|
@ -272,7 +272,7 @@ nd6_ra_input(struct mbuf *m, int off, int icmp6len)
|
||||
|
||||
bzero(&dr0, sizeof(dr0));
|
||||
dr0.rtaddr = saddr6;
|
||||
dr0.flags = nd_ra->nd_ra_flags_reserved;
|
||||
dr0.raflags = nd_ra->nd_ra_flags_reserved;
|
||||
/*
|
||||
* Effectively-disable routes from RA messages when
|
||||
* ND6_IFF_NO_RADR enabled on the receiving interface or
|
||||
@ -503,7 +503,6 @@ defrouter_addreq(struct nd_defrouter *new)
|
||||
}
|
||||
if (error == 0)
|
||||
new->installed = 1;
|
||||
return;
|
||||
}
|
||||
|
||||
struct nd_defrouter *
|
||||
@ -702,8 +701,6 @@ defrouter_select(void)
|
||||
defrouter_delreq(installed_dr);
|
||||
defrouter_addreq(selected_dr);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
@ -713,7 +710,7 @@ defrouter_select(void)
|
||||
static int
|
||||
rtpref(struct nd_defrouter *dr)
|
||||
{
|
||||
switch (dr->flags & ND_RA_FLAG_RTPREF_MASK) {
|
||||
switch (dr->raflags & ND_RA_FLAG_RTPREF_MASK) {
|
||||
case ND_RA_FLAG_RTPREF_HIGH:
|
||||
return (RTPREF_HIGH);
|
||||
case ND_RA_FLAG_RTPREF_MEDIUM:
|
||||
@ -727,7 +724,7 @@ rtpref(struct nd_defrouter *dr)
|
||||
* serious bug of kernel internal. We thus always bark here.
|
||||
* Or, can we even panic?
|
||||
*/
|
||||
log(LOG_ERR, "rtpref: impossible RA flag %x\n", dr->flags);
|
||||
log(LOG_ERR, "rtpref: impossible RA flag %x\n", dr->raflags);
|
||||
return (RTPREF_INVALID);
|
||||
}
|
||||
/* NOTREACHED */
|
||||
@ -737,17 +734,19 @@ static struct nd_defrouter *
|
||||
defrtrlist_update(struct nd_defrouter *new)
|
||||
{
|
||||
struct nd_defrouter *dr, *n;
|
||||
int oldpref;
|
||||
|
||||
if ((dr = defrouter_lookup(&new->rtaddr, new->ifp)) != NULL) {
|
||||
/* entry exists */
|
||||
if (new->rtlifetime == 0) {
|
||||
defrtrlist_del(dr);
|
||||
dr = NULL;
|
||||
} else {
|
||||
int oldpref = rtpref(dr);
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
oldpref = rtpref(dr);
|
||||
|
||||
/* override */
|
||||
dr->flags = new->flags; /* xxx flag check */
|
||||
dr->raflags = new->raflags; /* XXX flag check */
|
||||
dr->rtlifetime = new->rtlifetime;
|
||||
dr->expire = new->expire;
|
||||
|
||||
@ -760,30 +759,22 @@ defrtrlist_update(struct nd_defrouter *new)
|
||||
return (dr);
|
||||
|
||||
/*
|
||||
* preferred router may be changed, so relocate
|
||||
* this router.
|
||||
* XXX: calling TAILQ_REMOVE directly is a bad manner.
|
||||
* However, since defrtrlist_del() has many side
|
||||
* effects, we intentionally do so here.
|
||||
* defrouter_select() below will handle routing
|
||||
* changes later.
|
||||
* The preferred router may have changed, so relocate this
|
||||
* router.
|
||||
*/
|
||||
TAILQ_REMOVE(&V_nd_defrouter, dr, dr_entry);
|
||||
n = dr;
|
||||
goto insert;
|
||||
}
|
||||
return (dr);
|
||||
}
|
||||
|
||||
/* entry does not exist */
|
||||
if (new->rtlifetime == 0)
|
||||
return (NULL);
|
||||
|
||||
n = (struct nd_defrouter *)malloc(sizeof(*n), M_IP6NDP, M_NOWAIT);
|
||||
n = malloc(sizeof(*n), M_IP6NDP, M_NOWAIT | M_ZERO);
|
||||
if (n == NULL)
|
||||
return (NULL);
|
||||
bzero(n, sizeof(*n));
|
||||
*n = *new;
|
||||
memcpy(n, new, sizeof(*n));
|
||||
|
||||
insert:
|
||||
/*
|
||||
@ -826,10 +817,9 @@ pfxrtr_add(struct nd_prefix *pr, struct nd_defrouter *dr)
|
||||
{
|
||||
struct nd_pfxrouter *new;
|
||||
|
||||
new = (struct nd_pfxrouter *)malloc(sizeof(*new), M_IP6NDP, M_NOWAIT);
|
||||
new = malloc(sizeof(*new), M_IP6NDP, M_NOWAIT | M_ZERO);
|
||||
if (new == NULL)
|
||||
return;
|
||||
bzero(new, sizeof(*new));
|
||||
new->router = dr;
|
||||
|
||||
LIST_INSERT_HEAD(&pr->ndpr_advrtrs, new, pfr_entry);
|
||||
@ -869,10 +859,9 @@ nd6_prelist_add(struct nd_prefixctl *pr, struct nd_defrouter *dr,
|
||||
int error = 0;
|
||||
char ip6buf[INET6_ADDRSTRLEN];
|
||||
|
||||
new = (struct nd_prefix *)malloc(sizeof(*new), M_IP6NDP, M_NOWAIT);
|
||||
new = malloc(sizeof(*new), M_IP6NDP, M_NOWAIT | M_ZERO);
|
||||
if (new == NULL)
|
||||
return(ENOMEM);
|
||||
bzero(new, sizeof(*new));
|
||||
return (ENOMEM);
|
||||
new->ndpr_ifp = pr->ndpr_ifp;
|
||||
new->ndpr_prefix = pr->ndpr_prefix;
|
||||
new->ndpr_plen = pr->ndpr_plen;
|
||||
|
@ -371,7 +371,7 @@ sa6_recoverscope(struct sockaddr_in6 *sin6)
|
||||
zoneid != sin6->sin6_scope_id) {
|
||||
log(LOG_NOTICE,
|
||||
"%s: embedded scope mismatch: %s%%%d. "
|
||||
"sin6_scope_id was overridden.", __func__,
|
||||
"sin6_scope_id was overridden\n", __func__,
|
||||
ip6_sprintf(ip6buf, &sin6->sin6_addr),
|
||||
sin6->sin6_scope_id);
|
||||
}
|
||||
|
@ -42,11 +42,11 @@ typedef struct __mcontext {
|
||||
#define _MC_AV_VALID 0x02
|
||||
int mc_onstack; /* saved onstack flag */
|
||||
int mc_len; /* sizeof(__mcontext) */
|
||||
uint64_t mc_avec[32*2]; /* vector register file */
|
||||
uint32_t mc_av[2];
|
||||
register_t mc_frame[42];
|
||||
uint64_t mc_fpreg[33];
|
||||
uint64_t mc_vsxfpreg[32]; /* low-order half of VSR0-31 */
|
||||
__uint64_t mc_avec[32*2]; /* vector register file */
|
||||
__uint32_t mc_av[2];
|
||||
__register_t mc_frame[42];
|
||||
__uint64_t mc_fpreg[33];
|
||||
__uint64_t mc_vsxfpreg[32]; /* low-order half of VSR0-31 */
|
||||
} mcontext_t __aligned(16);
|
||||
|
||||
#if defined(_KERNEL) && defined(__powerpc64__)
|
||||
|
@ -50,7 +50,7 @@ struct gpregs {
|
||||
};
|
||||
|
||||
struct fpregs {
|
||||
__uint128_t fp_x[32];
|
||||
__uint64_t fp_x[64] __aligned(16);
|
||||
__uint64_t fp_fcsr;
|
||||
int fp_flags;
|
||||
int pad;
|
||||
|
@ -33,11 +33,11 @@
|
||||
#define _MACHINE_UCONTEXT_H_
|
||||
|
||||
struct __mcontext {
|
||||
uint64_t mc_global[8];
|
||||
uint64_t mc_out[8];
|
||||
uint64_t mc_local[8];
|
||||
uint64_t mc_in[8];
|
||||
uint32_t mc_fp[64];
|
||||
__uint64_t mc_global[8];
|
||||
__uint64_t mc_out[8];
|
||||
__uint64_t mc_local[8];
|
||||
__uint64_t mc_in[8];
|
||||
__uint32_t mc_fp[64];
|
||||
} __aligned(64);
|
||||
|
||||
typedef struct __mcontext mcontext_t;
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user