Skip to content

Commit bf48efe

Browse files
Parse register information
1 parent 691bbd9 commit bf48efe

File tree

1 file changed

+105
-0
lines changed

1 file changed

+105
-0
lines changed

src/main/java/svd/SVDPlugin.java

Lines changed: 105 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,15 +40,27 @@
4040
import ghidra.program.model.address.Address;
4141
import ghidra.program.model.address.AddressOverflowException;
4242
import ghidra.program.model.address.AddressSpace;
43+
import ghidra.program.model.data.DataTypeConflictHandler;
44+
import ghidra.program.model.data.ProgramBasedDataTypeManager;
45+
import ghidra.program.model.data.StructureDataType;
46+
import ghidra.program.model.data.UnsignedLongDataType;
47+
import ghidra.program.model.listing.Listing;
4348
import ghidra.program.model.listing.Program;
4449
import ghidra.program.model.mem.Memory;
4550
import ghidra.program.model.mem.MemoryBlock;
4651
import ghidra.program.model.mem.MemoryConflictException;
52+
import ghidra.program.model.symbol.Namespace;
53+
import ghidra.program.model.symbol.SourceType;
54+
import ghidra.program.model.symbol.SymbolTable;
55+
import ghidra.program.model.util.CodeUnitInsertionException;
4756
import ghidra.util.Msg;
57+
import ghidra.util.exception.DuplicateNameException;
58+
import ghidra.util.exception.InvalidInputException;
4859
import io.svdparser.SvdAddressBlock;
4960
import io.svdparser.SvdDevice;
5061
import io.svdparser.SvdParserException;
5162
import io.svdparser.SvdPeripheral;
63+
import io.svdparser.SvdRegister;
5264
import svd.MemoryUtils.MemRangeRelation;
5365

5466
//@formatter:off
@@ -149,6 +161,14 @@ private String getPeriphBlockName(SvdPeripheral periph, SvdAddressBlock block) {
149161
}
150162

151163
private void processBlock(JComponent parentComponent, Program program, BlockInfo blockInfo) {
164+
boolean memOk = processBlockMemory(parentComponent, program, blockInfo);
165+
if (memOk) {
166+
processBlockSymbol(program, blockInfo);
167+
processBlockDataTypes(program, blockInfo);
168+
}
169+
}
170+
171+
private boolean processBlockMemory(JComponent parentComponent, Program program, BlockInfo blockInfo) {
152172
Memory memory = program.getMemory();
153173
MemoryBlock[] collidingMemoryBlocks = MemoryUtils.getBlockCollidingMemoryBlocks(memory, blockInfo.block);
154174
if (collidingMemoryBlocks.length == 0) {
@@ -160,7 +180,9 @@ private void processBlock(JComponent parentComponent, Program program, BlockInfo
160180
Msg.showWarn(getClass(), null, "Load SVD", "Could not create a region for " + blockInfo.name + "@"
161181
+ String.format("0x%08x", blockInfo.block.getAddress()) + "+"
162182
+ String.format("0x%08x", blockInfo.block.getSize()) + ". It conflicts with an existing region!");
183+
return false;
163184
}
185+
return true;
164186
}
165187

166188
private void createMemoryBlock(Program program, BlockInfo blockInfo) {
@@ -295,4 +317,87 @@ private void updateMatchingMemoryBlock(JComponent parentComponent, Program progr
295317
program.endTransaction(transactionId, ok);
296318
}
297319
}
320+
321+
private void processBlockSymbol(Program program, BlockInfo blockInfo) {
322+
// Calculate address of the block...
323+
AddressSpace addrSpace = program.getAddressFactory().getDefaultAddressSpace();
324+
Address addr = addrSpace.getAddress(blockInfo.block.getAddress().longValue());
325+
326+
// Create a symbol name...
327+
SymbolTable symTable = program.getSymbolTable();
328+
Namespace namespace = getOrCreateNamespace(program, "Peripherals");
329+
int transactionId = program.startTransaction("SVD " + blockInfo.name + " symtable creation");
330+
boolean ok = false;
331+
try {
332+
symTable.createLabel(addr, blockInfo.name.replace('/', '_'), namespace, SourceType.IMPORTED);
333+
ok = true;
334+
} catch (InvalidInputException e) {
335+
// TODO Auto-generated catch block
336+
e.printStackTrace();
337+
}
338+
program.endTransaction(transactionId, ok);
339+
}
340+
341+
private Namespace getOrCreateNamespace(Program program, String name) {
342+
SymbolTable symTable = program.getSymbolTable();
343+
Namespace namespace = symTable.getNamespace(name, null);
344+
if (namespace != null)
345+
return namespace;
346+
347+
int transactionId = program.startTransaction("SVD " + name + " namespace creation");
348+
boolean ok = false;
349+
try {
350+
namespace = symTable.createNameSpace(null, name, SourceType.IMPORTED);
351+
ok = true;
352+
} catch (DuplicateNameException | InvalidInputException e) {
353+
// TODO Auto-generated catch block
354+
e.printStackTrace();
355+
}
356+
program.endTransaction(transactionId, ok);
357+
return namespace;
358+
}
359+
360+
private void processBlockDataTypes(Program program, BlockInfo blockInfo) {
361+
StructureDataType struct = createPeripheralBlockDataType(blockInfo);
362+
363+
// Add struct to the data type manager...
364+
ProgramBasedDataTypeManager dataTypeManager = program.getDataTypeManager();
365+
int transactionId = program.startTransaction("SVD " + blockInfo.name + " data type creation");
366+
boolean ok = false;
367+
try {
368+
dataTypeManager.addDataType(struct, DataTypeConflictHandler.REPLACE_HANDLER);
369+
ok = true;
370+
} catch (IllegalArgumentException e) {
371+
e.printStackTrace();
372+
}
373+
program.endTransaction(transactionId, ok);
374+
375+
// Calculate address of the block...
376+
AddressSpace addrSpace = program.getAddressFactory().getDefaultAddressSpace();
377+
Address addr = addrSpace.getAddress(blockInfo.block.getAddress().longValue());
378+
379+
// Add data type to listing...
380+
Listing listing = program.getListing();
381+
transactionId = program.startTransaction("SVD " + blockInfo.name + " data type listing placement");
382+
ok = false;
383+
try {
384+
listing.createData(addr, struct);
385+
ok = true;
386+
} catch (CodeUnitInsertionException e) {
387+
// TODO Auto-generated catch block
388+
e.printStackTrace();
389+
}
390+
program.endTransaction(transactionId, ok);
391+
}
392+
393+
private StructureDataType createPeripheralBlockDataType(BlockInfo blockInfo) {
394+
String struct_name = blockInfo.name.replace('/', '_') + "_reg_t";
395+
StructureDataType struct = new StructureDataType(struct_name, blockInfo.block.getSize().intValue());
396+
for (SvdPeripheral periph : blockInfo.peripherals)
397+
for (SvdRegister reg : periph.getRegisters())
398+
if (reg.getOffset() < blockInfo.block.getSize())
399+
struct.replaceAtOffset(reg.getOffset(), new UnsignedLongDataType(), reg.getSize() / 8,
400+
reg.getName(), reg.getDescription());
401+
return struct;
402+
}
298403
}

0 commit comments

Comments
 (0)