From 577328f23058f5929275d2e8a2bea869088602fe Mon Sep 17 00:00:00 2001 From: ghidra1 Date: Tue, 12 Apr 2022 15:25:12 -0400 Subject: [PATCH] GP-1907: Updated ELF related loader to eliminate use of ContinuesInterceptor --- .../cmd/formats/ElfBinaryAnalysisCommand.java | 11 +-- .../app/util/bin/format/elf/ElfDynamic.java | 29 ++---- .../util/bin/format/elf/ElfDynamicTable.java | 19 +--- .../app/util/bin/format/elf/ElfHeader.java | 92 ++++++++----------- .../util/bin/format/elf/ElfProgramHeader.java | 37 +++----- .../util/bin/format/elf/ElfRelocation.java | 88 ++++++++++-------- .../bin/format/elf/ElfRelocationTable.java | 59 ++++-------- .../util/bin/format/elf/ElfSectionHeader.java | 40 +++----- .../app/util/bin/format/elf/ElfString.java | 71 -------------- .../util/bin/format/elf/ElfStringTable.java | 39 ++------ .../app/util/bin/format/elf/ElfSymbol.java | 49 ++++------ .../util/bin/format/elf/ElfSymbolTable.java | 30 ++---- .../ghidra/app/util/opinion/ElfDataType.java | 5 +- .../ghidra/app/util/opinion/ElfLoader.java | 9 +- .../util/opinion/ElfLoaderOptionsFactory.java | 3 +- .../app/util/opinion/ElfProgramBuilder.java | 6 +- .../formats/android/oat/OatFileSystem.java | 7 +- .../elf/relocation/MIPS_Elf64Relocation.java | 7 +- 18 files changed, 194 insertions(+), 407 deletions(-) delete mode 100644 Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/elf/ElfString.java diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/cmd/formats/ElfBinaryAnalysisCommand.java b/Ghidra/Features/Base/src/main/java/ghidra/app/cmd/formats/ElfBinaryAnalysisCommand.java index b423fe8060..f3481ac1a7 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/cmd/formats/ElfBinaryAnalysisCommand.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/cmd/formats/ElfBinaryAnalysisCommand.java @@ -17,7 +17,6 @@ package ghidra.app.cmd.formats; import java.util.Arrays; -import generic.continues.RethrowContinuesFactory; import ghidra.app.plugin.core.analysis.AnalysisWorker; import ghidra.app.plugin.core.analysis.AutoAnalysisManager; import ghidra.app.util.bin.*; @@ -36,7 +35,8 @@ import ghidra.program.model.mem.Memory; import ghidra.program.model.mem.MemoryBlock; import ghidra.program.model.symbol.*; import ghidra.program.model.util.CodeUnitInsertionException; -import ghidra.util.*; +import ghidra.util.Msg; +import ghidra.util.StringUtilities; import ghidra.util.exception.CancelledException; import ghidra.util.exception.DuplicateNameException; import ghidra.util.task.TaskMonitor; @@ -80,8 +80,7 @@ public class ElfBinaryAnalysisCommand extends FlatProgramAPI ByteProvider provider = new MemoryByteProvider(currentProgram.getMemory(), currentProgram.getAddressFactory().getDefaultAddressSpace()); try { - ElfHeader elf = ElfHeader.createElfHeader(RethrowContinuesFactory.INSTANCE, provider, - msg -> messages.appendMsg(msg)); + ElfHeader elf = new ElfHeader(provider, msg -> messages.appendMsg(msg)); elf.parse(); processElfHeader(elf, listing); @@ -221,7 +220,7 @@ public class ElfBinaryAnalysisCommand extends FlatProgramAPI } Structure phStructDt = (Structure) elf.getProgramHeaders()[0].toDataType(); - phStructDt = (Structure) phStructDt.clone(listing.getDataTypeManager()); + phStructDt = phStructDt.clone(listing.getDataTypeManager()); Array arrayDt = new ArrayDataType(phStructDt, headerCount, size); Data array = createData(addr(elf.e_phoff()), arrayDt); @@ -382,7 +381,7 @@ public class ElfBinaryAnalysisCommand extends FlatProgramAPI } String name = symbols[j].getNameAsString(); - long value = symbols[j].getValue() & Conv.INT_MASK; + long value = Integer.toUnsignedLong((int) symbols[j].getValue()); try { Address currAddr = symbolTableAddr.add(j * symbolTable2.getEntrySize()); diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/elf/ElfDynamic.java b/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/elf/ElfDynamic.java index 26e9fff4e1..b6f5572fbc 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/elf/ElfDynamic.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/elf/ElfDynamic.java @@ -17,9 +17,10 @@ package ghidra.app.util.bin.format.elf; import java.io.IOException; +import ghidra.app.util.bin.BinaryReader; import ghidra.app.util.bin.ByteArrayConverter; -import ghidra.app.util.bin.format.FactoryBundledWithBinaryReader; -import ghidra.util.*; +import ghidra.util.DataConverter; +import ghidra.util.StringUtilities; /** * A class to represent the Elf32_Dyn data structure. @@ -56,28 +57,14 @@ public class ElfDynamic implements ByteArrayConverter { private ElfHeader elf; private int d_tag; -// private ElfDynamicType d_tag_type; private long d_val; - public static ElfDynamic createElfDynamic( -FactoryBundledWithBinaryReader reader, ElfHeader elf) - throws IOException { - ElfDynamic elfDynamic = (ElfDynamic) reader.getFactory().create(ElfDynamic.class); - elfDynamic.initElfDynamic(reader, elf); - return elfDynamic; - } - - /** - * DO NOT USE THIS CONSTRUCTOR, USE create*(GenericFactory ...) FACTORY METHODS INSTEAD. - */ - public ElfDynamic() {} - - private void initElfDynamic(FactoryBundledWithBinaryReader reader, ElfHeader elf) + public ElfDynamic(BinaryReader reader, ElfHeader elf) throws IOException { this.elf = elf; if (elf.is32Bit()) { d_tag = reader.readNextInt(); - d_val = reader.readNextInt() & Conv.INT_MASK; + d_val = Integer.toUnsignedLong(reader.readNextInt()); } else { d_tag = (int) reader.readNextLong(); @@ -148,7 +135,7 @@ FactoryBundledWithBinaryReader reader, ElfHeader elf) * @param value the new value dynamic */ public void setValue(int value) { - this.d_val = value & Conv.INT_MASK; + this.d_val = Integer.toUnsignedLong(value); } /** @@ -191,8 +178,8 @@ FactoryBundledWithBinaryReader reader, ElfHeader elf) } /** - * Returns the size in bytes of this object. - */ + * @return the size in bytes of this object. + */ public int sizeof() { return elf.is32Bit() ? 8 : 16; } diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/elf/ElfDynamicTable.java b/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/elf/ElfDynamicTable.java index bce6f47b9c..6a99121800 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/elf/ElfDynamicTable.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/elf/ElfDynamicTable.java @@ -18,7 +18,7 @@ package ghidra.app.util.bin.format.elf; import java.io.IOException; import java.util.*; -import ghidra.app.util.bin.format.FactoryBundledWithBinaryReader; +import ghidra.app.util.bin.BinaryReader; import ghidra.program.model.data.*; import ghidra.util.DataConverter; import ghidra.util.exception.DuplicateNameException; @@ -42,20 +42,7 @@ public class ElfDynamicTable implements ElfFileSection { private long fileOffset; private long addrOffset; - public static ElfDynamicTable createDynamicTable(FactoryBundledWithBinaryReader reader, - ElfHeader header, long fileOffset, long addrOffset) throws IOException { - ElfDynamicTable pt_dynamic = (ElfDynamicTable) reader.getFactory().create(ElfDynamicTable.class); - pt_dynamic.initDynamicTable(reader, header, fileOffset, addrOffset); - return pt_dynamic; - } - - /** - * DO NOT USE THIS CONSTRUCTOR, USE create*(GenericFactory ...) FACTORY METHODS INSTEAD. - */ - public ElfDynamicTable() { - } - - private void initDynamicTable(FactoryBundledWithBinaryReader reader, ElfHeader header, + public ElfDynamicTable(BinaryReader reader, ElfHeader header, long fileOffset, long addrOffset) throws IOException { long oldptr = reader.getPointerIndex(); @@ -68,7 +55,7 @@ public class ElfDynamicTable implements ElfFileSection { // Collect set of all _DYNAMIC array tags specified in .dynamic section while (true) { - ElfDynamic dyn = ElfDynamic.createElfDynamic(reader, header); + ElfDynamic dyn = new ElfDynamic(reader, header); dynamics.add(dyn); if (dyn.getTag() == ElfDynamicType.DT_NULL.value) { break; diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/elf/ElfHeader.java b/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/elf/ElfHeader.java index ae47cf9dce..15b11988db 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/elf/ElfHeader.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/elf/ElfHeader.java @@ -20,9 +20,7 @@ import java.io.RandomAccessFile; import java.util.*; import java.util.function.Consumer; -import generic.continues.GenericFactory; import ghidra.app.util.bin.*; -import ghidra.app.util.bin.format.FactoryBundledWithBinaryReader; import ghidra.app.util.bin.format.Writeable; import ghidra.app.util.bin.format.elf.ElfRelocationTable.TableFormat; import ghidra.app.util.bin.format.elf.extend.ElfExtensionFactory; @@ -30,7 +28,8 @@ import ghidra.app.util.bin.format.elf.extend.ElfLoadAdapter; import ghidra.program.model.data.*; import ghidra.program.model.mem.MemoryAccessException; import ghidra.program.model.mem.MemoryBlock; -import ghidra.util.*; +import ghidra.util.DataConverter; +import ghidra.util.Msg; import ghidra.util.exception.AssertException; import ghidra.util.exception.NotFoundException; @@ -49,7 +48,7 @@ public class ElfHeader implements StructConverter, Writeable { private HashMap dynamicTypeMap; private ByteProvider provider; // original byte provider - private FactoryBundledWithBinaryReader reader; // based on unlimited byte provider + private BinaryReader reader; // unlimited reader private ElfLoadAdapter elfLoadAdapter = new ElfLoadAdapter(); private byte e_ident_magic_num; //magic number @@ -98,28 +97,17 @@ public class ElfHeader implements StructConverter, Writeable { private static int INITIAL_READ_LEN = ElfConstants.EI_NIDENT + 18; /** - * Constructs a new ELF header using the specified byte provider. - * Only the one header is parsed. The related headers are not - * parsed until {@link #parse()} is invoked. - * @param factory instantiation factory - * @param provider the byte provider to supply the bytes - * @param errorConsumer optional error consumer or null for no logging - * @return ELF Header object - * @throws ElfException if the underlying bytes in the byte provider - * do not constitute a valid ELF. + * Construct ElfHeader from byte provider + * @param provider byte provider + * @param errorConsumer error consumer + * @throws ElfException if header parse failed */ - public static ElfHeader createElfHeader(GenericFactory factory, ByteProvider provider, - Consumer errorConsumer) - throws ElfException { - ElfHeader elfHeader = (ElfHeader) factory.create(ElfHeader.class); - elfHeader.initElfHeader(factory, provider, errorConsumer); - return elfHeader; - } - - /** - * DO NOT USE THIS CONSTRUCTOR, USE create*(GenericFactory ...) FACTORY METHODS INSTEAD. - */ - public ElfHeader() { + public ElfHeader(ByteProvider provider, Consumer errorConsumer) throws ElfException { + this.provider = provider; + this.errorConsumer = errorConsumer != null ? errorConsumer : msg -> { + /* no logging if errorConsumer was null */ + }; + initElfHeader(); } /** @@ -143,20 +131,14 @@ public class ElfHeader implements StructConverter, Writeable { errorConsumer.accept(msg); } - protected void initElfHeader(GenericFactory factory, ByteProvider provider, - Consumer errorConsumer) - throws ElfException { + protected void initElfHeader() throws ElfException { try { - this.provider = provider; - this.errorConsumer = errorConsumer != null ? errorConsumer : msg -> { - /* no logging if errorConsumer was null */ - }; determineHeaderEndianess(); // reader uses unbounded provider wrapper to allow handling of missing/truncated headers - reader = new FactoryBundledWithBinaryReader(factory, - new UnlimitedByteProviderWrapper(provider), hasLittleEndianHeaders); + reader = new BinaryReader(new UnlimitedByteProviderWrapper(provider), + hasLittleEndianHeaders); e_ident_magic_num = reader.readNextByte(); e_ident_magic_str = reader.readNextAsciiString(ElfConstants.MAGIC_STR_LEN); @@ -278,7 +260,7 @@ public class ElfHeader implements StructConverter, Writeable { * Adjust address offset for certain pre-linked binaries which do not adjust certain * header fields (e.g., dynamic table address entries). Standard GNU/Linux pre-linked * shared libraries have adjusted header entries and this method should have no effect. - * @param address + * @param address unadjusted address offset * @return address with appropriate pre-link adjustment added */ public long adjustAddressForPrelink(long address) { @@ -299,7 +281,7 @@ public class ElfHeader implements StructConverter, Writeable { * Unadjust address offset for certain pre-linked binaries which do not adjust certain * header fields (e.g., dynamic table address entries). This may be needed when updating * a header address field which requires pre-link adjustment. - * @param address + * @param address prelink-adjusted address offset * @return address with appropriate pre-link adjustment subtracted */ public long unadjustAddressForPrelink(long address) { @@ -489,7 +471,7 @@ public class ElfHeader implements StructConverter, Writeable { format = TableFormat.RELR; } - ElfRelocationTable relocTable = ElfRelocationTable.createElfRelocationTable(reader, + ElfRelocationTable relocTable = new ElfRelocationTable(reader, this, section, section.getOffset(), section.getAddress(), section.getSize(), section.getEntrySize(), addendTypeReloc, symbolTable, sectionToBeRelocated, format); @@ -587,7 +569,7 @@ public class ElfHeader implements StructConverter, Writeable { format = TableFormat.RELR; } - ElfRelocationTable relocTable = ElfRelocationTable.createElfRelocationTable(reader, + ElfRelocationTable relocTable = new ElfRelocationTable(reader, this, null, relocTableOffset, relocTableAddr, tableSize, tableEntrySize, addendTypeReloc, dynamicSymbolTable, null, format); relocationTableList.add(relocTable); @@ -599,7 +581,7 @@ public class ElfHeader implements StructConverter, Writeable { /** * Get linked section - * @param sectionIndex + * @param sectionIndex section index * @param expectedTypes list of expectedTypes (may be omitted to accept any type) * @return section or null if not found */ @@ -661,7 +643,7 @@ public class ElfHeader implements StructConverter, Writeable { if (loadHeader != null) { long dynamicTableOffset = loadHeader.getOffset() + (dynamicHeaders[0].getVirtualAddress() - loadHeader.getVirtualAddress()); - dynamicTable = ElfDynamicTable.createDynamicTable(reader, this, dynamicTableOffset, + dynamicTable = new ElfDynamicTable(reader, this, dynamicTableOffset, dynamicHeaders[0].getVirtualAddress()); return; } @@ -678,7 +660,7 @@ public class ElfHeader implements StructConverter, Writeable { if (loadHeader != null) { long dynamicTableOffset = loadHeader.getOffset() + (dynamicSections[0].getAddress() - loadHeader.getVirtualAddress()); - dynamicTable = ElfDynamicTable.createDynamicTable(reader, this, dynamicTableOffset, + dynamicTable = new ElfDynamicTable(reader, this, dynamicTableOffset, dynamicSections[0].getAddress()); return; } @@ -686,7 +668,7 @@ public class ElfHeader implements StructConverter, Writeable { } - private void parseStringTables() throws IOException { + private void parseStringTables() { // identify dynamic symbol table address long dynamicStringTableAddr = -1; @@ -703,7 +685,7 @@ public class ElfHeader implements StructConverter, Writeable { ArrayList stringTableList = new ArrayList<>(); for (ElfSectionHeader stringTableSectionHeader : sectionHeaders) { if (stringTableSectionHeader.getType() == ElfSectionHeaderConstants.SHT_STRTAB) { - ElfStringTable stringTable = ElfStringTable.createElfStringTable(reader, this, + ElfStringTable stringTable = new ElfStringTable(reader, this, stringTableSectionHeader, stringTableSectionHeader.getOffset(), stringTableSectionHeader.getAddress(), stringTableSectionHeader.getSize()); stringTableList.add(stringTable); @@ -724,7 +706,7 @@ public class ElfHeader implements StructConverter, Writeable { stringTableList.toArray(stringTables); } - private ElfStringTable parseDynamicStringTable(long dynamicStringTableAddr) throws IOException { + private ElfStringTable parseDynamicStringTable(long dynamicStringTableAddr) { if (!dynamicTable.containsDynamicValue(ElfDynamicType.DT_STRSZ)) { errorConsumer.accept("Failed to parse DT_STRTAB, missing dynamic dependency"); @@ -748,7 +730,7 @@ public class ElfHeader implements StructConverter, Writeable { return null; } - return ElfStringTable.createElfStringTable(reader, this, null, + return new ElfStringTable(reader, this, null, stringTableLoadHeader.getOffset(dynamicStringTableAddr), dynamicStringTableAddr, stringTableSize); } @@ -792,7 +774,7 @@ public class ElfHeader implements StructConverter, Writeable { boolean isDyanmic = ElfSectionHeaderConstants.dot_dynsym .equals(symbolTableSectionHeader.getNameAsString()); - ElfSymbolTable symbolTable = ElfSymbolTable.createElfSymbolTable(reader, this, + ElfSymbolTable symbolTable = new ElfSymbolTable(reader, this, symbolTableSectionHeader, symbolTableSectionHeader.getOffset(), symbolTableSectionHeader.getAddress(), symbolTableSectionHeader.getSize(), symbolTableSectionHeader.getEntrySize(), stringTable, isDyanmic); @@ -880,7 +862,7 @@ public class ElfHeader implements StructConverter, Writeable { symCount = reader.readInt(symbolHashTableOffset + 4); // nchain from DT_HASH } - return ElfSymbolTable.createElfSymbolTable(reader, this, null, symbolTableOffset, + return new ElfSymbolTable(reader, this, null, symbolTableOffset, tableAddr, tableEntrySize * symCount, tableEntrySize, dynamicStringTable, true); } catch (NotFoundException e) { @@ -890,7 +872,7 @@ public class ElfHeader implements StructConverter, Writeable { /** * Walk DT_GNU_HASH table to determine dynamic symbol count - * @param DT_GNU_HASH table file offset + * @param gnuHashTableOffset DT_GNU_HASH table file offset * @return dynamic symbol count * @throws IOException file read error */ @@ -966,7 +948,7 @@ public class ElfHeader implements StructConverter, Writeable { missing = true; } reader.setPointerIndex(index); - sectionHeaders[i] = ElfSectionHeader.createElfSectionHeader(reader, this); + sectionHeaders[i] = new ElfSectionHeader(reader, this); } //note: we cannot retrieve all the names @@ -992,7 +974,7 @@ public class ElfHeader implements StructConverter, Writeable { missing = true; } reader.setPointerIndex(index); - programHeaders[i] = ElfProgramHeader.createElfProgramHeader(reader, this); + programHeaders[i] = new ElfProgramHeader(reader, this); } // TODO: Find sample file which requires this hack to verify its necessity @@ -1045,7 +1027,7 @@ public class ElfHeader implements StructConverter, Writeable { private long getMinBase(long addr, long minBase) { if (is32Bit()) { - addr &= Conv.INT_MASK; + addr = Integer.toUnsignedLong((int) addr); } if (Long.compareUnsigned(addr, minBase) < 0) { minBase = addr; @@ -1079,7 +1061,7 @@ public class ElfHeader implements StructConverter, Writeable { try { int headerType = reader.peekNextInt(); if (headerType == ElfProgramHeaderConstants.PT_LOAD) { - ElfProgramHeader header = ElfProgramHeader.createElfProgramHeader(reader, this); + ElfProgramHeader header = new ElfProgramHeader(reader, this); minBase = getMinBase(header.getVirtualAddress(), minBase); } } @@ -1418,7 +1400,7 @@ public class ElfHeader implements StructConverter, Writeable { /** * Returns the section headers with the specified type. * The array could be zero-length, but will not be null. - * @param type + * @param type section type * @return the section headers with the specified type * @see ElfSectionHeader */ @@ -1548,7 +1530,7 @@ public class ElfHeader implements StructConverter, Writeable { /** * Returns the program headers with the specified type. * The array could be zero-length, but will not be null. - * @param type + * @param type program header type * @return the program headers with the specified type * @see ElfProgramHeader */ @@ -1671,6 +1653,7 @@ public class ElfHeader implements StructConverter, Writeable { /** * Returns the string table associated to the specified section header. * Or, null if one does not exist. + * @param section section whose associated string table is requested * @return the string table associated to the specified section header */ public ElfStringTable getStringTable(ElfSectionHeader section) { @@ -1701,6 +1684,7 @@ public class ElfHeader implements StructConverter, Writeable { /** * Returns the symbol table associated to the specified section header. * Or, null if one does not exist. + * @param symbolTableSection symbol table section header * @return the symbol table associated to the specified section header */ public ElfSymbolTable getSymbolTable(ElfSectionHeader symbolTableSection) { diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/elf/ElfProgramHeader.java b/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/elf/ElfProgramHeader.java index 292bbf2089..709e6531a7 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/elf/ElfProgramHeader.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/elf/ElfProgramHeader.java @@ -21,9 +21,11 @@ import java.util.HashMap; import ghidra.app.util.bin.BinaryReader; import ghidra.app.util.bin.StructConverter; -import ghidra.app.util.bin.format.*; +import ghidra.app.util.bin.format.MemoryLoadable; +import ghidra.app.util.bin.format.Writeable; import ghidra.program.model.data.*; -import ghidra.util.*; +import ghidra.util.DataConverter; +import ghidra.util.StringUtilities; /** * An executable or shared object file's program header table is an @@ -76,36 +78,22 @@ public class ElfProgramHeader private long p_memsz; private long p_align; - private FactoryBundledWithBinaryReader reader; + private BinaryReader reader; - static ElfProgramHeader createElfProgramHeader(FactoryBundledWithBinaryReader reader, - ElfHeader header) throws IOException { - ElfProgramHeader elfProgramHeader = - (ElfProgramHeader) reader.getFactory().create(ElfProgramHeader.class); - elfProgramHeader.initElfProgramHeader(reader, header); - return elfProgramHeader; - } - - /** - * DO NOT USE THIS CONSTRUCTOR, USE create*(GenericFactory ...) FACTORY METHODS INSTEAD. - */ - public ElfProgramHeader() { - } - - protected void initElfProgramHeader(FactoryBundledWithBinaryReader reader, ElfHeader header) + public ElfProgramHeader(BinaryReader reader, ElfHeader header) throws IOException { this.header = header; this.reader = reader; if (header.is32Bit()) { p_type = reader.readNextInt(); - p_offset = reader.readNextInt() & Conv.INT_MASK; - p_vaddr = reader.readNextInt() & Conv.INT_MASK; - p_paddr = reader.readNextInt() & Conv.INT_MASK; - p_filesz = reader.readNextInt() & Conv.INT_MASK; - p_memsz = reader.readNextInt() & Conv.INT_MASK; + p_offset = Integer.toUnsignedLong(reader.readNextInt()); + p_vaddr = Integer.toUnsignedLong(reader.readNextInt()); + p_paddr = Integer.toUnsignedLong(reader.readNextInt()); + p_filesz = Integer.toUnsignedLong(reader.readNextInt()); + p_memsz = Integer.toUnsignedLong(reader.readNextInt()); p_flags = reader.readNextInt(); - p_align = reader.readNextInt() & Conv.INT_MASK; + p_align = Integer.toUnsignedLong(reader.readNextInt()); } else if (header.is64Bit()) { p_type = reader.readNextInt(); @@ -130,6 +118,7 @@ public class ElfProgramHeader /** * Constructs a new program header with the specified type. + * @param header ELF header * @param type the new type of the program header */ public ElfProgramHeader(ElfHeader header, int type) { diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/elf/ElfRelocation.java b/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/elf/ElfRelocation.java index 5bd545a753..ec9c6d1a9a 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/elf/ElfRelocation.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/elf/ElfRelocation.java @@ -16,18 +16,15 @@ package ghidra.app.util.bin.format.elf; import java.io.IOException; +import java.lang.reflect.Constructor; -import generic.continues.GenericFactory; -import ghidra.app.util.bin.ByteArrayConverter; -import ghidra.app.util.bin.StructConverter; -import ghidra.app.util.bin.format.FactoryBundledWithBinaryReader; +import ghidra.app.util.bin.*; import ghidra.app.util.bin.format.elf.extend.ElfLoadAdapter; import ghidra.app.util.bin.format.elf.relocation.ElfRelocationContext; import ghidra.app.util.bin.format.elf.relocation.ElfRelocationHandler; import ghidra.program.model.data.*; import ghidra.util.Conv; import ghidra.util.DataConverter; -import ghidra.util.exception.AssertException; /** * A class to represent the Elf32_Rel and Elf64_Rel data structure. @@ -70,6 +67,11 @@ import ghidra.util.exception.AssertException; * relocation table which only specifies r_offset for each entry. * * + * + * NOTE: instantiation relies on the use of a default constructor which must be + * implemented by any extension. An extension should implement the methods + * {@link #initElfRelocation(BinaryReader, ElfHeader, int, boolean)} and/or + * {@link #initElfRelocation(ElfHeader, int, boolean, long, long, long)}. */ public class ElfRelocation implements ByteArrayConverter, StructConverter { @@ -88,20 +90,18 @@ public class ElfRelocation implements ByteArrayConverter, StructConverter { private int relocationIndex; /** - * GenericFactory construction and initialization method for a ELF relocation entry + * Factory construction and initialization method for a ELF relocation entry * @param reader binary reader positioned at start of relocation entry. * @param elfHeader ELF header * @param relocationIndex index of entry in relocation table * @param withAddend true if if RELA entry with addend, else false * @return ELF relocation object - * @throws IOException + * @throws IOException if an IO or parse error occurs */ - static ElfRelocation createElfRelocation(FactoryBundledWithBinaryReader reader, + static ElfRelocation createElfRelocation(BinaryReader reader, ElfHeader elfHeader, int relocationIndex, boolean withAddend) throws IOException { - - Class elfRelocationClass = getElfRelocationClass(elfHeader); - ElfRelocation elfRelocation = - (ElfRelocation) reader.getFactory().create(elfRelocationClass); + Class elfRelocationClazz = getElfRelocationClass(elfHeader); + ElfRelocation elfRelocation = getInstance(elfRelocationClazz); elfRelocation.initElfRelocation(reader, elfHeader, relocationIndex, withAddend); return elfRelocation; } @@ -109,7 +109,6 @@ public class ElfRelocation implements ByteArrayConverter, StructConverter { /** * GenericFactory construction and initialization method for a ELF representative * relocation entry - * @param reader binary reader positioned at start of relocation entry. * @param elfHeader ELF header * @param relocationIndex index of entry in relocation table * @param withAddend true if if RELA entry with addend, else false @@ -117,23 +116,33 @@ public class ElfRelocation implements ByteArrayConverter, StructConverter { * @param r_info The info value for the entry * @param r_addend The addend for the entry * @return ELF relocation object + * @throws IOException if an IO or parse error occurs */ - static ElfRelocation createElfRelocation(GenericFactory factory, ElfHeader elfHeader, - int relocationIndex, boolean withAddend, long r_offset, long r_info, long r_addend) { - - Class elfRelocationClass = getElfRelocationClass(elfHeader); - ElfRelocation elfRelocation = (ElfRelocation) factory.create(elfRelocationClass); - try { - elfRelocation.initElfRelocation(elfHeader, relocationIndex, withAddend, r_offset, - r_info, r_addend); - } - catch (IOException e) { - // absence of reader should prevent any IOException from occurring - throw new AssertException("unexpected IO error", e); - } + static ElfRelocation createElfRelocation(ElfHeader elfHeader, + int relocationIndex, boolean withAddend, long r_offset, long r_info, long r_addend) + throws IOException { + Class elfRelocationClazz = getElfRelocationClass(elfHeader); + ElfRelocation elfRelocation = getInstance(elfRelocationClazz); + elfRelocation.initElfRelocation(elfHeader, relocationIndex, withAddend, r_offset, r_info, + r_addend); return elfRelocation; } + private static ElfRelocation getInstance(Class elfRelocationClazz) + throws IOException { + try { + Constructor constructor = elfRelocationClazz.getConstructor(); + return constructor.newInstance(); + } + catch (NoSuchMethodException e) { + throw new IOException( + elfRelocationClazz.getName() + " does not provide default constructor"); + } + catch (Exception e) { + throw new IOException(e); + } + } + private static Class getElfRelocationClass(ElfHeader elfHeader) { Class elfRelocationClass = null; ElfLoadAdapter loadAdapter = elfHeader.getLoadAdapter(); @@ -147,8 +156,11 @@ public class ElfRelocation implements ByteArrayConverter, StructConverter { } /** - * DO NOT USE THIS CONSTRUCTOR, USE create*(GenericFactory ...) FACTORY METHODS INSTEAD. - * @see ElfRelocation#createElfRelocation + * Instantiate an uninitialized relocation object. + *

+ * NOTE: This method is intended for use by the various factory methods which should generally + * be used when building-up a relocation table (see {@link #createElfRelocation(BinaryReader, ElfHeader, int, boolean)} + * and {@link #createElfRelocation(ElfHeader, int, boolean, long, long, long)}). */ public ElfRelocation() { } @@ -160,9 +172,9 @@ public class ElfRelocation implements ByteArrayConverter, StructConverter { * @param elfHeader ELF header * @param relocationTableIndex index of relocation within relocation table * @param withAddend true if if RELA entry with addend, else false - * @throws IOException + * @throws IOException if an IO or parse error occurs */ - protected void initElfRelocation(FactoryBundledWithBinaryReader reader, ElfHeader elfHeader, + protected void initElfRelocation(BinaryReader reader, ElfHeader elfHeader, int relocationTableIndex, boolean withAddend) throws IOException { this.is32bit = elfHeader.is32Bit(); this.relocationIndex = relocationTableIndex; @@ -180,7 +192,7 @@ public class ElfRelocation implements ByteArrayConverter, StructConverter { * @param r_offset The offset for the entry * @param r_info The info value for the entry * @param r_addend The addend for the entry - * @throws IOException + * @throws IOException if an IO or parse error occurs */ protected void initElfRelocation(ElfHeader elfHeader, int relocationTableIndex, boolean withAddend, long r_offset, long r_info, long r_addend) throws IOException { @@ -189,10 +201,10 @@ public class ElfRelocation implements ByteArrayConverter, StructConverter { this.hasAddend = withAddend; if (is32bit) { - this.r_offset = r_offset & Conv.INT_MASK; - this.r_info = r_info & Conv.INT_MASK; + this.r_offset = Integer.toUnsignedLong((int) r_offset); + this.r_info = Integer.toUnsignedLong((int) r_info); if (hasAddend) { - this.r_addend = r_addend & Conv.INT_MASK; + this.r_addend = Integer.toUnsignedLong((int) r_addend); } } else { @@ -204,12 +216,12 @@ public class ElfRelocation implements ByteArrayConverter, StructConverter { } } - private void readEntryData(FactoryBundledWithBinaryReader reader) throws IOException { + private void readEntryData(BinaryReader reader) throws IOException { if (is32bit) { - this.r_offset = reader.readNextInt() & Conv.INT_MASK; - this.r_info = reader.readNextInt() & Conv.INT_MASK; + this.r_offset = Integer.toUnsignedLong(reader.readNextInt()); + this.r_info = Integer.toUnsignedLong(reader.readNextInt()); if (hasAddend) { - r_addend = reader.readNextInt() & Conv.INT_MASK; + r_addend = Integer.toUnsignedLong(reader.readNextInt()); } } else { diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/elf/ElfRelocationTable.java b/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/elf/ElfRelocationTable.java index fa8983b3b1..55a1d666fe 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/elf/ElfRelocationTable.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/elf/ElfRelocationTable.java @@ -19,9 +19,8 @@ import java.io.IOException; import java.util.ArrayList; import java.util.List; -import generic.continues.GenericFactory; +import ghidra.app.util.bin.BinaryReader; import ghidra.app.util.bin.ByteArrayConverter; -import ghidra.app.util.bin.format.FactoryBundledWithBinaryReader; import ghidra.app.util.bin.format.dwarf4.LEB128; import ghidra.program.model.data.ArrayDataType; import ghidra.program.model.data.DataType; @@ -50,14 +49,14 @@ public class ElfRelocationTable implements ElfFileSection, ByteArrayConverter { private long entrySize; private boolean addendTypeReloc; - private GenericFactory factory; + private ElfHeader elfHeader; private ElfRelocation[] relocs; /** - * Create an Elf Relocation Table - * @param reader + * Construct an Elf Relocation Table + * @param reader byte provider reader * @param header elf header * @param relocTableSection relocation table section header or null if associated with a dynamic table entry * @param fileOffset relocation table file offset @@ -68,28 +67,9 @@ public class ElfRelocationTable implements ElfFileSection, ByteArrayConverter { * @param symbolTable associated symbol table * @param sectionToBeRelocated or null for dynamic relocation table * @param format table format - * @return Elf relocation table object - * @throws IOException + * @throws IOException if an IO or parse error occurs */ - static ElfRelocationTable createElfRelocationTable(FactoryBundledWithBinaryReader reader, - ElfHeader header, ElfSectionHeader relocTableSection, long fileOffset, long addrOffset, - long length, long entrySize, boolean addendTypeReloc, ElfSymbolTable symbolTable, - ElfSectionHeader sectionToBeRelocated, TableFormat format) throws IOException { - ElfRelocationTable elfRelocationTable = - (ElfRelocationTable) reader.getFactory().create(ElfRelocationTable.class); - elfRelocationTable.initElfRelocationTable(reader, header, relocTableSection, fileOffset, - addrOffset, length, entrySize, addendTypeReloc, symbolTable, sectionToBeRelocated, - format); - return elfRelocationTable; - } - - /** - * DO NOT USE THIS CONSTRUCTOR, USE create*(GenericFactory ...) FACTORY METHODS INSTEAD. - */ - public ElfRelocationTable() { - } - - private void initElfRelocationTable(FactoryBundledWithBinaryReader reader, ElfHeader header, + public ElfRelocationTable(BinaryReader reader, ElfHeader header, ElfSectionHeader relocTableSection, long fileOffset, long addrOffset, long length, long entrySize, boolean addendTypeReloc, ElfSymbolTable symbolTable, ElfSectionHeader sectionToBeRelocated, TableFormat format) throws IOException { @@ -101,7 +81,6 @@ public class ElfRelocationTable implements ElfFileSection, ByteArrayConverter { this.entrySize = entrySize; this.addendTypeReloc = addendTypeReloc; this.elfHeader = header; - this.factory = reader.getFactory(); this.format = format; this.sectionToBeRelocated = sectionToBeRelocated; @@ -127,7 +106,7 @@ public class ElfRelocationTable implements ElfFileSection, ByteArrayConverter { relocList.toArray(relocs); } - private List parseStandardRelocations(FactoryBundledWithBinaryReader reader) + private List parseStandardRelocations(BinaryReader reader) throws IOException { List relocations = new ArrayList<>(); @@ -142,23 +121,23 @@ public class ElfRelocationTable implements ElfFileSection, ByteArrayConverter { return relocations; } - private long readNextRelrEntry(FactoryBundledWithBinaryReader reader) throws IOException { + private long readNextRelrEntry(BinaryReader reader) throws IOException { return entrySize == 8 ? reader.readNextLong() : reader.readNextUnsignedInt(); } - private long addRelrEntry(long offset, List relocList) { - relocList.add(ElfRelocation.createElfRelocation(factory, elfHeader, relocList.size(), + private long addRelrEntry(long offset, List relocList) throws IOException { + relocList.add(ElfRelocation.createElfRelocation(elfHeader, relocList.size(), addendTypeReloc, offset, 0, 0)); return offset + entrySize; } - private long addRelrEntries(long baseOffset, long entry, List relocList) { - + private long addRelrEntries(long baseOffset, long entry, List relocList) + throws IOException { long offset = baseOffset; while (entry != 0) { entry >>>= 1; if ((entry & 1) != 0) { - relocList.add(ElfRelocation.createElfRelocation(factory, elfHeader, + relocList.add(ElfRelocation.createElfRelocation(elfHeader, relocList.size(), addendTypeReloc, offset, 0, 0)); } offset += entrySize; @@ -167,7 +146,7 @@ public class ElfRelocationTable implements ElfFileSection, ByteArrayConverter { return baseOffset + (nBits * entrySize); } - private List parseRelrRelocations(FactoryBundledWithBinaryReader reader) + private List parseRelrRelocations(BinaryReader reader) throws IOException { // NOTE: Current implementation supports an entrySize of 8 or 4. This could be @@ -193,7 +172,7 @@ public class ElfRelocationTable implements ElfFileSection, ByteArrayConverter { return relocList; } - private List parseAndroidRelocations(FactoryBundledWithBinaryReader reader) + private List parseAndroidRelocations(BinaryReader reader) throws IOException { String identifier = reader.readNextAsciiString(4); @@ -258,8 +237,8 @@ public class ElfRelocationTable implements ElfFileSection, ByteArrayConverter { } rAddend = addend; } - relocations.add(ElfRelocation.createElfRelocation(reader.getFactory(), - elfHeader, relocationIndex++, addendTypeReloc, offset, info, rAddend)); + relocations.add(ElfRelocation.createElfRelocation(elfHeader, relocationIndex++, + addendTypeReloc, offset, info, rAddend)); } remainingRelocations -= groupSize; @@ -363,7 +342,7 @@ public class ElfRelocationTable implements ElfFileSection, ByteArrayConverter { } @Override - public DataType toDataType() { + public DataType toDataType() throws IOException { if (format == TableFormat.RELR) { String relrStructureName = "Elf_RelrRelocationTable_" + Long.toHexString(addrOffset); return new ElfRelrRelocationTableDataType(relrStructureName, (int) length, @@ -374,7 +353,7 @@ public class ElfRelocationTable implements ElfFileSection, ByteArrayConverter { } ElfRelocation relocationRepresentative = - ElfRelocation.createElfRelocation(factory, elfHeader, -1, addendTypeReloc, 0, 0, 0); + ElfRelocation.createElfRelocation(elfHeader, -1, addendTypeReloc, 0, 0, 0); DataType relocEntryDataType = relocationRepresentative.toDataType(); return new ArrayDataType(relocEntryDataType, (int) (length / entrySize), (int) entrySize); } diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/elf/ElfSectionHeader.java b/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/elf/ElfSectionHeader.java index bac3a95579..eaf0104300 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/elf/ElfSectionHeader.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/elf/ElfSectionHeader.java @@ -20,11 +20,13 @@ import java.util.HashMap; import ghidra.app.util.bin.BinaryReader; import ghidra.app.util.bin.StructConverter; -import ghidra.app.util.bin.format.*; +import ghidra.app.util.bin.format.MemoryLoadable; +import ghidra.app.util.bin.format.Writeable; import ghidra.program.model.data.*; import ghidra.program.model.mem.MemoryAccessException; import ghidra.program.model.mem.MemoryBlock; -import ghidra.util.*; +import ghidra.util.DataConverter; +import ghidra.util.StringUtilities; /** * A class to represent the Elf32_Shdr data structure. @@ -80,7 +82,7 @@ public class ElfSectionHeader implements StructConverter, Writeable, MemoryLoada private long sh_addralign; private long sh_entsize; - private FactoryBundledWithBinaryReader reader; + private BinaryReader reader; private ElfHeader header; private String name; @@ -88,21 +90,7 @@ public class ElfSectionHeader implements StructConverter, Writeable, MemoryLoada private boolean modified = false; private boolean bytesChanged = false; - static ElfSectionHeader createElfSectionHeader(FactoryBundledWithBinaryReader reader, - ElfHeader header) throws IOException { - ElfSectionHeader elfSectionHeader = - (ElfSectionHeader) reader.getFactory().create(ElfSectionHeader.class); - elfSectionHeader.initElfSectionHeader(reader, header); - return elfSectionHeader; - } - - /** - * DO NOT USE THIS CONSTRUCTOR, USE create*(GenericFactory ...) FACTORY METHODS INSTEAD. - */ - public ElfSectionHeader() { - } - - private void initElfSectionHeader(FactoryBundledWithBinaryReader reader, ElfHeader header) + public ElfSectionHeader(BinaryReader reader, ElfHeader header) throws IOException { this.reader = reader; this.header = header; @@ -111,10 +99,10 @@ public class ElfSectionHeader implements StructConverter, Writeable, MemoryLoada sh_type = reader.readNextInt(); if (header.is32Bit()) { - sh_flags = reader.readNextInt() & Conv.INT_MASK; - sh_addr = reader.readNextInt() & Conv.INT_MASK; - sh_offset = reader.readNextInt() & Conv.INT_MASK; - sh_size = reader.readNextInt() & Conv.INT_MASK; + sh_flags = Integer.toUnsignedLong(reader.readNextInt()); + sh_addr = Integer.toUnsignedLong(reader.readNextInt()); + sh_offset = Integer.toUnsignedLong(reader.readNextInt()); + sh_size = Integer.toUnsignedLong(reader.readNextInt()); } else if (header.is64Bit()) { sh_flags = reader.readNextLong(); @@ -127,8 +115,8 @@ public class ElfSectionHeader implements StructConverter, Writeable, MemoryLoada sh_info = reader.readNextInt(); if (header.is32Bit()) { - sh_addralign = reader.readNextInt() & Conv.INT_MASK; - sh_entsize = reader.readNextInt() & Conv.INT_MASK; + sh_addralign = Integer.toUnsignedLong(reader.readNextInt()); + sh_entsize = Integer.toUnsignedLong(reader.readNextInt()); } else if (header.is64Bit()) { sh_addralign = reader.readNextLong(); @@ -568,7 +556,7 @@ public class ElfSectionHeader implements StructConverter, Writeable, MemoryLoada /** * Sets the name of this section (may get changed due to conflict) - * @param name + * @param name section name */ public void setName(String name) { this.name = name; @@ -631,7 +619,7 @@ public class ElfSectionHeader implements StructConverter, Writeable, MemoryLoada } private void checkSize() { - if (sh_size > (Integer.MAX_VALUE & Conv.INT_MASK)) { + if (sh_size > Integer.toUnsignedLong(Integer.MAX_VALUE)) { throw new UnsupportedOperationException( "ELF Section is too large: 0x" + Long.toHexString(sh_size)); } diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/elf/ElfString.java b/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/elf/ElfString.java deleted file mode 100644 index 0ed76d5c2e..0000000000 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/elf/ElfString.java +++ /dev/null @@ -1,71 +0,0 @@ -/* ### - * IP: GHIDRA - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package ghidra.app.util.bin.format.elf; - -import java.io.IOException; - -import ghidra.app.util.bin.format.FactoryBundledWithBinaryReader; - -public class ElfString { - - /** - * Read an ElfString at the readers current position. ElfString only supports - * null-terminated ASCII strings. - * @param reader reader positioned at start of string - * @param stringOffset string offset from start of string table - * @param header Elf header object - * @return Elf string object - * @throws IOException - */ - public static ElfString createElfString(FactoryBundledWithBinaryReader reader, int stringOffset, - ElfHeader header) throws IOException { - ElfString elfString = (ElfString) reader.getFactory().create(ElfString.class); - elfString.initElfString(reader, stringOffset, header); - return elfString; - } - - private ElfHeader header; - private int stringOffset; - private String string; - - /** - * DO NOT USE THIS CONSTRUCTOR, USE create*(GenericFactory ...) FACTORY METHODS INSTEAD. - */ - public ElfString() { - } - - private void initElfString(FactoryBundledWithBinaryReader reader, int stringOffset, - ElfHeader header) throws IOException { - this.header = header; - this.stringOffset = stringOffset; - this.string = reader.readAsciiString(0); - } - - /** - * @return string object - */ - public String getString() { - return string; - } - - /** - * @return string offset within string table - */ - public int getStringOffset() { - return stringOffset; - } - -} diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/elf/ElfStringTable.java b/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/elf/ElfStringTable.java index 2ed4a2c709..7c72600010 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/elf/ElfStringTable.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/elf/ElfStringTable.java @@ -18,33 +18,11 @@ package ghidra.app.util.bin.format.elf; import java.io.IOException; import ghidra.app.util.bin.BinaryReader; -import ghidra.app.util.bin.format.FactoryBundledWithBinaryReader; import ghidra.program.model.data.DataType; import ghidra.util.exception.DuplicateNameException; public class ElfStringTable implements ElfFileSection { - /** - * Create and parse an Elf string table - * @param reader the binary reader containing the elf string table - * @param header elf header - * @param stringTableSection string table section header or null if associated with a dynamic table entry - * @param fileOffset symbol table file offset - * @param addrOffset memory address of symbol table (should already be adjusted for prelink) - * @param length length of symbol table in bytes of -1 if unknown - * @return Elf string table object - * @throws IOException - */ - public static ElfStringTable createElfStringTable(FactoryBundledWithBinaryReader reader, - ElfHeader header, ElfSectionHeader stringTableSection, long fileOffset, long addrOffset, - long length) throws IOException { - ElfStringTable elfStringTable = - (ElfStringTable) reader.getFactory().create(ElfStringTable.class); - elfStringTable.initElfStringTable(reader, header, stringTableSection, fileOffset, - addrOffset, length); - return elfStringTable; - } - private ElfHeader header; private ElfSectionHeader stringTableSection; // may be null @@ -52,15 +30,16 @@ public class ElfStringTable implements ElfFileSection { private long addrOffset; private long length; - // private LongObjectHashtable stringOffsetMap; - /** - * DO NOT USE THIS CONSTRUCTOR, USE create*(GenericFactory ...) FACTORY METHODS INSTEAD. + * Construct and parse an Elf string table + * @param reader the binary reader containing the elf string table + * @param header elf header + * @param stringTableSection string table section header or null if associated with a dynamic table entry + * @param fileOffset symbol table file offset + * @param addrOffset memory address of symbol table (should already be adjusted for prelink) + * @param length length of symbol table in bytes of -1 if unknown */ - public ElfStringTable() { - } - - private void initElfStringTable(FactoryBundledWithBinaryReader reader, ElfHeader header, + public ElfStringTable(BinaryReader reader, ElfHeader header, ElfSectionHeader stringTableSection, long fileOffset, long addrOffset, long length) { this.header = header; this.stringTableSection = stringTableSection; @@ -71,7 +50,7 @@ public class ElfStringTable implements ElfFileSection { /** * Read string from table at specified relative table offset - * @param reader + * @param reader byte reader * @param stringOffset table relative string offset * @return string or null on error */ diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/elf/ElfSymbol.java b/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/elf/ElfSymbol.java index 16a0468b89..f11d6be757 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/elf/ElfSymbol.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/elf/ElfSymbol.java @@ -17,9 +17,8 @@ package ghidra.app.util.bin.format.elf; import java.io.IOException; +import ghidra.app.util.bin.BinaryReader; import ghidra.app.util.bin.ByteArrayConverter; -import ghidra.app.util.bin.format.FactoryBundledWithBinaryReader; -import ghidra.util.Conv; import ghidra.util.DataConverter; import ghidra.util.exception.NotFoundException; @@ -104,33 +103,9 @@ public class ElfSymbol implements ByteArrayConverter { private String nameAsString; /** - * create an ElfSymbol() + * Creates a new section symbol. * Warning! the routine initSymbolName() must be called on the symbol later * to initialize the string name. This is a performance enhancement. - * - * @param reader to read symbol from - * @param symbolIndex index of the symbol to read - * @param symbolTable symbol table to associate the symbol to - * @param header else header - * @return newly created ElfSymbol - * - * @throws IOException if an issue with reading occurs - */ - public static ElfSymbol createElfSymbol(FactoryBundledWithBinaryReader reader, int symbolIndex, - ElfSymbolTable symbolTable, ElfHeader header) throws IOException { - ElfSymbol elfSymbol = (ElfSymbol) reader.getFactory().create(ElfSymbol.class); - elfSymbol.initElfSymbol(reader, symbolIndex, symbolTable, header); - return elfSymbol; - } - - /** - * DO NOT USE THIS CONSTRUCTOR, USE create*(GenericFactory ...) FACTORY METHODS INSTEAD. - */ - public ElfSymbol() { - } - - /** - * Creates a new section symbol. * @param header the corresponding ELF header * @param sectionAddress the start address of the section * @param sectionHeaderIndex the index of the section in the section header table @@ -147,6 +122,8 @@ public class ElfSymbol implements ByteArrayConverter { /** * Creates a new global function symbol. + * Warning! the routine initSymbolName() must be called on the symbol later + * to initialize the string name. This is a performance enhancement. * @param header the corresponding ELF header * @param name the byte index of the name * @param nameAsString the string name of the section @@ -178,7 +155,17 @@ public class ElfSymbol implements ByteArrayConverter { this.symbolTableIndex = symbolIndex; } - private void initElfSymbol(FactoryBundledWithBinaryReader reader, int symbolIndex, + /** + * Construct a normal ElfSymbol. + * Warning! the routine initSymbolName() must be called on the symbol later + * to initialize the string name. This is a performance enhancement. + * @param reader to read symbol from + * @param symbolIndex index of the symbol to read + * @param symbolTable symbol table to associate the symbol to + * @param header else header + * @throws IOException if an issue with reading occurs + */ + public ElfSymbol(BinaryReader reader, int symbolIndex, ElfSymbolTable symbolTable, ElfHeader header) throws IOException { this.header = header; this.symbolTable = symbolTable; @@ -186,8 +173,8 @@ public class ElfSymbol implements ByteArrayConverter { if (header.is32Bit()) { st_name = reader.readNextInt(); - st_value = reader.readNextInt() & Conv.INT_MASK; - st_size = reader.readNextInt() & Conv.INT_MASK; + st_value = Integer.toUnsignedLong(reader.readNextInt()); + st_size = Integer.toUnsignedLong(reader.readNextInt()); st_info = reader.readNextByte(); st_other = reader.readNextByte(); st_shndx = reader.readNextShort(); @@ -235,7 +222,7 @@ public class ElfSymbol implements ByteArrayConverter { * @param reader to read from * @param stringTable stringTable to initialize symbol name */ - public void initSymbolName(FactoryBundledWithBinaryReader reader, ElfStringTable stringTable) { + public void initSymbolName(BinaryReader reader, ElfStringTable stringTable) { if (nameAsString == null) { nameAsString = stringTable.readString(reader, st_name); } diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/elf/ElfSymbolTable.java b/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/elf/ElfSymbolTable.java index fcb4631af9..a17a70a2cd 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/elf/ElfSymbolTable.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/elf/ElfSymbolTable.java @@ -20,8 +20,8 @@ import java.util.ArrayList; import java.util.List; import java.util.stream.Collectors; +import ghidra.app.util.bin.BinaryReader; import ghidra.app.util.bin.ByteArrayConverter; -import ghidra.app.util.bin.format.FactoryBundledWithBinaryReader; import ghidra.program.model.data.*; import ghidra.util.DataConverter; import ghidra.util.exception.DuplicateNameException; @@ -46,8 +46,8 @@ public class ElfSymbolTable implements ElfFileSection, ByteArrayConverter { private ElfSymbol[] symbols; /** - * Create and parse an Elf symbol table - * @param reader + * Construct and parse an Elf symbol table + * @param reader byte reader * @param header elf header * @param symbolTableSection string table section header or null if associated with a dynamic table entry * @param fileOffset symbol table file offset @@ -56,27 +56,9 @@ public class ElfSymbolTable implements ElfFileSection, ByteArrayConverter { * @param entrySize size of each symbol entry in bytes * @param stringTable associated string table * @param isDynamic true if symbol table is the dynamic symbol table - * @return Elf symbol table object - * @throws IOException + * @throws IOException if an IO or parse error occurs */ - static ElfSymbolTable createElfSymbolTable(FactoryBundledWithBinaryReader reader, - ElfHeader header, ElfSectionHeader symbolTableSection, long fileOffset, long addrOffset, - long length, long entrySize, ElfStringTable stringTable, boolean isDynamic) - throws IOException { - ElfSymbolTable elfSymbolTable = - (ElfSymbolTable) reader.getFactory().create(ElfSymbolTable.class); - elfSymbolTable.initElfSymbolTable(reader, header, symbolTableSection, fileOffset, - addrOffset, length, entrySize, stringTable, isDynamic); - return elfSymbolTable; - } - - /** - * DO NOT USE THIS CONSTRUCTOR, USE create*(GenericFactory ...) FACTORY METHODS INSTEAD. - */ - public ElfSymbolTable() { - } - - private void initElfSymbolTable(FactoryBundledWithBinaryReader reader, ElfHeader header, + public ElfSymbolTable(BinaryReader reader, ElfHeader header, ElfSectionHeader symbolTableSection, long fileOffset, long addrOffset, long length, long entrySize, ElfStringTable stringTable, boolean isDynamic) throws IOException { @@ -103,7 +85,7 @@ public class ElfSymbolTable implements ElfFileSection, ByteArrayConverter { // Reposition reader to start of symbol element since ElfSymbol object // may not consume all symbol element data reader.setPointerIndex(entryPos); - ElfSymbol sym = ElfSymbol.createElfSymbol(reader, i, this, header); + ElfSymbol sym = new ElfSymbol(reader, i, this, header); symbolList.add(sym); entryPos += entrySize; } diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/util/opinion/ElfDataType.java b/Ghidra/Features/Base/src/main/java/ghidra/app/util/opinion/ElfDataType.java index 23b0d837d7..700444eff6 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/util/opinion/ElfDataType.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/util/opinion/ElfDataType.java @@ -15,7 +15,6 @@ */ package ghidra.app.util.opinion; -import generic.continues.RethrowContinuesFactory; import ghidra.app.util.bin.ByteArrayProvider; import ghidra.app.util.bin.format.elf.ElfHeader; import ghidra.docking.settings.Settings; @@ -56,13 +55,13 @@ public class ElfDataType extends FactoryStructureDataType { ByteArrayProvider bap = new ByteArrayProvider(bytes); - ElfHeader elf = ElfHeader.createElfHeader(RethrowContinuesFactory.INSTANCE, bap, null); + ElfHeader elf = new ElfHeader(bap, null); elf.parse(); struct.add(elf.toDataType()); } catch (Exception e) { - + // ignore } } diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/util/opinion/ElfLoader.java b/Ghidra/Features/Base/src/main/java/ghidra/app/util/opinion/ElfLoader.java index 9439010d81..ffb45e43a1 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/util/opinion/ElfLoader.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/util/opinion/ElfLoader.java @@ -18,15 +18,12 @@ package ghidra.app.util.opinion; import java.io.IOException; import java.util.*; -import generic.continues.GenericFactory; -import generic.continues.RethrowContinuesFactory; import ghidra.app.util.Option; import ghidra.app.util.OptionUtils; import ghidra.app.util.bin.ByteProvider; import ghidra.app.util.bin.format.elf.ElfException; import ghidra.app.util.bin.format.elf.ElfHeader; import ghidra.app.util.importer.MessageLog; -import ghidra.app.util.importer.MessageLogContinuesFactory; import ghidra.framework.model.DomainFolder; import ghidra.framework.model.DomainObject; import ghidra.framework.options.Options; @@ -106,8 +103,7 @@ public class ElfLoader extends AbstractLibrarySupportLoader { List loadSpecs = new ArrayList<>(); try { - ElfHeader elf = - ElfHeader.createElfHeader(RethrowContinuesFactory.INSTANCE, provider, null); + ElfHeader elf = new ElfHeader(provider, null); // TODO: Why do we convey image base to loader ? This will be managed by each loader ! List results = QueryOpinionService.query(getName(), elf.getMachineName(), elf.getFlags()); @@ -149,8 +145,7 @@ public class ElfLoader extends AbstractLibrarySupportLoader { throws IOException, CancelledException { try { - GenericFactory factory = MessageLogContinuesFactory.create(log); - ElfHeader elf = ElfHeader.createElfHeader(factory, provider, msg -> log.appendMsg(msg)); + ElfHeader elf = new ElfHeader(provider, msg -> log.appendMsg(msg)); ElfProgramBuilder.loadElf(elf, program, options, log, monitor); } catch (ElfException e) { diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/util/opinion/ElfLoaderOptionsFactory.java b/Ghidra/Features/Base/src/main/java/ghidra/app/util/opinion/ElfLoaderOptionsFactory.java index 0a10df0409..550f8b4995 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/util/opinion/ElfLoaderOptionsFactory.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/util/opinion/ElfLoaderOptionsFactory.java @@ -17,7 +17,6 @@ package ghidra.app.util.opinion; import java.util.List; -import generic.continues.RethrowContinuesFactory; import ghidra.app.util.Option; import ghidra.app.util.OptionUtils; import ghidra.app.util.bin.ByteProvider; @@ -61,7 +60,7 @@ public class ElfLoaderOptionsFactory { options.add(new Option(PERFORM_RELOCATIONS_NAME, PERFORM_RELOCATIONS_DEFAULT, Boolean.class, Loader.COMMAND_LINE_ARG_PREFIX + "-applyRelocations")); - ElfHeader elf = ElfHeader.createElfHeader(RethrowContinuesFactory.INSTANCE, provider, null); + ElfHeader elf = new ElfHeader(provider, null); long imageBase = elf.findImageBase(); if (imageBase == 0 && (elf.isRelocatable() || elf.isSharedObject())) { diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/util/opinion/ElfProgramBuilder.java b/Ghidra/Features/Base/src/main/java/ghidra/app/util/opinion/ElfProgramBuilder.java index 1df8f31230..0d43d28b54 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/util/opinion/ElfProgramBuilder.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/util/opinion/ElfProgramBuilder.java @@ -24,7 +24,6 @@ import java.util.*; import org.apache.commons.compress.compressors.xz.XZCompressorInputStream; import org.apache.commons.lang3.StringUtils; -import generic.continues.GenericFactory; import ghidra.app.cmd.label.SetLabelPrimaryCmd; import ghidra.app.util.MemoryBlockUtils; import ghidra.app.util.Option; @@ -35,7 +34,6 @@ import ghidra.app.util.bin.format.elf.ElfDynamicType.ElfDynamicValueType; import ghidra.app.util.bin.format.elf.extend.ElfLoadAdapter; import ghidra.app.util.bin.format.elf.relocation.*; import ghidra.app.util.importer.MessageLog; -import ghidra.app.util.importer.MessageLogContinuesFactory; import ghidra.framework.options.Options; import ghidra.program.database.mem.FileBytes; import ghidra.program.database.register.AddressRangeObjectMap; @@ -1425,9 +1423,7 @@ class ElfProgramBuilder extends MemorySectionResolver implements ElfLoadHelper { try (ByteProvider debugDataBP = new ObfuscatedFileByteProvider(tmpFile, null, AccessMode.READ)) { - GenericFactory factory = MessageLogContinuesFactory.create(log); - ElfHeader minidebugElf = - ElfHeader.createElfHeader(factory, debugDataBP, null); + ElfHeader minidebugElf = new ElfHeader(debugDataBP, null); minidebugElf.parse(); ElfSymbolTable[] minidebugSymbolTables = minidebugElf.getSymbolTables(); diff --git a/Ghidra/Features/FileFormats/src/main/java/ghidra/file/formats/android/oat/OatFileSystem.java b/Ghidra/Features/FileFormats/src/main/java/ghidra/file/formats/android/oat/OatFileSystem.java index ea37005455..c9251e7c0a 100644 --- a/Ghidra/Features/FileFormats/src/main/java/ghidra/file/formats/android/oat/OatFileSystem.java +++ b/Ghidra/Features/FileFormats/src/main/java/ghidra/file/formats/android/oat/OatFileSystem.java @@ -18,7 +18,6 @@ package ghidra.file.formats.android.oat; import java.io.IOException; import java.util.*; -import generic.continues.RethrowContinuesFactory; import ghidra.app.util.bin.*; import ghidra.app.util.bin.format.elf.*; import ghidra.app.util.importer.MessageLog; @@ -55,8 +54,7 @@ public class OatFileSystem extends GFileSystemBase { ElfConstants.MAGIC_STR.equalsIgnoreCase(e_ident_magic_str); if (magicMatch) { - ElfHeader elf = - ElfHeader.createElfHeader(RethrowContinuesFactory.INSTANCE, provider, null); + ElfHeader elf = new ElfHeader(provider, null); elf.parse(); ElfSymbolTable dynamicSymbolTable = elf.getDynamicSymbolTable(); @@ -98,8 +96,7 @@ public class OatFileSystem extends GFileSystemBase { monitor.setMaximum(10); monitor.setMessage("Parsing ELF header..."); monitor.incrementProgress(1); - ElfHeader elf = - ElfHeader.createElfHeader(RethrowContinuesFactory.INSTANCE, provider, null); + ElfHeader elf = new ElfHeader(provider, null); elf.parse(); monitor.incrementProgress(1); diff --git a/Ghidra/Processors/MIPS/src/main/java/ghidra/app/util/bin/format/elf/relocation/MIPS_Elf64Relocation.java b/Ghidra/Processors/MIPS/src/main/java/ghidra/app/util/bin/format/elf/relocation/MIPS_Elf64Relocation.java index d739a21fd0..c1f3387ec4 100644 --- a/Ghidra/Processors/MIPS/src/main/java/ghidra/app/util/bin/format/elf/relocation/MIPS_Elf64Relocation.java +++ b/Ghidra/Processors/MIPS/src/main/java/ghidra/app/util/bin/format/elf/relocation/MIPS_Elf64Relocation.java @@ -17,7 +17,7 @@ package ghidra.app.util.bin.format.elf.relocation; import java.io.IOException; -import ghidra.app.util.bin.format.FactoryBundledWithBinaryReader; +import ghidra.app.util.bin.BinaryReader; import ghidra.app.util.bin.format.elf.ElfHeader; import ghidra.app.util.bin.format.elf.ElfRelocation; import ghidra.program.model.data.*; @@ -35,14 +35,13 @@ public class MIPS_Elf64Relocation extends ElfRelocation { private int type; // contains upto 3 relocation types (1-byte each) /** - * DO NOT USE THIS CONSTRUCTOR, USE create*(GenericFactory ...) FACTORY METHODS INSTEAD. - * @see ElfRelocation#createElfRelocation + * Construction an uninitialized relocation instance */ public MIPS_Elf64Relocation() { } @Override - protected void initElfRelocation(FactoryBundledWithBinaryReader reader, ElfHeader elfHeader, + protected void initElfRelocation(BinaryReader reader, ElfHeader elfHeader, int relocationTableIndex, boolean withAddend) throws IOException { super.initElfRelocation(reader, elfHeader, relocationTableIndex, withAddend); long info = getRelocationInfo();