summaryrefslogtreecommitdiff
path: root/view/elf/elfview.cpp
diff options
context:
space:
mode:
authorGalen Williamson <galen@vector35.com>2025-06-29 11:23:58 -0400
committerGalen Williamson <galen@vector35.com>2025-06-29 18:28:48 -0400
commite8206bc27e1633c7e4c99907f43bf67d2f200cd5 (patch)
tree2315bec284e9bb692a0eb8986578fe18e2289d23 /view/elf/elfview.cpp
parent91f1eccb6c41a7ef60fd66387ffae075f88141a4 (diff)
[powerpc] Full merge of PowerPC disassembler PRs, including:
* Remove dependency on capstone for PowerPC disassembly #6292 * Add support for PowerPC VLE instruction set #6740 * Add support for paired-single instructions #6821 * Various post-merge fixes and tweaks to disassembly and lifting * Removal of dependence on capstone for assembler's scoring mechanism (capstone currently disabled, but not removed from codebase yet)
Diffstat (limited to 'view/elf/elfview.cpp')
-rw-r--r--view/elf/elfview.cpp70
1 files changed, 70 insertions, 0 deletions
diff --git a/view/elf/elfview.cpp b/view/elf/elfview.cpp
index 25e00152..d7dc1203 100644
--- a/view/elf/elfview.cpp
+++ b/view/elf/elfview.cpp
@@ -2875,6 +2875,8 @@ uint64_t ElfViewType::ParseHeaders(BinaryView* data, ElfIdent& ident, ElfCommonH
commonHeader.arch = reader.Read16();
commonHeader.version = reader.Read32();
+ bool is32bit = ident.fileClass == 1;
+
// parse Elf64Header
if (ident.fileClass == 1) // 32-bit ELF
{
@@ -2908,6 +2910,37 @@ uint64_t ElfViewType::ParseHeaders(BinaryView* data, ElfIdent& ident, ElfCommonH
return 0;
}
+ // This is some disgusting code duplication, the PowerPC ELF recognizer
+ // needs some section information passed to it:
+ // (1) contents of the .ppc.EMB.apuinfo to figure out additional
+ // processor information (SPE, Altivec, etc.)
+ // (2) whether any sections have VLE flags
+ //
+ // But this function doesn't have a handle to the ElfView, so we
+ // duplicate the section iteration/parsing logic
+ //
+ // We're early enough in the process that if sizes aren't what we expect
+ // them to be, we just don't pass section info to the ELF recognizer
+ // function, but pass everything else to aid troubleshooting
+ uint16_t sectionHeaderSize = header.sectionHeaderSize;
+ uint32_t sectionCount = header.sectionHeaderCount;
+ if (is32bit && (sectionHeaderSize != sizeof(Elf32SectionHeader)))
+ {
+ m_logger->LogWarn(
+ "The section header size reported by e_shentsize (0x%lx) is different from the size of Elf32_Shdr (0x%lx). "
+ "Won't do first pass section header parsing.",
+ sectionHeaderSize, sizeof(Elf32SectionHeader));
+ sectionCount = 0;
+ }
+ else if (!is32bit && (sectionHeaderSize != sizeof(Elf64SectionHeader)))
+ {
+ m_logger->LogWarn(
+ "The section header size reported by e_shentsize (0x%lx) is different from the size of Elf64_Shdr (0x%lx). "
+ "Won't do first pass section header parsing.",
+ sectionHeaderSize, sizeof(Elf64SectionHeader));
+ sectionCount = 0;
+ }
+
map<string, Ref<Metadata>> metadataMap = {
{"EI_CLASS", new Metadata((uint64_t) ident.fileClass)},
{"EI_DATA", new Metadata((uint64_t) ident.encoding)},
@@ -2917,6 +2950,43 @@ uint64_t ElfViewType::ParseHeaders(BinaryView* data, ElfIdent& ident, ElfCommonH
{"e_flags", new Metadata((uint64_t) header.flags)},
};
+ BinaryReader sectionReader(data);
+ sectionReader.SetEndianness(endianness);
+ uint64_t flagsOffset = header.sectionHeaderOffset;
+ if (is32bit)
+ flagsOffset += offsetof(Elf32SectionHeader, flags);
+ else
+ flagsOffset += offsetof(Elf64SectionHeader, flags);
+
+ for (unsigned int i=0; i < sectionCount; ++i)
+ {
+ sectionReader.Seek(flagsOffset);
+ uint64_t flags;
+ try
+ {
+ if (is32bit)
+ flags = sectionReader.Read32();
+ else
+ flags = sectionReader.Read64();
+ }
+ catch (ReadException&)
+ {
+ m_logger->LogWarn("Failed to read section flags at offset %" PRIx64, flagsOffset);
+ // Note that any previously read flags values will
+ // still persist in the metadata map
+ sectionCount = 0;
+ break;
+ }
+
+ char metaname[0x20];
+ snprintf(metaname, sizeof metaname, "sectionFlags[%d]", i);
+
+ metadataMap[metaname] = new Metadata((uint64_t)flags);
+ flagsOffset += header.sectionHeaderSize;
+ }
+
+ metadataMap["numSections"] = new Metadata((uint64_t) sectionCount);
+
Ref<Metadata> metadata = new Metadata(metadataMap);
// retrieve architecture
// FIXME: Architecture registration methods should perhaps be virtual and take the raw data, or some additional opaque information.