27 #ifndef BFELF_LOADER_H 28 #define BFELF_LOADER_H 36 #pragma GCC system_header 43 #define scast(a, b) (static_cast<a>(b)) 45 #define scast(a, b) ((a)(b)) 49 #define rcast(a, b) (reinterpret_cast<a>(b)) 51 #define rcast(a, b) ((a)(b)) 55 #define add(a, b, c) (reinterpret_cast<a>(reinterpret_cast<const char *>(b) + (c))) 57 #define add(a, b, c) ((a)((const char *)(b) + (c))) 72 #ifndef BFELF_MAX_NEEDED 73 #define BFELF_MAX_NEEDED (25) 76 #ifndef BFELF_MAX_SEGMENTS 77 #define BFELF_MAX_SEGMENTS (4) 95 typedef uint64_t bfelf64_addr;
96 typedef uint64_t bfelf64_off;
97 typedef uint16_t bfelf64_half;
98 typedef uint32_t bfelf64_word;
99 typedef int32_t bfelf64_sword;
100 typedef uint64_t bfelf64_xword;
101 typedef int64_t bfelf64_sxword;
111 static inline int64_t
112 private_error(
const char *header,
const char *msg,
const char *func,
int line, int64_t code)
114 ALERT(
"%s [%d] %s: %s\n", func, line, header, msg);
118 #define bfinvalid_argument(a) \ 119 private_error("invalid argument", a, __func__, __LINE__, BFELF_ERROR_INVALID_ARG); 121 #define bfinvalid_file(a) \ 122 private_error("invalid file", a, __func__, __LINE__, BFELF_ERROR_INVALID_FILE); 124 #define bfinvalid_index(a) \ 125 private_error("invalid index", a, __func__, __LINE__, BFELF_ERROR_INVALID_INDEX); 127 #define bfinvalid_signature(a) \ 128 private_error("invalid signature", a, __func__, __LINE__, BFELF_ERROR_INVALID_SIGNATURE); 130 #define bfunsupported_file(a) \ 131 private_error("unsupported elf file", a, __func__, __LINE__, BFELF_ERROR_UNSUPPORTED_FILE); 133 #define bfloader_full(a) \ 134 private_error("loader full", a, __func__, __LINE__, BFELF_ERROR_LOADER_FULL); 136 #define bfno_such_symbol(a) \ 137 private_error("no such symbol", a, __func__, __LINE__, BFELF_ERROR_NO_SUCH_SYMBOL); 139 #define bfunsupported_rel(a) \ 140 private_error("unsupported relocation", a, __func__, __LINE__, BFELF_ERROR_UNSUPPORTED_RELA); 150 static inline int64_t
151 private_strcmp(
const char *s1,
const char *s2)
153 while (*s1 && (*s1 == *s2))
235 bfelf64_xword num_load_instr;
238 bfelf64_xword num_loadable_segments;
239 const struct bfelf_phdr *loadable_segments[BFELF_MAX_SEGMENTS];
241 bfelf64_addr start_addr;
242 bfelf64_xword total_memsz;
244 bfelf64_xword num_needed;
245 bfelf64_xword needed[BFELF_MAX_NEEDED];
247 const struct bfelf_ehdr *ehdr;
248 const struct bfelf_phdr *phdrtab;
249 const struct bfelf_shdr *shdrtab;
254 const char *shstrtab;
256 bfelf64_word nbucket;
258 const bfelf64_word *bucket;
259 const bfelf64_word *chain;
260 const bfelf64_word *hash;
262 bfelf64_xword dynnum;
263 const struct bfelf_dyn *dyntab;
265 bfelf64_xword symnum;
266 const struct bfelf_sym *symtab;
268 bfelf64_xword relanum_dyn;
269 const struct bfelf_rela *relatab_dyn;
271 bfelf64_xword relanum_plt;
272 const struct bfelf_rela *relatab_plt;
277 bfelf64_addr init_array;
278 bfelf64_xword init_arraysz;
280 bfelf64_addr fini_array;
281 bfelf64_xword fini_arraysz;
284 bfelf64_xword eh_framesz;
286 bfelf64_xword flags_1;
287 bfelf64_xword stack_flags;
289 bfelf64_addr relaro_vaddr;
290 bfelf64_xword relaro_memsz;
309 #define bfei_mag0 scast(bfelf64_sword, 0) 310 #define bfei_mag1 scast(bfelf64_sword, 1) 311 #define bfei_mag2 scast(bfelf64_sword, 2) 312 #define bfei_mag3 scast(bfelf64_sword, 3) 313 #define bfei_class scast(bfelf64_sword, 4) 314 #define bfei_data scast(bfelf64_sword, 5) 315 #define bfei_version scast(bfelf64_sword, 6) 316 #define bfei_osabi scast(bfelf64_sword, 7) 317 #define bfei_abiversion scast(bfelf64_sword, 8) 318 #define bfei_pad scast(bfelf64_sword, 9) 319 #define bfei_nident scast(bfelf64_sword, 16) 331 #define bfelfclass32 scast(unsigned char, 1) 332 #define bfelfclass64 scast(unsigned char, 2) 344 #define bfelfdata2lsb scast(unsigned char, 1) 345 #define bfelfdata2msb scast(unsigned char, 2) 357 #define bfev_current scast(unsigned char, 1) 369 #define bfelfosabi_sysv scast(unsigned char, 0) 370 #define bfelfosabi_hpux scast(unsigned char, 1) 371 #define bfelfosabi_standalone scast(unsigned char, 255) 383 #define bfet_none scast(bfelf64_half, 0) 384 #define bfet_rel scast(bfelf64_half, 1) 385 #define bfet_exec scast(bfelf64_half, 2) 386 #define bfet_dyn scast(bfelf64_half, 3) 387 #define bfet_core scast(bfelf64_half, 4) 388 #define bfet_loos scast(bfelf64_half, 0xFE00) 389 #define bfet_hios scast(bfelf64_half, 0xFEFF) 390 #define bfet_loproc scast(bfelf64_half, 0xFF00) 391 #define bfet_hiproc scast(bfelf64_half, 0xFFFF) 403 #define bfem_none scast(bfelf64_half, 0) 404 #define bfem_m32 scast(bfelf64_half, 1) 405 #define bfem_sparc scast(bfelf64_half, 2) 406 #define bfem_386 scast(bfelf64_half, 3) 407 #define bfem_68k scast(bfelf64_half, 4) 408 #define bfem_88k scast(bfelf64_half, 5) 409 #define bfem_486 scast(bfelf64_half, 6) 410 #define bfem_860 scast(bfelf64_half, 7) 411 #define bfem_mips scast(bfelf64_half, 8) 412 #define bfem_mips_rs3_le scast(bfelf64_half, 10) 413 #define bfem_mips_rs4_be scast(bfelf64_half, 11) 414 #define bfem_parisc scast(bfelf64_half, 15) 415 #define bfem_sparc32plus scast(bfelf64_half, 18) 416 #define bfem_ppc scast(bfelf64_half, 20) 417 #define bfem_ppc64 scast(bfelf64_half, 21) 418 #define bfem_spu scast(bfelf64_half, 23) 419 #define bfem_arm scast(bfelf64_half, 40) 420 #define bfem_sh scast(bfelf64_half, 42) 421 #define bfem_sparcv9 scast(bfelf64_half, 43) 422 #define bfem_h8_300 scast(bfelf64_half, 46) 423 #define bfem_ia_64 scast(bfelf64_half, 50) 424 #define bfem_x86_64 scast(bfelf64_half, 62) 425 #define bfem_s390 scast(bfelf64_half, 22) 426 #define bfem_cris scast(bfelf64_half, 76) 427 #define bfem_v850 scast(bfelf64_half, 87) 428 #define bfem_m32r scast(bfelf64_half, 88) 429 #define bfem_mn10300 scast(bfelf64_half, 89) 430 #define bfem_openrisc scast(bfelf64_half, 92) 431 #define bfem_blackfin scast(bfelf64_half, 106) 432 #define bfem_altera_nios2 scast(bfelf64_half, 113) 433 #define bfem_ti_c6000 scast(bfelf64_half, 140) 434 #define bfem_aarch64 scast(bfelf64_half, 183) 435 #define bfem_frv scast(bfelf64_half, 0x5441) 436 #define bfem_avr32 scast(bfelf64_half, 0x18AD) 437 #define bfem_alpha scast(bfelf64_half, 0x9026) 438 #define bfem_cygnus_v850 scast(bfelf64_half, 0x9080) 439 #define bfem_cygnus_m32r scast(bfelf64_half, 0x9041) 440 #define bfem_s390_old scast(bfelf64_half, 0xA390) 441 #define bfem_cygnus_mn10300 scast(bfelf64_half, 0xBEEF) 458 unsigned char e_ident[bfei_nident];
460 bfelf64_half e_machine;
461 bfelf64_word e_version;
462 bfelf64_addr e_entry;
465 bfelf64_word e_flags;
466 bfelf64_half e_ehsize;
467 bfelf64_half e_phentsize;
468 bfelf64_half e_phnum;
469 bfelf64_half e_shentsize;
470 bfelf64_half e_shnum;
471 bfelf64_half e_shstrndx;
488 #define bfsht_null scast(bfelf64_word, 0) 489 #define bfsht_progbits scast(bfelf64_word, 1) 490 #define bfsht_symtab scast(bfelf64_word, 2) 491 #define bfsht_strtab scast(bfelf64_word, 3) 492 #define bfsht_rela scast(bfelf64_word, 4) 493 #define bfsht_hash scast(bfelf64_word, 5) 494 #define bfsht_dynamic scast(bfelf64_word, 6) 495 #define bfsht_note scast(bfelf64_word, 7) 496 #define bfsht_nobits scast(bfelf64_word, 8) 497 #define bfsht_rel scast(bfelf64_word, 9) 498 #define bfsht_shlib scast(bfelf64_word, 10) 499 #define bfsht_dynsym scast(bfelf64_word, 11) 500 #define bfsht_init_array scast(bfelf64_word, 14) 501 #define bfsht_fini_array scast(bfelf64_word, 15) 502 #define bfsht_loos scast(bfelf64_word, 0x60000000) 503 #define bfsht_hios scast(bfelf64_word, 0x6FFFFFFF) 504 #define bfsht_loproc scast(bfelf64_word, 0x70000000) 505 #define bfsht_x86_64_unwind scast(bfelf64_word, 0x70000001) 506 #define bfsht_hiproc scast(bfelf64_word, 0x7FFFFFFF) 518 #define bfshf_write scast(bfelf64_xword, 0x1) 519 #define bfshf_alloc scast(bfelf64_xword, 0x2) 520 #define bfshf_execinstr scast(bfelf64_xword, 0x4) 521 #define bfshf_maskos scast(bfelf64_xword, 0x0F000000) 522 #define bfshf_maskproc scast(bfelf64_xword, 0xF0000000) 523 #define bfshf_undocumneted scast(bfelf64_xword, 0x00000060) 525 #define bfshf_a (bfshf_alloc) 526 #define bfshf_wa (bfshf_write | bfshf_alloc) 527 #define bfshf_ai (bfshf_alloc | bfshf_write | bfshf_undocumneted) 545 bfelf64_word sh_name;
546 bfelf64_word sh_type;
547 bfelf64_xword sh_flags;
548 bfelf64_addr sh_addr;
549 bfelf64_off sh_offset;
550 bfelf64_xword sh_size;
551 bfelf64_word sh_link;
552 bfelf64_word sh_info;
553 bfelf64_xword sh_addralign;
554 bfelf64_xword sh_entsize;
571 #define bfdt_null scast(bfelf64_xword, 0) 572 #define bfdt_needed scast(bfelf64_xword, 1) 573 #define bfdt_pltrelsz scast(bfelf64_xword, 2) 574 #define bfdt_pltgot scast(bfelf64_xword, 3) 575 #define bfdt_hash scast(bfelf64_xword, 4) 576 #define bfdt_strtab scast(bfelf64_xword, 5) 577 #define bfdt_symtab scast(bfelf64_xword, 6) 578 #define bfdt_rela scast(bfelf64_xword, 7) 579 #define bfdt_relasz scast(bfelf64_xword, 8) 580 #define bfdt_relaent scast(bfelf64_xword, 9) 581 #define bfdt_strsz scast(bfelf64_xword, 10) 582 #define bfdt_syment scast(bfelf64_xword, 11) 583 #define bfdt_init scast(bfelf64_xword, 12) 584 #define bfdt_fini scast(bfelf64_xword, 13) 585 #define bfdt_soname scast(bfelf64_xword, 14) 586 #define bfdt_rpath scast(bfelf64_xword, 15) 587 #define bfdt_symbolic scast(bfelf64_xword, 16) 588 #define bfdt_rel scast(bfelf64_xword, 17) 589 #define bfdt_relsz scast(bfelf64_xword, 18) 590 #define bfdt_relent scast(bfelf64_xword, 19) 591 #define bfdt_pltrel scast(bfelf64_xword, 20) 592 #define bfdt_debug scast(bfelf64_xword, 21) 593 #define bfdt_textrel scast(bfelf64_xword, 22) 594 #define bfdt_jmprel scast(bfelf64_xword, 23) 595 #define bfdt_bind_now scast(bfelf64_xword, 24) 596 #define bfdt_init_array scast(bfelf64_xword, 25) 597 #define bfdt_fini_array scast(bfelf64_xword, 26) 598 #define bfdt_init_arraysz scast(bfelf64_xword, 27) 599 #define bfdt_fini_arraysz scast(bfelf64_xword, 28) 600 #define bfdt_loos scast(bfelf64_xword, 0x60000000) 601 #define bfdt_relacount scast(bfelf64_xword, 0x6ffffff9) 602 #define bfdt_relcount scast(bfelf64_xword, 0x6ffffffa) 603 #define bfdt_flags_1 scast(bfelf64_xword, 0x6ffffffb) 604 #define bfdt_hios scast(bfelf64_xword, 0x6FFFFFFF) 605 #define bfdt_loproc scast(bfelf64_xword, 0x70000000) 606 #define bfdt_hiproc scast(bfelf64_xword, 0x7FFFFFFF) 608 #define bfdf_1_now scast(bfelf64_xword, 0x00000001) 609 #define bfdf_1_global scast(bfelf64_xword, 0x00000002) 610 #define bfdf_1_group scast(bfelf64_xword, 0x00000004) 611 #define bfdf_1_nodelete scast(bfelf64_xword, 0x00000008) 612 #define bfdf_1_loadfltr scast(bfelf64_xword, 0x00000010) 613 #define bfdf_1_initfirst scast(bfelf64_xword, 0x00000020) 614 #define bfdf_1_noopen scast(bfelf64_xword, 0x00000040) 615 #define bfdf_1_origin scast(bfelf64_xword, 0x00000080) 616 #define bfdf_1_direct scast(bfelf64_xword, 0x00000100) 617 #define bfdf_1_trans scast(bfelf64_xword, 0x00000200) 618 #define bfdf_1_interpose scast(bfelf64_xword, 0x00000400) 619 #define bfdf_1_nodeflib scast(bfelf64_xword, 0x00000800) 620 #define bfdf_1_nodump scast(bfelf64_xword, 0x00001000) 621 #define bfdf_1_confalt scast(bfelf64_xword, 0x00002000) 622 #define bfdf_1_endfiltee scast(bfelf64_xword, 0x00004000) 623 #define bfdf_1_dispreldne scast(bfelf64_xword, 0x00008000) 624 #define bfdf_1_disprelpnd scast(bfelf64_xword, 0x00010000) 625 #define bfdf_1_nodirect scast(bfelf64_xword, 0x00020000) 626 #define bfdf_1_ignmuldef scast(bfelf64_xword, 0x00040000) 627 #define bfdf_1_noksyms scast(bfelf64_xword, 0x00080000) 628 #define bfdf_1_nohdr scast(bfelf64_xword, 0x00100000) 629 #define bfdf_1_edited scast(bfelf64_xword, 0x00200000) 630 #define bfdf_1_noreloc scast(bfelf64_xword, 0x00400000) 631 #define bfdf_1_symintpose scast(bfelf64_xword, 0x00800000) 632 #define bfdf_1_globaudit scast(bfelf64_xword, 0x01000000) 633 #define bfdf_1_singleton scast(bfelf64_xword, 0x02000000) 634 #define bfdf_1_pie scast(bfelf64_xword, 0x08000000) 653 bfelf64_sxword d_tag;
671 #define bfstb_local scast(unsigned char, 0) 672 #define bfstb_global scast(unsigned char, 1) 673 #define bfstb_weak scast(unsigned char, 2) 674 #define bfstb_loos scast(unsigned char, 10) 675 #define bfstb_hios scast(unsigned char, 12) 676 #define bfstb_loproc scast(unsigned char, 13) 677 #define bfstb_hiproc scast(unsigned char, 15) 689 #define bfstt_notype scast(unsigned char, 0) 690 #define bfstt_object scast(unsigned char, 1) 691 #define bfstt_func scast(unsigned char, 2) 692 #define bfstt_section scast(unsigned char, 3) 693 #define bfstt_file scast(unsigned char, 4) 694 #define bfstt_loos scast(unsigned char, 10) 695 #define bfstt_hios scast(unsigned char, 12) 696 #define bfstt_loproc scast(unsigned char, 13) 697 #define bfstt_hiproc scast(unsigned char, 15) 709 #define BFELF_SYM_BIND(x) ((x) >> 4) 710 #define BFELF_SYM_TYPE(x) ((x)&0xF) 736 bfelf64_word st_name;
737 unsigned char st_info;
738 unsigned char st_other;
739 bfelf64_half st_shndx;
740 bfelf64_addr st_value;
741 bfelf64_xword st_size;
758 #define BFR_X86_64_64 scast(bfelf64_xword, 1) 759 #define BFR_X86_64_GLOB_DAT scast(bfelf64_xword, 6) 760 #define BFR_X86_64_JUMP_SLOT scast(bfelf64_xword, 7) 761 #define BFR_X86_64_RELATIVE scast(bfelf64_xword, 8) 775 bfelf64_addr r_offset;
776 bfelf64_xword r_info;
791 bfelf64_addr r_offset;
792 bfelf64_xword r_info;
793 bfelf64_sxword r_addend;
806 #define BFELF_REL_SYM(i) ((i) >> 32) 807 #define BFELF_REL_TYPE(i) ((i)&0xFFFFFFFFL) 823 #define bfpt_null scast(bfelf64_word, 0) 824 #define bfpt_load scast(bfelf64_word, 1) 825 #define bfpt_dynamic scast(bfelf64_word, 2) 826 #define bfpt_interp scast(bfelf64_word, 3) 827 #define bfpt_note scast(bfelf64_word, 4) 828 #define bfpt_shlib scast(bfelf64_word, 5) 829 #define bfpt_phdr scast(bfelf64_word, 6) 830 #define bfpt_loos scast(bfelf64_word, 0x60000000) 831 #define bfpt_gnu_eh_frame scast(bfelf64_word, 0x6474e550) 832 #define bfpt_gnu_stack scast(bfelf64_word, 0x6474e551) 833 #define bfpt_gnu_relro scast(bfelf64_word, 0x6474e552) 834 #define bfpt_hios scast(bfelf64_word, 0x6FFFFFFF) 835 #define bfpt_loproc scast(bfelf64_word, 0x70000000) 836 #define bfpt_hiproc scast(bfelf64_word, 0x7FFFFFFF) 848 #define bfpf_x scast(bfelf64_xword, 0x1) 849 #define bfpf_w scast(bfelf64_xword, 0x2) 850 #define bfpf_r scast(bfelf64_xword, 0x4) 851 #define bfpf_maskos scast(bfelf64_xword, 0x00FF0000) 852 #define bfpf_maskproc scast(bfelf64_xword, 0xFF000000) 873 bfelf64_word p_flags;
874 bfelf64_off p_offset;
875 bfelf64_addr p_vaddr;
876 bfelf64_addr p_paddr;
877 bfelf64_xword p_filesz;
878 bfelf64_xword p_memsz;
879 bfelf64_xword p_align;
897 struct bfelf_loader_t
900 bfelf64_word relocated;
912 static inline unsigned long 913 private_hash(
const char *
name)
915 unsigned long h = 0, g;
920 unsigned char uc = scast(
unsigned char, c);
931 if ((g = (h & 0xf0000000)))
942 static inline int64_t
943 private_get_sym_by_hash(
struct bfelf_file_t *ef,
const char *name,
const struct bfelf_sym **sym)
947 unsigned long x = private_hash(name);
949 i = ef->bucket[x % ef->nbucket];
950 while (i > STN_UNDEF && i < ef->nchain)
954 *sym = &(ef->symtab[i]);
955 str = &(ef->strtab[(*sym)->st_name]);
957 ret = private_strcmp(name, str);
970 static inline int64_t
971 private_get_sym_by_name(
struct bfelf_file_t *ef,
const char *name,
const struct bfelf_sym **sym)
978 return private_get_sym_by_hash(ef, name, sym);
981 for (i = 0; i < ef->symnum; i++)
985 *sym = &(ef->symtab[i]);
986 str = &(ef->strtab[(*sym)->st_name]);
988 ret = private_strcmp(name, str);
1000 static inline int64_t
1001 private_get_sym_global(
1002 struct bfelf_loader_t *loader,
1004 struct bfelf_file_t **ef_found,
1005 const struct bfelf_sym **sym)
1009 const struct bfelf_sym *found_sym = 0;
1010 struct bfelf_file_t *ef_ignore = *ef_found;
1015 for (i = 0; i < loader->num; i++)
1017 if (loader->efs[i] == ef_ignore)
1022 ret = private_get_sym_by_name(loader->efs[i], name, &found_sym);
1028 if (found_sym->st_value == 0)
1032 *ef_found = loader->efs[i];
1034 if (BFELF_SYM_BIND(found_sym->st_info) == bfstb_weak)
1047 return bfno_such_symbol(name);
1058 static inline int64_t
1059 private_relocate_symbol(
1060 struct bfelf_loader_t *loader,
struct bfelf_file_t *ef,
const struct bfelf_rela *rela)
1063 const char *
str = 0;
1064 const struct bfelf_sym *found_sym = 0;
1065 struct bfelf_file_t *found_ef = ef;
1066 bfelf64_addr *ptr = rcast(bfelf64_addr *, ef->exec_addr + rela->r_offset - ef->start_addr);
1068 if (BFELF_REL_TYPE(rela->r_info) == BFR_X86_64_RELATIVE)
1070 *ptr = rcast(bfelf64_addr, ef->exec_virt + rela->r_addend);
1074 found_sym = &(ef->symtab[BFELF_REL_SYM(rela->r_info)]);
1076 if (BFELF_SYM_BIND(found_sym->st_info) == bfstb_weak)
1081 if (found_sym->st_value == 0 || found_ef == 0)
1083 str = &(ef->strtab[found_sym->st_name]);
1085 ret = private_get_sym_global(loader, str, &found_ef, &found_sym);
1092 *ptr = rcast(bfelf64_addr, found_ef->exec_virt + found_sym->st_value);
1094 switch (BFELF_REL_TYPE(rela->r_info))
1097 *ptr += scast(bfelf64_addr, rela->r_addend);
1100 case BFR_X86_64_GLOB_DAT:
1101 case BFR_X86_64_JUMP_SLOT:
1105 return bfunsupported_rel(str);
1111 static inline int64_t
1112 private_relocate_symbols(
struct bfelf_loader_t *loader,
struct bfelf_file_t *ef)
1117 for (i = 0; i < ef->relanum_dyn; i++)
1119 const struct bfelf_rela *rela = &(ef->relatab_dyn[i]);
1121 ret = private_relocate_symbol(loader, ef, rela);
1128 for (i = 0; i < ef->relanum_plt; i++)
1130 const struct bfelf_rela *rela = &(ef->relatab_plt[i]);
1132 ret = private_relocate_symbol(loader, ef, rela);
1150 static inline int64_t
1151 private_check_signature(
struct bfelf_file_t *ef)
1153 if (ef->ehdr->e_ident[bfei_mag0] != 0x7F)
1155 return bfinvalid_signature(
"magic #0 has unexpected value");
1158 if (ef->ehdr->e_ident[bfei_mag1] !=
'E')
1160 return bfinvalid_signature(
"magic #1 has unexpected value");
1163 if (ef->ehdr->e_ident[bfei_mag2] !=
'L')
1165 return bfinvalid_signature(
"magic #2 has unexpected value");
1168 if (ef->ehdr->e_ident[bfei_mag3] !=
'F')
1170 return bfinvalid_signature(
"magic #3 has unexpected value");
1176 static inline int64_t
1177 private_check_support(
struct bfelf_file_t *ef)
1179 if (ef->ehdr->e_ident[bfei_class] != bfelfclass64)
1181 return bfunsupported_file(
"file is not 64bit");
1184 if (ef->ehdr->e_ident[bfei_data] != bfelfdata2lsb)
1186 return bfunsupported_file(
"file is not little endian");
1189 if (ef->ehdr->e_ident[bfei_version] != bfev_current)
1191 return bfunsupported_file(
"unsupported version");
1194 if (ef->ehdr->e_ident[bfei_osabi] != bfelfosabi_sysv)
1196 return bfunsupported_file(
"file does not use the system v abi");
1199 if (ef->ehdr->e_ident[bfei_abiversion] != 0)
1201 return bfunsupported_file(
"unsupported abi version");
1204 if (ef->ehdr->e_type != bfet_dyn && ef->ehdr->e_type != bfet_exec)
1206 return bfunsupported_file(
"file must be an executable or shared library");
1209 if (ef->ehdr->e_machine != bfem_x86_64)
1211 return bfunsupported_file(
"file must be compiled for x86_64");
1214 if (ef->ehdr->e_version != bfev_current)
1216 return bfunsupported_file(
"unsupported version");
1219 if (ef->ehdr->e_flags != 0)
1221 return bfunsupported_file(
"unsupported flags");
1228 private_process_segments(
struct bfelf_file_t *ef)
1230 bfelf64_xword i = 0;
1232 for (i = 0; i < ef->ehdr->e_phnum; i++)
1234 const struct bfelf_phdr *phdr = &(ef->phdrtab[i]);
1236 switch (phdr->p_type)
1240 if (ef->num_loadable_segments < BFELF_MAX_SEGMENTS)
1242 ef->total_memsz = phdr->p_vaddr + phdr->p_memsz;
1243 ef->loadable_segments[ef->num_loadable_segments++] = phdr;
1249 ef->dynoff = phdr->p_offset;
1250 ef->dynnum = phdr->p_filesz /
sizeof(
struct bfelf_dyn);
1253 case bfpt_gnu_stack:
1254 ef->stack_flags = phdr->p_flags;
1257 case bfpt_gnu_relro:
1258 ef->relaro_vaddr = phdr->p_vaddr;
1259 ef->relaro_memsz = phdr->p_memsz;
1264 if (ef->num_loadable_segments > 0)
1266 ef->start_addr = ef->loadable_segments[0]->p_vaddr;
1267 ef->total_memsz -= ef->start_addr;
1270 for (i = 0; i < ef->num_loadable_segments; i++)
1272 const struct bfelf_phdr *phdr = ef->loadable_segments[i];
1274 ef->load_instr[i].perm = phdr->p_flags;
1275 ef->load_instr[i].mem_offset = phdr->p_vaddr - ef->start_addr;
1276 ef->load_instr[i].file_offset = phdr->p_offset;
1277 ef->load_instr[i].memsz = phdr->p_memsz;
1278 ef->load_instr[i].filesz = phdr->p_filesz;
1279 ef->load_instr[i].virt_addr = phdr->p_vaddr;
1281 ef->num_load_instr++;
1286 private_process_dynamic_section(
struct bfelf_file_t *ef)
1288 bfelf64_xword i = 0;
1290 if (ef->dynnum == 0 || ef->dynoff == 0)
1294 ef->dyntab = rcast(
const struct bfelf_dyn *, ef->file + ef->dynoff);
1296 for (i = 0; i < ef->dynnum; i++)
1298 const struct bfelf_dyn *dyn = &(ef->dyntab[i]);
1307 if (ef->num_needed < BFELF_MAX_NEEDED)
1309 ef->needed[ef->num_needed++] = dyn->d_val;
1315 ef->relanum_plt = dyn->d_val /
sizeof(
struct bfelf_rela);
1319 ef->hash = rcast(bfelf64_word *, dyn->d_val);
1323 ef->strtab = rcast(
char *, dyn->d_val);
1327 ef->symtab = rcast(
struct bfelf_sym *, dyn->d_val);
1331 ef->relatab_dyn = rcast(
struct bfelf_rela *, dyn->d_val);
1335 ef->relanum_dyn = dyn->d_val /
sizeof(
struct bfelf_rela);
1339 ef->init = dyn->d_val;
1343 ef->fini = dyn->d_val;
1347 ef->relatab_plt = rcast(
struct bfelf_rela *, dyn->d_val);
1350 case bfdt_init_array:
1351 ef->init_array = dyn->d_val;
1354 case bfdt_fini_array:
1355 ef->fini_array = dyn->d_val;
1358 case bfdt_init_arraysz:
1359 ef->init_arraysz = dyn->d_val;
1362 case bfdt_fini_arraysz:
1363 ef->fini_arraysz = dyn->d_val;
1367 ef->flags_1 = dyn->d_val;
1396 static inline int64_t
1397 bfelf_file_init(
const char *
file, uint64_t filesz,
struct bfelf_file_t *ef)
1404 return bfinvalid_argument(
"file == NULL");
1409 return bfinvalid_argument(
"ef == NULL");
1412 if (filesz == 0 || filesz <
sizeof(
struct bfelf_ehdr))
1414 return bfinvalid_argument(
"filesz invalid");
1417 for (i = 0; i <
sizeof(
struct bfelf_file_t); i++)
1419 rcast(
char *, ef)[i] = 0;
1423 ef->filesz = filesz;
1425 ef->ehdr = rcast(
const struct bfelf_ehdr *, file);
1426 ef->phdrtab = rcast(
const struct bfelf_phdr *, file + ef->ehdr->e_phoff);
1427 ef->shdrtab = rcast(
const struct bfelf_shdr *, file + ef->ehdr->e_shoff);
1429 ret = private_check_signature(ef);
1435 ret = private_check_support(ef);
1441 private_process_segments(ef);
1442 private_process_dynamic_section(ef);
1444 ef->entry = ef->ehdr->e_entry;
1445 ef->shstrtab = rcast(
const char *, file + ef->shdrtab[ef->ehdr->e_shstrndx].sh_offset);
1464 for (i = 0; i < ef->ehdr->e_shnum; i++)
1466 const struct bfelf_shdr *shdr = &(ef->shdrtab[i]);
1467 const char *name = &ef->shstrtab[shdr->sh_name];
1471 ef->eh_frame = shdr->sh_addr;
1472 ef->eh_framesz = shdr->sh_size;
1478 ef->init_array = shdr->sh_addr;
1479 ef->init_arraysz = shdr->sh_size;
1485 ef->fini_array = shdr->sh_addr;
1486 ef->fini_arraysz = shdr->sh_size;
1495 for (i = 0; i <
sizeof(
struct bfelf_file_t); i++)
1497 rcast(
char *, ef)[i] = 0;
1517 static inline int64_t
1518 bfelf_file_get_num_load_instrs(
struct bfelf_file_t *ef)
1522 return bfinvalid_argument(
"ef == NULL");
1525 return scast(int64_t, ef->num_load_instr);
1544 static inline int64_t
1549 return bfinvalid_argument(
"ef == NULL");
1554 return bfinvalid_argument(
"phdr == NULL");
1557 if (index >= ef->num_load_instr)
1559 return bfinvalid_index(
"index >= number of load instructions");
1562 *instr = &(ef->load_instr[
index]);
1582 static inline int64_t
1583 bfelf_file_get_section_info(
struct bfelf_file_t *ef,
struct section_info_t *info)
1589 return bfinvalid_argument(
"ef == NULL");
1594 return bfinvalid_argument(
"info == NULL");
1599 rcast(
char *, info)[i] = 0;
1604 info->
init_addr = ef->init + ef->exec_virt;
1609 info->
fini_addr = ef->fini + ef->exec_virt;
1612 if (ef->init_array != 0)
1618 if (ef->fini_array != 0)
1624 if (ef->eh_frame != 0)
1646 static inline int64_t
1647 bfelf_file_get_entry(
struct bfelf_file_t *ef,
void **
addr)
1651 return bfinvalid_argument(
"ef == NULL");
1656 return bfinvalid_argument(
"addr == NULL");
1659 *addr = rcast(
void *, ef->entry + ef->exec_virt);
1676 static inline int64_t
1677 bfelf_file_get_stack_perm(
struct bfelf_file_t *ef, bfelf64_xword *perm)
1681 return bfinvalid_argument(
"ef == NULL");
1686 return bfinvalid_argument(
"perm == NULL");
1689 *perm = ef->stack_flags;
1709 static inline int64_t
1710 bfelf_file_get_relro(
struct bfelf_file_t *ef, bfelf64_addr *addr, bfelf64_xword *
size)
1714 return bfinvalid_argument(
"ef == NULL");
1719 return bfinvalid_argument(
"addr == NULL");
1724 return bfinvalid_argument(
"size == NULL");
1727 *addr = ef->relaro_vaddr + rcast(bfelf64_addr, ef->exec_virt);
1728 *size = ef->relaro_memsz;
1744 static inline int64_t
1745 bfelf_file_get_num_needed(
struct bfelf_file_t *ef)
1749 return bfinvalid_argument(
"ef == NULL");
1752 return scast(int64_t, ef->num_needed);
1771 static inline int64_t
1772 bfelf_file_get_needed(
struct bfelf_file_t *ef, uint64_t index,
const char **needed)
1776 return bfinvalid_argument(
"ef == NULL");
1781 return bfinvalid_argument(
"needed == NULL");
1784 if (index >= ef->num_needed)
1786 return bfinvalid_index(
"index >= number of needed");
1789 *needed = &(ef->strtab[ef->needed[
index]]);
1805 static inline int64_t
1806 bfelf_file_get_total_size(
struct bfelf_file_t *ef)
1810 return bfinvalid_argument(
"ef == NULL");
1813 return scast(int64_t, ef->total_memsz);
1828 static inline int64_t
1829 bfelf_file_get_pic_pie(
struct bfelf_file_t *ef)
1833 return bfinvalid_argument(
"ef == NULL");
1836 return ef->start_addr == 0 ? 1 : 0;
1861 static inline int64_t
1863 struct bfelf_loader_t *loader,
struct bfelf_file_t *ef,
char *exec_addr,
char *exec_virt)
1869 return bfinvalid_argument(
"loader == NULL");
1874 return bfinvalid_argument(
"ef == NULL");
1879 return bfinvalid_argument(
"exec_addr == NULL");
1884 return bfloader_full(
"increase MAX_NUM_MODULES");
1887 if (ef->added++ != 0)
1889 return bfinvalid_argument(
"ef already added");
1892 ef->exec_addr = exec_addr;
1894 if (ef->start_addr == 0)
1896 ef->exec_virt = exec_virt;
1899 start = rcast(bfelf64_addr, ef->exec_addr - ef->start_addr);
1901 ef->hash = add(
const bfelf64_word *, ef->hash, start);
1902 ef->strtab = add(
const char *, ef->strtab, start);
1903 ef->symtab = add(
const struct bfelf_sym *, ef->symtab, start);
1904 ef->relatab_dyn = add(
const struct bfelf_rela *, ef->relatab_dyn, start);
1905 ef->relatab_plt = add(
const struct bfelf_rela *, ef->relatab_plt, start);
1907 ef->nbucket = ef->hash[0];
1908 ef->nchain = ef->hash[1];
1909 ef->bucket = &(ef->hash[2]);
1910 ef->chain = &(ef->hash[2 + ef->nbucket]);
1917 ef->symnum = (rcast(bfelf64_addr, ef->strtab) - rcast(bfelf64_addr, ef->symtab)) /
1918 sizeof(
struct bfelf_sym);
1920 loader->efs[loader->num++] = ef;
1937 static inline int64_t
1938 bfelf_loader_relocate(
struct bfelf_loader_t *loader)
1945 return bfinvalid_argument(
"loader == NULL");
1948 if (loader->relocated == 1)
1953 for (i = 0; i < loader->num; i++)
1955 ret = private_relocate_symbols(loader, loader->efs[i]);
1962 loader->relocated = 1;
1985 static inline int64_t
1986 bfelf_loader_resolve_symbol(
struct bfelf_loader_t *loader,
const char *name,
void **addr)
1990 struct bfelf_file_t *found_ef = 0;
1991 const struct bfelf_sym *found_sym = 0;
1995 return bfinvalid_argument(
"loader == NULL");
2000 return bfinvalid_argument(
"name == NULL");
2005 return bfinvalid_argument(
"addr == NULL");
2008 ret = private_get_sym_global(loader, name, &found_ef, &found_sym);
2014 *addr = found_ef->exec_virt + found_sym->st_value;
#define BFELF_ERROR_NO_SUCH_SYMBOL
#define BFELF_ERROR_MISMATCH
constexpr const auto size
auto index(const T virt, const F from)
constexpr const auto addr
constexpr const auto name