diff --git a/llvm/include/llvm/Object/ELF.h b/llvm/include/llvm/Object/ELF.h --- a/llvm/include/llvm/Object/ELF.h +++ b/llvm/include/llvm/Object/ELF.h @@ -184,7 +184,16 @@ ELFFile(StringRef Object); + void createFakeSections(); + std::unique_ptr FakeSec; + int NumFakeSec; + public: + ELFFile(const ELFFile& other) : Buf(other.Buf) { + if (getHeader().e_type == ELF::ET_CORE) + createFakeSections(); + } + const Elf_Ehdr &getHeader() const { return *reinterpret_cast(base()); } @@ -746,7 +755,10 @@ return 0; } -template ELFFile::ELFFile(StringRef Object) : Buf(Object) {} +template ELFFile::ELFFile(StringRef Object) : Buf(Object) { + if (getHeader().e_type == ELF::ET_CORE) + createFakeSections(); +} template Expected> ELFFile::create(StringRef Object) { @@ -757,11 +769,51 @@ return ELFFile(Object); } +/// This function creates fake section headers from program headers. +/// This is for linux perf tools because it copies a part of kcore +/// to disassemble a single function in the kernel. +template +void ELFFile::createFakeSections() { + auto PhdrsOrErr = program_headers(); + if (!PhdrsOrErr) + return; + + NumFakeSec = 0; + for (auto Phdr : *PhdrsOrErr) { + if (!(Phdr.p_type & ELF::PT_LOAD)) + continue; + if (!(Phdr.p_flags & ELF::PF_X)) + continue; + NumFakeSec++; + } + if (NumFakeSec == 0) + return; + + FakeSec = std::make_unique(NumFakeSec); + + auto Shdr = &FakeSec[0]; + for (auto Phdr : *PhdrsOrErr) { + if (!(Phdr.p_type & ELF::PT_LOAD)) + continue; + if (!(Phdr.p_flags & ELF::PF_X)) + continue; + Shdr->sh_type = ELF::SHT_PROGBITS; + Shdr->sh_flags = ELF::SHF_ALLOC | ELF::SHF_EXECINSTR; + Shdr->sh_addr = Phdr.p_vaddr; + Shdr->sh_size = Phdr.p_memsz; + Shdr->sh_offset = Phdr.p_offset; + ++Shdr; + } +} + template Expected ELFFile::sections() const { const uintX_t SectionTableOffset = getHeader().e_shoff; - if (SectionTableOffset == 0) + if (SectionTableOffset == 0) { + if (getHeader().e_type == ELF::ET_CORE && NumFakeSec) + return makeArrayRef(&FakeSec[0], NumFakeSec); return ArrayRef(); + } if (getHeader().e_shentsize != sizeof(Elf_Shdr)) return createError("invalid e_shentsize in ELF header: " +