@@ -23,7 +23,6 @@ namespace LIEF {
23
23
namespace ELF {
24
24
template <typename ELF_T>
25
25
void Parser::parse_binary (void ) {
26
- using Elf_Addr = typename ELF_T::Elf_Addr;
27
26
using Elf_Off = typename ELF_T::Elf_Off;
28
27
29
28
VLOG (VDEBUG) << " Start parsing" ;
@@ -481,99 +480,175 @@ uint32_t Parser::get_numberof_dynamic_symbols(DYNSYM_COUNT_METHODS mtd) const {
481
480
case DYNSYM_COUNT_METHODS::COUNT_AUTO:
482
481
default :
483
482
{
484
- uint32_t nb_dynsym = 0 ;
485
-
486
- nb_dynsym = this ->get_numberof_dynamic_symbols <ELF_T>(DYNSYM_COUNT_METHODS::COUNT_HASH);
483
+ uint32_t nb_dynsym, nb_dynsym_tmp = 0 ;
487
484
488
- if (nb_dynsym > 0 ) {
489
- return nb_dynsym;
490
- }
485
+ nb_dynsym = this ->get_numberof_dynamic_symbols <ELF_T>(DYNSYM_COUNT_METHODS::COUNT_RELOCATIONS);
491
486
492
- nb_dynsym = this ->get_numberof_dynamic_symbols <ELF_T>(DYNSYM_COUNT_METHODS::COUNT_SECTION);
487
+ nb_dynsym_tmp = this ->get_numberof_dynamic_symbols <ELF_T>(DYNSYM_COUNT_METHODS::COUNT_SECTION);
493
488
494
- if (nb_dynsym > 0 ) {
495
- return nb_dynsym;
489
+ if (nb_dynsym_tmp < Parser::NB_MAX_SYMBOLS and
490
+ nb_dynsym_tmp > nb_dynsym and
491
+ (nb_dynsym_tmp - nb_dynsym) < Parser::DELTA_NB_SYMBOLS) {
492
+ nb_dynsym = nb_dynsym_tmp;
496
493
}
497
494
495
+ nb_dynsym_tmp = this ->get_numberof_dynamic_symbols <ELF_T>(DYNSYM_COUNT_METHODS::COUNT_HASH);
498
496
499
- nb_dynsym = this -> get_numberof_dynamic_symbols <ELF_T>(DYNSYM_COUNT_METHODS::COUNT_RELOCATIONS);
500
-
501
- if ( nb_dynsym > 0 ) {
502
- return nb_dynsym;
497
+ if (nb_dynsym_tmp < Parser::NB_MAX_SYMBOLS and
498
+ nb_dynsym_tmp > nb_dynsym and
499
+ (nb_dynsym_tmp - nb_dynsym) < Parser::DELTA_NB_SYMBOLS ) {
500
+ nb_dynsym = nb_dynsym_tmp ;
503
501
}
504
502
505
- return 0 ;
503
+ return nb_dynsym ;
506
504
}
507
505
}
508
506
}
509
507
510
508
template <typename ELF_T>
511
509
uint32_t Parser::nb_dynsym_relocations (void ) const {
512
- using Elf_Rela = typename ELF_T::Elf_Rela;
513
- using Elf_Rel = typename ELF_T::Elf_Rel;
510
+ uint32_t nb_symbols = 0 ;
514
511
515
- using Elf_Addr = typename ELF_T::Elf_Addr;
516
- using Elf_Off = typename ELF_T::Elf_Off;
512
+ // Dynamic Relocations
513
+ // ===================
517
514
518
- auto && it_pltgot_relocations_size = std::find_if (
515
+ // RELA
516
+ // ----
517
+ auto && it_dynamic_relocations = std::find_if (
519
518
std::begin (this ->binary_ ->dynamic_entries_ ),
520
519
std::end (this ->binary_ ->dynamic_entries_ ),
521
520
[] (const DynamicEntry* entry) {
522
- return entry != nullptr and entry->tag () == DYNAMIC_TAGS::DT_PLTRELSZ ;
521
+ return entry != nullptr and entry->tag () == DYNAMIC_TAGS::DT_RELA ;
523
522
});
524
523
525
- auto && it_pltgot_relocations_type = std::find_if (
524
+ auto && it_dynamic_relocations_size = std::find_if (
526
525
std::begin (this ->binary_ ->dynamic_entries_ ),
527
526
std::end (this ->binary_ ->dynamic_entries_ ),
528
527
[] (const DynamicEntry* entry) {
529
- return entry != nullptr and entry->tag () == DYNAMIC_TAGS::DT_PLTREL ;
528
+ return entry != nullptr and entry->tag () == DYNAMIC_TAGS::DT_RELASZ ;
530
529
});
531
530
532
- if (it_pltgot_relocations_size == std::end (this ->binary_ ->dynamic_entries_ )) {
533
- return 0 ;
531
+ if (it_dynamic_relocations != std::end (this ->binary_ ->dynamic_entries_ ) and
532
+ it_dynamic_relocations_size != std::end (this ->binary_ ->dynamic_entries_ )) {
533
+ const uint64_t virtual_address = (*it_dynamic_relocations)->value ();
534
+ const uint64_t size = (*it_dynamic_relocations_size)->value ();
535
+ try {
536
+ uint64_t offset = this ->binary_ ->virtual_address_to_offset (virtual_address);
537
+ nb_symbols = std::max (nb_symbols, this ->max_relocation_index <ELF_T, typename ELF_T::Elf_Rela>(offset, size));
538
+ } catch (const LIEF::exception &) {
539
+ }
534
540
}
535
541
536
- DYNAMIC_TAGS type;
537
- const Elf_Off size = (*it_pltgot_relocations_size)->value ();
538
542
539
- if (it_pltgot_relocations_type != std::end (this ->binary_ ->dynamic_entries_ )) {
540
- type = static_cast <DYNAMIC_TAGS>((*it_pltgot_relocations_type)->value ());
541
- } else {
542
- if (std::is_same<ELF_T, ELF64>::value) {
543
- type = DYNAMIC_TAGS::DT_RELA;
544
- } else {
545
- type = DYNAMIC_TAGS::DT_REL;
543
+ // REL
544
+ // ---
545
+ it_dynamic_relocations = std::find_if (
546
+ std::begin (this ->binary_ ->dynamic_entries_ ),
547
+ std::end (this ->binary_ ->dynamic_entries_ ),
548
+ [] (const DynamicEntry* entry) {
549
+ return entry != nullptr and entry->tag () == DYNAMIC_TAGS::DT_REL;
550
+ });
551
+
552
+ it_dynamic_relocations_size = std::find_if (
553
+ std::begin (this ->binary_ ->dynamic_entries_ ),
554
+ std::end (this ->binary_ ->dynamic_entries_ ),
555
+ [] (const DynamicEntry* entry) {
556
+ return entry != nullptr and entry->tag () == DYNAMIC_TAGS::DT_RELSZ;
557
+ });
558
+
559
+ if (it_dynamic_relocations != std::end (this ->binary_ ->dynamic_entries_ ) and
560
+ it_dynamic_relocations_size != std::end (this ->binary_ ->dynamic_entries_ )) {
561
+ const uint64_t virtual_address = (*it_dynamic_relocations)->value ();
562
+ const uint64_t size = (*it_dynamic_relocations_size)->value ();
563
+ try {
564
+ const uint64_t offset = this ->binary_ ->virtual_address_to_offset (virtual_address);
565
+ nb_symbols = std::max (nb_symbols, this ->max_relocation_index <ELF_T, typename ELF_T::Elf_Rel>(offset, size));
566
+ } catch (const LIEF::exception &) {
567
+
546
568
}
569
+
547
570
}
548
571
549
- switch (type) {
550
- case DYNAMIC_TAGS::DT_RELA:
551
- {
552
- return static_cast <uint32_t >(size / sizeof (Elf_Rela));
553
- break ;
554
- }
572
+ // Parse PLT/GOT Relocations
573
+ // ==========================
574
+ auto && it_pltgot_relocations = std::find_if (
575
+ std::begin (this ->binary_ ->dynamic_entries_ ),
576
+ std::end (this ->binary_ ->dynamic_entries_ ),
577
+ [] (const DynamicEntry* entry) {
578
+ return entry != nullptr and entry->tag () == DYNAMIC_TAGS::DT_JMPREL;
579
+ });
555
580
556
- case DYNAMIC_TAGS::DT_REL:
557
- {
558
- return static_cast <uint32_t >(size / sizeof (Elf_Rel));
559
- break ;
581
+ auto && it_pltgot_relocations_size = std::find_if (
582
+ std::begin (this ->binary_ ->dynamic_entries_ ),
583
+ std::end (this ->binary_ ->dynamic_entries_ ),
584
+ [] (const DynamicEntry* entry) {
585
+ return entry != nullptr and entry->tag () == DYNAMIC_TAGS::DT_PLTRELSZ;
586
+ });
587
+
588
+ auto && it_pltgot_relocations_type = std::find_if (
589
+ std::begin (this ->binary_ ->dynamic_entries_ ),
590
+ std::end (this ->binary_ ->dynamic_entries_ ),
591
+ [] (const DynamicEntry* entry) {
592
+ return entry != nullptr and entry->tag () == DYNAMIC_TAGS::DT_PLTREL;
593
+ });
594
+
595
+ if (it_pltgot_relocations != std::end (this ->binary_ ->dynamic_entries_ ) and
596
+ it_pltgot_relocations_size != std::end (this ->binary_ ->dynamic_entries_ )) {
597
+ const uint64_t virtual_address = (*it_pltgot_relocations)->value ();
598
+ const uint64_t size = (*it_pltgot_relocations_size)->value ();
599
+ DYNAMIC_TAGS type;
600
+ if (it_pltgot_relocations_type != std::end (this ->binary_ ->dynamic_entries_ )) {
601
+ type = static_cast <DYNAMIC_TAGS>((*it_pltgot_relocations_type)->value ());
602
+ } else {
603
+ // Try to guess: We assume that on ELF64 -> DT_RELA and on ELF32 -> DT_REL
604
+ if (std::is_same<ELF_T, ELF64>::value) {
605
+ type = DYNAMIC_TAGS::DT_RELA;
606
+ } else {
607
+ type = DYNAMIC_TAGS::DT_REL;
560
608
}
609
+ }
561
610
562
- default :
563
- {
564
- return 0 ;
611
+ try {
612
+ const uint64_t offset = this ->binary_ ->virtual_address_to_offset (virtual_address);
613
+ if (type == DYNAMIC_TAGS::DT_RELA) {
614
+ nb_symbols = std::max (nb_symbols, this ->max_relocation_index <ELF_T, typename ELF_T::Elf_Rela>(offset, size));
615
+ } else {
616
+ nb_symbols = std::max (nb_symbols, this ->max_relocation_index <ELF_T, typename ELF_T::Elf_Rel>(offset, size));
565
617
}
618
+ } catch (const LIEF::exception & e) {
619
+ LOG (WARNING) << e.what ();
620
+
621
+ }
566
622
}
567
- return 0 ;
623
+
624
+ return nb_symbols;
568
625
}
569
626
627
+ template <typename ELF_T, typename REL_T>
628
+ uint32_t Parser::max_relocation_index (uint64_t relocations_offset, uint64_t size) const {
629
+ static_assert (std::is_same<REL_T, typename ELF_T::Elf_Rel>::value or
630
+ std::is_same<REL_T, typename ELF_T::Elf_Rela>::value, " REL_T must be Elf_Rel or Elf_Rela" );
631
+
632
+ const uint8_t shift = std::is_same<ELF_T, ELF32>::value ? 8 : 32 ;
633
+
634
+ const uint32_t nb_entries = static_cast <uint32_t >(size / sizeof (REL_T));
635
+
636
+ const REL_T* reloc_entry = reinterpret_cast <const REL_T*>(
637
+ this ->stream_ ->read (relocations_offset, nb_entries * sizeof (REL_T)));
638
+ uint32_t idx = 0 ;
639
+ for (uint32_t i = 0 ; i < nb_entries; ++i) {
640
+ idx = std::max (idx, static_cast <uint32_t >(reloc_entry->r_info >> shift));
641
+ reloc_entry++;
642
+ }
643
+ return (idx + 1 );
644
+ } // max_relocation_index
645
+
646
+
570
647
571
648
template <typename ELF_T>
572
649
uint32_t Parser::nb_dynsym_section (void ) const {
573
650
using Elf_Sym = typename ELF_T::Elf_Sym;
574
-
575
- using Elf_Addr = typename ELF_T::Elf_Addr;
576
- using Elf_Off = typename ELF_T::Elf_Off;
651
+ using Elf_Off = typename ELF_T::Elf_Off;
577
652
578
653
auto && it_dynamic_section = std::find_if (
579
654
std::begin (this ->binary_ ->sections_ ),
@@ -609,7 +684,6 @@ uint32_t Parser::nb_dynsym_hash(void) const {
609
684
610
685
template <typename ELF_T>
611
686
uint32_t Parser::nb_dynsym_sysv_hash (void ) const {
612
- using Elf_Addr = typename ELF_T::Elf_Addr;
613
687
using Elf_Off = typename ELF_T::Elf_Off;
614
688
615
689
const DynamicEntry& dyn_hash = this ->binary_ ->get (DYNAMIC_TAGS::DT_HASH);
@@ -633,7 +707,6 @@ template<typename ELF_T>
633
707
uint32_t Parser::nb_dynsym_gnu_hash (void ) const {
634
708
using uint__ = typename ELF_T::uint ;
635
709
636
- using Elf_Addr = typename ELF_T::Elf_Addr;
637
710
using Elf_Off = typename ELF_T::Elf_Off;
638
711
639
712
const DynamicEntry& dyn_hash = this ->binary_ ->get (DYNAMIC_TAGS::DT_GNU_HASH);
@@ -722,7 +795,6 @@ template<typename ELF_T>
722
795
void Parser::parse_sections (void ) {
723
796
using Elf_Shdr = typename ELF_T::Elf_Shdr;
724
797
725
- using Elf_Addr = typename ELF_T::Elf_Addr;
726
798
using Elf_Off = typename ELF_T::Elf_Off;
727
799
VLOG (VDEBUG) << " [+] Parsing Section" ;
728
800
@@ -780,7 +852,6 @@ template<typename ELF_T>
780
852
void Parser::parse_segments (void ) {
781
853
using Elf_Phdr = typename ELF_T::Elf_Phdr;
782
854
783
- using Elf_Addr = typename ELF_T::Elf_Addr;
784
855
using Elf_Off = typename ELF_T::Elf_Off;
785
856
786
857
VLOG (VDEBUG) << " [+] Parse Segments" ;
@@ -813,7 +884,7 @@ void Parser::parse_segments(void) {
813
884
this ->stream_ ->read (offset_to_content, size));
814
885
segment->content ({content, content + size});
815
886
if (segment->type () == SEGMENT_TYPES::PT_INTERP) {
816
- this ->binary_ ->interpreter_ = this ->stream_ ->read_string (offset_to_content);
887
+ this ->binary_ ->interpreter_ = this ->stream_ ->read_string (offset_to_content, segment-> physical_size () );
817
888
}
818
889
819
890
} catch (const LIEF::read_out_of_bound&) {
@@ -901,7 +972,6 @@ template<typename ELF_T>
901
972
void Parser::parse_dynamic_symbols (uint64_t offset) {
902
973
using Elf_Sym = typename ELF_T::Elf_Sym;
903
974
904
- using Elf_Addr = typename ELF_T::Elf_Addr;
905
975
using Elf_Off = typename ELF_T::Elf_Off;
906
976
VLOG (VDEBUG) << " [+] Parsing dynamics symbols" ;
907
977
@@ -1272,7 +1342,6 @@ template<typename ELF_T, typename REL_T>
1272
1342
void Parser::parse_pltgot_relocations (uint64_t offset, uint64_t size) {
1273
1343
static_assert (std::is_same<REL_T, typename ELF_T::Elf_Rel>::value or
1274
1344
std::is_same<REL_T, typename ELF_T::Elf_Rela>::value, " REL_T must be Elf_Rel or Elf_Rela" );
1275
- using Elf_Addr = typename ELF_T::Elf_Addr;
1276
1345
using Elf_Off = typename ELF_T::Elf_Off;
1277
1346
1278
1347
// Already Parsed
0 commit comments