mirror of
https://github.com/NationalSecurityAgency/ghidra.git
synced 2025-10-04 18:29:37 +02:00
GP-1036 EXTERNAL Block Offset-Reference refactor
This commit is contained in:
parent
332480a422
commit
2bced1cd43
43 changed files with 461 additions and 216 deletions
|
@ -56,7 +56,7 @@ public class DefaultModuleMapProposal
|
||||||
// TODO: Determine how to handle these.
|
// TODO: Determine how to handle these.
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (MemoryBlock.EXTERNAL_BLOCK_NAME.equals(block.getName())) {
|
if (block.isExternalBlock()) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
|
|
|
@ -15,7 +15,7 @@
|
||||||
*/
|
*/
|
||||||
package ghidra.trace.database.program;
|
package ghidra.trace.database.program;
|
||||||
|
|
||||||
import static ghidra.lifecycle.Unfinished.TODO;
|
import static ghidra.lifecycle.Unfinished.*;
|
||||||
|
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
import java.util.function.Function;
|
import java.util.function.Function;
|
||||||
|
@ -108,11 +108,10 @@ public abstract class AbstractDBTraceProgramViewReferenceManager implements Refe
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Reference addOffsetMemReference(Address fromAddr, Address toAddr, long offset,
|
public Reference addOffsetMemReference(Address fromAddr, Address toAddr, boolean toAddrIsBase,
|
||||||
RefType type, SourceType source, int opIndex) {
|
long offset, RefType type, SourceType source, int opIndex) {
|
||||||
return refs(true).addOffsetReference(chooseLifespan(fromAddr), fromAddr, toAddr, offset,
|
return refs(true).addOffsetReference(chooseLifespan(fromAddr), fromAddr, toAddr,
|
||||||
type,
|
toAddrIsBase, offset, type, source, opIndex);
|
||||||
source, opIndex);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -20,8 +20,12 @@ import ghidra.trace.database.symbol.DBTraceReferenceSpace.DBTraceReferenceEntry;
|
||||||
import ghidra.trace.model.symbol.TraceOffsetReference;
|
import ghidra.trace.model.symbol.TraceOffsetReference;
|
||||||
|
|
||||||
public class DBTraceOffsetReference extends DBTraceReference implements TraceOffsetReference {
|
public class DBTraceOffsetReference extends DBTraceReference implements TraceOffsetReference {
|
||||||
public DBTraceOffsetReference(DBTraceReferenceEntry ent) {
|
|
||||||
|
private boolean isExternalBlockReference;
|
||||||
|
|
||||||
|
public DBTraceOffsetReference(DBTraceReferenceEntry ent, boolean isExternalBlockReference) {
|
||||||
super(ent);
|
super(ent);
|
||||||
|
this.isExternalBlockReference = isExternalBlockReference;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -31,6 +35,9 @@ public class DBTraceOffsetReference extends DBTraceReference implements TraceOff
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Address getBaseAddress() {
|
public Address getBaseAddress() {
|
||||||
|
if (isExternalBlockReference) {
|
||||||
|
return ent.toAddress;
|
||||||
|
}
|
||||||
return ent.toAddress.subtractWrap(ent.ext);
|
return ent.toAddress.subtractWrap(ent.ext);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -179,9 +179,10 @@ public class DBTraceReferenceManager extends
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public DBTraceOffsetReference addOffsetReference(Range<Long> lifespan, Address fromAddress,
|
public DBTraceOffsetReference addOffsetReference(Range<Long> lifespan, Address fromAddress,
|
||||||
Address toAddress, long offset, RefType refType, SourceType source, int operandIndex) {
|
Address toAddress, boolean toAddrIsBase, long offset, RefType refType,
|
||||||
|
SourceType source, int operandIndex) {
|
||||||
return delegateWrite(fromAddress.getAddressSpace(), s -> s.addOffsetReference(lifespan,
|
return delegateWrite(fromAddress.getAddressSpace(), s -> s.addOffsetReference(lifespan,
|
||||||
fromAddress, toAddress, offset, refType, source, operandIndex));
|
fromAddress, toAddress, toAddrIsBase, offset, refType, source, operandIndex));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -27,6 +27,7 @@ import db.DBRecord;
|
||||||
import ghidra.program.model.address.*;
|
import ghidra.program.model.address.*;
|
||||||
import ghidra.program.model.lang.Language;
|
import ghidra.program.model.lang.Language;
|
||||||
import ghidra.program.model.lang.Register;
|
import ghidra.program.model.lang.Register;
|
||||||
|
import ghidra.program.model.mem.MemoryBlock;
|
||||||
import ghidra.program.model.symbol.*;
|
import ghidra.program.model.symbol.*;
|
||||||
import ghidra.trace.database.DBTrace;
|
import ghidra.trace.database.DBTrace;
|
||||||
import ghidra.trace.database.DBTraceUtils;
|
import ghidra.trace.database.DBTraceUtils;
|
||||||
|
@ -41,11 +42,13 @@ import ghidra.trace.database.space.AbstractDBTraceSpaceBasedManager.DBTraceSpace
|
||||||
import ghidra.trace.database.space.DBTraceSpaceBased;
|
import ghidra.trace.database.space.DBTraceSpaceBased;
|
||||||
import ghidra.trace.model.Trace.TraceReferenceChangeType;
|
import ghidra.trace.model.Trace.TraceReferenceChangeType;
|
||||||
import ghidra.trace.model.Trace.TraceSymbolChangeType;
|
import ghidra.trace.model.Trace.TraceSymbolChangeType;
|
||||||
|
import ghidra.trace.model.memory.TraceMemoryRegion;
|
||||||
import ghidra.trace.model.symbol.TraceReference;
|
import ghidra.trace.model.symbol.TraceReference;
|
||||||
import ghidra.trace.model.symbol.TraceReferenceSpace;
|
import ghidra.trace.model.symbol.TraceReferenceSpace;
|
||||||
import ghidra.trace.model.thread.TraceThread;
|
import ghidra.trace.model.thread.TraceThread;
|
||||||
import ghidra.trace.util.TraceChangeRecord;
|
import ghidra.trace.util.TraceChangeRecord;
|
||||||
import ghidra.util.LockHold;
|
import ghidra.util.LockHold;
|
||||||
|
import ghidra.util.Msg;
|
||||||
import ghidra.util.database.*;
|
import ghidra.util.database.*;
|
||||||
import ghidra.util.database.annot.*;
|
import ghidra.util.database.annot.*;
|
||||||
import ghidra.util.exception.VersionException;
|
import ghidra.util.exception.VersionException;
|
||||||
|
@ -69,7 +72,7 @@ public class DBTraceReferenceSpace implements DBTraceSpaceBased, TraceReferenceS
|
||||||
OFFSET {
|
OFFSET {
|
||||||
@Override
|
@Override
|
||||||
protected DBTraceReference construct(DBTraceReferenceEntry ent) {
|
protected DBTraceReference construct(DBTraceReferenceEntry ent) {
|
||||||
return new DBTraceOffsetReference(ent);
|
return new DBTraceOffsetReference(ent, false);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
SHIFT {
|
SHIFT {
|
||||||
|
@ -77,6 +80,12 @@ public class DBTraceReferenceSpace implements DBTraceSpaceBased, TraceReferenceS
|
||||||
protected DBTraceReference construct(DBTraceReferenceEntry ent) {
|
protected DBTraceReference construct(DBTraceReferenceEntry ent) {
|
||||||
return new DBTraceShiftedReference(ent);
|
return new DBTraceShiftedReference(ent);
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
OFFSET_EXTERNAL { // Offset Reference into EXTERNAL memory block region
|
||||||
|
@Override
|
||||||
|
protected DBTraceReference construct(DBTraceReferenceEntry ent) {
|
||||||
|
return new DBTraceOffsetReference(ent, true);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
protected abstract DBTraceReference construct(DBTraceReferenceEntry ent);
|
protected abstract DBTraceReference construct(DBTraceReferenceEntry ent);
|
||||||
|
@ -411,7 +420,7 @@ public class DBTraceReferenceSpace implements DBTraceSpaceBased, TraceReferenceS
|
||||||
// TODO: Reference (from, to, opIndex) must be unique!
|
// TODO: Reference (from, to, opIndex) must be unique!
|
||||||
if (reference.isOffsetReference()) {
|
if (reference.isOffsetReference()) {
|
||||||
OffsetReference oRef = (OffsetReference) reference;
|
OffsetReference oRef = (OffsetReference) reference;
|
||||||
return addOffsetReference(lifespan, oRef.getFromAddress(), oRef.getToAddress(),
|
return addOffsetReference(lifespan, oRef.getFromAddress(), oRef.getBaseAddress(), true,
|
||||||
oRef.getOffset(), oRef.getReferenceType(), oRef.getSource(),
|
oRef.getOffset(), oRef.getReferenceType(), oRef.getSource(),
|
||||||
oRef.getOperandIndex());
|
oRef.getOperandIndex());
|
||||||
}
|
}
|
||||||
|
@ -461,18 +470,61 @@ public class DBTraceReferenceSpace implements DBTraceSpaceBased, TraceReferenceS
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private boolean isExternalBlockAddress(Range<Long> lifespan, Address addr) {
|
||||||
|
// TODO: Verify that this works for emulation
|
||||||
|
TraceMemoryRegion region =
|
||||||
|
trace.getMemoryManager().getRegionContaining(lifespan.lowerEndpoint(), addr);
|
||||||
|
return region != null && MemoryBlock.EXTERNAL_BLOCK_NAME.equals(region.getName());
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public DBTraceOffsetReference addOffsetReference(Range<Long> lifespan, Address fromAddress,
|
public DBTraceOffsetReference addOffsetReference(Range<Long> lifespan, Address fromAddress,
|
||||||
Address toAddress, long offset, RefType refType, SourceType source, int operandIndex) {
|
Address toAddress, boolean toAddrIsBase, long offset, RefType refType,
|
||||||
|
SourceType source, int operandIndex) {
|
||||||
if (operandIndex < -1) {
|
if (operandIndex < -1) {
|
||||||
throw new IllegalArgumentException("operandIndex");
|
throw new IllegalArgumentException("operandIndex");
|
||||||
}
|
}
|
||||||
|
|
||||||
try (LockHold hold = LockHold.lock(lock.writeLock())) {
|
try (LockHold hold = LockHold.lock(lock.writeLock())) {
|
||||||
|
|
||||||
|
// Handle EXTERNAL Block offset-reference transformation
|
||||||
|
TypeEnum type = TypeEnum.OFFSET;
|
||||||
|
boolean isExternalBlockRef = isExternalBlockAddress(lifespan, toAddress);
|
||||||
|
boolean badOffsetReference = false;
|
||||||
|
if (isExternalBlockRef) {
|
||||||
|
type = TypeEnum.OFFSET_EXTERNAL;
|
||||||
|
if (!toAddrIsBase) {
|
||||||
|
Address baseAddr = toAddress.subtractWrap(offset);
|
||||||
|
if (isExternalBlockAddress(lifespan, baseAddr)) {
|
||||||
|
toAddress = baseAddr;
|
||||||
|
toAddrIsBase = true;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
// assume unintentional reference into EXTERNAL block
|
||||||
|
isExternalBlockRef = false;
|
||||||
|
type = TypeEnum.OFFSET;
|
||||||
|
badOffsetReference = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (toAddrIsBase) {
|
||||||
|
toAddress = toAddress.addWrap(offset);
|
||||||
|
toAddrIsBase = false;
|
||||||
|
if (isExternalBlockAddress(lifespan, toAddress)) {
|
||||||
|
badOffsetReference = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (badOffsetReference) {
|
||||||
|
Msg.warn(this, "Offset Reference from " + fromAddress +
|
||||||
|
" produces bad Xref into EXTERNAL block");
|
||||||
|
}
|
||||||
|
|
||||||
makeWay(lifespan, fromAddress, toAddress, operandIndex);
|
makeWay(lifespan, fromAddress, toAddress, operandIndex);
|
||||||
|
|
||||||
DBTraceReferenceEntry entry = referenceMapSpace.put(fromAddress, lifespan, null);
|
DBTraceReferenceEntry entry = referenceMapSpace.put(fromAddress, lifespan, null);
|
||||||
entry.set(toAddress, -1, refType, operandIndex, offset, false, TypeEnum.OFFSET, source);
|
entry.set(toAddress, -1, refType, operandIndex, offset, false, type, source);
|
||||||
DBTraceOffsetReference ref = new DBTraceOffsetReference(entry);
|
DBTraceOffsetReference ref = new DBTraceOffsetReference(entry, isExternalBlockRef);
|
||||||
entry.ref = ref;
|
entry.ref = ref;
|
||||||
manager.doAddXRef(entry);
|
manager.doAddXRef(entry);
|
||||||
return ref;
|
return ref;
|
||||||
|
|
|
@ -32,7 +32,8 @@ public interface TraceReferenceOperations {
|
||||||
RefType refType, SourceType source, int operandIndex);
|
RefType refType, SourceType source, int operandIndex);
|
||||||
|
|
||||||
TraceOffsetReference addOffsetReference(Range<Long> lifespan, Address fromAddress,
|
TraceOffsetReference addOffsetReference(Range<Long> lifespan, Address fromAddress,
|
||||||
Address toAddress, long offset, RefType refType, SourceType source, int operandIndex);
|
Address toAddress, boolean toAddrIsBase, long offset, RefType refType,
|
||||||
|
SourceType source, int operandIndex);
|
||||||
|
|
||||||
TraceShiftedReference addShiftedReference(Range<Long> lifespan, Address fromAddress,
|
TraceShiftedReference addShiftedReference(Range<Long> lifespan, Address fromAddress,
|
||||||
Address toAddress, int shift, RefType refType, SourceType source, int operandIndex);
|
Address toAddress, int shift, RefType refType, SourceType source, int operandIndex);
|
||||||
|
|
|
@ -303,9 +303,9 @@ public class ToyDBTraceBuilder implements AutoCloseable {
|
||||||
}
|
}
|
||||||
|
|
||||||
public DBTraceReference addOffsetReference(long creationSnap, Address from, Address to,
|
public DBTraceReference addOffsetReference(long creationSnap, Address from, Address to,
|
||||||
long offset) {
|
boolean toAddrIsBase, long offset) {
|
||||||
return trace.getReferenceManager()
|
return trace.getReferenceManager()
|
||||||
.addOffsetReference(Range.atLeast(creationSnap), from, to,
|
.addOffsetReference(Range.atLeast(creationSnap), from, to, toAddrIsBase,
|
||||||
offset, RefType.DATA, SourceType.DEFAULT, -1);
|
offset, RefType.DATA, SourceType.DEFAULT, -1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -133,6 +133,7 @@ public class DBTraceReferenceManagerTest extends AbstractGhidraHeadlessIntegrati
|
||||||
long offset) {
|
long offset) {
|
||||||
super(startSnap, fromAddress, toAddress);
|
super(startSnap, fromAddress, toAddress);
|
||||||
this.offset = offset;
|
this.offset = offset;
|
||||||
|
// NOTE: intended for test use in the absence of any EXTERNAL memory block concern
|
||||||
this.baseAddress = toAddress.subtract(offset);
|
this.baseAddress = toAddress.subtract(offset);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -198,7 +199,7 @@ public class DBTraceReferenceManagerTest extends AbstractGhidraHeadlessIntegrati
|
||||||
new DummyTraceShiftedReference(0, b.addr(0x4002), b.addr(0x5002), 1));
|
new DummyTraceShiftedReference(0, b.addr(0x4002), b.addr(0x5002), 1));
|
||||||
}
|
}
|
||||||
|
|
||||||
assertTrue(memRef instanceof DBTraceReference);
|
assertNotNull(memRef);
|
||||||
assertTrue(offRef instanceof DBTraceOffsetReference);
|
assertTrue(offRef instanceof DBTraceOffsetReference);
|
||||||
assertTrue(sftRef instanceof DBTraceShiftedReference);
|
assertTrue(sftRef instanceof DBTraceShiftedReference);
|
||||||
|
|
||||||
|
@ -231,7 +232,7 @@ public class DBTraceReferenceManagerTest extends AbstractGhidraHeadlessIntegrati
|
||||||
@Test
|
@Test
|
||||||
public void testAddOffsetReference() {
|
public void testAddOffsetReference() {
|
||||||
try (UndoableTransaction tid = b.startTransaction()) {
|
try (UndoableTransaction tid = b.startTransaction()) {
|
||||||
b.addOffsetReference(0, b.addr(0x4001), b.addr(0x5001), 20);
|
b.addOffsetReference(0, b.addr(0x4001), b.addr(0x5001), false, 20);
|
||||||
}
|
}
|
||||||
DBTraceReferenceSpace space =
|
DBTraceReferenceSpace space =
|
||||||
manager.getReferenceSpace(b.language.getDefaultDataSpace(), false);
|
manager.getReferenceSpace(b.language.getDefaultDataSpace(), false);
|
||||||
|
@ -285,7 +286,7 @@ public class DBTraceReferenceManagerTest extends AbstractGhidraHeadlessIntegrati
|
||||||
DBTraceReference stkRef;
|
DBTraceReference stkRef;
|
||||||
try (UndoableTransaction tid = b.startTransaction()) {
|
try (UndoableTransaction tid = b.startTransaction()) {
|
||||||
memRef = b.addMemoryReference(0, b.addr(0x4000), b.addr(0x5000));
|
memRef = b.addMemoryReference(0, b.addr(0x4000), b.addr(0x5000));
|
||||||
offRef = b.addOffsetReference(0, b.addr(0x4001), b.addr(0x5001), 20);
|
offRef = b.addOffsetReference(0, b.addr(0x4001), b.addr(0x5001), false, 20);
|
||||||
sftRef = b.addShiftedReference(0, b.addr(0x4002), b.addr(0x5002), 1);
|
sftRef = b.addShiftedReference(0, b.addr(0x4002), b.addr(0x5002), 1);
|
||||||
regRef = b.addRegisterReference(0, b.addr(0x4003), "r5");
|
regRef = b.addRegisterReference(0, b.addr(0x4003), "r5");
|
||||||
stkRef = b.addStackReference(0, b.addr(0x4004), 0x20);
|
stkRef = b.addStackReference(0, b.addr(0x4004), 0x20);
|
||||||
|
@ -323,7 +324,7 @@ public class DBTraceReferenceManagerTest extends AbstractGhidraHeadlessIntegrati
|
||||||
DBTraceReference stkRef;
|
DBTraceReference stkRef;
|
||||||
try (UndoableTransaction tid = b.startTransaction()) {
|
try (UndoableTransaction tid = b.startTransaction()) {
|
||||||
memRef = b.addMemoryReference(0, b.addr(0x4000), b.addr(0x5000), 3);
|
memRef = b.addMemoryReference(0, b.addr(0x4000), b.addr(0x5000), 3);
|
||||||
offRef = b.addOffsetReference(0, b.addr(0x4000), b.addr(0x5001), 20);
|
offRef = b.addOffsetReference(0, b.addr(0x4000), b.addr(0x5001), false, 20);
|
||||||
sftRef = b.addShiftedReference(0, b.addr(0x4000), b.addr(0x5002), 1);
|
sftRef = b.addShiftedReference(0, b.addr(0x4000), b.addr(0x5002), 1);
|
||||||
regRef = b.addRegisterReference(0, b.addr(0x4000), "r5");
|
regRef = b.addRegisterReference(0, b.addr(0x4000), "r5");
|
||||||
stkRef = b.addStackReference(0, b.addr(0x4000), 0x20);
|
stkRef = b.addStackReference(0, b.addr(0x4000), 0x20);
|
||||||
|
@ -376,7 +377,7 @@ public class DBTraceReferenceManagerTest extends AbstractGhidraHeadlessIntegrati
|
||||||
DBTraceReference offRef;
|
DBTraceReference offRef;
|
||||||
try (UndoableTransaction tid = b.startTransaction()) {
|
try (UndoableTransaction tid = b.startTransaction()) {
|
||||||
memRef = b.addMemoryReference(0, b.addr(0x4000), b.addr(0x5000));
|
memRef = b.addMemoryReference(0, b.addr(0x4000), b.addr(0x5000));
|
||||||
offRef = b.addOffsetReference(0, b.addr(0x4000), b.addr(0x5001), 20);
|
offRef = b.addOffsetReference(0, b.addr(0x4000), b.addr(0x5001), false, 20);
|
||||||
|
|
||||||
assertNull(manager.getPrimaryReferenceFrom(0, b.addr(0x4000), -1));
|
assertNull(manager.getPrimaryReferenceFrom(0, b.addr(0x4000), -1));
|
||||||
|
|
||||||
|
@ -400,7 +401,7 @@ public class DBTraceReferenceManagerTest extends AbstractGhidraHeadlessIntegrati
|
||||||
flowRef = manager.addMemoryReference(Range.atLeast(0L), b.addr(0x4000), b.addr(0x4001),
|
flowRef = manager.addMemoryReference(Range.atLeast(0L), b.addr(0x4000), b.addr(0x4001),
|
||||||
RefType.FLOW, SourceType.DEFAULT, -1);
|
RefType.FLOW, SourceType.DEFAULT, -1);
|
||||||
b.addMemoryReference(0, b.addr(0x4000), b.addr(0x5000));
|
b.addMemoryReference(0, b.addr(0x4000), b.addr(0x5000));
|
||||||
b.addOffsetReference(0, b.addr(0x4000), b.addr(0x5001), 20);
|
b.addOffsetReference(0, b.addr(0x4000), b.addr(0x5001), false, 20);
|
||||||
}
|
}
|
||||||
|
|
||||||
assertEquals(Set.of(flowRef),
|
assertEquals(Set.of(flowRef),
|
||||||
|
@ -412,7 +413,7 @@ public class DBTraceReferenceManagerTest extends AbstractGhidraHeadlessIntegrati
|
||||||
DBTraceReference keptRef;
|
DBTraceReference keptRef;
|
||||||
try (UndoableTransaction tid = b.startTransaction()) {
|
try (UndoableTransaction tid = b.startTransaction()) {
|
||||||
b.addMemoryReference(0, b.addr(0x4000), b.addr(0x5000), 3);
|
b.addMemoryReference(0, b.addr(0x4000), b.addr(0x5000), 3);
|
||||||
b.addOffsetReference(0, b.addr(0x4000), b.addr(0x5001), 20);
|
b.addOffsetReference(0, b.addr(0x4000), b.addr(0x5001), false, 20);
|
||||||
b.addShiftedReference(0, b.addr(0x4000), b.addr(0x5002), 1);
|
b.addShiftedReference(0, b.addr(0x4000), b.addr(0x5002), 1);
|
||||||
b.addRegisterReference(0, b.addr(0x4000), "r5");
|
b.addRegisterReference(0, b.addr(0x4000), "r5");
|
||||||
b.addStackReference(0, b.addr(0x4000), 0x20);
|
b.addStackReference(0, b.addr(0x4000), 0x20);
|
||||||
|
@ -449,7 +450,7 @@ public class DBTraceReferenceManagerTest extends AbstractGhidraHeadlessIntegrati
|
||||||
DBTraceReference sftRef;
|
DBTraceReference sftRef;
|
||||||
try (UndoableTransaction tid = b.startTransaction()) {
|
try (UndoableTransaction tid = b.startTransaction()) {
|
||||||
memRef = b.addMemoryReference(0, b.addr(0x4000), b.addr(0x5000));
|
memRef = b.addMemoryReference(0, b.addr(0x4000), b.addr(0x5000));
|
||||||
offRef = b.addOffsetReference(0, b.addr(0x4001), b.addr(0x5000), 20);
|
offRef = b.addOffsetReference(0, b.addr(0x4001), b.addr(0x5000), false, 20);
|
||||||
sftRef = b.addShiftedReference(0, b.addr(0x4002), b.addr(0x5000), 1);
|
sftRef = b.addShiftedReference(0, b.addr(0x4002), b.addr(0x5000), 1);
|
||||||
b.addRegisterReference(0, b.addr(0x4003), "r5");
|
b.addRegisterReference(0, b.addr(0x4003), "r5");
|
||||||
b.addStackReference(0, b.addr(0x4004), 0x20);
|
b.addStackReference(0, b.addr(0x4004), 0x20);
|
||||||
|
@ -466,7 +467,7 @@ public class DBTraceReferenceManagerTest extends AbstractGhidraHeadlessIntegrati
|
||||||
DBTraceReference keptRef;
|
DBTraceReference keptRef;
|
||||||
try (UndoableTransaction tid = b.startTransaction()) {
|
try (UndoableTransaction tid = b.startTransaction()) {
|
||||||
b.addMemoryReference(0, b.addr(0x4000), b.addr(0x5000), 3);
|
b.addMemoryReference(0, b.addr(0x4000), b.addr(0x5000), 3);
|
||||||
b.addOffsetReference(0, b.addr(0x4001), b.addr(0x5000), 20);
|
b.addOffsetReference(0, b.addr(0x4001), b.addr(0x5000), false, 20);
|
||||||
b.addShiftedReference(0, b.addr(0x4002), b.addr(0x5000), 1);
|
b.addShiftedReference(0, b.addr(0x4002), b.addr(0x5000), 1);
|
||||||
keptRef = b.addMemoryReference(0, b.addr(0x8000), b.addr(0x5001));
|
keptRef = b.addMemoryReference(0, b.addr(0x8000), b.addr(0x5001));
|
||||||
}
|
}
|
||||||
|
@ -498,7 +499,7 @@ public class DBTraceReferenceManagerTest extends AbstractGhidraHeadlessIntegrati
|
||||||
public void testGetReferenceSourcesAndDestinations() {
|
public void testGetReferenceSourcesAndDestinations() {
|
||||||
try (UndoableTransaction tid = b.startTransaction()) {
|
try (UndoableTransaction tid = b.startTransaction()) {
|
||||||
b.addMemoryReference(0, b.addr(0x4000), b.addr(0x5000));
|
b.addMemoryReference(0, b.addr(0x4000), b.addr(0x5000));
|
||||||
b.addOffsetReference(0, b.addr(0x4001), b.addr(0x5001), 20);
|
b.addOffsetReference(0, b.addr(0x4001), b.addr(0x5001), false, 20);
|
||||||
b.addShiftedReference(0, b.addr(0x4002), b.addr(0x5002), 1);
|
b.addShiftedReference(0, b.addr(0x4002), b.addr(0x5002), 1);
|
||||||
b.addRegisterReference(0, b.addr(0x4003), "r5");
|
b.addRegisterReference(0, b.addr(0x4003), "r5");
|
||||||
b.addStackReference(0, b.addr(0x4004), 0x20);
|
b.addStackReference(0, b.addr(0x4004), 0x20);
|
||||||
|
@ -520,7 +521,7 @@ public class DBTraceReferenceManagerTest extends AbstractGhidraHeadlessIntegrati
|
||||||
|
|
||||||
try (UndoableTransaction tid = b.startTransaction()) {
|
try (UndoableTransaction tid = b.startTransaction()) {
|
||||||
b.addMemoryReference(0, b.addr(0x4000), b.addr(0x5000));
|
b.addMemoryReference(0, b.addr(0x4000), b.addr(0x5000));
|
||||||
b.addOffsetReference(0, b.addr(0x4000), b.addr(0x5001), 20);
|
b.addOffsetReference(0, b.addr(0x4000), b.addr(0x5001), false, 20);
|
||||||
b.addShiftedReference(0, b.addr(0x4000), b.addr(0x5002), 1);
|
b.addShiftedReference(0, b.addr(0x4000), b.addr(0x5002), 1);
|
||||||
b.addRegisterReference(0, b.addr(0x4000), "r5");
|
b.addRegisterReference(0, b.addr(0x4000), "r5");
|
||||||
b.addStackReference(0, b.addr(0x4000), 0x20);
|
b.addStackReference(0, b.addr(0x4000), 0x20);
|
||||||
|
@ -538,7 +539,7 @@ public class DBTraceReferenceManagerTest extends AbstractGhidraHeadlessIntegrati
|
||||||
public void testSaveAndLoad() throws CancelledException, IOException, VersionException {
|
public void testSaveAndLoad() throws CancelledException, IOException, VersionException {
|
||||||
try (UndoableTransaction tid = b.startTransaction()) {
|
try (UndoableTransaction tid = b.startTransaction()) {
|
||||||
b.addMemoryReference(0, b.addr(0x4000), b.addr(0x5000));
|
b.addMemoryReference(0, b.addr(0x4000), b.addr(0x5000));
|
||||||
b.addOffsetReference(0, b.addr(0x4000), b.addr(0x5001), 20);
|
b.addOffsetReference(0, b.addr(0x4000), b.addr(0x5001), false, 20);
|
||||||
b.addShiftedReference(0, b.addr(0x4000), b.addr(0x5002), 1);
|
b.addShiftedReference(0, b.addr(0x4000), b.addr(0x5002), 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -575,7 +576,7 @@ public class DBTraceReferenceManagerTest extends AbstractGhidraHeadlessIntegrati
|
||||||
public void testUndo() throws IOException {
|
public void testUndo() throws IOException {
|
||||||
try (UndoableTransaction tid = b.startTransaction()) {
|
try (UndoableTransaction tid = b.startTransaction()) {
|
||||||
b.addMemoryReference(0, b.addr(0x4000), b.addr(0x5000));
|
b.addMemoryReference(0, b.addr(0x4000), b.addr(0x5000));
|
||||||
b.addOffsetReference(0, b.addr(0x4000), b.addr(0x5001), 20);
|
b.addOffsetReference(0, b.addr(0x4000), b.addr(0x5001), false, 20);
|
||||||
b.addShiftedReference(0, b.addr(0x4000), b.addr(0x5002), 1);
|
b.addShiftedReference(0, b.addr(0x4000), b.addr(0x5002), 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -29,7 +29,6 @@ import ghidra.program.model.block.CodeBlock;
|
||||||
import ghidra.program.model.lang.Register;
|
import ghidra.program.model.lang.Register;
|
||||||
import ghidra.program.model.lang.RegisterValue;
|
import ghidra.program.model.lang.RegisterValue;
|
||||||
import ghidra.program.model.listing.*;
|
import ghidra.program.model.listing.*;
|
||||||
import ghidra.program.model.mem.MemoryBlock;
|
|
||||||
import ghidra.program.model.pcode.PcodeOp;
|
import ghidra.program.model.pcode.PcodeOp;
|
||||||
import ghidra.program.model.pcode.Varnode;
|
import ghidra.program.model.pcode.Varnode;
|
||||||
import ghidra.program.model.symbol.*;
|
import ghidra.program.model.symbol.*;
|
||||||
|
@ -237,7 +236,7 @@ public class CreateThunkFunctionCmd extends BackgroundCommand {
|
||||||
}
|
}
|
||||||
|
|
||||||
private AddressSetView computeThunkBody(Program program) {
|
private AddressSetView computeThunkBody(Program program) {
|
||||||
if (MemoryBlock.isExternalBlockAddress(entry, program)) {
|
if (program.getMemory().isExternalBlockAddress(entry)) {
|
||||||
return new AddressSet(entry, entry);
|
return new AddressSet(entry, entry);
|
||||||
}
|
}
|
||||||
Listing listing = program.getListing();
|
Listing listing = program.getListing();
|
||||||
|
@ -306,7 +305,7 @@ public class CreateThunkFunctionCmd extends BackgroundCommand {
|
||||||
if (f == null) {
|
if (f == null) {
|
||||||
// If referencedFunctionAddr contained within EXTERNAL block attempt to
|
// If referencedFunctionAddr contained within EXTERNAL block attempt to
|
||||||
// create a thunk function for it
|
// create a thunk function for it
|
||||||
if (MemoryBlock.isExternalBlockAddress(referencedFunctionAddr, program)) {
|
if (program.getMemory().isExternalBlockAddress(referencedFunctionAddr)) {
|
||||||
CreateThunkFunctionCmd extThunkCmd =
|
CreateThunkFunctionCmd extThunkCmd =
|
||||||
new CreateThunkFunctionCmd(referencedFunctionAddr, false);
|
new CreateThunkFunctionCmd(referencedFunctionAddr, false);
|
||||||
if (extThunkCmd.applyTo(program)) {
|
if (extThunkCmd.applyTo(program)) {
|
||||||
|
@ -627,7 +626,7 @@ public class CreateThunkFunctionCmd extends BackgroundCommand {
|
||||||
*/
|
*/
|
||||||
static Address getThunkedExternalFunctionAddress(Program program, Address entry) {
|
static Address getThunkedExternalFunctionAddress(Program program, Address entry) {
|
||||||
|
|
||||||
if (!MemoryBlock.isExternalBlockAddress(entry, program)) {
|
if (!program.getMemory().isExternalBlockAddress(entry)) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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.
|
||||||
|
@ -20,6 +19,7 @@ import ghidra.framework.cmd.Command;
|
||||||
import ghidra.framework.model.DomainObject;
|
import ghidra.framework.model.DomainObject;
|
||||||
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.mem.MemoryBlock;
|
||||||
import ghidra.program.model.symbol.*;
|
import ghidra.program.model.symbol.*;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -29,24 +29,35 @@ public class AddOffsetMemRefCmd implements Command {
|
||||||
|
|
||||||
private Address fromAddr;
|
private Address fromAddr;
|
||||||
private Address toAddr;
|
private Address toAddr;
|
||||||
|
private boolean toAddrIsBase;
|
||||||
private RefType refType;
|
private RefType refType;
|
||||||
private SourceType source;
|
private SourceType source;
|
||||||
private int opIndex;
|
private int opIndex;
|
||||||
private long offset;
|
private long offset;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Command constructor for adding an offset memory reference
|
* Command constructor for adding an offset memory reference. The first memory reference placed on
|
||||||
|
* an operand will be made primary by default. All non-memory references
|
||||||
|
* will be removed from the specified operand. If toAddr corresponds to
|
||||||
|
* the EXTERNAL memory block (see {@link MemoryBlock#EXTERNAL_BLOCK_NAME}) the
|
||||||
|
* resulting offset reference will report to/base address as the same
|
||||||
|
* regardless of specified offset.
|
||||||
* @param fromAddr address of the codeunit where the reference occurs
|
* @param fromAddr address of the codeunit where the reference occurs
|
||||||
* @param toAddr address of the location being referenced.
|
* @param toAddr address of the location being referenced.
|
||||||
|
* @param toAddrIsBase if true toAddr is treated as base address, else treated as (base+offet).
|
||||||
|
* It is generally preferred to specify as a base address to ensure proper handling of
|
||||||
|
* EXTERNAL block case.
|
||||||
* @param refType reference type - how the location is being referenced.
|
* @param refType reference type - how the location is being referenced.
|
||||||
* @param source the source of the reference
|
* @param source the source of the reference
|
||||||
* @param opIndex the operand index in the code unit where the reference occurs
|
* @param opIndex the operand index in the code unit where the reference occurs
|
||||||
* @param offset value added to a base address to get the toAddr
|
* @param offset value added to a base address to get the toAddr
|
||||||
*/
|
*/
|
||||||
public AddOffsetMemRefCmd(Address fromAddr, Address toAddr, RefType refType,
|
public AddOffsetMemRefCmd(Address fromAddr, Address toAddr, boolean toAddrIsBase,
|
||||||
|
RefType refType,
|
||||||
SourceType source, int opIndex, long offset) {
|
SourceType source, int opIndex, long offset) {
|
||||||
this.fromAddr = fromAddr;
|
this.fromAddr = fromAddr;
|
||||||
this.toAddr = toAddr;
|
this.toAddr = toAddr;
|
||||||
|
this.toAddrIsBase = toAddrIsBase;
|
||||||
this.refType = refType;
|
this.refType = refType;
|
||||||
this.source = source;
|
this.source = source;
|
||||||
this.opIndex = opIndex;
|
this.opIndex = opIndex;
|
||||||
|
@ -60,11 +71,11 @@ public class AddOffsetMemRefCmd implements Command {
|
||||||
public boolean applyTo(DomainObject obj) {
|
public boolean applyTo(DomainObject obj) {
|
||||||
Program p = (Program)obj;
|
Program p = (Program)obj;
|
||||||
ReferenceManager refMgr = p.getReferenceManager();
|
ReferenceManager refMgr = p.getReferenceManager();
|
||||||
refMgr.addOffsetMemReference(fromAddr, toAddr, offset, refType, source, opIndex);
|
refMgr.addOffsetMemReference(fromAddr, toAddr, toAddrIsBase, offset, refType, source,
|
||||||
|
opIndex);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @see ghidra.framework.cmd.Command#getStatusMsg()
|
* @see ghidra.framework.cmd.Command#getStatusMsg()
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -125,8 +125,7 @@ public class OperandReferenceAnalyzer extends AbstractAnalyzer {
|
||||||
|
|
||||||
private boolean newCodeFound = false;
|
private boolean newCodeFound = false;
|
||||||
private int processorAlignment = 1;
|
private int processorAlignment = 1;
|
||||||
private MemoryBlock externalBlock;
|
private boolean respectExecuteFlags = OPTION_DEFAULT_RESPECT_EXECUTE_ENABLED;
|
||||||
private boolean respectExecuteFlags = true;
|
|
||||||
|
|
||||||
public OperandReferenceAnalyzer() {
|
public OperandReferenceAnalyzer() {
|
||||||
this(NAME, DESCRIPTION, AnalyzerType.INSTRUCTION_ANALYZER);
|
this(NAME, DESCRIPTION, AnalyzerType.INSTRUCTION_ANALYZER);
|
||||||
|
@ -192,8 +191,6 @@ public class OperandReferenceAnalyzer extends AbstractAnalyzer {
|
||||||
|
|
||||||
processorAlignment = program.getLanguage().getInstructionAlignment();
|
processorAlignment = program.getLanguage().getInstructionAlignment();
|
||||||
|
|
||||||
externalBlock = program.getMemory().getBlock(MemoryBlock.EXTERNAL_BLOCK_NAME);
|
|
||||||
|
|
||||||
newCodeFound = false;
|
newCodeFound = false;
|
||||||
int count = NOTIFICATION_INTERVAL;
|
int count = NOTIFICATION_INTERVAL;
|
||||||
long initial_count = set.getNumAddresses();
|
long initial_count = set.getNumAddresses();
|
||||||
|
@ -574,12 +571,8 @@ public class OperandReferenceAnalyzer extends AbstractAnalyzer {
|
||||||
throws CancelledException {
|
throws CancelledException {
|
||||||
// Check any direct jumps into the EXTERNAL memory section
|
// Check any direct jumps into the EXTERNAL memory section
|
||||||
// These don't return!
|
// These don't return!
|
||||||
if (externalBlock == null) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
Address toAddr = reference.getToAddress();
|
Address toAddr = reference.getToAddress();
|
||||||
if (!externalBlock.contains(toAddr)) {
|
if (!program.getMemory().isExternalBlockAddress(toAddr)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
Address fromAddr = reference.getFromAddress();
|
Address fromAddr = reference.getFromAddress();
|
||||||
|
@ -779,8 +772,8 @@ public class OperandReferenceAnalyzer extends AbstractAnalyzer {
|
||||||
instr.removeOperandReference(opIndex, target);
|
instr.removeOperandReference(opIndex, target);
|
||||||
program.getReferenceManager()
|
program.getReferenceManager()
|
||||||
.addOffsetMemReference(instr.getMinAddress(),
|
.addOffsetMemReference(instr.getMinAddress(),
|
||||||
lastGoodTable.getTopAddress(), -((i + 3) * entryLen), RefType.DATA,
|
lastGoodTable.getTopAddress(), false, -((i + 3) * entryLen),
|
||||||
SourceType.ANALYSIS, opIndex);
|
RefType.DATA, SourceType.ANALYSIS, opIndex);
|
||||||
}
|
}
|
||||||
|
|
||||||
return lastGoodTable;
|
return lastGoodTable;
|
||||||
|
|
|
@ -294,7 +294,7 @@ public class ScalarOperandAnalyzer extends AbstractAnalyzer {
|
||||||
// add in an offcut reference
|
// add in an offcut reference
|
||||||
program.getReferenceManager()
|
program.getReferenceManager()
|
||||||
.addOffsetMemReference(refInstr.getMinAddress(), offAddr,
|
.addOffsetMemReference(refInstr.getMinAddress(), offAddr,
|
||||||
-entryLen, RefType.DATA, SourceType.ANALYSIS, opIndex);
|
false, -entryLen, RefType.DATA, SourceType.ANALYSIS, opIndex);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -332,7 +332,7 @@ public class ScalarOperandAnalyzer extends AbstractAnalyzer {
|
||||||
// add in an offcut reference
|
// add in an offcut reference
|
||||||
program.getReferenceManager()
|
program.getReferenceManager()
|
||||||
.addOffsetMemReference(instr.getMinAddress(), offAddr,
|
.addOffsetMemReference(instr.getMinAddress(), offAddr,
|
||||||
(i + 3) * entryLen, RefType.DATA, SourceType.ANALYSIS, opIndex);
|
false, (i + 3) * entryLen, RefType.DATA, SourceType.ANALYSIS, opIndex);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -577,7 +577,7 @@ public class ReferencesPlugin extends Plugin {
|
||||||
int opIndex = editRef.getOperandIndex();
|
int opIndex = editRef.getOperandIndex();
|
||||||
cmd.add(new RemoveReferenceCmd(editRef));
|
cmd.add(new RemoveReferenceCmd(editRef));
|
||||||
if (isOffsetRef) {
|
if (isOffsetRef) {
|
||||||
cmd.add(new AddOffsetMemRefCmd(fromCodeUnit.getMinAddress(), toAddr, refType,
|
cmd.add(new AddOffsetMemRefCmd(fromCodeUnit.getMinAddress(), toAddr, false, refType,
|
||||||
SourceType.USER_DEFINED, opIndex, offset));
|
SourceType.USER_DEFINED, opIndex, offset));
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
@ -612,7 +612,7 @@ public class ReferencesPlugin extends Plugin {
|
||||||
|
|
||||||
Command cmd;
|
Command cmd;
|
||||||
if (isOffsetRef) {
|
if (isOffsetRef) {
|
||||||
cmd = new AddOffsetMemRefCmd(fromAddr, toAddr, refType, SourceType.USER_DEFINED,
|
cmd = new AddOffsetMemRefCmd(fromAddr, toAddr, false, refType, SourceType.USER_DEFINED,
|
||||||
opIndex, offset);
|
opIndex, offset);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
|
|
@ -22,9 +22,12 @@ import org.apache.commons.lang3.StringUtils;
|
||||||
import ghidra.app.util.bin.format.elf.*;
|
import ghidra.app.util.bin.format.elf.*;
|
||||||
import ghidra.app.util.importer.MessageLog;
|
import ghidra.app.util.importer.MessageLog;
|
||||||
import ghidra.program.model.address.Address;
|
import ghidra.program.model.address.Address;
|
||||||
|
import ghidra.program.model.data.*;
|
||||||
|
import ghidra.program.model.data.DataUtilities.ClearDataMode;
|
||||||
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.mem.MemoryBlock;
|
import ghidra.program.model.util.CodeUnitInsertionException;
|
||||||
|
import ghidra.util.Msg;
|
||||||
import ghidra.util.classfinder.ExtensionPoint;
|
import ghidra.util.classfinder.ExtensionPoint;
|
||||||
import ghidra.util.exception.NotFoundException;
|
import ghidra.util.exception.NotFoundException;
|
||||||
|
|
||||||
|
@ -73,9 +76,31 @@ abstract public class ElfRelocationHandler implements ExtensionPoint {
|
||||||
throws MemoryAccessException, NotFoundException;
|
throws MemoryAccessException, NotFoundException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Determine if symbolAddr is contained within the EXTERNAL block. If so, relocationAddress will be marked
|
* Apply a pointer-typedef with a specified component-offset.
|
||||||
* with a <code>Unsupported EXTERNAL Data Elf Relocation</code> error bookmark.
|
* @param program
|
||||||
* NOTE: This method should only be invoked when the symbol offset will be adjust with a non-zero
|
* @param addr address where data should be applied
|
||||||
|
* @param componentOffset component offset
|
||||||
|
*/
|
||||||
|
public static void applyComponentOffsetPointer(Program program, Address addr,
|
||||||
|
long componentOffset) {
|
||||||
|
// TODO: we could also assign non-default address space setting if needed
|
||||||
|
PointerTypedef dt =
|
||||||
|
new PointerTypedef(null, null, -1, program.getDataTypeManager(), componentOffset);
|
||||||
|
try {
|
||||||
|
DataUtilities.createData(program, addr, dt, -1, false,
|
||||||
|
ClearDataMode.CLEAR_ALL_UNDEFINED_CONFLICT_DATA);
|
||||||
|
}
|
||||||
|
catch (CodeUnitInsertionException | DataTypeConflictException e) {
|
||||||
|
Msg.error(ElfRelocationHandler.class,
|
||||||
|
"Failed to apply component-offset pointer at " + addr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Determine if symbolAddr is contained within the EXTERNAL block with a non-zero adjustment.
|
||||||
|
* If so, relocationAddress will be marked with a <code>EXTERNAL Data Elf Relocation with pointer-offset</code>
|
||||||
|
* warning bookmark.
|
||||||
|
* NOTE: This method should only be invoked when the symbol offset will be adjusted with a non-zero
|
||||||
* value (i.e., addend).
|
* value (i.e., addend).
|
||||||
* @param program
|
* @param program
|
||||||
* @param relocationAddress relocation address to be bookmarked if EXTERNAL block relocation
|
* @param relocationAddress relocation address to be bookmarked if EXTERNAL block relocation
|
||||||
|
@ -83,19 +108,14 @@ abstract public class ElfRelocationHandler implements ExtensionPoint {
|
||||||
* @param symbolName symbol name (may not be null if symbolAddr is not null)
|
* @param symbolName symbol name (may not be null if symbolAddr is not null)
|
||||||
* @param adjustment relocation symbol offset adjustment/addend
|
* @param adjustment relocation symbol offset adjustment/addend
|
||||||
* @param log import log
|
* @param log import log
|
||||||
* @return true if symbolAddress contained within EXTERNAL block.
|
|
||||||
*/
|
*/
|
||||||
public static boolean isUnsupportedExternalRelocation(Program program,
|
public static void warnExternalOffsetRelocation(Program program,
|
||||||
Address relocationAddress, Address symbolAddr, String symbolName, long adjustment,
|
Address relocationAddress, Address symbolAddr, String symbolName, long adjustment,
|
||||||
MessageLog log) {
|
MessageLog log) {
|
||||||
|
|
||||||
if (symbolAddr == null) {
|
if (symbolAddr == null || adjustment == 0 ||
|
||||||
return false;
|
!program.getMemory().isExternalBlockAddress(symbolAddr)) {
|
||||||
}
|
return;
|
||||||
|
|
||||||
MemoryBlock block = program.getMemory().getBlock(symbolAddr);
|
|
||||||
if (block == null || !MemoryBlock.EXTERNAL_BLOCK_NAME.equals(block.getName())) {
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
String sign = "+";
|
String sign = "+";
|
||||||
|
@ -106,12 +126,13 @@ abstract public class ElfRelocationHandler implements ExtensionPoint {
|
||||||
String adjStr = sign + "0x" + Long.toHexString(adjustment);
|
String adjStr = sign + "0x" + Long.toHexString(adjustment);
|
||||||
|
|
||||||
symbolName = symbolName == null ? "<no name>" : symbolName;
|
symbolName = symbolName == null ? "<no name>" : symbolName;
|
||||||
log.appendMsg("Unsupported EXTERNAL Data Elf Relocation: at " + relocationAddress +
|
Msg.warn(ElfRelocationHandler.class,
|
||||||
|
"EXTERNAL Data Elf Relocation with offset: at " + relocationAddress +
|
||||||
" (External Location = " + symbolName + adjStr + ")");
|
" (External Location = " + symbolName + adjStr + ")");
|
||||||
BookmarkManager bookmarkManager = program.getBookmarkManager();
|
BookmarkManager bookmarkManager = program.getBookmarkManager();
|
||||||
bookmarkManager.setBookmark(relocationAddress, BookmarkType.ERROR, "EXTERNAL Relocation",
|
bookmarkManager.setBookmark(relocationAddress, BookmarkType.WARNING, "EXTERNAL Relocation",
|
||||||
"Unsupported EXTERNAL Data Elf Relocation: External Location = " + symbolName + adjStr);
|
"EXTERNAL Data Elf Relocation with offset: External Location = " + symbolName +
|
||||||
return true;
|
adjStr);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -95,7 +95,7 @@ public class DemangledAddressTable extends DemangledObject {
|
||||||
}
|
}
|
||||||
|
|
||||||
Listing listing = program.getListing();
|
Listing listing = program.getListing();
|
||||||
if (MemoryBlock.isExternalBlockAddress(address, program)) {
|
if (program.getMemory().isExternalBlockAddress(address)) {
|
||||||
Msg.warn(this,
|
Msg.warn(this,
|
||||||
"Unable to fully apply external demangled Address Table at " + address + ": " +
|
"Unable to fully apply external demangled Address Table at " + address + ": " +
|
||||||
s.getName(true));
|
s.getName(true));
|
||||||
|
|
|
@ -29,7 +29,6 @@ import ghidra.program.model.address.AddressSetView;
|
||||||
import ghidra.program.model.data.*;
|
import ghidra.program.model.data.*;
|
||||||
import ghidra.program.model.lang.PrototypeModel;
|
import ghidra.program.model.lang.PrototypeModel;
|
||||||
import ghidra.program.model.listing.*;
|
import ghidra.program.model.listing.*;
|
||||||
import ghidra.program.model.mem.MemoryBlock;
|
|
||||||
import ghidra.program.model.symbol.*;
|
import ghidra.program.model.symbol.*;
|
||||||
import ghidra.program.model.util.CodeUnitInsertionException;
|
import ghidra.program.model.util.CodeUnitInsertionException;
|
||||||
import ghidra.util.Msg;
|
import ghidra.util.Msg;
|
||||||
|
@ -347,7 +346,7 @@ public class DemangledFunction extends DemangledObject {
|
||||||
* This method assumes preconditions test has been run.
|
* This method assumes preconditions test has been run.
|
||||||
*/
|
*/
|
||||||
private boolean shouldDisassemble(Program program, Address address, DemanglerOptions options) {
|
private boolean shouldDisassemble(Program program, Address address, DemanglerOptions options) {
|
||||||
if (!address.isMemoryAddress() || MemoryBlock.isExternalBlockAddress(address, program)) {
|
if (!address.isMemoryAddress() || program.getMemory().isExternalBlockAddress(address)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
CodeUnit codeUnit = program.getListing().getCodeUnitAt(address);
|
CodeUnit codeUnit = program.getListing().getCodeUnitAt(address);
|
||||||
|
|
|
@ -221,7 +221,7 @@ class MarkupXmlMgr {
|
||||||
Command cmd = null;
|
Command cmd = null;
|
||||||
if (baseAddr != null) {
|
if (baseAddr != null) {
|
||||||
long offset = toAddr.subtract(baseAddr);
|
long offset = toAddr.subtract(baseAddr);
|
||||||
cmd = new AddOffsetMemRefCmd(fromAddr, toAddr, refType,
|
cmd = new AddOffsetMemRefCmd(fromAddr, toAddr, false, refType,
|
||||||
userDefined ? SourceType.USER_DEFINED : SourceType.DEFAULT, opIndex, offset);
|
userDefined ? SourceType.USER_DEFINED : SourceType.DEFAULT, opIndex, offset);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
|
|
@ -758,7 +758,7 @@ public class ProgramBuilder {
|
||||||
return tx(() -> {
|
return tx(() -> {
|
||||||
ReferenceManager refManager = program.getReferenceManager();
|
ReferenceManager refManager = program.getReferenceManager();
|
||||||
Reference ref = refManager.addOffsetMemReference(addr(fromAddress), addr(toAddress),
|
Reference ref = refManager.addOffsetMemReference(addr(fromAddress), addr(toAddress),
|
||||||
offset, refType, sourceType, opIndex);
|
false, offset, refType, sourceType, opIndex);
|
||||||
return ref;
|
return ref;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
@ -444,8 +444,9 @@ public class DiffUtility extends SimpleDiffUtility {
|
||||||
|
|
||||||
Reference newRef;
|
Reference newRef;
|
||||||
if (ref.isOffsetReference()) {
|
if (ref.isOffsetReference()) {
|
||||||
newRef = otherRefMgr.addOffsetMemReference(otherFromAddress, otherToAddress,
|
OffsetReference offRef = (OffsetReference) ref;
|
||||||
((OffsetReference) ref).getOffset(), ref.getReferenceType(), ref.getSource(),
|
newRef = otherRefMgr.addOffsetMemReference(otherFromAddress, offRef.getBaseAddress(),
|
||||||
|
true, offRef.getOffset(), ref.getReferenceType(), ref.getSource(),
|
||||||
ref.getOperandIndex());
|
ref.getOperandIndex());
|
||||||
}
|
}
|
||||||
else if (ref.isShiftedReference()) {
|
else if (ref.isShiftedReference()) {
|
||||||
|
|
|
@ -29,7 +29,6 @@ import ghidra.program.model.data.*;
|
||||||
import ghidra.program.model.lang.*;
|
import ghidra.program.model.lang.*;
|
||||||
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.mem.MemoryBlock;
|
|
||||||
import ghidra.program.model.pcode.PcodeOp;
|
import ghidra.program.model.pcode.PcodeOp;
|
||||||
import ghidra.program.model.pcode.Varnode;
|
import ghidra.program.model.pcode.Varnode;
|
||||||
import ghidra.program.model.scalar.Scalar;
|
import ghidra.program.model.scalar.Scalar;
|
||||||
|
@ -75,7 +74,6 @@ public class SymbolicPropogator {
|
||||||
new NotFoundException("Divide by zero");
|
new NotFoundException("Divide by zero");
|
||||||
|
|
||||||
private long pointerMask;
|
private long pointerMask;
|
||||||
private AddressRange externalBlockRange;
|
|
||||||
|
|
||||||
protected static final int MAX_EXACT_INSTRUCTIONS = 100;
|
protected static final int MAX_EXACT_INSTRUCTIONS = 100;
|
||||||
|
|
||||||
|
@ -99,7 +97,6 @@ public class SymbolicPropogator {
|
||||||
spaceContext = new ProgramContextImpl(language);
|
spaceContext = new ProgramContextImpl(language);
|
||||||
|
|
||||||
setPointerMask(program);
|
setPointerMask(program);
|
||||||
setExternalRange(program);
|
|
||||||
|
|
||||||
context = new VarnodeContext(program, programContext, spaceContext);
|
context = new VarnodeContext(program, programContext, spaceContext);
|
||||||
context.setDebug(debug);
|
context.setDebug(debug);
|
||||||
|
@ -122,18 +119,6 @@ public class SymbolicPropogator {
|
||||||
pointerMask = maskSize[ptrSize];
|
pointerMask = maskSize[ptrSize];
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Identify EXTERNAL block range which should not be disassembled.
|
|
||||||
* @param program
|
|
||||||
* @return EXTERNAL block range or null if not found
|
|
||||||
*/
|
|
||||||
private void setExternalRange(Program program) {
|
|
||||||
MemoryBlock block = program.getMemory().getBlock(MemoryBlock.EXTERNAL_BLOCK_NAME);
|
|
||||||
if (block != null) {
|
|
||||||
externalBlockRange = new AddressRangeImpl(block.getStart(), block.getEnd());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Process a subroutine using the processor function.
|
* Process a subroutine using the processor function.
|
||||||
* The process function can control what flows are followed and when to stop.
|
* The process function can control what flows are followed and when to stop.
|
||||||
|
@ -2329,7 +2314,7 @@ public class SymbolicPropogator {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (refType.isFlow() && !refType.isIndirect() &&
|
if (refType.isFlow() && !refType.isIndirect() &&
|
||||||
(externalBlockRange == null || !externalBlockRange.contains(target))) {
|
!program.getMemory().isExternalBlockAddress(target)) {
|
||||||
Data udata = program.getListing().getUndefinedDataAt(target);
|
Data udata = program.getListing().getUndefinedDataAt(target);
|
||||||
if (udata != null) {
|
if (udata != null) {
|
||||||
DisassembleCommand cmd = new DisassembleCommand(target, null, true);
|
DisassembleCommand cmd = new DisassembleCommand(target, null, true);
|
||||||
|
|
|
@ -748,8 +748,8 @@ public class ReferenceManagerTest extends AbstractGhidraHeadedIntegrationTest {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testAddOffsetReference() {
|
public void testAddOffsetReference() {
|
||||||
refMgr.addOffsetMemReference(addr(100), addr(600), 100, RefType.COMPUTED_JUMP,
|
refMgr.addOffsetMemReference(addr(100), addr(600), false, 100,
|
||||||
SourceType.USER_DEFINED, 0);
|
RefType.COMPUTED_JUMP, SourceType.USER_DEFINED, 0);
|
||||||
|
|
||||||
Reference ref = refMgr.getReference(addr(100), addr(600), 0);
|
Reference ref = refMgr.getReference(addr(100), addr(600), 0);
|
||||||
assertNotNull(ref);
|
assertNotNull(ref);
|
||||||
|
|
|
@ -69,11 +69,11 @@ public class AddressBasedLocationTest extends AbstractGhidraHeadlessIntegrationT
|
||||||
ReferenceManager rm = program.getReferenceManager();
|
ReferenceManager rm = program.getReferenceManager();
|
||||||
|
|
||||||
Reference offsetRef1 =
|
Reference offsetRef1 =
|
||||||
rm.addOffsetMemReference(addr("CODE:0"), addr("CODE:110"), 0x10, DATA, ANALYSIS, 0);
|
rm.addOffsetMemReference(addr("CODE:0"), addr("CODE:110"), false, 0x10, DATA, ANALYSIS, 0);
|
||||||
Reference offsetRef2 =
|
Reference offsetRef2 =
|
||||||
rm.addOffsetMemReference(addr("CODE:1"), addr("CODE:f0"), -0x10, DATA, ANALYSIS, 0);
|
rm.addOffsetMemReference(addr("CODE:1"), addr("CODE:f0"), false, -0x10, DATA, ANALYSIS, 0);
|
||||||
Reference offsetRef3 =
|
Reference offsetRef3 =
|
||||||
rm.addOffsetMemReference(addr("CODE:2"), addr("CODE:120"), 0x20, DATA, ANALYSIS, 0);
|
rm.addOffsetMemReference(addr("CODE:2"), addr("CODE:120"), false, 0x20, DATA, ANALYSIS, 0);
|
||||||
|
|
||||||
Reference stackRef1 = rm.addStackReference(addr("CODE:3"), 0, 0x10, DATA, ANALYSIS);
|
Reference stackRef1 = rm.addStackReference(addr("CODE:3"), 0, 0x10, DATA, ANALYSIS);
|
||||||
Reference stackRef2 = rm.addStackReference(addr("CODE:4"), 0, -0x10, DATA, ANALYSIS);
|
Reference stackRef2 = rm.addStackReference(addr("CODE:4"), 0, -0x10, DATA, ANALYSIS);
|
||||||
|
|
|
@ -473,7 +473,7 @@ public class DecompileCallback {
|
||||||
if (error != null && addr.equals(error.getInstructionAddress())) {
|
if (error != null && addr.equals(error.getInstructionAddress())) {
|
||||||
throw new UnknownInstructionException(error.getConflictMessage());
|
throw new UnknownInstructionException(error.getConflictMessage());
|
||||||
}
|
}
|
||||||
if (MemoryBlock.isExternalBlockAddress(addr, program)) {
|
if (program.getMemory().isExternalBlockAddress(addr)) {
|
||||||
throw new UnknownInstructionException(
|
throw new UnknownInstructionException(
|
||||||
"Unable to disassemble EXTERNAL block location: " + addr);
|
"Unable to disassemble EXTERNAL block location: " + addr);
|
||||||
}
|
}
|
||||||
|
|
|
@ -2115,8 +2115,9 @@ public class CodeManager implements ErrorHandler, ManagerDB {
|
||||||
long pointerComponentOffset =
|
long pointerComponentOffset =
|
||||||
PointerTypedefInspector.getPointerComponentOffset((TypeDef) dataType);
|
PointerTypedefInspector.getPointerComponentOffset((TypeDef) dataType);
|
||||||
if (pointerComponentOffset != 0) {
|
if (pointerComponentOffset != 0) {
|
||||||
refManager.addOffsetMemReference(data.getMinAddress(), toAddr,
|
refManager.addOffsetMemReference(data.getMinAddress(),
|
||||||
pointerComponentOffset, RefType.DATA, SourceType.DEFAULT, 0);
|
toAddr.subtractWrap(pointerComponentOffset), true, pointerComponentOffset,
|
||||||
|
RefType.DATA, SourceType.DEFAULT, 0);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -31,7 +31,6 @@ import ghidra.program.model.address.*;
|
||||||
import ghidra.program.model.data.*;
|
import ghidra.program.model.data.*;
|
||||||
import ghidra.program.model.lang.*;
|
import ghidra.program.model.lang.*;
|
||||||
import ghidra.program.model.listing.*;
|
import ghidra.program.model.listing.*;
|
||||||
import ghidra.program.model.mem.MemoryBlock;
|
|
||||||
import ghidra.program.model.pcode.HighFunction;
|
import ghidra.program.model.pcode.HighFunction;
|
||||||
import ghidra.program.model.symbol.*;
|
import ghidra.program.model.symbol.*;
|
||||||
import ghidra.program.model.util.PropertyMapManager;
|
import ghidra.program.model.util.PropertyMapManager;
|
||||||
|
@ -348,8 +347,7 @@ public class FunctionManagerDB implements FunctionManager {
|
||||||
if (body == null || !body.contains(entryPoint)) {
|
if (body == null || !body.contains(entryPoint)) {
|
||||||
throw new IllegalArgumentException("Function body must contain the entrypoint");
|
throw new IllegalArgumentException("Function body must contain the entrypoint");
|
||||||
}
|
}
|
||||||
if (codeMgr.getDefinedDataAt(entryPoint) != null &&
|
if (codeMgr.getDefinedDataAt(entryPoint) != null) {
|
||||||
!MemoryBlock.isExternalBlockAddress(entryPoint, program)) {
|
|
||||||
throw new IllegalArgumentException(
|
throw new IllegalArgumentException(
|
||||||
"Function entryPoint may not be created on defined data");
|
"Function entryPoint may not be created on defined data");
|
||||||
}
|
}
|
||||||
|
|
|
@ -57,6 +57,7 @@ public class MemoryMapDB implements Memory, ManagerDB, LiveMemoryListener {
|
||||||
private AddressSet initializedLoadedAddrSet = new AddressSet();
|
private AddressSet initializedLoadedAddrSet = new AddressSet();
|
||||||
private AddressSet allInitializedAddrSet = new AddressSet();
|
private AddressSet allInitializedAddrSet = new AddressSet();
|
||||||
private AddressSetView executeSet = null;
|
private AddressSetView executeSet = null;
|
||||||
|
private AddressSet externalBlockAddrSet;
|
||||||
|
|
||||||
private MemoryBlock lastBlock;// the last accessed block
|
private MemoryBlock lastBlock;// the last accessed block
|
||||||
private LiveMemoryHandler liveMemory;
|
private LiveMemoryHandler liveMemory;
|
||||||
|
@ -130,6 +131,7 @@ public class MemoryMapDB implements Memory, ManagerDB, LiveMemoryListener {
|
||||||
addrSet = new AddressSet();
|
addrSet = new AddressSet();
|
||||||
initializedLoadedAddrSet = new AddressSet();
|
initializedLoadedAddrSet = new AddressSet();
|
||||||
allInitializedAddrSet = new AddressSet();
|
allInitializedAddrSet = new AddressSet();
|
||||||
|
externalBlockAddrSet = new AddressSet();
|
||||||
// we have to process the non-mapped blocks first because to process the mapped
|
// we have to process the non-mapped blocks first because to process the mapped
|
||||||
// blocks we need the address sets for the non-mapped blocks to be complete
|
// blocks we need the address sets for the non-mapped blocks to be complete
|
||||||
for (MemoryBlockDB block : blocks) {
|
for (MemoryBlockDB block : blocks) {
|
||||||
|
@ -161,6 +163,10 @@ public class MemoryMapDB implements Memory, ManagerDB, LiveMemoryListener {
|
||||||
private void addBlockAddresses(MemoryBlockDB block, boolean scanAllMappedBlocksIfNeeded) {
|
private void addBlockAddresses(MemoryBlockDB block, boolean scanAllMappedBlocksIfNeeded) {
|
||||||
AddressSet blockSet = new AddressSet(block.getStart(), block.getEnd());
|
AddressSet blockSet = new AddressSet(block.getStart(), block.getEnd());
|
||||||
addrSet = addrSet.union(blockSet);
|
addrSet = addrSet.union(blockSet);
|
||||||
|
if (block.isExternalBlock()) {
|
||||||
|
// NOTE: no handling for mapped blocks which should never map onto EXTERNAL block
|
||||||
|
externalBlockAddrSet.add(block.getStart(), block.getEnd());
|
||||||
|
}
|
||||||
if (block.isMapped()) {
|
if (block.isMapped()) {
|
||||||
|
|
||||||
// Identify source-blocks which block maps onto and add as a mapped-block to each of these
|
// Identify source-blocks which block maps onto and add as a mapped-block to each of these
|
||||||
|
@ -1765,6 +1771,11 @@ public class MemoryMapDB implements Memory, ManagerDB, LiveMemoryListener {
|
||||||
return addrSet.isEmpty();
|
return addrSet.isEmpty();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isExternalBlockAddress(Address addr) {
|
||||||
|
return externalBlockAddrSet.contains(addr);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Address getMinAddress() {
|
public Address getMinAddress() {
|
||||||
return addrSet.getMinAddress();
|
return addrSet.getMinAddress();
|
||||||
|
|
|
@ -15,11 +15,10 @@
|
||||||
*/
|
*/
|
||||||
package ghidra.program.database.references;
|
package ghidra.program.database.references;
|
||||||
|
|
||||||
import ghidra.program.model.address.*;
|
import ghidra.program.model.address.Address;
|
||||||
import ghidra.program.model.listing.*;
|
import ghidra.program.model.listing.Program;
|
||||||
import ghidra.program.model.symbol.*;
|
import ghidra.program.model.symbol.*;
|
||||||
import ghidra.program.util.*;
|
import ghidra.program.util.SimpleDiffUtility;
|
||||||
import ghidra.util.task.TaskMonitor;
|
|
||||||
|
|
||||||
class MemReferenceDB extends ReferenceDB {
|
class MemReferenceDB extends ReferenceDB {
|
||||||
|
|
||||||
|
@ -44,6 +43,10 @@ class MemReferenceDB extends ReferenceDB {
|
||||||
this(program, from, to, type, opIndex, sourceType, isPrimary, symbolID, false, false, 0);
|
this(program, from, to, type, opIndex, sourceType, isPrimary, symbolID, false, false, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected boolean isExternalBlockReference() {
|
||||||
|
return program.getMemory().isExternalBlockAddress(getToAddress());
|
||||||
|
}
|
||||||
|
|
||||||
public boolean isOffset() {
|
public boolean isOffset() {
|
||||||
return isOffset;
|
return isOffset;
|
||||||
}
|
}
|
||||||
|
@ -56,12 +59,6 @@ class MemReferenceDB extends ReferenceDB {
|
||||||
return offsetOrShift;
|
return offsetOrShift;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @see ghidra.program.database.references.ReferenceDB#setProgram(ghidra.program.model.listing.Program)
|
|
||||||
*/
|
|
||||||
void setProgram(Program program) {
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @see ghidra.program.model.symbol.Reference#isOffsetReference()
|
* @see ghidra.program.model.symbol.Reference#isOffsetReference()
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -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.
|
||||||
|
@ -28,17 +27,17 @@ class OffsetReferenceDB extends MemReferenceDB implements OffsetReference {
|
||||||
offset);
|
offset);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
@Override
|
||||||
* @see ghidra.program.model.symbol.OffsetReference#getOffset()
|
|
||||||
*/
|
|
||||||
public long getOffset() {
|
public long getOffset() {
|
||||||
return offsetOrShift;
|
return offsetOrShift;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
@Override
|
||||||
* @see ghidra.program.model.symbol.OffsetReference#getBaseAddress()
|
|
||||||
*/
|
|
||||||
public Address getBaseAddress() {
|
public Address getBaseAddress() {
|
||||||
|
if (isExternalBlockReference()) {
|
||||||
|
// EXTERNAL block: must report toAddr and base as the same regardless of offset
|
||||||
|
return toAddr;
|
||||||
|
}
|
||||||
return toAddr.subtractWrap(offsetOrShift);
|
return toAddr.subtractWrap(offsetOrShift);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -56,4 +55,5 @@ class OffsetReferenceDB extends MemReferenceDB implements OffsetReference {
|
||||||
OffsetReference ref = (OffsetReference) obj;
|
OffsetReference ref = (OffsetReference) obj;
|
||||||
return offsetOrShift == ref.getOffset();
|
return offsetOrShift == ref.getOffset();
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -34,6 +34,7 @@ import ghidra.program.model.pcode.Varnode;
|
||||||
import ghidra.program.model.symbol.*;
|
import ghidra.program.model.symbol.*;
|
||||||
import ghidra.program.util.ChangeManager;
|
import ghidra.program.util.ChangeManager;
|
||||||
import ghidra.util.Lock;
|
import ghidra.util.Lock;
|
||||||
|
import ghidra.util.Msg;
|
||||||
import ghidra.util.exception.*;
|
import ghidra.util.exception.*;
|
||||||
import ghidra.util.task.TaskMonitor;
|
import ghidra.util.task.TaskMonitor;
|
||||||
|
|
||||||
|
@ -486,12 +487,48 @@ public class ReferenceDBManager implements ReferenceManager, ManagerDB, ErrorHan
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private boolean isExternalBlockAddress(Address addr) {
|
||||||
|
return program.getMemory().isExternalBlockAddress(addr);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Reference addOffsetMemReference(Address fromAddr, Address toAddr, long offset,
|
public Reference addOffsetMemReference(Address fromAddr, Address toAddr, boolean toAddrIsBase,
|
||||||
RefType type, SourceType sourceType, int opIndex) {
|
long offset, RefType type, SourceType sourceType, int opIndex) {
|
||||||
if (!fromAddr.isMemoryAddress() || !toAddr.isMemoryAddress()) {
|
if (!fromAddr.isMemoryAddress() || !toAddr.isMemoryAddress()) {
|
||||||
throw new IllegalArgumentException("From and To addresses must be memory addresses");
|
throw new IllegalArgumentException("From and To addresses must be memory addresses");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Handle EXTERNAL Block offset-reference transformation
|
||||||
|
boolean isExternalBlockRef = isExternalBlockAddress(toAddr);
|
||||||
|
boolean badOffsetReference = false;
|
||||||
|
if (isExternalBlockRef) {
|
||||||
|
// NOTE: Resulting EXTERNAL Block reference may become incorrect
|
||||||
|
// if EXTERNAL block is moved or removed.
|
||||||
|
if (!toAddrIsBase) {
|
||||||
|
Address baseAddr = toAddr.subtractWrap(offset);
|
||||||
|
if (isExternalBlockAddress(baseAddr)) {
|
||||||
|
toAddr = baseAddr;
|
||||||
|
toAddrIsBase = true;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
// assume unintentional reference into EXTERNAL block
|
||||||
|
isExternalBlockRef = false;
|
||||||
|
badOffsetReference = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (toAddrIsBase) {
|
||||||
|
Address addr = toAddr.addWrap(offset);
|
||||||
|
if (isExternalBlockAddress(addr)) {
|
||||||
|
badOffsetReference = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (badOffsetReference) {
|
||||||
|
Msg.warn(this, "Offset Reference from " + fromAddr +
|
||||||
|
" produces bad Xref into EXTERNAL block");
|
||||||
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
removeNonMemRefs(fromAddr, opIndex);
|
removeNonMemRefs(fromAddr, opIndex);
|
||||||
return addRef(fromAddr, toAddr, type, sourceType, opIndex, true, false, offset);
|
return addRef(fromAddr, toAddr, type, sourceType, opIndex, true, false, offset);
|
||||||
|
@ -1883,7 +1920,9 @@ public class ReferenceDBManager implements ReferenceManager, ManagerDB, ErrorHan
|
||||||
Reference memRef;
|
Reference memRef;
|
||||||
if (ref.isOffsetReference()) {
|
if (ref.isOffsetReference()) {
|
||||||
OffsetReference offRef = (OffsetReference) ref;
|
OffsetReference offRef = (OffsetReference) ref;
|
||||||
memRef = addOffsetMemReference(from, to, offRef.getOffset(), type, sourceType, opIndex);
|
memRef =
|
||||||
|
addOffsetMemReference(from, offRef.getBaseAddress(), true, offRef.getOffset(), type,
|
||||||
|
sourceType, opIndex);
|
||||||
}
|
}
|
||||||
else if (ref.isShiftedReference()) {
|
else if (ref.isShiftedReference()) {
|
||||||
ShiftedReference shiftRef = (ShiftedReference) ref;
|
ShiftedReference shiftRef = (ShiftedReference) ref;
|
||||||
|
|
|
@ -23,6 +23,7 @@ import ghidra.framework.store.LockException;
|
||||||
import ghidra.program.database.mem.*;
|
import ghidra.program.database.mem.*;
|
||||||
import ghidra.program.model.address.*;
|
import ghidra.program.model.address.*;
|
||||||
import ghidra.program.model.listing.Program;
|
import ghidra.program.model.listing.Program;
|
||||||
|
import ghidra.program.model.symbol.OffsetReference;
|
||||||
import ghidra.util.exception.CancelledException;
|
import ghidra.util.exception.CancelledException;
|
||||||
import ghidra.util.exception.NotFoundException;
|
import ghidra.util.exception.NotFoundException;
|
||||||
import ghidra.util.task.TaskMonitor;
|
import ghidra.util.task.TaskMonitor;
|
||||||
|
@ -87,6 +88,23 @@ public interface Memory extends AddressSetView {
|
||||||
*/
|
*/
|
||||||
public boolean isBigEndian();
|
public boolean isBigEndian();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Determine if the specified address is contained within the reserved EXTERNAL block
|
||||||
|
* (see {@link MemoryBlock#EXTERNAL_BLOCK_NAME}). This artificial memory block has certain
|
||||||
|
* limitations that may require associated addresses to be properly identified. All
|
||||||
|
* data access/referencing has the biggest exposure since the importers generally
|
||||||
|
* allocate a fixed and possibly insufficient amount of memory to corresponding data
|
||||||
|
* symbols. Any pointer math performed based upon an EXTERNAL block symbol address
|
||||||
|
* is likely to produce an unuseable address that may collide with unrelated symbols
|
||||||
|
* stored within the memory block (e.g., {@link OffsetReference} is one such example).
|
||||||
|
* @param addr address
|
||||||
|
* @return true if address is contained within EXTERNAL memory block, else false.
|
||||||
|
*/
|
||||||
|
public default boolean isExternalBlockAddress(Address addr) {
|
||||||
|
MemoryBlock block = getBlock(addr);
|
||||||
|
return block != null && block.isExternalBlock();
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets the live memory handler
|
* Sets the live memory handler
|
||||||
* @param handler the live memory handler
|
* @param handler the live memory handler
|
||||||
|
|
|
@ -22,7 +22,8 @@ import java.util.List;
|
||||||
|
|
||||||
import ghidra.framework.store.LockException;
|
import ghidra.framework.store.LockException;
|
||||||
import ghidra.program.model.address.Address;
|
import ghidra.program.model.address.Address;
|
||||||
import ghidra.program.model.listing.Program;
|
import ghidra.program.model.address.AddressSpace;
|
||||||
|
import ghidra.program.model.symbol.OffsetReference;
|
||||||
import ghidra.util.NamingUtilities;
|
import ghidra.util.NamingUtilities;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -31,8 +32,18 @@ import ghidra.util.NamingUtilities;
|
||||||
public interface MemoryBlock extends Serializable, Comparable<MemoryBlock> {
|
public interface MemoryBlock extends Serializable, Comparable<MemoryBlock> {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A special EXTERNAL block may be created by certain program loaders (e.g., Elf) to act as a
|
* A special purpose EXTERNAL block may be created by certain program loaders
|
||||||
* stand-in for unknown external symbol locations.
|
* (e.g., Elf) to act as a stand-in for unknown external symbol locations when
|
||||||
|
* relocation support is required using a valid memory address. While the
|
||||||
|
* EXTERNAL block is created out of neccessity for relocation processing it
|
||||||
|
* introduces a number of limitations when used to carry data symbols
|
||||||
|
* where pointer math and offset-references may occur.
|
||||||
|
* <p>
|
||||||
|
* The method {@link Memory#isExternalBlockAddress(Address)}
|
||||||
|
* may be used to determine if a specific address is contained within an EXTERNAL memory block.
|
||||||
|
* <p>
|
||||||
|
* NOTE: Close proximity to the end of an address space should be avoided
|
||||||
|
* to allow for {@link OffsetReference} use.
|
||||||
*/
|
*/
|
||||||
public static final String EXTERNAL_BLOCK_NAME = "EXTERNAL";
|
public static final String EXTERNAL_BLOCK_NAME = "EXTERNAL";
|
||||||
|
|
||||||
|
@ -272,9 +283,27 @@ public interface MemoryBlock extends Serializable, Comparable<MemoryBlock> {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns true if this is either a bit-mapped or byte-mapped block
|
* Returns true if this is either a bit-mapped or byte-mapped block
|
||||||
|
*
|
||||||
|
* @return true if this is either a bit-mapped or byte-mapped block
|
||||||
*/
|
*/
|
||||||
public boolean isMapped();
|
public boolean isMapped();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns true if this is a reserved EXTERNAL memory block based upon its name
|
||||||
|
* (see {@link MemoryBlock#EXTERNAL_BLOCK_NAME}). Checks for individual addresses may be done
|
||||||
|
* using {@link Memory#isExternalBlockAddress(Address)}.
|
||||||
|
* <p>
|
||||||
|
* Note that EXTERNAL blocks always resides within a memory space and never within the artifial
|
||||||
|
* {@link AddressSpace#EXTERNAL_SPACE} which is not a memory space. This can be a source of confusion.
|
||||||
|
* An EXTERNAL memory block exists to facilitate relocation processing for some external
|
||||||
|
* symbols which require a real memory address.
|
||||||
|
*
|
||||||
|
* @return true if this is a reserved EXTERNAL memory block
|
||||||
|
*/
|
||||||
|
public default boolean isExternalBlock() {
|
||||||
|
return EXTERNAL_BLOCK_NAME.equals(getName());
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns true if this is an overlay block (i.e., contained within overlay space).
|
* Returns true if this is an overlay block (i.e., contained within overlay space).
|
||||||
*
|
*
|
||||||
|
@ -300,19 +329,4 @@ public interface MemoryBlock extends Serializable, Comparable<MemoryBlock> {
|
||||||
*/
|
*/
|
||||||
public List<MemoryBlockSourceInfo> getSourceInfos();
|
public List<MemoryBlockSourceInfo> getSourceInfos();
|
||||||
|
|
||||||
/**
|
|
||||||
* Determine if the specified address is contained within the reserved EXTERNAL block.
|
|
||||||
*
|
|
||||||
* @param address address of interest
|
|
||||||
* @param program
|
|
||||||
* @return true if address is contained within the reserved EXTERNAL block, else false.
|
|
||||||
*/
|
|
||||||
public static boolean isExternalBlockAddress(Address address, Program program) {
|
|
||||||
Memory memory = program.getMemory();
|
|
||||||
if (!address.isMemoryAddress()) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
MemoryBlock block = memory.getBlock(address);
|
|
||||||
return block != null && MemoryBlock.EXTERNAL_BLOCK_NAME.equals(block.getName());
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,10 +16,15 @@
|
||||||
package ghidra.program.model.symbol;
|
package ghidra.program.model.symbol;
|
||||||
|
|
||||||
import ghidra.program.model.address.Address;
|
import ghidra.program.model.address.Address;
|
||||||
|
import ghidra.program.model.mem.MemoryBlock;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* <code>OffsetReference</code> is a memory reference whose "to" address is
|
* <code>OffsetReference</code> is a memory reference whose "to" address is
|
||||||
* computed from a base address plus an offset.
|
* computed from a base address plus an offset.
|
||||||
|
* <p>
|
||||||
|
* NOTE: References into the reserved EXTERNAL block must report {@link #getToAddress()}
|
||||||
|
* the same as {@link #getBaseAddress()} regardless of offset value due to symbol
|
||||||
|
* spacing limitations within the EXTERNAL block. See {@link MemoryBlock#EXTERNAL_BLOCK_NAME}.
|
||||||
*/
|
*/
|
||||||
public interface OffsetReference extends Reference {
|
public interface OffsetReference extends Reference {
|
||||||
|
|
||||||
|
@ -35,4 +40,12 @@ public interface OffsetReference extends Reference {
|
||||||
*/
|
*/
|
||||||
public Address getBaseAddress();
|
public Address getBaseAddress();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return the base address plus the offset. The exception to this is the
|
||||||
|
* EXTERNAL block case where this method returns the base address regardless
|
||||||
|
* of the offset value.
|
||||||
|
* @return reference "to" address
|
||||||
|
*/
|
||||||
|
public Address getToAddress();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -18,6 +18,7 @@ package ghidra.program.model.symbol;
|
||||||
import ghidra.program.model.address.*;
|
import ghidra.program.model.address.*;
|
||||||
import ghidra.program.model.lang.Register;
|
import ghidra.program.model.lang.Register;
|
||||||
import ghidra.program.model.listing.Variable;
|
import ghidra.program.model.listing.Variable;
|
||||||
|
import ghidra.program.model.mem.MemoryBlock;
|
||||||
import ghidra.util.exception.DuplicateNameException;
|
import ghidra.util.exception.DuplicateNameException;
|
||||||
import ghidra.util.exception.InvalidInputException;
|
import ghidra.util.exception.InvalidInputException;
|
||||||
|
|
||||||
|
@ -32,7 +33,8 @@ public interface ReferenceManager {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Add a memory, stack, register or external reference
|
* Add a memory, stack, register or external reference
|
||||||
* @param reference
|
* @param reference reference to be added
|
||||||
|
* @return new reference
|
||||||
*/
|
*/
|
||||||
public Reference addReference(Reference reference);
|
public Reference addReference(Reference reference);
|
||||||
|
|
||||||
|
@ -45,6 +47,7 @@ public interface ReferenceManager {
|
||||||
* @param stackOffset stack offset of the reference
|
* @param stackOffset stack offset of the reference
|
||||||
* @param type reference type - how the location is being referenced.
|
* @param type reference type - how the location is being referenced.
|
||||||
* @param source the source of this reference
|
* @param source the source of this reference
|
||||||
|
* @return new stack reference
|
||||||
*/
|
*/
|
||||||
public Reference addStackReference(Address fromAddr, int opIndex, int stackOffset, RefType type,
|
public Reference addStackReference(Address fromAddr, int opIndex, int stackOffset, RefType type,
|
||||||
SourceType source);
|
SourceType source);
|
||||||
|
@ -58,12 +61,13 @@ public interface ReferenceManager {
|
||||||
* @param register register to add the reference to
|
* @param register register to add the reference to
|
||||||
* @param type reference type - how the location is being referenced.
|
* @param type reference type - how the location is being referenced.
|
||||||
* @param source the source of this reference
|
* @param source the source of this reference
|
||||||
|
* @return new register reference
|
||||||
*/
|
*/
|
||||||
public Reference addRegisterReference(Address fromAddr, int opIndex, Register register,
|
public Reference addRegisterReference(Address fromAddr, int opIndex, Register register,
|
||||||
RefType type, SourceType source);
|
RefType type, SourceType source);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Adds a memory reference. Only first the first memory reference placed on
|
* Adds a memory reference. The first memory reference placed on
|
||||||
* an operand will be made primary by default. All non-memory references
|
* an operand will be made primary by default. All non-memory references
|
||||||
* will be removed from the specified operand.
|
* will be removed from the specified operand.
|
||||||
* @param fromAddr address of the codeunit where the reference occurs
|
* @param fromAddr address of the codeunit where the reference occurs
|
||||||
|
@ -73,37 +77,46 @@ public interface ReferenceManager {
|
||||||
* @param source the source of this reference
|
* @param source the source of this reference
|
||||||
* @param opIndex the operand index
|
* @param opIndex the operand index
|
||||||
* display of the operand making this reference
|
* display of the operand making this reference
|
||||||
|
* @return new memory reference
|
||||||
*/
|
*/
|
||||||
public Reference addMemoryReference(Address fromAddr, Address toAddr, RefType type,
|
public Reference addMemoryReference(Address fromAddr, Address toAddr, RefType type,
|
||||||
SourceType source, int opIndex);
|
SourceType source, int opIndex);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Add an offset memory reference. Only first the first memory reference placed on
|
* Add an offset memory reference. The first memory reference placed on
|
||||||
* an operand will be made primary by default. All non-memory references
|
* an operand will be made primary by default. All non-memory references
|
||||||
* will be removed from the specified operand.
|
* will be removed from the specified operand. If toAddr corresponds to
|
||||||
|
* the EXTERNAL memory block (see {@link MemoryBlock#EXTERNAL_BLOCK_NAME}) the
|
||||||
|
* resulting offset reference will report to/base address as the same
|
||||||
|
* regardless of specified offset.
|
||||||
* @param fromAddr address for the "from"
|
* @param fromAddr address for the "from"
|
||||||
* @param toAddr address of the "to"
|
* @param toAddr address of the location being referenced.
|
||||||
|
* @param toAddrIsBase if true toAddr is treated as base address, else treated as (base+offet).
|
||||||
|
* It is generally preferred to specify as a base address to ensure proper handling of
|
||||||
|
* EXTERNAL block case.
|
||||||
* @param offset value added to a base address to get the toAddr
|
* @param offset value added to a base address to get the toAddr
|
||||||
* @param type reference type - how the location is being referenced
|
* @param type reference type - how the location is being referenced
|
||||||
* @param source the source of this reference
|
* @param source the source of this reference
|
||||||
* @param opIndex the operand index
|
* @param opIndex the operand index
|
||||||
|
* @return new offset reference
|
||||||
*/
|
*/
|
||||||
public Reference addOffsetMemReference(Address fromAddr, Address toAddr, long offset,
|
public Reference addOffsetMemReference(Address fromAddr, Address toAddr, boolean toAddrIsBase,
|
||||||
RefType type, SourceType source, int opIndex);
|
long offset, RefType type, SourceType source, int opIndex);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Add a shifted memory reference; the "to" address is computed as the value
|
* Add a shifted memory reference; the "to" address is computed as the value
|
||||||
* at the operand at opIndex shifted by some number of bits, specified in the
|
* at the operand at opIndex shifted by some number of bits, specified in the
|
||||||
* shiftValue parameter. Only first the first memory reference placed on
|
* shiftValue parameter. The first memory reference placed on
|
||||||
* an operand will be made primary by default. All non-memory references
|
* an operand will be made primary by default. All non-memory references
|
||||||
* will be removed from the specified operand.
|
* will be removed from the specified operand.
|
||||||
* @param fromAddr address for the "from"
|
* @param fromAddr address for the "from"
|
||||||
* @param toAddr computed as the value of the operand at opIndex shifted
|
* @param toAddr computed as the value of the operand at opIndex shifted
|
||||||
* by the number of bits specified by shiftValue
|
* by the number of bits specified by shiftValue
|
||||||
* @param shiftValue
|
* @param shiftValue shifted value
|
||||||
* @param type reference type - how the location is being referenced
|
* @param type reference type - how the location is being referenced
|
||||||
* @param source the source of this reference
|
* @param source the source of this reference
|
||||||
* @param opIndex the operand index
|
* @param opIndex the operand index
|
||||||
|
* @return new shifted reference
|
||||||
*/
|
*/
|
||||||
public Reference addShiftedMemReference(Address fromAddr, Address toAddr, int shiftValue,
|
public Reference addShiftedMemReference(Address fromAddr, Address toAddr, int shiftValue,
|
||||||
RefType type, SourceType source, int opIndex);
|
RefType type, SourceType source, int opIndex);
|
||||||
|
@ -117,8 +130,9 @@ public interface ReferenceManager {
|
||||||
* @param extLabel label within the external program, may be null if extAddr is not null
|
* @param extLabel label within the external program, may be null if extAddr is not null
|
||||||
* @param extAddr address within the external program, may be null
|
* @param extAddr address within the external program, may be null
|
||||||
* @param source the source of this reference
|
* @param source the source of this reference
|
||||||
* @param type reference type - how the location is being referenced
|
|
||||||
* @param opIndex operand index
|
* @param opIndex operand index
|
||||||
|
* @param type reference type - how the location is being referenced
|
||||||
|
* @return new external space reference
|
||||||
* @throws InvalidInputException
|
* @throws InvalidInputException
|
||||||
* @throws DuplicateNameException
|
* @throws DuplicateNameException
|
||||||
*/
|
*/
|
||||||
|
@ -135,8 +149,9 @@ public interface ReferenceManager {
|
||||||
* @param extLabel label within the external program, may be null if extAddr is not null
|
* @param extLabel label within the external program, may be null if extAddr is not null
|
||||||
* @param extAddr address within the external program, may be null
|
* @param extAddr address within the external program, may be null
|
||||||
* @param source the source of this reference
|
* @param source the source of this reference
|
||||||
* @param type reference type - how the location is being referenced
|
|
||||||
* @param opIndex operand index
|
* @param opIndex operand index
|
||||||
|
* @param type reference type - how the location is being referenced
|
||||||
|
* @return new external space reference
|
||||||
* @throws InvalidInputException
|
* @throws InvalidInputException
|
||||||
* @throws DuplicateNameException
|
* @throws DuplicateNameException
|
||||||
*/
|
*/
|
||||||
|
@ -191,7 +206,7 @@ public interface ReferenceManager {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the referenced function variable.
|
* Returns the referenced function variable.
|
||||||
* @param reference
|
* @param reference variable reference
|
||||||
* @return function variable or null if variable not found
|
* @return function variable or null if variable not found
|
||||||
*/
|
*/
|
||||||
public Variable getReferencedVariable(Reference reference);
|
public Variable getReferencedVariable(Reference reference);
|
||||||
|
@ -204,19 +219,23 @@ public interface ReferenceManager {
|
||||||
public void setPrimary(Reference ref, boolean isPrimary);
|
public void setPrimary(Reference ref, boolean isPrimary);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Return whether the given address has flow references from this address.
|
* Return whether the given address has flow references from it.
|
||||||
* @param addr the address to test for flow references.
|
* @param addr the address to test for flow references.
|
||||||
|
* @return true if the given address has flow references from it, else false
|
||||||
*/
|
*/
|
||||||
public boolean hasFlowReferencesFrom(Address addr);
|
public boolean hasFlowReferencesFrom(Address addr);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the flow references from the given address.
|
* Get all flow references from the given address.
|
||||||
* @param addr the address of the codeunit to get all flows from.
|
* @param addr the address of the codeunit to get all flows from.
|
||||||
|
* @return get all flow references from the given address.
|
||||||
|
*
|
||||||
*/
|
*/
|
||||||
public Reference[] getFlowReferencesFrom(Address addr);
|
public Reference[] getFlowReferencesFrom(Address addr);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns an iterator over all external references
|
* Returns an iterator over all external space references
|
||||||
|
* @return reference iterator over all external space references
|
||||||
*/
|
*/
|
||||||
public ReferenceIterator getExternalReferences();
|
public ReferenceIterator getExternalReferences();
|
||||||
|
|
||||||
|
@ -224,6 +243,7 @@ public interface ReferenceManager {
|
||||||
* Get an iterator over all references that have the given address as
|
* Get an iterator over all references that have the given address as
|
||||||
* their "To" address.
|
* their "To" address.
|
||||||
* @param addr the address that all references in the iterator refer to.
|
* @param addr the address that all references in the iterator refer to.
|
||||||
|
* @return reference iterator over all references to the specified address.
|
||||||
*/
|
*/
|
||||||
public ReferenceIterator getReferencesTo(Address addr);
|
public ReferenceIterator getReferencesTo(Address addr);
|
||||||
|
|
||||||
|
@ -242,6 +262,7 @@ public interface ReferenceManager {
|
||||||
* @param fromAddr the address of the codeunit making the reference.
|
* @param fromAddr the address of the codeunit making the reference.
|
||||||
* @param toAddr the address being referred to.
|
* @param toAddr the address being referred to.
|
||||||
* @param opIndex the operand index.
|
* @param opIndex the operand index.
|
||||||
|
* @return reference which satisfies the specified criteria or null
|
||||||
*/
|
*/
|
||||||
public Reference getReference(Address fromAddr, Address toAddr, int opIndex);
|
public Reference getReference(Address fromAddr, Address toAddr, int opIndex);
|
||||||
|
|
||||||
|
@ -267,6 +288,8 @@ public interface ReferenceManager {
|
||||||
* fromAddr.
|
* fromAddr.
|
||||||
* @param fromAddr the address of the codeunit being tested
|
* @param fromAddr the address of the codeunit being tested
|
||||||
* @param opIndex the index of the operand being tested.
|
* @param opIndex the index of the operand being tested.
|
||||||
|
* @return true if one or more reference from the specified address
|
||||||
|
* and opindex are defined, else false
|
||||||
*/
|
*/
|
||||||
public boolean hasReferencesFrom(Address fromAddr, int opIndex);
|
public boolean hasReferencesFrom(Address fromAddr, int opIndex);
|
||||||
|
|
||||||
|
@ -274,6 +297,8 @@ public interface ReferenceManager {
|
||||||
* Returns true if there are any memory references at the given
|
* Returns true if there are any memory references at the given
|
||||||
* address.
|
* address.
|
||||||
* @param fromAddr the address of the codeunit being tested
|
* @param fromAddr the address of the codeunit being tested
|
||||||
|
* @return true if one or more reference from the specified address
|
||||||
|
* are defined, else false
|
||||||
*/
|
*/
|
||||||
public boolean hasReferencesFrom(Address fromAddr);
|
public boolean hasReferencesFrom(Address fromAddr);
|
||||||
|
|
||||||
|
@ -281,6 +306,8 @@ public interface ReferenceManager {
|
||||||
* Get the primary reference from the given address.
|
* Get the primary reference from the given address.
|
||||||
* @param addr from address
|
* @param addr from address
|
||||||
* @param opIndex operand index
|
* @param opIndex operand index
|
||||||
|
* @return the primary reference from the specified address
|
||||||
|
* and opindex if it exists, else null
|
||||||
*/
|
*/
|
||||||
public Reference getPrimaryReferenceFrom(Address addr, int opIndex);
|
public Reference getPrimaryReferenceFrom(Address addr, int opIndex);
|
||||||
|
|
||||||
|
@ -289,6 +316,7 @@ public interface ReferenceManager {
|
||||||
* reference
|
* reference
|
||||||
* @param startAddr address to position iterator.
|
* @param startAddr address to position iterator.
|
||||||
* @param forward true means to iterate in the forward direction
|
* @param forward true means to iterate in the forward direction
|
||||||
|
* @return address iterator where references from exist
|
||||||
*/
|
*/
|
||||||
public AddressIterator getReferenceSourceIterator(Address startAddr, boolean forward);
|
public AddressIterator getReferenceSourceIterator(Address startAddr, boolean forward);
|
||||||
|
|
||||||
|
@ -297,6 +325,8 @@ public interface ReferenceManager {
|
||||||
* reference, restricted by the given address set.
|
* reference, restricted by the given address set.
|
||||||
* @param addrSet the set of address to restrict the iterator or null for all addresses.
|
* @param addrSet the set of address to restrict the iterator or null for all addresses.
|
||||||
* @param forward true means to iterate in the forward direction
|
* @param forward true means to iterate in the forward direction
|
||||||
|
* address iterator where references from exist
|
||||||
|
* @return address iterator where references from exist constrained by addrSet
|
||||||
*/
|
*/
|
||||||
public AddressIterator getReferenceSourceIterator(AddressSetView addrSet, boolean forward);
|
public AddressIterator getReferenceSourceIterator(AddressSetView addrSet, boolean forward);
|
||||||
|
|
||||||
|
@ -305,6 +335,8 @@ public interface ReferenceManager {
|
||||||
* reference.
|
* reference.
|
||||||
* @param startAddr start of iterator
|
* @param startAddr start of iterator
|
||||||
* @param forward true means to iterate in the forward direction
|
* @param forward true means to iterate in the forward direction
|
||||||
|
* address iterator where references to exist
|
||||||
|
* @return address iterator where references to exist
|
||||||
*/
|
*/
|
||||||
public AddressIterator getReferenceDestinationIterator(Address startAddr, boolean forward);
|
public AddressIterator getReferenceDestinationIterator(Address startAddr, boolean forward);
|
||||||
|
|
||||||
|
@ -313,20 +345,21 @@ public interface ReferenceManager {
|
||||||
* memory reference, restricted by the given address set.
|
* memory reference, restricted by the given address set.
|
||||||
* @param addrSet the set of address to restrict the iterator or null for all addresses.
|
* @param addrSet the set of address to restrict the iterator or null for all addresses.
|
||||||
* @param forward true means to iterate in the forward direction
|
* @param forward true means to iterate in the forward direction
|
||||||
|
* @return address iterator where references to exist constrained by addrSet
|
||||||
*/
|
*/
|
||||||
public AddressIterator getReferenceDestinationIterator(AddressSetView addrSet, boolean forward);
|
public AddressIterator getReferenceDestinationIterator(AddressSetView addrSet, boolean forward);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the number of memory References to the specified
|
* Returns the number of references to the specified <code>toAddr</code>.
|
||||||
* <code>toAddr</code>
|
|
||||||
* @param toAddr the address being referenced
|
* @param toAddr the address being referenced
|
||||||
|
* @return the number of references to the specified <code>toAddr</code>.
|
||||||
*/
|
*/
|
||||||
public int getReferenceCountTo(Address toAddr);
|
public int getReferenceCountTo(Address toAddr);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the number of memory References from the specified
|
* Returns the number of references from the specified <code>fromAddr</code>.
|
||||||
* <code>fromAddr</code>
|
|
||||||
* @param fromAddr the address of the codeunit making the reference.
|
* @param fromAddr the address of the codeunit making the reference.
|
||||||
|
* @return the number of references from the specified <code>fromAddr</code>.
|
||||||
*/
|
*/
|
||||||
public int getReferenceCountFrom(Address fromAddr);
|
public int getReferenceCountFrom(Address fromAddr);
|
||||||
|
|
||||||
|
@ -343,6 +376,7 @@ public interface ReferenceManager {
|
||||||
/**
|
/**
|
||||||
* Return true if a memory reference exists with the given "to" address.
|
* Return true if a memory reference exists with the given "to" address.
|
||||||
* @param toAddr address being referred to.
|
* @param toAddr address being referred to.
|
||||||
|
* @return true if specified toAddr has one or more references to it, else false.
|
||||||
*/
|
*/
|
||||||
public boolean hasReferencesTo(Address toAddr);
|
public boolean hasReferencesTo(Address toAddr);
|
||||||
|
|
||||||
|
@ -350,6 +384,7 @@ public interface ReferenceManager {
|
||||||
* Uodate the reference type on a memory reference.
|
* Uodate the reference type on a memory reference.
|
||||||
* @param ref reference to be updated
|
* @param ref reference to be updated
|
||||||
* @param refType new reference type
|
* @param refType new reference type
|
||||||
|
* @return updated reference
|
||||||
*/
|
*/
|
||||||
public Reference updateRefType(Reference ref, RefType refType);
|
public Reference updateRefType(Reference ref, RefType refType);
|
||||||
|
|
||||||
|
@ -379,6 +414,7 @@ public interface ReferenceManager {
|
||||||
/**
|
/**
|
||||||
* Returns the reference level for the references to the given address
|
* Returns the reference level for the references to the given address
|
||||||
* @param toAddr the address at which to find the highest reference level
|
* @param toAddr the address at which to find the highest reference level
|
||||||
|
* @return reference level for specified to address.
|
||||||
*/
|
*/
|
||||||
public byte getReferenceLevel(Address toAddr);
|
public byte getReferenceLevel(Address toAddr);
|
||||||
|
|
||||||
|
|
|
@ -48,8 +48,8 @@ public class ReferenceManagerTestDouble implements ReferenceManager {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Reference addOffsetMemReference(Address fromAddr, Address toAddr, long offset,
|
public Reference addOffsetMemReference(Address fromAddr, Address toAddr, boolean toAddrIsBase,
|
||||||
RefType type, SourceType source, int opIndex) {
|
long offset, RefType type, SourceType source, int opIndex) {
|
||||||
throw new UnsupportedOperationException();
|
throw new UnsupportedOperationException();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -71,12 +71,13 @@ public class AARCH64_ElfRelocationHandler extends ElfRelocationHandler {
|
||||||
switch (type) {
|
switch (type) {
|
||||||
// .xword: (S+A)
|
// .xword: (S+A)
|
||||||
case AARCH64_ElfRelocationConstants.R_AARCH64_ABS64: {
|
case AARCH64_ElfRelocationConstants.R_AARCH64_ABS64: {
|
||||||
if (addend != 0 && isUnsupportedExternalRelocation(program, relocationAddress,
|
|
||||||
symbolAddr, symbolName, addend, elfRelocationContext.getLog())) {
|
|
||||||
addend = 0; // prefer bad fixup for EXTERNAL over really-bad fixup
|
|
||||||
}
|
|
||||||
newValue = (symbolValue + addend);
|
newValue = (symbolValue + addend);
|
||||||
memory.setLong(relocationAddress, newValue);
|
memory.setLong(relocationAddress, newValue);
|
||||||
|
if (addend != 0) {
|
||||||
|
warnExternalOffsetRelocation(program, relocationAddress,
|
||||||
|
symbolAddr, symbolName, addend, elfRelocationContext.getLog());
|
||||||
|
applyComponentOffsetPointer(program, relocationAddress, addend);
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -91,15 +91,16 @@ public class ARM_ElfRelocationHandler extends ElfRelocationHandler {
|
||||||
if (elfRelocationContext.extractAddend()) {
|
if (elfRelocationContext.extractAddend()) {
|
||||||
addend = memory.getInt(relocationAddress);
|
addend = memory.getInt(relocationAddress);
|
||||||
}
|
}
|
||||||
if (addend != 0 && isUnsupportedExternalRelocation(program, relocationAddress,
|
|
||||||
symbolAddr, symbolName, addend, elfRelocationContext.getLog())) {
|
|
||||||
addend = 0; // prefer bad fixup for EXTERNAL over really-bad fixup
|
|
||||||
}
|
|
||||||
newValue = (int) (symbolValue + addend);
|
newValue = (int) (symbolValue + addend);
|
||||||
if (isThumb) {
|
if (isThumb) {
|
||||||
newValue |= 1;
|
newValue |= 1;
|
||||||
}
|
}
|
||||||
memory.setInt(relocationAddress, newValue);
|
memory.setInt(relocationAddress, newValue);
|
||||||
|
if (addend != 0) {
|
||||||
|
warnExternalOffsetRelocation(program, relocationAddress,
|
||||||
|
symbolAddr, symbolName, addend, elfRelocationContext.getLog());
|
||||||
|
applyComponentOffsetPointer(program, relocationAddress, addend);
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case ARM_ElfRelocationConstants.R_ARM_REL32: { // Target class: Data
|
case ARM_ElfRelocationConstants.R_ARM_REL32: { // Target class: Data
|
||||||
|
|
|
@ -61,6 +61,7 @@ public class MIPS_ElfRelocationHandler extends ElfRelocationHandler {
|
||||||
|
|
||||||
MIPS_ElfRelocationContext mipsRelocationContext =
|
MIPS_ElfRelocationContext mipsRelocationContext =
|
||||||
(MIPS_ElfRelocationContext) elfRelocationContext;
|
(MIPS_ElfRelocationContext) elfRelocationContext;
|
||||||
|
mipsRelocationContext.lastSymbolAddr = null;
|
||||||
|
|
||||||
int type = relocation.getType();
|
int type = relocation.getType();
|
||||||
int symbolIndex = relocation.getSymbolIndex();
|
int symbolIndex = relocation.getSymbolIndex();
|
||||||
|
@ -117,6 +118,8 @@ public class MIPS_ElfRelocationHandler extends ElfRelocationHandler {
|
||||||
Memory memory = program.getMemory();
|
Memory memory = program.getMemory();
|
||||||
MessageLog log = mipsRelocationContext.getLog();
|
MessageLog log = mipsRelocationContext.getLog();
|
||||||
|
|
||||||
|
ElfHeader elf = mipsRelocationContext.getElfHeader();
|
||||||
|
|
||||||
long offset = (int) relocationAddress.getOffset();
|
long offset = (int) relocationAddress.getOffset();
|
||||||
|
|
||||||
ElfSymbol elfSymbol = mipsRelocationContext.getSymbol(symbolIndex);
|
ElfSymbol elfSymbol = mipsRelocationContext.getSymbol(symbolIndex);
|
||||||
|
@ -125,6 +128,10 @@ public class MIPS_ElfRelocationHandler extends ElfRelocationHandler {
|
||||||
long symbolValue = mipsRelocationContext.getSymbolValue(elfSymbol);
|
long symbolValue = mipsRelocationContext.getSymbolValue(elfSymbol);
|
||||||
String symbolName = elfSymbol.getNameAsString();
|
String symbolName = elfSymbol.getNameAsString();
|
||||||
|
|
||||||
|
if (symbolIndex != 0) {
|
||||||
|
mipsRelocationContext.lastSymbolAddr = symbolAddr;
|
||||||
|
}
|
||||||
|
|
||||||
long addend = 0;
|
long addend = 0;
|
||||||
if (mipsRelocationContext.useSavedAddend) {
|
if (mipsRelocationContext.useSavedAddend) {
|
||||||
if (mipsRelocationContext.savedAddendHasError) {
|
if (mipsRelocationContext.savedAddendHasError) {
|
||||||
|
@ -396,30 +403,31 @@ public class MIPS_ElfRelocationHandler extends ElfRelocationHandler {
|
||||||
writeNewValue = true;
|
writeNewValue = true;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case MIPS_ElfRelocationConstants.R_MIPS_32:
|
|
||||||
value = (int) symbolValue;
|
|
||||||
value += mipsRelocationContext.extractAddend() ? oldValue : addend;
|
|
||||||
|
|
||||||
newValue = value;
|
|
||||||
writeNewValue = true;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case MIPS_ElfRelocationConstants.R_MIPS_REL32:
|
case MIPS_ElfRelocationConstants.R_MIPS_REL32:
|
||||||
// TODO: unsure if reloc valid for symbolIndex != 0
|
// TODO: unsure if reloc valid for symbolIndex != 0
|
||||||
if (symbolIndex == 0) {
|
if (symbolIndex == 0) {
|
||||||
symbolValue = mipsRelocationContext.getImageBaseWordAdjustmentOffset();
|
symbolValue = mipsRelocationContext.getImageBaseWordAdjustmentOffset();
|
||||||
}
|
}
|
||||||
|
case MIPS_ElfRelocationConstants.R_MIPS_32:
|
||||||
value = (int) symbolValue;
|
value = (int) symbolValue;
|
||||||
int a = (int) (mipsRelocationContext.extractAddend() ? oldValue : addend);
|
int intAddend = (int) (mipsRelocationContext.extractAddend() ? oldValue : addend);
|
||||||
// NOTE: this may not detect correctly for all combound relocations
|
value += intAddend;
|
||||||
if (a != 0 && isUnsupportedExternalRelocation(program, relocationAddress,
|
|
||||||
symbolAddr, symbolName, a, log)) {
|
|
||||||
a = 0; // prefer bad fixup for EXTERNAL over really-bad fixup
|
|
||||||
}
|
|
||||||
value += a;
|
|
||||||
|
|
||||||
newValue = value;
|
newValue = value;
|
||||||
writeNewValue = true;
|
writeNewValue = true;
|
||||||
|
|
||||||
|
if (symbolIndex != 0 && intAddend != 0 && !saveValue) {
|
||||||
|
// If not continuing with compound relocation perform fixup so
|
||||||
|
// we can create offset-pointer now.
|
||||||
|
// NOTE: this may not handle all combound relocation cases
|
||||||
|
memory.setInt(relocationAddress, newValue);
|
||||||
|
writeNewValue = false;
|
||||||
|
warnExternalOffsetRelocation(program, relocationAddress,
|
||||||
|
symbolAddr, symbolName, intAddend, mipsRelocationContext.getLog());
|
||||||
|
if (elf.is32Bit()) {
|
||||||
|
applyComponentOffsetPointer(program, relocationAddress, intAddend);
|
||||||
|
}
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case MIPS_ElfRelocationConstants.R_MIPS_26:
|
case MIPS_ElfRelocationConstants.R_MIPS_26:
|
||||||
|
@ -461,6 +469,24 @@ public class MIPS_ElfRelocationHandler extends ElfRelocationHandler {
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
memory.setLong(relocationAddress, newValueBig);
|
memory.setLong(relocationAddress, newValueBig);
|
||||||
|
Address addr =
|
||||||
|
symbolIndex == 0 ? mipsRelocationContext.lastSymbolAddr : symbolAddr;
|
||||||
|
if (addr != null && addend != 0) {
|
||||||
|
if (symbolIndex == 0) {
|
||||||
|
// compute addend used with compound relocation and lastSymbolAddr
|
||||||
|
addend -= addr.getOffset();
|
||||||
|
}
|
||||||
|
if (addend != 0) {
|
||||||
|
// If not continuing with compound relocation perform fixup so
|
||||||
|
// we can create offset-pointer now.
|
||||||
|
// NOTE: this may not handle all combound relocation cases
|
||||||
|
warnExternalOffsetRelocation(program, relocationAddress,
|
||||||
|
addr, symbolName, addend, mipsRelocationContext.getLog());
|
||||||
|
if (elf.is64Bit()) {
|
||||||
|
applyComponentOffsetPointer(program, relocationAddress, addend);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
@ -1020,6 +1046,8 @@ public class MIPS_ElfRelocationHandler extends ElfRelocationHandler {
|
||||||
private boolean savedAddendHasError = false;
|
private boolean savedAddendHasError = false;
|
||||||
private long savedAddend;
|
private long savedAddend;
|
||||||
|
|
||||||
|
private Address lastSymbolAddr;
|
||||||
|
|
||||||
MIPS_ElfRelocationContext(MIPS_ElfRelocationHandler handler, ElfLoadHelper loadHelper,
|
MIPS_ElfRelocationContext(MIPS_ElfRelocationHandler handler, ElfLoadHelper loadHelper,
|
||||||
ElfRelocationTable relocationTable, Map<ElfSymbol, Address> symbolMap) {
|
ElfRelocationTable relocationTable, Map<ElfSymbol, Address> symbolMap) {
|
||||||
super(handler, loadHelper, relocationTable, symbolMap);
|
super(handler, loadHelper, relocationTable, symbolMap);
|
||||||
|
|
|
@ -222,12 +222,13 @@ public class PowerPC64_ElfRelocationHandler extends ElfRelocationHandler {
|
||||||
case PowerPC64_ElfRelocationConstants.R_PPC64_UADDR64:
|
case PowerPC64_ElfRelocationConstants.R_PPC64_UADDR64:
|
||||||
case PowerPC64_ElfRelocationConstants.R_PPC64_ADDR64:
|
case PowerPC64_ElfRelocationConstants.R_PPC64_ADDR64:
|
||||||
case PowerPC64_ElfRelocationConstants.R_PPC64_GLOB_DAT:
|
case PowerPC64_ElfRelocationConstants.R_PPC64_GLOB_DAT:
|
||||||
if (addend != 0 && isUnsupportedExternalRelocation(program, relocationAddress,
|
|
||||||
symbolAddr, symbolName, addend, elfRelocationContext.getLog())) {
|
|
||||||
addend = 0; // prefer bad fixup for EXTERNAL over really-bad fixup
|
|
||||||
}
|
|
||||||
value64 = symbolValue + addend;
|
value64 = symbolValue + addend;
|
||||||
memory.setLong(relocationAddress, value64);
|
memory.setLong(relocationAddress, value64);
|
||||||
|
if (addend != 0) {
|
||||||
|
warnExternalOffsetRelocation(program, relocationAddress,
|
||||||
|
symbolAddr, symbolName, addend, elfRelocationContext.getLog());
|
||||||
|
applyComponentOffsetPointer(program, relocationAddress, addend);
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
case PowerPC64_ElfRelocationConstants.R_PPC64_TOC:
|
case PowerPC64_ElfRelocationConstants.R_PPC64_TOC:
|
||||||
memory.setLong(relocationAddress, toc);
|
memory.setLong(relocationAddress, toc);
|
||||||
|
|
|
@ -91,12 +91,13 @@ public class PowerPC_ElfRelocationHandler extends ElfRelocationHandler {
|
||||||
case PowerPC_ElfRelocationConstants.R_PPC_ADDR32:
|
case PowerPC_ElfRelocationConstants.R_PPC_ADDR32:
|
||||||
case PowerPC_ElfRelocationConstants.R_PPC_UADDR32:
|
case PowerPC_ElfRelocationConstants.R_PPC_UADDR32:
|
||||||
case PowerPC_ElfRelocationConstants.R_PPC_GLOB_DAT:
|
case PowerPC_ElfRelocationConstants.R_PPC_GLOB_DAT:
|
||||||
if (addend != 0 && isUnsupportedExternalRelocation(program, relocationAddress,
|
|
||||||
symbolAddr, symbolName, addend, elfRelocationContext.getLog())) {
|
|
||||||
addend = 0; // prefer bad fixup for EXTERNAL over really-bad fixup
|
|
||||||
}
|
|
||||||
newValue = symbolValue + addend;
|
newValue = symbolValue + addend;
|
||||||
memory.setInt(relocationAddress, newValue);
|
memory.setInt(relocationAddress, newValue);
|
||||||
|
if (addend != 0) {
|
||||||
|
warnExternalOffsetRelocation(program, relocationAddress,
|
||||||
|
symbolAddr, symbolName, addend, elfRelocationContext.getLog());
|
||||||
|
applyComponentOffsetPointer(program, relocationAddress, addend);
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
case PowerPC_ElfRelocationConstants.R_PPC_ADDR24:
|
case PowerPC_ElfRelocationConstants.R_PPC_ADDR24:
|
||||||
newValue = (symbolValue + addend) >> 2;
|
newValue = (symbolValue + addend) >> 2;
|
||||||
|
|
|
@ -92,16 +92,26 @@ public class RISCV_ElfRelocationHandler extends ElfRelocationHandler {
|
||||||
// Runtime relocation word32 = S + A
|
// Runtime relocation word32 = S + A
|
||||||
value32 = (int)(symbolValue + addend);
|
value32 = (int)(symbolValue + addend);
|
||||||
memory.setInt(relocationAddress, value32);
|
memory.setInt(relocationAddress, value32);
|
||||||
|
if (addend != 0) {
|
||||||
|
warnExternalOffsetRelocation(program, relocationAddress,
|
||||||
|
symbolAddr, symbolName, addend, elfRelocationContext.getLog());
|
||||||
|
if (elf.is32Bit()) {
|
||||||
|
applyComponentOffsetPointer(program, relocationAddress, addend);
|
||||||
|
}
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case RISCV_ElfRelocationConstants.R_RISCV_64:
|
case RISCV_ElfRelocationConstants.R_RISCV_64:
|
||||||
// Runtime relocation word64 = S + A
|
// Runtime relocation word64 = S + A
|
||||||
if (addend != 0 && isUnsupportedExternalRelocation(program, relocationAddress,
|
|
||||||
symbolAddr, symbolName, addend, elfRelocationContext.getLog())) {
|
|
||||||
addend = 0; // prefer bad fixup for EXTERNAL over really-bad fixup
|
|
||||||
}
|
|
||||||
value64 = symbolValue + addend;
|
value64 = symbolValue + addend;
|
||||||
memory.setLong(relocationAddress, value64);
|
memory.setLong(relocationAddress, value64);
|
||||||
|
if (addend != 0) {
|
||||||
|
warnExternalOffsetRelocation(program, relocationAddress,
|
||||||
|
symbolAddr, symbolName, addend, elfRelocationContext.getLog());
|
||||||
|
if (elf.is64Bit()) {
|
||||||
|
applyComponentOffsetPointer(program, relocationAddress, addend);
|
||||||
|
}
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case RISCV_ElfRelocationConstants.R_RISCV_RELATIVE:
|
case RISCV_ElfRelocationConstants.R_RISCV_RELATIVE:
|
||||||
|
|
|
@ -63,18 +63,22 @@ public class SH_ElfRelocationHandler extends ElfRelocationHandler {
|
||||||
|
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case SH_ElfRelocationConstants.R_SH_DIR32:
|
case SH_ElfRelocationConstants.R_SH_DIR32:
|
||||||
case SH_ElfRelocationConstants.R_SH_GLOB_DAT:
|
// 32-bit absolute relocation w/ addend
|
||||||
case SH_ElfRelocationConstants.R_SH_JMP_SLOT:
|
|
||||||
// 32-bit absolute relocations
|
|
||||||
if (elfRelocationContext.extractAddend()) {
|
if (elfRelocationContext.extractAddend()) {
|
||||||
addend = memory.getInt(relocationAddress);
|
addend = memory.getInt(relocationAddress);
|
||||||
}
|
}
|
||||||
if (addend != 0 && isUnsupportedExternalRelocation(program, relocationAddress,
|
|
||||||
symbolAddr, symbolName, addend, elfRelocationContext.getLog())) {
|
|
||||||
addend = 0; // prefer bad fixup for EXTERNAL over really-bad fixup
|
|
||||||
}
|
|
||||||
newValue = symbolValue + addend;
|
newValue = symbolValue + addend;
|
||||||
memory.setInt(relocationAddress, newValue);
|
memory.setInt(relocationAddress, newValue);
|
||||||
|
if (addend != 0) {
|
||||||
|
warnExternalOffsetRelocation(program, relocationAddress,
|
||||||
|
symbolAddr, symbolName, addend, elfRelocationContext.getLog());
|
||||||
|
applyComponentOffsetPointer(program, relocationAddress, addend);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case SH_ElfRelocationConstants.R_SH_GLOB_DAT:
|
||||||
|
case SH_ElfRelocationConstants.R_SH_JMP_SLOT:
|
||||||
|
// 32-bit absolute relocations, no addend
|
||||||
|
memory.setInt(relocationAddress, symbolValue);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case SH_ElfRelocationConstants.R_SH_REL32: // 32-bit PC relative relocation
|
case SH_ElfRelocationConstants.R_SH_REL32: // 32-bit PC relative relocation
|
||||||
|
|
|
@ -82,12 +82,13 @@ public class X86_32_ElfRelocationHandler extends ElfRelocationHandler {
|
||||||
|
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case X86_32_ElfRelocationConstants.R_386_32:
|
case X86_32_ElfRelocationConstants.R_386_32:
|
||||||
if (addend != 0 && isUnsupportedExternalRelocation(program, relocationAddress,
|
|
||||||
symbolAddr, symbolName, addend, elfRelocationContext.getLog())) {
|
|
||||||
addend = 0; // prefer bad fixup for EXTERNAL over really-bad fixup
|
|
||||||
}
|
|
||||||
value = (int) (symbolValue + addend);
|
value = (int) (symbolValue + addend);
|
||||||
memory.setInt(relocationAddress, value);
|
memory.setInt(relocationAddress, value);
|
||||||
|
if (addend != 0) {
|
||||||
|
warnExternalOffsetRelocation(program, relocationAddress,
|
||||||
|
symbolAddr, symbolName, addend, elfRelocationContext.getLog());
|
||||||
|
applyComponentOffsetPointer(program, relocationAddress, addend);
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
case X86_32_ElfRelocationConstants.R_386_PC32:
|
case X86_32_ElfRelocationConstants.R_386_PC32:
|
||||||
value = (int) (symbolValue + addend - offset);
|
value = (int) (symbolValue + addend - offset);
|
||||||
|
|
|
@ -87,12 +87,13 @@ public class X86_64_ElfRelocationHandler extends ElfRelocationHandler {
|
||||||
"Runtime copy not supported", elfRelocationContext.getLog());
|
"Runtime copy not supported", elfRelocationContext.getLog());
|
||||||
break;
|
break;
|
||||||
case X86_64_ElfRelocationConstants.R_X86_64_64:
|
case X86_64_ElfRelocationConstants.R_X86_64_64:
|
||||||
if (addend != 0 && isUnsupportedExternalRelocation(program, relocationAddress,
|
|
||||||
symbolAddr, symbolName, addend, elfRelocationContext.getLog())) {
|
|
||||||
addend = 0; // prefer bad fixup for EXTERNAL over really-bad fixup
|
|
||||||
}
|
|
||||||
value = symbolValue + addend;
|
value = symbolValue + addend;
|
||||||
memory.setLong(relocationAddress, value);
|
memory.setLong(relocationAddress, value);
|
||||||
|
if (addend != 0) {
|
||||||
|
warnExternalOffsetRelocation(program, relocationAddress,
|
||||||
|
symbolAddr, symbolName, addend, elfRelocationContext.getLog());
|
||||||
|
applyComponentOffsetPointer(program, relocationAddress, addend);
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
case X86_64_ElfRelocationConstants.R_X86_64_16:
|
case X86_64_ElfRelocationConstants.R_X86_64_16:
|
||||||
value = symbolValue + addend;
|
value = symbolValue + addend;
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue