Sponsored by:	The FreeBSD Foundation
This commit is contained in:
gjb 2016-02-15 21:58:52 +00:00
commit 64f34d0d71
293 changed files with 11342 additions and 3321 deletions

View File

@ -1804,6 +1804,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 \
@ -1816,6 +1817,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

View File

@ -38,6 +38,8 @@
# xargs -n1 | sort | uniq -d;
# done
# 20160211: Remove obsolete unbound-control-setup
OLD_FILES+=usr/sbin/unbound-control-setup
# 20160116: Update mandoc to cvs snapshot 20160116
OLD_FILES+=usr/share/mdocml/example.style.css
OLD_FILES+=usr/share/mdocml/style.css

View File

@ -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)

View File

@ -0,0 +1,2 @@
# TODO(#511): Revert after the source tree is -Wconversion clean.
WARNS=5

View File

@ -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)

View File

@ -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));

View File

@ -23,7 +23,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* $Id: elfdefinitions.h 3253 2015-10-10 18:31:33Z kaiwang27 $
* $Id: elfdefinitions.h 3392 2016-02-05 19:51:22Z emaste $
*/
/*
@ -1228,6 +1228,7 @@ _ELF_DEFINE_STB(STB_GLOBAL, 1, \
_ELF_DEFINE_STB(STB_WEAK, 2, \
"visible across all object files but with low precedence") \
_ELF_DEFINE_STB(STB_LOOS, 10, "start of OS-specific range") \
_ELF_DEFINE_STB(STB_GNU_UNIQUE, 10, "unique symbol (GNU)") \
_ELF_DEFINE_STB(STB_HIOS, 12, "end of OS-specific range") \
_ELF_DEFINE_STB(STB_LOPROC, 13, \
"start of processor-specific range") \
@ -1259,6 +1260,7 @@ _ELF_DEFINE_STT(STT_LOPROC, 13, \
"start of processor-specific types") \
_ELF_DEFINE_STT(STT_ARM_TFUNC, 13, "Thumb function (GNU)") \
_ELF_DEFINE_STT(STT_ARM_16BIT, 15, "Thumb label (GNU)") \
_ELF_DEFINE_STT(STT_SPARC_REGISTER, 13, "SPARC register information") \
_ELF_DEFINE_STT(STT_HIPROC, 15, \
"end of processor-specific types")
@ -1395,7 +1397,7 @@ _ELF_DEFINE_RELOC(R_386_GOT32, 3) \
_ELF_DEFINE_RELOC(R_386_PLT32, 4) \
_ELF_DEFINE_RELOC(R_386_COPY, 5) \
_ELF_DEFINE_RELOC(R_386_GLOB_DAT, 6) \
_ELF_DEFINE_RELOC(R_386_JMP_SLOT, 7) \
_ELF_DEFINE_RELOC(R_386_JUMP_SLOT, 7) \
_ELF_DEFINE_RELOC(R_386_RELATIVE, 8) \
_ELF_DEFINE_RELOC(R_386_GOTOFF, 9) \
_ELF_DEFINE_RELOC(R_386_GOTPC, 10) \
@ -1407,9 +1409,129 @@ _ELF_DEFINE_RELOC(R_386_PC8, 23)
/*
*/
#define _ELF_DEFINE_AARCH64_RELOCATIONS() \
_ELF_DEFINE_RELOC(R_AARCH64_ABS64, 257) \
_ELF_DEFINE_RELOC(R_AARCH64_ABS32, 258) \
#define _ELF_DEFINE_AARCH64_RELOCATIONS() \
_ELF_DEFINE_RELOC(R_AARCH64_NONE, 0) \
_ELF_DEFINE_RELOC(R_AARCH64_ABS64, 257) \
_ELF_DEFINE_RELOC(R_AARCH64_ABS32, 258) \
_ELF_DEFINE_RELOC(R_AARCH64_ABS16, 259) \
_ELF_DEFINE_RELOC(R_AARCH64_PREL64, 260) \
_ELF_DEFINE_RELOC(R_AARCH64_PREL32, 261) \
_ELF_DEFINE_RELOC(R_AARCH64_PREL16, 262) \
_ELF_DEFINE_RELOC(R_AARCH64_MOVW_UABS_G0, 263) \
_ELF_DEFINE_RELOC(R_AARCH64_MOVW_UABS_G0_NC, 264) \
_ELF_DEFINE_RELOC(R_AARCH64_MOVW_UABS_G1, 265) \
_ELF_DEFINE_RELOC(R_AARCH64_MOVW_UABS_G1_NC, 266) \
_ELF_DEFINE_RELOC(R_AARCH64_MOVW_UABS_G2, 267) \
_ELF_DEFINE_RELOC(R_AARCH64_MOVW_UABS_G2_NC, 268) \
_ELF_DEFINE_RELOC(R_AARCH64_MOVW_UABS_G3, 269) \
_ELF_DEFINE_RELOC(R_AARCH64_MOVW_SABS_G0, 270) \
_ELF_DEFINE_RELOC(R_AARCH64_MOVW_SABS_G1, 271) \
_ELF_DEFINE_RELOC(R_AARCH64_MOVW_SABS_G2, 272) \
_ELF_DEFINE_RELOC(R_AARCH64_LD_PREL_LO19, 273) \
_ELF_DEFINE_RELOC(R_AARCH64_ADR_PREL_LO21, 274) \
_ELF_DEFINE_RELOC(R_AARCH64_ADR_PREL_PG_HI21, 275) \
_ELF_DEFINE_RELOC(R_AARCH64_ADR_PREL_PG_HI21_NC, 276) \
_ELF_DEFINE_RELOC(R_AARCH64_ADD_ABS_LO12_NC, 277) \
_ELF_DEFINE_RELOC(R_AARCH64_LDST8_ABS_LO12_NC, 278) \
_ELF_DEFINE_RELOC(R_AARCH64_TSTBR14, 279) \
_ELF_DEFINE_RELOC(R_AARCH64_CONDBR19, 280) \
_ELF_DEFINE_RELOC(R_AARCH64_JUMP26, 282) \
_ELF_DEFINE_RELOC(R_AARCH64_CALL26, 283) \
_ELF_DEFINE_RELOC(R_AARCH64_LDST16_ABS_LO12_NC, 284) \
_ELF_DEFINE_RELOC(R_AARCH64_LDST32_ABS_LO12_NC, 285) \
_ELF_DEFINE_RELOC(R_AARCH64_LDST64_ABS_LO12_NC, 286) \
_ELF_DEFINE_RELOC(R_AARCH64_MOVW_PREL_G0, 287) \
_ELF_DEFINE_RELOC(R_AARCH64_MOVW_PREL_G0_NC, 288) \
_ELF_DEFINE_RELOC(R_AARCH64_MOVW_PREL_G1, 289) \
_ELF_DEFINE_RELOC(R_AARCH64_MOVW_PREL_G1_NC, 290) \
_ELF_DEFINE_RELOC(R_AARCH64_MOVW_PREL_G2, 291) \
_ELF_DEFINE_RELOC(R_AARCH64_MOVW_PREL_G2_NC, 292) \
_ELF_DEFINE_RELOC(R_AARCH64_MOVW_PREL_G3, 293) \
_ELF_DEFINE_RELOC(R_AARCH64_LDST128_ABS_LO12_NC, 299) \
_ELF_DEFINE_RELOC(R_AARCH64_MOVW_GOTOFF_G0, 300) \
_ELF_DEFINE_RELOC(R_AARCH64_MOVW_GOTOFF_G0_NC, 301) \
_ELF_DEFINE_RELOC(R_AARCH64_MOVW_GOTOFF_G1, 302) \
_ELF_DEFINE_RELOC(R_AARCH64_MOVW_GOTOFF_G1_NC, 303) \
_ELF_DEFINE_RELOC(R_AARCH64_MOVW_GOTOFF_G2, 304) \
_ELF_DEFINE_RELOC(R_AARCH64_MOVW_GOTOFF_G2_NC, 305) \
_ELF_DEFINE_RELOC(R_AARCH64_MOVW_GOTOFF_G3, 306) \
_ELF_DEFINE_RELOC(R_AARCH64_GOTREL64, 307) \
_ELF_DEFINE_RELOC(R_AARCH64_GOTREL32, 308) \
_ELF_DEFINE_RELOC(R_AARCH64_GOT_LD_PREL19, 309) \
_ELF_DEFINE_RELOC(R_AARCH64_LD64_GOTOFF_LO15, 310) \
_ELF_DEFINE_RELOC(R_AARCH64_ADR_GOT_PAGE, 311) \
_ELF_DEFINE_RELOC(R_AARCH64_LD64_GOT_LO12_NC, 312) \
_ELF_DEFINE_RELOC(R_AARCH64_LD64_GOTPAGE_LO15, 313) \
_ELF_DEFINE_RELOC(R_AARCH64_TLSGD_ADR_PREL21, 512) \
_ELF_DEFINE_RELOC(R_AARCH64_TLSGD_ADR_PAGE21, 513) \
_ELF_DEFINE_RELOC(R_AARCH64_TLSGD_ADD_LO12_NC, 514) \
_ELF_DEFINE_RELOC(R_AARCH64_TLSGD_MOVW_G1, 515) \
_ELF_DEFINE_RELOC(R_AARCH64_TLSGD_MOVW_G0_NC, 516) \
_ELF_DEFINE_RELOC(R_AARCH64_TLSLD_ADR_PREL21, 517) \
_ELF_DEFINE_RELOC(R_AARCH64_TLSLD_ADR_PAGE21, 518) \
_ELF_DEFINE_RELOC(R_AARCH64_TLSLD_ADD_LO12_NC, 519) \
_ELF_DEFINE_RELOC(R_AARCH64_TLSLD_MOVW_G1, 520) \
_ELF_DEFINE_RELOC(R_AARCH64_TLSLD_MOVW_G0_NC, 521) \
_ELF_DEFINE_RELOC(R_AARCH64_TLSLD_LD_PREL19, 522) \
_ELF_DEFINE_RELOC(R_AARCH64_TLSLD_MOVW_DTPREL_G2, 523) \
_ELF_DEFINE_RELOC(R_AARCH64_TLSLD_MOVW_DTPREL_G1, 524) \
_ELF_DEFINE_RELOC(R_AARCH64_TLSLD_MOVW_DTPREL_G1_NC, 525) \
_ELF_DEFINE_RELOC(R_AARCH64_TLSLD_MOVW_DTPREL_G0, 526) \
_ELF_DEFINE_RELOC(R_AARCH64_TLSLD_MOVW_DTPREL_G0_NC, 527) \
_ELF_DEFINE_RELOC(R_AARCH64_TLSLD_ADD_DTPREL_HI12, 529) \
_ELF_DEFINE_RELOC(R_AARCH64_TLSLD_ADD_DTPREL_LO12_NC, 530) \
_ELF_DEFINE_RELOC(R_AARCH64_TLSLD_LDST8_DTPREL_LO12, 531) \
_ELF_DEFINE_RELOC(R_AARCH64_TLSLD_LDST8_DTPREL_LO12_NC, 532) \
_ELF_DEFINE_RELOC(R_AARCH64_TLSLD_LDST16_DTPREL_LO12, 533) \
_ELF_DEFINE_RELOC(R_AARCH64_TLSLD_LDST16_DTPREL_LO12_NC, 534) \
_ELF_DEFINE_RELOC(R_AARCH64_TLSLD_LDST32_DTPREL_LO12, 535) \
_ELF_DEFINE_RELOC(R_AARCH64_TLSLD_LDST32_DTPREL_LO12_NC, 536) \
_ELF_DEFINE_RELOC(R_AARCH64_TLSLD_LDST64_DTPREL_LO12, 537) \
_ELF_DEFINE_RELOC(R_AARCH64_TLSLD_LDST64_DTPREL_LO12_NC, 538) \
_ELF_DEFINE_RELOC(R_AARCH64_TLSIE_MOVW_GOTTPREL_G1, 539) \
_ELF_DEFINE_RELOC(R_AARCH64_TLSIE_MOVW_GOTTPREL_G0_NC, 540) \
_ELF_DEFINE_RELOC(R_AARCH64_TLSIE_ADR_GOTTPREL_PAGE21, 541) \
_ELF_DEFINE_RELOC(R_AARCH64_TLSIE_LD64_GOTTPREL_LO12_NC, 542) \
_ELF_DEFINE_RELOC(R_AARCH64_TLSIE_LD_GOTTPREL_PREL19, 543) \
_ELF_DEFINE_RELOC(R_AARCH64_TLSLE_MOVW_TPREL_G2, 544) \
_ELF_DEFINE_RELOC(R_AARCH64_TLSLE_MOVW_TPREL_G1, 545) \
_ELF_DEFINE_RELOC(R_AARCH64_TLSLE_MOVW_TPREL_G1_NC, 546) \
_ELF_DEFINE_RELOC(R_AARCH64_TLSLE_MOVW_TPREL_G0, 547) \
_ELF_DEFINE_RELOC(R_AARCH64_TLSLE_MOVW_TPREL_G0_NC, 548) \
_ELF_DEFINE_RELOC(R_AARCH64_TLSLE_ADD_TPREL_HI12, 549) \
_ELF_DEFINE_RELOC(R_AARCH64_TLSLE_ADD_TPREL_LO12, 550) \
_ELF_DEFINE_RELOC(R_AARCH64_TLSLE_ADD_TPREL_LO12_NC, 551) \
_ELF_DEFINE_RELOC(R_AARCH64_TLSLE_LDST8_TPREL_LO12, 552) \
_ELF_DEFINE_RELOC(R_AARCH64_TLSLE_LDST8_TPREL_LO12_NC, 553) \
_ELF_DEFINE_RELOC(R_AARCH64_TLSLE_LDST16_TPREL_LO12, 554) \
_ELF_DEFINE_RELOC(R_AARCH64_TLSLE_LDST16_TPREL_LO12_NC, 555) \
_ELF_DEFINE_RELOC(R_AARCH64_TLSLE_LDST32_TPREL_LO12, 556) \
_ELF_DEFINE_RELOC(R_AARCH64_TLSLE_LDST32_TPREL_LO12_NC, 557) \
_ELF_DEFINE_RELOC(R_AARCH64_TLSLE_LDST64_TPREL_LO12, 558) \
_ELF_DEFINE_RELOC(R_AARCH64_TLSLE_LDST64_TPREL_LO12_NC, 559) \
_ELF_DEFINE_RELOC(R_AARCH64_TLSDESC_LD_PREL19, 560) \
_ELF_DEFINE_RELOC(R_AARCH64_TLSDESC_ADR_PREL21, 561) \
_ELF_DEFINE_RELOC(R_AARCH64_TLSDESC_ADR_PAGE21, 562) \
_ELF_DEFINE_RELOC(R_AARCH64_TLSDESC_LD64_LO12, 563) \
_ELF_DEFINE_RELOC(R_AARCH64_TLSDESC_ADD_LO12, 564) \
_ELF_DEFINE_RELOC(R_AARCH64_TLSDESC_OFF_G1, 565) \
_ELF_DEFINE_RELOC(R_AARCH64_TLSDESC_OFF_G0_NC, 566) \
_ELF_DEFINE_RELOC(R_AARCH64_TLSDESC_LDR, 567) \
_ELF_DEFINE_RELOC(R_AARCH64_TLSDESC_ADD, 568) \
_ELF_DEFINE_RELOC(R_AARCH64_TLSDESC_CALL, 569) \
_ELF_DEFINE_RELOC(R_AARCH64_TLSLE_LDST128_TPREL_LO12, 570) \
_ELF_DEFINE_RELOC(R_AARCH64_TLSLE_LDST128_TPREL_LO12_NC, 571) \
_ELF_DEFINE_RELOC(R_AARCH64_TLSLD_LDST128_DTPREL_LO12, 572) \
_ELF_DEFINE_RELOC(R_AARCH64_TLSLD_LDST128_DTPREL_LO12_NC, 573) \
_ELF_DEFINE_RELOC(R_AARCH64_COPY, 1024) \
_ELF_DEFINE_RELOC(R_AARCH64_GLOB_DAT, 1025) \
_ELF_DEFINE_RELOC(R_AARCH64_JUMP_SLOT, 1026) \
_ELF_DEFINE_RELOC(R_AARCH64_RELATIVE, 1027) \
_ELF_DEFINE_RELOC(R_AARCH64_TLS_DTPREL64, 1028) \
_ELF_DEFINE_RELOC(R_AARCH64_TLS_DTPMOD64, 1029) \
_ELF_DEFINE_RELOC(R_AARCH64_TLS_TPREL64, 1030) \
_ELF_DEFINE_RELOC(R_AARCH64_TLSDESC, 1031) \
_ELF_DEFINE_RELOC(R_AARCH64_IRELATIVE, 1032)
/*
* These are the symbols used in the Sun ``Linkers and Loaders
@ -1633,7 +1755,7 @@ _ELF_DEFINE_RELOC(R_IA_64_LTV32MSB, 0x74) \
_ELF_DEFINE_RELOC(R_IA_64_LTV32LSB, 0x75) \
_ELF_DEFINE_RELOC(R_IA_64_LTV64MSB, 0x76) \
_ELF_DEFINE_RELOC(R_IA_64_LTV64LSB, 0x77) \
_ELF_DEFINE_RELOC(R_IA_64_PCREL21BIa, 0x79) \
_ELF_DEFINE_RELOC(R_IA_64_PCREL21BI, 0x79) \
_ELF_DEFINE_RELOC(R_IA_64_PCREL22, 0x7A) \
_ELF_DEFINE_RELOC(R_IA_64_PCREL64I, 0x7B) \
_ELF_DEFINE_RELOC(R_IA_64_IPLTMSB, 0x80) \
@ -1723,7 +1845,7 @@ _ELF_DEFINE_RELOC(R_PPC_REL32, 26) \
_ELF_DEFINE_RELOC(R_PPC_PLT32, 27) \
_ELF_DEFINE_RELOC(R_PPC_PLTREL32, 28) \
_ELF_DEFINE_RELOC(R_PPC_PLT16_LO, 29) \
_ELF_DEFINE_RELOC(R_PPL_PLT16_HI, 30) \
_ELF_DEFINE_RELOC(R_PPC_PLT16_HI, 30) \
_ELF_DEFINE_RELOC(R_PPC_PLT16_HA, 31) \
_ELF_DEFINE_RELOC(R_PPC_SDAREL16, 32) \
_ELF_DEFINE_RELOC(R_PPC_SECTOFF, 33) \
@ -1926,7 +2048,7 @@ _ELF_DEFINE_RELOC(R_RISCV_SUB32, 39) \
_ELF_DEFINE_RELOC(R_RISCV_SUB64, 40) \
_ELF_DEFINE_RELOC(R_RISCV_GNU_VTINHERIT, 41) \
_ELF_DEFINE_RELOC(R_RISCV_GNU_VTENTRY, 42) \
_ELF_DEFINE_RELOC(R_RISCV_ALIGN 43) \
_ELF_DEFINE_RELOC(R_RISCV_ALIGN, 43) \
_ELF_DEFINE_RELOC(R_RISCV_RVC_BRANCH, 44) \
_ELF_DEFINE_RELOC(R_RISCV_RVC_JUMP, 45)
@ -2042,6 +2164,7 @@ _ELF_DEFINE_IA64_RELOCATIONS() \
_ELF_DEFINE_MIPS_RELOCATIONS() \
_ELF_DEFINE_PPC32_RELOCATIONS() \
_ELF_DEFINE_PPC64_RELOCATIONS() \
_ELF_DEFINE_RISCV_RELOCATIONS() \
_ELF_DEFINE_SPARC_RELOCATIONS() \
_ELF_DEFINE_X86_64_RELOCATIONS()

View File

@ -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 {

View File

@ -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;
}
}

View File

@ -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}

View File

@ -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));

View File

@ -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

View File

@ -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);

View File

@ -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\

View 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);
}

View File

@ -34,7 +34,7 @@
#include "elfcopy.h"
ELFTC_VCSID("$Id: sections.c 3272 2015-12-11 20:00:54Z kaiwang27 $");
ELFTC_VCSID("$Id: sections.c 3346 2016-01-17 20:09:15Z kaiwang27 $");
static void add_gnu_debuglink(struct elfcopy *ecp);
static uint32_t calc_crc32(const char *p, size_t len, uint32_t crc);
@ -223,6 +223,7 @@ static int
is_debug_section(const char *name)
{
const char *dbg_sec[] = {
".apple_",
".debug",
".gnu.linkonce.wi.",
".line",
@ -369,7 +370,7 @@ create_scn(struct elfcopy *ecp)
is = NULL;
while ((is = elf_nextscn(ecp->ein, is)) != NULL) {
if (gelf_getshdr(is, &ish) == NULL)
errx(EXIT_FAILURE, "219 gelf_getshdr failed: %s",
errx(EXIT_FAILURE, "gelf_getshdr failed: %s",
elf_errmsg(-1));
if ((name = elf_strptr(ecp->ein, indx, ish.sh_name)) == NULL)
errx(EXIT_FAILURE, "elf_strptr failed: %s",
@ -416,12 +417,19 @@ create_scn(struct elfcopy *ecp)
* is loadable, but if user explicitly set section flags
* while neither "load" nor "alloc" is set, we make the
* section unloadable.
*
* Sections in relocatable object is loadable if
* section flag SHF_ALLOC is set.
*/
if (sec_flags &&
(sec_flags & (SF_LOAD | SF_ALLOC)) == 0)
s->loadable = 0;
else
else {
s->loadable = add_to_inseg_list(ecp, s);
if ((ecp->flags & RELOCATABLE) &&
(ish.sh_flags & SHF_ALLOC))
s->loadable = 1;
}
} else {
/* Assuming .shstrtab is "unloadable". */
s = ecp->shstrtab;
@ -875,10 +883,10 @@ resync_sections(struct elfcopy *ecp)
if (s->align == 0)
s->align = 1;
if (off <= s->off) {
if (!s->loadable)
if (!s->loadable || (ecp->flags & RELOCATABLE))
s->off = roundup(off, s->align);
} else {
if (s->loadable)
if (s->loadable && (ecp->flags & RELOCATABLE) == 0)
warnx("moving loadable section %s, "
"is this intentional?", s->name);
s->off = roundup(off, s->align);
@ -1028,8 +1036,11 @@ print_section(struct section *s)
print_data(s->buf, s->sz);
} else {
id = NULL;
while ((id = elf_getdata(s->is, id)) != NULL)
while ((id = elf_getdata(s->is, id)) != NULL ||
(id = elf_rawdata(s->is, id)) != NULL) {
(void) elf_errno();
print_data(id->d_buf, id->d_size);
}
elferr = elf_errno();
if (elferr != 0)
errx(EXIT_FAILURE, "elf_getdata() failed: %s",
@ -1049,7 +1060,9 @@ read_section(struct section *s, size_t *size)
sz = 0;
b = NULL;
id = NULL;
while ((id = elf_getdata(s->is, id)) != NULL) {
while ((id = elf_getdata(s->is, id)) != NULL ||
(id = elf_rawdata(s->is, id)) != NULL) {
(void) elf_errno();
if (b == NULL)
b = malloc(id->d_size);
else
@ -1077,10 +1090,10 @@ copy_shdr(struct elfcopy *ecp, struct section *s, const char *name, int copy,
GElf_Shdr ish, osh;
if (gelf_getshdr(s->is, &ish) == NULL)
errx(EXIT_FAILURE, "526 gelf_getshdr() failed: %s",
errx(EXIT_FAILURE, "gelf_getshdr() failed: %s",
elf_errmsg(-1));
if (gelf_getshdr(s->os, &osh) == NULL)
errx(EXIT_FAILURE, "529 gelf_getshdr() failed: %s",
errx(EXIT_FAILURE, "gelf_getshdr() failed: %s",
elf_errmsg(-1));
if (copy)
@ -1097,19 +1110,32 @@ copy_shdr(struct elfcopy *ecp, struct section *s, const char *name, int copy,
if (sec_flags) {
osh.sh_flags = 0;
if (sec_flags & SF_ALLOC) {
if (sec_flags & SF_ALLOC)
osh.sh_flags |= SHF_ALLOC;
if (!s->loadable)
warnx("set SHF_ALLOC flag for "
"unloadable section %s",
s->name);
}
if ((sec_flags & SF_READONLY) == 0)
osh.sh_flags |= SHF_WRITE;
if (sec_flags & SF_CODE)
osh.sh_flags |= SHF_EXECINSTR;
if ((sec_flags & SF_CONTENTS) &&
s->type == SHT_NOBITS && s->sz > 0) {
/*
* Convert SHT_NOBITS section to section with
* (zero'ed) content on file.
*/
osh.sh_type = s->type = SHT_PROGBITS;
if ((s->buf = calloc(1, s->sz)) == NULL)
err(EXIT_FAILURE, "malloc failed");
s->nocopy = 1;
}
} else {
osh.sh_flags = ish.sh_flags;
/*
* Newer binutils as(1) emits the section flag
* SHF_INFO_LINK for relocation sections. elfcopy
* emits this flag in the output section if it's
* missing in the input section, to remain compatible
* with binutils.
*/
if (ish.sh_type == SHT_REL || ish.sh_type == SHT_RELA)
osh.sh_flags |= SHF_INFO_LINK;
}
@ -1135,11 +1161,14 @@ copy_data(struct section *s)
return;
if ((id = elf_getdata(s->is, NULL)) == NULL) {
elferr = elf_errno();
if (elferr != 0)
errx(EXIT_FAILURE, "elf_getdata() failed: %s",
elf_errmsg(elferr));
return;
(void) elf_errno();
if ((id = elf_rawdata(s->is, NULL)) == NULL) {
elferr = elf_errno();
if (elferr != 0)
errx(EXIT_FAILURE, "failed to read section:"
" %s", s->name);
return;
}
}
if ((od = elf_newdata(s->os)) == NULL)
@ -1245,6 +1274,7 @@ insert_sections(struct elfcopy *ecp)
struct sec_add *sa;
struct section *s;
size_t off;
uint64_t stype;
/* Put these sections in the end of current list. */
off = 0;
@ -1259,8 +1289,20 @@ insert_sections(struct elfcopy *ecp)
/* TODO: Add section header vma/lma, flag changes here */
/*
* The default section type for user added section is
* SHT_PROGBITS. If the section name match certain patterns,
* elfcopy will try to set a more appropriate section type.
* However, data type is always set to ELF_T_BYTE and no
* translation is performed by libelf.
*/
stype = SHT_PROGBITS;
if (strcmp(sa->name, ".note") == 0 ||
strncmp(sa->name, ".note.", strlen(".note.")) == 0)
stype = SHT_NOTE;
(void) create_external_section(ecp, sa->name, NULL, sa->content,
sa->size, off, SHT_PROGBITS, ELF_T_BYTE, 0, 1, 0, 0);
sa->size, off, stype, ELF_T_BYTE, 0, 1, 0, 0);
}
}
@ -1285,7 +1327,7 @@ update_shdr(struct elfcopy *ecp, int update_link)
continue;
if (gelf_getshdr(s->os, &osh) == NULL)
errx(EXIT_FAILURE, "668 gelf_getshdr failed: %s",
errx(EXIT_FAILURE, "gelf_getshdr failed: %s",
elf_errmsg(-1));
/* Find section name in string table and set sh_name. */
@ -1364,7 +1406,7 @@ set_shstrtab(struct elfcopy *ecp)
}
if (gelf_getshdr(s->os, &sh) == NULL)
errx(EXIT_FAILURE, "692 gelf_getshdr() failed: %s",
errx(EXIT_FAILURE, "gelf_getshdr() failed: %s",
elf_errmsg(-1));
sh.sh_addr = 0;
sh.sh_addralign = 1;
@ -1431,14 +1473,17 @@ add_section(struct elfcopy *ecp, const char *arg)
if (stat(fn, &sb) == -1)
err(EXIT_FAILURE, "stat failed");
sa->size = sb.st_size;
if ((sa->content = malloc(sa->size)) == NULL)
err(EXIT_FAILURE, "malloc failed");
if ((fp = fopen(fn, "r")) == NULL)
err(EXIT_FAILURE, "can not open %s", fn);
if (fread(sa->content, 1, sa->size, fp) == 0 ||
ferror(fp))
err(EXIT_FAILURE, "fread failed");
fclose(fp);
if (sa->size > 0) {
if ((sa->content = malloc(sa->size)) == NULL)
err(EXIT_FAILURE, "malloc failed");
if ((fp = fopen(fn, "r")) == NULL)
err(EXIT_FAILURE, "can not open %s", fn);
if (fread(sa->content, 1, sa->size, fp) == 0 ||
ferror(fp))
err(EXIT_FAILURE, "fread failed");
fclose(fp);
} else
sa->content = NULL;
STAILQ_INSERT_TAIL(&ecp->v_sadd, sa, sadd_list);
ecp->flags |= SEC_ADD;

View File

@ -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++;

View File

@ -25,6 +25,7 @@
*/
#include <sys/param.h>
#include <assert.h>
#include <err.h>
#include <fnmatch.h>
#include <stdio.h>
@ -33,7 +34,13 @@
#include "elfcopy.h"
ELFTC_VCSID("$Id: symbols.c 3222 2015-05-24 23:47:23Z kaiwang27 $");
ELFTC_VCSID("$Id: symbols.c 3376 2016-01-26 18:41:39Z emaste $");
/* Backwards compatibility for systems with older ELF definitions. */
#ifndef STB_GNU_UNIQUE
#define STB_GNU_UNIQUE 10
#endif
/* Symbol table buffer structure. */
struct symbuf {
@ -79,7 +86,6 @@ static int lookup_exact_string(hash_head *hash, const char *buf,
static int generate_symbols(struct elfcopy *ecp);
static void mark_reloc_symbols(struct elfcopy *ecp, size_t sc);
static void mark_section_group_symbols(struct elfcopy *ecp, size_t sc);
static int match_wildcard(const char *name, const char *pattern);
uint32_t str_hash(const char *s);
/* Convenient bit vector operation macros. */
@ -102,7 +108,8 @@ static int
is_global_symbol(unsigned char st_info)
{
if (GELF_ST_BIND(st_info) == STB_GLOBAL)
if (GELF_ST_BIND(st_info) == STB_GLOBAL ||
GELF_ST_BIND(st_info) == STB_GNU_UNIQUE)
return (1);
return (0);
@ -190,12 +197,6 @@ is_remove_symbol(struct elfcopy *ecp, size_t sc, int i, GElf_Sym *s,
SHN_UNDEF, /* st_shndx */
};
if (lookup_symop_list(ecp, name, SYMOP_KEEP) != NULL)
return (0);
if (lookup_symop_list(ecp, name, SYMOP_STRIP) != NULL)
return (1);
/*
* Keep the first symbol if it is the special reserved symbol.
* XXX Should we generate one if it's missing?
@ -208,15 +209,34 @@ is_remove_symbol(struct elfcopy *ecp, size_t sc, int i, GElf_Sym *s,
ecp->secndx[s->st_shndx] == 0)
return (1);
/* Keep the symbol if specified by command line option -K. */
if (lookup_symop_list(ecp, name, SYMOP_KEEP) != NULL)
return (0);
if (ecp->strip == STRIP_ALL)
return (1);
/* Mark symbols used in relocation. */
if (ecp->v_rel == NULL)
mark_reloc_symbols(ecp, sc);
/* Mark symbols used in section groups. */
if (ecp->v_grp == NULL)
mark_section_group_symbols(ecp, sc);
/*
* Strip the symbol if specified by command line option -N,
* unless it's used in relocation.
*/
if (lookup_symop_list(ecp, name, SYMOP_STRIP) != NULL) {
if (BIT_ISSET(ecp->v_rel, i)) {
warnx("not stripping symbol `%s' because it is named"
" in a relocation", name);
return (0);
}
return (1);
}
if (is_needed_symbol(ecp, i, s))
return (0);
@ -565,8 +585,11 @@ generate_symbols(struct elfcopy *ecp)
* If the symbol is a STT_SECTION symbol, mark the section
* it points to.
*/
if (GELF_ST_TYPE(sym.st_info) == STT_SECTION)
if (GELF_ST_TYPE(sym.st_info) == STT_SECTION &&
sym.st_shndx < SHN_LORESERVE) {
assert(ecp->secndx[sym.st_shndx] < (uint64_t)ecp->nos);
BIT_SET(ecp->v_secsym, ecp->secndx[sym.st_shndx]);
}
}
/*
@ -861,6 +884,8 @@ add_to_symtab(struct elfcopy *ecp, const char *name, uint64_t st_value,
* It handles buffer growing, st_name calculating and st_shndx
* updating for symbols with non-special section index.
*/
#define _ST_NAME_EMPTY_l 0
#define _ST_NAME_EMPTY_g -1
#define _ADDSYM(B, SZ) do { \
if (sy_buf->B##SZ == NULL) { \
sy_buf->B##SZ = malloc(sy_buf->B##cap * \
@ -920,7 +945,8 @@ add_to_symtab(struct elfcopy *ecp, const char *name, uint64_t st_value,
st_buf->B.sz += strlen(name) + 1; \
} \
} else \
sy_buf->B##SZ[sy_buf->n##B##s].st_name = 0; \
sy_buf->B##SZ[sy_buf->n##B##s].st_name = \
(Elf##SZ##_Word)_ST_NAME_EMPTY_##B; \
sy_buf->n##B##s++; \
} while (0)
@ -945,6 +971,8 @@ add_to_symtab(struct elfcopy *ecp, const char *name, uint64_t st_value,
ecp->strtab->sz = st_buf->l.sz + st_buf->g.sz;
#undef _ADDSYM
#undef _ST_NAME_EMPTY_l
#undef _ST_NAME_EMPTY_g
}
void
@ -961,10 +989,17 @@ finalize_external_symtab(struct elfcopy *ecp)
sy_buf = ecp->symtab->buf;
st_buf = ecp->strtab->buf;
for (i = 0; (size_t) i < sy_buf->ngs; i++) {
if (ecp->oec == ELFCLASS32)
sy_buf->g32[i].st_name += st_buf->l.sz;
else
sy_buf->g64[i].st_name += st_buf->l.sz;
if (ecp->oec == ELFCLASS32) {
if (sy_buf->g32[i].st_name == (Elf32_Word)-1)
sy_buf->g32[i].st_name = 0;
else
sy_buf->g32[i].st_name += st_buf->l.sz;
} else {
if (sy_buf->g64[i].st_name == (Elf64_Word)-1)
sy_buf->g64[i].st_name = 0;
else
sy_buf->g64[i].st_name += st_buf->l.sz;
}
}
}
@ -1105,46 +1140,47 @@ add_to_symop_list(struct elfcopy *ecp, const char *name, const char *newname,
{
struct symop *s;
if ((s = lookup_symop_list(ecp, name, ~0U)) == NULL) {
if ((s = calloc(1, sizeof(*s))) == NULL)
errx(EXIT_FAILURE, "not enough memory");
s->name = name;
if (op == SYMOP_REDEF)
s->newname = newname;
}
assert (name != NULL);
STAILQ_FOREACH(s, &ecp->v_symop, symop_list)
if (!strcmp(name, s->name))
goto found;
s->op |= op;
if ((s = calloc(1, sizeof(*s))) == NULL)
errx(EXIT_FAILURE, "not enough memory");
STAILQ_INSERT_TAIL(&ecp->v_symop, s, symop_list);
}
static int
match_wildcard(const char *name, const char *pattern)
{
int reverse, match;
reverse = 0;
if (*pattern == '!') {
reverse = 1;
pattern++;
}
match = 0;
if (!fnmatch(pattern, name, 0))
match = 1;
return (reverse ? !match : match);
s->name = name;
found:
if (op == SYMOP_REDEF)
s->newname = newname;
s->op |= op;
}
struct symop *
lookup_symop_list(struct elfcopy *ecp, const char *name, unsigned int op)
{
struct symop *s;
struct symop *s, *ret;
const char *pattern;
STAILQ_FOREACH(s, &ecp->v_symop, symop_list) {
if (name == NULL || !strcmp(name, s->name) ||
((ecp->flags & WILDCARD) && match_wildcard(name, s->name)))
if ((s->op & op) != 0)
if ((s->op & op) == 0)
continue;
if (name == NULL || !strcmp(name, s->name))
return (s);
if ((ecp->flags & WILDCARD) == 0)
continue;
/* Handle wildcards. */
pattern = s->name;
if (pattern[0] == '!') {
/* Negative match. */
pattern++;
ret = NULL;
} else {
/* Regular wildcard match. */
ret = s;
}
if (!fnmatch(pattern, name, 0))
return (ret);
}
return (NULL);

View File

@ -50,7 +50,7 @@
#include "_elftc.h"
ELFTC_VCSID("$Id: elfdump.c 3250 2015-10-06 13:56:15Z emaste $");
ELFTC_VCSID("$Id: elfdump.c 3391 2016-02-05 19:43:01Z emaste $");
#if defined(ELFTC_NEED_ELF_NOTE_DEFINITION)
#include "native-elf-format.h"
@ -155,77 +155,82 @@ le32dec(const void *pp)
static const char *
d_tags(uint64_t tag)
{
static char unknown_buf[64];
switch (tag) {
case 0: return "DT_NULL";
case 1: return "DT_NEEDED";
case 2: return "DT_PLTRELSZ";
case 3: return "DT_PLTGOT";
case 4: return "DT_HASH";
case 5: return "DT_STRTAB";
case 6: return "DT_SYMTAB";
case 7: return "DT_RELA";
case 8: return "DT_RELASZ";
case 9: return "DT_RELAENT";
case 10: return "DT_STRSZ";
case 11: return "DT_SYMENT";
case 12: return "DT_INIT";
case 13: return "DT_FINI";
case 14: return "DT_SONAME";
case 15: return "DT_RPATH";
case 16: return "DT_SYMBOLIC";
case 17: return "DT_REL";
case 18: return "DT_RELSZ";
case 19: return "DT_RELENT";
case 20: return "DT_PLTREL";
case 21: return "DT_DEBUG";
case 22: return "DT_TEXTREL";
case 23: return "DT_JMPREL";
case 24: return "DT_BIND_NOW";
case 25: return "DT_INIT_ARRAY";
case 26: return "DT_FINI_ARRAY";
case 27: return "DT_INIT_ARRAYSZ";
case 28: return "DT_FINI_ARRAYSZ";
case 29: return "DT_RUNPATH";
case 30: return "DT_FLAGS";
case 32: return "DT_PREINIT_ARRAY"; /* XXX: DT_ENCODING */
case 33: return "DT_PREINIT_ARRAYSZ";
case DT_NULL: return "DT_NULL";
case DT_NEEDED: return "DT_NEEDED";
case DT_PLTRELSZ: return "DT_PLTRELSZ";
case DT_PLTGOT: return "DT_PLTGOT";
case DT_HASH: return "DT_HASH";
case DT_STRTAB: return "DT_STRTAB";
case DT_SYMTAB: return "DT_SYMTAB";
case DT_RELA: return "DT_RELA";
case DT_RELASZ: return "DT_RELASZ";
case DT_RELAENT: return "DT_RELAENT";
case DT_STRSZ: return "DT_STRSZ";
case DT_SYMENT: return "DT_SYMENT";
case DT_INIT: return "DT_INIT";
case DT_FINI: return "DT_FINI";
case DT_SONAME: return "DT_SONAME";
case DT_RPATH: return "DT_RPATH";
case DT_SYMBOLIC: return "DT_SYMBOLIC";
case DT_REL: return "DT_REL";
case DT_RELSZ: return "DT_RELSZ";
case DT_RELENT: return "DT_RELENT";
case DT_PLTREL: return "DT_PLTREL";
case DT_DEBUG: return "DT_DEBUG";
case DT_TEXTREL: return "DT_TEXTREL";
case DT_JMPREL: return "DT_JMPREL";
case DT_BIND_NOW: return "DT_BIND_NOW";
case DT_INIT_ARRAY: return "DT_INIT_ARRAY";
case DT_FINI_ARRAY: return "DT_FINI_ARRAY";
case DT_INIT_ARRAYSZ: return "DT_INIT_ARRAYSZ";
case DT_FINI_ARRAYSZ: return "DT_FINI_ARRAYSZ";
case DT_RUNPATH: return "DT_RUNPATH";
case DT_FLAGS: return "DT_FLAGS";
case DT_PREINIT_ARRAY: return "DT_PREINIT_ARRAY"; /* XXX DT_ENCODING */
case DT_PREINIT_ARRAYSZ:return "DT_PREINIT_ARRAYSZ";
/* 0x6000000D - 0x6ffff000 operating system-specific semantics */
case 0x6ffffdf5: return "DT_GNU_PRELINKED";
case 0x6ffffdf6: return "DT_GNU_CONFLICTSZ";
case 0x6ffffdf7: return "DT_GNU_LIBLISTSZ";
case 0x6ffffdf8: return "DT_SUNW_CHECKSUM";
case 0x6ffffdf9: return "DT_PLTPADSZ";
case 0x6ffffdfa: return "DT_MOVEENT";
case 0x6ffffdfb: return "DT_MOVESZ";
case 0x6ffffdfc: return "DT_FEATURE";
case 0x6ffffdfd: return "DT_POSFLAG_1";
case 0x6ffffdfe: return "DT_SYMINSZ";
case 0x6ffffdff: return "DT_SYMINENT (DT_VALRNGHI)";
case 0x6ffffe00: return "DT_ADDRRNGLO";
case 0x6ffffef5: return "DT_GNU_HASH";
case 0x6ffffef8: return "DT_GNU_CONFLICT";
case 0x6ffffef9: return "DT_GNU_LIBLIST";
case 0x6ffffefa: return "DT_CONFIG";
case 0x6ffffefb: return "DT_DEPAUDIT";
case 0x6ffffefc: return "DT_AUDIT";
case 0x6ffffefd: return "DT_PLTPAD";
case 0x6ffffefe: return "DT_MOVETAB";
case 0x6ffffeff: return "DT_SYMINFO (DT_ADDRRNGHI)";
case 0x6ffffff9: return "DT_RELACOUNT";
case 0x6ffffffa: return "DT_RELCOUNT";
case 0x6ffffffb: return "DT_FLAGS_1";
case 0x6ffffffc: return "DT_VERDEF";
case 0x6ffffffd: return "DT_VERDEFNUM";
case 0x6ffffffe: return "DT_VERNEED";
case 0x6fffffff: return "DT_VERNEEDNUM";
case 0x6ffffff0: return "DT_GNU_VERSYM";
case 0x6ffffdf5: return "DT_GNU_PRELINKED";
case 0x6ffffdf6: return "DT_GNU_CONFLICTSZ";
case 0x6ffffdf7: return "DT_GNU_LIBLISTSZ";
case 0x6ffffdf8: return "DT_SUNW_CHECKSUM";
case DT_PLTPADSZ: return "DT_PLTPADSZ";
case DT_MOVEENT: return "DT_MOVEENT";
case DT_MOVESZ: return "DT_MOVESZ";
case 0x6ffffdfc: return "DT_FEATURE";
case DT_POSFLAG_1: return "DT_POSFLAG_1";
case DT_SYMINSZ: return "DT_SYMINSZ";
case DT_SYMINENT: return "DT_SYMINENT (DT_VALRNGHI)";
case DT_ADDRRNGLO: return "DT_ADDRRNGLO";
case DT_GNU_HASH: return "DT_GNU_HASH";
case 0x6ffffef8: return "DT_GNU_CONFLICT";
case 0x6ffffef9: return "DT_GNU_LIBLIST";
case 0x6ffffefa: return "DT_CONFIG";
case 0x6ffffefb: return "DT_DEPAUDIT";
case 0x6ffffefc: return "DT_AUDIT";
case 0x6ffffefd: return "DT_PLTPAD";
case 0x6ffffefe: return "DT_MOVETAB";
case DT_SYMINFO: return "DT_SYMINFO (DT_ADDRRNGHI)";
case DT_RELACOUNT: return "DT_RELACOUNT";
case DT_RELCOUNT: return "DT_RELCOUNT";
case DT_FLAGS_1: return "DT_FLAGS_1";
case DT_VERDEF: return "DT_VERDEF";
case DT_VERDEFNUM: return "DT_VERDEFNUM";
case DT_VERNEED: return "DT_VERNEED";
case DT_VERNEEDNUM: return "DT_VERNEEDNUM";
case 0x6ffffff0: return "DT_GNU_VERSYM";
/* 0x70000000 - 0x7fffffff processor-specific semantics */
case 0x70000000: return "DT_IA_64_PLT_RESERVE";
case 0x7ffffffd: return "DT_SUNW_AUXILIARY";
case 0x7ffffffe: return "DT_SUNW_USED";
case 0x7fffffff: return "DT_SUNW_FILTER";
default: return "ERROR: TAG NOT DEFINED";
case 0x70000000: return "DT_IA_64_PLT_RESERVE";
case 0x7ffffffd: return "DT_SUNW_AUXILIARY";
case 0x7ffffffe: return "DT_SUNW_USED";
case 0x7fffffff: return "DT_SUNW_FILTER";
}
snprintf(unknown_buf, sizeof(unknown_buf),
"<unknown: %#llx>", (unsigned long long)tag);
return (unknown_buf);
}
static const char *
@ -313,42 +318,79 @@ sh_name(struct elfdump *ed, int ndx)
/* http://www.sco.com/developers/gabi/latest/ch4.sheader.html#sh_type */
static const char *
sh_types(u_int64_t sht) {
switch (sht) {
case 0: return "SHT_NULL";
case 1: return "SHT_PROGBITS";
case 2: return "SHT_SYMTAB";
case 3: return "SHT_STRTAB";
case 4: return "SHT_RELA";
case 5: return "SHT_HASH";
case 6: return "SHT_DYNAMIC";
case 7: return "SHT_NOTE";
case 8: return "SHT_NOBITS";
case 9: return "SHT_REL";
case 10: return "SHT_SHLIB";
case 11: return "SHT_DYNSYM";
case 14: return "SHT_INIT_ARRAY";
case 15: return "SHT_FINI_ARRAY";
case 16: return "SHT_PREINIT_ARRAY";
case 17: return "SHT_GROUP";
case 18: return "SHT_SYMTAB_SHNDX";
/* 0x60000000 - 0x6fffffff operating system-specific semantics */
case 0x6ffffff0: return "XXX:VERSYM";
case 0x6ffffff4: return "SHT_SUNW_dof";
case 0x6ffffff6: return "SHT_GNU_HASH";
case 0x6ffffff7: return "SHT_GNU_LIBLIST";
case 0x6ffffffc: return "XXX:VERDEF";
case 0x6ffffffd: return "SHT_SUNW(GNU)_verdef";
case 0x6ffffffe: return "SHT_SUNW(GNU)_verneed";
case 0x6fffffff: return "SHT_SUNW(GNU)_versym";
/* 0x70000000 - 0x7fffffff processor-specific semantics */
case 0x70000000: return "SHT_IA_64_EXT";
case 0x70000001: return "SHT_IA_64_UNWIND";
case 0x7ffffffd: return "XXX:AUXILIARY";
case 0x7fffffff: return "XXX:FILTER";
/* 0x80000000 - 0xffffffff application programs */
default: return "ERROR: SHT NOT DEFINED";
sh_types(uint64_t mach, uint64_t sht) {
static char unknown_buf[64];
if (sht < 0x60000000) {
switch (sht) {
case SHT_NULL: return "SHT_NULL";
case SHT_PROGBITS: return "SHT_PROGBITS";
case SHT_SYMTAB: return "SHT_SYMTAB";
case SHT_STRTAB: return "SHT_STRTAB";
case SHT_RELA: return "SHT_RELA";
case SHT_HASH: return "SHT_HASH";
case SHT_DYNAMIC: return "SHT_DYNAMIC";
case SHT_NOTE: return "SHT_NOTE";
case SHT_NOBITS: return "SHT_NOBITS";
case SHT_REL: return "SHT_REL";
case SHT_SHLIB: return "SHT_SHLIB";
case SHT_DYNSYM: return "SHT_DYNSYM";
case SHT_INIT_ARRAY: return "SHT_INIT_ARRAY";
case SHT_FINI_ARRAY: return "SHT_FINI_ARRAY";
case SHT_PREINIT_ARRAY: return "SHT_PREINIT_ARRAY";
case SHT_GROUP: return "SHT_GROUP";
case SHT_SYMTAB_SHNDX: return "SHT_SYMTAB_SHNDX";
}
} else if (sht < 0x70000000) {
/* 0x60000000-0x6fffffff operating system-specific semantics */
switch (sht) {
case 0x6ffffff0: return "XXX:VERSYM";
case SHT_SUNW_dof: return "SHT_SUNW_dof";
case SHT_GNU_HASH: return "SHT_GNU_HASH";
case 0x6ffffff7: return "SHT_GNU_LIBLIST";
case 0x6ffffffc: return "XXX:VERDEF";
case SHT_SUNW_verdef: return "SHT_SUNW(GNU)_verdef";
case SHT_SUNW_verneed: return "SHT_SUNW(GNU)_verneed";
case SHT_SUNW_versym: return "SHT_SUNW(GNU)_versym";
}
} else if (sht < 0x80000000) {
/* 0x70000000 - 0x7fffffff processor-specific semantics */
switch (mach) {
case EM_ARM:
switch (sht) {
case SHT_ARM_EXIDX: return "SHT_ARM_EXIDX";
case SHT_ARM_PREEMPTMAP: return "SHT_ARM_PREEMPTMAP";
case SHT_ARM_ATTRIBUTES: return "SHT_ARM_ATTRIBUTES";
case SHT_ARM_DEBUGOVERLAY:
return "SHT_ARM_DEBUGOVERLAY";
case SHT_ARM_OVERLAYSECTION:
return "SHT_ARM_OVERLAYSECTION";
}
break;
case EM_IA_64:
switch (sht) {
case 0x70000000: return "SHT_IA_64_EXT";
case 0x70000001: return "SHT_IA_64_UNWIND";
}
break;
case EM_MIPS:
switch (sht) {
case SHT_MIPS_REGINFO: return "SHT_MIPS_REGINFO";
case SHT_MIPS_OPTIONS: return "SHT_MIPS_OPTIONS";
case SHT_MIPS_ABIFLAGS: return "SHT_MIPS_ABIFLAGS";
}
break;
}
switch (sht) {
case 0x7ffffffd: return "XXX:AUXILIARY";
case 0x7fffffff: return "XXX:FILTER";
}
}
/* 0x80000000 - 0xffffffff application programs */
snprintf(unknown_buf, sizeof(unknown_buf),
"<unknown: %#llx>", (unsigned long long)sht);
return (unknown_buf);
}
/*
@ -390,22 +432,87 @@ sh_flags(uint64_t shf)
return (flg);
}
static const char *st_types[] = {
"STT_NOTYPE", "STT_OBJECT", "STT_FUNC", "STT_SECTION", "STT_FILE",
"STT_COMMON", "STT_TLS"
};
static const char *
st_type(unsigned int mach, unsigned int type)
{
static char s_type[32];
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));
}
}
}

View File

@ -0,0 +1,2 @@
# TODO(#511): Revert after the source tree is -Wconversion clean.
WARNS=5

View File

@ -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. */

View File

@ -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

View File

@ -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);
}

View File

@ -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;

View File

@ -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;

View File

@ -0,0 +1,2 @@
# TODO(#511): Revert after the source tree is -Wconversion clean.
WARNS=5

View File

@ -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__)

View File

@ -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

View File

@ -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

View File

@ -37,7 +37,7 @@
#include <sys/mman.h>
#endif
ELFTC_VCSID("$Id: elftc_copyfile.c 2981 2014-02-01 02:41:13Z jkoshy $");
ELFTC_VCSID("$Id: elftc_copyfile.c 3297 2016-01-09 15:26:34Z jkoshy $");
/*
* Copy the contents referenced by 'ifd' to 'ofd'. Returns 0 on
@ -47,11 +47,11 @@ ELFTC_VCSID("$Id: elftc_copyfile.c 2981 2014-02-01 02:41:13Z jkoshy $");
int
elftc_copyfile(int ifd, int ofd)
{
size_t file_size, n;
int buf_mmapped;
struct stat sb;
char *b, *buf;
ssize_t nw;
size_t n;
ssize_t nr, nw;
/* Determine the input file's size. */
if (fstat(ifd, &sb) < 0)
@ -63,12 +63,13 @@ elftc_copyfile(int ifd, int ofd)
buf = NULL;
buf_mmapped = 0;
file_size = (size_t) sb.st_size;
#if ELFTC_HAVE_MMAP
/*
* Prefer mmap() if it is available.
*/
buf = mmap(NULL, sb.st_size, PROT_READ, MAP_SHARED, ifd, (off_t) 0);
buf = mmap(NULL, file_size, PROT_READ, MAP_SHARED, ifd, (off_t) 0);
if (buf != MAP_FAILED)
buf_mmapped = 1;
else
@ -80,24 +81,27 @@ elftc_copyfile(int ifd, int ofd)
* failed, allocate a buffer, and read in input data.
*/
if (buf_mmapped == false) {
if ((buf = malloc(sb.st_size)) == NULL)
return (-1);
if (read(ifd, buf, sb.st_size) != sb.st_size) {
free(buf);
if ((buf = malloc(file_size)) == NULL)
return (-1);
b = buf;
for (n = file_size; n > 0; n -= (size_t) nr, b += nr) {
if ((nr = read(ifd, b, n)) < 0) {
free(buf);
return (-1);
}
}
}
/*
* Write data to the output file descriptor.
*/
for (n = sb.st_size, b = buf; n > 0; n -= nw, b += nw)
for (n = file_size, b = buf; n > 0; n -= (size_t) nw, b += nw)
if ((nw = write(ofd, b, n)) <= 0)
break;
/* Release the input buffer. */
#if ELFTC_HAVE_MMAP
if (buf_mmapped && munmap(buf, sb.st_size) < 0)
if (buf_mmapped && munmap(buf, file_size) < 0)
return (-1);
#endif

View File

@ -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;

View File

@ -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

View File

@ -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;
/*

View File

@ -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,

View File

@ -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'):

View File

@ -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"

View File

@ -0,0 +1,2 @@
# TODO(#511): Revert after the source tree is -Wconversion clean.
WARNS=5

View 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"

View 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_ */

View 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_ */

View 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);
}

View 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);
}

View 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);
}

View 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);
}

View 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);
}

View 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);
}

View 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);
}

View 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

View File

@ -0,0 +1,2 @@
# TODO(#511): Revert after the source tree is -Wconversion clean.
WARNS=5

View 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_ */

View 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);
}

View 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);
}

View 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);
}

View 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);
}

View 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);
}

View 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);
}

View 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);
}

View 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);
}

View 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);
}

View 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);
}

View File

@ -0,0 +1,2 @@
# TODO(#511): Revert after the source tree is -Wconversion clean.
WARNS=5

View File

@ -0,0 +1,2 @@
# TODO(#511): Revert after the source tree is -Wconversion clean.
WARNS=5

View File

@ -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;

View File

@ -0,0 +1,2 @@
# TODO(#511): Revert after the source tree is -Wconversion clean.
WARNS=5

View File

@ -0,0 +1,2 @@
# TODO(#511): Revert after the source tree is -Wconversion clean.
WARNS=5

View File

@ -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 .

View File

@ -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;

View File

@ -95,7 +95,7 @@ PYUNBOUND_SRC=
# libunbound_wrap.lo if python libunbound wrapper enabled.
PYUNBOUND_OBJ=@PYUNBOUND_OBJ@
COMMON_SRC=services/cache/dns.c services/cache/infra.c services/cache/rrset.c \
util/data/dname.c util/data/msgencode.c util/data/msgparse.c \
util/as112.c util/data/dname.c util/data/msgencode.c util/data/msgparse.c \
util/data/msgreply.c util/data/packed_rrset.c iterator/iterator.c \
iterator/iter_delegpt.c iterator/iter_donotq.c iterator/iter_fwd.c \
iterator/iter_hints.c iterator/iter_priv.c iterator/iter_resptype.c \
@ -113,7 +113,7 @@ validator/val_neg.c validator/val_nsec3.c validator/val_nsec.c \
validator/val_secalgo.c validator/val_sigcrypt.c \
validator/val_utils.c dns64/dns64.c $(CHECKLOCK_SRC) $(DNSTAP_SRC)
COMMON_OBJ_WITHOUT_NETCALL=dns.lo infra.lo rrset.lo dname.lo msgencode.lo \
msgparse.lo msgreply.lo packed_rrset.lo iterator.lo iter_delegpt.lo \
as112.lo msgparse.lo msgreply.lo packed_rrset.lo iterator.lo iter_delegpt.lo \
iter_donotq.lo iter_fwd.lo iter_hints.lo iter_priv.lo iter_resptype.lo \
iter_scrub.lo iter_utils.lo localzone.lo mesh.lo modstack.lo \
outbound_list.lo alloc.lo config_file.lo configlexer.lo configparser.lo \
@ -595,6 +595,7 @@ depend:
rm -f $(DEPEND_TMP) $(DEPEND_TMP2)
# Dependencies
as112.lo as112.o: $(srcdir)/util/as112.c $(srcdir)/util/as112.h
dns.lo dns.o: $(srcdir)/services/cache/dns.c config.h $(srcdir)/iterator/iter_delegpt.h $(srcdir)/util/log.h \
$(srcdir)/validator/val_nsec.h $(srcdir)/util/data/packed_rrset.h $(srcdir)/util/storage/lruhash.h \
$(srcdir)/util/locks.h $(srcdir)/services/cache/dns.h $(srcdir)/util/data/msgreply.h \
@ -702,7 +703,7 @@ localzone.lo localzone.o: $(srcdir)/services/localzone.c config.h $(srcdir)/serv
$(srcdir)/sldns/sbuffer.h $(srcdir)/util/regional.h $(srcdir)/util/config_file.h $(srcdir)/util/data/dname.h \
$(srcdir)/util/storage/lruhash.h $(srcdir)/util/data/packed_rrset.h $(srcdir)/util/data/msgencode.h \
$(srcdir)/util/net_help.h $(srcdir)/util/netevent.h $(srcdir)/util/data/msgreply.h \
$(srcdir)/util/data/msgparse.h $(srcdir)/sldns/pkthdr.h
$(srcdir)/util/data/msgparse.h $(srcdir)/sldns/pkthdr.h $(srcdir)/util/as112.h
mesh.lo mesh.o: $(srcdir)/services/mesh.c config.h $(srcdir)/services/mesh.h $(srcdir)/util/rbtree.h \
$(srcdir)/util/netevent.h $(srcdir)/util/data/msgparse.h $(srcdir)/util/storage/lruhash.h $(srcdir)/util/locks.h \
$(srcdir)/util/log.h $(srcdir)/sldns/pkthdr.h $(srcdir)/sldns/rrdef.h $(srcdir)/util/module.h \
@ -821,7 +822,7 @@ val_anchor.lo val_anchor.o: $(srcdir)/validator/val_anchor.c config.h $(srcdir)/
$(srcdir)/util/rbtree.h $(srcdir)/util/locks.h $(srcdir)/util/log.h $(srcdir)/validator/val_sigcrypt.h \
$(srcdir)/util/data/packed_rrset.h $(srcdir)/util/storage/lruhash.h $(srcdir)/validator/autotrust.h \
$(srcdir)/util/data/dname.h $(srcdir)/util/net_help.h $(srcdir)/util/config_file.h $(srcdir)/sldns/sbuffer.h \
$(srcdir)/sldns/rrdef.h $(srcdir)/sldns/str2wire.h
$(srcdir)/sldns/rrdef.h $(srcdir)/sldns/str2wire.h $(srcdir)/util/as112.h
validator.lo validator.o: $(srcdir)/validator/validator.c config.h $(srcdir)/validator/validator.h \
$(srcdir)/util/module.h $(srcdir)/util/storage/lruhash.h $(srcdir)/util/locks.h $(srcdir)/util/log.h \
$(srcdir)/util/data/msgreply.h $(srcdir)/util/data/packed_rrset.h $(srcdir)/util/data/msgparse.h \

