mirror of
https://github.com/NationalSecurityAgency/ghidra.git
synced 2025-10-04 18:29:37 +02:00
GP-4742 Added addr='next' to pspec labels. Constrained address spaces for heuristic references
This commit is contained in:
parent
f854828f73
commit
bceb82f733
8 changed files with 319 additions and 81 deletions
|
@ -32,8 +32,7 @@ import ghidra.program.database.ProgramDB;
|
||||||
import ghidra.program.database.function.OverlappingFunctionException;
|
import ghidra.program.database.function.OverlappingFunctionException;
|
||||||
import ghidra.program.model.address.*;
|
import ghidra.program.model.address.*;
|
||||||
import ghidra.program.model.lang.*;
|
import ghidra.program.model.lang.*;
|
||||||
import ghidra.program.model.listing.FunctionManager;
|
import ghidra.program.model.listing.*;
|
||||||
import ghidra.program.model.listing.Program;
|
|
||||||
import ghidra.program.model.mem.InvalidAddressException;
|
import ghidra.program.model.mem.InvalidAddressException;
|
||||||
import ghidra.program.model.mem.MemoryConflictException;
|
import ghidra.program.model.mem.MemoryConflictException;
|
||||||
import ghidra.program.model.symbol.*;
|
import ghidra.program.model.symbol.*;
|
||||||
|
@ -487,7 +486,7 @@ public abstract class AbstractProgramLoader implements Loader {
|
||||||
for (Register reg : lang.getRegisters()) {
|
for (Register reg : lang.getRegisters()) {
|
||||||
Address addr = reg.getAddress();
|
Address addr = reg.getAddress();
|
||||||
if (addr.isMemoryAddress()) {
|
if (addr.isMemoryAddress()) {
|
||||||
createSymbol(program, reg.getName(), addr, false, true, true);
|
createSymbol(program, reg.getName(), addr, null, false, true, true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// optionally create default symbols defined by pspec
|
// optionally create default symbols defined by pspec
|
||||||
|
@ -495,7 +494,7 @@ public abstract class AbstractProgramLoader implements Loader {
|
||||||
boolean anchorSymbols = shouldAnchorSymbols(options);
|
boolean anchorSymbols = shouldAnchorSymbols(options);
|
||||||
List<AddressLabelInfo> labels = lang.getDefaultSymbols();
|
List<AddressLabelInfo> labels = lang.getDefaultSymbols();
|
||||||
for (AddressLabelInfo info : labels) {
|
for (AddressLabelInfo info : labels) {
|
||||||
createSymbol(program, info.getLabel(), info.getAddress(), info.isEntry(),
|
createSymbol(program, info.getLabel(), info.getAddress(), info.getDescription(), info.isEntry(),
|
||||||
info.isPrimary(), anchorSymbols);
|
info.isPrimary(), anchorSymbols);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -507,13 +506,16 @@ public abstract class AbstractProgramLoader implements Loader {
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void createSymbol(Program program, String labelname, Address address,
|
private static void createSymbol(Program program, String labelname, Address address,
|
||||||
boolean isEntry, boolean isPrimary, boolean anchorSymbols) {
|
String comment, boolean isEntry, boolean isPrimary, boolean anchorSymbols) {
|
||||||
SymbolTable symTable = program.getSymbolTable();
|
SymbolTable symTable = program.getSymbolTable();
|
||||||
Address addr = address;
|
Address addr = address;
|
||||||
Symbol s = symTable.getPrimarySymbol(addr);
|
Symbol s = symTable.getPrimarySymbol(addr);
|
||||||
try {
|
try {
|
||||||
Namespace namespace = program.getGlobalNamespace();
|
Namespace namespace = program.getGlobalNamespace();
|
||||||
s = symTable.createLabel(addr, labelname, namespace, SourceType.IMPORTED);
|
s = symTable.createLabel(addr, labelname, namespace, SourceType.IMPORTED);
|
||||||
|
if (comment != null) {
|
||||||
|
program.getListing().setComment(address, CodeUnit.EOL_COMMENT, comment);
|
||||||
|
}
|
||||||
if (isEntry) {
|
if (isEntry) {
|
||||||
symTable.addExternalEntryPoint(addr);
|
symTable.addExternalEntryPoint(addr);
|
||||||
}
|
}
|
||||||
|
|
|
@ -145,25 +145,7 @@ public class SymbolicPropogator {
|
||||||
|
|
||||||
this.evaluator = eval;
|
this.evaluator = eval;
|
||||||
|
|
||||||
AddressSpace defaultDataSpace = program.getLanguage().getDefaultDataSpace();
|
initValidAddressSpaces();
|
||||||
AddressSpace defaultSpace = program.getLanguage().getDefaultSpace();
|
|
||||||
defaultSpacesAreTheSame = defaultSpace.equals(defaultDataSpace);
|
|
||||||
|
|
||||||
AddressSpace defaultAddrSpace = program.getAddressFactory().getDefaultAddressSpace();
|
|
||||||
|
|
||||||
// Only make reference if other reference or symbol exists
|
|
||||||
memorySpaces = new ArrayList<>();
|
|
||||||
for (AddressSpace space : program.getAddressFactory().getAddressSpaces()) {
|
|
||||||
if (!space.isLoadedMemorySpace()) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if (space == defaultAddrSpace) {
|
|
||||||
memorySpaces.add(0, space); // default space is always at index 0
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
memorySpaces.add(space);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// if assuming, make a copy of programContext
|
// if assuming, make a copy of programContext
|
||||||
savedProgramContext = programContext;
|
savedProgramContext = programContext;
|
||||||
|
@ -206,6 +188,44 @@ public class SymbolicPropogator {
|
||||||
return bodyDone;
|
return bodyDone;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Initialize address spaces to be used for a potential reference with an unknown space.
|
||||||
|
*/
|
||||||
|
private void initValidAddressSpaces() {
|
||||||
|
AddressSpace defaultDataSpace = program.getLanguage().getDefaultDataSpace();
|
||||||
|
AddressSpace defaultSpace = program.getLanguage().getDefaultSpace();
|
||||||
|
defaultSpacesAreTheSame = defaultSpace.equals(defaultDataSpace);
|
||||||
|
|
||||||
|
AddressSpace defaultAddrSpace = program.getAddressFactory().getDefaultAddressSpace();
|
||||||
|
|
||||||
|
// Only make reference if other reference or symbol exists
|
||||||
|
memorySpaces = new ArrayList<>();
|
||||||
|
for (AddressSpace space : program.getAddressFactory().getAddressSpaces()) {
|
||||||
|
if (!space.isLoadedMemorySpace()) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// only default or defaultData based overlay spaces added
|
||||||
|
if (space.isOverlaySpace()) {
|
||||||
|
OverlayAddressSpace ovSpace = (OverlayAddressSpace) space;
|
||||||
|
AddressSpace baseSpace = ovSpace.getPhysicalSpace();
|
||||||
|
if (!( baseSpace.equals(defaultDataSpace) || baseSpace.equals(defaultSpace) ) ) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (!( space.equals(defaultDataSpace) || space.equals(defaultSpace) ) ) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (space.equals(defaultAddrSpace)) {
|
||||||
|
memorySpaces.add(0, space); // default space is always at index 0
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
memorySpaces.add(space);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Save off the current context and set the current context to a copy
|
* Save off the current context and set the current context to a copy
|
||||||
* This is done so that the values in the context are not changed, but can be used for computation.
|
* This is done so that the values in the context are not changed, but can be used for computation.
|
||||||
|
@ -2307,7 +2327,8 @@ public class SymbolicPropogator {
|
||||||
AddressSpace instrSpace = instruction.getMinAddress().getAddressSpace();
|
AddressSpace instrSpace = instruction.getMinAddress().getAddressSpace();
|
||||||
|
|
||||||
// Find likely preferred target space
|
// Find likely preferred target space
|
||||||
// 1. only non-overlay space is default space, or
|
// 1. only non-overlay spaces are defaultSpace of defaultDataSpace,
|
||||||
|
// or overlay spaces with base space of defaultSpace or defaultDataSpace
|
||||||
// 2. presence of destination symbol/reference at only one of many possible targets
|
// 2. presence of destination symbol/reference at only one of many possible targets
|
||||||
|
|
||||||
// if this instruction is in an overlay space overlaying the default space, change the default space
|
// if this instruction is in an overlay space overlaying the default space, change the default space
|
||||||
|
|
|
@ -24,16 +24,19 @@ import org.junit.Test;
|
||||||
import generic.test.AbstractGenericTest;
|
import generic.test.AbstractGenericTest;
|
||||||
import ghidra.app.plugin.core.analysis.ConstantPropagationAnalyzer;
|
import ghidra.app.plugin.core.analysis.ConstantPropagationAnalyzer;
|
||||||
import ghidra.app.plugin.core.analysis.ConstantPropagationContextEvaluator;
|
import ghidra.app.plugin.core.analysis.ConstantPropagationContextEvaluator;
|
||||||
|
import ghidra.framework.store.LockException;
|
||||||
import ghidra.program.database.ProgramBuilder;
|
import ghidra.program.database.ProgramBuilder;
|
||||||
import ghidra.program.model.address.Address;
|
import ghidra.program.model.address.*;
|
||||||
import ghidra.program.model.address.AddressSet;
|
|
||||||
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.mem.MemoryConflictException;
|
||||||
import ghidra.program.model.pcode.Varnode;
|
import ghidra.program.model.pcode.Varnode;
|
||||||
import ghidra.program.model.symbol.Reference;
|
import ghidra.program.model.symbol.Reference;
|
||||||
import ghidra.program.model.symbol.ReferenceIterator;
|
import ghidra.program.model.symbol.ReferenceIterator;
|
||||||
import ghidra.program.util.SymbolicPropogator.Value;
|
import ghidra.program.util.SymbolicPropogator.Value;
|
||||||
|
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;
|
||||||
|
|
||||||
|
@ -307,6 +310,167 @@ public class ConstantPropogationReferenceTest extends AbstractGenericTest {
|
||||||
assertOperandReferenceTo(1, instr, addr("0x00040100"));
|
assertOperandReferenceTo(1, instr, addr("0x00040100"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testOverlayReferences_AARCH64() throws Exception {
|
||||||
|
|
||||||
|
builder = new ProgramBuilder("thunk", ProgramBuilder._AARCH64);
|
||||||
|
|
||||||
|
// Copy and use PasteCopiedListingsBytesScript
|
||||||
|
// 00400000 fd 7b bf a9 stp x29,x30,[sp, #local_10]!
|
||||||
|
// 00400004 fd 03 00 91 mov x29,sp
|
||||||
|
// 00400008 60 00 00 d0 adrp x0,0x40e000
|
||||||
|
// 0040000c 01 00 24 91 add x1,x0,#0x900
|
||||||
|
// 00400010 60 00 00 d0 adrp x0,0x40e000
|
||||||
|
// 00400014 00 40 24 91 add x0=>data:DWORD_0040e910,x0,#0x910
|
||||||
|
// 00400018 e2 03 01 aa mov x2=>data:DWORD_0040e900,x1
|
||||||
|
// 0040001c e1 15 80 52 mov w1,#0xaf
|
||||||
|
// 00400020 05 00 00 94 bl FUN_00400034
|
||||||
|
// 00400024 21 00 80 d2 mov x1,#0x1
|
||||||
|
// 00400028 40 00 80 d2 mov x0,#0x2
|
||||||
|
// 0040002c 02 00 00 94 bl FUN_00400034
|
||||||
|
// 00400030 c0 03 5f d6 ret
|
||||||
|
//
|
||||||
|
// 00400034 c0 03 5f d6 ret
|
||||||
|
// 00400038 00 00 00 00 ddw 0h
|
||||||
|
// 0040003c 00 00 00 00 ddw 0h
|
||||||
|
//
|
||||||
|
// 0040e900 53 74 72 69 ddw 53747269h
|
||||||
|
// 0040e904 6e 67 50 61 ddw 6E675061h
|
||||||
|
// 0040e908 72 61 6d 31 ddw 72616D31h
|
||||||
|
// 0040e90c 00 00 00 00 ddw 0h
|
||||||
|
//
|
||||||
|
// 0040e910 53 74 72 69 ddw 53747269h
|
||||||
|
// 0040e914 6e 67 50 61 ddw 6E675061h
|
||||||
|
// 0040e918 72 61 6d 32 ddw 72616D32h
|
||||||
|
// 0040e91c 00 00 00 00 ddw 0h
|
||||||
|
|
||||||
|
String ovBlockName = "textov";
|
||||||
|
|
||||||
|
MemoryBlock textBlock = builder.createOverlayMemory(ovBlockName,"0x400000",0x10000);
|
||||||
|
|
||||||
|
builder.setBytes(textBlock.getStart().toString(),
|
||||||
|
"fd 7b bf a9 fd 03 00 91 60 00 00 d0 01 00 24 91 60 00 00 d0 00 40 24 91 e2 03 01 aa e1 15 80 52 05 00 00 94 21 00 80 d2 40 00 80 d2 02 00 00 94 c0 03 5f d6 c0 03 5f d6");
|
||||||
|
|
||||||
|
builder.setBytes(ovBlockName+":"+"0x0040e900",
|
||||||
|
"53 74 72 69 6e 67 50 61 72 61 6d 31 00 00 00 00 53 74 72 69 6e 67 50 61 72 61 6d 32 00 00 00 00");
|
||||||
|
|
||||||
|
builder.disassemble(textBlock.getStart().toString(), 16*4);
|
||||||
|
|
||||||
|
analyzer = new ConstantPropagationAnalyzer();
|
||||||
|
|
||||||
|
program = builder.getProgram();
|
||||||
|
program.startTransaction("Test");
|
||||||
|
Address codeStart = addr(ovBlockName+":"+"0x00400000");
|
||||||
|
Listing listing = program.getListing();
|
||||||
|
assertNotNull("Bad instruction disassembly", listing.getInstructionAt(codeStart));
|
||||||
|
|
||||||
|
AddressSet addressSet = new AddressSet(codeStart, codeStart.add(16*4));
|
||||||
|
analyze(addressSet);
|
||||||
|
|
||||||
|
Instruction instr;
|
||||||
|
instr = listing.getInstructionAt(addr(ovBlockName+":"+"0x00400000").add(20));
|
||||||
|
assertNoOperandReference(1, instr);
|
||||||
|
assertOperandReferenceTo(0, instr, addr(ovBlockName+":"+"0x0040e910"));
|
||||||
|
|
||||||
|
instr = listing.getInstructionAt(addr(ovBlockName+":"+"0x00400000").add(24));
|
||||||
|
assertNoOperandReference(1, instr);
|
||||||
|
assertOperandReferenceTo(0, instr, addr(ovBlockName+":"+"0x0040e900"));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testOverlayReferencesToBase_AARCH64() throws Exception {
|
||||||
|
|
||||||
|
builder = new ProgramBuilder("thunk", ProgramBuilder._AARCH64);
|
||||||
|
|
||||||
|
String ovBlockName = "textov";
|
||||||
|
|
||||||
|
// Same as above test
|
||||||
|
|
||||||
|
MemoryBlock textBlock = builder.createOverlayMemory(ovBlockName,"0x400000",0x1000);
|
||||||
|
|
||||||
|
builder.setBytes(textBlock.getStart().toString(),
|
||||||
|
"fd 7b bf a9 fd 03 00 91 60 00 00 d0 01 00 24 91 60 00 00 d0 00 40 24 91 e2 03 01 aa e1 15 80 52 05 00 00 94 21 00 80 d2 40 00 80 d2 02 00 00 94 c0 03 5f d6 c0 03 5f d6");
|
||||||
|
|
||||||
|
builder.setBytes("0x0040e900",
|
||||||
|
"53 74 72 69 6e 67 50 61 72 61 6d 31 00 00 00 00 53 74 72 69 6e 67 50 61 72 61 6d 32 00 00 00 00");
|
||||||
|
|
||||||
|
builder.disassemble(textBlock.getStart().toString(), 16*4);
|
||||||
|
|
||||||
|
analyzer = new ConstantPropagationAnalyzer();
|
||||||
|
|
||||||
|
program = builder.getProgram();
|
||||||
|
program.startTransaction("Test");
|
||||||
|
Address codeStart = addr(ovBlockName+":"+"0x00400000");
|
||||||
|
Listing listing = program.getListing();
|
||||||
|
assertNotNull("Bad instruction disassembly", listing.getInstructionAt(codeStart));
|
||||||
|
|
||||||
|
AddressSet addressSet = new AddressSet(codeStart, codeStart.add(16*4));
|
||||||
|
analyze(addressSet);
|
||||||
|
|
||||||
|
Instruction instr;
|
||||||
|
instr = listing.getInstructionAt(addr(ovBlockName+":"+"0x00400000").add(20));
|
||||||
|
assertNoOperandReference(1, instr);
|
||||||
|
assertOperandReferenceTo(0, instr, addr("0x0040e910"));
|
||||||
|
|
||||||
|
instr = listing.getInstructionAt(addr(ovBlockName+":"+"0x00400000").add(24));
|
||||||
|
assertNoOperandReference(1, instr);
|
||||||
|
assertOperandReferenceTo(0, instr, addr("0x0040e900"));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testOverlayReferencesToSplit_AARCH64() throws Exception {
|
||||||
|
|
||||||
|
builder = new ProgramBuilder("thunk", ProgramBuilder._AARCH64);
|
||||||
|
|
||||||
|
String ovBlockName = "textov";
|
||||||
|
|
||||||
|
// Same as above test
|
||||||
|
|
||||||
|
MemoryBlock textBlock = builder.createOverlayMemory(ovBlockName,"0x400000",0x1000);
|
||||||
|
|
||||||
|
builder.setBytes(textBlock.getStart().toString(),
|
||||||
|
"fd 7b bf a9 fd 03 00 91 60 00 00 d0 01 00 24 91 60 00 00 d0 00 40 24 91 e2 03 01 aa e1 15 80 52 05 00 00 94 21 00 80 d2 40 00 80 d2 02 00 00 94 c0 03 5f d6 c0 03 5f d6");
|
||||||
|
|
||||||
|
|
||||||
|
builder.withTransaction(() -> {
|
||||||
|
try {
|
||||||
|
MemoryBlock dataBlock = builder.getProgram().getMemory().createInitializedBlock(ovBlockName, textBlock.getStart().getAddressSpace().getAddressInThisSpaceOnly(0x0040e900), 0x100L, (byte) 0, TaskMonitor.DUMMY,
|
||||||
|
false);
|
||||||
|
|
||||||
|
builder.setBytes(dataBlock.getStart().toString(),
|
||||||
|
"53 74 72 69 6e 67 50 61 72 61 6d 31 00 00 00 00 53 74 72 69 6e 67 50 61 72 61 6d 32 00 00 00 00");
|
||||||
|
}
|
||||||
|
catch (Exception e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
builder.disassemble(textBlock.getStart().toString(), 16*4);
|
||||||
|
|
||||||
|
analyzer = new ConstantPropagationAnalyzer();
|
||||||
|
|
||||||
|
program = builder.getProgram();
|
||||||
|
program.startTransaction("Test");
|
||||||
|
Address codeStart = addr(ovBlockName+":"+"0x00400000");
|
||||||
|
Listing listing = program.getListing();
|
||||||
|
assertNotNull("Bad instruction disassembly", listing.getInstructionAt(codeStart));
|
||||||
|
|
||||||
|
AddressSet addressSet = new AddressSet(codeStart, codeStart.add(16*4));
|
||||||
|
analyze(addressSet);
|
||||||
|
|
||||||
|
Instruction instr;
|
||||||
|
instr = listing.getInstructionAt(addr(ovBlockName+":"+"0x00400000").add(20));
|
||||||
|
assertNoOperandReference(1, instr);
|
||||||
|
assertOperandReferenceTo(0, instr, addr(ovBlockName+":"+"0x0040e910"));
|
||||||
|
|
||||||
|
instr = listing.getInstructionAt(addr(ovBlockName+":"+"0x00400000").add(24));
|
||||||
|
assertNoOperandReference(1, instr);
|
||||||
|
assertOperandReferenceTo(0, instr, addr(ovBlockName+":"+"0x0040e900"));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testPIC_Call_X86_64() throws Exception {
|
public void testPIC_Call_X86_64() throws Exception {
|
||||||
|
|
||||||
|
|
|
@ -384,27 +384,29 @@ void ArchitectureGhidra::buildSymbols(DocumentStorage &store)
|
||||||
|
|
||||||
{
|
{
|
||||||
const Element *symtag = store.getTag(ELEM_DEFAULT_SYMBOLS.getName());
|
const Element *symtag = store.getTag(ELEM_DEFAULT_SYMBOLS.getName());
|
||||||
if (symtag == (const Element *)0) return;
|
if (symtag == (const Element*) 0)
|
||||||
XmlDecode decoder(this,symtag);
|
return;
|
||||||
|
XmlDecode decoder(this, symtag);
|
||||||
uint4 el = decoder.openElement(ELEM_DEFAULT_SYMBOLS);
|
uint4 el = decoder.openElement(ELEM_DEFAULT_SYMBOLS);
|
||||||
while(decoder.peekElement() != 0) {
|
Address lastAddr(Address::m_minimal);
|
||||||
|
int4 lastSize = -1;
|
||||||
|
while (decoder.peekElement() != 0) {
|
||||||
uint4 subel = decoder.openElement(ELEM_SYMBOL);
|
uint4 subel = decoder.openElement(ELEM_SYMBOL);
|
||||||
string addrString;
|
string addrString;
|
||||||
string name;
|
string name;
|
||||||
int4 size = 0;
|
int4 size = 0;
|
||||||
int4 volatileState = -1;
|
int4 volatileState = -1;
|
||||||
for(;;) {
|
for (;;) {
|
||||||
uint4 attribId = decoder.getNextAttributeId();
|
uint4 attribId = decoder.getNextAttributeId();
|
||||||
if (attribId == 0) break;
|
if (attribId == 0)
|
||||||
|
break;
|
||||||
if (attribId == ATTRIB_NAME)
|
if (attribId == ATTRIB_NAME)
|
||||||
name = decoder.readString();
|
name = decoder.readString();
|
||||||
else if (attribId == ATTRIB_ADDRESS) {
|
else if (attribId == ATTRIB_ADDRESS) {
|
||||||
addrString = decoder.readString();
|
addrString = decoder.readString();
|
||||||
}
|
} else if (attribId == ATTRIB_VOLATILE) {
|
||||||
else if (attribId == ATTRIB_VOLATILE) {
|
|
||||||
volatileState = decoder.readBool() ? 1 : 0;
|
volatileState = decoder.readBool() ? 1 : 0;
|
||||||
}
|
} else if (attribId == ATTRIB_SIZE)
|
||||||
else if (attribId == ATTRIB_SIZE)
|
|
||||||
size = decoder.readSignedInteger();
|
size = decoder.readSignedInteger();
|
||||||
}
|
}
|
||||||
decoder.closeElement(subel);
|
decoder.closeElement(subel);
|
||||||
|
@ -417,14 +419,21 @@ void ArchitectureGhidra::buildSymbols(DocumentStorage &store)
|
||||||
// feed the global symbol to the decompiler on a per function basic.
|
// feed the global symbol to the decompiler on a per function basic.
|
||||||
if (volatileState < 0)
|
if (volatileState < 0)
|
||||||
continue;
|
continue;
|
||||||
Address addr = parseAddressSimple(addrString);
|
Address addr;
|
||||||
|
if (addrString == "next" && lastSize != -1) {
|
||||||
|
addr = lastAddr + lastSize;
|
||||||
|
} else {
|
||||||
|
addr = parseAddressSimple(addrString);
|
||||||
|
}
|
||||||
if (size == 0)
|
if (size == 0)
|
||||||
size = addr.getSpace()->getWordSize();
|
size = addr.getSpace()->getWordSize();
|
||||||
Range range(addr.getSpace(),addr.getOffset(),addr.getOffset() + (size-1));
|
Range range(addr.getSpace(), addr.getOffset(), addr.getOffset() + (size - 1));
|
||||||
if (volatileState == 0)
|
if (volatileState == 0)
|
||||||
symboltab->clearPropertyRange(Varnode::volatil, range);
|
symboltab->clearPropertyRange(Varnode::volatil, range);
|
||||||
else
|
else
|
||||||
symboltab->setPropertyRange(Varnode::volatil, range);
|
symboltab->setPropertyRange(Varnode::volatil, range);
|
||||||
|
lastAddr = addr;
|
||||||
|
lastSize = size;
|
||||||
}
|
}
|
||||||
decoder.closeElement(el);
|
decoder.closeElement(el);
|
||||||
}
|
}
|
||||||
|
|
|
@ -267,27 +267,35 @@ void SleighArchitecture::buildSymbols(DocumentStorage &store)
|
||||||
|
|
||||||
{
|
{
|
||||||
const Element *symtag = store.getTag(ELEM_DEFAULT_SYMBOLS.getName());
|
const Element *symtag = store.getTag(ELEM_DEFAULT_SYMBOLS.getName());
|
||||||
if (symtag == (const Element *)0) return;
|
if (symtag == (const Element*) 0)
|
||||||
XmlDecode decoder(this,symtag);
|
return;
|
||||||
|
XmlDecode decoder(this, symtag);
|
||||||
uint4 el = decoder.openElement(ELEM_DEFAULT_SYMBOLS);
|
uint4 el = decoder.openElement(ELEM_DEFAULT_SYMBOLS);
|
||||||
while(decoder.peekElement() != 0) {
|
Address lastAddr(Address::m_minimal);
|
||||||
|
int4 lastSize = -1;
|
||||||
|
while (decoder.peekElement() != 0) {
|
||||||
uint4 subel = decoder.openElement(ELEM_SYMBOL);
|
uint4 subel = decoder.openElement(ELEM_SYMBOL);
|
||||||
Address addr;
|
Address addr;
|
||||||
string name;
|
string name;
|
||||||
|
string description;
|
||||||
int4 size = 0;
|
int4 size = 0;
|
||||||
int4 volatileState = -1;
|
int4 volatileState = -1;
|
||||||
for(;;) {
|
for (;;) {
|
||||||
uint4 attribId = decoder.getNextAttributeId();
|
uint4 attribId = decoder.getNextAttributeId();
|
||||||
if (attribId == 0) break;
|
if (attribId == 0)
|
||||||
|
break;
|
||||||
if (attribId == ATTRIB_NAME)
|
if (attribId == ATTRIB_NAME)
|
||||||
name = decoder.readString();
|
name = decoder.readString();
|
||||||
else if (attribId == ATTRIB_ADDRESS) {
|
else if (attribId == ATTRIB_ADDRESS) {
|
||||||
addr = parseAddressSimple(decoder.readString());
|
string addrStr = decoder.readString();
|
||||||
|
if (addrStr == "next" && lastSize != -1) {
|
||||||
|
addr = lastAddr + lastSize;
|
||||||
|
} else {
|
||||||
|
addr = parseAddressSimple(addrStr);
|
||||||
}
|
}
|
||||||
else if (attribId == ATTRIB_VOLATILE) {
|
} else if (attribId == ATTRIB_VOLATILE) {
|
||||||
volatileState = decoder.readBool() ? 1 : 0;
|
volatileState = decoder.readBool() ? 1 : 0;
|
||||||
}
|
} else if (attribId == ATTRIB_SIZE)
|
||||||
else if (attribId == ATTRIB_SIZE)
|
|
||||||
size = decoder.readSignedInteger();
|
size = decoder.readSignedInteger();
|
||||||
}
|
}
|
||||||
decoder.closeElement(subel);
|
decoder.closeElement(subel);
|
||||||
|
@ -298,7 +306,7 @@ void SleighArchitecture::buildSymbols(DocumentStorage &store)
|
||||||
if (size == 0)
|
if (size == 0)
|
||||||
size = addr.getSpace()->getWordSize();
|
size = addr.getSpace()->getWordSize();
|
||||||
if (volatileState >= 0) {
|
if (volatileState >= 0) {
|
||||||
Range range(addr.getSpace(),addr.getOffset(),addr.getOffset() + (size-1));
|
Range range(addr.getSpace(), addr.getOffset(), addr.getOffset() + (size - 1));
|
||||||
if (volatileState == 0)
|
if (volatileState == 0)
|
||||||
symboltab->clearPropertyRange(Varnode::volatil, range);
|
symboltab->clearPropertyRange(Varnode::volatil, range);
|
||||||
else
|
else
|
||||||
|
@ -307,6 +315,8 @@ void SleighArchitecture::buildSymbols(DocumentStorage &store)
|
||||||
Datatype *ct = types->getBase(size, TYPE_UNKNOWN);
|
Datatype *ct = types->getBase(size, TYPE_UNKNOWN);
|
||||||
Address usepoint;
|
Address usepoint;
|
||||||
symboltab->getGlobalScope()->addSymbol(name, ct, addr, usepoint);
|
symboltab->getGlobalScope()->addSymbol(name, ct, addr, usepoint);
|
||||||
|
lastAddr = addr;
|
||||||
|
lastSize = size;
|
||||||
}
|
}
|
||||||
decoder.closeElement(el);
|
decoder.closeElement(el);
|
||||||
}
|
}
|
||||||
|
|
|
@ -146,6 +146,9 @@
|
||||||
<ref name="symbol_type"/>
|
<ref name="symbol_type"/>
|
||||||
</attribute>
|
</attribute>
|
||||||
</optional>
|
</optional>
|
||||||
|
<optional>
|
||||||
|
<attribute name="description"/>
|
||||||
|
</optional>
|
||||||
</element>
|
</element>
|
||||||
|
|
||||||
</oneOrMore>
|
</oneOrMore>
|
||||||
|
|
|
@ -756,14 +756,28 @@ public class SleighLanguage implements Language {
|
||||||
}
|
}
|
||||||
else if (elName.equals("default_symbols")) {
|
else if (elName.equals("default_symbols")) {
|
||||||
XmlElement subel = parser.start();
|
XmlElement subel = parser.start();
|
||||||
|
Address previousAddr = null;
|
||||||
|
int previousSize = 1;
|
||||||
while (parser.peek().getName().equals("symbol")) {
|
while (parser.peek().getName().equals("symbol")) {
|
||||||
XmlElement symbol = parser.start();
|
XmlElement symbol = parser.start();
|
||||||
String labelName = symbol.getAttribute("name");
|
String labelName = symbol.getAttribute("name");
|
||||||
String addressString = symbol.getAttribute("address");
|
String addressString = symbol.getAttribute("address");
|
||||||
String typeString = symbol.getAttribute("type");
|
String typeString = symbol.getAttribute("type");
|
||||||
|
String comment = symbol.getAttribute("description");
|
||||||
ProcessorSymbolType type = ProcessorSymbolType.getType(typeString);
|
ProcessorSymbolType type = ProcessorSymbolType.getType(typeString);
|
||||||
boolean isEntry = SpecXmlUtils.decodeBoolean(symbol.getAttribute("entry"));
|
boolean isEntry = SpecXmlUtils.decodeBoolean(symbol.getAttribute("entry"));
|
||||||
Address startAddress = addressFactory.getAddress(addressString);
|
Address startAddress = null;
|
||||||
|
if (addressString.equalsIgnoreCase("next")) {
|
||||||
|
if (previousAddr == null) {
|
||||||
|
Msg.error(this, "use of addr=\"next\" tag with no previous address for " +
|
||||||
|
labelName + " : " + description.getSpecFile());
|
||||||
|
} else {
|
||||||
|
startAddress = previousAddr.add(previousSize);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
startAddress = addressFactory.getAddress(addressString);
|
||||||
|
}
|
||||||
int rangeSize = SpecXmlUtils.decodeInt(symbol.getAttribute("size"));
|
int rangeSize = SpecXmlUtils.decodeInt(symbol.getAttribute("size"));
|
||||||
Boolean isVolatile =
|
Boolean isVolatile =
|
||||||
SpecXmlUtils.decodeNullableBoolean(symbol.getAttribute("volatile"));
|
SpecXmlUtils.decodeNullableBoolean(symbol.getAttribute("volatile"));
|
||||||
|
@ -774,7 +788,7 @@ public class SleighLanguage implements Language {
|
||||||
else {
|
else {
|
||||||
AddressLabelInfo info;
|
AddressLabelInfo info;
|
||||||
try {
|
try {
|
||||||
info = new AddressLabelInfo(startAddress, rangeSize, labelName, false,
|
info = new AddressLabelInfo(startAddress, rangeSize, labelName, comment, false,
|
||||||
isEntry, type, isVolatile);
|
isEntry, type, isVolatile);
|
||||||
}
|
}
|
||||||
catch (AddressOverflowException e) {
|
catch (AddressOverflowException e) {
|
||||||
|
@ -801,6 +815,8 @@ public class SleighLanguage implements Language {
|
||||||
}
|
}
|
||||||
// skip the end tag
|
// skip the end tag
|
||||||
parser.end(symbol);
|
parser.end(symbol);
|
||||||
|
previousAddr = startAddress;
|
||||||
|
previousSize = rangeSize;
|
||||||
}
|
}
|
||||||
parser.end(subel);
|
parser.end(subel);
|
||||||
}
|
}
|
||||||
|
|
|
@ -29,6 +29,7 @@ public class AddressLabelInfo implements Comparable<AddressLabelInfo> {
|
||||||
private Address addr;
|
private Address addr;
|
||||||
private Address endAddr;
|
private Address endAddr;
|
||||||
private String label;
|
private String label;
|
||||||
|
private String description;
|
||||||
private boolean isPrimary;
|
private boolean isPrimary;
|
||||||
private boolean isEntry;
|
private boolean isEntry;
|
||||||
private ProcessorSymbolType processorSymbolType;
|
private ProcessorSymbolType processorSymbolType;
|
||||||
|
@ -41,12 +42,13 @@ public class AddressLabelInfo implements Comparable<AddressLabelInfo> {
|
||||||
* @param addr Address object that describes the memory address
|
* @param addr Address object that describes the memory address
|
||||||
* @param sizeInBytes Integer describing the Size in bytes that the label applies to.
|
* @param sizeInBytes Integer describing the Size in bytes that the label applies to.
|
||||||
* @param label String label or alias for the Address
|
* @param label String label or alias for the Address
|
||||||
|
* @param description Label description
|
||||||
* @param isPrimary boolean describes if this object is the primary label for the Address 'addr'
|
* @param isPrimary boolean describes if this object is the primary label for the Address 'addr'
|
||||||
* @param isEntry boolean describes if this object is an entry label for the Address 'addr'
|
* @param isEntry boolean describes if this object is an entry label for the Address 'addr'
|
||||||
* @param type ProcessorSymbolType the type of symbol
|
* @param type ProcessorSymbolType the type of symbol
|
||||||
* @param isVolatile Boolean describes if the memory at this address is volatile
|
* @param isVolatile Boolean describes if the memory at this address is volatile
|
||||||
*/
|
*/
|
||||||
public AddressLabelInfo(Address addr, Integer sizeInBytes, String label, boolean isPrimary,
|
public AddressLabelInfo(Address addr, Integer sizeInBytes, String label, String description, boolean isPrimary,
|
||||||
boolean isEntry, ProcessorSymbolType type, Boolean isVolatile) throws AddressOverflowException {
|
boolean isEntry, ProcessorSymbolType type, Boolean isVolatile) throws AddressOverflowException {
|
||||||
this.addr = addr;
|
this.addr = addr;
|
||||||
if ( sizeInBytes == null || sizeInBytes <= 0 ) {
|
if ( sizeInBytes == null || sizeInBytes <= 0 ) {
|
||||||
|
@ -57,6 +59,7 @@ public class AddressLabelInfo implements Comparable<AddressLabelInfo> {
|
||||||
}
|
}
|
||||||
this.endAddr = this.addr.addNoWrap(this.sizeInBytes-1);
|
this.endAddr = this.addr.addNoWrap(this.sizeInBytes-1);
|
||||||
this.label = label;
|
this.label = label;
|
||||||
|
this.description = description;
|
||||||
this.isPrimary = isPrimary;
|
this.isPrimary = isPrimary;
|
||||||
this.isEntry = isEntry;
|
this.isEntry = isEntry;
|
||||||
this.processorSymbolType = type;
|
this.processorSymbolType = type;
|
||||||
|
@ -64,28 +67,35 @@ public class AddressLabelInfo implements Comparable<AddressLabelInfo> {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the object's address.
|
* @return object's address.
|
||||||
*/
|
*/
|
||||||
public final Address getAddress() {
|
public final Address getAddress() {
|
||||||
return addr;
|
return addr;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the object's end address.
|
* @return the object's end address.
|
||||||
*/
|
*/
|
||||||
public final Address getEndAddress() {
|
public final Address getEndAddress() {
|
||||||
return endAddr;
|
return endAddr;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the object's label or alias.
|
* @return the object's label or alias.
|
||||||
*/
|
*/
|
||||||
public final String getLabel() {
|
public final String getLabel() {
|
||||||
return label;
|
return label;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the object's size in bytes. Always non-zero positive value and defaults to
|
* @return the object's description if it has one, null otherwise
|
||||||
|
*/
|
||||||
|
public final String getDescription() {
|
||||||
|
return description;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return the object's size in bytes. Always non-zero positive value and defaults to
|
||||||
* addressable unit size of associated address space.
|
* addressable unit size of associated address space.
|
||||||
*/
|
*/
|
||||||
public final int getByteSize() {
|
public final int getByteSize() {
|
||||||
|
@ -93,14 +103,14 @@ public class AddressLabelInfo implements Comparable<AddressLabelInfo> {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns whether the object is the primary label at the address.
|
* @return whether the object is the primary label at the address.
|
||||||
*/
|
*/
|
||||||
public final boolean isPrimary() {
|
public final boolean isPrimary() {
|
||||||
return isPrimary;
|
return isPrimary;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns whether the object is volatile.
|
* @return whether the object is volatile.
|
||||||
* Boolean.False when the address is explicitly not volatile.
|
* Boolean.False when the address is explicitly not volatile.
|
||||||
* Boolean.True when the address is volatile.
|
* Boolean.True when the address is volatile.
|
||||||
* NULL when the volatility is not defined at this address.
|
* NULL when the volatility is not defined at this address.
|
||||||
|
@ -164,6 +174,9 @@ public class AddressLabelInfo implements Comparable<AddressLabelInfo> {
|
||||||
buf.append("isEntry = " + isEntry);
|
buf.append("isEntry = " + isEntry);
|
||||||
buf.append(", ");
|
buf.append(", ");
|
||||||
buf.append("type = " + processorSymbolType);
|
buf.append("type = " + processorSymbolType);
|
||||||
|
if (description != null) {
|
||||||
|
buf.append("description = " + description);
|
||||||
|
}
|
||||||
return buf.toString();
|
return buf.toString();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue