@@ -24,6 +24,7 @@ class ElfReaderImplBase {
2424 virtual Debuglink read_debuglink () = 0;
2525 virtual Debugaltlink read_debugaltlink () = 0;
2626 virtual string read_buildid () = 0;
27+ virtual string read_interp () = 0;
2728 virtual bool addr_to_offset (uintptr_t addr, uintptr_t & offset) = 0;
2829 virtual SectionOffsets find_section_file_offsets (const char * name) = 0;
2930 virtual const vector<uint8_t >* decompress_section (SectionOffsets offsets) = 0;
@@ -44,15 +45,19 @@ template <typename Arch> class ElfReaderImpl : public ElfReaderImplBase {
4445 virtual Debuglink read_debuglink () override ;
4546 virtual Debugaltlink read_debugaltlink () override ;
4647 virtual string read_buildid () override ;
48+ virtual string read_interp () override ;
4749 virtual bool addr_to_offset (uintptr_t addr, uintptr_t & offset) override ;
4850 virtual SectionOffsets find_section_file_offsets (const char * name) override ;
4951 virtual const vector<uint8_t >* decompress_section (SectionOffsets offsets) override ;
5052
5153private:
5254 const typename Arch::ElfShdr* find_section (const char * n);
55+ const typename Arch::ElfPhdr* find_programheader (uint32_t pt);
5356
5457 const typename Arch::ElfEhdr* elfheader;
58+ const typename Arch::ElfPhdr* programheader;
5559 const typename Arch::ElfShdr* sections;
60+ size_t programheader_size;
5661 size_t sections_size;
5762 vector<char > section_names;
5863};
@@ -75,11 +80,20 @@ ElfReaderImpl<Arch>::ElfReaderImpl(ElfReader& r) : ElfReaderImplBase(r) {
7580 elfheader->e_ident [EI_DATA] != Arch::elfendian ||
7681 elfheader->e_machine != Arch::elfmachine ||
7782 elfheader->e_shentsize != sizeof (typename Arch::ElfShdr) ||
83+ elfheader->e_phentsize != sizeof (typename Arch::ElfPhdr) ||
7884 elfheader->e_shstrndx >= elfheader->e_shnum ) {
7985 LOG (debug) << " Invalid ELF file: invalid header" ;
8086 return ;
8187 }
8288
89+ programheader =
90+ r.read <typename Arch::ElfPhdr>(elfheader->e_phoff , elfheader->e_phnum );
91+ if (!programheader || !elfheader->e_phnum ) {
92+ LOG (debug) << " Invalid ELF file: no program headers" ;
93+ return ;
94+ }
95+ programheader_size = elfheader->e_phnum ;
96+
8397 sections =
8498 r.read <typename Arch::ElfShdr>(elfheader->e_shoff , elfheader->e_shnum );
8599 if (!sections || !elfheader->e_shnum ) {
@@ -103,6 +117,23 @@ ElfReaderImpl<Arch>::ElfReaderImpl(ElfReader& r) : ElfReaderImplBase(r) {
103117 ok_ = true ;
104118}
105119
120+ template <typename Arch>
121+ const typename Arch::ElfPhdr* ElfReaderImpl<Arch>::find_programheader(uint32_t pt) {
122+ const typename Arch::ElfPhdr* ph = nullptr ;
123+
124+ for (size_t i = 0 ; i < programheader_size; ++i) {
125+ auto & p = programheader[i];
126+ if (p.p_type == pt) {
127+ ph = &p;
128+ }
129+ }
130+
131+ if (!ph) {
132+ LOG (debug) << " Missing program header " << pt;
133+ }
134+ return ph;
135+ }
136+
106137template <typename Arch>
107138const typename Arch::ElfShdr* ElfReaderImpl<Arch>::find_section(const char * n) {
108139 const typename Arch::ElfShdr* section = nullptr ;
@@ -438,6 +469,28 @@ string ElfReaderImpl<Arch>::read_buildid() {
438469 return result;
439470}
440471
472+ template <typename Arch>
473+ string ElfReaderImpl<Arch>::read_interp() {
474+ string result;
475+ if (!ok ()) {
476+ return result;
477+ }
478+
479+ const typename Arch::ElfPhdr* ph = find_programheader (PT_INTERP);
480+ if (!ph) {
481+ return result;
482+ }
483+
484+ const char * file_name = r.read <char >(ph->p_offset , ph->p_filesz );
485+ if (!file_name) {
486+ LOG (warn) << " Invalid ELF file: can't read PT_INTERP" ;
487+ return result;
488+ }
489+
490+ null_terminated (file_name, ph->p_filesz , result);
491+ return result;
492+ }
493+
441494template <typename Arch>
442495bool ElfReaderImpl<Arch>::addr_to_offset(uintptr_t addr, uintptr_t & offset) {
443496 for (size_t i = 0 ; i < sections_size; ++i) {
@@ -492,6 +545,7 @@ DwarfSpan ElfReader::dwarf_section(const char* name, bool known_to_be_compressed
492545}
493546
494547string ElfReader::read_buildid () { return impl ().read_buildid (); }
548+ string ElfReader::read_interp () { return impl ().read_interp (); }
495549
496550bool ElfReader::addr_to_offset (uintptr_t addr, uintptr_t & offset) {
497551 return impl ().addr_to_offset (addr, offset);
0 commit comments