View File

@ -508,13 +508,17 @@ server:
# local-zone: "8.b.d.0.1.0.0.2.ip6.arpa." nodefault
# And for 64.100.in-addr.arpa. to 127.100.in-addr.arpa.
# if unbound is running service for the local host then it is useful
# If unbound is running service for the local host then it is useful
# to perform lan-wide lookups to the upstream, and unblock the
# long list of local-zones above. If this unbound is a dns server
# for a network of computers, disabled is better and stops information
# leakage of local lan information.
# unblock-lan-zones: no
# The insecure-lan-zones option disables validation for
# these zones, as if they were all listed as domain-insecure.
# insecure-lan-zones: no
# a number of locally served zones can be configured.
# local-zone: <zone> <type>
# local-data: "<resource record string>"

View File

@ -508,13 +508,17 @@ server:
# local-zone: "8.b.d.0.1.0.0.2.ip6.arpa." nodefault
# And for 64.100.in-addr.arpa. to 127.100.in-addr.arpa.
# if unbound is running service for the local host then it is useful
# If unbound is running service for the local host then it is useful
# to perform lan-wide lookups to the upstream, and unblock the
# long list of local-zones above. If this unbound is a dns server
# for a network of computers, disabled is better and stops information
# leakage of local lan information.
# unblock-lan-zones: no
# The insecure-lan-zones option disables validation for
# these zones, as if they were all listed as domain-insecure.
# insecure-lan-zones: no
# a number of locally served zones can be configured.
# local-zone: <zone> <type>
# local-data: "<resource record string>"

View File

@ -841,6 +841,11 @@ as a (DHCP-) DNS network resolver for a group of machines, where such
lookups should be filtered (RFC compliance), this also stops potential
data leakage about the local network to the upstream DNS servers.
.TP
.B insecure\-lan\-zones: \fI<yesno>
Default is disabled. If enabled, then reverse lookups in private
address space are not validated. This is usually required whenever
\fIunblock\-lan\-zones\fR is used.
.TP
.B local\-zone: \fI<zone> <type>
Configure a local zone. The type determines the answer to give if
there is no match from local\-data. The types are deny, refuse, static,

View File

@ -841,6 +841,11 @@ as a (DHCP-) DNS network resolver for a group of machines, where such
lookups should be filtered (RFC compliance), this also stops potential
data leakage about the local network to the upstream DNS servers.
.TP
.B insecure\-lan\-zones: \fI<yesno>
Default is disabled. If enabled, then reverse lookups in private
address space are not validated. This is usually required whenever
\fIunblock\-lan\-zones\fR is used.
.TP
.B local\-zone: \fI<zone> <type>
Configure a local zone. The type determines the answer to give if
there is no match from local\-data. The types are deny, refuse, static,

View File

@ -51,6 +51,7 @@
#include "util/netevent.h"
#include "util/data/msgreply.h"
#include "util/data/msgparse.h"
#include "util/as112.h"
struct local_zones*
local_zones_create(void)
@ -592,6 +593,7 @@ static int
lz_enter_defaults(struct local_zones* zones, struct config_file* cfg)
{
struct local_zone* z;
const char** zstr;
/* this list of zones is from RFC 6303 */
@ -654,110 +656,14 @@ lz_enter_defaults(struct local_zones* zones, struct config_file* cfg)
lock_rw_unlock(&z->lock);
}
/* if unblock lan-zones, then do not add the zones below.
* we do add the zones above, about 127.0.0.1, because localhost is
* not on the lan. */
if(cfg->unblock_lan_zones)
return 1;
/* block LAN level zones */
if ( !add_as112_default(zones, cfg, "10.in-addr.arpa.") ||
!add_as112_default(zones, cfg, "16.172.in-addr.arpa.") ||
!add_as112_default(zones, cfg, "17.172.in-addr.arpa.") ||
!add_as112_default(zones, cfg, "18.172.in-addr.arpa.") ||
!add_as112_default(zones, cfg, "19.172.in-addr.arpa.") ||
!add_as112_default(zones, cfg, "20.172.in-addr.arpa.") ||
!add_as112_default(zones, cfg, "21.172.in-addr.arpa.") ||
!add_as112_default(zones, cfg, "22.172.in-addr.arpa.") ||
!add_as112_default(zones, cfg, "23.172.in-addr.arpa.") ||
!add_as112_default(zones, cfg, "24.172.in-addr.arpa.") ||
!add_as112_default(zones, cfg, "25.172.in-addr.arpa.") ||
!add_as112_default(zones, cfg, "26.172.in-addr.arpa.") ||
!add_as112_default(zones, cfg, "27.172.in-addr.arpa.") ||
!add_as112_default(zones, cfg, "28.172.in-addr.arpa.") ||
!add_as112_default(zones, cfg, "29.172.in-addr.arpa.") ||
!add_as112_default(zones, cfg, "30.172.in-addr.arpa.") ||
!add_as112_default(zones, cfg, "31.172.in-addr.arpa.") ||
!add_as112_default(zones, cfg, "168.192.in-addr.arpa.") ||
!add_as112_default(zones, cfg, "0.in-addr.arpa.") ||
!add_as112_default(zones, cfg, "64.100.in-addr.arpa.") ||
!add_as112_default(zones, cfg, "65.100.in-addr.arpa.") ||
!add_as112_default(zones, cfg, "66.100.in-addr.arpa.") ||
!add_as112_default(zones, cfg, "67.100.in-addr.arpa.") ||
!add_as112_default(zones, cfg, "68.100.in-addr.arpa.") ||
!add_as112_default(zones, cfg, "69.100.in-addr.arpa.") ||
!add_as112_default(zones, cfg, "70.100.in-addr.arpa.") ||
!add_as112_default(zones, cfg, "71.100.in-addr.arpa.") ||
!add_as112_default(zones, cfg, "72.100.in-addr.arpa.") ||
!add_as112_default(zones, cfg, "73.100.in-addr.arpa.") ||
!add_as112_default(zones, cfg, "74.100.in-addr.arpa.") ||
!add_as112_default(zones, cfg, "75.100.in-addr.arpa.") ||
!add_as112_default(zones, cfg, "76.100.in-addr.arpa.") ||
!add_as112_default(zones, cfg, "77.100.in-addr.arpa.") ||
!add_as112_default(zones, cfg, "78.100.in-addr.arpa.") ||
!add_as112_default(zones, cfg, "79.100.in-addr.arpa.") ||
!add_as112_default(zones, cfg, "80.100.in-addr.arpa.") ||
!add_as112_default(zones, cfg, "81.100.in-addr.arpa.") ||
!add_as112_default(zones, cfg, "82.100.in-addr.arpa.") ||
!add_as112_default(zones, cfg, "83.100.in-addr.arpa.") ||
!add_as112_default(zones, cfg, "84.100.in-addr.arpa.") ||
!add_as112_default(zones, cfg, "85.100.in-addr.arpa.") ||
!add_as112_default(zones, cfg, "86.100.in-addr.arpa.") ||
!add_as112_default(zones, cfg, "87.100.in-addr.arpa.") ||
!add_as112_default(zones, cfg, "88.100.in-addr.arpa.") ||
!add_as112_default(zones, cfg, "89.100.in-addr.arpa.") ||
!add_as112_default(zones, cfg, "90.100.in-addr.arpa.") ||
!add_as112_default(zones, cfg, "91.100.in-addr.arpa.") ||
!add_as112_default(zones, cfg, "92.100.in-addr.arpa.") ||
!add_as112_default(zones, cfg, "93.100.in-addr.arpa.") ||
!add_as112_default(zones, cfg, "94.100.in-addr.arpa.") ||
!add_as112_default(zones, cfg, "95.100.in-addr.arpa.") ||
!add_as112_default(zones, cfg, "96.100.in-addr.arpa.") ||
!add_as112_default(zones, cfg, "97.100.in-addr.arpa.") ||
!add_as112_default(zones, cfg, "98.100.in-addr.arpa.") ||
!add_as112_default(zones, cfg, "99.100.in-addr.arpa.") ||
!add_as112_default(zones, cfg, "100.100.in-addr.arpa.") ||
!add_as112_default(zones, cfg, "101.100.in-addr.arpa.") ||
!add_as112_default(zones, cfg, "102.100.in-addr.arpa.") ||
!add_as112_default(zones, cfg, "103.100.in-addr.arpa.") ||
!add_as112_default(zones, cfg, "104.100.in-addr.arpa.") ||
!add_as112_default(zones, cfg, "105.100.in-addr.arpa.") ||
!add_as112_default(zones, cfg, "106.100.in-addr.arpa.") ||
!add_as112_default(zones, cfg, "107.100.in-addr.arpa.") ||
!add_as112_default(zones, cfg, "108.100.in-addr.arpa.") ||
!add_as112_default(zones, cfg, "109.100.in-addr.arpa.") ||
!add_as112_default(zones, cfg, "110.100.in-addr.arpa.") ||
!add_as112_default(zones, cfg, "111.100.in-addr.arpa.") ||
!add_as112_default(zones, cfg, "112.100.in-addr.arpa.") ||
!add_as112_default(zones, cfg, "113.100.in-addr.arpa.") ||
!add_as112_default(zones, cfg, "114.100.in-addr.arpa.") ||
!add_as112_default(zones, cfg, "115.100.in-addr.arpa.") ||
!add_as112_default(zones, cfg, "116.100.in-addr.arpa.") ||
!add_as112_default(zones, cfg, "117.100.in-addr.arpa.") ||
!add_as112_default(zones, cfg, "118.100.in-addr.arpa.") ||
!add_as112_default(zones, cfg, "119.100.in-addr.arpa.") ||
!add_as112_default(zones, cfg, "120.100.in-addr.arpa.") ||
!add_as112_default(zones, cfg, "121.100.in-addr.arpa.") ||
!add_as112_default(zones, cfg, "122.100.in-addr.arpa.") ||
!add_as112_default(zones, cfg, "123.100.in-addr.arpa.") ||
!add_as112_default(zones, cfg, "124.100.in-addr.arpa.") ||
!add_as112_default(zones, cfg, "125.100.in-addr.arpa.") ||
!add_as112_default(zones, cfg, "126.100.in-addr.arpa.") ||
!add_as112_default(zones, cfg, "127.100.in-addr.arpa.") ||
!add_as112_default(zones, cfg, "254.169.in-addr.arpa.") ||
!add_as112_default(zones, cfg, "2.0.192.in-addr.arpa.") ||
!add_as112_default(zones, cfg, "100.51.198.in-addr.arpa.") ||
!add_as112_default(zones, cfg, "113.0.203.in-addr.arpa.") ||
!add_as112_default(zones, cfg, "255.255.255.255.in-addr.arpa.") ||
!add_as112_default(zones, cfg, "0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.ip6.arpa.") ||
!add_as112_default(zones, cfg, "d.f.ip6.arpa.") ||
!add_as112_default(zones, cfg, "8.e.f.ip6.arpa.") ||
!add_as112_default(zones, cfg, "9.e.f.ip6.arpa.") ||
!add_as112_default(zones, cfg, "a.e.f.ip6.arpa.") ||
!add_as112_default(zones, cfg, "b.e.f.ip6.arpa.") ||
!add_as112_default(zones, cfg, "8.b.d.0.1.0.0.2.ip6.arpa.")) {
log_err("out of memory adding default zone");
return 0;
/* block AS112 zones, unless asked not to */
if(!cfg->unblock_lan_zones) {
for(zstr = as112_zones; *zstr; zstr++) {
if(!add_as112_default(zones, cfg, *zstr)) {
log_err("out of memory adding default zone");
return 0;
}
}
}
return 1;
}

View File

@ -0,0 +1,143 @@
/*
* util/as112.c - list of local zones.
*
* Copyright (c) 2007, NLnet Labs. All rights reserved.
*
* This software is open source.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* 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.
*
* Neither the name of the NLNET LABS nor the names of its contributors may
* be used to endorse or promote products derived from this software without
* specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 COPYRIGHT
* HOLDER 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.
*/
/**
* \file
*
* This file provides a list of lan zones.
*/
#include "util/as112.h"
static const char* as112_zone_array[] = {
"10.in-addr.arpa.",
"16.172.in-addr.arpa.",
"17.172.in-addr.arpa.",
"18.172.in-addr.arpa.",
"19.172.in-addr.arpa.",
"20.172.in-addr.arpa.",
"21.172.in-addr.arpa.",
"22.172.in-addr.arpa.",
"23.172.in-addr.arpa.",
"24.172.in-addr.arpa.",
"25.172.in-addr.arpa.",
"26.172.in-addr.arpa.",
"27.172.in-addr.arpa.",
"28.172.in-addr.arpa.",
"29.172.in-addr.arpa.",
"30.172.in-addr.arpa.",
"31.172.in-addr.arpa.",
"168.192.in-addr.arpa.",
"0.in-addr.arpa.",
"64.100.in-addr.arpa.",
"65.100.in-addr.arpa.",
"66.100.in-addr.arpa.",
"67.100.in-addr.arpa.",
"68.100.in-addr.arpa.",
"69.100.in-addr.arpa.",
"70.100.in-addr.arpa.",
"71.100.in-addr.arpa.",
"72.100.in-addr.arpa.",
"73.100.in-addr.arpa.",
"74.100.in-addr.arpa.",
"75.100.in-addr.arpa.",
"76.100.in-addr.arpa.",
"77.100.in-addr.arpa.",
"78.100.in-addr.arpa.",
"79.100.in-addr.arpa.",
"80.100.in-addr.arpa.",
"81.100.in-addr.arpa.",
"82.100.in-addr.arpa.",
"83.100.in-addr.arpa.",
"84.100.in-addr.arpa.",
"85.100.in-addr.arpa.",
"86.100.in-addr.arpa.",
"87.100.in-addr.arpa.",
"88.100.in-addr.arpa.",
"89.100.in-addr.arpa.",
"90.100.in-addr.arpa.",
"91.100.in-addr.arpa.",
"92.100.in-addr.arpa.",
"93.100.in-addr.arpa.",
"94.100.in-addr.arpa.",
"95.100.in-addr.arpa.",
"96.100.in-addr.arpa.",
"97.100.in-addr.arpa.",
"98.100.in-addr.arpa.",
"99.100.in-addr.arpa.",
"100.100.in-addr.arpa.",
"101.100.in-addr.arpa.",
"102.100.in-addr.arpa.",
"103.100.in-addr.arpa.",
"104.100.in-addr.arpa.",
"105.100.in-addr.arpa.",
"106.100.in-addr.arpa.",
"107.100.in-addr.arpa.",
"108.100.in-addr.arpa.",
"109.100.in-addr.arpa.",
"110.100.in-addr.arpa.",
"111.100.in-addr.arpa.",
"112.100.in-addr.arpa.",
"113.100.in-addr.arpa.",
"114.100.in-addr.arpa.",
"115.100.in-addr.arpa.",
"116.100.in-addr.arpa.",
"117.100.in-addr.arpa.",
"118.100.in-addr.arpa.",
"119.100.in-addr.arpa.",
"120.100.in-addr.arpa.",
"121.100.in-addr.arpa.",
"122.100.in-addr.arpa.",
"123.100.in-addr.arpa.",
"124.100.in-addr.arpa.",
"125.100.in-addr.arpa.",
"126.100.in-addr.arpa.",
"127.100.in-addr.arpa.",
"254.169.in-addr.arpa.",
"2.0.192.in-addr.arpa.",
"100.51.198.in-addr.arpa.",
"113.0.203.in-addr.arpa.",
"255.255.255.255.in-addr.arpa.",
"0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.ip6.arpa.",
"d.f.ip6.arpa.",
"8.e.f.ip6.arpa.",
"9.e.f.ip6.arpa.",
"a.e.f.ip6.arpa.",
"b.e.f.ip6.arpa.",
"8.b.d.0.1.0.0.2.ip6.arpa.",
0
};
const char** as112_zones = as112_zone_array;

