mirror of
https://github.com/NationalSecurityAgency/ghidra.git
synced 2025-10-05 10:49:34 +02:00
Merge branch 'ghidra1_PIC30_ElfImportFixes'
This commit is contained in:
commit
305a1ddf98
28 changed files with 904 additions and 317 deletions
|
@ -60,7 +60,7 @@
|
|||
by importers. At this point in time there is no capability provided by the Memory Map provider to create a
|
||||
new File Bytes instance.</P>
|
||||
|
||||
<P><B>Overlay</B> - Each of the above memory block types may optionally be specified as an <I>Overlay</I> at the
|
||||
<P><A name="OverlayType"></A><B>Overlay</B> - Each of the above memory block types may optionally be specified as an <I>Overlay</I> at the
|
||||
time of creation. If this option is selected, the block is created in a new
|
||||
overlay address space. Overlay blocks can serve various
|
||||
purposes where a memory range may contain different data/code or map to different areas of memory
|
||||
|
|
|
@ -27,6 +27,7 @@ import ghidra.app.util.importer.MessageLog;
|
|||
import ghidra.framework.options.Options;
|
||||
import ghidra.program.model.address.AddressSetView;
|
||||
import ghidra.program.model.data.BuiltInDataTypeManager;
|
||||
import ghidra.program.model.lang.Language;
|
||||
import ghidra.program.model.listing.Program;
|
||||
import ghidra.util.Msg;
|
||||
import ghidra.util.exception.CancelledException;
|
||||
|
@ -91,6 +92,15 @@ public class DWARFAnalyzer extends AbstractAnalyzer {
|
|||
setSupportsOneTimeAnalysis();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean getDefaultEnablement(Program program) {
|
||||
// TODO: DWARF implementation needs improvements to handle Harvard Architectures properly
|
||||
// Currently unable to produce addresses which should refer to data space resulting in
|
||||
// improperly placed symbols, etc.
|
||||
Language language = program.getLanguage();
|
||||
return language.getDefaultSpace() == language.getDefaultDataSpace();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean added(Program program, AddressSetView set, TaskMonitor monitor, MessageLog log)
|
||||
throws CancelledException {
|
||||
|
|
|
@ -443,7 +443,7 @@ public class EntryPointAnalyzer extends AbstractAnalyzer {
|
|||
}
|
||||
|
||||
private boolean isLanguageDefinedEntry(Program program, Address addr) {
|
||||
List<AddressLabelInfo> labelList = program.getLanguage().getDefaultLabels();
|
||||
List<AddressLabelInfo> labelList = program.getLanguage().getDefaultSymbols();
|
||||
for (AddressLabelInfo info : labelList) {
|
||||
if (addr.equals(info.getAddress())) {
|
||||
return info.isEntry();
|
||||
|
@ -453,7 +453,7 @@ public class EntryPointAnalyzer extends AbstractAnalyzer {
|
|||
}
|
||||
|
||||
private boolean isLanguageDefinedEntryPointer(Program program, Address addr) {
|
||||
List<AddressLabelInfo> labelList = program.getLanguage().getDefaultLabels();
|
||||
List<AddressLabelInfo> labelList = program.getLanguage().getDefaultSymbols();
|
||||
for (AddressLabelInfo info : labelList) {
|
||||
if (addr.equals(info.getAddress())) {
|
||||
ProcessorSymbolType type = info.getProcessorSymbolType();
|
||||
|
|
|
@ -110,6 +110,9 @@ public class ParamInfo {
|
|||
}
|
||||
|
||||
void setOrdinal(int i) {
|
||||
if (original != null && original.getOrdinal() != i) {
|
||||
original = null;
|
||||
}
|
||||
this.ordinal = i;
|
||||
}
|
||||
|
||||
|
|
|
@ -865,7 +865,7 @@ public class DIEAggregate {
|
|||
|
||||
// if the DWARF attr was a DW_FORM_addr, it doesn't need fixing up
|
||||
if (high.form == DWARFForm.DW_FORM_addr) {
|
||||
return highVal.getUnsignedValue() + getProgram().getProgramBaseAddressFixup();
|
||||
return highVal.getUnsignedValue() + getProgram().getProgramBaseAddressFixup() - 1;
|
||||
}
|
||||
|
||||
// else it was a DW_FORM_data value and is relative to the lowPC value
|
||||
|
|
|
@ -605,7 +605,7 @@ public class DWARFFunctionImporter {
|
|||
|
||||
private final Address toAddr(Number offset) {
|
||||
return currentProgram.getAddressFactory().getDefaultAddressSpace().getAddress(
|
||||
offset.longValue());
|
||||
offset.longValue(), true);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -630,12 +630,11 @@ public class ElfHeader implements StructConverter, Writeable {
|
|||
}
|
||||
|
||||
ArrayList<ElfStringTable> stringTableList = new ArrayList<>();
|
||||
for (int i = 0; i < sectionHeaders.length; ++i) {
|
||||
if (sectionHeaders[i].getType() == ElfSectionHeaderConstants.SHT_STRTAB) {
|
||||
ElfSectionHeader stringTableSectionHeader = sectionHeaders[i];
|
||||
for (ElfSectionHeader stringTableSectionHeader : sectionHeaders) {
|
||||
if (stringTableSectionHeader.getType() == ElfSectionHeaderConstants.SHT_STRTAB) {
|
||||
ElfStringTable stringTable = ElfStringTable.createElfStringTable(reader, this,
|
||||
stringTableSectionHeader, stringTableSectionHeader.getOffset(),
|
||||
sectionHeaders[i].getAddress(), stringTableSectionHeader.getSize());
|
||||
stringTableSectionHeader.getAddress(), stringTableSectionHeader.getSize());
|
||||
stringTableList.add(stringTable);
|
||||
if (stringTable.getAddressOffset() == dynamicStringTableAddr) {
|
||||
dynamicStringTable = stringTable;
|
||||
|
@ -703,10 +702,9 @@ public class ElfHeader implements StructConverter, Writeable {
|
|||
|
||||
// Add section based symbol tables
|
||||
ArrayList<ElfSymbolTable> symbolTableList = new ArrayList<>();
|
||||
for (int i = 0; i < sectionHeaders.length; ++i) {
|
||||
if (sectionHeaders[i].getType() == ElfSectionHeaderConstants.SHT_SYMTAB ||
|
||||
sectionHeaders[i].getType() == ElfSectionHeaderConstants.SHT_DYNSYM) {
|
||||
ElfSectionHeader symbolTableSectionHeader = sectionHeaders[i];
|
||||
for (ElfSectionHeader symbolTableSectionHeader : sectionHeaders) {
|
||||
if (symbolTableSectionHeader.getType() == ElfSectionHeaderConstants.SHT_SYMTAB ||
|
||||
symbolTableSectionHeader.getType() == ElfSectionHeaderConstants.SHT_DYNSYM) {
|
||||
if (symbolTableSectionHeader.getOffset() < 0) {
|
||||
continue;
|
||||
}
|
||||
|
@ -896,15 +894,15 @@ public class ElfHeader implements StructConverter, Writeable {
|
|||
// HACK: 07/01/2013 - Added hack for malformed ELF file with only program header sections
|
||||
ElfProgramHeader[] pheaders = getProgramHeaders();
|
||||
long size = 0;
|
||||
for (int i = 0; i < pheaders.length; i++) {
|
||||
size += pheaders[i].getFileSize();
|
||||
for (ElfProgramHeader pheader : pheaders) {
|
||||
size += pheader.getFileSize();
|
||||
}
|
||||
if (size == fileLength) {
|
||||
// adjust program section file offset to be based on relative read offset
|
||||
long relOffset = 0;
|
||||
for (int i = 0; i < pheaders.length; i++) {
|
||||
pheaders[i].setOffset(relOffset);
|
||||
relOffset += pheaders[i].getFileSize();
|
||||
for (ElfProgramHeader pheader : pheaders) {
|
||||
pheader.setOffset(relOffset);
|
||||
relOffset += pheader.getFileSize();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1322,9 +1320,9 @@ public class ElfHeader implements StructConverter, Writeable {
|
|||
*/
|
||||
public ElfSectionHeader[] getSections(int type) {
|
||||
ArrayList<ElfSectionHeader> list = new ArrayList<>();
|
||||
for (int i = 0; i < sectionHeaders.length; i++) {
|
||||
if (sectionHeaders[i].getType() == type) {
|
||||
list.add(sectionHeaders[i]);
|
||||
for (ElfSectionHeader sectionHeader : sectionHeaders) {
|
||||
if (sectionHeader.getType() == type) {
|
||||
list.add(sectionHeader);
|
||||
}
|
||||
}
|
||||
ElfSectionHeader[] sections = new ElfSectionHeader[list.size()];
|
||||
|
@ -1340,15 +1338,17 @@ public class ElfHeader implements StructConverter, Writeable {
|
|||
*/
|
||||
public ElfSectionHeader getSection(String name) {
|
||||
List<ElfSectionHeader> list = new ArrayList<>();
|
||||
for (int i = 0; i < sectionHeaders.length; i++) {
|
||||
if (name != null && name.equals(sectionHeaders[i].getNameAsString())) {
|
||||
list.add(sectionHeaders[i]);
|
||||
for (ElfSectionHeader sectionHeader : sectionHeaders) {
|
||||
if (name != null && name.equals(sectionHeader.getNameAsString())) {
|
||||
list.add(sectionHeader);
|
||||
}
|
||||
}
|
||||
if (list.size() == 0)
|
||||
if (list.size() == 0) {
|
||||
return null;
|
||||
if (list.size() > 1)
|
||||
}
|
||||
if (list.size() > 1) {
|
||||
throw new RuntimeException(">1 section with name of " + name);
|
||||
}
|
||||
return list.get(0);
|
||||
}
|
||||
|
||||
|
@ -1359,9 +1359,9 @@ public class ElfHeader implements StructConverter, Writeable {
|
|||
* @return the section header with the specified address
|
||||
*/
|
||||
public ElfSectionHeader getSectionAt(long address) {
|
||||
for (int i = 0; i < sectionHeaders.length; i++) {
|
||||
if (sectionHeaders[i].getAddress() == address) {
|
||||
return sectionHeaders[i];
|
||||
for (ElfSectionHeader sectionHeader : sectionHeaders) {
|
||||
if (sectionHeader.getAddress() == address) {
|
||||
return sectionHeader;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
|
@ -1375,14 +1375,14 @@ public class ElfHeader implements StructConverter, Writeable {
|
|||
*/
|
||||
public ElfSectionHeader getSectionLoadHeaderContaining(long address) {
|
||||
// FIXME: verify
|
||||
for (int i = 0; i < sectionHeaders.length; i++) {
|
||||
if (!sectionHeaders[i].isAlloc()) {
|
||||
for (ElfSectionHeader sectionHeader : sectionHeaders) {
|
||||
if (!sectionHeader.isAlloc()) {
|
||||
continue;
|
||||
}
|
||||
long start = sectionHeaders[i].getAddress();
|
||||
long end = start + sectionHeaders[i].getSize();
|
||||
long start = sectionHeader.getAddress();
|
||||
long end = start + sectionHeader.getSize();
|
||||
if (start <= address && address <= end) {
|
||||
return sectionHeaders[i];
|
||||
return sectionHeader;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
|
@ -1447,9 +1447,9 @@ public class ElfHeader implements StructConverter, Writeable {
|
|||
*/
|
||||
public ElfProgramHeader[] getProgramHeaders(int type) {
|
||||
ArrayList<ElfProgramHeader> list = new ArrayList<>();
|
||||
for (int i = 0; i < programHeaders.length; i++) {
|
||||
if (programHeaders[i].getType() == type) {
|
||||
list.add(programHeaders[i]);
|
||||
for (ElfProgramHeader programHeader : programHeaders) {
|
||||
if (programHeader.getType() == type) {
|
||||
list.add(programHeader);
|
||||
}
|
||||
}
|
||||
ElfProgramHeader[] arr = new ElfProgramHeader[list.size()];
|
||||
|
@ -1487,9 +1487,9 @@ public class ElfHeader implements StructConverter, Writeable {
|
|||
* @return the program header with the specified address
|
||||
*/
|
||||
public ElfProgramHeader getProgramHeaderAt(long virtualAddr) {
|
||||
for (int i = 0; i < programHeaders.length; i++) {
|
||||
if (programHeaders[i].getVirtualAddress() == virtualAddr) {
|
||||
return programHeaders[i];
|
||||
for (ElfProgramHeader programHeader : programHeaders) {
|
||||
if (programHeader.getVirtualAddress() == virtualAddr) {
|
||||
return programHeader;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
|
@ -1502,15 +1502,15 @@ public class ElfHeader implements StructConverter, Writeable {
|
|||
* @return the program header with the specified address
|
||||
*/
|
||||
public ElfProgramHeader getProgramLoadHeaderContaining(long virtualAddr) {
|
||||
for (int i = 0; i < programHeaders.length; i++) {
|
||||
if (programHeaders[i] == null ||
|
||||
programHeaders[i].getType() != ElfProgramHeaderConstants.PT_LOAD) {
|
||||
for (ElfProgramHeader programHeader : programHeaders) {
|
||||
if (programHeader == null ||
|
||||
programHeader.getType() != ElfProgramHeaderConstants.PT_LOAD) {
|
||||
continue;
|
||||
}
|
||||
long start = programHeaders[i].getVirtualAddress();
|
||||
long end = programHeaders[i].getAdjustedMemorySize() - 1 + start;
|
||||
long start = programHeader.getVirtualAddress();
|
||||
long end = programHeader.getAdjustedMemorySize() - 1 + start;
|
||||
if (virtualAddr >= start && virtualAddr <= end) {
|
||||
return programHeaders[i];
|
||||
return programHeader;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
|
@ -1523,15 +1523,15 @@ public class ElfHeader implements StructConverter, Writeable {
|
|||
* @return the program header with the specified file offset
|
||||
*/
|
||||
public ElfProgramHeader getProgramLoadHeaderContainingFileOffset(long offset) {
|
||||
for (int i = 0; i < programHeaders.length; i++) {
|
||||
if (programHeaders[i] == null ||
|
||||
programHeaders[i].getType() != ElfProgramHeaderConstants.PT_LOAD) {
|
||||
for (ElfProgramHeader programHeader : programHeaders) {
|
||||
if (programHeader == null ||
|
||||
programHeader.getType() != ElfProgramHeaderConstants.PT_LOAD) {
|
||||
continue;
|
||||
}
|
||||
long start = programHeaders[i].getOffset();
|
||||
long end = start + (programHeaders[i].getFileSize() - 1);
|
||||
long start = programHeader.getOffset();
|
||||
long end = start + (programHeader.getFileSize() - 1);
|
||||
if (offset >= start && offset <= end) {
|
||||
return programHeaders[i];
|
||||
return programHeader;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
|
@ -1567,9 +1567,9 @@ public class ElfHeader implements StructConverter, Writeable {
|
|||
* @return the string table associated to the specified section header
|
||||
*/
|
||||
public ElfStringTable getStringTable(ElfSectionHeader section) {
|
||||
for (int i = 0; i < stringTables.length; i++) {
|
||||
if (stringTables[i].getFileOffset() == section.getOffset()) {
|
||||
return stringTables[i];
|
||||
for (ElfStringTable stringTable : stringTables) {
|
||||
if (stringTable.getFileOffset() == section.getOffset()) {
|
||||
return stringTable;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
|
@ -1600,9 +1600,9 @@ public class ElfHeader implements StructConverter, Writeable {
|
|||
if (symbolTableSection == null) {
|
||||
return null;
|
||||
}
|
||||
for (int i = 0; i < symbolTables.length; i++) {
|
||||
if (symbolTables[i].getFileOffset() == symbolTableSection.getOffset()) {
|
||||
return symbolTables[i];
|
||||
for (ElfSymbolTable symbolTable : symbolTables) {
|
||||
if (symbolTable.getFileOffset() == symbolTableSection.getOffset()) {
|
||||
return symbolTable;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
|
@ -1633,9 +1633,9 @@ public class ElfHeader implements StructConverter, Writeable {
|
|||
* @return the relocation table located at the specified fileOffset or null
|
||||
*/
|
||||
public ElfRelocationTable getRelocationTableAtOffset(long fileOffset) {
|
||||
for (int i = 0; i < relocationTables.length; i++) {
|
||||
if (relocationTables[i].getFileOffset() == fileOffset) {
|
||||
return relocationTables[i];
|
||||
for (ElfRelocationTable relocationTable : relocationTables) {
|
||||
if (relocationTable.getFileOffset() == fileOffset) {
|
||||
return relocationTable;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
|
@ -1707,7 +1707,7 @@ public class ElfHeader implements StructConverter, Writeable {
|
|||
* @return e_entry component ordinal
|
||||
*/
|
||||
public int getEntryComponentOrdinal() {
|
||||
return 9;
|
||||
return 11;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -1716,7 +1716,7 @@ public class ElfHeader implements StructConverter, Writeable {
|
|||
* @return e_phoff component ordinal
|
||||
*/
|
||||
public int getPhoffComponentOrdinal() {
|
||||
return 10;
|
||||
return 12;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -1725,7 +1725,7 @@ public class ElfHeader implements StructConverter, Writeable {
|
|||
* @return e_shoff component ordinal
|
||||
*/
|
||||
public int getShoffComponentOrdinal() {
|
||||
return 11;
|
||||
return 13;
|
||||
}
|
||||
|
||||
private void addSection(ElfSectionHeader newSection) {
|
||||
|
|
|
@ -259,4 +259,14 @@ public class ElfRelocationContext {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get relocation address
|
||||
* @param baseAddress base address
|
||||
* @param relocOffset relocation offset relative to baseAddress
|
||||
* @return relocation address
|
||||
*/
|
||||
public Address getRelocationAddress(Address baseAddress, long relocOffset) {
|
||||
return baseAddress.addWrap(relocOffset);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -179,7 +179,8 @@ public abstract class AbstractProgramLoader implements Loader {
|
|||
public List<Option> getDefaultOptions(ByteProvider provider, LoadSpec loadSpec,
|
||||
DomainObject domainObject, boolean isLoadIntoProgram) {
|
||||
ArrayList<Option> list = new ArrayList<>();
|
||||
list.add(new Option(APPLY_LABELS_OPTION_NAME, shouldApplyProcessorLabelsByDefault(),
|
||||
list.add(new Option(APPLY_LABELS_OPTION_NAME,
|
||||
shouldApplyProcessorLabelsByDefault(),
|
||||
Boolean.class, Loader.COMMAND_LINE_ARG_PREFIX + "-applyLabels"));
|
||||
list.add(new Option(ANCHOR_LABELS_OPTION_NAME, true, Boolean.class,
|
||||
Loader.COMMAND_LINE_ARG_PREFIX + "-anchorLabels"));
|
||||
|
@ -404,13 +405,34 @@ public abstract class AbstractProgramLoader implements Loader {
|
|||
private void applyProcessorLabels(List<Option> options, Program program) {
|
||||
int id = program.startTransaction("Finalize load");
|
||||
try {
|
||||
Language lang = program.getLanguage();
|
||||
// always create anchored symbols for memory mapped registers
|
||||
// which may be explicitly referenced by pcode
|
||||
for (Register reg : lang.getRegisters()) {
|
||||
Address addr = reg.getAddress();
|
||||
if (addr.isMemoryAddress()) {
|
||||
AddressLabelInfo info = new AddressLabelInfo(addr, reg.getName(),
|
||||
reg.isBaseRegister(), SourceType.IMPORTED);
|
||||
createSymbol(program, info, true);
|
||||
}
|
||||
}
|
||||
// optionally create default symbols defined by pspec
|
||||
if (shouldApplyProcessorLabels(options)) {
|
||||
boolean anchorSymbols = shouldAnchorSymbols(options);
|
||||
Language lang = program.getLanguage();
|
||||
SymbolTable symTable = program.getSymbolTable();
|
||||
|
||||
List<AddressLabelInfo> labels = lang.getDefaultLabels();
|
||||
List<AddressLabelInfo> labels = lang.getDefaultSymbols();
|
||||
for (AddressLabelInfo info : labels) {
|
||||
createSymbol(program, info, anchorSymbols);
|
||||
}
|
||||
}
|
||||
GhidraProgramUtilities.removeAnalyzedFlag(program);
|
||||
}
|
||||
finally {
|
||||
program.endTransaction(id, true);
|
||||
}
|
||||
}
|
||||
|
||||
private void createSymbol(Program program, AddressLabelInfo info, boolean anchorSymbols) {
|
||||
SymbolTable symTable = program.getSymbolTable();
|
||||
Address addr = info.getAddress();
|
||||
Symbol s = symTable.getPrimarySymbol(addr);
|
||||
try {
|
||||
|
@ -449,13 +471,6 @@ public abstract class AbstractProgramLoader implements Loader {
|
|||
// Nothing to do
|
||||
}
|
||||
}
|
||||
}
|
||||
GhidraProgramUtilities.removeAnalyzedFlag(program);
|
||||
}
|
||||
finally {
|
||||
program.endTransaction(id, true);
|
||||
}
|
||||
}
|
||||
|
||||
private String computeBinaryMD5(ByteProvider provider) throws IOException {
|
||||
try (InputStream in = provider.getInputStream(0)) {
|
||||
|
|
|
@ -23,9 +23,8 @@ import ghidra.app.util.OptionUtils;
|
|||
import ghidra.app.util.bin.ByteProvider;
|
||||
import ghidra.app.util.bin.format.elf.ElfException;
|
||||
import ghidra.app.util.bin.format.elf.ElfHeader;
|
||||
import ghidra.program.model.address.AddressOutOfBoundsException;
|
||||
import ghidra.program.model.address.AddressSpace;
|
||||
import ghidra.program.model.lang.LanguageNotFoundException;
|
||||
import ghidra.program.model.address.*;
|
||||
import ghidra.program.model.lang.*;
|
||||
import ghidra.util.NumericUtilities;
|
||||
import ghidra.util.StringUtilities;
|
||||
|
||||
|
@ -42,6 +41,8 @@ public class ElfLoaderOptionsFactory {
|
|||
public static final long IMAGE_BASE_DEFAULT = 0x00010000;
|
||||
public static final long IMAGE64_BASE_DEFAULT = 0x00100000L;
|
||||
|
||||
public static final String IMAGE_DATA_IMAGE_BASE_OPTION_NAME = "Data Image Base";
|
||||
|
||||
public static final String INCLUDE_OTHER_BLOCKS = "Import Non-Loaded Data";// as OTHER overlay blocks
|
||||
static final boolean INCLUDE_OTHER_BLOCKS_DEFAULT = true;
|
||||
|
||||
|
@ -66,13 +67,21 @@ public class ElfLoaderOptionsFactory {
|
|||
if (imageBase == 0 && (elf.isRelocatable() || elf.isSharedObject())) {
|
||||
imageBase = elf.is64Bit() ? IMAGE64_BASE_DEFAULT : IMAGE_BASE_DEFAULT;
|
||||
}
|
||||
AddressSpace defaultSpace =
|
||||
loadSpec.getLanguageCompilerSpec().getLanguage().getDefaultSpace();
|
||||
Language language = loadSpec.getLanguageCompilerSpec().getLanguage();
|
||||
AddressSpace defaultSpace = language.getDefaultSpace();
|
||||
|
||||
String baseOffsetStr = getBaseOffsetString(imageBase, defaultSpace);
|
||||
options.add(new Option(IMAGE_BASE_OPTION_NAME, baseOffsetStr, String.class,
|
||||
String hexValueStr = getBaseAddressOffsetString(imageBase, defaultSpace);
|
||||
options.add(new Option(IMAGE_BASE_OPTION_NAME, hexValueStr, String.class,
|
||||
Loader.COMMAND_LINE_ARG_PREFIX + "-imagebase"));
|
||||
|
||||
if (includeDataImageBaseOption(elf, language)) {
|
||||
long minDataImageBase = getRecommendedMinimumDataImageBase(elf, language);
|
||||
hexValueStr =
|
||||
getBaseAddressOffsetString(minDataImageBase, language.getDefaultDataSpace());
|
||||
options.add(new Option(IMAGE_DATA_IMAGE_BASE_OPTION_NAME, hexValueStr, String.class,
|
||||
Loader.COMMAND_LINE_ARG_PREFIX + "-dataImageBase"));
|
||||
}
|
||||
|
||||
options.add(new Option(INCLUDE_OTHER_BLOCKS, INCLUDE_OTHER_BLOCKS_DEFAULT, Boolean.class,
|
||||
Loader.COMMAND_LINE_ARG_PREFIX + "-includeOtherBlocks"));
|
||||
|
||||
|
@ -81,13 +90,55 @@ public class ElfLoaderOptionsFactory {
|
|||
Boolean.class, Loader.COMMAND_LINE_ARG_PREFIX + "-resolveExternalSymbols"));
|
||||
}
|
||||
|
||||
private static String getBaseOffsetString(long imageBase, AddressSpace defaultSpace) {
|
||||
long maxOffset = defaultSpace.getMaxAddress().getAddressableWordOffset();
|
||||
private static boolean includeDataImageBaseOption(ElfHeader elf, Language language) {
|
||||
// only include option if all segments and section have a 0 address
|
||||
AddressSpace defaultSpace = language.getDefaultSpace();
|
||||
AddressSpace defaultDataSpace = language.getDefaultDataSpace();
|
||||
if (defaultDataSpace.equals(defaultSpace)) {
|
||||
return false;
|
||||
}
|
||||
return elf.isRelocatable() && elf.getImageBase() == 0;
|
||||
}
|
||||
|
||||
private static long getRecommendedMinimumDataImageBase(ElfHeader elf, Language language) {
|
||||
|
||||
String minDataOffset =
|
||||
language.getProperty(GhidraLanguagePropertyKeys.MINIMUM_DATA_IMAGE_BASE);
|
||||
if (minDataOffset != null) {
|
||||
return NumericUtilities.parseHexLong(minDataOffset);
|
||||
}
|
||||
|
||||
AddressSpace defaultDataSpace = language.getDefaultDataSpace();
|
||||
int unitSize = defaultDataSpace.getAddressableUnitSize();
|
||||
|
||||
// logic assumes memory mapped registers reside at low-end addresses (e.g., 0)
|
||||
long minOffset = 0;
|
||||
for (Register reg : language.getRegisters()) {
|
||||
Address addr = reg.getAddress();
|
||||
if (defaultDataSpace.equals(addr.getAddressSpace())) {
|
||||
long offset = addr.getOffset();
|
||||
if (offset < 0) {
|
||||
continue;
|
||||
}
|
||||
offset += reg.getMinimumByteSize();
|
||||
if (offset > minOffset) {
|
||||
minOffset = offset;
|
||||
}
|
||||
}
|
||||
}
|
||||
// set minimum align
|
||||
int align = 16 * unitSize;
|
||||
minOffset += align - (minOffset % align);
|
||||
return minOffset / unitSize;
|
||||
}
|
||||
|
||||
private static String getBaseAddressOffsetString(long imageBase, AddressSpace space) {
|
||||
long maxOffset = space.getMaxAddress().getAddressableWordOffset();
|
||||
while (Long.compareUnsigned(imageBase, maxOffset) > 0) {
|
||||
imageBase >>>= 4;
|
||||
}
|
||||
String baseOffsetStr = Long.toHexString(imageBase);
|
||||
int minNibbles = Math.min(8, defaultSpace.getSize() / 4);
|
||||
int minNibbles = Math.min(8, space.getSize() / 4);
|
||||
int baseOffsetStrLen = baseOffsetStr.length();
|
||||
if (baseOffsetStrLen < minNibbles) {
|
||||
baseOffsetStr =
|
||||
|
@ -97,6 +148,12 @@ public class ElfLoaderOptionsFactory {
|
|||
}
|
||||
|
||||
static String validateOptions(LoadSpec loadSpec, List<Option> options) {
|
||||
Language language;
|
||||
try {
|
||||
language = loadSpec.getLanguageCompilerSpec().getLanguage();
|
||||
} catch (LanguageNotFoundException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
for (Option option : options) {
|
||||
String name = option.getName();
|
||||
if (name.equals(PERFORM_RELOCATIONS_NAME)) {
|
||||
|
@ -110,14 +167,23 @@ public class ElfLoaderOptionsFactory {
|
|||
}
|
||||
}
|
||||
else if (name.equals(IMAGE_BASE_OPTION_NAME)) {
|
||||
return validateAddressSpaceOffsetOption(option, language.getDefaultSpace());
|
||||
}
|
||||
else if (name.equals(IMAGE_DATA_IMAGE_BASE_OPTION_NAME)) {
|
||||
return validateAddressSpaceOffsetOption(option, language.getDefaultDataSpace());
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private static String validateAddressSpaceOffsetOption(Option option, AddressSpace space) {
|
||||
String name = option.getName();
|
||||
if (!String.class.isAssignableFrom(option.getValueClass())) {
|
||||
return "Invalid type for option: " + name + " - " + option.getValueClass();
|
||||
}
|
||||
String value = (String) option.getValue();
|
||||
try {
|
||||
AddressSpace space =
|
||||
loadSpec.getLanguageCompilerSpec().getLanguage().getDefaultSpace();
|
||||
space.getAddress(Long.parseUnsignedLong(value, 16));// verify valid address
|
||||
space.getAddress(Long.parseUnsignedLong(value, 16), true);// verify valid address
|
||||
}
|
||||
catch (NumberFormatException e) {
|
||||
return "Invalid " + name + " - expecting hexidecimal address offset";
|
||||
|
@ -125,11 +191,6 @@ public class ElfLoaderOptionsFactory {
|
|||
catch (AddressOutOfBoundsException e) {
|
||||
return "Invalid " + name + " - " + e.getMessage();
|
||||
}
|
||||
catch (LanguageNotFoundException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
|
@ -149,4 +210,9 @@ public class ElfLoaderOptionsFactory {
|
|||
public static String getImageBaseOption(List<Option> options) {
|
||||
return OptionUtils.getOption(IMAGE_BASE_OPTION_NAME, options, (String) null);
|
||||
}
|
||||
|
||||
public static String getDataImageBaseOption(List<Option> options) {
|
||||
return OptionUtils.getOption(IMAGE_DATA_IMAGE_BASE_OPTION_NAME, options, (String) null);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -19,8 +19,7 @@ import java.io.IOException;
|
|||
import java.io.InputStream;
|
||||
import java.math.BigInteger;
|
||||
import java.text.NumberFormat;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.*;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
import ghidra.app.cmd.label.SetLabelPrimaryCmd;
|
||||
|
@ -69,6 +68,7 @@ class ElfProgramBuilder extends MemorySectionResolver implements ElfLoadHelper {
|
|||
private static final int DISCARDABLE_SEGMENT_SIZE = 0xff;
|
||||
|
||||
private List<Option> options;
|
||||
private Long dataImageBase; // cached data image base option or null if not applicable
|
||||
private MessageLog log;
|
||||
|
||||
private ElfHeader elf;
|
||||
|
@ -250,6 +250,17 @@ class ElfProgramBuilder extends MemorySectionResolver implements ElfLoadHelper {
|
|||
}
|
||||
}
|
||||
|
||||
private long getImageDataBase() {
|
||||
if (dataImageBase == null) {
|
||||
dataImageBase = 0L;
|
||||
String imageBaseStr = ElfLoaderOptionsFactory.getDataImageBaseOption(options);
|
||||
if (imageBaseStr != null) {
|
||||
dataImageBase = NumericUtilities.parseHexLong(imageBaseStr);
|
||||
}
|
||||
}
|
||||
return dataImageBase;
|
||||
}
|
||||
|
||||
private void addProgramProperties(TaskMonitor monitor) throws CancelledException {
|
||||
|
||||
monitor.checkCanceled();
|
||||
|
@ -709,7 +720,7 @@ class ElfProgramBuilder extends MemorySectionResolver implements ElfLoadHelper {
|
|||
}
|
||||
|
||||
private void processRelocationTable(ElfRelocationTable relocationTable,
|
||||
ElfRelocationContext context, AddressSpace relocationSpace, long baseOffset,
|
||||
ElfRelocationContext context, AddressSpace relocationSpace, long baseWordOffset,
|
||||
TaskMonitor monitor) throws CancelledException {
|
||||
|
||||
ElfSymbol[] symbols = relocationTable.getAssociatedSymbolTable().getSymbols();
|
||||
|
@ -725,8 +736,11 @@ class ElfProgramBuilder extends MemorySectionResolver implements ElfLoadHelper {
|
|||
symbolName = symbols[symbolIndex].getNameAsString();
|
||||
}
|
||||
|
||||
long relocationOffset = baseOffset + reloc.getOffset();
|
||||
Address relocAddr = relocationSpace.getTruncatedAddress(relocationOffset, 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)
|
||||
Address relocAddr = context != null ? context.getRelocationAddress(baseAddress, reloc.getOffset()) : baseAddress.addWrap(reloc.getOffset());;
|
||||
// Address relocAddr = relocationSpace.getTruncatedAddress(relocationOffset, true);
|
||||
|
||||
long[] values = new long[] { reloc.getSymbolIndex() };
|
||||
|
||||
|
@ -1261,6 +1275,7 @@ class ElfProgramBuilder extends MemorySectionResolver implements ElfLoadHelper {
|
|||
short sectionIndex = elfSymbol.getSectionHeaderIndex();
|
||||
Address symSectionBase = null;
|
||||
AddressSpace defaultSpace = getDefaultAddressSpace();
|
||||
AddressSpace defaultDataSpace = getDefaultDataSpace();
|
||||
AddressSpace symbolSpace = defaultSpace;
|
||||
long symOffset = elfSymbol.getValue();
|
||||
|
||||
|
@ -1276,11 +1291,14 @@ class ElfProgramBuilder extends MemorySectionResolver implements ElfLoadHelper {
|
|||
return null;
|
||||
}
|
||||
symbolSpace = symSectionBase.getAddressSpace();
|
||||
} // else assume sections have been stripped - always use default space
|
||||
} // else assume sections have been stripped
|
||||
if (symbolSpace.getPhysicalSpace() == defaultSpace) {
|
||||
symOffset =
|
||||
elf.adjustAddressForPrelink(symOffset) + getImageBaseWordAdjustmentOffset();
|
||||
}
|
||||
else if (symbolSpace.getPhysicalSpace() == defaultDataSpace) {
|
||||
symOffset += getImageDataBase();
|
||||
}
|
||||
}
|
||||
else if (sectionIndex == ElfSectionHeaderConstants.SHN_UNDEF) { // Not section relative 0x0000 (e.g., no sections defined)
|
||||
// FIXME: No sections defined or refers to external symbol
|
||||
|
@ -1288,10 +1306,8 @@ class ElfProgramBuilder extends MemorySectionResolver implements ElfLoadHelper {
|
|||
// EXTERNAL block is affected by the program image base
|
||||
symOffset += getImageBaseWordAdjustmentOffset();
|
||||
}
|
||||
//FIXME! We are not handling absolute and common symbols properly
|
||||
//Should constants be placed in constant space?
|
||||
else if (sectionIndex == ElfSectionHeaderConstants.SHN_ABS) { // Absolute value/address - 0xfff1
|
||||
// TODO: Which space ? Can't distinguish data vs. code/default space
|
||||
// TODO: Which space ? Can't distinguish simple constant vs. data vs. code/default space
|
||||
// The should potentially be assign a constant address instead (not possible currently)
|
||||
|
||||
// Note: Assume data space - symbols will be "pinned"
|
||||
|
@ -2463,24 +2479,18 @@ class ElfProgramBuilder extends MemorySectionResolver implements ElfLoadHelper {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Process the program headers and their loaded segments many of which are normally
|
||||
* loaded through the section headers.
|
||||
* This is probably not the correct thing to do unless you have a munged ELF
|
||||
* @param maintainExecuteBit
|
||||
* @throws CancelledException
|
||||
*
|
||||
*/
|
||||
private void processProgramHeaders(TaskMonitor monitor) throws CancelledException {
|
||||
|
||||
if (elf.isRelocatable() && elf.e_phnum() != 0) {
|
||||
log("Ignoring unexpected program headers for relocatable ELF (e_phnum=" +
|
||||
elf.e_phnum() + ")");
|
||||
return;
|
||||
}
|
||||
|
||||
monitor.setMessage("Processing program headers...");
|
||||
|
||||
boolean includeOtherBlocks = ElfLoaderOptionsFactory.includeOtherBlocks(options);
|
||||
|
||||
// TODO: Use of nextRelocStart only works within default space
|
||||
// and cause problems if used within data space - we may need to devise
|
||||
// a better approach to allocating load addresses
|
||||
long nextRelocStart = elf.getImageBase();
|
||||
|
||||
ElfProgramHeader[] elfProgramHeaders = elf.getProgramHeaders();
|
||||
for (int i = 0; i < elfProgramHeaders.length; ++i) {
|
||||
monitor.checkCanceled();
|
||||
|
@ -2514,16 +2524,22 @@ class ElfProgramBuilder extends MemorySectionResolver implements ElfLoadHelper {
|
|||
"] with invalid file offset");
|
||||
continue;
|
||||
}
|
||||
nextRelocStart = processProgramHeader(elfProgramHeader, nextRelocStart, i, monitor);
|
||||
processProgramHeader(elfProgramHeader, i);
|
||||
}
|
||||
}
|
||||
|
||||
private long processProgramHeader(ElfProgramHeader elfProgramHeader, long relocStart,
|
||||
int segmentNumber, TaskMonitor monitor) throws AddressOutOfBoundsException {
|
||||
/**
|
||||
* Process the specified program header by ensuring that it has a suitable memory address assigned
|
||||
* and added to the memory resolver.
|
||||
* @param elfProgramHeader ELF program header to be processed
|
||||
* @param segmentNumber program header index number
|
||||
* @throws AddressOutOfBoundsException if an invalid memory address is encountered
|
||||
*/
|
||||
private void processProgramHeader(
|
||||
ElfProgramHeader elfProgramHeader,
|
||||
int segmentNumber) throws AddressOutOfBoundsException {
|
||||
|
||||
// FIXME: the relocStart concept does not properly consider multiple address spaces
|
||||
|
||||
// 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
|
||||
// problem is that we can only handle a single memory block per overlay range - we may need to
|
||||
// not load segment in this case and defer to section!! Such situations may also
|
||||
|
@ -2543,30 +2559,13 @@ class ElfProgramBuilder extends MemorySectionResolver implements ElfLoadHelper {
|
|||
if (fullSizeBytes <= 0) {
|
||||
log("Skipping zero-length segment [" + segmentNumber + "," +
|
||||
elfProgramHeader.getDescription() + "] at address " + address.toString(true));
|
||||
return relocStart;
|
||||
}
|
||||
|
||||
// In a relocatable ELF, the address of all sections is zero.
|
||||
// Therefore, we shall manufacture an arbitrary address that
|
||||
// will pack the sections together. (may not work with separate Data space!)
|
||||
long nextRelocStart = relocStart;
|
||||
if (elf.isRelocatable() && addr == 0 && fullSizeBytes != 0) {
|
||||
log("Relocatable segment [" + segmentNumber + "] assigned address " +
|
||||
address.toString(true));
|
||||
// TODO: Use of nextRelocStart only works within default space
|
||||
// and cause problems if used within data space - we may need to devise
|
||||
// a better approach to allocating load addresses
|
||||
long vaddr = addr;
|
||||
addr = nextRelocStart; // TODO: Force proper alignment
|
||||
address = address.getNewAddress(nextRelocStart, true);
|
||||
elfProgramHeader.setAddress(addr, vaddr);
|
||||
nextRelocStart += fullSizeBytes / space.getAddressableUnitSize();
|
||||
return;
|
||||
}
|
||||
|
||||
if (!space.isValidRange(address.getOffset(), fullSizeBytes)) {
|
||||
log("Skipping unloadable segment [" + segmentNumber + "] at address " +
|
||||
address.toString(true) + " (size=" + fullSizeBytes + ")");
|
||||
return relocStart;
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
|
@ -2596,7 +2595,6 @@ class ElfProgramBuilder extends MemorySectionResolver implements ElfLoadHelper {
|
|||
catch (AddressOverflowException e) {
|
||||
log("Failed to load segment [" + segmentNumber + "]: " + getMessage(e));
|
||||
}
|
||||
return nextRelocStart;
|
||||
}
|
||||
|
||||
private String getSectionComment(long addr, long byteSize, int addressableUnitSize,
|
||||
|
@ -2653,10 +2651,12 @@ class ElfProgramBuilder extends MemorySectionResolver implements ElfLoadHelper {
|
|||
* When an image is relocatable generally all sections will have a zero address. It is only
|
||||
* when special sections are present (e.g., __ksymtab) that we may encounter sections with
|
||||
* a non-zero address.
|
||||
* @param monitor
|
||||
* @param monitor task monitor
|
||||
* @return start of relocation area
|
||||
* @throws CancelledException task cancelled
|
||||
*/
|
||||
private long computeRelocationStartAddress(TaskMonitor monitor) {
|
||||
private long computeRelocationStartAddress(AddressSpace space, long baseOffset,
|
||||
TaskMonitor monitor) throws CancelledException {
|
||||
if (!elf.isRelocatable()) {
|
||||
return 0; // not applicable
|
||||
}
|
||||
|
@ -2664,9 +2664,7 @@ class ElfProgramBuilder extends MemorySectionResolver implements ElfLoadHelper {
|
|||
AddressSpace defaultSpace = getDefaultAddressSpace();
|
||||
ElfSectionHeader[] sections = elf.getSections();
|
||||
for (ElfSectionHeader elfSectionToLoad : sections) {
|
||||
if (monitor.isCancelled()) {
|
||||
return 0;
|
||||
}
|
||||
monitor.checkCanceled();
|
||||
long addr = elfSectionToLoad.getAddress();
|
||||
if (addr < 0) {
|
||||
relocStartAddr = 0;
|
||||
|
@ -2674,9 +2672,9 @@ class ElfProgramBuilder extends MemorySectionResolver implements ElfLoadHelper {
|
|||
}
|
||||
if (elfSectionToLoad.isAlloc() && addr != 0) {
|
||||
AddressSpace loadSpace = getSectionAddressSpace(elfSectionToLoad);
|
||||
if (loadSpace.equals(defaultSpace)) {
|
||||
if (loadSpace.equals(space)) {
|
||||
long sectionByteLength = elfSectionToLoad.getAdjustedSize(); // size in bytes
|
||||
long sectionLength = sectionByteLength / defaultSpace.getAddressableUnitSize();
|
||||
long sectionLength = sectionByteLength / space.getAddressableUnitSize();
|
||||
relocStartAddr = Math.max(relocStartAddr, addr + sectionLength);
|
||||
}
|
||||
}
|
||||
|
@ -2687,26 +2685,23 @@ class ElfProgramBuilder extends MemorySectionResolver implements ElfLoadHelper {
|
|||
if (testOffset != defaultSpace.getTruncatedAddress(testOffset, true).getOffset()) {
|
||||
relocStartAddr = 0;
|
||||
}
|
||||
|
||||
return relocStartAddr + elf.getImageBase();
|
||||
return relocStartAddr + baseOffset;
|
||||
}
|
||||
|
||||
private void processSectionHeaders(TaskMonitor monitor) {
|
||||
private void processSectionHeaders(TaskMonitor monitor) throws CancelledException {
|
||||
monitor.setMessage("Processing section headers...");
|
||||
|
||||
boolean includeOtherBlocks = ElfLoaderOptionsFactory.includeOtherBlocks(options);
|
||||
|
||||
// TODO: Use of nextRelocStart only works within default space
|
||||
// and cause problems if used within data space - we may need to devise
|
||||
// a better approach to allocating load addresses
|
||||
long nextRelocStart = computeRelocationStartAddress(monitor);
|
||||
// establish section address provider for relocatable ELF binaries
|
||||
RelocatableImageBaseProvider relocatableImageBaseProvider = null;
|
||||
if (elf.isRelocatable()) {
|
||||
relocatableImageBaseProvider = new RelocatableImageBaseProvider(monitor);
|
||||
}
|
||||
|
||||
ElfSectionHeader[] sections = elf.getSections();
|
||||
for (int i = 0; i < sections.length; ++i) {
|
||||
if (monitor.isCancelled()) {
|
||||
return;
|
||||
}
|
||||
ElfSectionHeader elfSectionToLoad = sections[i];
|
||||
for (ElfSectionHeader elfSectionToLoad : sections) {
|
||||
monitor.checkCanceled();
|
||||
if (elfSectionToLoad.getType() != ElfSectionHeaderConstants.SHN_UNDEF &&
|
||||
(includeOtherBlocks || elfSectionToLoad.isAlloc())) {
|
||||
long fileOffset = elfSectionToLoad.getOffset();
|
||||
|
@ -2715,34 +2710,48 @@ class ElfProgramBuilder extends MemorySectionResolver implements ElfLoadHelper {
|
|||
"] with invalid file offset");
|
||||
continue;
|
||||
}
|
||||
nextRelocStart = processSectionHeader(elfSectionToLoad, i, nextRelocStart, monitor);
|
||||
long size = elfSectionToLoad.getSize();
|
||||
if (size <= 0 || size >= fileBytes.getSize()) {
|
||||
log("Skipping section [" + elfSectionToLoad.getNameAsString() +
|
||||
"] with invalid size");
|
||||
continue;
|
||||
}
|
||||
processSectionHeader(elfSectionToLoad, relocatableImageBaseProvider);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private long processSectionHeader(ElfSectionHeader elfSectionToLoad, int index, long relocStart,
|
||||
TaskMonitor monitor) throws AddressOutOfBoundsException {
|
||||
/**
|
||||
* Process the specified section header by ensuring that it has a suitable memory address assigned
|
||||
* and added to the memory resolver.
|
||||
* @param elfSectionToLoad ELF section header to be processed
|
||||
* @param relocatableImageBaseProvider section address provider for relocatable ELF binaries.
|
||||
* @throws AddressOutOfBoundsException if an invalid memory address is encountered
|
||||
*/
|
||||
private void processSectionHeader(ElfSectionHeader elfSectionToLoad,
|
||||
RelocatableImageBaseProvider relocatableImageBaseProvider)
|
||||
throws AddressOutOfBoundsException {
|
||||
|
||||
long addr = elfSectionToLoad.getAddress();
|
||||
long sectionByteLength = elfSectionToLoad.getAdjustedSize(); // size in bytes
|
||||
long loadOffset = elfSectionToLoad.getOffset(); // file offset in bytes
|
||||
Long nextRelocOffset = null;
|
||||
|
||||
// TODO: if addr!=0, create section symbol (allows non loaded section to have some presence)
|
||||
// In a relocatable ELF (object module), the address of all sections is zero.
|
||||
// Therefore, we shall assign an arbitrary address that
|
||||
// will pack the sections together with proper alignment.
|
||||
|
||||
long nextRelocStart = relocStart;
|
||||
|
||||
// In a relocatable ELF, the address of all sections is zero.
|
||||
// Therefore, we shall manufacture an arbitrary address that
|
||||
// will pack the sections together.
|
||||
if (elfSectionToLoad.isAlloc() && elf.isRelocatable() && addr == 0) {
|
||||
// TODO: Use of nextRelocStart only works within default space
|
||||
// and cause problems if used within data space - we may need to devise
|
||||
// a better approach to allocating load addresses
|
||||
addr = NumericUtilities.getUnsignedAlignedValue(nextRelocStart,
|
||||
// TODO: if program headers are present (very unlikely for object module)
|
||||
// they should be used to determine section load address since they would
|
||||
// be assigned first.
|
||||
AddressSpace space = getSectionAddressSpace(elfSectionToLoad);
|
||||
long relocOffset = relocatableImageBaseProvider.getNextRelocatableOffset(space);
|
||||
addr = NumericUtilities.getUnsignedAlignedValue(
|
||||
relocOffset,
|
||||
elfSectionToLoad.getAddressAlignment());
|
||||
elfSectionToLoad.setAddress(addr);
|
||||
nextRelocStart =
|
||||
addr + (sectionByteLength / getDefaultAddressSpace().getAddressableUnitSize());
|
||||
nextRelocOffset = addr + (sectionByteLength / space.getAddressableUnitSize());
|
||||
}
|
||||
|
||||
Address address = null;
|
||||
|
@ -2752,6 +2761,7 @@ class ElfProgramBuilder extends MemorySectionResolver implements ElfLoadHelper {
|
|||
// Check for and consume uninitialized portion of PT_LOAD segment if possible
|
||||
ElfProgramHeader loadHeader = elf.getProgramLoadHeaderContaining(addr);
|
||||
if (loadHeader != null) {
|
||||
// NOTE: should never apply to relocatable ELF
|
||||
Address segmentStart = getSegmentLoadAddress(loadHeader);
|
||||
AddressSpace segmentSpace = segmentStart.getAddressSpace();
|
||||
long loadSizeBytes = loadHeader.getAdjustedLoadSize();
|
||||
|
@ -2772,7 +2782,7 @@ class ElfProgramBuilder extends MemorySectionResolver implements ElfLoadHelper {
|
|||
|
||||
if (sectionByteLength == 0) {
|
||||
log("Skipping empty section [" + elfSectionToLoad.getNameAsString() + "]");
|
||||
return relocStart;
|
||||
return;
|
||||
}
|
||||
|
||||
if (address == null) {
|
||||
|
@ -2783,7 +2793,7 @@ class ElfProgramBuilder extends MemorySectionResolver implements ElfLoadHelper {
|
|||
if (!space.isValidRange(address.getOffset(), sectionByteLength)) {
|
||||
log("Skipping unloadable section [" + elfSectionToLoad.getNameAsString() +
|
||||
"] at address " + address.toString(true) + " (size=" + sectionByteLength + ")");
|
||||
return relocStart;
|
||||
return;
|
||||
}
|
||||
|
||||
final String blockName = elfSectionToLoad.getNameAsString();
|
||||
|
@ -2793,7 +2803,7 @@ class ElfProgramBuilder extends MemorySectionResolver implements ElfLoadHelper {
|
|||
elfSectionToLoad.getType() == ElfSectionHeaderConstants.SHT_NOBITS) {
|
||||
if (!elfSectionToLoad.isAlloc() &&
|
||||
elfSectionToLoad.getType() != ElfSectionHeaderConstants.SHT_PROGBITS) {
|
||||
return nextRelocStart; // non-allocate at runtime
|
||||
return; // non-allocate at runtime
|
||||
}
|
||||
String comment =
|
||||
getSectionComment(addr, sectionByteLength, space.getAddressableUnitSize(),
|
||||
|
@ -2816,7 +2826,9 @@ class ElfProgramBuilder extends MemorySectionResolver implements ElfLoadHelper {
|
|||
getMessage(e));
|
||||
}
|
||||
|
||||
return nextRelocStart;
|
||||
if (nextRelocOffset != null) {
|
||||
relocatableImageBaseProvider.setNextRelocatableOffset(space, nextRelocOffset);
|
||||
}
|
||||
}
|
||||
|
||||
private String pad(int value) {
|
||||
|
@ -3009,4 +3021,32 @@ class ElfProgramBuilder extends MemorySectionResolver implements ElfLoadHelper {
|
|||
revisedLength, comment, BLOCK_SOURCE_NAME, r, w, x, log);
|
||||
}
|
||||
|
||||
private class RelocatableImageBaseProvider {
|
||||
|
||||
Map<Integer, Long> nextRelocationOffsetMap = new HashMap<>();
|
||||
|
||||
RelocatableImageBaseProvider(TaskMonitor monitor) throws CancelledException {
|
||||
AddressSpace defaultSpace = getDefaultAddressSpace();
|
||||
AddressSpace defaultDataSpace = getDefaultDataSpace();
|
||||
long baseOffset = computeRelocationStartAddress(defaultSpace, elf.getImageBase(), monitor);
|
||||
nextRelocationOffsetMap.put(defaultSpace.getUnique(), baseOffset);
|
||||
if (defaultDataSpace != defaultSpace) {
|
||||
baseOffset = computeRelocationStartAddress(defaultDataSpace, getImageDataBase(), monitor);
|
||||
nextRelocationOffsetMap.put(defaultDataSpace.getUnique(), baseOffset);
|
||||
}
|
||||
// In the future, an extension could introduce additional space entries
|
||||
}
|
||||
|
||||
void setNextRelocatableOffset(AddressSpace space, Long nextRelocOffset) {
|
||||
int unique = space.getUnique();
|
||||
nextRelocationOffsetMap.put(unique, nextRelocOffset);
|
||||
}
|
||||
|
||||
long getNextRelocatableOffset(AddressSpace space) {
|
||||
int unique = space.getUnique();
|
||||
Long nextRelocOffset = nextRelocationOffsetMap.get(unique);
|
||||
return nextRelocOffset == null ? 0 : nextRelocOffset;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -563,13 +563,17 @@ public class ImporterDialog extends DialogComponentProvider {
|
|||
}
|
||||
|
||||
private LanguageCompilerSpecPair getPreferredLanguage(Loader loader) {
|
||||
LanguageCompilerSpecPair preferredSpecPair = null;
|
||||
for (LoadSpec loadSpec : loaderMap.get(loader)) {
|
||||
if (loadSpec.isPreferred()) {
|
||||
return loadSpec.getLanguageCompilerSpec();
|
||||
}
|
||||
}
|
||||
if (preferredSpecPair != null) {
|
||||
return null;
|
||||
}
|
||||
preferredSpecPair = loadSpec.getLanguageCompilerSpec();
|
||||
}
|
||||
}
|
||||
return preferredSpecPair;
|
||||
}
|
||||
|
||||
private DomainFolder getProjectRootFolder() {
|
||||
Project project = AppInfo.getActiveProject();
|
||||
|
|
|
@ -265,22 +265,6 @@ public class SleighLanguage implements Language {
|
|||
return getRegisterManager().getContextBaseRegister();
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<AddressLabelInfo> getDefaultLabels() {
|
||||
ArrayList<AddressLabelInfo> list = new ArrayList<>();
|
||||
|
||||
Register regs[] = getRegisters();
|
||||
for (Register reg : regs) {
|
||||
if (reg.getAddressSpace().isMemorySpace()) {
|
||||
AddressLabelInfo entry = new AddressLabelInfo(reg.getAddress(), reg.getName(), true,
|
||||
SourceType.IMPORTED);
|
||||
list.add(entry);
|
||||
}
|
||||
}
|
||||
list.addAll(getDefaultSymbols());
|
||||
return list;
|
||||
}
|
||||
|
||||
@Override
|
||||
public MemoryBlockDefinition[] getDefaultMemoryBlocks() {
|
||||
return defaultMemoryBlocks;
|
||||
|
|
|
@ -119,4 +119,15 @@ public final class GhidraLanguagePropertyKeys {
|
|||
* NOTE: This is an experimental concept which may be removed in the future
|
||||
*/
|
||||
public static final String RESET_CONTEXT_ON_UPGRADE = "resetContextOnUpgrade";
|
||||
|
||||
/**
|
||||
* Property to indicate the minimum recommended base address within the default
|
||||
* data space for placing relocatable data sections. This is intended to
|
||||
* avoid loading into low memory regions where registers may be defined.
|
||||
* The default value for ELF will be just beyond the last memory register defined
|
||||
* within the default data space. This option is only utilized by the
|
||||
* ELF Loader for Harvard Architecures when loading a relocatable ELF binary
|
||||
* (i.e., object module) and corresponds to the ELF Loader option: <code>Data Image Base</code>.
|
||||
*/
|
||||
public static final String MINIMUM_DATA_IMAGE_BASE = "minimumDataImageBase";
|
||||
}
|
||||
|
|
|
@ -226,13 +226,6 @@ public interface Language {
|
|||
*/
|
||||
public Register getRegister(Address addr, int size);
|
||||
|
||||
/**
|
||||
* Return the list of labels for well-known locations.
|
||||
*
|
||||
* @return AddressLabelPair[] empty array if there are no labels
|
||||
*/
|
||||
public List<AddressLabelInfo> getDefaultLabels();
|
||||
|
||||
/**
|
||||
* Get the default program counter register for this language if there is
|
||||
* one.
|
||||
|
@ -254,7 +247,8 @@ public interface Language {
|
|||
public MemoryBlockDefinition[] getDefaultMemoryBlocks();
|
||||
|
||||
/**
|
||||
* Returns the default symbols for this language.
|
||||
* Returns the default symbols for this language. This list does not
|
||||
* contain registers.
|
||||
* @return the default symbols for this language
|
||||
*/
|
||||
public List<AddressLabelInfo> getDefaultSymbols();
|
||||
|
|
|
@ -585,11 +585,6 @@ class OldLanguage implements Language {
|
|||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<AddressLabelInfo> getDefaultLabels() {
|
||||
throw new UnsupportedOperationException("Language for upgrade use only (getDefaultLabels)");
|
||||
}
|
||||
|
||||
@Override
|
||||
public Register getProgramCounter() {
|
||||
throw new UnsupportedOperationException(
|
||||
|
|
|
@ -9,6 +9,8 @@ data/languages/PIC24.sinc||GHIDRA||||END|
|
|||
data/languages/PIC24E.slaspec||GHIDRA||reviewed||END|
|
||||
data/languages/PIC24F.slaspec||GHIDRA||reviewed||END|
|
||||
data/languages/PIC24H.slaspec||GHIDRA||reviewed||END|
|
||||
data/languages/PIC30.dwarf||GHIDRA||||END|
|
||||
data/languages/PIC33.dwarf||GHIDRA||||END|
|
||||
data/languages/dsPIC30F.slaspec||GHIDRA||reviewed||END|
|
||||
data/languages/dsPIC33C.slaspec||GHIDRA||||END|
|
||||
data/languages/dsPIC33E.slaspec||GHIDRA||reviewed||END|
|
||||
|
|
|
@ -48,6 +48,7 @@
|
|||
id="dsPIC30F:LE:24:default">
|
||||
<description>dsPIC30F</description>
|
||||
<compiler name="default" spec="PIC24.cspec" id="default"/>
|
||||
<external_name tool="DWARF.register.mapping.file" name="PIC30.dwarf"/>
|
||||
</language>
|
||||
<language processor="dsPIC33F"
|
||||
endian="little"
|
||||
|
@ -60,6 +61,7 @@
|
|||
id="dsPIC33F:LE:24:default">
|
||||
<description>dsPIC33F</description>
|
||||
<compiler name="default" spec="PIC24.cspec" id="default"/>
|
||||
<external_name tool="DWARF.register.mapping.file" name="PIC30.dwarf"/>
|
||||
</language>
|
||||
<language processor="dsPIC33E"
|
||||
endian="little"
|
||||
|
@ -72,6 +74,7 @@
|
|||
id="dsPIC33E:LE:24:default">
|
||||
<description>dsPIC33E</description>
|
||||
<compiler name="default" spec="PIC24.cspec" id="default"/>
|
||||
<external_name tool="DWARF.register.mapping.file" name="PIC33.dwarf"/>
|
||||
</language>
|
||||
<language processor="dsPIC33C"
|
||||
endian="little"
|
||||
|
@ -84,5 +87,6 @@
|
|||
id="dsPIC33C:LE:24:default">
|
||||
<description>dsPIC33C</description>
|
||||
<compiler name="default" spec="PIC24.cspec" id="default"/>
|
||||
<external_name tool="DWARF.register.mapping.file" name="PIC33.dwarf"/>
|
||||
</language>
|
||||
</language_definitions>
|
||||
|
|
|
@ -5,6 +5,9 @@
|
|||
<constraint loader="Executable and Linking Format (ELF)" compilerSpecID="default">
|
||||
<!-- Elf treats as 32-bit while our definition indicates 24-bit -->
|
||||
<constraint primary="118" processor="dsPIC30F" endian="little" />
|
||||
<constraint primary="118" processor="dsPIC33E" endian="little" />
|
||||
<constraint primary="118" processor="dsPIC33C" endian="little" />
|
||||
<constraint primary="118" processor="dsPIC33F" endian="little" />
|
||||
</constraint>
|
||||
<constraint loader="Common Object File Format (COFF)" compilerSpecID="default">
|
||||
<constraint primary="4662" processor="dsPIC30F" endian="little" />
|
||||
|
|
|
@ -3,8 +3,8 @@
|
|||
<processor_spec>
|
||||
<properties>
|
||||
<property key="assemblyRating:dsPIC30F:LE:24:default" value="POOR"/>
|
||||
<property key="assemblyMessage:dsPIC30F:LE:24:default"
|
||||
value="The language tested with a rating of POOR; however, the failures all deal with extraneous instructions. The assembler may offer you several options. At least one of them will be correct, but others may be erroneous."/>
|
||||
<property key="assemblyMessage:dsPIC30F:LE:24:default" value="The language tested with a rating of POOR; however, the failures all deal with extraneous instructions. The assembler may offer you several options. At least one of them will be correct, but others may be erroneous."/>
|
||||
<property key="minimumDataImageBase" value="0x1000" />
|
||||
</properties>
|
||||
<programcounter register="PC"/>
|
||||
<data_space space="ram"/>
|
||||
|
|
|
@ -806,10 +806,10 @@ f13byte_t: TOK_f13 is TOK_B=1 & TOK_f13
|
|||
{ export *[ram]:1 TOK_f13; }
|
||||
|
||||
f15_t: addr is TOK_f15
|
||||
[ addr = ( TOK_f15 << 1 ); ] { tmp:2 = addr; export *[ram]:2 tmp; }
|
||||
[ addr = ( TOK_f15 << 1 ); ] { export *[ram]:2 addr; }
|
||||
|
||||
f15b_t: addr is TOK_f15b
|
||||
[ addr = ( TOK_f15b << 1 ); ] { tmp:2 = addr; export *[ram]:2 tmp; }
|
||||
[ addr = ( TOK_f15b << 1 ); ] { export *[ram]:2 addr; }
|
||||
|
||||
k3_t: "#"TOK_k3 is TOK_k3
|
||||
{ export *[const]:1 TOK_k3; }
|
||||
|
@ -3992,6 +3992,8 @@ define pcodeop pic30_rem2;
|
|||
Wnd_t = -shift;
|
||||
}
|
||||
|
||||
# TODO: locate encoding details for FEX instruction
|
||||
# :fex
|
||||
|
||||
:ff1l Ws_t,Wnd_t is OP_23_20=0xC & OP_19_16=0xF & OP_15_12=0x8 & OP_11=0x0 & Wnd_t & $(WSconstraint) & Ws_t {
|
||||
|
||||
|
@ -7609,6 +7611,12 @@ define pcodeop pwrsavOp;
|
|||
testSRL_Z(Wnd_t);
|
||||
}
|
||||
|
||||
# SSTEP - ICD instruction compatible with Microchips ICD debugging hardware
|
||||
# TODO: locate encoding details for SSTEP instruction
|
||||
# define pcodeop sstep;
|
||||
# :sstep is OP_23_0=?? {
|
||||
# sstep(); # In-Circuit Debugger (ICD) Single Step
|
||||
# }
|
||||
|
||||
:sub.w f13_t^WREG_t is OP_23_20=0xB & OP_19_16=0x5 & OP_15=0 & WREG_t & f13_t {
|
||||
|
||||
|
@ -8184,6 +8192,11 @@ define pcodeop verifyslave;
|
|||
}
|
||||
@endif
|
||||
|
||||
# URUN - ICD instruction compatible with Microchips ICD debugging hardware
|
||||
define pcodeop urun;
|
||||
:urun is OP_23_0=0xDAC000 {
|
||||
urun(); # In-Circuit Debugger (ICD) Run
|
||||
}
|
||||
|
||||
:xor.w f13_t^WREG_t is OP_23_20=0xB & OP_19_16=0x6 & OP_15=1 & WREG_t & f13_t {
|
||||
|
||||
|
|
21
Ghidra/Processors/PIC/data/languages/PIC30.dwarf
Normal file
21
Ghidra/Processors/PIC/data/languages/PIC30.dwarf
Normal file
|
@ -0,0 +1,21 @@
|
|||
<dwarf>
|
||||
<register_mappings>
|
||||
|
||||
<register_mapping dwarf="0" ghidra="W0" auto_count="15"/> <!-- W0..W14 -->
|
||||
|
||||
<register_mapping dwarf="15" ghidra="W15" stackpointer="true"/>
|
||||
<register_mapping dwarf="16" ghidra="RCOUNT"/>
|
||||
<register_mapping dwarf="17" ghidra="ACCA"/>
|
||||
<register_mapping dwarf="18" ghidra="ACCB"/>
|
||||
<register_mapping dwarf="19" ghidra="PSVPAG"/>
|
||||
<!-- <register_mapping dwarf="20" ghidra="PMADDR"/> **not implemented** -->
|
||||
<!-- <register_mapping dwarf="21" ghidra="PMMODE"/> **not implemented** -->
|
||||
<!-- <register_mapping dwarf="22" ghidra="PMDIN1"/> **not implemented** -->
|
||||
<!-- <register_mapping dwarf="23" ghidra="PMDIN2"/> **not implemented** -->
|
||||
<!-- <register_mapping dwarf="24" ghidra="DSWPAG"/> **not implemented** -->
|
||||
|
||||
<!-- <register_mapping dwarf="25" ghidra="SINK0" auto_count="8"/> **not implemented** -->
|
||||
|
||||
</register_mappings>
|
||||
<call_frame_cfa value="4"/>
|
||||
</dwarf>
|
21
Ghidra/Processors/PIC/data/languages/PIC33.dwarf
Normal file
21
Ghidra/Processors/PIC/data/languages/PIC33.dwarf
Normal file
|
@ -0,0 +1,21 @@
|
|||
<dwarf>
|
||||
<register_mappings>
|
||||
|
||||
<register_mapping dwarf="0" ghidra="W0" auto_count="15"/> <!-- W0..W14 -->
|
||||
|
||||
<register_mapping dwarf="15" ghidra="W15" stackpointer="true"/>
|
||||
<register_mapping dwarf="16" ghidra="RCOUNT"/>
|
||||
<register_mapping dwarf="17" ghidra="ACCA"/>
|
||||
<register_mapping dwarf="18" ghidra="ACCB"/>
|
||||
<register_mapping dwarf="19" ghidra="DSRPAG"/>
|
||||
<!-- <register_mapping dwarf="20" ghidra="PMADDR"/> **not implemented** -->
|
||||
<!-- <register_mapping dwarf="21" ghidra="PMMODE"/> **not implemented** -->
|
||||
<!-- <register_mapping dwarf="22" ghidra="PMDIN1"/> **not implemented** -->
|
||||
<!-- <register_mapping dwarf="23" ghidra="PMDIN2"/> **not implemented** -->
|
||||
<register_mapping dwarf="24" ghidra="DSWPAG"/>
|
||||
|
||||
<!-- <register_mapping dwarf="25" ghidra="SINK0" auto_count="8"/> **not implemented** -->
|
||||
|
||||
</register_mappings>
|
||||
<call_frame_cfa value="4"/>
|
||||
</dwarf>
|
|
@ -0,0 +1,162 @@
|
|||
/* ###
|
||||
* 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.plugin.core.analysis;
|
||||
|
||||
import ghidra.app.services.*;
|
||||
import ghidra.app.util.importer.MessageLog;
|
||||
import ghidra.app.util.opinion.ElfLoader;
|
||||
import ghidra.program.model.address.*;
|
||||
import ghidra.program.model.data.*;
|
||||
import ghidra.program.model.listing.*;
|
||||
import ghidra.program.model.mem.*;
|
||||
import ghidra.program.model.scalar.Scalar;
|
||||
import ghidra.program.model.symbol.*;
|
||||
import ghidra.program.model.util.CodeUnitInsertionException;
|
||||
import ghidra.util.GhidraDataConverter;
|
||||
import ghidra.util.Msg;
|
||||
import ghidra.util.exception.AssertException;
|
||||
import ghidra.util.exception.CancelledException;
|
||||
import ghidra.util.task.TaskMonitor;
|
||||
|
||||
public class Pic24DInitAnalyzer extends AbstractAnalyzer {
|
||||
|
||||
private static final int DST_ORDINAL = 0;
|
||||
private static final int LEN_ORDINAL = 1;
|
||||
private static final int FORMAT_ORDINAL = 2;
|
||||
private static final int PAGE_ORDINAL = 3;
|
||||
|
||||
public Pic24DInitAnalyzer() {
|
||||
super("DInit Analyzer", "Processes .dinit Data Initialization Section", AnalyzerType.BYTE_ANALYZER);
|
||||
setPriority(AnalysisPriority.BLOCK_ANALYSIS.before());
|
||||
setDefaultEnablement(true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canAnalyze(Program program) {
|
||||
String processorName = program.getLanguage().getProcessor().toString();
|
||||
boolean isSupportedProcessor =
|
||||
processorName.contentEquals("PIC-24") || processorName.startsWith("dsPIC3");
|
||||
if (!isSupportedProcessor) {
|
||||
return false;
|
||||
}
|
||||
if (!ElfLoader.ELF_NAME.equals(program.getExecutableFormat())) {
|
||||
return false;
|
||||
}
|
||||
return program.getMemory().getBlock(".dinit") != null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean added(Program program, AddressSetView set, TaskMonitor monitor, MessageLog log)
|
||||
throws CancelledException {
|
||||
|
||||
Listing listing = program.getListing();
|
||||
ReferenceManager referenceManager = program.getReferenceManager();
|
||||
|
||||
MemoryBlock dinitBlock = program.getMemory().getBlock(".dinit");
|
||||
if (listing.getDefinedDataContaining(dinitBlock.getStart()) != null) {
|
||||
Msg.info(this, "Skipping .dinit processing due to existing data at " + dinitBlock.getStart());
|
||||
return true;
|
||||
}
|
||||
|
||||
MemoryBufferImpl memBuffer = new MemoryBufferImpl(program.getMemory(), dinitBlock.getStart());
|
||||
long available = dinitBlock.getSize();
|
||||
|
||||
Structure dataRecordType = new StructureDataType("data_record", 0, program.getDataTypeManager());
|
||||
dataRecordType.setInternallyAligned(true);
|
||||
dataRecordType.add(PointerDataType.dataType, "dst", null);
|
||||
// NOTE: long is used instead of int to ensure that 4-bytes within ROM are consumed
|
||||
dataRecordType.add(LongDataType.dataType, "len", null);
|
||||
try {
|
||||
dataRecordType.addBitField(LongDataType.dataType, 7, "format", null); // Valid formats: 0, 1, 2
|
||||
dataRecordType.addBitField(LongDataType.dataType, 9, "page", null); // TODO: factor into dst ram reference
|
||||
} catch (InvalidDataTypeException e) {
|
||||
throw new AssertException(e);
|
||||
}
|
||||
dataRecordType.setFlexibleArrayComponent(ByteDataType.dataType, "data", null);
|
||||
|
||||
dataRecordType = (Structure) program.getDataTypeManager().resolve(dataRecordType, null);
|
||||
|
||||
GhidraDataConverter converter = GhidraDataConverter.getInstance(false);
|
||||
|
||||
AddressSpace dataSpace = program.getLanguage().getDefaultDataSpace();
|
||||
|
||||
try {
|
||||
Address addr = dinitBlock.getStart();
|
||||
int offset = 0;
|
||||
while (offset < available) {
|
||||
short dst = converter.getShort(memBuffer, offset);
|
||||
if (dst == 0) {
|
||||
break;
|
||||
}
|
||||
Data dataRecord = listing.createData(addr, dataRecordType);
|
||||
|
||||
Scalar len = (Scalar) dataRecord.getComponent(LEN_ORDINAL).getValue();
|
||||
Scalar format = (Scalar) dataRecord.getComponent(FORMAT_ORDINAL).getValue();
|
||||
Scalar page = (Scalar) dataRecord.getComponent(PAGE_ORDINAL).getValue();
|
||||
|
||||
// replace dst reference
|
||||
Reference ref = referenceManager.getPrimaryReferenceFrom(addr, 0);
|
||||
if (ref != null) {
|
||||
referenceManager.delete(ref); // remove bad ref into ROM space
|
||||
}
|
||||
// TODO: use page
|
||||
Address dstAddr = dataSpace.getAddress(dst & 0x0ffff);
|
||||
referenceManager.addMemoryReference(addr, dstAddr, RefType.DATA, SourceType.ANALYSIS, 0);
|
||||
|
||||
offset += dataRecordType.getLength();
|
||||
addr = addr.add(dataRecord.getLength());
|
||||
|
||||
Data arrayData = null;
|
||||
long fmt = format.getValue();
|
||||
if (fmt != 0) {
|
||||
int flexArrayLen = 0;
|
||||
if (fmt == 1) { // 2-bytes consumed per 4-byte ROM location
|
||||
flexArrayLen = (int)(4 * ((len.getValue() + 1) / 2));
|
||||
}
|
||||
else if (fmt == 2) { // 3-bytes consumed per 4-byte ROM location
|
||||
flexArrayLen = (int)(4 * ((len.getValue() + 2) / 3));
|
||||
}
|
||||
else {
|
||||
Msg.error(this, "Invalid .dinit format value at " + dataRecord.getComponent(FORMAT_ORDINAL).getAddress());
|
||||
break;
|
||||
}
|
||||
|
||||
// bounds check
|
||||
if (flexArrayLen < 0 || (offset + flexArrayLen) > available) {
|
||||
Msg.error(this, "Invalid .dinit len value at " + dataRecord.getComponent(LEN_ORDINAL).getAddress());
|
||||
break;
|
||||
}
|
||||
|
||||
Array flexArray = new ArrayDataType(ByteDataType.dataType, flexArrayLen, 1);
|
||||
arrayData = listing.createData(addr, flexArray);
|
||||
|
||||
offset += flexArrayLen;
|
||||
addr = addr.add(flexArrayLen);
|
||||
}
|
||||
|
||||
// NOTE: ELF Loader already loads initialized data intended for ROM into mapped RAM regions
|
||||
// TODO: determine if it is necessary to perform actual initialization
|
||||
// initializeData(program, dstAddr, arrayData, fmt, len);
|
||||
|
||||
}
|
||||
} catch (MemoryAccessException | CodeUnitInsertionException e) {
|
||||
Msg.error(this, "Failed during .dinit processing: " + e.getMessage());
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
|
@ -29,7 +29,61 @@ public class PIC30_ElfExtension extends ElfExtension {
|
|||
|
||||
public static final int EM_DSPIC30F = 118; /* Microchip Technology dsPIC30F DSC */
|
||||
|
||||
// ELF Header Flags (e_flags)
|
||||
public static final int P30F = 1 << 0;
|
||||
public static final int P30FSMPS = 1 << 1;
|
||||
public static final int P33F = 1 << 2;
|
||||
public static final int P24F = 1 << 3;
|
||||
public static final int P24H = 1 << 4;
|
||||
public static final int P24FK = 1 << 5;
|
||||
public static final int P33E = 1 << 6;
|
||||
public static final int P24E = 1 << 7;
|
||||
|
||||
// Section Header Flags (sh_flags)
|
||||
public static final int SHF_MEMORY = (1 << 18); /* User-defined memory */
|
||||
public static final int SHF_UNUSED = (1 << 19); /* Unused */
|
||||
/* OS and processor-specific flags start at postion 20 */
|
||||
public static final int SHF_SECURE = (1 << 20); /* Secure segment */
|
||||
public static final int SHF_BOOT = (1 << 21); /* Boot segment */
|
||||
public static final int SHF_DMA = (1 << 22); /* DMA memory */
|
||||
public static final int SHF_NOLOAD = (1 << 23); /* Do not allocate or load */
|
||||
public static final int SHF_NEAR = (1 << 24); /* Near memory */
|
||||
public static final int SHF_PERSIST = (1 << 25); /* Persistent */
|
||||
public static final int SHF_XMEM = (1 << 26); /* X Memory */
|
||||
public static final int SHF_YMEM = (1 << 27); /* Y Memory */
|
||||
public static final int SHF_PSV = (1 << 28); /* Constants in program memory */
|
||||
public static final int SHF_EEDATA = (1 << 29); /* Data Flash memory */
|
||||
public static final int SHF_ABSOLUTE = (1 << 30); /* Absolute address */
|
||||
public static final int SHF_REVERSE = (1 << 31); /* Reverse aligned */
|
||||
|
||||
/**
|
||||
NOTES:
|
||||
|
||||
EDS/PSV Sections - section data resides with ROM space but is accessable via the
|
||||
the RAM data space at 0x8000 - 0xFFFF with the use of page register. Page use
|
||||
may vary by CPU (EDS, PSV low-word access, PSV high-word access). PSV high-word
|
||||
access capability is only provided when EDS is supported. See page registers
|
||||
DSRPAG and DSWPAG. Page registers must be non-zero when used. Page boundary
|
||||
handling must be explicitly handled in code. EDS memory may be directly
|
||||
accessed provided the page register as been
|
||||
|
||||
Three ways to access page memory:
|
||||
|
||||
1. Direct access using DSRPAG/DSWPAGpage registers (PIC24E, dsPIC33E and dsPIC33C).
|
||||
With read/write page register set to non-zero value, offset 0..0x7FFF within
|
||||
the page may be directly accessed by first setting bit-15 of offset before
|
||||
performing a load or store to the range 0x8000..0xFFFF.
|
||||
|
||||
2. Table read/write instruction may be used by setting TBLPAG register and
|
||||
performing operation with a table offset in the range 0..0x7FFF.
|
||||
|
||||
3. PSV direct access with PSVPAG register (PIC24F, PIC24H, dsPIC30F AND dsPIC33F).
|
||||
Set PSV bit of CORCONL register, set page in PSVPAG register (macro psvpage() used
|
||||
to obtain page from symbol). Access location with offset 0..0x7FFF (macro psvoffset() used
|
||||
to obtain offset from symbol). Macro produces offset in the range 0x8000..0xFFFF.
|
||||
|
||||
|
||||
**/
|
||||
|
||||
@Override
|
||||
public boolean canHandle(ElfHeader elf) {
|
||||
|
@ -84,11 +138,30 @@ public class PIC30_ElfExtension extends ElfExtension {
|
|||
|
||||
private boolean isDataLoad(ElfSectionHeader section) {
|
||||
if (!section.isAlloc()) {
|
||||
return false;
|
||||
return isDebugSection(section);
|
||||
}
|
||||
return !section.isExecutable();
|
||||
}
|
||||
|
||||
private boolean isDataLoad(MemoryLoadable loadable) {
|
||||
if (loadable instanceof ElfSectionHeader) {
|
||||
return isDataLoad((ElfSectionHeader)loadable);
|
||||
}
|
||||
return isDataLoad((ElfProgramHeader)loadable);
|
||||
}
|
||||
|
||||
private boolean isDebugSection(ElfSectionHeader section) {
|
||||
String name = section.getNameAsString();
|
||||
return name.startsWith(".debug_") || ".comment".equals(name);
|
||||
}
|
||||
|
||||
private boolean isDebugSection(MemoryLoadable loadable) {
|
||||
if (loadable instanceof ElfSectionHeader) {
|
||||
return isDebugSection((ElfSectionHeader)loadable);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getAdjustedLoadSize(ElfProgramHeader elfProgramHeader) {
|
||||
long fileSize = elfProgramHeader.getFileSize();
|
||||
|
@ -111,28 +184,37 @@ public class PIC30_ElfExtension extends ElfExtension {
|
|||
public InputStream getFilteredLoadInputStream(ElfLoadHelper elfLoadHelper,
|
||||
MemoryLoadable loadable, Address start, long dataLength, InputStream dataInput) {
|
||||
Language language = elfLoadHelper.getProgram().getLanguage();
|
||||
if (!language.getDefaultDataSpace().equals(start.getAddressSpace().getPhysicalSpace())) {
|
||||
if (!isDataLoad(loadable) && !language.getDefaultDataSpace().equals(start.getAddressSpace().getPhysicalSpace())) {
|
||||
return dataInput;
|
||||
}
|
||||
|
||||
if (loadable instanceof ElfSectionHeader) {
|
||||
ElfSectionHeader section = (ElfSectionHeader) loadable;
|
||||
if ((section.getFlags() & SHF_PSV) != 0) {
|
||||
if (!elfLoadHelper.getElfHeader().isRelocatable() && (section.getFlags() & SHF_PSV) != 0) {
|
||||
// TODO: this is really mapped into ROM space where PT_LOAD was done to physical memory
|
||||
// In the absence of suitable mapping, we will load into RAM space
|
||||
return new PIC30FilteredPSVDataInputStream(dataInput);
|
||||
}
|
||||
}
|
||||
else {
|
||||
return new PIC30FilteredPSVDataInputStream(dataInput);
|
||||
}
|
||||
|
||||
// Data space loading pads after every byte with Microchip toolchain
|
||||
// NOTE: this could vary and we may need to improve detection of this situation
|
||||
|
||||
return new PIC30FilteredDataInputStream(dataInput);
|
||||
return new PIC30FilteredDataInputStream(dataInput, !isDebugSection(loadable));
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasFilteredLoadInputStream(ElfLoadHelper elfLoadHelper, MemoryLoadable loadable,
|
||||
Address start) {
|
||||
if (loadable == null) {
|
||||
return false;
|
||||
}
|
||||
if (isDataLoad(loadable)) {
|
||||
return true;
|
||||
}
|
||||
Language language = elfLoadHelper.getProgram().getLanguage();
|
||||
return language.getDefaultDataSpace().equals(start.getAddressSpace().getPhysicalSpace());
|
||||
}
|
||||
|
@ -144,15 +226,18 @@ public class PIC30_ElfExtension extends ElfExtension {
|
|||
protected boolean padByteToggle;
|
||||
protected long pos;
|
||||
|
||||
protected PIC30FilteredDataInputStream(InputStream in) {
|
||||
private final boolean checkPadding;
|
||||
|
||||
protected PIC30FilteredDataInputStream(InputStream in, boolean checkPadding) {
|
||||
super(in);
|
||||
padByteToggle = false; // first byte is data not padding
|
||||
this.checkPadding = checkPadding;
|
||||
}
|
||||
|
||||
protected int readNextByte() throws IOException {
|
||||
int r = in.read();
|
||||
if (padByteToggle && r != 0) {
|
||||
// expected padding
|
||||
if (checkPadding && padByteToggle && r != 0) {
|
||||
// expected padding - debug sections appear to be inconsistent with filler
|
||||
throw new IOException("expected Data padding byte, pos=" + pos);
|
||||
}
|
||||
++pos;
|
||||
|
@ -204,7 +289,7 @@ public class PIC30_ElfExtension extends ElfExtension {
|
|||
private boolean firstByteToggle; // firstByte of data or pad
|
||||
|
||||
protected PIC30FilteredPSVDataInputStream(InputStream in) {
|
||||
super(in);
|
||||
super(in, true);
|
||||
firstByteToggle = true;
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,46 @@
|
|||
/* ###
|
||||
* 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.relocation;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
import ghidra.app.util.bin.format.elf.ElfLoadHelper;
|
||||
import ghidra.app.util.bin.format.elf.ElfRelocationTable;
|
||||
import ghidra.app.util.bin.format.elf.ElfSymbol;
|
||||
import ghidra.program.model.address.Address;
|
||||
import ghidra.program.model.address.AddressSpace;
|
||||
|
||||
class PIC30_ElfRelocationContext extends ElfRelocationContext {
|
||||
|
||||
protected PIC30_ElfRelocationContext(ElfRelocationHandler handler, ElfLoadHelper loadHelper,
|
||||
ElfRelocationTable relocationTable, Map<ElfSymbol, Address> symbolMap) {
|
||||
super(handler, loadHelper, relocationTable, symbolMap);
|
||||
}
|
||||
|
||||
private boolean isDebugSection(AddressSpace overlaySpace) {
|
||||
String name = overlaySpace.getName();
|
||||
return name.startsWith(".debug_") || ".comment".equals(name);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Address getRelocationAddress(Address baseAddress, long relocOffset) {
|
||||
if (!baseAddress.isLoadedMemoryAddress() && isDebugSection(baseAddress.getAddressSpace())) {
|
||||
relocOffset = relocOffset >> 1;
|
||||
}
|
||||
return baseAddress.addWrap(relocOffset);
|
||||
}
|
||||
|
||||
}
|
|
@ -15,8 +15,11 @@
|
|||
*/
|
||||
package ghidra.app.util.bin.format.elf.relocation;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
import ghidra.app.util.bin.format.elf.*;
|
||||
import ghidra.program.model.address.Address;
|
||||
import ghidra.program.model.lang.Register;
|
||||
import ghidra.program.model.listing.Program;
|
||||
import ghidra.program.model.mem.Memory;
|
||||
import ghidra.program.model.mem.MemoryAccessException;
|
||||
|
@ -24,16 +27,78 @@ import ghidra.util.exception.NotFoundException;
|
|||
|
||||
public class PIC30_ElfRelocationHandler extends ElfRelocationHandler {
|
||||
|
||||
/* ARC Relocations */
|
||||
/* PIC30 Relocation Types */
|
||||
|
||||
//Numbers found in ./include/elf/arc.h:
|
||||
// Numbers found in ./include/elf/pic30.h:
|
||||
public static final int R_PIC30_NONE = 0;
|
||||
public static final int R_PIC30_8 = 1;
|
||||
public static final int R_PIC30_16 = 2;
|
||||
public static final int R_PIC30_32 = 3;
|
||||
public static final int R_PIC30_FILE_REG_BYTE = 4;
|
||||
public static final int R_PIC30_FILE_REG = 5;
|
||||
public static final int R_PIC30_FILE_REG_WORD = 6;
|
||||
public static final int R_PIC30_FILE_REG_WORD_WITH_DST = 7;
|
||||
public static final int R_PIC30_WORD = 8;
|
||||
public static final int R_PIC30_PBYTE = 9;
|
||||
public static final int R_PIC30_PWORD = 10;
|
||||
public static final int R_PIC30_HANDLE = 11;
|
||||
public static final int R_PIC30_PADDR = 12;
|
||||
public static final int R_PIC30_P_PADDR = 13;
|
||||
public static final int R_PIC30_PSVOFFSET = 14;
|
||||
public static final int R_PIC30_TBLOFFSET = 15;
|
||||
public static final int R_PIC30_WORD_HANDLE = 16;
|
||||
public static final int R_PIC30_WORD_PSVOFFSET = 17;
|
||||
public static final int R_PIC30_PSVPAGE = 18;
|
||||
public static final int R_PIC30_P_PSVPAGE = 19;
|
||||
public static final int R_PIC30_WORD_PSVPAGE = 20;
|
||||
public static final int R_PIC30_WORD_TBLOFFSET = 21;
|
||||
public static final int R_PIC30_TBLPAGE = 22;
|
||||
public static final int R_PIC30_P_TBLPAGE = 23;
|
||||
public static final int R_PIC30_WORD_TBLPAGE = 24;
|
||||
public static final int R_PIC30_P_HANDLE = 25;
|
||||
public static final int R_PIC30_P_PSVOFFSET = 26;
|
||||
public static final int R_PIC30_P_TBLOFFSET = 27;
|
||||
public static final int R_PIC30_PCREL_BRANCH = 28;
|
||||
public static final int R_PIC30_BRANCH_ABSOLUTE = 29;
|
||||
public static final int R_PIC30_PCREL_DO = 30;
|
||||
public static final int R_PIC30_DO_ABSOLUTE = 31;
|
||||
public static final int R_PIC30_PGM_ADDR_LSB = 32;
|
||||
public static final int R_PIC30_PGM_ADDR_MSB = 33;
|
||||
public static final int R_PIC30_UNSIGNED_4 = 34;
|
||||
public static final int R_PIC30_UNSIGNED_5 = 35;
|
||||
public static final int R_PIC30_BIT_SELECT_3 = 36;
|
||||
public static final int R_PIC30_BIT_SELECT_4_BYTE = 37;
|
||||
public static final int R_PIC30_BIT_SELECT_4 = 38;
|
||||
public static final int R_PIC30_DSP_6 = 39;
|
||||
public static final int R_PIC30_DSP_PRESHIFT = 40;
|
||||
public static final int R_PIC30_SIGNED_10_BYTE = 41;
|
||||
public static final int R_PIC30_UNSIGNED_10 = 42;
|
||||
public static final int R_PIC30_UNSIGNED_14 = 43;
|
||||
public static final int R_PIC30_FRAME_SIZE = 44;
|
||||
public static final int R_PIC30_PWRSAV_MODE = 45;
|
||||
public static final int R_PIC30_DMAOFFSET = 46;
|
||||
public static final int R_PIC30_P_DMAOFFSET = 47;
|
||||
public static final int R_PIC30_WORD_DMAOFFSET = 48;
|
||||
public static final int R_PIC30_PSVPTR = 49;
|
||||
public static final int R_PIC30_P_PSVPTR = 50;
|
||||
public static final int R_PIC30_L_PSVPTR = 51;
|
||||
public static final int R_PIC30_WORD_PSVPTR = 52;
|
||||
public static final int R_PIC30_CALL_ACCESS = 53;
|
||||
public static final int R_PIC30_PCREL_ACCESS = 54;
|
||||
public static final int R_PIC30_ACCESS = 55;
|
||||
public static final int R_PIC30_P_ACCESS = 56;
|
||||
public static final int R_PIC30_L_ACCESS = 57;
|
||||
public static final int R_PIC30_WORD_ACCESS = 58;
|
||||
public static final int R_PIC30_EDSPAGE = 59;
|
||||
public static final int R_PIC30_P_EDSPAGE = 60;
|
||||
public static final int R_PIC30_WORD_EDSPAGE = 61;
|
||||
public static final int R_PIC30_EDSOFFSET = 62;
|
||||
public static final int R_PIC30_P_EDSOFFSET = 63;
|
||||
public static final int R_PIC30_WORD_EDSOFFSET = 64;
|
||||
public static final int R_PIC30_UNSIGNED_8 = 65;
|
||||
|
||||
// cached state assumes new instance created for each import use
|
||||
private Boolean isEDSVariant = null;
|
||||
|
||||
@Override
|
||||
public boolean canRelocate(ElfHeader elf) {
|
||||
|
@ -41,8 +106,24 @@ public class PIC30_ElfRelocationHandler extends ElfRelocationHandler {
|
|||
}
|
||||
|
||||
@Override
|
||||
public void relocate(ElfRelocationContext elfRelocationContext, ElfRelocation relocation,
|
||||
Address relocationAddress) throws MemoryAccessException, NotFoundException {
|
||||
public PIC30_ElfRelocationContext createRelocationContext(ElfLoadHelper loadHelper,
|
||||
ElfRelocationTable relocationTable, Map<ElfSymbol, Address> symbolMap) {
|
||||
return new PIC30_ElfRelocationContext(this, loadHelper, relocationTable, symbolMap);
|
||||
}
|
||||
|
||||
private boolean isEDSVariant(ElfRelocationContext elfRelocationContext) {
|
||||
if (isEDSVariant == null) {
|
||||
// NOTE: non-EDS variants may improperly define DSRPAG
|
||||
// in register space which should be corrected
|
||||
Register reg = elfRelocationContext.program.getRegister("DSRPAG");
|
||||
isEDSVariant = reg != null && reg.getAddressSpace().isMemorySpace();
|
||||
}
|
||||
return isEDSVariant;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void relocate(ElfRelocationContext elfRelocationContext, ElfRelocation relocation, Address relocationAddress)
|
||||
throws MemoryAccessException, NotFoundException {
|
||||
|
||||
int type = relocation.getType();
|
||||
if (type == R_PIC30_NONE) {
|
||||
|
@ -54,52 +135,66 @@ public class PIC30_ElfRelocationHandler extends ElfRelocationHandler {
|
|||
|
||||
int symbolIndex = relocation.getSymbolIndex();
|
||||
|
||||
long addend = relocation.getAddend(); // will be 0 for REL case
|
||||
int addend = (int) relocation.getAddend();
|
||||
|
||||
if (symbolIndex == 0) {//TODO
|
||||
if (symbolIndex == 0) {// TODO
|
||||
return;
|
||||
}
|
||||
|
||||
long offset = (int) relocationAddress.getOffset();
|
||||
long relocWordOffset = (int) relocationAddress.getAddressableWordOffset();
|
||||
|
||||
ElfSymbol sym = elfRelocationContext.getSymbol(symbolIndex);
|
||||
long symbolValue = elfRelocationContext.getSymbolValue(sym);
|
||||
int symbolValue = (int) elfRelocationContext.getSymbolValue(sym); // word offset
|
||||
|
||||
int oldValue = memory.getInt(relocationAddress);
|
||||
short oldShortValue = memory.getShort(relocationAddress);
|
||||
|
||||
int newValue;
|
||||
|
||||
ElfHeader elf = elfRelocationContext.getElfHeader();
|
||||
if (elf.e_machine() == ElfConstants.EM_DSPIC30F) {//Defined in ./bfd/elf32-arc.c:
|
||||
if (elf.e_machine() == ElfConstants.EM_DSPIC30F) {
|
||||
switch (type) {
|
||||
case R_PIC30_32:
|
||||
newValue = (((int) symbolValue + (int) addend + oldValue) & 0xffffffff);
|
||||
memory.setInt(relocationAddress, newValue);
|
||||
break;
|
||||
case R_PIC30_PCREL_BRANCH:
|
||||
int offsetValue = memory.getShort(relocationAddress) + 1;
|
||||
offsetValue = offsetValue * 2; // make it byte oriented - this should normally be 0
|
||||
newValue = (int) (((symbolValue + (int) addend - (offset + 4))));
|
||||
newValue >>>= 2; // turn it into word offset, and align to even address, actually an error if it isn't aligned
|
||||
// work it into the instruction
|
||||
memory.setShort(relocationAddress, (short) (newValue & 0xffff));
|
||||
break;
|
||||
case R_PIC30_16:
|
||||
short oldShortValue = memory.getShort(relocationAddress);
|
||||
newValue = ((((int) symbolValue + (int) addend + oldShortValue) >> 1) & 0xffff);
|
||||
case R_PIC30_16: // 2
|
||||
newValue = (symbolValue + addend + oldShortValue) & 0xffff;
|
||||
memory.setShort(relocationAddress, (short) newValue);
|
||||
break;
|
||||
case R_PIC30_FILE_REG_WORD_WITH_DST:
|
||||
newValue = ((((int) symbolValue + (int) addend) >> 1) & 0x7fff);
|
||||
int dst = (oldValue >> 4) & 0x7fff;
|
||||
newValue = ((newValue + dst) << 4) | (oldValue & 0xfff1000f);
|
||||
case R_PIC30_32: // 3
|
||||
newValue = symbolValue + addend + oldValue;
|
||||
memory.setInt(relocationAddress, newValue);
|
||||
break;
|
||||
case R_PIC30_WORD:
|
||||
newValue = ((((int) symbolValue + (int) addend) >> 1) & 0xffff);
|
||||
newValue = (newValue << 4) | oldValue;
|
||||
case R_PIC30_FILE_REG_WORD_WITH_DST: // 7
|
||||
int reloc = symbolValue >> 1;
|
||||
reloc += addend;
|
||||
reloc += oldValue >> 4;
|
||||
reloc &= 0x7fff;
|
||||
newValue = (reloc << 4) | (oldValue & ~0x7fff0);
|
||||
memory.setInt(relocationAddress, newValue);
|
||||
break;
|
||||
case R_PIC30_8:
|
||||
case R_PIC30_WORD: // 8
|
||||
case R_PIC30_WORD_TBLOFFSET: // 0x15
|
||||
reloc = symbolValue;
|
||||
reloc += addend;
|
||||
reloc += oldValue >> 4;
|
||||
reloc &= 0xffff;
|
||||
newValue = (reloc << 4) | (oldValue & ~0x0ffff0);
|
||||
memory.setInt(relocationAddress, newValue);
|
||||
break;
|
||||
case R_PIC30_WORD_TBLPAGE: // 0x18
|
||||
reloc = symbolValue >> 16;
|
||||
reloc += addend;
|
||||
reloc += oldValue >> 4;
|
||||
reloc &= 0xffff;
|
||||
if (isEDSVariant(elfRelocationContext)) {
|
||||
reloc |= 0x100;
|
||||
}
|
||||
newValue = (reloc << 4) | (oldValue & ~0x0ffff0);
|
||||
memory.setInt(relocationAddress, newValue);
|
||||
break;
|
||||
case R_PIC30_PCREL_BRANCH: // 0x1c
|
||||
newValue = (int) (symbolValue - relocWordOffset + oldShortValue - 2);
|
||||
newValue >>>= 1;
|
||||
memory.setShort(relocationAddress, (short) (newValue & 0xffff));
|
||||
break;
|
||||
default:
|
||||
String symbolName = sym.getNameAsString();
|
||||
markAsUnhandled(program, relocationAddress, type, symbolIndex, symbolName,
|
||||
|
|
|
@ -589,6 +589,7 @@ The Headless Analyzer uses the command-line parameters discussed below. See <a h
|
|||
<LI><typewriter>-loader-loadExternalLibs <true|false></typewriter></LI>
|
||||
<LI><typewriter>-loader-applyRelocations <true|false></typewriter></LI>
|
||||
<LI><typewriter>-loader-imagebase <imagebase<sup>3</sup>></typewriter></LI>
|
||||
<LI><typewriter>-loader-dataImageBase <dataImageBase<sup>4</sup>></typewriter></LI>
|
||||
<LI><typewriter>-loader-includeOtherBlocks <true|false></typewriter></LI>
|
||||
<LI><typewriter>-loader-resolveExternalSymbols <true|false></typewriter></LI>
|
||||
</UL>
|
||||
|
@ -609,9 +610,11 @@ The Headless Analyzer uses the command-line parameters discussed below. See <a h
|
|||
</UL>
|
||||
</UL>
|
||||
<br>
|
||||
<sup>1. Address must be in the form [space:]offset. Space is optional, and offset is a hex value with no leading 0x.</sup><br>
|
||||
<sup>2. To specify hexadecimal, use a leading 0x.</sup><br>
|
||||
<sup>3. Address is in the default space, and must be specified as a hexadecimal value without the leading 0x.</sup><br>
|
||||
<sup>1</sup>Address must be in the form [space:]offset. Space is optional, and offset is a hex value with no leading 0x.<br>
|
||||
<sup>2</sup>To specify hexadecimal, use a leading 0x.<br>
|
||||
<sup>3</sup>Base address is in the default space and must be specified as a hexadecimal value without the leading 0x.<br>
|
||||
<sup>4</sup>Base address is in the default data space and must be specified as a hexadecimal value without the leading 0x.
|
||||
This option only applies to Harvard Architecture processors when loading relocatable ELF binaries (i.e., object modules).<br>
|
||||
</LI>
|
||||
|
||||
</UL>
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue