mirror of
https://github.com/NationalSecurityAgency/ghidra.git
synced 2024-11-22 04:05:39 +00:00
Merge remote-tracking branch 'origin/GP-4742_emteere_PSPECImprovements--SQUASHED'
This commit is contained in:
commit
47b08753e5
@ -32,8 +32,7 @@ import ghidra.program.database.ProgramDB;
|
||||
import ghidra.program.database.function.OverlappingFunctionException;
|
||||
import ghidra.program.model.address.*;
|
||||
import ghidra.program.model.lang.*;
|
||||
import ghidra.program.model.listing.FunctionManager;
|
||||
import ghidra.program.model.listing.Program;
|
||||
import ghidra.program.model.listing.*;
|
||||
import ghidra.program.model.mem.InvalidAddressException;
|
||||
import ghidra.program.model.mem.MemoryConflictException;
|
||||
import ghidra.program.model.symbol.*;
|
||||
@ -487,7 +486,7 @@ public abstract class AbstractProgramLoader implements Loader {
|
||||
for (Register reg : lang.getRegisters()) {
|
||||
Address addr = reg.getAddress();
|
||||
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
|
||||
@ -495,7 +494,7 @@ public abstract class AbstractProgramLoader implements Loader {
|
||||
boolean anchorSymbols = shouldAnchorSymbols(options);
|
||||
List<AddressLabelInfo> labels = lang.getDefaultSymbols();
|
||||
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);
|
||||
}
|
||||
}
|
||||
@ -507,13 +506,16 @@ public abstract class AbstractProgramLoader implements Loader {
|
||||
}
|
||||
|
||||
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();
|
||||
Address addr = address;
|
||||
Symbol s = symTable.getPrimarySymbol(addr);
|
||||
try {
|
||||
Namespace namespace = program.getGlobalNamespace();
|
||||
s = symTable.createLabel(addr, labelname, namespace, SourceType.IMPORTED);
|
||||
if (comment != null) {
|
||||
program.getListing().setComment(address, CodeUnit.EOL_COMMENT, comment);
|
||||
}
|
||||
if (isEntry) {
|
||||
symTable.addExternalEntryPoint(addr);
|
||||
}
|
||||
|
@ -145,25 +145,7 @@ public class SymbolicPropogator {
|
||||
|
||||
this.evaluator = eval;
|
||||
|
||||
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;
|
||||
}
|
||||
if (space == defaultAddrSpace) {
|
||||
memorySpaces.add(0, space); // default space is always at index 0
|
||||
}
|
||||
else {
|
||||
memorySpaces.add(space);
|
||||
}
|
||||
}
|
||||
initValidAddressSpaces();
|
||||
|
||||
// if assuming, make a copy of programContext
|
||||
savedProgramContext = programContext;
|
||||
@ -206,6 +188,44 @@ public class SymbolicPropogator {
|
||||
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
|
||||
* 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();
|
||||
|
||||
// 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
|
||||
|
||||
// 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 ghidra.app.plugin.core.analysis.ConstantPropagationAnalyzer;
|
||||
import ghidra.app.plugin.core.analysis.ConstantPropagationContextEvaluator;
|
||||
import ghidra.framework.store.LockException;
|
||||
import ghidra.program.database.ProgramBuilder;
|
||||
import ghidra.program.model.address.Address;
|
||||
import ghidra.program.model.address.AddressSet;
|
||||
import ghidra.program.model.address.*;
|
||||
import ghidra.program.model.lang.Register;
|
||||
import ghidra.program.model.lang.RegisterValue;
|
||||
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.symbol.Reference;
|
||||
import ghidra.program.model.symbol.ReferenceIterator;
|
||||
import ghidra.program.util.SymbolicPropogator.Value;
|
||||
import ghidra.util.exception.CancelledException;
|
||||
import ghidra.util.exception.NotFoundException;
|
||||
import ghidra.util.task.TaskMonitor;
|
||||
|
||||
@ -307,6 +310,167 @@ public class ConstantPropogationReferenceTest extends AbstractGenericTest {
|
||||
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
|
||||
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());
|
||||
if (symtag == (const Element *)0) return;
|
||||
XmlDecode decoder(this,symtag);
|
||||
if (symtag == (const Element*) 0)
|
||||
return;
|
||||
XmlDecode decoder(this, symtag);
|
||||
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);
|
||||
string addrString;
|
||||
string name;
|
||||
int4 size = 0;
|
||||
int4 volatileState = -1;
|
||||
for(;;) {
|
||||
for (;;) {
|
||||
uint4 attribId = decoder.getNextAttributeId();
|
||||
if (attribId == 0) break;
|
||||
if (attribId == 0)
|
||||
break;
|
||||
if (attribId == ATTRIB_NAME)
|
||||
name = decoder.readString();
|
||||
else if (attribId == ATTRIB_ADDRESS) {
|
||||
addrString = decoder.readString();
|
||||
}
|
||||
else if (attribId == ATTRIB_VOLATILE) {
|
||||
} else if (attribId == ATTRIB_VOLATILE) {
|
||||
volatileState = decoder.readBool() ? 1 : 0;
|
||||
}
|
||||
else if (attribId == ATTRIB_SIZE)
|
||||
} else if (attribId == ATTRIB_SIZE)
|
||||
size = decoder.readSignedInteger();
|
||||
}
|
||||
decoder.closeElement(subel);
|
||||
@ -417,14 +419,21 @@ void ArchitectureGhidra::buildSymbols(DocumentStorage &store)
|
||||
// feed the global symbol to the decompiler on a per function basic.
|
||||
if (volatileState < 0)
|
||||
continue;
|
||||
Address addr = parseAddressSimple(addrString);
|
||||
Address addr;
|
||||
if (addrString == "next" && lastSize != -1) {
|
||||
addr = lastAddr + lastSize;
|
||||
} else {
|
||||
addr = parseAddressSimple(addrString);
|
||||
}
|
||||
if (size == 0)
|
||||
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)
|
||||
symboltab->clearPropertyRange(Varnode::volatil, range);
|
||||
else
|
||||
symboltab->setPropertyRange(Varnode::volatil, range);
|
||||
lastAddr = addr;
|
||||
lastSize = size;
|
||||
}
|
||||
decoder.closeElement(el);
|
||||
}
|
||||
|
@ -267,27 +267,35 @@ void SleighArchitecture::buildSymbols(DocumentStorage &store)
|
||||
|
||||
{
|
||||
const Element *symtag = store.getTag(ELEM_DEFAULT_SYMBOLS.getName());
|
||||
if (symtag == (const Element *)0) return;
|
||||
XmlDecode decoder(this,symtag);
|
||||
if (symtag == (const Element*) 0)
|
||||
return;
|
||||
XmlDecode decoder(this, symtag);
|
||||
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);
|
||||
Address addr;
|
||||
string name;
|
||||
string description;
|
||||
int4 size = 0;
|
||||
int4 volatileState = -1;
|
||||
for(;;) {
|
||||
for (;;) {
|
||||
uint4 attribId = decoder.getNextAttributeId();
|
||||
if (attribId == 0) break;
|
||||
if (attribId == 0)
|
||||
break;
|
||||
if (attribId == ATTRIB_NAME)
|
||||
name = decoder.readString();
|
||||
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;
|
||||
}
|
||||
else if (attribId == ATTRIB_SIZE)
|
||||
} else if (attribId == ATTRIB_SIZE)
|
||||
size = decoder.readSignedInteger();
|
||||
}
|
||||
decoder.closeElement(subel);
|
||||
@ -298,7 +306,7 @@ void SleighArchitecture::buildSymbols(DocumentStorage &store)
|
||||
if (size == 0)
|
||||
size = addr.getSpace()->getWordSize();
|
||||
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)
|
||||
symboltab->clearPropertyRange(Varnode::volatil, range);
|
||||
else
|
||||
@ -307,6 +315,8 @@ void SleighArchitecture::buildSymbols(DocumentStorage &store)
|
||||
Datatype *ct = types->getBase(size, TYPE_UNKNOWN);
|
||||
Address usepoint;
|
||||
symboltab->getGlobalScope()->addSymbol(name, ct, addr, usepoint);
|
||||
lastAddr = addr;
|
||||
lastSize = size;
|
||||
}
|
||||
decoder.closeElement(el);
|
||||
}
|
||||
|
@ -146,6 +146,9 @@
|
||||
<ref name="symbol_type"/>
|
||||
</attribute>
|
||||
</optional>
|
||||
<optional>
|
||||
<attribute name="description"/>
|
||||
</optional>
|
||||
</element>
|
||||
|
||||
</oneOrMore>
|
||||
|
@ -756,14 +756,28 @@ public class SleighLanguage implements Language {
|
||||
}
|
||||
else if (elName.equals("default_symbols")) {
|
||||
XmlElement subel = parser.start();
|
||||
Address previousAddr = null;
|
||||
int previousSize = 1;
|
||||
while (parser.peek().getName().equals("symbol")) {
|
||||
XmlElement symbol = parser.start();
|
||||
String labelName = symbol.getAttribute("name");
|
||||
String addressString = symbol.getAttribute("address");
|
||||
String typeString = symbol.getAttribute("type");
|
||||
String comment = symbol.getAttribute("description");
|
||||
ProcessorSymbolType type = ProcessorSymbolType.getType(typeString);
|
||||
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"));
|
||||
Boolean isVolatile =
|
||||
SpecXmlUtils.decodeNullableBoolean(symbol.getAttribute("volatile"));
|
||||
@ -774,7 +788,7 @@ public class SleighLanguage implements Language {
|
||||
else {
|
||||
AddressLabelInfo info;
|
||||
try {
|
||||
info = new AddressLabelInfo(startAddress, rangeSize, labelName, false,
|
||||
info = new AddressLabelInfo(startAddress, rangeSize, labelName, comment, false,
|
||||
isEntry, type, isVolatile);
|
||||
}
|
||||
catch (AddressOverflowException e) {
|
||||
@ -801,6 +815,8 @@ public class SleighLanguage implements Language {
|
||||
}
|
||||
// skip the end tag
|
||||
parser.end(symbol);
|
||||
previousAddr = startAddress;
|
||||
previousSize = rangeSize;
|
||||
}
|
||||
parser.end(subel);
|
||||
}
|
||||
|
@ -29,6 +29,7 @@ public class AddressLabelInfo implements Comparable<AddressLabelInfo> {
|
||||
private Address addr;
|
||||
private Address endAddr;
|
||||
private String label;
|
||||
private String description;
|
||||
private boolean isPrimary;
|
||||
private boolean isEntry;
|
||||
private ProcessorSymbolType processorSymbolType;
|
||||
@ -41,12 +42,13 @@ public class AddressLabelInfo implements Comparable<AddressLabelInfo> {
|
||||
* @param addr Address object that describes the memory address
|
||||
* @param sizeInBytes Integer describing the Size in bytes that the label applies to.
|
||||
* @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 isEntry boolean describes if this object is an entry label for the Address 'addr'
|
||||
* @param type ProcessorSymbolType the type of symbol
|
||||
* @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 {
|
||||
this.addr = addr;
|
||||
if ( sizeInBytes == null || sizeInBytes <= 0 ) {
|
||||
@ -57,6 +59,7 @@ public class AddressLabelInfo implements Comparable<AddressLabelInfo> {
|
||||
}
|
||||
this.endAddr = this.addr.addNoWrap(this.sizeInBytes-1);
|
||||
this.label = label;
|
||||
this.description = description;
|
||||
this.isPrimary = isPrimary;
|
||||
this.isEntry = isEntry;
|
||||
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() {
|
||||
return addr;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the object's end address.
|
||||
* @return the object's end address.
|
||||
*/
|
||||
public final Address getEndAddress() {
|
||||
return endAddr;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the object's label or alias.
|
||||
* @return the object's label or alias.
|
||||
*/
|
||||
public final String getLabel() {
|
||||
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.
|
||||
*/
|
||||
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() {
|
||||
return isPrimary;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether the object is volatile.
|
||||
* @return whether the object is volatile.
|
||||
* Boolean.False when the address is explicitly not volatile.
|
||||
* Boolean.True when the address is volatile.
|
||||
* 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(", ");
|
||||
buf.append("type = " + processorSymbolType);
|
||||
if (description != null) {
|
||||
buf.append("description = " + description);
|
||||
}
|
||||
return buf.toString();
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user