mirror of
https://github.com/NationalSecurityAgency/ghidra.git
synced 2025-10-05 02:39:44 +02:00
Merge remote-tracking branch 'origin/GP-348_ghidra1_ElfRelrRelocations' into Ghidra_9.2
This commit is contained in:
commit
149407a682
15 changed files with 371 additions and 46 deletions
|
@ -414,7 +414,14 @@ public class ElfBinaryAnalysisCommand extends FlatProgramAPI
|
|||
// elf.getSection(relocationTable.getFileOffset()); // may be null
|
||||
Address relocationTableAddress = addr(relocationTable.getFileOffset());
|
||||
try {
|
||||
createData(relocationTableAddress, relocationTable.toDataType());
|
||||
DataType dataType = relocationTable.toDataType();
|
||||
if (dataType != null) {
|
||||
createData(relocationTableAddress, dataType);
|
||||
}
|
||||
else {
|
||||
listing.setComment(relocationTableAddress, CodeUnit.PRE_COMMENT,
|
||||
"ELF Relocation Table (markup not yet supported)");
|
||||
}
|
||||
}
|
||||
catch (Exception e) {
|
||||
messages.appendMsg(
|
||||
|
|
|
@ -269,14 +269,6 @@ public class FrameDescriptionEntry extends GccAnalysisClass {
|
|||
|
||||
createAndCommentData(program, addr, encodedDt, comment, CodeUnit.EOL_COMMENT);
|
||||
if (pcBeginAddr.getOffset() != 0x0) {
|
||||
// if the program was moved from a preferred image base, need to adjust
|
||||
// the beginning of frame pointer
|
||||
Long oib = ElfLoader.getElfOriginalImageBase(program);
|
||||
if (oib != null) {
|
||||
long imageBaseOffset = program.getImageBase().getOffset() - oib;
|
||||
pcBeginAddr = pcBeginAddr.add(imageBaseOffset);
|
||||
}
|
||||
|
||||
program.getReferenceManager().addMemoryReference(addr, pcBeginAddr, RefType.DATA,
|
||||
SourceType.ANALYSIS, 0);
|
||||
}
|
||||
|
|
|
@ -18,6 +18,7 @@ package ghidra.app.util.bin.format.elf;
|
|||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import ghidra.util.Msg;
|
||||
import ghidra.util.StringUtilities;
|
||||
import ghidra.util.exception.DuplicateNameException;
|
||||
|
||||
|
@ -94,6 +95,15 @@ public class ElfDynamicType {
|
|||
public static ElfDynamicType DT_FLAGS = addDefaultDynamicType(30, "DT_FLAGS",
|
||||
"Flags for the object being loaded", ElfDynamicValueType.VALUE);
|
||||
|
||||
// Experimental RELR relocation support
|
||||
// - see proposal at https://groups.google.com/forum/#!topic/generic-abi/bX460iggiKg
|
||||
public static ElfDynamicType DT_RELRSZ = addDefaultDynamicType(35, "DT_RELRSZ",
|
||||
"Total size of Relr relocs", ElfDynamicValueType.VALUE);
|
||||
public static ElfDynamicType DT_RELR =
|
||||
addDefaultDynamicType(36, "DT_RELR", "Address of Relr relocs", ElfDynamicValueType.ADDRESS);
|
||||
public static ElfDynamicType DT_RELRENT = addDefaultDynamicType(37, "DT_RELRENT",
|
||||
"Size of Relr relocation entry", ElfDynamicValueType.VALUE);
|
||||
|
||||
public static final int DF_ORIGIN = 0x1; // $ORIGIN processing required
|
||||
public static final int DF_SYMBOLIC = 0x2; // Symbolic symbol resolution required
|
||||
public static final int DF_TEXTREL = 0x4; // Text relocations exist
|
||||
|
@ -114,12 +124,18 @@ public class ElfDynamicType {
|
|||
"DT_ANDROID_REL", "Address of Rel relocs", ElfDynamicValueType.ADDRESS);
|
||||
public static ElfDynamicType DT_ANDROID_RELSZ = addDefaultDynamicType(0x60000010,
|
||||
"DT_ANDROID_RELSZ", "Total size of Rel relocs", ElfDynamicValueType.VALUE);
|
||||
|
||||
public static ElfDynamicType DT_ANDROID_RELA = addDefaultDynamicType(0x60000011,
|
||||
"DT_ANDROID_RELA", "Address of Rela relocs", ElfDynamicValueType.ADDRESS);
|
||||
public static ElfDynamicType DT_ANDROID_RELASZ = addDefaultDynamicType(0x60000012,
|
||||
"DT_ANDROID_RELASZ", "Total size of Rela relocs", ElfDynamicValueType.VALUE);
|
||||
|
||||
public static ElfDynamicType DT_ANDROID_RELR = addDefaultDynamicType(0x6FFFE000,
|
||||
"DT_ANDROID_RELR", "Address of Relr relocs", ElfDynamicValueType.ADDRESS);
|
||||
public static ElfDynamicType DT_ANDROID_RELRSZ = addDefaultDynamicType(0x6FFFE001,
|
||||
"DT_ANDROID_RELRSZ", "Total size of Relr relocs", ElfDynamicValueType.VALUE);
|
||||
public static ElfDynamicType DT_ANDROID_RELRENT = addDefaultDynamicType(0x6FFFE003,
|
||||
"DT_ANDROID_RELRENT", "Size of Relr relocation entry", ElfDynamicValueType.VALUE);
|
||||
|
||||
// Value Range (??): 0x6ffffd00 - 0x6ffffdff
|
||||
|
||||
public static ElfDynamicType DT_GNU_PRELINKED = addDefaultDynamicType(0x6ffffdf5,
|
||||
|
@ -218,7 +234,9 @@ public class ElfDynamicType {
|
|||
return type;
|
||||
}
|
||||
catch (DuplicateNameException e) {
|
||||
throw new RuntimeException("ElfDynamicType initialization error", e);
|
||||
// Make sure error is properly logged during static initialization
|
||||
Msg.error(ElfDynamicType.class, "ElfDynamicType initialization error", e);
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -372,6 +372,12 @@ public class ElfHeader implements StructConverter, Writeable {
|
|||
parseDynamicRelocTable(relocationTableList, ElfDynamicType.DT_ANDROID_RELA, null,
|
||||
ElfDynamicType.DT_ANDROID_RELASZ, true);
|
||||
|
||||
parseDynamicRelocTable(relocationTableList, ElfDynamicType.DT_RELR,
|
||||
ElfDynamicType.DT_RELRENT, ElfDynamicType.DT_RELRSZ, false);
|
||||
|
||||
parseDynamicRelocTable(relocationTableList, ElfDynamicType.DT_ANDROID_RELR,
|
||||
ElfDynamicType.DT_ANDROID_RELRENT, ElfDynamicType.DT_ANDROID_RELRSZ, false);
|
||||
|
||||
parseJMPRelocTable(relocationTableList);
|
||||
|
||||
// In general the above dynamic relocation tables should cover most cases, we will
|
||||
|
@ -390,8 +396,10 @@ public class ElfHeader implements StructConverter, Writeable {
|
|||
int sectionHeaderType = section.getType();
|
||||
if (sectionHeaderType == ElfSectionHeaderConstants.SHT_REL ||
|
||||
sectionHeaderType == ElfSectionHeaderConstants.SHT_RELA ||
|
||||
sectionHeaderType == ElfSectionHeaderConstants.SHT_RELR ||
|
||||
sectionHeaderType == ElfSectionHeaderConstants.SHT_ANDROID_REL ||
|
||||
sectionHeaderType == ElfSectionHeaderConstants.SHT_ANDROID_RELA) {
|
||||
sectionHeaderType == ElfSectionHeaderConstants.SHT_ANDROID_RELA ||
|
||||
sectionHeaderType == ElfSectionHeaderConstants.SHT_ANDROID_RELR) {
|
||||
|
||||
for (ElfRelocationTable relocTable : relocationTableList) {
|
||||
if (relocTable.getFileOffset() == section.getOffset()) {
|
||||
|
@ -440,6 +448,10 @@ public class ElfHeader implements StructConverter, Writeable {
|
|||
sectionHeaderType == ElfSectionHeaderConstants.SHT_ANDROID_RELA) {
|
||||
format = TableFormat.ANDROID;
|
||||
}
|
||||
else if (sectionHeaderType == ElfSectionHeaderConstants.SHT_RELR ||
|
||||
sectionHeaderType == ElfSectionHeaderConstants.SHT_ANDROID_RELR) {
|
||||
format = TableFormat.RELR;
|
||||
}
|
||||
|
||||
ElfRelocationTable relocTable = ElfRelocationTable.createElfRelocationTable(reader,
|
||||
this, section, section.getOffset(), section.getAddress(), section.getSize(),
|
||||
|
@ -527,6 +539,10 @@ public class ElfHeader implements StructConverter, Writeable {
|
|||
relocTableAddrType == ElfDynamicType.DT_ANDROID_RELA) {
|
||||
format = TableFormat.ANDROID;
|
||||
}
|
||||
else if (relocTableAddrType == ElfDynamicType.DT_RELR ||
|
||||
relocTableAddrType == ElfDynamicType.DT_ANDROID_RELR) {
|
||||
format = TableFormat.RELR;
|
||||
}
|
||||
|
||||
ElfRelocationTable relocTable = ElfRelocationTable.createElfRelocationTable(reader,
|
||||
this, null, relocTableOffset, relocTableAddr, tableSize, tableEntrySize,
|
||||
|
|
|
@ -22,6 +22,8 @@ import ghidra.app.util.bin.ByteArrayConverter;
|
|||
import ghidra.app.util.bin.StructConverter;
|
||||
import ghidra.app.util.bin.format.FactoryBundledWithBinaryReader;
|
||||
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;
|
||||
|
@ -38,29 +40,34 @@ import ghidra.util.exception.AssertException;
|
|||
*
|
||||
* REL entry:
|
||||
*
|
||||
* typedef struct {
|
||||
* Elf32_Addr r_offset;
|
||||
* Elf32_Word r_info;
|
||||
* } Elf32_Rel;
|
||||
* typedef struct {
|
||||
* Elf32_Addr r_offset;
|
||||
* Elf32_Word r_info;
|
||||
* } Elf32_Rel;
|
||||
*
|
||||
* typedef struct {
|
||||
* Elf64_Addr r_offset;
|
||||
* Elf64_Xword r_info;
|
||||
* } Elf64_Rel;
|
||||
* typedef struct {
|
||||
* Elf64_Addr r_offset;
|
||||
* Elf64_Xword r_info;
|
||||
* } Elf64_Rel;
|
||||
*
|
||||
* RELA entry with addend:
|
||||
*
|
||||
* * typedef struct {
|
||||
* Elf32_Addr r_offset;
|
||||
* Elf32_Word r_info;
|
||||
* Elf32_Sword r_addend;
|
||||
* } Elf32_Rela;
|
||||
* typedef struct {
|
||||
* Elf32_Addr r_offset;
|
||||
* Elf32_Word r_info;
|
||||
* Elf32_Sword r_addend;
|
||||
* } Elf32_Rela;
|
||||
*
|
||||
* typedef struct {
|
||||
* Elf64_Addr r_offset; //Address
|
||||
* Elf64_Xword r_info; //Relocation type and symbol index
|
||||
* Elf64_Sxword r_addend; //Addend
|
||||
* } Elf64_Rela;
|
||||
* typedef struct {
|
||||
* Elf64_Addr r_offset; //Address
|
||||
* Elf64_Xword r_info; //Relocation type and symbol index
|
||||
* Elf64_Sxword r_addend; //Addend
|
||||
* } Elf64_Rela;
|
||||
*
|
||||
* RELR entry (see SHT_RELR, DT_RELR):
|
||||
* NOTE: Relocation type is data <i>relative</i> and must be specified by appropriate relocation handler
|
||||
* (see {@link ElfRelocationHandler#getRelrRelocationType()}) since it is not contained within the
|
||||
* relocation table which only specifies <i>r_offset</i> for each entry.
|
||||
*
|
||||
* </pre>
|
||||
*/
|
||||
|
@ -261,6 +268,8 @@ public class ElfRelocation implements ByteArrayConverter, StructConverter {
|
|||
|
||||
/**
|
||||
* Returns the symbol index where the relocation must be made.
|
||||
* A value of 0 is generally returned when no symbol is relavent
|
||||
* to the relocation.
|
||||
* @return the symbol index
|
||||
*/
|
||||
public int getSymbolIndex() {
|
||||
|
@ -269,13 +278,28 @@ public class ElfRelocation implements ByteArrayConverter, StructConverter {
|
|||
|
||||
/**
|
||||
* The type of relocation to apply.
|
||||
* NOTE: Relocation types are processor-specific.
|
||||
* NOTE 1: Relocation types are processor-specific (see {@link ElfRelocationHandler}).
|
||||
* NOTE 2: A type of 0 is returned by default for RELR relocations and must be updated
|
||||
* during relocation processing (see {@link #setType(long)}). The appropriate RELR
|
||||
* relocation type can be obtained from the appropriate
|
||||
* {@link ElfRelocationHandler#getRelrRelocationType()} or
|
||||
* {@link ElfRelocationContext#getRelrRelocationType()} if available.
|
||||
* @return type of relocation to apply
|
||||
*/
|
||||
public int getType() {
|
||||
return (int) (is32bit ? (r_info & Conv.BYTE_MASK) : (r_info & Conv.INT_MASK));
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the relocation type associated with this relocation.
|
||||
* Updating the relocation type is required for RELR relocations.
|
||||
* @param type relocation type to be applied
|
||||
*/
|
||||
public void setType(long type) {
|
||||
long mask = is32bit ? Conv.BYTE_MASK : Conv.INT_MASK;
|
||||
r_info = (r_info & ~mask) + (type & mask);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the r_info relocation entry field value
|
||||
* @return r_info value
|
||||
|
@ -364,4 +388,5 @@ public class ElfRelocation implements ByteArrayConverter, StructConverter {
|
|||
}
|
||||
return is32bit ? 8 : 16;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -34,7 +34,7 @@ import ghidra.util.Msg;
|
|||
public class ElfRelocationTable implements ElfFileSection, ByteArrayConverter {
|
||||
|
||||
public enum TableFormat {
|
||||
DEFAULT, ANDROID;
|
||||
DEFAULT, ANDROID, RELR;
|
||||
}
|
||||
|
||||
private TableFormat format;
|
||||
|
@ -111,7 +111,10 @@ public class ElfRelocationTable implements ElfFileSection, ByteArrayConverter {
|
|||
reader.setPointerIndex(fileOffset);
|
||||
|
||||
List<ElfRelocation> relocList;
|
||||
if (format == TableFormat.ANDROID) {
|
||||
if (format == TableFormat.RELR) {
|
||||
relocList = parseRelrRelocations(reader);
|
||||
}
|
||||
else if (format == TableFormat.ANDROID) {
|
||||
relocList = parseAndroidRelocations(reader);
|
||||
}
|
||||
else {
|
||||
|
@ -139,6 +142,57 @@ public class ElfRelocationTable implements ElfFileSection, ByteArrayConverter {
|
|||
return relocations;
|
||||
}
|
||||
|
||||
private long readNextRelrEntry(FactoryBundledWithBinaryReader reader) throws IOException {
|
||||
return entrySize == 8 ? reader.readNextLong() : reader.readNextUnsignedInt();
|
||||
}
|
||||
|
||||
private long addRelrEntry(long offset, List<ElfRelocation> relocList) {
|
||||
relocList.add(ElfRelocation.createElfRelocation(factory, elfHeader, relocList.size(),
|
||||
addendTypeReloc, offset, 0, 0));
|
||||
return offset + entrySize;
|
||||
}
|
||||
|
||||
private long addRelrEntries(long baseOffset, long entry, List<ElfRelocation> relocList) {
|
||||
|
||||
long offset = baseOffset;
|
||||
while (entry != 0) {
|
||||
entry >>>= 1;
|
||||
if ((entry & 1) != 0) {
|
||||
relocList.add(ElfRelocation.createElfRelocation(factory, elfHeader,
|
||||
relocList.size(), addendTypeReloc, offset, 0, 0));
|
||||
}
|
||||
offset += entrySize;
|
||||
}
|
||||
long nBits = (entrySize * 8) - 1;
|
||||
return baseOffset + (nBits * entrySize);
|
||||
}
|
||||
|
||||
private List<ElfRelocation> parseRelrRelocations(FactoryBundledWithBinaryReader reader)
|
||||
throws IOException {
|
||||
|
||||
// NOTE: Current implementation supports an entrySize of 8 or 4. This could be
|
||||
// made more flexable if needed (applies to ElfRelrRelocationTableDataType as well)
|
||||
|
||||
List<ElfRelocation> relocList = new ArrayList<>();
|
||||
long remaining = length; // limit to number of bytes specified for RELR table
|
||||
|
||||
long offset = readNextRelrEntry(reader);
|
||||
offset = addRelrEntry(offset, relocList);
|
||||
remaining -= entrySize;
|
||||
|
||||
while (remaining > 0) {
|
||||
long nextValue = readNextRelrEntry(reader);
|
||||
if ((nextValue & 1) == 1) {
|
||||
offset = addRelrEntries(offset, nextValue, relocList);
|
||||
}
|
||||
else {
|
||||
offset = addRelrEntry(nextValue, relocList);
|
||||
}
|
||||
remaining -= entrySize;
|
||||
}
|
||||
return relocList;
|
||||
}
|
||||
|
||||
private List<ElfRelocation> parseAndroidRelocations(FactoryBundledWithBinaryReader reader)
|
||||
throws IOException {
|
||||
|
||||
|
@ -288,6 +342,10 @@ public class ElfRelocationTable implements ElfFileSection, ByteArrayConverter {
|
|||
return relocTableSection;
|
||||
}
|
||||
|
||||
public boolean isRelrTable() {
|
||||
return format == TableFormat.RELR;
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getFileOffset() {
|
||||
return fileOffset;
|
||||
|
@ -300,7 +358,12 @@ public class ElfRelocationTable implements ElfFileSection, ByteArrayConverter {
|
|||
|
||||
@Override
|
||||
public DataType toDataType() {
|
||||
if (format == TableFormat.ANDROID) {
|
||||
if (format == TableFormat.RELR) {
|
||||
String relrStructureName = "Elf_RelrRelocationTable_" + Long.toHexString(addrOffset);
|
||||
return new ElfRelrRelocationTableDataType(relrStructureName, (int) length,
|
||||
(int) entrySize);
|
||||
}
|
||||
else if (format == TableFormat.ANDROID) {
|
||||
return new AndroidElfRelocationTableDataType();
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,117 @@
|
|||
/* ###
|
||||
* 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 ghidra.program.model.data.*;
|
||||
import ghidra.program.model.mem.MemBuffer;
|
||||
import ghidra.program.model.mem.MemoryAccessException;
|
||||
import ghidra.util.exception.DuplicateNameException;
|
||||
|
||||
/**
|
||||
* <code>ElfRelrRelocationTableDataType</code> is a Factory datatype which defines a markup
|
||||
* structure corresponding to a specified ELF REL relocation table. The REL entry size and
|
||||
* total length in bytes is required when interpreting a RELR table.
|
||||
*/
|
||||
class ElfRelrRelocationTableDataType extends FactoryStructureDataType {
|
||||
|
||||
private int length;
|
||||
private int entrySize;
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
* @param structName structure name for resulting structure
|
||||
* @param length total length of RELR table in bytes
|
||||
* @param entrySize RELR entry size. This size also generally corresponds to the
|
||||
* size if a stored pointer.
|
||||
*/
|
||||
ElfRelrRelocationTableDataType(String structName, int length, int entrySize) {
|
||||
this(structName, length, entrySize, null);
|
||||
}
|
||||
|
||||
private ElfRelrRelocationTableDataType(String structName, int length, int entrySize,
|
||||
DataTypeManager dtm) {
|
||||
super(structName, dtm);
|
||||
this.length = length;
|
||||
this.entrySize = entrySize;
|
||||
}
|
||||
|
||||
@Override
|
||||
public DataType clone(DataTypeManager dtm) {
|
||||
if (dtm == dataMgr) {
|
||||
return this;
|
||||
}
|
||||
return new ElfRelrRelocationTableDataType(getName(), length, entrySize, dtm);
|
||||
}
|
||||
|
||||
private long readNextRelrEntry(MemBuffer buf, int bufOffset) throws MemoryAccessException {
|
||||
return entrySize == 8 ? buf.getLong(bufOffset) : buf.getUnsignedInt(bufOffset);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void populateDynamicStructure(MemBuffer buf, Structure struct) {
|
||||
|
||||
DataType entryDataType = entrySize == 8 ? QWordDataType.dataType : DWordDataType.dataType;
|
||||
|
||||
int bufOffset = 0;
|
||||
int remaining = length; // limit to number of bytes specified for RELR table
|
||||
int index = 0; // relr base index
|
||||
|
||||
struct.add(entryDataType, "r_relr_base_" + (++index), null);
|
||||
bufOffset += entrySize;
|
||||
remaining -= entrySize;
|
||||
|
||||
int bitMaskCount = 0;
|
||||
|
||||
try {
|
||||
while (remaining > 0) {
|
||||
long nextValue = readNextRelrEntry(buf, bufOffset);
|
||||
if ((nextValue & 1) == 1) {
|
||||
++bitMaskCount;
|
||||
}
|
||||
else {
|
||||
if (bitMaskCount != 0) {
|
||||
DataType maskArray = new ArrayDataType(entryDataType, bitMaskCount, entrySize);
|
||||
struct.add(maskArray, "r_relr_bits_" + index, null);
|
||||
bitMaskCount = 0;
|
||||
}
|
||||
struct.add(entryDataType, "r_relr_base_" + (++index), null);
|
||||
}
|
||||
bufOffset += entrySize;
|
||||
remaining -= entrySize;
|
||||
}
|
||||
|
||||
if (bitMaskCount != 0) {
|
||||
DataType maskArray = new ArrayDataType(entryDataType, bitMaskCount, entrySize);
|
||||
struct.add(maskArray, "r_relr_bits_" + index, null);
|
||||
}
|
||||
}
|
||||
catch (MemoryAccessException | IllegalArgumentException e) {
|
||||
// ignore
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Structure setCategoryPath(Structure struct, MemBuffer buf) {
|
||||
try {
|
||||
struct.setCategoryPath(new CategoryPath("/ELF"));
|
||||
}
|
||||
catch (DuplicateNameException e) {
|
||||
// ignore - will not happen
|
||||
}
|
||||
return struct;
|
||||
}
|
||||
|
||||
}
|
|
@ -108,6 +108,8 @@ public class ElfSectionHeaderConstants {
|
|||
public static final int SHT_GROUP = 17;
|
||||
/**Extended section indeces*/
|
||||
public static final int SHT_SYMTAB_SHNDX = 18;
|
||||
/**Experimental support - see proposal at https://groups.google.com/forum/#!topic/generic-abi/bX460iggiKg */
|
||||
public static final int SHT_RELR = 19;
|
||||
|
||||
// OS Specific Section Types
|
||||
|
||||
|
@ -116,6 +118,9 @@ public class ElfSectionHeaderConstants {
|
|||
/**Android relocation entries with explicit addends*/
|
||||
public static final int SHT_ANDROID_RELA = 0x60000002;
|
||||
|
||||
/**Android's experimental support for SHT_RELR sections (see above) */
|
||||
public static final int SHT_ANDROID_RELR = 0x6fffff00;
|
||||
|
||||
/**Object attributes */
|
||||
public static final int SHT_GNU_ATTRIBUTES = 0x6ffffff5;
|
||||
/**GNU-style hash table */
|
||||
|
|
|
@ -92,6 +92,15 @@ public class ElfRelocationContext {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the RELR relocation type associated with the underlying
|
||||
* relocation handler.
|
||||
* @return RELR relocation type or 0 if not supported
|
||||
*/
|
||||
public long getRelrRelocationType() {
|
||||
return handler != null ? handler.getRelrRelocationType() : 0;
|
||||
}
|
||||
|
||||
private void handleUnsupportedTLSRelocation(ElfRelocation relocation,
|
||||
Address relocationAddress) {
|
||||
long symbolIndex = relocation.getSymbolIndex();
|
||||
|
@ -116,7 +125,7 @@ public class ElfRelocationContext {
|
|||
* @param loadHelper Elf load helper
|
||||
* @param relocationTable Elf relocation table
|
||||
* @param symbolMap Elf symbol placement map
|
||||
* @return relocation context
|
||||
* @return relocation context or null
|
||||
*/
|
||||
public static ElfRelocationContext getRelocationContext(ElfLoadHelper loadHelper,
|
||||
ElfRelocationTable relocationTable, Map<ElfSymbol, Address> symbolMap) {
|
||||
|
|
|
@ -33,12 +33,24 @@ abstract public class ElfRelocationHandler implements ExtensionPoint {
|
|||
|
||||
abstract public boolean canRelocate(ElfHeader elf);
|
||||
|
||||
/**
|
||||
* Get the architecture-specific relative relocation type
|
||||
* which should be applied to RELR relocations. The
|
||||
* default implementation returns 0 which indicates
|
||||
* RELR is unsupported.
|
||||
* @return RELR relocation type
|
||||
*/
|
||||
public int getRelrRelocationType() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Relocation context for a specific Elf image and relocation table. The relocation context
|
||||
* is used to process relocations and manage any data required to process relocations.
|
||||
* @param loadHelper Elf load helper
|
||||
* @param relocationTable Elf relocation table
|
||||
* @param symbolMap Elf symbol placement map
|
||||
* @return relocation context or null if unsupported
|
||||
*/
|
||||
public ElfRelocationContext createRelocationContext(ElfLoadHelper loadHelper,
|
||||
ElfRelocationTable relocationTable, Map<ElfSymbol, Address> symbolMap) {
|
||||
|
@ -80,6 +92,18 @@ abstract public class ElfRelocationHandler implements ExtensionPoint {
|
|||
") Symbol = " + symbolName + " (0x" + Long.toHexString(symbolIndex) + ").");
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate error log entry and bookmark at relocationAddress indicating
|
||||
* an unsupported RELR relocation.
|
||||
* @param program
|
||||
* @param relocationAddress relocation address to be bookmarked
|
||||
*/
|
||||
public static void markAsUnsupportedRelr(Program program, Address relocationAddress) {
|
||||
BookmarkManager bookmarkManager = program.getBookmarkManager();
|
||||
bookmarkManager.setBookmark(relocationAddress, BookmarkType.ERROR,
|
||||
"Unsupported RELR Relocation", "ELF Extension does not specify type");
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate error log entry and bookmark at relocationAddress where
|
||||
* import failed to transition block to initialized while processing relocation.
|
||||
|
|
|
@ -726,6 +726,16 @@ class ElfProgramBuilder extends MemorySectionResolver implements ElfLoadHelper {
|
|||
ElfSymbol[] symbols = relocationTable.getAssociatedSymbolTable().getSymbols();
|
||||
ElfRelocation[] relocs = relocationTable.getRelocations();
|
||||
|
||||
boolean relrTypeUnknown = false;
|
||||
long relrRelocationType = 0;
|
||||
if (relocationTable.isRelrTable() && context != null) {
|
||||
relrRelocationType = context.getRelrRelocationType();
|
||||
if (relrRelocationType == 0) {
|
||||
relrTypeUnknown = true;
|
||||
log("Failed to process RELR relocations - extension does not define RELR type");
|
||||
}
|
||||
}
|
||||
|
||||
for (ElfRelocation reloc : relocs) {
|
||||
|
||||
monitor.checkCanceled();
|
||||
|
@ -746,6 +756,12 @@ class ElfProgramBuilder extends MemorySectionResolver implements ElfLoadHelper {
|
|||
|
||||
byte[] bytes = elf.is64Bit() ? new byte[8] : new byte[4];
|
||||
|
||||
long type = reloc.getType();
|
||||
if (relrRelocationType != 0) {
|
||||
type = relrRelocationType;
|
||||
reloc.setType(relrRelocationType);
|
||||
}
|
||||
|
||||
try {
|
||||
MemoryBlock relocBlock = memory.getBlock(relocAddr);
|
||||
if (relocBlock == null) {
|
||||
|
@ -758,7 +774,7 @@ class ElfProgramBuilder extends MemorySectionResolver implements ElfLoadHelper {
|
|||
catch (Exception e) {
|
||||
Msg.error(this, "Unexpected Exception", e);
|
||||
ElfRelocationHandler.markAsUninitializedMemory(program, relocAddr,
|
||||
reloc.getType(), reloc.getSymbolIndex(), symbolName, log);
|
||||
type, reloc.getSymbolIndex(), symbolName, log);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
@ -766,11 +782,15 @@ class ElfProgramBuilder extends MemorySectionResolver implements ElfLoadHelper {
|
|||
memory.getBytes(relocAddr, bytes);
|
||||
|
||||
if (context != null && context.hasRelocationHandler()) {
|
||||
context.processRelocation(reloc, relocAddr);
|
||||
if (relrTypeUnknown) {
|
||||
ElfRelocationHandler.markAsUnsupportedRelr(program, relocAddr);
|
||||
}
|
||||
else {
|
||||
context.processRelocation(reloc, relocAddr);
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (MemoryAccessException e) {
|
||||
long type = reloc.getType();
|
||||
if (type != 0) { // ignore if type 0 which is always NONE (no relocation performed)
|
||||
log("Unable to perform relocation: Type = " + type + " (0x" +
|
||||
Long.toHexString(type) + ") at " + relocAddr + " (Symbol = " + symbolName +
|
||||
|
@ -956,7 +976,14 @@ class ElfProgramBuilder extends MemorySectionResolver implements ElfLoadHelper {
|
|||
private void markupRelocationTable(Address relocTableAddr, ElfRelocationTable relocTable,
|
||||
TaskMonitor monitor) {
|
||||
try {
|
||||
listing.createData(relocTableAddr, relocTable.toDataType());
|
||||
DataType dataType = relocTable.toDataType();
|
||||
if (dataType != null) {
|
||||
listing.createData(relocTableAddr, dataType);
|
||||
}
|
||||
else {
|
||||
listing.setComment(relocTableAddr, CodeUnit.PRE_COMMENT,
|
||||
"ELF Relocation Table (markup not yet supported)");
|
||||
}
|
||||
}
|
||||
catch (Exception e) {
|
||||
log("Failed to properly markup relocation table: " + getMessage(e));
|
||||
|
|
|
@ -34,11 +34,13 @@ public abstract class FactoryStructureDataType extends BuiltIn implements Factor
|
|||
super(null, name, dtm);
|
||||
}
|
||||
|
||||
@Override
|
||||
public abstract DataType clone(DataTypeManager dtm);
|
||||
|
||||
/**
|
||||
* @see ghidra.program.model.data.DataType#getLength()
|
||||
*/
|
||||
@Override
|
||||
public int getLength() {
|
||||
return -1;
|
||||
}
|
||||
|
@ -46,6 +48,7 @@ public abstract class FactoryStructureDataType extends BuiltIn implements Factor
|
|||
/**
|
||||
* @see ghidra.program.model.data.DataType#getValue(ghidra.program.model.mem.MemBuffer, ghidra.docking.settings.Settings, int)
|
||||
*/
|
||||
@Override
|
||||
public Object getValue(MemBuffer buf, Settings settings, int length) {
|
||||
return null;
|
||||
}
|
||||
|
@ -53,6 +56,7 @@ public abstract class FactoryStructureDataType extends BuiltIn implements Factor
|
|||
/**
|
||||
* @see ghidra.program.model.data.DataType#getRepresentation(ghidra.program.model.mem.MemBuffer, ghidra.docking.settings.Settings, int)
|
||||
*/
|
||||
@Override
|
||||
public String getRepresentation(MemBuffer buf, Settings settings, int length) {
|
||||
return null;
|
||||
}
|
||||
|
@ -60,10 +64,12 @@ public abstract class FactoryStructureDataType extends BuiltIn implements Factor
|
|||
/**
|
||||
* @see ghidra.program.model.data.DataType#getDescription()
|
||||
*/
|
||||
@Override
|
||||
public String getDescription() {
|
||||
return "Dynamic Data Type should not be instantiated directly";
|
||||
}
|
||||
|
||||
@Override
|
||||
public DataType getDataType(MemBuffer buf) {
|
||||
Structure struct = new StructureDataType(getName(), 0);
|
||||
if (buf != null) {
|
||||
|
@ -80,7 +86,7 @@ public abstract class FactoryStructureDataType extends BuiltIn implements Factor
|
|||
* @param buf
|
||||
* @return Returns a new structure with the correct category.
|
||||
*/
|
||||
private Structure setCategoryPath(Structure struct, MemBuffer buf) {
|
||||
protected Structure setCategoryPath(Structure struct, MemBuffer buf) {
|
||||
CategoryPath path = CategoryPath.ROOT;
|
||||
try {
|
||||
path =
|
||||
|
@ -94,8 +100,9 @@ public abstract class FactoryStructureDataType extends BuiltIn implements Factor
|
|||
}
|
||||
|
||||
private void setCategory(DataType dt, CategoryPath path) {
|
||||
if (dt == null)
|
||||
if (dt == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
dt.setCategoryPath(path);
|
||||
|
@ -105,15 +112,15 @@ public abstract class FactoryStructureDataType extends BuiltIn implements Factor
|
|||
if (dt instanceof Structure) {
|
||||
Structure struct = (Structure) dt;
|
||||
DataTypeComponent[] comps = struct.getDefinedComponents();
|
||||
for (int i = 0; i < comps.length; i++) {
|
||||
setCategory(comps[i].getDataType(), path);
|
||||
for (DataTypeComponent comp : comps) {
|
||||
setCategory(comp.getDataType(), path);
|
||||
}
|
||||
}
|
||||
else if (dt instanceof Union) {
|
||||
Union union = (Union) dt;
|
||||
DataTypeComponent[] comps = union.getComponents();
|
||||
for (int i = 0; i < comps.length; i++) {
|
||||
setCategory(comps[i].getDataType(), path);
|
||||
for (DataTypeComponent comp : comps) {
|
||||
setCategory(comp.getDataType(), path);
|
||||
}
|
||||
}
|
||||
else if (dt instanceof TypeDef) {
|
||||
|
|
|
@ -29,6 +29,11 @@ public class AARCH64_ElfRelocationHandler extends ElfRelocationHandler {
|
|||
return elf.e_machine() == ElfConstants.EM_AARCH64;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getRelrRelocationType() {
|
||||
return AARCH64_ElfRelocationConstants.R_AARCH64_RELATIVE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void relocate(ElfRelocationContext elfRelocationContext, ElfRelocation relocation,
|
||||
Address relocationAddress) throws MemoryAccessException, NotFoundException {
|
||||
|
|
|
@ -29,6 +29,11 @@ public class X86_32_ElfRelocationHandler extends ElfRelocationHandler {
|
|||
return elf.e_machine() == ElfConstants.EM_386;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getRelrRelocationType() {
|
||||
return X86_32_ElfRelocationConstants.R_386_RELATIVE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void relocate(ElfRelocationContext elfRelocationContext, ElfRelocation relocation,
|
||||
Address relocationAddress) throws MemoryAccessException, NotFoundException {
|
||||
|
|
|
@ -29,6 +29,11 @@ public class X86_64_ElfRelocationHandler extends ElfRelocationHandler {
|
|||
return elf.e_machine() == ElfConstants.EM_X86_64;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getRelrRelocationType() {
|
||||
return X86_64_ElfRelocationConstants.R_X86_64_RELATIVE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void relocate(ElfRelocationContext elfRelocationContext, ElfRelocation relocation,
|
||||
Address relocationAddress) throws MemoryAccessException, NotFoundException {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue