mirror of
https://github.com/NationalSecurityAgency/ghidra.git
synced 2026-05-30 03:37:20 +08:00
Merge remote-tracking branch 'origin/GT-3661_ghidra1_ElfStrippedImprovements'
This commit is contained in:
@@ -42,7 +42,7 @@ public class ElfHeader implements StructConverter, Writeable {
|
|||||||
private static final int MAX_HEADERS_TO_CHECK_FOR_IMAGEBASE = 20;
|
private static final int MAX_HEADERS_TO_CHECK_FOR_IMAGEBASE = 20;
|
||||||
|
|
||||||
private static final int PAD_LENGTH = 7;
|
private static final int PAD_LENGTH = 7;
|
||||||
|
|
||||||
private HashMap<Integer, ElfProgramHeaderType> programHeaderTypeMap;
|
private HashMap<Integer, ElfProgramHeaderType> programHeaderTypeMap;
|
||||||
private HashMap<Integer, ElfSectionHeaderType> sectionHeaderTypeMap;
|
private HashMap<Integer, ElfSectionHeaderType> sectionHeaderTypeMap;
|
||||||
private HashMap<Integer, ElfDynamicType> dynamicTypeMap;
|
private HashMap<Integer, ElfDynamicType> dynamicTypeMap;
|
||||||
@@ -357,8 +357,8 @@ public class ElfHeader implements StructConverter, Writeable {
|
|||||||
try {
|
try {
|
||||||
boolean isRela = (dynamicTable
|
boolean isRela = (dynamicTable
|
||||||
.getDynamicValue(ElfDynamicType.DT_PLTREL) == ElfDynamicType.DT_RELA.value);
|
.getDynamicValue(ElfDynamicType.DT_PLTREL) == ElfDynamicType.DT_RELA.value);
|
||||||
parseDynamicRelocTable(relocationTableList, ElfDynamicType.DT_JMPREL,
|
parseDynamicRelocTable(relocationTableList, ElfDynamicType.DT_JMPREL, null,
|
||||||
null, ElfDynamicType.DT_PLTRELSZ, isRela);
|
ElfDynamicType.DT_PLTRELSZ, isRela);
|
||||||
}
|
}
|
||||||
catch (NotFoundException e) {
|
catch (NotFoundException e) {
|
||||||
// ignore - skip (required dynamic table value is missing)
|
// ignore - skip (required dynamic table value is missing)
|
||||||
@@ -746,8 +746,8 @@ public class ElfHeader implements StructConverter, Writeable {
|
|||||||
" linked to string table section " +
|
" linked to string table section " +
|
||||||
stringTableSectionHeader.getNameAsString());
|
stringTableSectionHeader.getNameAsString());
|
||||||
|
|
||||||
boolean isDyanmic = ElfSectionHeaderConstants.dot_dynsym.equals(
|
boolean isDyanmic = ElfSectionHeaderConstants.dot_dynsym
|
||||||
symbolTableSectionHeader.getNameAsString());
|
.equals(symbolTableSectionHeader.getNameAsString());
|
||||||
|
|
||||||
ElfSymbolTable symbolTable = ElfSymbolTable.createElfSymbolTable(reader, this,
|
ElfSymbolTable symbolTable = ElfSymbolTable.createElfSymbolTable(reader, this,
|
||||||
symbolTableSectionHeader, symbolTableSectionHeader.getOffset(),
|
symbolTableSectionHeader, symbolTableSectionHeader.getOffset(),
|
||||||
@@ -967,6 +967,16 @@ public class ElfHeader implements StructConverter, Writeable {
|
|||||||
return e_ident_class == ElfConstants.ELF_CLASS_64;
|
return e_ident_class == ElfConstants.ELF_CLASS_64;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private long getMinBase(long addr, long minBase) {
|
||||||
|
if (is32Bit()) {
|
||||||
|
addr &= Conv.INT_MASK;
|
||||||
|
}
|
||||||
|
if (Long.compareUnsigned(addr, minBase) < 0) {
|
||||||
|
minBase = addr;
|
||||||
|
}
|
||||||
|
return minBase;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Inspect the Elf image and determine the default image base prior
|
* Inspect the Elf image and determine the default image base prior
|
||||||
* to the {@link #parse()} method being invoked (i.e., only the main Elf
|
* to the {@link #parse()} method being invoked (i.e., only the main Elf
|
||||||
@@ -981,10 +991,9 @@ public class ElfHeader implements StructConverter, Writeable {
|
|||||||
// FIXME! This needs to be consistent with the getImageBase() method
|
// FIXME! This needs to be consistent with the getImageBase() method
|
||||||
// which currently considers prelink.
|
// which currently considers prelink.
|
||||||
|
|
||||||
int n = Math.min(e_phnum, MAX_HEADERS_TO_CHECK_FOR_IMAGEBASE);
|
|
||||||
|
|
||||||
long minBase = -1;
|
long minBase = -1;
|
||||||
|
|
||||||
|
int n = Math.min(e_phnum, MAX_HEADERS_TO_CHECK_FOR_IMAGEBASE);
|
||||||
for (int i = 0; i < n; ++i) {
|
for (int i = 0; i < n; ++i) {
|
||||||
long index = e_phoff + (i * e_phentsize);
|
long index = e_phoff + (i * e_phentsize);
|
||||||
reader.setPointerIndex(index);
|
reader.setPointerIndex(index);
|
||||||
@@ -992,14 +1001,7 @@ public class ElfHeader implements StructConverter, Writeable {
|
|||||||
int headerType = reader.peekNextInt();
|
int headerType = reader.peekNextInt();
|
||||||
if (headerType == ElfProgramHeaderConstants.PT_LOAD) {
|
if (headerType == ElfProgramHeaderConstants.PT_LOAD) {
|
||||||
ElfProgramHeader header = ElfProgramHeader.createElfProgramHeader(reader, this);
|
ElfProgramHeader header = ElfProgramHeader.createElfProgramHeader(reader, this);
|
||||||
long addr = header.getVirtualAddress();
|
minBase = getMinBase(header.getVirtualAddress(), minBase);
|
||||||
// TODO: not sure why we need to mask value
|
|
||||||
if (is32Bit()) {
|
|
||||||
addr &= Conv.INT_MASK;
|
|
||||||
}
|
|
||||||
if (Long.compareUnsigned(addr, minBase) < 0) {
|
|
||||||
minBase = addr;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch (IOException e) {
|
catch (IOException e) {
|
||||||
@@ -1033,15 +1035,9 @@ public class ElfHeader implements StructConverter, Writeable {
|
|||||||
int n = Math.min(programHeaders.length, MAX_HEADERS_TO_CHECK_FOR_IMAGEBASE);
|
int n = Math.min(programHeaders.length, MAX_HEADERS_TO_CHECK_FOR_IMAGEBASE);
|
||||||
long minBase = -1;
|
long minBase = -1;
|
||||||
for (int i = 0; i < n; i++) {
|
for (int i = 0; i < n; i++) {
|
||||||
|
ElfProgramHeader header = programHeaders[i];
|
||||||
if (programHeaders[i].getType() == ElfProgramHeaderConstants.PT_LOAD) {
|
if (programHeaders[i].getType() == ElfProgramHeaderConstants.PT_LOAD) {
|
||||||
long addr = programHeaders[i].getVirtualAddress();
|
minBase = getMinBase(header.getVirtualAddress(), minBase);
|
||||||
// TODO: not sure why we need to mask value
|
|
||||||
if (is32Bit()) {
|
|
||||||
addr &= Conv.INT_MASK;
|
|
||||||
}
|
|
||||||
if (Long.compareUnsigned(addr, minBase) < 0) {
|
|
||||||
minBase = addr;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
elfImageBase = (minBase == -1 ? 0 : minBase);
|
elfImageBase = (minBase == -1 ? 0 : minBase);
|
||||||
@@ -1197,7 +1193,7 @@ public class ElfHeader implements StructConverter, Writeable {
|
|||||||
public short e_machine() {
|
public short e_machine() {
|
||||||
return e_machine;
|
return e_machine;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This member identifies the target operating system and ABI.
|
* This member identifies the target operating system and ABI.
|
||||||
* @return the target operating system and ABI
|
* @return the target operating system and ABI
|
||||||
@@ -1205,7 +1201,7 @@ public class ElfHeader implements StructConverter, Writeable {
|
|||||||
public byte e_ident_osabi() {
|
public byte e_ident_osabi() {
|
||||||
return e_ident_osabi;
|
return e_ident_osabi;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This member identifies the target ABI version.
|
* This member identifies the target ABI version.
|
||||||
* @return the target ABI version
|
* @return the target ABI version
|
||||||
|
|||||||
+6
-6
@@ -339,7 +339,7 @@ public class ElfSectionHeader implements StructConverter, Writeable, MemoryLoada
|
|||||||
return sh_name;
|
return sh_name;
|
||||||
}
|
}
|
||||||
|
|
||||||
void updateName() throws IOException {
|
void updateName() {
|
||||||
if (reader == null) {
|
if (reader == null) {
|
||||||
throw new UnsupportedOperationException("This ElfSectionHeader does not have a reader");
|
throw new UnsupportedOperationException("This ElfSectionHeader does not have a reader");
|
||||||
}
|
}
|
||||||
@@ -349,11 +349,11 @@ public class ElfSectionHeader implements StructConverter, Writeable, MemoryLoada
|
|||||||
name = null;
|
name = null;
|
||||||
try {
|
try {
|
||||||
if (sh_name >= 0 && e_shstrndx >= 0 && e_shstrndx < sections.length) {
|
if (sh_name >= 0 && e_shstrndx >= 0 && e_shstrndx < sections.length) {
|
||||||
ElfSectionHeader stringTableSectionHeader = sections[e_shstrndx];
|
// read section name from string table
|
||||||
if (sh_name < stringTableSectionHeader.sh_size) {
|
long stringTableOffset = sections[e_shstrndx].getOffset();
|
||||||
// read section name from string table
|
if (stringTableOffset >= 0) {
|
||||||
long stringTableOffset = sections[e_shstrndx].getOffset();
|
long offset = stringTableOffset + sh_name;
|
||||||
if (stringTableOffset >= 0) {
|
if (offset < reader.length()) {
|
||||||
name = reader.readAsciiString(stringTableOffset + sh_name);
|
name = reader.readAsciiString(stringTableOffset + sh_name);
|
||||||
if ("".equals(name)) {
|
if ("".equals(name)) {
|
||||||
name = null;
|
name = null;
|
||||||
|
|||||||
+177
-51
@@ -38,6 +38,7 @@ import ghidra.program.database.mem.FileBytes;
|
|||||||
import ghidra.program.database.register.AddressRangeObjectMap;
|
import ghidra.program.database.register.AddressRangeObjectMap;
|
||||||
import ghidra.program.model.address.*;
|
import ghidra.program.model.address.*;
|
||||||
import ghidra.program.model.data.*;
|
import ghidra.program.model.data.*;
|
||||||
|
import ghidra.program.model.data.Array;
|
||||||
import ghidra.program.model.data.DataUtilities.ClearDataMode;
|
import ghidra.program.model.data.DataUtilities.ClearDataMode;
|
||||||
import ghidra.program.model.listing.*;
|
import ghidra.program.model.listing.*;
|
||||||
import ghidra.program.model.mem.*;
|
import ghidra.program.model.mem.*;
|
||||||
@@ -47,15 +48,16 @@ import ghidra.program.model.symbol.*;
|
|||||||
import ghidra.program.model.util.AddressSetPropertyMap;
|
import ghidra.program.model.util.AddressSetPropertyMap;
|
||||||
import ghidra.program.model.util.CodeUnitInsertionException;
|
import ghidra.program.model.util.CodeUnitInsertionException;
|
||||||
import ghidra.util.*;
|
import ghidra.util.*;
|
||||||
|
import ghidra.util.datastruct.*;
|
||||||
import ghidra.util.exception.*;
|
import ghidra.util.exception.*;
|
||||||
import ghidra.util.task.TaskMonitor;
|
import ghidra.util.task.TaskMonitor;
|
||||||
import ghidra.util.task.TaskMonitorAdapter;
|
|
||||||
|
|
||||||
class ElfProgramBuilder extends MemorySectionResolver implements ElfLoadHelper {
|
class ElfProgramBuilder extends MemorySectionResolver implements ElfLoadHelper {
|
||||||
|
|
||||||
public static final String BLOCK_SOURCE_NAME = "Elf Loader";
|
public static final String BLOCK_SOURCE_NAME = "Elf Loader";
|
||||||
|
|
||||||
private static final String SEGMENT_NAME_PREFIX = "segment_";
|
private static final String SEGMENT_NAME_PREFIX = "segment_";
|
||||||
|
private static final String UNALLOCATED_NAME_PREFIX = "unallocated_";
|
||||||
|
|
||||||
private static final String ELF_HEADER_BLOCK_NAME = "_elfHeader";
|
private static final String ELF_HEADER_BLOCK_NAME = "_elfHeader";
|
||||||
private static final String ELF_PROGRAM_HEADERS_BLOCK_NAME = "_elfProgramHeaders";
|
private static final String ELF_PROGRAM_HEADERS_BLOCK_NAME = "_elfProgramHeaders";
|
||||||
@@ -118,10 +120,13 @@ class ElfProgramBuilder extends MemorySectionResolver implements ElfLoadHelper {
|
|||||||
// resolve segment/sections and create program memory blocks
|
// resolve segment/sections and create program memory blocks
|
||||||
ByteProvider byteProvider = elf.getReader().getByteProvider();
|
ByteProvider byteProvider = elf.getReader().getByteProvider();
|
||||||
try (InputStream fileIn = byteProvider.getInputStream(0)) {
|
try (InputStream fileIn = byteProvider.getInputStream(0)) {
|
||||||
fileBytes = program.getMemory().createFileBytes(byteProvider.getName(), 0,
|
fileBytes = program.getMemory()
|
||||||
byteProvider.length(), fileIn, monitor);
|
.createFileBytes(byteProvider.getName(), 0, byteProvider.length(), fileIn,
|
||||||
|
monitor);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
adjustSegmentAndSectionFileAllocations(byteProvider);
|
||||||
|
|
||||||
// process headers and define "section" within memory elfProgramBuilder
|
// process headers and define "section" within memory elfProgramBuilder
|
||||||
processProgramHeaders(monitor);
|
processProgramHeaders(monitor);
|
||||||
processSectionHeaders(monitor);
|
processSectionHeaders(monitor);
|
||||||
@@ -179,20 +184,138 @@ class ElfProgramBuilder extends MemorySectionResolver implements ElfLoadHelper {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void adjustSegmentAndSectionFileAllocations(ByteProvider byteProvider)
|
||||||
|
throws IOException {
|
||||||
|
|
||||||
|
// Identify file ranges not consumed by segments and sections
|
||||||
|
RangeMap fileMap = new RangeMap();
|
||||||
|
fileMap.paintRange(0, byteProvider.length() - 1, -1); // -1: unallocated
|
||||||
|
|
||||||
|
ElfProgramHeader[] segments = elf.getProgramHeaders();
|
||||||
|
ElfSectionHeader[] sections = elf.getSections();
|
||||||
|
|
||||||
|
for (ElfProgramHeader segment : segments) {
|
||||||
|
if (segment.getType() == ElfProgramHeaderConstants.PT_NULL) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
long size = segment.getFileSize();
|
||||||
|
long offset = segment.getOffset();
|
||||||
|
if (size > 0) {
|
||||||
|
fileMap.paintRange(offset, offset + size - 1, -2); // -2: used by segment
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (ElfSectionHeader section : sections) {
|
||||||
|
if (section.getType() == ElfSectionHeaderConstants.SHT_NULL) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
section.getSize();
|
||||||
|
section.getOffset();
|
||||||
|
long size = section.getSize();
|
||||||
|
long offset = section.getOffset();
|
||||||
|
if (size > 0) {
|
||||||
|
fileMap.paintRange(offset, offset + size - 1, -3); // -3: used by section
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Allocate unused file ranges (0: first segment index, segments.length: first section index)
|
||||||
|
|
||||||
|
// Make segment file allocations
|
||||||
|
for (int i = 0; i < segments.length; i++) {
|
||||||
|
ElfProgramHeader segment = segments[i];
|
||||||
|
if (segment.getType() == ElfProgramHeaderConstants.PT_NULL) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
long size = segment.getFileSize();
|
||||||
|
long offset = segment.getOffset();
|
||||||
|
if (size == 0 && offset > 0) {
|
||||||
|
ValueRange valueRange = fileMap.getValueRange(offset);
|
||||||
|
if (valueRange == null || valueRange.getValue() < -1) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (valueRange.getValue() >= 0 && valueRange.getStart() < segment.getOffset()) {
|
||||||
|
ElfProgramHeader otherSegment = segments[valueRange.getValue()];
|
||||||
|
otherSegment.setSize(offset - valueRange.getStart(), 0); // reduce previous segment allocation
|
||||||
|
}
|
||||||
|
segment.setSize(valueRange.getEnd() - offset + 1, 0);
|
||||||
|
fileMap.paintRange(offset, valueRange.getEnd(), i); // allocated to segment
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Make section file allocations
|
||||||
|
int firstSectionIndex = segments.length;
|
||||||
|
for (int i = 0; i < sections.length; i++) {
|
||||||
|
ElfSectionHeader section = sections[i];
|
||||||
|
if (section.getType() == ElfSectionHeaderConstants.SHT_NULL) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
long size = section.getSize();
|
||||||
|
long offset = section.getOffset();
|
||||||
|
if (size == 0 && offset > 0) {
|
||||||
|
ValueRange valueRange = fileMap.getValueRange(offset);
|
||||||
|
if (valueRange == null || valueRange.getValue() < -1) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (valueRange.getValue() >= firstSectionIndex &&
|
||||||
|
valueRange.getStart() < section.getOffset()) {
|
||||||
|
ElfSectionHeader otherSection =
|
||||||
|
sections[valueRange.getValue() - firstSectionIndex];
|
||||||
|
otherSection.setSize(offset - valueRange.getStart()); // reduce previous section allocation
|
||||||
|
}
|
||||||
|
section.setSize(valueRange.getEnd() - offset + 1);
|
||||||
|
Msg.info(this, "Forced section " + i + " size: " + section.getSize());
|
||||||
|
fileMap.paintRange(offset, valueRange.getEnd(), firstSectionIndex + i); // allocated to section
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Ignore header regions which will always be allocated to blocks
|
||||||
|
int elfHeaderSize = elf.toDataType().getLength();
|
||||||
|
fileMap.paintRange(0, elfHeaderSize - 1, -4);
|
||||||
|
int programHeaderSize = elf.e_phentsize() * elf.e_phnum();
|
||||||
|
if (programHeaderSize != 0) {
|
||||||
|
fileMap.paintRange(elf.e_phoff(), elf.e_phoff() + programHeaderSize - 1, -4);
|
||||||
|
}
|
||||||
|
int sectionHeaderSize = elf.e_shentsize() * elf.e_shnum();
|
||||||
|
if (sectionHeaderSize != 0) {
|
||||||
|
fileMap.paintRange(elf.e_shoff(), elf.e_shoff() + sectionHeaderSize - 1, -4);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Unused file ranges - add as OTHER blocks
|
||||||
|
IndexRangeIterator rangeIterator = fileMap.getIndexRangeIterator(0);
|
||||||
|
int unallocatedIndex = 0;
|
||||||
|
while (rangeIterator.hasNext()) {
|
||||||
|
IndexRange range = rangeIterator.next();
|
||||||
|
int value = fileMap.getValue(range.getStart());
|
||||||
|
if (value != -1) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
String name = UNALLOCATED_NAME_PREFIX + unallocatedIndex++;
|
||||||
|
try {
|
||||||
|
addInitializedMemorySection(null, range.getStart(),
|
||||||
|
range.getEnd() - range.getStart() + 1, AddressSpace.OTHER_SPACE.getMinAddress(),
|
||||||
|
name, false, false, false, null, false, false);
|
||||||
|
}
|
||||||
|
catch (AddressOverflowException e) {
|
||||||
|
// ignore
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private void pruneDiscardableBlocks() {
|
private void pruneDiscardableBlocks() {
|
||||||
byte[] bytes = new byte[DISCARDABLE_SEGMENT_SIZE];
|
byte[] bytes = new byte[DISCARDABLE_SEGMENT_SIZE];
|
||||||
try {
|
try {
|
||||||
for (MemoryBlock block : memory.getBlocks()) {
|
for (MemoryBlock block : memory.getBlocks()) {
|
||||||
long size = block.getSize();
|
long size = block.getSize();
|
||||||
if (size > DISCARDABLE_SEGMENT_SIZE ||
|
if (size > DISCARDABLE_SEGMENT_SIZE ||
|
||||||
!block.getName().startsWith(SEGMENT_NAME_PREFIX)) {
|
!(block.getName().startsWith(SEGMENT_NAME_PREFIX) ||
|
||||||
|
block.getName().startsWith(UNALLOCATED_NAME_PREFIX))) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
block.getBytes(block.getStart(), bytes, 0, (int) size);
|
block.getBytes(block.getStart(), bytes, 0, (int) size);
|
||||||
if (isZeroedArray(bytes, (int) size)) {
|
if (isZeroedArray(bytes, (int) size)) {
|
||||||
Msg.debug(this,
|
Msg.debug(this,
|
||||||
"Removing discardable alignment/filler segment at " + block.getStart());
|
"Removing discardable alignment/filler segment at " + block.getStart());
|
||||||
memory.removeBlock(block, TaskMonitorAdapter.DUMMY_MONITOR);
|
memory.removeBlock(block, TaskMonitor.DUMMY);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -250,7 +373,7 @@ class ElfProgramBuilder extends MemorySectionResolver implements ElfLoadHelper {
|
|||||||
Msg.error(this, "Can't set image base.", e);
|
Msg.error(this, "Can't set image base.", e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private long getImageDataBase() {
|
private long getImageDataBase() {
|
||||||
if (dataImageBase == null) {
|
if (dataImageBase == null) {
|
||||||
dataImageBase = 0L;
|
dataImageBase = 0L;
|
||||||
@@ -448,8 +571,8 @@ class ElfProgramBuilder extends MemorySectionResolver implements ElfLoadHelper {
|
|||||||
}
|
}
|
||||||
|
|
||||||
monitor.setMessage("Processing GNU Definitions");
|
monitor.setMessage("Processing GNU Definitions");
|
||||||
for (ElfProgramHeader roSegment : elf.getProgramHeaders(
|
for (ElfProgramHeader roSegment : elf
|
||||||
ElfProgramHeaderConstants.PT_GNU_RELRO)) {
|
.getProgramHeaders(ElfProgramHeaderConstants.PT_GNU_RELRO)) {
|
||||||
ElfProgramHeader loadedSegment =
|
ElfProgramHeader loadedSegment =
|
||||||
elf.getProgramLoadHeaderContaining(roSegment.getVirtualAddress());
|
elf.getProgramLoadHeaderContaining(roSegment.getVirtualAddress());
|
||||||
if (loadedSegment != null) {
|
if (loadedSegment != null) {
|
||||||
@@ -747,11 +870,12 @@ class ElfProgramBuilder extends MemorySectionResolver implements ElfLoadHelper {
|
|||||||
symbolName = symbols[symbolIndex].getNameAsString();
|
symbolName = symbols[symbolIndex].getNameAsString();
|
||||||
}
|
}
|
||||||
|
|
||||||
Address baseAddress = relocationSpace.getTruncatedAddress(baseWordOffset, true);
|
Address baseAddress = relocationSpace.getTruncatedAddress(baseWordOffset, true);
|
||||||
// long relocationOffset = baseWordOffset + reloc.getOffset();
|
|
||||||
// r_offset is defined to be a byte offset (assume byte size is 1)
|
// relocation offset (r_offset) is defined to be a byte offset (assume byte size is 1)
|
||||||
Address relocAddr = context != null ? context.getRelocationAddress(baseAddress, reloc.getOffset()) : baseAddress.addWrap(reloc.getOffset());
|
Address relocAddr =
|
||||||
// Address relocAddr = relocationSpace.getTruncatedAddress(relocationOffset, true);
|
context != null ? context.getRelocationAddress(baseAddress, reloc.getOffset())
|
||||||
|
: baseAddress.addWrap(reloc.getOffset());
|
||||||
|
|
||||||
long[] values = new long[] { reloc.getSymbolIndex() };
|
long[] values = new long[] { reloc.getSymbolIndex() };
|
||||||
|
|
||||||
@@ -774,8 +898,8 @@ 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, type,
|
||||||
type, reloc.getSymbolIndex(), symbolName, log);
|
reloc.getSymbolIndex(), symbolName, log);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -800,8 +924,8 @@ class ElfProgramBuilder extends MemorySectionResolver implements ElfLoadHelper {
|
|||||||
}
|
}
|
||||||
finally {
|
finally {
|
||||||
// Save relocation data
|
// Save relocation data
|
||||||
program.getRelocationTable().add(relocAddr, reloc.getType(), values, bytes,
|
program.getRelocationTable()
|
||||||
symbolName);
|
.add(relocAddr, reloc.getType(), values, bytes, symbolName);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1171,9 +1295,8 @@ class ElfProgramBuilder extends MemorySectionResolver implements ElfLoadHelper {
|
|||||||
Address externalBlockAddress = externalBlockLimits.getMinAddress();
|
Address externalBlockAddress = externalBlockLimits.getMinAddress();
|
||||||
long size = lastExternalBlockEntryAddress.subtract(externalBlockAddress) + 1;
|
long size = lastExternalBlockEntryAddress.subtract(externalBlockAddress) + 1;
|
||||||
try {
|
try {
|
||||||
MemoryBlock block =
|
MemoryBlock block = memory.createUninitializedBlock(MemoryBlock.EXTERNAL_BLOCK_NAME,
|
||||||
memory.createUninitializedBlock(MemoryBlock.EXTERNAL_BLOCK_NAME,
|
externalBlockAddress, size, false);
|
||||||
externalBlockAddress, size, false);
|
|
||||||
|
|
||||||
// assume any value in external is writable.
|
// assume any value in external is writable.
|
||||||
block.setWrite(true);
|
block.setWrite(true);
|
||||||
@@ -1530,7 +1653,6 @@ class ElfProgramBuilder extends MemorySectionResolver implements ElfLoadHelper {
|
|||||||
/**
|
/**
|
||||||
* Find a specific named symbol within the fake EXTERNAL block.
|
* Find a specific named symbol within the fake EXTERNAL block.
|
||||||
* NOTE: It is assumed that ELF will never produced duplicate names.
|
* NOTE: It is assumed that ELF will never produced duplicate names.
|
||||||
* @param programSymbolTable program's symbol table
|
|
||||||
* @param name symbol name
|
* @param name symbol name
|
||||||
* @param extMin EXTERNAL block minimum address
|
* @param extMin EXTERNAL block minimum address
|
||||||
* @param extMax EXTERNAL block maximum address
|
* @param extMax EXTERNAL block maximum address
|
||||||
@@ -1613,9 +1735,9 @@ class ElfProgramBuilder extends MemorySectionResolver implements ElfLoadHelper {
|
|||||||
Function f = createOneByteFunction(null, address, false);
|
Function f = createOneByteFunction(null, address, false);
|
||||||
if (f != null) {
|
if (f != null) {
|
||||||
if (isFakeExternal && !f.isThunk()) {
|
if (isFakeExternal && !f.isThunk()) {
|
||||||
ExternalLocation extLoc =
|
ExternalLocation extLoc = program.getExternalManager()
|
||||||
program.getExternalManager().addExtFunction(Library.UNKNOWN,
|
.addExtFunction(Library.UNKNOWN, name, null,
|
||||||
name, null, SourceType.IMPORTED);
|
SourceType.IMPORTED);
|
||||||
f.setThunkedFunction(extLoc.getFunction());
|
f.setThunkedFunction(extLoc.getFunction());
|
||||||
// revert thunk function symbol to default source
|
// revert thunk function symbol to default source
|
||||||
Symbol s = f.getSymbol();
|
Symbol s = f.getSymbol();
|
||||||
@@ -1709,8 +1831,8 @@ class ElfProgramBuilder extends MemorySectionResolver implements ElfLoadHelper {
|
|||||||
|
|
||||||
ExternalLocation extLoc = null;
|
ExternalLocation extLoc = null;
|
||||||
try {
|
try {
|
||||||
extLoc = program.getExternalManager().addExtFunction(Library.UNKNOWN, name, null,
|
extLoc = program.getExternalManager()
|
||||||
SourceType.IMPORTED);
|
.addExtFunction(Library.UNKNOWN, name, null, SourceType.IMPORTED);
|
||||||
}
|
}
|
||||||
catch (InvalidInputException e) {
|
catch (InvalidInputException e) {
|
||||||
log.appendMsg("Failed to create external function '" + name + "': " + getMessage(e));
|
log.appendMsg("Failed to create external function '" + name + "': " + getMessage(e));
|
||||||
@@ -1770,9 +1892,9 @@ class ElfProgramBuilder extends MemorySectionResolver implements ElfLoadHelper {
|
|||||||
/**
|
/**
|
||||||
* When transitioning to an external thunk, remove the old symbol on the linkage pointer/thunk
|
* When transitioning to an external thunk, remove the old symbol on the linkage pointer/thunk
|
||||||
* if it is the only symbol at that address.
|
* if it is the only symbol at that address.
|
||||||
* @param address
|
* @param address symbol address
|
||||||
* @param name
|
* @param name symbol name
|
||||||
* @return
|
* @return true if symbol removed, else false
|
||||||
*/
|
*/
|
||||||
private boolean removeOldSymbol(Address address, String name) {
|
private boolean removeOldSymbol(Address address, String name) {
|
||||||
SymbolTable symbolTable = program.getSymbolTable();
|
SymbolTable symbolTable = program.getSymbolTable();
|
||||||
@@ -2168,8 +2290,9 @@ class ElfProgramBuilder extends MemorySectionResolver implements ElfLoadHelper {
|
|||||||
}
|
}
|
||||||
Address refAddr = getDefaultAddress(elf.adjustAddressForPrelink(value.getValue()));
|
Address refAddr = getDefaultAddress(elf.adjustAddressForPrelink(value.getValue()));
|
||||||
if (!definedMemoryOnly || memory.getBlock(refAddr) != null) {
|
if (!definedMemoryOnly || memory.getBlock(refAddr) != null) {
|
||||||
program.getReferenceManager().addMemoryReference(valueData.getAddress(), refAddr,
|
program.getReferenceManager()
|
||||||
RefType.DATA, SourceType.ANALYSIS, 0);
|
.addMemoryReference(valueData.getAddress(), refAddr, RefType.DATA,
|
||||||
|
SourceType.ANALYSIS, 0);
|
||||||
if (label != null) {
|
if (label != null) {
|
||||||
// add label if a non-default label does not exist
|
// add label if a non-default label does not exist
|
||||||
Symbol[] symbols = program.getSymbolTable().getSymbols(refAddr);
|
Symbol[] symbols = program.getSymbolTable().getSymbols(refAddr);
|
||||||
@@ -2390,8 +2513,10 @@ class ElfProgramBuilder extends MemorySectionResolver implements ElfLoadHelper {
|
|||||||
if (!resolvedLoadAddresses.isEmpty()) {
|
if (!resolvedLoadAddresses.isEmpty()) {
|
||||||
// Not contained within loaded bytes - compute relative to block start.
|
// Not contained within loaded bytes - compute relative to block start.
|
||||||
// Always return non-overlay address
|
// Always return non-overlay address
|
||||||
return resolvedLoadAddresses.get(0).getMinAddress().add(
|
return resolvedLoadAddresses.get(0)
|
||||||
byteOffsetWithinSection).getPhysicalAddress();
|
.getMinAddress()
|
||||||
|
.add(byteOffsetWithinSection)
|
||||||
|
.getPhysicalAddress();
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
@@ -2614,9 +2739,8 @@ class ElfProgramBuilder extends MemorySectionResolver implements ElfLoadHelper {
|
|||||||
* @param segmentNumber program header index number
|
* @param segmentNumber program header index number
|
||||||
* @throws AddressOutOfBoundsException if an invalid memory address is encountered
|
* @throws AddressOutOfBoundsException if an invalid memory address is encountered
|
||||||
*/
|
*/
|
||||||
private void processProgramHeader(
|
private void processProgramHeader(ElfProgramHeader elfProgramHeader, int segmentNumber)
|
||||||
ElfProgramHeader elfProgramHeader,
|
throws AddressOutOfBoundsException {
|
||||||
int segmentNumber) throws AddressOutOfBoundsException {
|
|
||||||
|
|
||||||
// FIXME: If physical and virtual addresses do not match this may be an overlay situation.
|
// FIXME: If physical and virtual addresses do not match this may be an overlay situation.
|
||||||
// If sections exist they should use file offsets to correlate to overlay segment - the
|
// If sections exist they should use file offsets to correlate to overlay segment - the
|
||||||
@@ -2640,7 +2764,7 @@ class ElfProgramBuilder extends MemorySectionResolver implements ElfLoadHelper {
|
|||||||
elfProgramHeader.getDescription() + "] at address " + address.toString(true));
|
elfProgramHeader.getDescription() + "] at address " + address.toString(true));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!space.isValidRange(address.getOffset(), fullSizeBytes)) {
|
if (!space.isValidRange(address.getOffset(), fullSizeBytes)) {
|
||||||
log("Skipping unloadable segment [" + segmentNumber + "] at address " +
|
log("Skipping unloadable segment [" + segmentNumber + "] at address " +
|
||||||
address.toString(true) + " (size=" + fullSizeBytes + ")");
|
address.toString(true) + " (size=" + fullSizeBytes + ")");
|
||||||
@@ -2687,8 +2811,9 @@ class ElfProgramBuilder extends MemorySectionResolver implements ElfLoadHelper {
|
|||||||
if (buf.length() != 0) {
|
if (buf.length() != 0) {
|
||||||
buf.append(' ');
|
buf.append(' ');
|
||||||
}
|
}
|
||||||
BigInteger max = BigInteger.valueOf(addr).add(
|
BigInteger max = BigInteger.valueOf(addr)
|
||||||
BigInteger.valueOf(byteSize / addressableUnitSize)).subtract(BigInteger.ONE);
|
.add(BigInteger.valueOf(byteSize / addressableUnitSize))
|
||||||
|
.subtract(BigInteger.ONE);
|
||||||
buf.append(String.format("[0x%x - 0x%s]", addr, max.toString(16)));
|
buf.append(String.format("[0x%x - 0x%s]", addr, max.toString(16)));
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
@@ -2771,13 +2896,13 @@ class ElfProgramBuilder extends MemorySectionResolver implements ElfLoadHelper {
|
|||||||
monitor.setMessage("Processing section headers...");
|
monitor.setMessage("Processing section headers...");
|
||||||
|
|
||||||
boolean includeOtherBlocks = ElfLoaderOptionsFactory.includeOtherBlocks(options);
|
boolean includeOtherBlocks = ElfLoaderOptionsFactory.includeOtherBlocks(options);
|
||||||
|
|
||||||
// establish section address provider for relocatable ELF binaries
|
// establish section address provider for relocatable ELF binaries
|
||||||
RelocatableImageBaseProvider relocatableImageBaseProvider = null;
|
RelocatableImageBaseProvider relocatableImageBaseProvider = null;
|
||||||
if (elf.isRelocatable()) {
|
if (elf.isRelocatable()) {
|
||||||
relocatableImageBaseProvider = new RelocatableImageBaseProvider(monitor);
|
relocatableImageBaseProvider = new RelocatableImageBaseProvider(monitor);
|
||||||
}
|
}
|
||||||
|
|
||||||
ElfSectionHeader[] sections = elf.getSections();
|
ElfSectionHeader[] sections = elf.getSections();
|
||||||
for (ElfSectionHeader elfSectionToLoad : sections) {
|
for (ElfSectionHeader elfSectionToLoad : sections) {
|
||||||
monitor.checkCanceled();
|
monitor.checkCanceled();
|
||||||
@@ -2821,15 +2946,14 @@ class ElfProgramBuilder extends MemorySectionResolver implements ElfLoadHelper {
|
|||||||
// In a relocatable ELF (object module), the address of all sections is zero.
|
// In a relocatable ELF (object module), the address of all sections is zero.
|
||||||
// Therefore, we shall assign an arbitrary address that
|
// Therefore, we shall assign an arbitrary address that
|
||||||
// will pack the sections together with proper alignment.
|
// will pack the sections together with proper alignment.
|
||||||
|
|
||||||
if (elfSectionToLoad.isAlloc() && elf.isRelocatable() && addr == 0) {
|
if (elfSectionToLoad.isAlloc() && elf.isRelocatable() && addr == 0) {
|
||||||
// TODO: if program headers are present (very unlikely for object module)
|
// TODO: if program headers are present (very unlikely for object module)
|
||||||
// they should be used to determine section load address since they would
|
// they should be used to determine section load address since they would
|
||||||
// be assigned first.
|
// be assigned first.
|
||||||
AddressSpace space = getSectionAddressSpace(elfSectionToLoad);
|
AddressSpace space = getSectionAddressSpace(elfSectionToLoad);
|
||||||
long relocOffset = relocatableImageBaseProvider.getNextRelocatableOffset(space);
|
long relocOffset = relocatableImageBaseProvider.getNextRelocatableOffset(space);
|
||||||
addr = NumericUtilities.getUnsignedAlignedValue(
|
addr = NumericUtilities.getUnsignedAlignedValue(relocOffset,
|
||||||
relocOffset,
|
|
||||||
elfSectionToLoad.getAddressAlignment());
|
elfSectionToLoad.getAddressAlignment());
|
||||||
elfSectionToLoad.setAddress(addr);
|
elfSectionToLoad.setAddress(addr);
|
||||||
nextRelocOffset = addr + (sectionByteLength / space.getAddressableUnitSize());
|
nextRelocOffset = addr + (sectionByteLength / space.getAddressableUnitSize());
|
||||||
@@ -2880,8 +3004,8 @@ class ElfProgramBuilder extends MemorySectionResolver implements ElfLoadHelper {
|
|||||||
final String blockName = elfSectionToLoad.getNameAsString();
|
final String blockName = elfSectionToLoad.getNameAsString();
|
||||||
|
|
||||||
try {
|
try {
|
||||||
if (loadOffset == -1 ||
|
if (loadOffset == -1 || (loadOffset == 0 &&
|
||||||
elfSectionToLoad.getType() == ElfSectionHeaderConstants.SHT_NOBITS) {
|
elfSectionToLoad.getType() == ElfSectionHeaderConstants.SHT_NOBITS)) {
|
||||||
if (!elfSectionToLoad.isAlloc() &&
|
if (!elfSectionToLoad.isAlloc() &&
|
||||||
elfSectionToLoad.getType() != ElfSectionHeaderConstants.SHT_PROGBITS) {
|
elfSectionToLoad.getType() != ElfSectionHeaderConstants.SHT_PROGBITS) {
|
||||||
return; // non-allocate at runtime
|
return; // non-allocate at runtime
|
||||||
@@ -2906,7 +3030,7 @@ class ElfProgramBuilder extends MemorySectionResolver implements ElfLoadHelper {
|
|||||||
log("Failed to load section [" + elfSectionToLoad.getNameAsString() + "]: " +
|
log("Failed to load section [" + elfSectionToLoad.getNameAsString() + "]: " +
|
||||||
getMessage(e));
|
getMessage(e));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (nextRelocOffset != null) {
|
if (nextRelocOffset != null) {
|
||||||
relocatableImageBaseProvider.setNextRelocatableOffset(space, nextRelocOffset);
|
relocatableImageBaseProvider.setNextRelocatableOffset(space, nextRelocOffset);
|
||||||
}
|
}
|
||||||
@@ -2997,8 +3121,8 @@ class ElfProgramBuilder extends MemorySectionResolver implements ElfLoadHelper {
|
|||||||
private InputStream getInitializedBlockInputStream(MemoryLoadable loadable, Address start,
|
private InputStream getInitializedBlockInputStream(MemoryLoadable loadable, Address start,
|
||||||
long fileOffset, long dataLength) throws IOException {
|
long fileOffset, long dataLength) throws IOException {
|
||||||
InputStream dataInput = elf.getReader().getByteProvider().getInputStream(fileOffset);
|
InputStream dataInput = elf.getReader().getByteProvider().getInputStream(fileOffset);
|
||||||
return elf.getLoadAdapter().getFilteredLoadInputStream(this, loadable, start, dataLength,
|
return elf.getLoadAdapter()
|
||||||
dataInput);
|
.getFilteredLoadInputStream(this, loadable, start, dataLength, dataInput);
|
||||||
}
|
}
|
||||||
|
|
||||||
private String formatFloat(float value, int maxDecimalPlaces) {
|
private String formatFloat(float value, int maxDecimalPlaces) {
|
||||||
@@ -3109,10 +3233,12 @@ class ElfProgramBuilder extends MemorySectionResolver implements ElfLoadHelper {
|
|||||||
RelocatableImageBaseProvider(TaskMonitor monitor) throws CancelledException {
|
RelocatableImageBaseProvider(TaskMonitor monitor) throws CancelledException {
|
||||||
AddressSpace defaultSpace = getDefaultAddressSpace();
|
AddressSpace defaultSpace = getDefaultAddressSpace();
|
||||||
AddressSpace defaultDataSpace = getDefaultDataSpace();
|
AddressSpace defaultDataSpace = getDefaultDataSpace();
|
||||||
long baseOffset = computeRelocationStartAddress(defaultSpace, elf.getImageBase(), monitor);
|
long baseOffset =
|
||||||
|
computeRelocationStartAddress(defaultSpace, elf.getImageBase(), monitor);
|
||||||
nextRelocationOffsetMap.put(defaultSpace.getUnique(), baseOffset);
|
nextRelocationOffsetMap.put(defaultSpace.getUnique(), baseOffset);
|
||||||
if (defaultDataSpace != defaultSpace) {
|
if (defaultDataSpace != defaultSpace) {
|
||||||
baseOffset = computeRelocationStartAddress(defaultDataSpace, getImageDataBase(), monitor);
|
baseOffset =
|
||||||
|
computeRelocationStartAddress(defaultDataSpace, getImageDataBase(), monitor);
|
||||||
nextRelocationOffsetMap.put(defaultDataSpace.getUnique(), baseOffset);
|
nextRelocationOffsetMap.put(defaultDataSpace.getUnique(), baseOffset);
|
||||||
}
|
}
|
||||||
// In the future, an extension could introduce additional space entries
|
// In the future, an extension could introduce additional space entries
|
||||||
|
|||||||
Reference in New Issue
Block a user