GP-1036 EXTERNAL Block Offset-Reference refactor

This commit is contained in:
ghidra1 2022-03-08 05:08:02 -05:00
parent 332480a422
commit 2bced1cd43
43 changed files with 461 additions and 216 deletions

View file

@ -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;

View file

@ -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

View file

@ -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);
} }
} }

View file

@ -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

View file

@ -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;

View file

@ -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);

View file

@ -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);
} }

View file

@ -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);
} }

View file

@ -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;
} }

View file

@ -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()
*/ */

View file

@ -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;

View file

@ -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;
} }
} }

View file

@ -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 {

View file

@ -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);
} }
/** /**

View file

@ -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));

View file

@ -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);

View file

@ -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 {

View file

@ -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;
}); });
} }

View file

@ -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()) {

View file

@ -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);

View file

@ -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);

View file

@ -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);

View file

@ -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);
} }

View file

@ -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;
} }
} }

View file

@ -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");
} }

View file

@ -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();

View file

@ -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()
*/ */

View file

@ -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();
} }
} }

View file

@ -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;

View file

@ -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

View file

@ -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());
}
} }

View file

@ -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();
} }

View file

@ -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);

View file

@ -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();
} }

View file

@ -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;
} }

View file

@ -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

View file

@ -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);

View file

@ -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);

View file

@ -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;

View file

@ -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:

View file

@ -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

View file

@ -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);

View file

@ -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;