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