View File

@ -0,0 +1,57 @@
/*
* util/as112.c - list of local zones.
*
* Copyright (c) 2007, NLnet Labs. All rights reserved.
*
* This software is open source.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* 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.
*
* Neither the name of the NLNET LABS nor the names of its contributors may
* be used to endorse or promote products derived from this software without
* specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 COPYRIGHT
* HOLDER 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.
*/
/**
* \file
*
* This file provides a list of lan zones
*/
#ifndef UTIL_AS112_H
#define UTIL_AS112_H
/**
* Array of text-format domain names of the AS112 zones.
* The array ends with NULL. "AS112" is a service on the internet that
* that this array is named after. The names in this list (or some of them)
* are null-routed by this service to avoid load on central servers caused by
* mistaken lookups for local content on the global internet.
*
* This is the list of names that unbound should not normally be sending
* on towards the internet, because they are local-use.
*/
extern const char** as112_zones;
#endif

View File

@ -210,6 +210,7 @@ config_create(void)
cfg->local_zones_nodefault = NULL;
cfg->local_data = NULL;
cfg->unblock_lan_zones = 0;
cfg->insecure_lan_zones = 0;
cfg->python_script = NULL;
cfg->remote_control_enable = 0;
cfg->control_ifs = NULL;
@ -458,6 +459,7 @@ int config_set_option(struct config_file* cfg, const char* opt,
else S_YNO("rrset-roundrobin:", rrset_roundrobin)
else S_STRLIST("local-data:", local_data)
else S_YNO("unblock-lan-zones:", unblock_lan_zones)
else S_YNO("insecure-lan-zones:", insecure_lan_zones)
else S_YNO("control-enable:", remote_control_enable)
else S_STRLIST("control-interface:", control_ifs)
else S_NUMBER_NONZERO("control-port:", control_port)
@ -739,6 +741,7 @@ config_get_option(struct config_file* cfg, const char* opt,
else O_YNO(opt, "minimal-responses", minimal_responses)
else O_YNO(opt, "rrset-roundrobin", rrset_roundrobin)
else O_YNO(opt, "unblock-lan-zones", unblock_lan_zones)
else O_YNO(opt, "insecure-lan-zones", insecure_lan_zones)
else O_DEC(opt, "max-udp-size", max_udp_size)
else O_STR(opt, "python-script", python_script)
else O_DEC(opt, "ratelimit", ratelimit)

View File

@ -285,8 +285,10 @@ struct config_file {
struct config_strlist* local_zones_nodefault;
/** local data RRs configured */
struct config_strlist* local_data;
/** unblock lan zones (reverse lookups for 10/8 and so on) */
/** unblock lan zones (reverse lookups for AS112 zones) */
int unblock_lan_zones;
/** insecure lan zones (don't validate AS112 zones) */
int insecure_lan_zones;
/** remote control section. enable toggle. */
int remote_control_enable;

View File

@ -321,6 +321,7 @@ local-zone{COLON} { YDVAR(2, VAR_LOCAL_ZONE) }
local-data{COLON} { YDVAR(1, VAR_LOCAL_DATA) }
local-data-ptr{COLON} { YDVAR(1, VAR_LOCAL_DATA_PTR) }
unblock-lan-zones{COLON} { YDVAR(1, VAR_UNBLOCK_LAN_ZONES) }
insecure-lan-zones{COLON} { YDVAR(1, VAR_INSECURE_LAN_ZONES) }
statistics-interval{COLON} { YDVAR(1, VAR_STATISTICS_INTERVAL) }
statistics-cumulative{COLON} { YDVAR(1, VAR_STATISTICS_CUMULATIVE) }
extended-statistics{COLON} { YDVAR(1, VAR_EXTENDED_STATISTICS) }

View File

@ -106,7 +106,8 @@ extern struct config_parser_state* cfg_parser;
%token VAR_IGNORE_CD_FLAG VAR_LOG_QUERIES VAR_TCP_UPSTREAM VAR_SSL_UPSTREAM
%token VAR_SSL_SERVICE_KEY VAR_SSL_SERVICE_PEM VAR_SSL_PORT VAR_FORWARD_FIRST
%token VAR_STUB_FIRST VAR_MINIMAL_RESPONSES VAR_RRSET_ROUNDROBIN
%token VAR_MAX_UDP_SIZE VAR_DELAY_CLOSE VAR_UNBLOCK_LAN_ZONES
%token VAR_MAX_UDP_SIZE VAR_DELAY_CLOSE
%token VAR_UNBLOCK_LAN_ZONES VAR_INSECURE_LAN_ZONES
%token VAR_INFRA_CACHE_MIN_RTT
%token VAR_DNS64_PREFIX VAR_DNS64_SYNTHALL
%token VAR_DNSTAP VAR_DNSTAP_ENABLE VAR_DNSTAP_SOCKET_PATH
@ -180,7 +181,8 @@ content_server: server_num_threads | server_verbosity | server_port |
server_log_queries | server_tcp_upstream | server_ssl_upstream |
server_ssl_service_key | server_ssl_service_pem | server_ssl_port |
server_minimal_responses | server_rrset_roundrobin | server_max_udp_size |
server_so_reuseport | server_delay_close | server_unblock_lan_zones |
server_so_reuseport | server_delay_close |
server_unblock_lan_zones | server_insecure_lan_zones |
server_dns64_prefix | server_dns64_synthall |
server_infra_cache_min_rtt | server_harden_algo_downgrade |
server_ip_transparent | server_ratelimit | server_ratelimit_slabs |
@ -722,6 +724,16 @@ server_unblock_lan_zones: VAR_UNBLOCK_LAN_ZONES STRING_ARG
free($2);
}
;
server_insecure_lan_zones: VAR_INSECURE_LAN_ZONES STRING_ARG
{
OUTYY(("P(server_insecure_lan_zones:%s)\n", $2));
if(strcmp($2, "yes") != 0 && strcmp($2, "no") != 0)
yyerror("expected yes or no.");
else cfg_parser->cfg->insecure_lan_zones =
(strcmp($2, "yes")==0);
free($2);
}
;
server_rrset_cache_size: VAR_RRSET_CACHE_SIZE STRING_ARG
{
OUTYY(("P(server_rrset_cache_size:%s)\n", $2));

View File

@ -48,6 +48,7 @@
#include "util/log.h"
#include "util/net_help.h"
#include "util/config_file.h"
#include "util/as112.h"
#include "sldns/sbuffer.h"
#include "sldns/rrdef.h"
#include "sldns/str2wire.h"
@ -1044,8 +1045,18 @@ int
anchors_apply_cfg(struct val_anchors* anchors, struct config_file* cfg)
{
struct config_strlist* f;
const char** zstr;
char* nm;
sldns_buffer* parsebuf = sldns_buffer_new(65535);
if(cfg->insecure_lan_zones) {
for(zstr = as112_zones; *zstr; zstr++) {
if(!anchor_insert_insecure(anchors, *zstr)) {
log_err("error in insecure-lan-zones: %s", *zstr);
sldns_buffer_free(parsebuf);
return 0;
}
}
}
for(f = cfg->domain_insecure; f; f = f->next) {
if(!f->str || f->str[0] == 0) /* empty "" */
continue;

View File

@ -694,6 +694,7 @@ iovctl_files="" # Config files for iovctl(8)
jail_enable="NO" # Set to NO to disable starting of any jails
jail_parallel_start="NO" # Start jails in the background
jail_list="" # Space separated list of names of jails
jail_reverse_stop="NO" # Stop jails in reverse order
##############################################################
### Define source_rc_confs, the mechanism used by /etc/rc.* ##

View File

@ -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;"
@ -521,7 +536,11 @@ jail_stop()
command=$jail_program
rc_flags=$jail_flags
command_args="-f $jail_conf -r"
$jail_jls name | while read _j; do
if checkyesno jail_reverse_stop; then
$jail_jls name | tail -r
else
$jail_jls name
fi | while read _j; do
echo -n " $_j"
_tmp=`mktemp -t jail` || exit 3
$command $rc_flags $command_args $_j >> $_tmp 2>&1
@ -536,6 +555,7 @@ jail_stop()
return
;;
esac
checkyesno jail_reverse_stop && set -- $(reverse_list $@)
for _j in $@; do
_j=$(echo $_j | tr /. _)
_jv=$(echo -n $_j | tr -c '[:alnum:]' _)
@ -571,5 +591,6 @@ jail_warn()
load_rc_config $name
case $# in
1) run_rc_command $@ ${jail_list:-_ALL} ;;
*) run_rc_command $@ ;;
*) jail_reverse_stop="no"
run_rc_command $@ ;;
esac

View File

@ -28,14 +28,14 @@ ntpd_precmd()
rc_flags="-g $rc_flags"
fi
if [ -z "$ntpd_chrootdir" ]; then
return 0;
fi
if [ ! -f $ntp_db_leapfile ]; then
ntpd_fetch_leapfile
fi
if [ -z "$ntpd_chrootdir" ]; then
return 0;
fi
# If running in a chroot cage, ensure that the appropriate files
# exist inside the cage, as well as helper symlinks into the cage
# from outside.

View File

@ -36,6 +36,10 @@
#include <sys/cdefs.h>
#include <sys/_types.h>
#include <sys/signal.h>
#if __POSIX_VISIBLE >= 200112 || __XSI_VISIBLE
#include <machine/ucontext.h>
#include <sys/_ucontext.h>
#endif
#if __BSD_VISIBLE
/*
@ -114,7 +118,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 *);

View File

@ -80,6 +80,7 @@ SUBDIR= ${SUBDIR_ORDERED} \
libopie \
libpam \
libpcap \
${_libpe} \
libpjdlog \
${_libpmc} \
${_libproc} \
@ -185,6 +186,7 @@ _cuse= libcuse
.if ${MK_TOOLCHAIN} != "no"
_libelftc= libelftc
_libpe= libpe
.endif
.if ${MK_FILE} != "no"

View File

@ -28,7 +28,7 @@
.\" @(#)fgetln.3 8.3 (Berkeley) 4/19/94
.\" $FreeBSD$
.\"
.Dd April 19, 1994
.Dd February 15, 2016
.Dt FGETLN 3
.Os
.Sh NAME
@ -97,6 +97,9 @@ These changes are lost as soon as the pointer becomes invalid.
The argument
.Fa stream
is not a stream open for reading.
.It Bq Er ENOMEM
The internal line buffer could not be expanded due to lack of available memory,
or because it would need to expand beyond INT_MAX in size.
.El
.Pp
The

View File

@ -37,6 +37,8 @@ static char sccsid[] = "@(#)fgetln.c 8.2 (Berkeley) 1/2/94";
__FBSDID("$FreeBSD$");
#include "namespace.h"
#include <errno.h>
#include <limits.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
@ -61,6 +63,10 @@ __slbexpand(FILE *fp, size_t newsize)
#endif
if (fp->_lb._size >= newsize)
return (0);
if (newsize > INT_MAX) {
errno = ENOMEM;
return (-1);
}
if ((p = realloc(fp->_lb._base, newsize)) == NULL)
return (-1);
fp->_lb._base = p;
@ -152,13 +158,14 @@ fgetln(FILE *fp, size_t *lenp)
}
*lenp = len;
#ifdef notdef
fp->_lb._base[len] = 0;
fp->_lb._base[len] = '\0';
#endif
FUNLOCKFILE(fp);
return ((char *)fp->_lb._base);
error:
*lenp = 0; /* ??? */
fp->_flags |= __SERR;
FUNLOCKFILE(fp);
return (NULL); /* ??? */
}

View File

@ -37,6 +37,7 @@ static char sccsid[] = "@(#)fputs.c 8.1 (Berkeley) 6/4/93";
__FBSDID("$FreeBSD$");
#include "namespace.h"
#include <limits.h>
#include <stdio.h>
#include <string.h>
#include "un-namespace.h"
@ -62,5 +63,7 @@ fputs(const char * __restrict s, FILE * __restrict fp)
ORIENT(fp, -1);
retval = __sfvwrite(fp, &uio);
FUNLOCKFILE(fp);
if (retval == 0)
return (iov.iov_len > INT_MAX ? INT_MAX : iov.iov_len);
return (retval);
}

View File

@ -405,7 +405,6 @@ system calls appeared in
The jail feature was written by
.An Poul-Henning Kamp
for R&D Associates
.Dq Li http://www.rndassociates.com/
who contributed it to
.Fx .
.An James Gritton

View File

@ -6,5 +6,5 @@
const char *
elftc_version(void)
{
return "elftoolchain r3272M";
return "elftoolchain r3400M";
}

View File

@ -1435,7 +1435,6 @@ http_connect(struct url *URL, struct url *purl, const char *flags)
}
if (strcasecmp(URL->scheme, SCHEME_HTTPS) == 0 &&
fetch_ssl(conn, URL, verbose) == -1) {
fetch_close(conn);
/* grrr */
errno = EAUTH;
fetch_syserr();

34
lib/libpe/Makefile Normal file
View 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>

View File

@ -14,7 +14,7 @@ PACKAGE= unbound
CFLAGS= -I${UNBOUNDDIR} -I${LDNSDIR} -I${.OBJDIR}
SRCS= alloc.c autotrust.c config_file.c configlexer.l configparser.y \
SRCS= alloc.c as112.c autotrust.c config_file.c configlexer.l configparser.y \
context.c dname.c dns.c dns64.c dnstree.c fptr_wlist.c infra.c \
iter_delegpt.c iter_donotq.c iter_fwd.c iter_hints.c iter_priv.c \
iter_resptype.c iter_scrub.c iter_utils.c iterator.c keyraw.c \

View File

@ -1,5 +1,13 @@
# $FreeBSD$
The below 4 samples require a VIMAGE enabled kernel:
# (as root)
$ cp VIMAGE /usr/src/sys/amd64/conf/
$ cd /usr/src
$ make KERNCONF=VIMAGE kernel
$ reboot
Sample 1: jail.conf(5)
$ cp jib jng /usr/sbin/

View File

@ -0,0 +1,59 @@
# $FreeBSD$
################################################################################
######################### VIMAGE KERNEL CONFIGURATION ##########################
################################################################################
#################### Inheritance
#
# Inherit from, and override `GENERIC'
#
include GENERIC # Base configuration file
ident VIMAGE # Kernel name
################################################################################
##################### ENABLE NON-INHERITED OPTIONS/DEVICES #####################
################################################################################
#################### Non-GENERIC options
#
# Network Virtualization for Jails
#
options VIMAGE # vnet paravirtualization
#
# Netgraph based bridging for vnet jails
# NB: Not strictly necessary; will load automatically via KLD when needed
#
options NETGRAPH # netgraph(4) system
options NETGRAPH_BRIDGE # ng_bridge(4)
options NETGRAPH_EIFACE # ng_eiface(4)
options NETGRAPH_ETHER # ng_ether(4)
options NETGRAPH_SOCKET # ng_socket(4)
#################### Non-GENERIC devices
#
# if_bridge based bridging for vnet jails
# NB: Not strictly necessary; will load automatically via KLD when needed
#
device epair # epair(4)
device if_bridge # if_bridge(4)
################################################################################
################ DISABLE UNNECESSARY INHERITED OPTIONS/DEVICES ################
################################################################################
#################### Disable select inherited options
# none
#################### Disable select inherited devices
# none
################################################################################
# END
################################################################################

View File

@ -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
}

View File

@ -154,6 +154,7 @@ usage()
show \
show1 \
shutdown \
stats \
; do
eval usage=\"\$jng_${action}_usage\"
[ "$usage" ] || continue
@ -165,12 +166,93 @@ 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
}
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
@ -179,7 +261,7 @@ mustberoot_to_continue()
fi
}
jng_bridge_usage="bridge [-b BRIDGE_NAME] NAME interface0 [interface1 ...]"
jng_bridge_usage="bridge [-b BRIDGE_NAME] NAME [!|=]iface0 [[!|=]iface1 ...]"
jng_bridge_descr="Create ng0_NAME [ng1_NAME ...]"
jng_bridge()
{
@ -200,22 +282,32 @@ jng_bridge()
mustberoot_to_continue
local iface iface_devid eiface eiface_devid
local new num quad i=0
local iface parent eiface eiface_devid
local new clone_mac no_derive 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
clone_mac=
no_derive=
case "$iface" in
=*) iface=${iface#=} clone_mac=1 ;;
!*) iface=${iface#!} no_derive=1 ;;
esac
# 1. Bring the interface up
# 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
# 2. Set promiscuous mode and don't overwrite src addr
# 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
# 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 ||
@ -223,7 +315,7 @@ jng_bridge()
ngctl name $iface:lower ${iface}bridge || return
fi
# 3.5. Optionally create a secondary bridge
# Optionally create a secondary bridge
if [ "$bridge" != "bridge" ] &&
! ngctl info "$iface$bridge:" > /dev/null 2>&1
then
@ -239,7 +331,7 @@ jng_bridge()
return
fi
# 4. Create a new interface to the bridge
# Create a new interface to the bridge
num=2
while ngctl msg "$iface$bridge:" getstats $num > /dev/null 2>&1
do
@ -247,7 +339,7 @@ jng_bridge()
done
ngctl mkpeer "$iface$bridge:" eiface link$num ether || return
# 5. Rename the new interface
# Rename the new interface
while [ ${#eiface} -gt 15 ]; do # OS limitation
eiface=${eiface%?}
done
@ -258,79 +350,20 @@ jng_bridge()
ifconfig $eiface 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 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' )
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
?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
else
num=0
local _${iface}_num=$num
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
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
ifconfig $eiface ether $eiface_devid > /dev/null 2>&1
[ "$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
}
@ -414,6 +447,39 @@ jng_shutdown()
jng_show "$name" | xargs -rn1 -I eiface ngctl shutdown eiface:
}
jng_stats_usage="stats NAME"
jng_stats_descr="Show ng_bridge link statistics for NAME interfaces"
jng_stats()
{
local OPTIND=1 OPTARG flag
while getopts "" flag; do
case "$flag" in
*) action_usage stats # NOTREACHED
esac
done
shift $(( $OPTIND -1 ))
local name="$1"
[ "${name:-x}" = "${name#*[!0-9a-zA-Z_]}" -a $# -eq 1 ] ||
action_usage stats # NOTREACHED
mustberoot_to_continue
for eiface in $( jng_show "$name" ); do
echo "$eiface:"
ngctl show $eiface: | awk '
$3 == "bridge" && $5 ~ /^link/ {
bridge = $2
link = substr($5, 5)
system(sprintf("ngctl msg %s: getstats %u",
bridge, link))
}' | fmt 2 | awk '
/=/ && fl = index($0, "=") {
printf "%20s = %s\n",
substr($0, 0, fl-1),
substr($0, 0, fl+1)
}
' # END-QUOTE
done
}
############################################################ MAIN
#

View File

@ -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 ,

View File

@ -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

View File

@ -24,7 +24,7 @@
.\"
.\" $FreeBSD$
.\"
.Dd February 26, 2015
.Dd February 11, 2016
.Dt UEFI 8
.Os
.Sh NAME
@ -73,9 +73,34 @@ as
.Pa /EFI/BOOT/BOOTX64.EFI .
.It
.Pa boot1.efi
locates the first partition with the type
.Li freebsd-ufs ,
and from it loads
reads boot configuration from
.Pa /boot.config
or
.Pa /boot/config .
Unlike other first-stage boot loaders,
.Pa boot1.efi
passes the configuration to the next stage boot loader and does not
itself act on the contents of the file.
.It
.Pa boot1.efi
searches partitions of type
.Li freebsd-ufs
and
.Li freebsd-zfs
for
.Pa loader.efi .
The search begins with partitions on the device from which
.Pa boot1.efi
was loaded, and continues with other available partitions.
If both
.Li freebsd-ufs
and
.Li freebsd-zfs
partitions exist on the same device the
.Li freebsd-zfs
partition is preferred.
.Pa boot1.efi
then loads and executes
.Pa loader.efi .
.It
.Pa loader.efi
@ -112,6 +137,7 @@ typical non-default kernel (optional)
.El
.Sh SEE ALSO
.Xr vt 4 ,
.Xr boot.config 5 ,
.Xr msdosfs 5 ,
.Xr boot 8 ,
.Xr gpart 8 ,
@ -135,19 +161,3 @@ Foundation sponsored portions of the work.
EFI environment variables are not supported by
.Xr loader 8
or the kernel.
.Pp
.Pa boot1.efi
loads
.Pa loader.efi
from the first FreeBSD-UFS file system it locates, even if it is on a
different disk.
.Pp
.Pa boot1.efi
cannot load
.Pa loader.efi
from a
.Xr ZFS 8
file system.
As a result,
.Nm
does not support a typical root file system on ZFS configuration.

Some files were not shown because too many files have changed in this diff Show More