From 68dc53768c15804d069649185f33baf0ffdc92e6 Mon Sep 17 00:00:00 2001 From: ghidra1 Date: Tue, 14 Nov 2023 18:42:03 -0500 Subject: [PATCH] GP-4202 corrected ELF PT_NOTE processing issue --- .../elf/info/StandardElfInfoProducer.java | 91 ++++++++++++------- .../program/model/reloc/Relocation.java | 5 +- 2 files changed, 58 insertions(+), 38 deletions(-) diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/elf/info/StandardElfInfoProducer.java b/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/elf/info/StandardElfInfoProducer.java index 9ae8b46ab4..097e4163a9 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/elf/info/StandardElfInfoProducer.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/elf/info/StandardElfInfoProducer.java @@ -23,6 +23,7 @@ import ghidra.app.util.bin.*; import ghidra.app.util.bin.format.elf.*; import ghidra.app.util.bin.format.elf.info.ElfInfoItem.ReaderFunc; import ghidra.program.model.address.Address; +import ghidra.program.model.address.AddressOutOfBoundsException; import ghidra.program.model.data.*; import ghidra.program.model.data.DataUtilities.ClearDataMode; import ghidra.program.model.listing.CodeUnit; @@ -52,12 +53,12 @@ public class StandardElfInfoProducer implements ElfInfoProducer { public static final CategoryPath ELF_CATEGORYPATH = new CategoryPath("/ELF"); - private static final Map> STANDARD_READERS = Map.of( - GnuDebugLink.SECTION_NAME, GnuDebugLink::read, - NoteAbiTag.SECTION_NAME, (br, prg) -> NoteAbiTag.read(ElfNote.read(br), prg), - NoteGnuBuildId.SECTION_NAME, (br, prg) -> NoteGnuBuildId.read(ElfNote.read(br), prg), - NoteGnuProperty.SECTION_NAME, (br, prg) -> NoteGnuProperty.read(ElfNote.read(br), prg), - ElfComment.SECTION_NAME, ElfComment::read); + private static final Map> STANDARD_READERS = + Map.of(GnuDebugLink.SECTION_NAME, GnuDebugLink::read, NoteAbiTag.SECTION_NAME, + (br, prg) -> NoteAbiTag.read(ElfNote.read(br), prg), NoteGnuBuildId.SECTION_NAME, + (br, prg) -> NoteGnuBuildId.read(ElfNote.read(br), prg), NoteGnuProperty.SECTION_NAME, + (br, prg) -> NoteGnuProperty.read(ElfNote.read(br), prg), ElfComment.SECTION_NAME, + ElfComment::read); private ElfLoadHelper elfLoadHelper; @@ -78,10 +79,10 @@ public class StandardElfInfoProducer implements ElfInfoProducer { ElfInfoItem.markupElfInfoItemSection(program, sectionName, readFunc); } - markupPTNOTESections(monitor); + markupPtNoteSegments(monitor); } - private void markupPTNOTESections(TaskMonitor monitor) throws CancelledException { + private void markupPtNoteSegments(TaskMonitor monitor) throws CancelledException { Program program = elfLoadHelper.getProgram(); Memory memory = program.getMemory(); for (ElfProgramHeader elfProgramHeader : elfLoadHelper.getElfHeader() @@ -90,43 +91,63 @@ public class StandardElfInfoProducer implements ElfInfoProducer { Address addr = elfLoadHelper.findLoadAddress(elfProgramHeader, 0); if (addr == null) { + elfLoadHelper.log("Failed to identify PT_NOTE load address"); continue; } - MemoryBlock memBlock = memory.getBlock(addr); - if (memBlock == null) { - continue; - } - try (ByteProvider bp = - MemoryByteProvider.createMemoryBlockByteProvider(program.getMemory(), memBlock)) { - BinaryReader br = new BinaryReader(bp, !program.getMemory().isBigEndian()); - while (br.hasNext()) { - monitor.checkCancelled(); - long start = br.getPointerIndex(); - ElfNote note = br.readNext(ElfNote::read); - br.align(4); // fix any notes with non-aligned size payloads - long noteLength = br.getPointerIndex() - start; - - try { - StructureDataType struct = note.toStructure(program.getDataTypeManager()); - DataUtilities.createData(program, addr, struct, -1, false, - ClearDataMode.CLEAR_ALL_UNDEFINED_CONFLICT_DATA); - String comment = - "ELF Note \"%s\", %xh".formatted(note.getName(), note.getVendorType()); - program.getListing().setComment(addr, CodeUnit.EOL_COMMENT, comment); - } - catch (CodeUnitInsertionException e) { - // ignore, continue to next note + try { + Address endAddr = null; + MemoryBlock memBlock = memory.getBlock(addr); + if (memBlock != null) { + long loadSize = elfProgramHeader.getAdjustedLoadSize(); + if (loadSize > 0) { + endAddr = addr.add(loadSize - 1); } + } - addr = addr.addWrap(noteLength); + if (endAddr == null) { + elfLoadHelper.log("Failed to markup non-loaded PT_NOTE at " + addr); + continue; + } + + try (ByteProvider bp = new MemoryByteProvider(program.getMemory(), addr, endAddr)) { + BinaryReader br = new BinaryReader(bp, !program.getMemory().isBigEndian()); + markupPtNote(br, program, addr, monitor); } } - catch (IOException e) { - Msg.warn(this, "Failed to read ELF Note at %s".formatted(addr), e); + catch (Exception e) { + // NOTE: There are some unsupported formats which may throw severe exceptions + elfLoadHelper.log("Failed to parse and markup ELF Note starting at " + addr); } } } + private void markupPtNote(BinaryReader br, Program program, Address noteAddr, + TaskMonitor monitor) + throws CancelledException, AddressOutOfBoundsException, IOException { + while (br.hasNext()) { + monitor.checkCancelled(); + + long start = br.getPointerIndex(); + ElfNote note = br.readNext(ElfNote::read); + br.align(4); // fix any notes with non-aligned size payloads + long noteLength = br.getPointerIndex() - start; + + try { + StructureDataType struct = note.toStructure(program.getDataTypeManager()); + DataUtilities.createData(program, noteAddr, struct, -1, false, + ClearDataMode.CLEAR_ALL_UNDEFINED_CONFLICT_DATA); + String comment = + "ELF Note \"%s\", %xh".formatted(note.getName(), note.getVendorType()); + program.getListing().setComment(noteAddr, CodeUnit.EOL_COMMENT, comment); + } + catch (CodeUnitInsertionException e) { + elfLoadHelper.log("Failed to markup ELF Note at " + noteAddr + ": data conflict"); + } + + noteAddr = noteAddr.add(noteLength); + } + } + } diff --git a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/reloc/Relocation.java b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/reloc/Relocation.java index 37955104e7..1c65a2b84c 100644 --- a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/reloc/Relocation.java +++ b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/reloc/Relocation.java @@ -38,7 +38,7 @@ public class Relocation { UNKNOWN(0, true), /** - * Relocation has be intentionally skipped and should not be treated as a failure. + * Relocation has been intentionally skipped and should not be treated as a failure. */ SKIPPED(1, false), @@ -105,8 +105,7 @@ public class Relocation { return s; } } - throw new IllegalArgumentException( - "Undefined Status value: " + value); + throw new IllegalArgumentException("Undefined Status value: " + value); } }