mirror of
https://github.com/NationalSecurityAgency/ghidra.git
synced 2025-10-05 10:49:34 +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
|
// elf.getSection(relocationTable.getFileOffset()); // may be null
|
||||||
Address relocationTableAddress = addr(relocationTable.getFileOffset());
|
Address relocationTableAddress = addr(relocationTable.getFileOffset());
|
||||||
try {
|
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) {
|
catch (Exception e) {
|
||||||
messages.appendMsg(
|
messages.appendMsg(
|
||||||
|
|
|
@ -269,14 +269,6 @@ public class FrameDescriptionEntry extends GccAnalysisClass {
|
||||||
|
|
||||||
createAndCommentData(program, addr, encodedDt, comment, CodeUnit.EOL_COMMENT);
|
createAndCommentData(program, addr, encodedDt, comment, CodeUnit.EOL_COMMENT);
|
||||||
if (pcBeginAddr.getOffset() != 0x0) {
|
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,
|
program.getReferenceManager().addMemoryReference(addr, pcBeginAddr, RefType.DATA,
|
||||||
SourceType.ANALYSIS, 0);
|
SourceType.ANALYSIS, 0);
|
||||||
}
|
}
|
||||||
|
|
|
@ -18,6 +18,7 @@ package ghidra.app.util.bin.format.elf;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
|
import ghidra.util.Msg;
|
||||||
import ghidra.util.StringUtilities;
|
import ghidra.util.StringUtilities;
|
||||||
import ghidra.util.exception.DuplicateNameException;
|
import ghidra.util.exception.DuplicateNameException;
|
||||||
|
|
||||||
|
@ -94,6 +95,15 @@ public class ElfDynamicType {
|
||||||
public static ElfDynamicType DT_FLAGS = addDefaultDynamicType(30, "DT_FLAGS",
|
public static ElfDynamicType DT_FLAGS = addDefaultDynamicType(30, "DT_FLAGS",
|
||||||
"Flags for the object being loaded", ElfDynamicValueType.VALUE);
|
"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_ORIGIN = 0x1; // $ORIGIN processing required
|
||||||
public static final int DF_SYMBOLIC = 0x2; // Symbolic symbol resolution required
|
public static final int DF_SYMBOLIC = 0x2; // Symbolic symbol resolution required
|
||||||
public static final int DF_TEXTREL = 0x4; // Text relocations exist
|
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);
|
"DT_ANDROID_REL", "Address of Rel relocs", ElfDynamicValueType.ADDRESS);
|
||||||
public static ElfDynamicType DT_ANDROID_RELSZ = addDefaultDynamicType(0x60000010,
|
public static ElfDynamicType DT_ANDROID_RELSZ = addDefaultDynamicType(0x60000010,
|
||||||
"DT_ANDROID_RELSZ", "Total size of Rel relocs", ElfDynamicValueType.VALUE);
|
"DT_ANDROID_RELSZ", "Total size of Rel relocs", ElfDynamicValueType.VALUE);
|
||||||
|
|
||||||
public static ElfDynamicType DT_ANDROID_RELA = addDefaultDynamicType(0x60000011,
|
public static ElfDynamicType DT_ANDROID_RELA = addDefaultDynamicType(0x60000011,
|
||||||
"DT_ANDROID_RELA", "Address of Rela relocs", ElfDynamicValueType.ADDRESS);
|
"DT_ANDROID_RELA", "Address of Rela relocs", ElfDynamicValueType.ADDRESS);
|
||||||
public static ElfDynamicType DT_ANDROID_RELASZ = addDefaultDynamicType(0x60000012,
|
public static ElfDynamicType DT_ANDROID_RELASZ = addDefaultDynamicType(0x60000012,
|
||||||
"DT_ANDROID_RELASZ", "Total size of Rela relocs", ElfDynamicValueType.VALUE);
|
"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
|
// Value Range (??): 0x6ffffd00 - 0x6ffffdff
|
||||||
|
|
||||||
public static ElfDynamicType DT_GNU_PRELINKED = addDefaultDynamicType(0x6ffffdf5,
|
public static ElfDynamicType DT_GNU_PRELINKED = addDefaultDynamicType(0x6ffffdf5,
|
||||||
|
@ -218,7 +234,9 @@ public class ElfDynamicType {
|
||||||
return type;
|
return type;
|
||||||
}
|
}
|
||||||
catch (DuplicateNameException e) {
|
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,
|
parseDynamicRelocTable(relocationTableList, ElfDynamicType.DT_ANDROID_RELA, null,
|
||||||
ElfDynamicType.DT_ANDROID_RELASZ, true);
|
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);
|
parseJMPRelocTable(relocationTableList);
|
||||||
|
|
||||||
// In general the above dynamic relocation tables should cover most cases, we will
|
// 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();
|
int sectionHeaderType = section.getType();
|
||||||
if (sectionHeaderType == ElfSectionHeaderConstants.SHT_REL ||
|
if (sectionHeaderType == ElfSectionHeaderConstants.SHT_REL ||
|
||||||
sectionHeaderType == ElfSectionHeaderConstants.SHT_RELA ||
|
sectionHeaderType == ElfSectionHeaderConstants.SHT_RELA ||
|
||||||
|
sectionHeaderType == ElfSectionHeaderConstants.SHT_RELR ||
|
||||||
sectionHeaderType == ElfSectionHeaderConstants.SHT_ANDROID_REL ||
|
sectionHeaderType == ElfSectionHeaderConstants.SHT_ANDROID_REL ||
|
||||||
sectionHeaderType == ElfSectionHeaderConstants.SHT_ANDROID_RELA) {
|
sectionHeaderType == ElfSectionHeaderConstants.SHT_ANDROID_RELA ||
|
||||||
|
sectionHeaderType == ElfSectionHeaderConstants.SHT_ANDROID_RELR) {
|
||||||
|
|
||||||
for (ElfRelocationTable relocTable : relocationTableList) {
|
for (ElfRelocationTable relocTable : relocationTableList) {
|
||||||
if (relocTable.getFileOffset() == section.getOffset()) {
|
if (relocTable.getFileOffset() == section.getOffset()) {
|
||||||
|
@ -440,6 +448,10 @@ public class ElfHeader implements StructConverter, Writeable {
|
||||||
sectionHeaderType == ElfSectionHeaderConstants.SHT_ANDROID_RELA) {
|
sectionHeaderType == ElfSectionHeaderConstants.SHT_ANDROID_RELA) {
|
||||||
format = TableFormat.ANDROID;
|
format = TableFormat.ANDROID;
|
||||||
}
|
}
|
||||||
|
else if (sectionHeaderType == ElfSectionHeaderConstants.SHT_RELR ||
|
||||||
|
sectionHeaderType == ElfSectionHeaderConstants.SHT_ANDROID_RELR) {
|
||||||
|
format = TableFormat.RELR;
|
||||||
|
}
|
||||||
|
|
||||||
ElfRelocationTable relocTable = ElfRelocationTable.createElfRelocationTable(reader,
|
ElfRelocationTable relocTable = ElfRelocationTable.createElfRelocationTable(reader,
|
||||||
this, section, section.getOffset(), section.getAddress(), section.getSize(),
|
this, section, section.getOffset(), section.getAddress(), section.getSize(),
|
||||||
|
@ -527,6 +539,10 @@ public class ElfHeader implements StructConverter, Writeable {
|
||||||
relocTableAddrType == ElfDynamicType.DT_ANDROID_RELA) {
|
relocTableAddrType == ElfDynamicType.DT_ANDROID_RELA) {
|
||||||
format = TableFormat.ANDROID;
|
format = TableFormat.ANDROID;
|
||||||
}
|
}
|
||||||
|
else if (relocTableAddrType == ElfDynamicType.DT_RELR ||
|
||||||
|
relocTableAddrType == ElfDynamicType.DT_ANDROID_RELR) {
|
||||||
|
format = TableFormat.RELR;
|
||||||
|
}
|
||||||
|
|
||||||
ElfRelocationTable relocTable = ElfRelocationTable.createElfRelocationTable(reader,
|
ElfRelocationTable relocTable = ElfRelocationTable.createElfRelocationTable(reader,
|
||||||
this, null, relocTableOffset, relocTableAddr, tableSize, tableEntrySize,
|
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.StructConverter;
|
||||||
import ghidra.app.util.bin.format.FactoryBundledWithBinaryReader;
|
import ghidra.app.util.bin.format.FactoryBundledWithBinaryReader;
|
||||||
import ghidra.app.util.bin.format.elf.extend.ElfLoadAdapter;
|
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.program.model.data.*;
|
||||||
import ghidra.util.Conv;
|
import ghidra.util.Conv;
|
||||||
import ghidra.util.DataConverter;
|
import ghidra.util.DataConverter;
|
||||||
|
@ -38,29 +40,34 @@ import ghidra.util.exception.AssertException;
|
||||||
*
|
*
|
||||||
* REL entry:
|
* REL entry:
|
||||||
*
|
*
|
||||||
* typedef struct {
|
* typedef struct {
|
||||||
* Elf32_Addr r_offset;
|
* Elf32_Addr r_offset;
|
||||||
* Elf32_Word r_info;
|
* Elf32_Word r_info;
|
||||||
* } Elf32_Rel;
|
* } Elf32_Rel;
|
||||||
*
|
*
|
||||||
* typedef struct {
|
* typedef struct {
|
||||||
* Elf64_Addr r_offset;
|
* Elf64_Addr r_offset;
|
||||||
* Elf64_Xword r_info;
|
* Elf64_Xword r_info;
|
||||||
* } Elf64_Rel;
|
* } Elf64_Rel;
|
||||||
*
|
*
|
||||||
* RELA entry with addend:
|
* RELA entry with addend:
|
||||||
*
|
*
|
||||||
* * typedef struct {
|
* typedef struct {
|
||||||
* Elf32_Addr r_offset;
|
* Elf32_Addr r_offset;
|
||||||
* Elf32_Word r_info;
|
* Elf32_Word r_info;
|
||||||
* Elf32_Sword r_addend;
|
* Elf32_Sword r_addend;
|
||||||
* } Elf32_Rela;
|
* } Elf32_Rela;
|
||||||
*
|
*
|
||||||
* typedef struct {
|
* typedef struct {
|
||||||
* Elf64_Addr r_offset; //Address
|
* Elf64_Addr r_offset; //Address
|
||||||
* Elf64_Xword r_info; //Relocation type and symbol index
|
* Elf64_Xword r_info; //Relocation type and symbol index
|
||||||
* Elf64_Sxword r_addend; //Addend
|
* Elf64_Sxword r_addend; //Addend
|
||||||
* } Elf64_Rela;
|
* } 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>
|
* </pre>
|
||||||
*/
|
*/
|
||||||
|
@ -261,6 +268,8 @@ public class ElfRelocation implements ByteArrayConverter, StructConverter {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the symbol index where the relocation must be made.
|
* 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
|
* @return the symbol index
|
||||||
*/
|
*/
|
||||||
public int getSymbolIndex() {
|
public int getSymbolIndex() {
|
||||||
|
@ -269,13 +278,28 @@ public class ElfRelocation implements ByteArrayConverter, StructConverter {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The type of relocation to apply.
|
* 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
|
* @return type of relocation to apply
|
||||||
*/
|
*/
|
||||||
public int getType() {
|
public int getType() {
|
||||||
return (int) (is32bit ? (r_info & Conv.BYTE_MASK) : (r_info & Conv.INT_MASK));
|
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
|
* Returns the r_info relocation entry field value
|
||||||
* @return r_info value
|
* @return r_info value
|
||||||
|
@ -364,4 +388,5 @@ public class ElfRelocation implements ByteArrayConverter, StructConverter {
|
||||||
}
|
}
|
||||||
return is32bit ? 8 : 16;
|
return is32bit ? 8 : 16;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -34,7 +34,7 @@ import ghidra.util.Msg;
|
||||||
public class ElfRelocationTable implements ElfFileSection, ByteArrayConverter {
|
public class ElfRelocationTable implements ElfFileSection, ByteArrayConverter {
|
||||||
|
|
||||||
public enum TableFormat {
|
public enum TableFormat {
|
||||||
DEFAULT, ANDROID;
|
DEFAULT, ANDROID, RELR;
|
||||||
}
|
}
|
||||||
|
|
||||||
private TableFormat format;
|
private TableFormat format;
|
||||||
|
@ -111,7 +111,10 @@ public class ElfRelocationTable implements ElfFileSection, ByteArrayConverter {
|
||||||
reader.setPointerIndex(fileOffset);
|
reader.setPointerIndex(fileOffset);
|
||||||
|
|
||||||
List<ElfRelocation> relocList;
|
List<ElfRelocation> relocList;
|
||||||
if (format == TableFormat.ANDROID) {
|
if (format == TableFormat.RELR) {
|
||||||
|
relocList = parseRelrRelocations(reader);
|
||||||
|
}
|
||||||
|
else if (format == TableFormat.ANDROID) {
|
||||||
relocList = parseAndroidRelocations(reader);
|
relocList = parseAndroidRelocations(reader);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
@ -139,6 +142,57 @@ public class ElfRelocationTable implements ElfFileSection, ByteArrayConverter {
|
||||||
return relocations;
|
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)
|
private List<ElfRelocation> parseAndroidRelocations(FactoryBundledWithBinaryReader reader)
|
||||||
throws IOException {
|
throws IOException {
|
||||||
|
|
||||||
|
@ -288,6 +342,10 @@ public class ElfRelocationTable implements ElfFileSection, ByteArrayConverter {
|
||||||
return relocTableSection;
|
return relocTableSection;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public boolean isRelrTable() {
|
||||||
|
return format == TableFormat.RELR;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public long getFileOffset() {
|
public long getFileOffset() {
|
||||||
return fileOffset;
|
return fileOffset;
|
||||||
|
@ -300,7 +358,12 @@ public class ElfRelocationTable implements ElfFileSection, ByteArrayConverter {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public DataType toDataType() {
|
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();
|
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;
|
public static final int SHT_GROUP = 17;
|
||||||
/**Extended section indeces*/
|
/**Extended section indeces*/
|
||||||
public static final int SHT_SYMTAB_SHNDX = 18;
|
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
|
// OS Specific Section Types
|
||||||
|
|
||||||
|
@ -116,6 +118,9 @@ public class ElfSectionHeaderConstants {
|
||||||
/**Android relocation entries with explicit addends*/
|
/**Android relocation entries with explicit addends*/
|
||||||
public static final int SHT_ANDROID_RELA = 0x60000002;
|
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 */
|
/**Object attributes */
|
||||||
public static final int SHT_GNU_ATTRIBUTES = 0x6ffffff5;
|
public static final int SHT_GNU_ATTRIBUTES = 0x6ffffff5;
|
||||||
/**GNU-style hash table */
|
/**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,
|
private void handleUnsupportedTLSRelocation(ElfRelocation relocation,
|
||||||
Address relocationAddress) {
|
Address relocationAddress) {
|
||||||
long symbolIndex = relocation.getSymbolIndex();
|
long symbolIndex = relocation.getSymbolIndex();
|
||||||
|
@ -116,7 +125,7 @@ public class ElfRelocationContext {
|
||||||
* @param loadHelper Elf load helper
|
* @param loadHelper Elf load helper
|
||||||
* @param relocationTable Elf relocation table
|
* @param relocationTable Elf relocation table
|
||||||
* @param symbolMap Elf symbol placement map
|
* @param symbolMap Elf symbol placement map
|
||||||
* @return relocation context
|
* @return relocation context or null
|
||||||
*/
|
*/
|
||||||
public static ElfRelocationContext getRelocationContext(ElfLoadHelper loadHelper,
|
public static ElfRelocationContext getRelocationContext(ElfLoadHelper loadHelper,
|
||||||
ElfRelocationTable relocationTable, Map<ElfSymbol, Address> symbolMap) {
|
ElfRelocationTable relocationTable, Map<ElfSymbol, Address> symbolMap) {
|
||||||
|
|
|
@ -33,12 +33,24 @@ abstract public class ElfRelocationHandler implements ExtensionPoint {
|
||||||
|
|
||||||
abstract public boolean canRelocate(ElfHeader elf);
|
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
|
* 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.
|
* is used to process relocations and manage any data required to process relocations.
|
||||||
* @param loadHelper Elf load helper
|
* @param loadHelper Elf load helper
|
||||||
* @param relocationTable Elf relocation table
|
* @param relocationTable Elf relocation table
|
||||||
* @param symbolMap Elf symbol placement map
|
* @param symbolMap Elf symbol placement map
|
||||||
|
* @return relocation context or null if unsupported
|
||||||
*/
|
*/
|
||||||
public ElfRelocationContext createRelocationContext(ElfLoadHelper loadHelper,
|
public ElfRelocationContext createRelocationContext(ElfLoadHelper loadHelper,
|
||||||
ElfRelocationTable relocationTable, Map<ElfSymbol, Address> symbolMap) {
|
ElfRelocationTable relocationTable, Map<ElfSymbol, Address> symbolMap) {
|
||||||
|
@ -80,6 +92,18 @@ abstract public class ElfRelocationHandler implements ExtensionPoint {
|
||||||
") Symbol = " + symbolName + " (0x" + Long.toHexString(symbolIndex) + ").");
|
") 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
|
* Generate error log entry and bookmark at relocationAddress where
|
||||||
* import failed to transition block to initialized while processing relocation.
|
* 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();
|
ElfSymbol[] symbols = relocationTable.getAssociatedSymbolTable().getSymbols();
|
||||||
ElfRelocation[] relocs = relocationTable.getRelocations();
|
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) {
|
for (ElfRelocation reloc : relocs) {
|
||||||
|
|
||||||
monitor.checkCanceled();
|
monitor.checkCanceled();
|
||||||
|
@ -746,6 +756,12 @@ class ElfProgramBuilder extends MemorySectionResolver implements ElfLoadHelper {
|
||||||
|
|
||||||
byte[] bytes = elf.is64Bit() ? new byte[8] : new byte[4];
|
byte[] bytes = elf.is64Bit() ? new byte[8] : new byte[4];
|
||||||
|
|
||||||
|
long type = reloc.getType();
|
||||||
|
if (relrRelocationType != 0) {
|
||||||
|
type = relrRelocationType;
|
||||||
|
reloc.setType(relrRelocationType);
|
||||||
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
MemoryBlock relocBlock = memory.getBlock(relocAddr);
|
MemoryBlock relocBlock = memory.getBlock(relocAddr);
|
||||||
if (relocBlock == null) {
|
if (relocBlock == null) {
|
||||||
|
@ -758,7 +774,7 @@ class ElfProgramBuilder extends MemorySectionResolver implements ElfLoadHelper {
|
||||||
catch (Exception e) {
|
catch (Exception e) {
|
||||||
Msg.error(this, "Unexpected Exception", e);
|
Msg.error(this, "Unexpected Exception", e);
|
||||||
ElfRelocationHandler.markAsUninitializedMemory(program, relocAddr,
|
ElfRelocationHandler.markAsUninitializedMemory(program, relocAddr,
|
||||||
reloc.getType(), reloc.getSymbolIndex(), symbolName, log);
|
type, reloc.getSymbolIndex(), symbolName, log);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -766,11 +782,15 @@ class ElfProgramBuilder extends MemorySectionResolver implements ElfLoadHelper {
|
||||||
memory.getBytes(relocAddr, bytes);
|
memory.getBytes(relocAddr, bytes);
|
||||||
|
|
||||||
if (context != null && context.hasRelocationHandler()) {
|
if (context != null && context.hasRelocationHandler()) {
|
||||||
context.processRelocation(reloc, relocAddr);
|
if (relrTypeUnknown) {
|
||||||
|
ElfRelocationHandler.markAsUnsupportedRelr(program, relocAddr);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
context.processRelocation(reloc, relocAddr);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch (MemoryAccessException e) {
|
catch (MemoryAccessException e) {
|
||||||
long type = reloc.getType();
|
|
||||||
if (type != 0) { // ignore if type 0 which is always NONE (no relocation performed)
|
if (type != 0) { // ignore if type 0 which is always NONE (no relocation performed)
|
||||||
log("Unable to perform relocation: Type = " + type + " (0x" +
|
log("Unable to perform relocation: Type = " + type + " (0x" +
|
||||||
Long.toHexString(type) + ") at " + relocAddr + " (Symbol = " + symbolName +
|
Long.toHexString(type) + ") at " + relocAddr + " (Symbol = " + symbolName +
|
||||||
|
@ -956,7 +976,14 @@ class ElfProgramBuilder extends MemorySectionResolver implements ElfLoadHelper {
|
||||||
private void markupRelocationTable(Address relocTableAddr, ElfRelocationTable relocTable,
|
private void markupRelocationTable(Address relocTableAddr, ElfRelocationTable relocTable,
|
||||||
TaskMonitor monitor) {
|
TaskMonitor monitor) {
|
||||||
try {
|
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) {
|
catch (Exception e) {
|
||||||
log("Failed to properly markup relocation table: " + getMessage(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);
|
super(null, name, dtm);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public abstract DataType clone(DataTypeManager dtm);
|
public abstract DataType clone(DataTypeManager dtm);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @see ghidra.program.model.data.DataType#getLength()
|
* @see ghidra.program.model.data.DataType#getLength()
|
||||||
*/
|
*/
|
||||||
|
@Override
|
||||||
public int getLength() {
|
public int getLength() {
|
||||||
return -1;
|
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)
|
* @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) {
|
public Object getValue(MemBuffer buf, Settings settings, int length) {
|
||||||
return null;
|
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)
|
* @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) {
|
public String getRepresentation(MemBuffer buf, Settings settings, int length) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
@ -60,10 +64,12 @@ public abstract class FactoryStructureDataType extends BuiltIn implements Factor
|
||||||
/**
|
/**
|
||||||
* @see ghidra.program.model.data.DataType#getDescription()
|
* @see ghidra.program.model.data.DataType#getDescription()
|
||||||
*/
|
*/
|
||||||
|
@Override
|
||||||
public String getDescription() {
|
public String getDescription() {
|
||||||
return "Dynamic Data Type should not be instantiated directly";
|
return "Dynamic Data Type should not be instantiated directly";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public DataType getDataType(MemBuffer buf) {
|
public DataType getDataType(MemBuffer buf) {
|
||||||
Structure struct = new StructureDataType(getName(), 0);
|
Structure struct = new StructureDataType(getName(), 0);
|
||||||
if (buf != null) {
|
if (buf != null) {
|
||||||
|
@ -80,7 +86,7 @@ public abstract class FactoryStructureDataType extends BuiltIn implements Factor
|
||||||
* @param buf
|
* @param buf
|
||||||
* @return Returns a new structure with the correct category.
|
* @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;
|
CategoryPath path = CategoryPath.ROOT;
|
||||||
try {
|
try {
|
||||||
path =
|
path =
|
||||||
|
@ -94,8 +100,9 @@ public abstract class FactoryStructureDataType extends BuiltIn implements Factor
|
||||||
}
|
}
|
||||||
|
|
||||||
private void setCategory(DataType dt, CategoryPath path) {
|
private void setCategory(DataType dt, CategoryPath path) {
|
||||||
if (dt == null)
|
if (dt == null) {
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
dt.setCategoryPath(path);
|
dt.setCategoryPath(path);
|
||||||
|
@ -105,15 +112,15 @@ public abstract class FactoryStructureDataType extends BuiltIn implements Factor
|
||||||
if (dt instanceof Structure) {
|
if (dt instanceof Structure) {
|
||||||
Structure struct = (Structure) dt;
|
Structure struct = (Structure) dt;
|
||||||
DataTypeComponent[] comps = struct.getDefinedComponents();
|
DataTypeComponent[] comps = struct.getDefinedComponents();
|
||||||
for (int i = 0; i < comps.length; i++) {
|
for (DataTypeComponent comp : comps) {
|
||||||
setCategory(comps[i].getDataType(), path);
|
setCategory(comp.getDataType(), path);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (dt instanceof Union) {
|
else if (dt instanceof Union) {
|
||||||
Union union = (Union) dt;
|
Union union = (Union) dt;
|
||||||
DataTypeComponent[] comps = union.getComponents();
|
DataTypeComponent[] comps = union.getComponents();
|
||||||
for (int i = 0; i < comps.length; i++) {
|
for (DataTypeComponent comp : comps) {
|
||||||
setCategory(comps[i].getDataType(), path);
|
setCategory(comp.getDataType(), path);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (dt instanceof TypeDef) {
|
else if (dt instanceof TypeDef) {
|
||||||
|
|
|
@ -29,6 +29,11 @@ public class AARCH64_ElfRelocationHandler extends ElfRelocationHandler {
|
||||||
return elf.e_machine() == ElfConstants.EM_AARCH64;
|
return elf.e_machine() == ElfConstants.EM_AARCH64;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getRelrRelocationType() {
|
||||||
|
return AARCH64_ElfRelocationConstants.R_AARCH64_RELATIVE;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void relocate(ElfRelocationContext elfRelocationContext, ElfRelocation relocation,
|
public void relocate(ElfRelocationContext elfRelocationContext, ElfRelocation relocation,
|
||||||
Address relocationAddress) throws MemoryAccessException, NotFoundException {
|
Address relocationAddress) throws MemoryAccessException, NotFoundException {
|
||||||
|
|
|
@ -29,6 +29,11 @@ public class X86_32_ElfRelocationHandler extends ElfRelocationHandler {
|
||||||
return elf.e_machine() == ElfConstants.EM_386;
|
return elf.e_machine() == ElfConstants.EM_386;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getRelrRelocationType() {
|
||||||
|
return X86_32_ElfRelocationConstants.R_386_RELATIVE;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void relocate(ElfRelocationContext elfRelocationContext, ElfRelocation relocation,
|
public void relocate(ElfRelocationContext elfRelocationContext, ElfRelocation relocation,
|
||||||
Address relocationAddress) throws MemoryAccessException, NotFoundException {
|
Address relocationAddress) throws MemoryAccessException, NotFoundException {
|
||||||
|
|
|
@ -29,6 +29,11 @@ public class X86_64_ElfRelocationHandler extends ElfRelocationHandler {
|
||||||
return elf.e_machine() == ElfConstants.EM_X86_64;
|
return elf.e_machine() == ElfConstants.EM_X86_64;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getRelrRelocationType() {
|
||||||
|
return X86_64_ElfRelocationConstants.R_X86_64_RELATIVE;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void relocate(ElfRelocationContext elfRelocationContext, ElfRelocation relocation,
|
public void relocate(ElfRelocationContext elfRelocationContext, ElfRelocation relocation,
|
||||||
Address relocationAddress) throws MemoryAccessException, NotFoundException {
|
Address relocationAddress) throws MemoryAccessException, NotFoundException {
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue