[PATCH] D128705: [llvm-objdump] Create fake sections for a ELF core file
Namhyung Kim via Phabricator via llvm-commits
llvm-commits at lists.llvm.org
Tue Jun 28 00:19:15 PDT 2022
namhyung created this revision.
namhyung added reviewers: Bigcheese, MaskRay, irogers.
Herald added a subscriber: StephenFan.
Herald added a project: All.
namhyung requested review of this revision.
Herald added a project: LLVM.
Herald added a subscriber: llvm-commits.
The linux perf tools use /proc/kcore for disassembly kernel functions.
Actually it copies the relevant parts to a temp file and then pass it to
objdump. But it doesn't have section headers so llvm-objdump cannot
handle it.
Let's create fake section headers for the program headers. It'd have a
single section for each segment to cover the entire range. And for this
purpose we can consider only executable code segments.
With this change, I can see `perf annotate` shows proper outputs.
Repository:
rG LLVM Github Monorepo
https://reviews.llvm.org/D128705
Files:
llvm/include/llvm/Object/ELF.h
Index: llvm/include/llvm/Object/ELF.h
===================================================================
--- llvm/include/llvm/Object/ELF.h
+++ llvm/include/llvm/Object/ELF.h
@@ -184,7 +184,16 @@
ELFFile(StringRef Object);
+ void createFakeSections();
+ std::unique_ptr<Elf_Shdr[]> FakeSec;
+ int NumFakeSec;
+
public:
+ ELFFile(const ELFFile<ELFT>& other) : Buf(other.Buf) {
+ if (getHeader().e_type == ELF::ET_CORE)
+ createFakeSections();
+ }
+
const Elf_Ehdr &getHeader() const {
return *reinterpret_cast<const Elf_Ehdr *>(base());
}
@@ -746,7 +755,10 @@
return 0;
}
-template <class ELFT> ELFFile<ELFT>::ELFFile(StringRef Object) : Buf(Object) {}
+template <class ELFT> ELFFile<ELFT>::ELFFile(StringRef Object) : Buf(Object) {
+ if (getHeader().e_type == ELF::ET_CORE)
+ createFakeSections();
+}
template <class ELFT>
Expected<ELFFile<ELFT>> ELFFile<ELFT>::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 <class ELFT>
+void ELFFile<ELFT>::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<Elf_Shdr[]>(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 <class ELFT>
Expected<typename ELFT::ShdrRange> ELFFile<ELFT>::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<Elf_Shdr>();
+ }
if (getHeader().e_shentsize != sizeof(Elf_Shdr))
return createError("invalid e_shentsize in ELF header: " +
-------------- next part --------------
A non-text attachment was scrubbed...
Name: D128705.440504.patch
Type: text/x-patch
Size: 2501 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20220628/8b4d9be4/attachment.bin>
More information about the llvm-commits
mailing list