mirror of
https://github.com/NationalSecurityAgency/ghidra.git
synced 2025-10-03 09:49:23 +02:00
GP-2128 changed relocation table to support multiple relocations at the same address and rely on original FileBytes for relocations when possible instead of storing within relocation.
This commit is contained in:
parent
3f351eed41
commit
b23ab30f58
25 changed files with 671 additions and 467 deletions
|
@ -1032,7 +1032,7 @@ public class OperandReferenceAnalyzer extends AbstractAnalyzer {
|
|||
RelocationTable relocationTable = program.getRelocationTable();
|
||||
if (relocationTable.isRelocatable()) {
|
||||
// if it is relocatable, then there should be no pointers in memory, other than relacatable ones
|
||||
if (relocationTable.getSize() > 0 && relocationTable.getRelocation(target) == null) {
|
||||
if (relocationTable.getSize() != 0 && !relocationTable.hasRelocation(target)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -30,7 +30,6 @@ import ghidra.program.model.lang.GhidraLanguagePropertyKeys;
|
|||
import ghidra.program.model.lang.Language;
|
||||
import ghidra.program.model.listing.*;
|
||||
import ghidra.program.model.mem.MemoryAccessException;
|
||||
import ghidra.program.model.reloc.Relocation;
|
||||
import ghidra.program.model.reloc.RelocationTable;
|
||||
import ghidra.program.model.scalar.Scalar;
|
||||
import ghidra.program.model.symbol.*;
|
||||
|
@ -115,13 +114,12 @@ public class ScalarOperandAnalyzer extends AbstractAnalyzer {
|
|||
}
|
||||
Scalar scalar = (Scalar) objs[j];
|
||||
|
||||
//if a relocation exists, then this is a valid address
|
||||
//if a relocation exists, assume this is a valid address
|
||||
RelocationTable relocTable = program.getRelocationTable();
|
||||
boolean found = false;
|
||||
for (int r = 0; r < instr.getLength(); ++r) {
|
||||
Address addr = instr.getMinAddress().add(r);
|
||||
RelocationTable relocTable = program.getRelocationTable();
|
||||
Relocation reloc = relocTable.getRelocation(addr);
|
||||
if (reloc != null) {
|
||||
if (relocTable.hasRelocation(addr)) {
|
||||
try {
|
||||
switch (scalar.bitLength()) {
|
||||
case 8:
|
||||
|
@ -196,7 +194,7 @@ public class ScalarOperandAnalyzer extends AbstractAnalyzer {
|
|||
RelocationTable relocationTable = program.getRelocationTable();
|
||||
if (relocationTable.isRelocatable()) {
|
||||
// if it is relocatable, then there should be no pointers in memory, other than relacatable ones
|
||||
if (relocationTable.getSize() > 0 && relocationTable.getRelocation(target) == null) {
|
||||
if (relocationTable.getSize() != 0 && !relocationTable.hasRelocation(target)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1407,7 +1407,8 @@ public class AddressTable {
|
|||
* relocatable programs. Every address should be in the relocation table.
|
||||
*
|
||||
* @param target location to check
|
||||
* @return
|
||||
* @return false if relocations are defined but not at the specified target address,
|
||||
* otherwise true.
|
||||
*/
|
||||
private static boolean isValidRelocationAddress(Program program, Address target) {
|
||||
// If the program is relocatable, and this address is not one of the relocations
|
||||
|
@ -1415,7 +1416,7 @@ public class AddressTable {
|
|||
RelocationTable relocationTable = program.getRelocationTable();
|
||||
if (relocationTable.isRelocatable()) {
|
||||
// if it is relocatable, then there should be no pointers in memory, other than relacatable ones
|
||||
if (relocationTable.getSize() > 0 && relocationTable.getRelocation(target) == null) {
|
||||
if (relocationTable.getSize() != 0 && !relocationTable.hasRelocation(target)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -274,7 +274,7 @@ public class EntryPointAnalyzer extends AbstractAnalyzer {
|
|||
}
|
||||
|
||||
// relocation at this place, don't trust it
|
||||
if (program.getRelocationTable().getRelocation(entry) != null) {
|
||||
if (program.getRelocationTable().hasRelocation(entry)) {
|
||||
laterIter.remove();
|
||||
continue;
|
||||
}
|
||||
|
|
|
@ -20,11 +20,11 @@ import java.awt.Dimension;
|
|||
|
||||
import javax.swing.*;
|
||||
|
||||
import ghidra.app.plugin.core.reloc.RelocationTableModel.RelocationRowObject;
|
||||
import ghidra.app.services.GoToService;
|
||||
import ghidra.framework.plugintool.ComponentProviderAdapter;
|
||||
import ghidra.framework.plugintool.ServiceProvider;
|
||||
import ghidra.program.model.listing.Program;
|
||||
import ghidra.program.model.reloc.Relocation;
|
||||
import ghidra.util.HelpLocation;
|
||||
import ghidra.util.table.*;
|
||||
|
||||
|
@ -34,8 +34,8 @@ class RelocationProvider extends ComponentProviderAdapter {
|
|||
private RelocationTablePlugin plugin;
|
||||
private JPanel mainPanel;
|
||||
private Program currentProgram;
|
||||
private GhidraTableFilterPanel<Relocation> tableFilterPanel;
|
||||
private GhidraThreadedTablePanel<Relocation> threadedPanel;
|
||||
private GhidraTableFilterPanel<RelocationRowObject> tableFilterPanel;
|
||||
private GhidraThreadedTablePanel<RelocationRowObject> threadedPanel;
|
||||
|
||||
RelocationProvider(RelocationTablePlugin plugin) {
|
||||
super(plugin.getTool(), "Relocation Table", plugin.getName());
|
||||
|
@ -83,6 +83,8 @@ class RelocationProvider extends ComponentProviderAdapter {
|
|||
table.setSelectionMode(ListSelectionModel.MULTIPLE_INTERVAL_SELECTION);
|
||||
table.setAutoResizeMode(JTable.AUTO_RESIZE_NEXT_COLUMN);
|
||||
|
||||
table.getSelectionModel().addListSelectionListener(e -> contextChanged());
|
||||
|
||||
ToolTipManager.sharedInstance().registerComponent(table);
|
||||
|
||||
panel.add(threadedPanel, BorderLayout.CENTER);
|
||||
|
|
|
@ -15,10 +15,12 @@
|
|||
*/
|
||||
package ghidra.app.plugin.core.reloc;
|
||||
|
||||
import java.util.Comparator;
|
||||
import java.util.Iterator;
|
||||
|
||||
import docking.widgets.table.DiscoverableTableUtils;
|
||||
import docking.widgets.table.TableColumnDescriptor;
|
||||
import ghidra.app.plugin.core.reloc.RelocationTableModel.RelocationRowObject;
|
||||
import ghidra.docking.settings.Settings;
|
||||
import ghidra.framework.plugintool.ServiceProvider;
|
||||
import ghidra.program.model.address.Address;
|
||||
|
@ -33,12 +35,31 @@ import ghidra.util.table.field.AbstractProgramBasedDynamicTableColumn;
|
|||
import ghidra.util.table.field.AddressTableColumn;
|
||||
import ghidra.util.task.TaskMonitor;
|
||||
|
||||
class RelocationTableModel extends AddressBasedTableModel<Relocation> {
|
||||
class RelocationTableModel extends AddressBasedTableModel<RelocationRowObject> {
|
||||
|
||||
final static String RELOCATION_ADDRESS = "Address";
|
||||
final static String RELOCATION_TYPE = "Type";
|
||||
final static String RELOCATION_VALUE = "Values";
|
||||
final static String RELOCATION_BYTES = "Original Bytes";
|
||||
private static Comparator<RelocationRowObject> ADDRESS_SORT_COMPARATOR =
|
||||
new Comparator<RelocationTableModel.RelocationRowObject>() {
|
||||
|
||||
@Override
|
||||
public int compare(RelocationRowObject o1, RelocationRowObject o2) {
|
||||
int c = o1.relocation.getAddress().compareTo(o2.relocation.getAddress());
|
||||
if (c == 0) {
|
||||
c = o1.relocationIndex - o2.relocationIndex;
|
||||
}
|
||||
return c;
|
||||
}
|
||||
};
|
||||
|
||||
static final int ADDRESS_COL = 0;
|
||||
static final int TYPE_COL = 1;
|
||||
static final int VALUE_COL = 2;
|
||||
static final int BYTES_COL = 3;
|
||||
static final int NAME_COL = 4;
|
||||
|
||||
static final String RELOCATION_ADDRESS = "Address";
|
||||
static final String RELOCATION_TYPE = "Type";
|
||||
static final String RELOCATION_VALUE = "Values";
|
||||
static final String RELOCATION_BYTES = "Original Bytes";
|
||||
static final String RELOCATION_NAME = "Name";
|
||||
|
||||
public RelocationTableModel(ServiceProvider serviceProvider, Program program,
|
||||
|
@ -47,8 +68,8 @@ class RelocationTableModel extends AddressBasedTableModel<Relocation> {
|
|||
}
|
||||
|
||||
@Override
|
||||
protected TableColumnDescriptor<Relocation> createTableColumnDescriptor() {
|
||||
TableColumnDescriptor<Relocation> descriptor = new TableColumnDescriptor<>();
|
||||
protected TableColumnDescriptor<RelocationRowObject> createTableColumnDescriptor() {
|
||||
TableColumnDescriptor<RelocationRowObject> descriptor = new TableColumnDescriptor<>();
|
||||
|
||||
descriptor.addVisibleColumn(
|
||||
DiscoverableTableUtils.adaptColumForModel(this, new AddressTableColumn()), 1, true);
|
||||
|
@ -60,6 +81,14 @@ class RelocationTableModel extends AddressBasedTableModel<Relocation> {
|
|||
return descriptor;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Comparator<RelocationRowObject> createSortComparator(int columnIndex) {
|
||||
if (columnIndex == ADDRESS_COL) {
|
||||
return ADDRESS_SORT_COMPARATOR;
|
||||
}
|
||||
return super.createSortComparator(columnIndex);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setProgram(Program p) {
|
||||
super.setProgram(p);
|
||||
|
@ -68,32 +97,48 @@ class RelocationTableModel extends AddressBasedTableModel<Relocation> {
|
|||
}
|
||||
|
||||
@Override
|
||||
protected void doLoad(Accumulator<Relocation> accumulator, TaskMonitor monitor)
|
||||
protected void doLoad(Accumulator<RelocationRowObject> accumulator, TaskMonitor monitor)
|
||||
throws CancelledException {
|
||||
if (getProgram() == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
int relocationIndex = 0;
|
||||
RelocationTable relocationTable = getProgram().getRelocationTable();
|
||||
Iterator<Relocation> iterator = relocationTable.getRelocations();
|
||||
while (iterator.hasNext()) {
|
||||
Relocation r = iterator.next();
|
||||
accumulator.add(r);
|
||||
accumulator.add(new RelocationRowObject(r, ++relocationIndex));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Address getAddress(int row) {
|
||||
Relocation relocation = filteredData.get(row);
|
||||
return relocation.getAddress();
|
||||
RelocationRowObject rowObject = filteredData.get(row);
|
||||
return rowObject.relocation.getAddress();
|
||||
}
|
||||
|
||||
//==================================================================================================
|
||||
// Inner Classes
|
||||
//==================================================================================================
|
||||
|
||||
static class RelocationRowObject {
|
||||
|
||||
/**
|
||||
* The relocationIndex must be used to differentiate multiple relocations
|
||||
* for the same address. This must be used for secondary comparison when sorting on address.
|
||||
*/
|
||||
final int relocationIndex;
|
||||
final Relocation relocation;
|
||||
|
||||
public RelocationRowObject(Relocation r, int relocationIndex) {
|
||||
this.relocationIndex = relocationIndex;
|
||||
this.relocation = r;
|
||||
}
|
||||
}
|
||||
|
||||
private static class RelocationTypeColumn extends
|
||||
AbstractProgramBasedDynamicTableColumn<Relocation, String> {
|
||||
AbstractProgramBasedDynamicTableColumn<RelocationRowObject, String> {
|
||||
|
||||
@Override
|
||||
public String getColumnName() {
|
||||
|
@ -101,15 +146,15 @@ class RelocationTableModel extends AddressBasedTableModel<Relocation> {
|
|||
}
|
||||
|
||||
@Override
|
||||
public String getValue(Relocation rowObject, Settings settings, Program program,
|
||||
public String getValue(RelocationRowObject rowObject, Settings settings, Program program,
|
||||
ServiceProvider serviceProvider) throws IllegalArgumentException {
|
||||
return "0x" + Integer.toHexString(rowObject.getType());
|
||||
return "0x" + Integer.toHexString(rowObject.relocation.getType());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private static class RelocationValueColumn extends
|
||||
AbstractProgramBasedDynamicTableColumn<Relocation, String> {
|
||||
AbstractProgramBasedDynamicTableColumn<RelocationRowObject, String> {
|
||||
|
||||
@Override
|
||||
public String getColumnName() {
|
||||
|
@ -117,9 +162,9 @@ class RelocationTableModel extends AddressBasedTableModel<Relocation> {
|
|||
}
|
||||
|
||||
@Override
|
||||
public String getValue(Relocation rowObject, Settings settings, Program program,
|
||||
public String getValue(RelocationRowObject rowObject, Settings settings, Program program,
|
||||
ServiceProvider serviceProvider) throws IllegalArgumentException {
|
||||
return packValues(rowObject.getValues());
|
||||
return packValues(rowObject.relocation.getValues());
|
||||
}
|
||||
|
||||
private String packValues(long[] values) {
|
||||
|
@ -138,7 +183,7 @@ class RelocationTableModel extends AddressBasedTableModel<Relocation> {
|
|||
}
|
||||
|
||||
private static class RelocationBytesColumn extends
|
||||
AbstractProgramBasedDynamicTableColumn<Relocation, String> {
|
||||
AbstractProgramBasedDynamicTableColumn<RelocationRowObject, String> {
|
||||
|
||||
@Override
|
||||
public String getColumnName() {
|
||||
|
@ -146,9 +191,9 @@ class RelocationTableModel extends AddressBasedTableModel<Relocation> {
|
|||
}
|
||||
|
||||
@Override
|
||||
public String getValue(Relocation rowObject, Settings settings, Program program,
|
||||
public String getValue(RelocationRowObject rowObject, Settings settings, Program program,
|
||||
ServiceProvider serviceProvider) throws IllegalArgumentException {
|
||||
return packBytes(rowObject.getBytes());
|
||||
return packBytes(rowObject.relocation.getBytes());
|
||||
}
|
||||
|
||||
private String packBytes(byte[] bytes) {
|
||||
|
@ -171,7 +216,7 @@ class RelocationTableModel extends AddressBasedTableModel<Relocation> {
|
|||
}
|
||||
|
||||
private static class RelocationNameColumn extends
|
||||
AbstractProgramBasedDynamicTableColumn<Relocation, String> {
|
||||
AbstractProgramBasedDynamicTableColumn<RelocationRowObject, String> {
|
||||
|
||||
@Override
|
||||
public String getColumnName() {
|
||||
|
@ -179,9 +224,9 @@ class RelocationTableModel extends AddressBasedTableModel<Relocation> {
|
|||
}
|
||||
|
||||
@Override
|
||||
public String getValue(Relocation rowObject, Settings settings, Program program,
|
||||
public String getValue(RelocationRowObject rowObject, Settings settings, Program program,
|
||||
ServiceProvider serviceProvider) throws IllegalArgumentException {
|
||||
return rowObject.getSymbolName();
|
||||
return rowObject.relocation.getSymbolName();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
/* ###
|
||||
* IP: GHIDRA
|
||||
* REVIEWED: YES
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
@ -16,17 +15,19 @@
|
|||
*/
|
||||
package ghidra.app.plugin.core.reloc;
|
||||
|
||||
import ghidra.app.plugin.core.reloc.RelocationTableModel.RelocationRowObject;
|
||||
import ghidra.framework.plugintool.ServiceProvider;
|
||||
import ghidra.program.model.address.Address;
|
||||
import ghidra.program.model.listing.Program;
|
||||
import ghidra.program.model.reloc.Relocation;
|
||||
import ghidra.util.table.ProgramLocationTableRowMapper;
|
||||
|
||||
public class RelocationToAddressTableRowMapper extends ProgramLocationTableRowMapper<Relocation, Address> {
|
||||
public class RelocationToAddressTableRowMapper
|
||||
extends ProgramLocationTableRowMapper<RelocationRowObject, Address> {
|
||||
|
||||
@Override
|
||||
public Address map( Relocation rowObject, Program program, ServiceProvider serviceProvider ) {
|
||||
return rowObject.getAddress();
|
||||
public Address map(RelocationRowObject rowObject, Program program,
|
||||
ServiceProvider serviceProvider) {
|
||||
return rowObject.relocation.getAddress();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -660,7 +660,7 @@ public class ElfDefaultGotPltMarkup {
|
|||
if (program.getImageBase().getOffset() != 0) {
|
||||
return null;
|
||||
}
|
||||
if (program.getRelocationTable().getRelocation(data.getAddress()) != null) {
|
||||
if (program.getRelocationTable().hasRelocation(data.getAddress())) {
|
||||
return null;
|
||||
}
|
||||
MemoryBlock tBlock = memory.getBlock(".text");
|
||||
|
|
|
@ -689,8 +689,6 @@ public class CoffLoader extends AbstractLibrarySupportLoader {
|
|||
sectionStartAddr.add(relocation.getAddress() - section.getVirtualAddress());
|
||||
short relocationType = relocation.getType();
|
||||
|
||||
byte[] origBytes = new byte[0];
|
||||
|
||||
if (handler == null) {
|
||||
++failureCount;
|
||||
handleRelocationError(program, address, relocationType,
|
||||
|
@ -698,7 +696,6 @@ public class CoffLoader extends AbstractLibrarySupportLoader {
|
|||
}
|
||||
else {
|
||||
try {
|
||||
origBytes = new byte[4];
|
||||
if (address.equals(failedAddr)) {
|
||||
// skip relocation if previous failed relocation was at the same address
|
||||
// since it is likely dependent on the previous failed relocation result
|
||||
|
@ -708,15 +705,10 @@ public class CoffLoader extends AbstractLibrarySupportLoader {
|
|||
String.format("Skipped dependent COFF Relocation type 0x%x at %s",
|
||||
relocationType, address.toString());
|
||||
Msg.error(this, program.getName() + ": " + logMessage);
|
||||
|
||||
// TODO: once RelocationTable can retain all relocations at the same address
|
||||
// this continue statement should be removed (see GP-2128)
|
||||
continue;
|
||||
}
|
||||
//else {
|
||||
program.getMemory().getBytes(address, origBytes);
|
||||
else {
|
||||
handler.relocate(address, relocation, relocationContext);
|
||||
//}
|
||||
}
|
||||
}
|
||||
catch (MemoryAccessException e) {
|
||||
++failureCount;
|
||||
|
@ -758,7 +750,7 @@ public class CoffLoader extends AbstractLibrarySupportLoader {
|
|||
// table. (see GP-2128)
|
||||
program.getRelocationTable()
|
||||
.add(address, relocation.getType(),
|
||||
new long[] { relocation.getSymbolIndex() }, origBytes,
|
||||
new long[] { relocation.getSymbolIndex() }, null,
|
||||
symbol != null ? symbol.getName() : "<null>");
|
||||
}
|
||||
}
|
||||
|
|
|
@ -902,8 +902,6 @@ class ElfProgramBuilder extends MemorySectionResolver implements ElfLoadHelper {
|
|||
|
||||
long[] values = new long[] { reloc.getSymbolIndex() };
|
||||
|
||||
byte[] bytes = elf.is64Bit() ? new byte[8] : new byte[4];
|
||||
|
||||
if (relrRelocationType != 0) {
|
||||
type = relrRelocationType;
|
||||
reloc.setType(relrRelocationType);
|
||||
|
@ -927,8 +925,6 @@ class ElfProgramBuilder extends MemorySectionResolver implements ElfLoadHelper {
|
|||
}
|
||||
}
|
||||
|
||||
memory.getBytes(relocAddr, bytes);
|
||||
|
||||
if (context != null) {
|
||||
if (relrTypeUnknown) {
|
||||
ElfRelocationHandler.markAsUnsupportedRelr(program, relocAddr);
|
||||
|
@ -948,7 +944,7 @@ class ElfProgramBuilder extends MemorySectionResolver implements ElfLoadHelper {
|
|||
finally {
|
||||
// Save relocation data
|
||||
program.getRelocationTable()
|
||||
.add(relocAddr, reloc.getType(), values, bytes, symbolName);
|
||||
.add(relocAddr, reloc.getType(), values, null, symbolName);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -957,13 +953,14 @@ class ElfProgramBuilder extends MemorySectionResolver implements ElfLoadHelper {
|
|||
public long getOriginalValue(Address addr, boolean signExtend) throws MemoryAccessException {
|
||||
byte[] bytes;
|
||||
int len = elf.is64Bit() ? 8 : 4;
|
||||
Relocation relocation = program.getRelocationTable().getRelocation(addr);
|
||||
if (relocation == null) {
|
||||
List<Relocation> relocations = program.getRelocationTable().getRelocations(addr);
|
||||
if (relocations.isEmpty()) {
|
||||
bytes = new byte[len];
|
||||
memory.getBytes(addr, bytes);
|
||||
}
|
||||
else {
|
||||
bytes = relocation.getBytes();
|
||||
// use bytes from first relocation
|
||||
bytes = relocations.get(0).getBytes();
|
||||
}
|
||||
DataConverter dataConverter = DataConverter.getInstance(elf.isBigEndian());
|
||||
return signExtend ? dataConverter.getSignedValue(bytes, len)
|
||||
|
@ -972,23 +969,18 @@ class ElfProgramBuilder extends MemorySectionResolver implements ElfLoadHelper {
|
|||
|
||||
@Override
|
||||
public boolean addFakeRelocTableEntry(Address address, int length)
|
||||
throws MemoryAccessException, AddressOverflowException {
|
||||
byte[] bytes = new byte[length];
|
||||
throws AddressOverflowException {
|
||||
Address maxAddr = address.addNoWrap(length - 1);
|
||||
RelocationTable relocationTable = program.getRelocationTable();
|
||||
Relocation relocation = relocationTable.getRelocation(address);
|
||||
if (relocation != null) {
|
||||
List<Relocation> relocations = relocationTable.getRelocations(address);
|
||||
if (!relocations.isEmpty()) {
|
||||
return false;
|
||||
}
|
||||
relocation = relocationTable.getRelocationAfter(address);
|
||||
if (relocation != null && relocation.getAddress().compareTo(maxAddr) <= 0) {
|
||||
Address nextRelocAddr = relocationTable.getRelocationAddressAfter(address);
|
||||
if (nextRelocAddr != null && nextRelocAddr.compareTo(maxAddr) <= 0) {
|
||||
return false;
|
||||
}
|
||||
int cnt = memory.getBytes(address, bytes);
|
||||
if (cnt != length) {
|
||||
throw new MemoryAccessException();
|
||||
}
|
||||
relocationTable.add(address, 0, new long[0], bytes, null);
|
||||
relocationTable.add(address, 0, new long[0], null, null);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
|
@ -1201,7 +1201,6 @@ public class MachoProgramBuilder {
|
|||
while (iter.hasNext()) {
|
||||
RelocationInfo relocationInfo = iter.next();
|
||||
Address address = relocationMap.get(relocationInfo);
|
||||
byte[] origBytes = getOriginalRelocationBytes(relocationInfo, address);
|
||||
MachoRelocation relocation = null;
|
||||
|
||||
if (handler == null) {
|
||||
|
@ -1235,7 +1234,7 @@ public class MachoProgramBuilder {
|
|||
.add(address, relocationInfo.getType(), new long[] { relocationInfo.getValue(),
|
||||
relocationInfo.getLength(), relocationInfo.isPcRelocated() ? 1 : 0,
|
||||
relocationInfo.isExternal() ? 1 : 0, relocationInfo.isScattered() ? 1 : 0 },
|
||||
origBytes, relocation.getTargetDescription());
|
||||
null, relocation.getTargetDescription());
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1477,20 +1476,6 @@ public class MachoProgramBuilder {
|
|||
}
|
||||
}
|
||||
|
||||
private byte[] getOriginalRelocationBytes(RelocationInfo relocation,
|
||||
Address relocationAddress) {
|
||||
|
||||
int relocationSize = (int) Math.pow(2, relocation.getLength());
|
||||
byte[] originalRelocationBytes = new byte[relocationSize];
|
||||
try {
|
||||
memory.getBytes(relocationAddress, originalRelocationBytes);
|
||||
}
|
||||
catch (MemoryAccessException e) {
|
||||
// fall through
|
||||
}
|
||||
return originalRelocationBytes;
|
||||
}
|
||||
|
||||
/**
|
||||
* Fixes up any chained fixups. Relies on the __thread_starts section being present.
|
||||
*
|
||||
|
@ -1655,8 +1640,6 @@ public class MachoProgramBuilder {
|
|||
long imageBaseOffset = program.getImageBase().getOffset();
|
||||
Address chainStart = memory.getProgram().getLanguage().getDefaultSpace().getAddress(page);
|
||||
|
||||
byte origBytes[] = new byte[8];
|
||||
|
||||
long next = -1;
|
||||
boolean start = true;
|
||||
while (next != 0) {
|
||||
|
@ -1718,10 +1701,10 @@ public class MachoProgramBuilder {
|
|||
newChainValue += imageBaseOffset;
|
||||
}
|
||||
|
||||
if (!start || program.getRelocationTable().getRelocation(chainLoc) == null) {
|
||||
if (!start || !program.getRelocationTable().hasRelocation(chainLoc)) {
|
||||
addRelocationTableEntry(chainLoc,
|
||||
(start ? 0x8000 : 0x4000) | (isAuthenticated ? 4 : 0) | (isBound ? 2 : 0) | 1,
|
||||
newChainValue, origBytes, symName);
|
||||
newChainValue, symName);
|
||||
DyldChainedPtr.setChainValue(memory, chainLoc, pointerFormat, newChainValue);
|
||||
}
|
||||
// delay creating data until after memory has been changed
|
||||
|
@ -1733,13 +1716,11 @@ public class MachoProgramBuilder {
|
|||
}
|
||||
}
|
||||
|
||||
private void addRelocationTableEntry(Address chainLoc, int type, long chainValue,
|
||||
byte[] origBytes, String name) throws MemoryAccessException {
|
||||
private void addRelocationTableEntry(Address chainLoc, int type, long chainValue, String name) {
|
||||
if (shouldAddChainedFixupsRelocations) {
|
||||
// Add entry to relocation table for the pointer fixup
|
||||
memory.getBytes(chainLoc, origBytes);
|
||||
program.getRelocationTable()
|
||||
.add(chainLoc, type, new long[] { chainValue }, origBytes, name);
|
||||
.add(chainLoc, type, new long[] { chainValue }, null, name);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -373,8 +373,7 @@ public class MzLoader extends AbstractLibrarySupportLoader {
|
|||
|
||||
// Add to relocation table
|
||||
prog.getRelocationTable()
|
||||
.add(fixupAddr, 0, new long[] { off, seg }, converter.getBytes(value),
|
||||
null);
|
||||
.add(fixupAddr, 0, new long[] { off, seg }, null, null);
|
||||
}
|
||||
}
|
||||
catch (IOException e) {
|
||||
|
|
|
@ -366,7 +366,8 @@ public class PeLoader extends AbstractPeDebugLoader {
|
|||
continue;
|
||||
}
|
||||
int offset = reloc.getOffset(j);
|
||||
long addr = Conv.intToLong(baseAddr + offset) + optionalHeader.getImageBase();
|
||||
long addr =
|
||||
Integer.toUnsignedLong(baseAddr + offset) + optionalHeader.getImageBase();
|
||||
Address relocAddr = space.getAddress(addr);
|
||||
|
||||
try {
|
||||
|
@ -390,7 +391,7 @@ public class PeLoader extends AbstractPeDebugLoader {
|
|||
}
|
||||
}
|
||||
|
||||
relocTable.add(relocAddr, type, null, bytes, null);
|
||||
relocTable.add(relocAddr, type, null, null, null);
|
||||
|
||||
}
|
||||
catch (MemoryAccessException e) {
|
||||
|
@ -437,7 +438,8 @@ public class PeLoader extends AbstractPeDebugLoader {
|
|||
return;
|
||||
}
|
||||
|
||||
long addr = Conv.intToLong(importInfo.getAddress()) + optionalHeader.getImageBase();
|
||||
long addr =
|
||||
Integer.toUnsignedLong(importInfo.getAddress()) + optionalHeader.getImageBase();
|
||||
|
||||
//If not 64bit make sure address is not larger
|
||||
//than 32bit. On WindowsCE some sections are
|
||||
|
|
|
@ -21,18 +21,10 @@ import ghidra.app.util.bin.BinaryReader;
|
|||
import ghidra.app.util.bin.MemoryByteProvider;
|
||||
import ghidra.app.util.bin.format.mz.DOSHeader;
|
||||
import ghidra.app.util.bin.format.pe.Constants;
|
||||
import ghidra.app.util.datatype.microsoft.GuidInfo;
|
||||
import ghidra.app.util.datatype.microsoft.GuidUtil;
|
||||
import ghidra.app.util.opinion.BinaryLoader;
|
||||
import ghidra.app.util.opinion.PeLoader;
|
||||
import ghidra.app.util.opinion.PeLoader.CompilerOpinion.CompilerEnum;
|
||||
import ghidra.program.model.address.*;
|
||||
import ghidra.program.model.data.DataType;
|
||||
import ghidra.program.model.data.TypeDef;
|
||||
import ghidra.program.model.listing.Program;
|
||||
import ghidra.program.model.mem.Memory;
|
||||
import ghidra.program.model.mem.MemoryAccessException;
|
||||
import ghidra.program.model.reloc.Relocation;
|
||||
|
||||
public class PEUtil {
|
||||
|
||||
|
@ -67,70 +59,73 @@ public class PEUtil {
|
|||
program.getCompiler().equals(CompilerEnum.Clang.toString()));
|
||||
}
|
||||
|
||||
static DataType getActualType(DataType dataType) {
|
||||
if (dataType instanceof TypeDef) {
|
||||
return getActualType(((TypeDef) dataType).getDataType());
|
||||
}
|
||||
return dataType;
|
||||
}
|
||||
// TODO: remove if not used
|
||||
|
||||
static boolean isValidPointer(Program program, Address addr) {
|
||||
Memory memory = program.getMemory();
|
||||
AddressFactory addressFactory = program.getAddressFactory();
|
||||
AddressSpace defaultSpace = addressFactory.getDefaultAddressSpace();
|
||||
try {
|
||||
int addrAsInt = memory.getInt(addr);
|
||||
Address pointedToAddr = addressFactory.getAddress(defaultSpace.getSpaceID(), addrAsInt);
|
||||
return memory.contains(pointedToAddr);
|
||||
}
|
||||
catch (MemoryAccessException e) {
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
static boolean isValidGuidPointer(Program program, Address addr) {
|
||||
Memory memory = program.getMemory();
|
||||
AddressFactory addressFactory = program.getAddressFactory();
|
||||
AddressSpace defaultSpace = addressFactory.getDefaultAddressSpace();
|
||||
try {
|
||||
int addrAsInt = memory.getInt(addr);
|
||||
Address pointedToAddr = addressFactory.getAddress(defaultSpace.getSpaceID(), addrAsInt);
|
||||
if (memory.contains(pointedToAddr)) {
|
||||
GuidInfo guidInfo = GuidUtil.getKnownGuid(program, pointedToAddr);
|
||||
if (guidInfo != null) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (MemoryAccessException e) {
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
static long getBytesToEndOfBlock(Program program, Address addr) {
|
||||
Memory memory = program.getMemory();
|
||||
Address endAddr = memory.getBlock(addr).getEnd();
|
||||
return endAddr.subtract(addr);
|
||||
}
|
||||
|
||||
static long getBytesToNextReferredToAddress(Program program, Address addr) {
|
||||
AddressIterator refIter =
|
||||
program.getReferenceManager().getReferenceDestinationIterator(addr.add(1L), true);
|
||||
if (refIter.hasNext()) {
|
||||
Address nextAddr = refIter.next();
|
||||
if (nextAddr != null) {
|
||||
return nextAddr.subtract(addr);
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static long getBytesToNextRelocation(Program program, Address addr) {
|
||||
Relocation nextReloc = program.getRelocationTable().getRelocationAfter(addr);
|
||||
if (nextReloc != null) {
|
||||
return nextReloc.getAddress().subtract(addr);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
// static DataType getActualType(DataType dataType) {
|
||||
// if (dataType instanceof TypeDef) {
|
||||
// return getActualType(((TypeDef) dataType).getDataType());
|
||||
// }
|
||||
// return dataType;
|
||||
// }
|
||||
//
|
||||
// static boolean isValidPointer(Program program, Address addr) {
|
||||
// Memory memory = program.getMemory();
|
||||
// AddressFactory addressFactory = program.getAddressFactory();
|
||||
// AddressSpace defaultSpace = addressFactory.getDefaultAddressSpace();
|
||||
// try {
|
||||
// int addrAsInt = memory.getInt(addr);
|
||||
// Address pointedToAddr = addressFactory.getAddress(defaultSpace.getSpaceID(), addrAsInt);
|
||||
// return memory.contains(pointedToAddr);
|
||||
// }
|
||||
// catch (MemoryAccessException e) {
|
||||
// }
|
||||
// return false;
|
||||
// }
|
||||
//
|
||||
// static boolean isValidGuidPointer(Program program, Address addr) {
|
||||
// Memory memory = program.getMemory();
|
||||
// AddressFactory addressFactory = program.getAddressFactory();
|
||||
// AddressSpace defaultSpace = addressFactory.getDefaultAddressSpace();
|
||||
// try {
|
||||
// int addrAsInt = memory.getInt(addr);
|
||||
// Address pointedToAddr = addressFactory.getAddress(defaultSpace.getSpaceID(), addrAsInt);
|
||||
// if (memory.contains(pointedToAddr)) {
|
||||
// GuidInfo guidInfo = GuidUtil.getKnownGuid(program, pointedToAddr);
|
||||
// if (guidInfo != null) {
|
||||
// return true;
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// catch (MemoryAccessException e) {
|
||||
// }
|
||||
// return false;
|
||||
// }
|
||||
//
|
||||
// static long getBytesToEndOfBlock(Program program, Address addr) {
|
||||
// Memory memory = program.getMemory();
|
||||
// Address endAddr = memory.getBlock(addr).getEnd();
|
||||
// return endAddr.subtract(addr);
|
||||
// }
|
||||
//
|
||||
// static long getBytesToNextReferredToAddress(Program program, Address addr) {
|
||||
// AddressIterator refIter =
|
||||
// program.getReferenceManager().getReferenceDestinationIterator(addr.add(1L), true);
|
||||
// if (refIter.hasNext()) {
|
||||
// Address nextAddr = refIter.next();
|
||||
// if (nextAddr != null) {
|
||||
// return nextAddr.subtract(addr);
|
||||
// }
|
||||
// }
|
||||
// return 0;
|
||||
// }
|
||||
//
|
||||
// static long getBytesToNextRelocation(Program program, Address addr) {
|
||||
// Address nextRelocAddr = program.getRelocationTable().getRelocationAddressAfter(addr);
|
||||
// if (nextRelocAddr != null &&
|
||||
// addr.getAddressSpace().equals(nextRelocAddr.getAddressSpace())) {
|
||||
// return nextRelocAddr.subtract(addr);
|
||||
// }
|
||||
// return 0;
|
||||
// }
|
||||
|
||||
}
|
||||
|
|
|
@ -26,31 +26,30 @@ import ghidra.util.task.TaskMonitor;
|
|||
|
||||
abstract class RelocationDBAdapter {
|
||||
|
||||
final static int TYPE_COL = 0;
|
||||
final static int VALU_COL = 1;
|
||||
final static int BYTES_COL = 2;
|
||||
final static int SYMBOL_NAME_COL = 3;
|
||||
// History:
|
||||
// V1 - added Type
|
||||
// V2 - added Value
|
||||
// V3 - added Bytes
|
||||
// V4 - added Name, switched Value to binary coded long[] from long
|
||||
// V5 - moved Addr key to column and indexed, use one-up key
|
||||
|
||||
final static int ADDR_COL = 0; // indexed
|
||||
final static int TYPE_COL = 1;
|
||||
final static int VALUE_COL = 2;
|
||||
final static int BYTES_COL = 3;
|
||||
final static int SYMBOL_NAME_COL = 4;
|
||||
|
||||
final static String TABLE_NAME = "Relocations";
|
||||
|
||||
final static Schema SCHEMA = new Schema(
|
||||
RelocationDBAdapterV4.VERSION, "Address", new Field[] { IntField.INSTANCE,
|
||||
RelocationDBAdapterV5.VERSION, "Index", new Field[] { LongField.INSTANCE, IntField.INSTANCE,
|
||||
BinaryField.INSTANCE, BinaryField.INSTANCE, StringField.INSTANCE },
|
||||
new String[] { "Type", "Values", "Bytes", "Symbol Name" });
|
||||
new String[] { "Address", "Type", "Values", "Bytes", "Symbol Name" });
|
||||
|
||||
static RelocationDBAdapter getAdapter(DBHandle dbHandle, int openMode, AddressMap addrMap,
|
||||
TaskMonitor monitor) throws VersionException, IOException {
|
||||
|
||||
if (openMode == DBConstants.CREATE) {
|
||||
return new RelocationDBAdapterV4(dbHandle, addrMap, true);
|
||||
}
|
||||
|
||||
try {
|
||||
RelocationDBAdapter adapter = new RelocationDBAdapterV4(dbHandle, addrMap, false);
|
||||
if (addrMap.isUpgraded()) {
|
||||
throw new VersionException(true);
|
||||
}
|
||||
return adapter;
|
||||
return new RelocationDBAdapterV5(dbHandle, addrMap, openMode == DBConstants.CREATE);
|
||||
}
|
||||
catch (VersionException e) {
|
||||
if (!e.isUpgradable() || openMode == DBConstants.UPDATE) {
|
||||
|
@ -65,9 +64,15 @@ abstract class RelocationDBAdapter {
|
|||
}
|
||||
|
||||
private static RelocationDBAdapter findReadOnlyAdapter(DBHandle handle, AddressMap addrMap)
|
||||
throws IOException {
|
||||
throws IOException, VersionException {
|
||||
try {
|
||||
return new RelocationDBAdapterV3(handle, addrMap, false);
|
||||
return new RelocationDBAdapterV4(handle, addrMap);
|
||||
}
|
||||
catch (VersionException e) {
|
||||
// try the next version
|
||||
}
|
||||
try {
|
||||
return new RelocationDBAdapterV3(handle, addrMap);
|
||||
}
|
||||
catch (VersionException e) {
|
||||
// try the next version
|
||||
|
@ -84,7 +89,7 @@ abstract class RelocationDBAdapter {
|
|||
catch (VersionException e) {
|
||||
// try the next version
|
||||
}
|
||||
return new RelocationDBAdapterNoTable();
|
||||
return new RelocationDBAdapterNoTable(handle);
|
||||
}
|
||||
|
||||
private static RelocationDBAdapter upgrade(DBHandle dbHandle, AddressMap addrMap,
|
||||
|
@ -97,27 +102,27 @@ abstract class RelocationDBAdapter {
|
|||
try {
|
||||
tmpHandle.startTransaction();
|
||||
|
||||
RelocationDBAdapter tmpAdapter = new RelocationDBAdapterV4(tmpHandle, addrMap, true);
|
||||
RelocationDBAdapter tmpAdapter = new RelocationDBAdapterV5(tmpHandle, addrMap, true);
|
||||
RecordIterator iter = oldAdapter.iterator();
|
||||
while (iter.hasNext()) {
|
||||
DBRecord rec = iter.next();
|
||||
Address addr = oldAddrMap.decodeAddress(rec.getKey());
|
||||
// decode with old address map
|
||||
Address addr = oldAddrMap.decodeAddress(rec.getLongValue(ADDR_COL));
|
||||
BinaryCodedField values =
|
||||
new BinaryCodedField((BinaryField) rec.getFieldValue(VALU_COL));
|
||||
tmpAdapter.add(addrMap.getKey(addr, true), rec.getIntValue(TYPE_COL),
|
||||
values.getLongArray(), null /* bytes */, null /* symbol name */);
|
||||
new BinaryCodedField((BinaryField) rec.getFieldValue(VALUE_COL));
|
||||
tmpAdapter.add(addr, rec.getIntValue(TYPE_COL),
|
||||
values.getLongArray(), rec.getBinaryData(BYTES_COL),
|
||||
rec.getString(SYMBOL_NAME_COL));
|
||||
}
|
||||
|
||||
dbHandle.deleteTable(TABLE_NAME);
|
||||
RelocationDBAdapter newAdapter = new RelocationDBAdapterV4(dbHandle, addrMap, true);
|
||||
|
||||
RelocationDBAdapterV5 newAdapter = new RelocationDBAdapterV5(dbHandle, addrMap, true);
|
||||
|
||||
iter = tmpAdapter.iterator();
|
||||
while (iter.hasNext()) {
|
||||
DBRecord rec = iter.next();
|
||||
BinaryCodedField values =
|
||||
new BinaryCodedField((BinaryField) rec.getFieldValue(VALU_COL));
|
||||
newAdapter.add(rec.getKey(), rec.getIntValue(TYPE_COL), values.getLongArray(),
|
||||
null /* bytes */, null /* symbol name */);
|
||||
newAdapter.add(rec);
|
||||
}
|
||||
return newAdapter;
|
||||
}
|
||||
|
@ -130,23 +135,52 @@ abstract class RelocationDBAdapter {
|
|||
// Adapter Required Methods
|
||||
//==================================================================================================
|
||||
|
||||
abstract void add(long addrKey, int type, long[] values, byte[] bytes, String symbolName)
|
||||
/**
|
||||
* Add new relocation record
|
||||
* @param addr relocation address
|
||||
* @param type relocation type
|
||||
* @param values relocation value (e.g., symbol index)
|
||||
* @param bytes original memory bytes
|
||||
* @param symbolName symbol name
|
||||
* @throws IOException if a database error occurs
|
||||
*/
|
||||
abstract void add(Address addr, int type, long[] values, byte[] bytes, String symbolName)
|
||||
throws IOException;
|
||||
|
||||
abstract void remove(long addrKey) throws IOException;
|
||||
|
||||
abstract DBRecord get(long addrKey) throws IOException;
|
||||
|
||||
/**
|
||||
* Iterator over all records in address order.
|
||||
* @return record iterator
|
||||
* @throws IOException if a database error occurs
|
||||
*/
|
||||
abstract RecordIterator iterator() throws IOException;
|
||||
|
||||
/**
|
||||
* Iterator over all relocation records in address order constrained by the specified address set.
|
||||
* @param set address set constraint
|
||||
* @return record iterator
|
||||
* @throws IOException if a database error occurs
|
||||
*/
|
||||
abstract RecordIterator iterator(AddressSetView set) throws IOException;
|
||||
|
||||
/**
|
||||
* Iterate over relocation records starting at specified start address.
|
||||
* @param start start address
|
||||
* @return relocation record iterator
|
||||
* @throws IOException if a database error occurs
|
||||
*/
|
||||
abstract RecordIterator iterator(Address start) throws IOException;
|
||||
|
||||
abstract int getVersion();
|
||||
|
||||
/**
|
||||
* Get the total number of relocation records
|
||||
* @return total number of relocation records
|
||||
*/
|
||||
abstract int getRecordCount();
|
||||
|
||||
/**
|
||||
* Translate relocation record to latest schema format
|
||||
* @param rec old record requiring translation
|
||||
* @return translated relocation record
|
||||
*/
|
||||
abstract DBRecord adaptRecord(DBRecord rec);
|
||||
|
||||
//==================================================================================================
|
||||
|
|
|
@ -15,16 +15,13 @@
|
|||
*/
|
||||
package ghidra.program.database.reloc;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import db.*;
|
||||
import ghidra.program.database.util.EmptyRecordIterator;
|
||||
import ghidra.program.model.address.Address;
|
||||
import ghidra.program.model.address.AddressSetView;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import java.lang.UnsupportedOperationException;
|
||||
|
||||
import db.DBRecord;
|
||||
import db.RecordIterator;
|
||||
import ghidra.util.exception.VersionException;
|
||||
|
||||
/**
|
||||
* A stub for a time when we did not produce these tables.
|
||||
|
@ -32,14 +29,22 @@ import db.RecordIterator;
|
|||
class RelocationDBAdapterNoTable extends RelocationDBAdapter {
|
||||
final static int VERSION = 0;
|
||||
|
||||
@Override
|
||||
void add(long addrKey, int type, long[] values, byte[] bytes, String symbolName) {
|
||||
throw new UnsupportedOperationException();
|
||||
/**
|
||||
* Construct V0 read-only adapter
|
||||
* @param handle database adapter
|
||||
* @throws IOException if database IO error occurs
|
||||
* @throws VersionException throw if table schema is not V0
|
||||
*/
|
||||
RelocationDBAdapterNoTable(DBHandle handle) throws IOException, VersionException {
|
||||
Table relocTable = handle.getTable(TABLE_NAME);
|
||||
if (relocTable != null) {
|
||||
throw new VersionException();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
DBRecord get(long addrKey) {
|
||||
return null;
|
||||
void add(Address addrKey, int type, long[] values, byte[] bytes, String symbolName) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -47,16 +52,6 @@ class RelocationDBAdapterNoTable extends RelocationDBAdapter {
|
|||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
int getVersion() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
void remove(long addrKey) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
RecordIterator iterator() throws IOException {
|
||||
return new EmptyRecordIterator();
|
||||
|
|
|
@ -15,59 +15,53 @@
|
|||
*/
|
||||
package ghidra.program.database.reloc;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import db.*;
|
||||
import ghidra.program.database.map.AddressKeyRecordIterator;
|
||||
import ghidra.program.database.map.AddressMap;
|
||||
import ghidra.program.model.address.Address;
|
||||
import ghidra.program.model.address.AddressSetView;
|
||||
import ghidra.util.exception.VersionException;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import java.lang.UnsupportedOperationException;
|
||||
|
||||
import db.*;
|
||||
|
||||
class RelocationDBAdapterV1 extends RelocationDBAdapter {
|
||||
final static int VERSION = 1;
|
||||
|
||||
private final static int V1_TYPE_COL = 0;
|
||||
|
||||
// final static Schema SCHEMA = new Schema(
|
||||
// RelocationDBAdapterV4.VERSION, "Address", new Field[] { IntField.INSTANCE },
|
||||
// new String[] { "Type" });
|
||||
|
||||
private Table relocTable;
|
||||
private AddressMap addrMap;
|
||||
|
||||
RelocationDBAdapterV1(DBHandle handle, AddressMap addrMap) throws VersionException {
|
||||
this.addrMap = addrMap.getOldAddressMap();
|
||||
/**
|
||||
* Construct V1 read-only adapter
|
||||
* @param handle database adapter
|
||||
* @param addrMap address map for decode
|
||||
* @throws IOException if database IO error occurs
|
||||
* @throws VersionException throw if table schema is not V1
|
||||
*/
|
||||
RelocationDBAdapterV1(DBHandle handle, AddressMap addrMap) throws IOException,
|
||||
VersionException {
|
||||
this.addrMap = addrMap;
|
||||
relocTable = handle.getTable(TABLE_NAME);
|
||||
if (relocTable == null) {
|
||||
throw new VersionException("Missing Table: " + TABLE_NAME);
|
||||
}
|
||||
else if (relocTable.getSchema().getVersion() != VERSION) {
|
||||
throw new VersionException(false);
|
||||
if (relocTable == null || relocTable.getSchema().getVersion() != VERSION) {
|
||||
throw new VersionException();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
void add(long addrKey, int type, long[] values, byte[] bytes, String symbolName) {
|
||||
void add(Address addrKey, int type, long[] values, byte[] bytes, String symbolName) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
DBRecord get(long addrKey) throws IOException {
|
||||
return relocTable.getRecord(addrKey);
|
||||
}
|
||||
|
||||
@Override
|
||||
int getRecordCount() {
|
||||
return relocTable.getRecordCount();
|
||||
}
|
||||
|
||||
@Override
|
||||
int getVersion() {
|
||||
return VERSION;
|
||||
}
|
||||
|
||||
@Override
|
||||
void remove(long addrKey) throws IOException {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
RecordIterator iterator() throws IOException {
|
||||
RecordIterator recIter = new AddressKeyRecordIterator(relocTable, addrMap);
|
||||
|
@ -89,9 +83,12 @@ class RelocationDBAdapterV1 extends RelocationDBAdapter {
|
|||
|
||||
@Override
|
||||
DBRecord adaptRecord(DBRecord rec) {
|
||||
if (rec == null) {
|
||||
return null;
|
||||
}
|
||||
DBRecord newRec = SCHEMA.createRecord(rec.getKey());
|
||||
newRec.setIntValue(TYPE_COL, rec.getIntValue(TYPE_COL));
|
||||
newRec.setBinaryData(BYTES_COL, null);
|
||||
newRec.setLongValue(ADDR_COL, rec.getKey()); // key was encoded address
|
||||
newRec.setIntValue(TYPE_COL, rec.getIntValue(V1_TYPE_COL));
|
||||
return newRec;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -15,59 +15,55 @@
|
|||
*/
|
||||
package ghidra.program.database.reloc;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import db.*;
|
||||
import ghidra.program.database.map.AddressKeyRecordIterator;
|
||||
import ghidra.program.database.map.AddressMap;
|
||||
import ghidra.program.model.address.Address;
|
||||
import ghidra.program.model.address.AddressSetView;
|
||||
import ghidra.util.exception.VersionException;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import java.lang.UnsupportedOperationException;
|
||||
|
||||
import db.*;
|
||||
|
||||
class RelocationDBAdapterV2 extends RelocationDBAdapter {
|
||||
final static int VERSION = 2;
|
||||
|
||||
private final static int V2_TYPE_COL = 0;
|
||||
private final static int V2_VALUE_COL = 1;
|
||||
|
||||
// final static Schema SCHEMA = new Schema(
|
||||
// RelocationDBAdapterV4.VERSION, "Address", new Field[] { IntField.INSTANCE,
|
||||
// LongField.INSTANCE },
|
||||
// new String[] { "Type", "Values" });
|
||||
|
||||
private Table relocTable;
|
||||
private AddressMap addrMap;
|
||||
|
||||
RelocationDBAdapterV2(DBHandle handle, AddressMap addrMap) throws VersionException {
|
||||
this.addrMap = addrMap.getOldAddressMap();
|
||||
/**
|
||||
* Construct V2 read-only adapter
|
||||
* @param handle database adapter
|
||||
* @param addrMap address map for decode
|
||||
* @throws IOException if database IO error occurs
|
||||
* @throws VersionException throw if table schema is not V2
|
||||
*/
|
||||
RelocationDBAdapterV2(DBHandle handle, AddressMap addrMap) throws IOException,
|
||||
VersionException {
|
||||
this.addrMap = addrMap;
|
||||
relocTable = handle.getTable(TABLE_NAME);
|
||||
if (relocTable == null) {
|
||||
throw new VersionException("Missing Table: " + TABLE_NAME);
|
||||
}
|
||||
else if (relocTable.getSchema().getVersion() != VERSION) {
|
||||
throw new VersionException(false);
|
||||
if (relocTable == null || relocTable.getSchema().getVersion() != VERSION) {
|
||||
throw new VersionException();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
void add(long addrKey, int type, long[] values, byte[] bytes, String symbolName) {
|
||||
void add(Address addrKey, int type, long[] values, byte[] bytes, String symbolName) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
DBRecord get(long addrKey) throws IOException {
|
||||
return relocTable.getRecord(addrKey);
|
||||
}
|
||||
|
||||
@Override
|
||||
int getRecordCount() {
|
||||
return relocTable.getRecordCount();
|
||||
}
|
||||
|
||||
@Override
|
||||
int getVersion() {
|
||||
return VERSION;
|
||||
}
|
||||
|
||||
@Override
|
||||
void remove(long addrKey) throws IOException {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
RecordIterator iterator() throws IOException {
|
||||
RecordIterator recIter = new AddressKeyRecordIterator(relocTable, addrMap);
|
||||
|
@ -89,11 +85,14 @@ class RelocationDBAdapterV2 extends RelocationDBAdapter {
|
|||
|
||||
@Override
|
||||
DBRecord adaptRecord(DBRecord rec) {
|
||||
if (rec == null) {
|
||||
return null;
|
||||
}
|
||||
DBRecord newRec = SCHEMA.createRecord(rec.getKey());
|
||||
newRec.setIntValue(TYPE_COL, rec.getIntValue(TYPE_COL));
|
||||
long[] values = new long[] { rec.getLongValue(VALU_COL) };
|
||||
newRec.setField(VALU_COL, new BinaryCodedField(values));
|
||||
newRec.setBinaryData(BYTES_COL, null);
|
||||
newRec.setLongValue(ADDR_COL, rec.getKey()); // key was encoded address
|
||||
newRec.setIntValue(TYPE_COL, rec.getIntValue(V2_TYPE_COL));
|
||||
long[] values = new long[] { rec.getLongValue(V2_VALUE_COL) };
|
||||
newRec.setField(VALUE_COL, new BinaryCodedField(values));
|
||||
return newRec;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -15,93 +15,88 @@
|
|||
*/
|
||||
package ghidra.program.database.reloc;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import db.*;
|
||||
import ghidra.program.database.map.AddressKeyRecordIterator;
|
||||
import ghidra.program.database.map.AddressMap;
|
||||
import ghidra.program.model.address.Address;
|
||||
import ghidra.program.model.address.AddressSetView;
|
||||
import ghidra.util.exception.VersionException;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import java.lang.UnsupportedOperationException;
|
||||
|
||||
import db.*;
|
||||
|
||||
class RelocationDBAdapterV3 extends RelocationDBAdapter {
|
||||
|
||||
final static int VERSION = 3;
|
||||
|
||||
private final static int V3_TYPE_COL = 0;
|
||||
private final static int V3_VALUE_COL = 1;
|
||||
private final static int V3_BYTES_COL = 2;
|
||||
|
||||
// final static Schema SCHEMA = new Schema(
|
||||
// RelocationDBAdapterV4.VERSION, "Address", new Field[] { IntField.INSTANCE,
|
||||
// LongField.INSTANCE, BinaryField.INSTANCE },
|
||||
// new String[] { "Type", "Values", "Bytes" });
|
||||
|
||||
private Table relocTable;
|
||||
private AddressMap addrMap;
|
||||
|
||||
RelocationDBAdapterV3(DBHandle handle, AddressMap addrMap, boolean create) throws IOException,
|
||||
/**
|
||||
* Construct V3 read-only adapter
|
||||
* @param handle database adapter
|
||||
* @param addrMap address map for decode
|
||||
* @throws IOException if database IO error occurs
|
||||
* @throws VersionException throw if table schema is not V3
|
||||
*/
|
||||
RelocationDBAdapterV3(DBHandle handle, AddressMap addrMap) throws IOException,
|
||||
VersionException {
|
||||
this.addrMap = addrMap;
|
||||
if (create) {
|
||||
relocTable = handle.createTable(TABLE_NAME, SCHEMA);
|
||||
}
|
||||
else {
|
||||
relocTable = handle.getTable(TABLE_NAME);
|
||||
if (relocTable == null) {
|
||||
throw new VersionException("Missing Table: " + TABLE_NAME);
|
||||
}
|
||||
else if (relocTable.getSchema().getVersion() != VERSION) {
|
||||
int version = relocTable.getSchema().getVersion();
|
||||
if (version < VERSION) {
|
||||
throw new VersionException(true);
|
||||
}
|
||||
throw new VersionException(VersionException.NEWER_VERSION, false);
|
||||
}
|
||||
relocTable = handle.getTable(TABLE_NAME);
|
||||
if (relocTable == null || relocTable.getSchema().getVersion() != VERSION) {
|
||||
throw new VersionException();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
void add(long addrKey, int type, long[] values, byte[] bytes, String symbolName)
|
||||
void add(Address addrKey, int type, long[] values, byte[] bytes, String symbolName)
|
||||
throws IOException {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
DBRecord get(long addrKey) throws IOException {
|
||||
return relocTable.getRecord(addrKey);
|
||||
}
|
||||
|
||||
@Override
|
||||
void remove(long addrKey) throws IOException {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
int getRecordCount() {
|
||||
return relocTable.getRecordCount();
|
||||
}
|
||||
|
||||
@Override
|
||||
int getVersion() {
|
||||
return VERSION;
|
||||
}
|
||||
|
||||
@Override
|
||||
RecordIterator iterator() throws IOException {
|
||||
return new AddressKeyRecordIterator(relocTable, addrMap);
|
||||
RecordIterator recIter = new AddressKeyRecordIterator(relocTable, addrMap);
|
||||
return new RecordIteratorAdapter(recIter);
|
||||
}
|
||||
|
||||
@Override
|
||||
RecordIterator iterator(AddressSetView set) throws IOException {
|
||||
return new AddressKeyRecordIterator(relocTable, addrMap, set, set.getMinAddress(), true);
|
||||
RecordIterator recIter =
|
||||
new AddressKeyRecordIterator(relocTable, addrMap, set, set.getMinAddress(), true);
|
||||
return new RecordIteratorAdapter(recIter);
|
||||
}
|
||||
|
||||
@Override
|
||||
RecordIterator iterator(Address start) throws IOException {
|
||||
return new AddressKeyRecordIterator(relocTable, addrMap, start, true);
|
||||
RecordIterator recIter = new AddressKeyRecordIterator(relocTable, addrMap, start, true);
|
||||
return new RecordIteratorAdapter(recIter);
|
||||
}
|
||||
|
||||
@Override
|
||||
DBRecord adaptRecord(DBRecord rec) {
|
||||
if (rec == null) {
|
||||
return null;
|
||||
}
|
||||
DBRecord newRec = SCHEMA.createRecord(rec.getKey());
|
||||
newRec.setIntValue(TYPE_COL, rec.getIntValue(TYPE_COL));
|
||||
long[] values = new long[] { rec.getLongValue(VALU_COL) };
|
||||
newRec.setField(VALU_COL, new BinaryCodedField(values));
|
||||
newRec.setBinaryData(BYTES_COL, null);
|
||||
newRec.setString(SYMBOL_NAME_COL, null);
|
||||
newRec.setLongValue(ADDR_COL, rec.getKey()); // key was encoded address
|
||||
newRec.setIntValue(TYPE_COL, rec.getIntValue(V3_TYPE_COL));
|
||||
long[] values = new long[] { rec.getLongValue(V3_VALUE_COL) };
|
||||
newRec.setField(VALUE_COL, new BinaryCodedField(values));
|
||||
newRec.setBinaryData(BYTES_COL, rec.getBinaryData(V3_BYTES_COL));
|
||||
return newRec;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -15,63 +15,51 @@
|
|||
*/
|
||||
package ghidra.program.database.reloc;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import db.*;
|
||||
import ghidra.program.database.map.AddressKeyRecordIterator;
|
||||
import ghidra.program.database.map.AddressMap;
|
||||
import ghidra.program.model.address.Address;
|
||||
import ghidra.program.model.address.AddressSetView;
|
||||
import ghidra.util.exception.VersionException;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import java.lang.UnsupportedOperationException;
|
||||
|
||||
import db.*;
|
||||
|
||||
public class RelocationDBAdapterV4 extends RelocationDBAdapter {
|
||||
final static int VERSION = 4;
|
||||
|
||||
private final static int V4_TYPE_COL = 0;
|
||||
private final static int V4_VALUE_COL = 1;
|
||||
private final static int V4_BYTES_COL = 2;
|
||||
private final static int V4_SYMBOL_NAME_COL = 3;
|
||||
|
||||
// final static Schema SCHEMA = new Schema(
|
||||
// RelocationDBAdapterV4.VERSION, "Address", new Field[] { IntField.INSTANCE,
|
||||
// BinaryField.INSTANCE, BinaryField.INSTANCE, StringField.INSTANCE },
|
||||
// new String[] { "Type", "Values", "Bytes", "Symbol Name" });
|
||||
|
||||
private Table relocTable;
|
||||
private AddressMap addrMap;
|
||||
|
||||
RelocationDBAdapterV4(DBHandle handle, AddressMap addrMap, boolean create) throws IOException,
|
||||
/**
|
||||
* Construct V4 read-only adapter
|
||||
* @param handle database adapter
|
||||
* @param addrMap address map for decode
|
||||
* @throws IOException if database IO error occurs
|
||||
* @throws VersionException throw if table schema is not V4
|
||||
*/
|
||||
RelocationDBAdapterV4(DBHandle handle, AddressMap addrMap) throws IOException,
|
||||
VersionException {
|
||||
this.addrMap = addrMap;
|
||||
if (create) {
|
||||
relocTable = handle.createTable(TABLE_NAME, SCHEMA);
|
||||
}
|
||||
else {
|
||||
relocTable = handle.getTable(TABLE_NAME);
|
||||
if (relocTable == null) {
|
||||
throw new VersionException("Missing Table: " + TABLE_NAME);
|
||||
}
|
||||
else if (relocTable.getSchema().getVersion() != VERSION) {
|
||||
int version = relocTable.getSchema().getVersion();
|
||||
if (version < VERSION) {
|
||||
throw new VersionException(true);
|
||||
}
|
||||
throw new VersionException(VersionException.NEWER_VERSION, false);
|
||||
}
|
||||
relocTable = handle.getTable(TABLE_NAME);
|
||||
if (relocTable == null || relocTable.getSchema().getVersion() != VERSION) {
|
||||
throw new VersionException();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
void add(long addrKey, int type, long[] values, byte[] bytes, String symbolName)
|
||||
void add(Address addr, int type, long[] values, byte[] bytes, String symbolName)
|
||||
throws IOException {
|
||||
DBRecord r = SCHEMA.createRecord(addrKey);
|
||||
r.setIntValue(TYPE_COL, type);
|
||||
r.setField(VALU_COL, new BinaryCodedField(values));
|
||||
r.setBinaryData(BYTES_COL, bytes);
|
||||
r.setString(SYMBOL_NAME_COL, symbolName);
|
||||
relocTable.putRecord(r);
|
||||
}
|
||||
|
||||
@Override
|
||||
DBRecord get(long addrKey) throws IOException {
|
||||
return relocTable.getRecord(addrKey);
|
||||
}
|
||||
|
||||
@Override
|
||||
int getVersion() {
|
||||
return VERSION;
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -79,30 +67,37 @@ public class RelocationDBAdapterV4 extends RelocationDBAdapter {
|
|||
return relocTable.getRecordCount();
|
||||
}
|
||||
|
||||
@Override
|
||||
void remove(long addrKey) throws IOException {
|
||||
relocTable.deleteRecord(addrKey);
|
||||
}
|
||||
|
||||
@Override
|
||||
RecordIterator iterator() throws IOException {
|
||||
return new AddressKeyRecordIterator(relocTable, addrMap);
|
||||
RecordIterator recIter = new AddressKeyRecordIterator(relocTable, addrMap);
|
||||
return new RecordIteratorAdapter(recIter);
|
||||
}
|
||||
|
||||
@Override
|
||||
RecordIterator iterator(AddressSetView set) throws IOException {
|
||||
return new AddressKeyRecordIterator(relocTable, addrMap, set, set.getMinAddress(), true);
|
||||
RecordIterator recIter =
|
||||
new AddressKeyRecordIterator(relocTable, addrMap, set, set.getMinAddress(), true);
|
||||
return new RecordIteratorAdapter(recIter);
|
||||
}
|
||||
|
||||
@Override
|
||||
RecordIterator iterator(Address start) throws IOException {
|
||||
return new AddressKeyRecordIterator(relocTable, addrMap, start, true);
|
||||
RecordIterator recIter = new AddressKeyRecordIterator(relocTable, addrMap, start, true);
|
||||
return new RecordIteratorAdapter(recIter);
|
||||
}
|
||||
|
||||
@Override
|
||||
DBRecord adaptRecord(DBRecord rec) {
|
||||
// my guess is that we don't need to do this until there is a version newer than us
|
||||
throw new UnsupportedOperationException("Don't know how to adapt to the new version");
|
||||
if (rec == null) {
|
||||
return null;
|
||||
}
|
||||
DBRecord newRec = SCHEMA.createRecord(rec.getKey());
|
||||
newRec.setLongValue(ADDR_COL, rec.getKey()); // key was encoded address
|
||||
newRec.setIntValue(TYPE_COL, rec.getIntValue(V4_TYPE_COL));
|
||||
newRec.setBinaryData(VALUE_COL, rec.getBinaryData(V4_VALUE_COL)); // binary coded long[]
|
||||
newRec.setBinaryData(BYTES_COL, rec.getBinaryData(V4_BYTES_COL));
|
||||
newRec.setString(SYMBOL_NAME_COL, rec.getString(V4_SYMBOL_NAME_COL));
|
||||
return newRec;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -0,0 +1,101 @@
|
|||
/* ###
|
||||
* 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.program.database.reloc;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import db.*;
|
||||
import ghidra.program.database.map.AddressIndexPrimaryKeyIterator;
|
||||
import ghidra.program.database.map.AddressMap;
|
||||
import ghidra.program.model.address.Address;
|
||||
import ghidra.program.model.address.AddressSetView;
|
||||
import ghidra.util.exception.VersionException;
|
||||
|
||||
public class RelocationDBAdapterV5 extends RelocationDBAdapter {
|
||||
final static int VERSION = 5;
|
||||
private Table relocTable;
|
||||
private AddressMap addrMap;
|
||||
|
||||
RelocationDBAdapterV5(DBHandle handle, AddressMap addrMap, boolean create) throws IOException,
|
||||
VersionException {
|
||||
this.addrMap = addrMap;
|
||||
if (create) {
|
||||
relocTable = handle.createTable(TABLE_NAME, SCHEMA, new int[] { ADDR_COL });
|
||||
}
|
||||
else {
|
||||
relocTable = handle.getTable(TABLE_NAME);
|
||||
if (relocTable == null) {
|
||||
throw new VersionException(true);
|
||||
}
|
||||
int version = relocTable.getSchema().getVersion();
|
||||
if (version != VERSION) {
|
||||
throw new VersionException(version < VERSION);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
void add(Address addr, int type, long[] values, byte[] bytes, String symbolName)
|
||||
throws IOException {
|
||||
long key = relocTable.getKey();
|
||||
DBRecord r = SCHEMA.createRecord(key);
|
||||
r.setLongValue(ADDR_COL, addrMap.getKey(addr, true));
|
||||
r.setIntValue(TYPE_COL, type);
|
||||
r.setField(VALUE_COL, new BinaryCodedField(values));
|
||||
r.setBinaryData(BYTES_COL, bytes);
|
||||
r.setString(SYMBOL_NAME_COL, symbolName);
|
||||
relocTable.putRecord(r);
|
||||
}
|
||||
|
||||
@Override
|
||||
int getRecordCount() {
|
||||
return relocTable.getRecordCount();
|
||||
}
|
||||
|
||||
@Override
|
||||
RecordIterator iterator() throws IOException {
|
||||
return new KeyToRecordIterator(relocTable, new AddressIndexPrimaryKeyIterator(relocTable,
|
||||
ADDR_COL, addrMap, true));
|
||||
}
|
||||
|
||||
@Override
|
||||
RecordIterator iterator(AddressSetView set) throws IOException {
|
||||
return new KeyToRecordIterator(relocTable, new AddressIndexPrimaryKeyIterator(relocTable,
|
||||
ADDR_COL, addrMap, set, true));
|
||||
}
|
||||
|
||||
@Override
|
||||
RecordIterator iterator(Address start) throws IOException {
|
||||
return new KeyToRecordIterator(relocTable, new AddressIndexPrimaryKeyIterator(relocTable,
|
||||
ADDR_COL, addrMap, start, true));
|
||||
}
|
||||
|
||||
@Override
|
||||
DBRecord adaptRecord(DBRecord rec) {
|
||||
// my guess is that we don't need to do this until there is a version newer than us
|
||||
throw new UnsupportedOperationException("Don't know how to adapt to the new version");
|
||||
}
|
||||
|
||||
/**
|
||||
* Add V5 relocation record to table.
|
||||
* @param rec relocation record
|
||||
* @throws IOException if database IO error occurs
|
||||
*/
|
||||
void add(DBRecord rec) throws IOException {
|
||||
relocTable.putRecord(rec);
|
||||
}
|
||||
|
||||
}
|
|
@ -15,13 +15,20 @@
|
|||
*/
|
||||
package ghidra.program.database.reloc;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.*;
|
||||
|
||||
import db.*;
|
||||
import ghidra.framework.options.Options;
|
||||
import ghidra.program.database.ManagerDB;
|
||||
import ghidra.program.database.ProgramDB;
|
||||
import ghidra.program.database.map.AddressMap;
|
||||
import ghidra.program.database.mem.AddressSourceInfo;
|
||||
import ghidra.program.database.mem.FileBytes;
|
||||
import ghidra.program.model.address.Address;
|
||||
import ghidra.program.model.address.AddressSetView;
|
||||
import ghidra.program.model.listing.Program;
|
||||
import ghidra.program.model.mem.MemoryBlockSourceInfo;
|
||||
import ghidra.program.model.reloc.Relocation;
|
||||
import ghidra.program.model.reloc.RelocationTable;
|
||||
import ghidra.util.Lock;
|
||||
|
@ -29,11 +36,6 @@ import ghidra.util.exception.CancelledException;
|
|||
import ghidra.util.exception.VersionException;
|
||||
import ghidra.util.task.TaskMonitor;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Iterator;
|
||||
|
||||
import db.*;
|
||||
|
||||
/**
|
||||
* An implementation of the relocation table interface.
|
||||
*
|
||||
|
@ -45,6 +47,7 @@ public class RelocationManager implements RelocationTable, ManagerDB {
|
|||
private AddressMap addrMap;
|
||||
private RelocationDBAdapter adapter;
|
||||
private Boolean isRelocatable = null;
|
||||
private Lock lock;
|
||||
|
||||
/**
|
||||
* Constructs a new relocation manager.
|
||||
|
@ -58,8 +61,8 @@ public class RelocationManager implements RelocationTable, ManagerDB {
|
|||
*/
|
||||
public RelocationManager(DBHandle handle, AddressMap addrMap, int openMode, Lock lock,
|
||||
TaskMonitor monitor) throws VersionException, IOException {
|
||||
|
||||
this.addrMap = addrMap;
|
||||
this.lock = lock;
|
||||
initializeAdapters(handle, openMode, monitor);
|
||||
}
|
||||
|
||||
|
@ -70,7 +73,7 @@ public class RelocationManager implements RelocationTable, ManagerDB {
|
|||
|
||||
@Override
|
||||
public void invalidateCache(boolean all) {
|
||||
// guess we don't care
|
||||
// no cache or DB objects
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -84,130 +87,196 @@ public class RelocationManager implements RelocationTable, ManagerDB {
|
|||
// Nothing to do
|
||||
}
|
||||
|
||||
private byte[] getOriginalBytes(Address addr, byte[] bytes) throws IOException {
|
||||
if (bytes != null) {
|
||||
return bytes;
|
||||
}
|
||||
int byteCount = program.getDefaultPointerSize() > 4 ? 8 : 4;
|
||||
byte[] originalBytes = new byte[byteCount];
|
||||
AddressSourceInfo addressSourceInfo = program.getMemory().getAddressSourceInfo(addr);
|
||||
MemoryBlockSourceInfo memoryBlockSourceInfo = addressSourceInfo.getMemoryBlockSourceInfo();
|
||||
Optional<FileBytes> optional = memoryBlockSourceInfo.getFileBytes();
|
||||
if (!optional.isEmpty()) {
|
||||
FileBytes fileBytes = optional.get();
|
||||
long fileBytesOffset = addressSourceInfo.getFileOffset();
|
||||
long offsetIntoSourceRange =
|
||||
fileBytesOffset - memoryBlockSourceInfo.getFileBytesOffset();
|
||||
long available = memoryBlockSourceInfo.getLength() - offsetIntoSourceRange;
|
||||
int readSize = (int) Math.min(available, byteCount);
|
||||
fileBytes.getOriginalBytes(fileBytesOffset, originalBytes, 0, readSize);
|
||||
}
|
||||
return originalBytes;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Relocation add(Address addr, int type, long[] values, byte[] bytes, String symbolName) {
|
||||
lock.acquire();
|
||||
try {
|
||||
adapter.add(addrMap.getKey(addr, true), type, values, bytes, symbolName);
|
||||
return new Relocation(addr, type, values, bytes, symbolName);
|
||||
adapter.add(addr, type, values, bytes, symbolName);
|
||||
return new Relocation(addr, type, values, getOriginalBytes(addr, bytes), symbolName);
|
||||
}
|
||||
catch (IOException e) {
|
||||
program.dbError(e);
|
||||
}
|
||||
finally {
|
||||
lock.release();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void remove(Relocation reloc) {
|
||||
public boolean hasRelocation(Address addr) {
|
||||
lock.acquire();
|
||||
try {
|
||||
adapter.remove(addrMap.getKey(reloc.getAddress(), false));
|
||||
}
|
||||
catch (IOException e) {
|
||||
program.dbError(e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Relocation getRelocation(Address addr) {
|
||||
try {
|
||||
DBRecord rec = adapter.get(addrMap.getKey(addr, false));
|
||||
if (rec != null) {
|
||||
return getRelocation(rec);
|
||||
RecordIterator it = adapter.iterator(addr);
|
||||
if (!it.hasNext()) {
|
||||
return false;
|
||||
}
|
||||
DBRecord r = it.next();
|
||||
Address a = addrMap.decodeAddress(r.getLongValue(RelocationDBAdapter.ADDR_COL));
|
||||
return addr.equals(a);
|
||||
}
|
||||
catch (IOException e) {
|
||||
program.dbError(e);
|
||||
}
|
||||
finally {
|
||||
lock.release();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Relocation> getRelocations(Address addr) {
|
||||
lock.acquire();
|
||||
try {
|
||||
List<Relocation> list = null;
|
||||
RecordIterator it = adapter.iterator(addr);
|
||||
while (it.hasNext()) {
|
||||
DBRecord rec = it.next();
|
||||
Address a = addrMap.decodeAddress(rec.getLongValue(RelocationDBAdapter.ADDR_COL));
|
||||
if (!addr.equals(a)) {
|
||||
break;
|
||||
}
|
||||
if (list == null) {
|
||||
list = new ArrayList<>();
|
||||
}
|
||||
list.add(getRelocation(rec));
|
||||
}
|
||||
return list == null ? List.of() : list;
|
||||
}
|
||||
catch (IOException e) {
|
||||
program.dbError(e);
|
||||
}
|
||||
finally {
|
||||
lock.release();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private Relocation getRelocation(DBRecord rec) {
|
||||
private Relocation getRelocation(DBRecord rec) throws IOException {
|
||||
Address addr = addrMap.decodeAddress(rec.getLongValue(RelocationDBAdapter.ADDR_COL));
|
||||
BinaryCodedField valuesField =
|
||||
new BinaryCodedField((BinaryField) rec.getFieldValue(RelocationDBAdapter.VALU_COL));
|
||||
return new Relocation(addrMap.decodeAddress(rec.getKey()),
|
||||
rec.getIntValue(RelocationDBAdapter.TYPE_COL), valuesField.getLongArray(),
|
||||
rec.getBinaryData(RelocationDBAdapter.BYTES_COL),
|
||||
rec.getString(RelocationDBAdapter.SYMBOL_NAME_COL));
|
||||
new BinaryCodedField((BinaryField) rec.getFieldValue(RelocationDBAdapter.VALUE_COL));
|
||||
byte[] originalBytes =
|
||||
getOriginalBytes(addr, rec.getBinaryData(RelocationDBAdapter.BYTES_COL));
|
||||
return new Relocation(addr, rec.getIntValue(RelocationDBAdapter.TYPE_COL),
|
||||
valuesField.getLongArray(),
|
||||
originalBytes, rec.getString(RelocationDBAdapter.SYMBOL_NAME_COL));
|
||||
}
|
||||
|
||||
@Override
|
||||
public Iterator<Relocation> getRelocations() {
|
||||
RecordIterator ri = null;
|
||||
lock.acquire();
|
||||
try {
|
||||
ri = adapter.iterator();
|
||||
}
|
||||
catch (IOException e) {
|
||||
program.dbError(e);
|
||||
}
|
||||
finally {
|
||||
lock.release();
|
||||
}
|
||||
return new RelocationIterator(ri);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Relocation getRelocationAfter(Address addr) {
|
||||
RecordIterator ri = null;
|
||||
public Address getRelocationAddressAfter(Address addr) {
|
||||
lock.acquire();
|
||||
try {
|
||||
ri = adapter.iterator(addr);
|
||||
if (ri.hasNext()) {
|
||||
DBRecord r = ri.next();
|
||||
Relocation relocation = getRelocation(r);
|
||||
if (!relocation.getAddress().equals(addr)) {
|
||||
return relocation;
|
||||
}
|
||||
// The previous relocation was for the address that we want one after, so try again.
|
||||
if (ri.hasNext()) {
|
||||
r = ri.next();
|
||||
return getRelocation(r);
|
||||
RecordIterator it = adapter.iterator(addr);
|
||||
while (it.hasNext()) {
|
||||
DBRecord rec = it.next();
|
||||
Address a = addrMap.decodeAddress(rec.getLongValue(RelocationDBAdapter.ADDR_COL));
|
||||
if (!addr.equals(a)) {
|
||||
return a;
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (IOException e) {
|
||||
program.dbError(e);
|
||||
}
|
||||
finally {
|
||||
lock.release();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Iterator<Relocation> getRelocations(AddressSetView set) {
|
||||
RecordIterator ri = null;
|
||||
RecordIterator it = null;
|
||||
lock.acquire();
|
||||
try {
|
||||
ri = adapter.iterator(set);
|
||||
it = adapter.iterator(set);
|
||||
}
|
||||
catch (IOException e) {
|
||||
program.dbError(e);
|
||||
}
|
||||
return new RelocationIterator(ri);
|
||||
finally {
|
||||
lock.release();
|
||||
}
|
||||
return new RelocationIterator(it);
|
||||
}
|
||||
|
||||
private class RelocationIterator implements Iterator<Relocation> {
|
||||
private RecordIterator ri;
|
||||
private RecordIterator it;
|
||||
|
||||
RelocationIterator(RecordIterator ri) {
|
||||
this.ri = ri;
|
||||
this.it = ri;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasNext() {
|
||||
if (ri == null)
|
||||
if (it == null)
|
||||
return false;
|
||||
lock.acquire();
|
||||
try {
|
||||
return ri.hasNext();
|
||||
return it.hasNext();
|
||||
}
|
||||
catch (IOException e) {
|
||||
program.dbError(e);
|
||||
}
|
||||
finally {
|
||||
lock.release();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Relocation next() {
|
||||
if (ri == null)
|
||||
if (it == null)
|
||||
return null;
|
||||
lock.acquire();
|
||||
try {
|
||||
DBRecord r = ri.next();
|
||||
DBRecord r = it.next();
|
||||
return getRelocation(r);
|
||||
}
|
||||
catch (IOException e) {
|
||||
program.dbError(e);
|
||||
}
|
||||
finally {
|
||||
lock.release();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
|
|
|
@ -31,10 +31,11 @@ public class Relocation {
|
|||
/**
|
||||
* Constructs a new relocation.
|
||||
*
|
||||
* @param addr the address where the relocation is required
|
||||
* @param type the type of relocation to perform
|
||||
* @param values the values needed when performing the relocation
|
||||
* @param bytes original instruction bytes affected by relocation
|
||||
* @param addr the address where the relocation is required
|
||||
* @param type the type of relocation to perform
|
||||
* @param values the values needed when performing the relocation. Definition of values is
|
||||
* specific to loader used and relocation type.
|
||||
* @param bytes original instruction bytes affected by relocation
|
||||
* @param symbolName the name of the symbol being relocated
|
||||
*/
|
||||
public Relocation(Address addr, int type, long[] values, byte[] bytes, String symbolName) {
|
||||
|
|
|
@ -15,13 +15,17 @@
|
|||
*/
|
||||
package ghidra.program.model.reloc;
|
||||
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
|
||||
import ghidra.program.database.mem.FileBytes;
|
||||
import ghidra.program.model.address.Address;
|
||||
import ghidra.program.model.address.AddressSetView;
|
||||
|
||||
import java.util.Iterator;
|
||||
|
||||
/**
|
||||
* An interface for storing the relocations defined in a program.
|
||||
* Table must preserve the order in which relocations are added such that
|
||||
* the iterators return them in the same order.
|
||||
*/
|
||||
public interface RelocationTable {
|
||||
/** Name of the relocatable property in the program information property list. */
|
||||
|
@ -33,47 +37,52 @@ public interface RelocationTable {
|
|||
*
|
||||
* @param addr the address where the relocation is required
|
||||
* @param type the type of relocation to perform
|
||||
* @param values the values needed when performing the relocation
|
||||
* @param bytes original instruction bytes affected by relocation
|
||||
* @param values the values needed when performing the relocation. Definition of values is
|
||||
* specific to loader used and relocation type.
|
||||
* @param bytes original instruction bytes affected by relocation. A null value should be
|
||||
* passed to rely on original underlying {@link FileBytes}.
|
||||
* @param symbolName the name of the symbol being relocated; may be null
|
||||
* @return the newly added relocation object
|
||||
*/
|
||||
public Relocation add(Address addr, int type, long[] values, byte[] bytes, String symbolName);
|
||||
|
||||
/**
|
||||
* Removes the relocation object.
|
||||
* @param reloc the relocation object to remove
|
||||
* Returns the ordered list of relocations which have been defined for the specified address.
|
||||
* In most cases there will be one or none, but in some cases multiple relocations may be
|
||||
* applied to a single address.
|
||||
* @param addr the address where the relocation(s) are defined
|
||||
* @return the ordered list of relocations which have been defined for the specified address.
|
||||
*/
|
||||
public void remove(Relocation reloc);
|
||||
public List<Relocation> getRelocations(Address addr);
|
||||
|
||||
/**
|
||||
* Returns the relocation with the specified address.
|
||||
* @param addr the address where the relocation is defined
|
||||
* @return the relocation with the specified address
|
||||
* Determine if the specified address has a relocation defined.
|
||||
* @param addr memory address within program
|
||||
* @return true if relocation defined, otherwise false
|
||||
*/
|
||||
public Relocation getRelocation(Address addr);
|
||||
public boolean hasRelocation(Address addr);
|
||||
|
||||
/**
|
||||
* Returns an iterator over all relocation points (in ascending address order) located
|
||||
* Returns an iterator over all defined relocations (in ascending address order) located
|
||||
* within the program.
|
||||
* @return relocation iterator
|
||||
* @return ordered relocation iterator
|
||||
*/
|
||||
public Iterator<Relocation> getRelocations();
|
||||
|
||||
/**
|
||||
* Returns an iterator over all the relocation points (in ascending address order) located
|
||||
* within the specified address set.
|
||||
* Returns an iterator over all defined relocations (in ascending address order) located
|
||||
* within the program over the specified address set.
|
||||
* @param set address set
|
||||
* @return relocation iterator
|
||||
* @return ordered relocation iterator
|
||||
*/
|
||||
public Iterator<Relocation> getRelocations(AddressSetView set);
|
||||
|
||||
/**
|
||||
* Returns the next relocation point which follows the specified address.
|
||||
* Returns the next relocation address which follows the specified address.
|
||||
* @param addr starting point
|
||||
* @return next relocation after addr
|
||||
* @return next relocation address after addr or null if none
|
||||
*/
|
||||
public Relocation getRelocationAfter(Address addr);
|
||||
public Address getRelocationAddressAfter(Address addr);
|
||||
|
||||
/**
|
||||
* Returns the number of relocation in this table.
|
||||
|
|
|
@ -16,6 +16,7 @@
|
|||
package ghidra.app.util.bin.format.elf.extend;
|
||||
|
||||
import java.math.BigInteger;
|
||||
import java.util.List;
|
||||
|
||||
import ghidra.app.util.bin.format.elf.*;
|
||||
import ghidra.app.util.bin.format.elf.ElfDynamicType.ElfDynamicValueType;
|
||||
|
@ -376,9 +377,9 @@ public class PowerPC64_ElfExtension extends ElfExtension {
|
|||
Function function = program.getListing().getFunctionAt(refAddr);
|
||||
if (function == null) {
|
||||
// Check for potential pointer table (unsure a non-function would be referenced by OPD section)
|
||||
Relocation reloc = program.getRelocationTable().getRelocation(refAddr);
|
||||
if (reloc != null &&
|
||||
reloc.getType() == PowerPC64_ElfRelocationConstants.R_PPC64_RELATIVE) {
|
||||
List<Relocation> relocations = program.getRelocationTable().getRelocations(refAddr);
|
||||
if (!relocations.isEmpty() &&
|
||||
relocations.get(0).getType() == PowerPC64_ElfRelocationConstants.R_PPC64_RELATIVE) {
|
||||
return program.getSymbolTable().getPrimarySymbol(refAddr);
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue