mirror of
https://github.com/NationalSecurityAgency/ghidra.git
synced 2026-06-01 02:46:28 +08:00
GP-3883 added source file manager
This commit is contained in:
+108
@@ -0,0 +1,108 @@
|
||||
/* ###
|
||||
* IP: GHIDRA
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package ghidra.program.database.sourcemap;
|
||||
|
||||
import org.junit.Before;
|
||||
|
||||
import generic.test.AbstractGenericTest;
|
||||
import ghidra.program.model.address.*;
|
||||
import ghidra.program.model.listing.*;
|
||||
import ghidra.program.model.sourcemap.SourceFileManager;
|
||||
import ghidra.test.ToyProgramBuilder;
|
||||
|
||||
public class AbstractSourceFileTest extends AbstractGenericTest {
|
||||
|
||||
protected Program program;
|
||||
protected ToyProgramBuilder builder;
|
||||
protected int baseOffset = 0x1001000;
|
||||
protected Address baseAddress;
|
||||
protected SourceFile source1;
|
||||
protected SourceFile source2;
|
||||
protected SourceFile source3;
|
||||
protected Instruction ret2_1;
|
||||
protected Instruction ret2_2;
|
||||
protected Instruction ret2_3;
|
||||
protected Instruction nop1_1;
|
||||
protected Instruction nop1_2;
|
||||
protected Instruction nop1_3;
|
||||
protected Instruction ret2_4;
|
||||
protected Instruction nop1_4;
|
||||
protected String path1 = "/test1";
|
||||
protected String path2 = "/test2/test2";
|
||||
protected String path3 = "/test3/test3/test3";
|
||||
protected String path4 = "/test4/test4/test4/test4";
|
||||
protected SourceFileManager sourceManager;
|
||||
|
||||
@Before
|
||||
public void setUp() throws Exception {
|
||||
builder = new ToyProgramBuilder("testprogram", true, false, this);
|
||||
int txID = builder.getProgram().startTransaction("create source map test program");
|
||||
long currentOffset = baseOffset;
|
||||
try {
|
||||
builder.createMemory(".text", Integer.toHexString(baseOffset), 64).setExecute(true);
|
||||
builder.addBytesReturn(currentOffset);
|
||||
currentOffset += 2;
|
||||
builder.addBytesNOP(currentOffset++, 1);
|
||||
builder.addBytesReturn(currentOffset);
|
||||
currentOffset += 2;
|
||||
builder.addBytesNOP(currentOffset++, 1);
|
||||
builder.addBytesReturn(currentOffset);
|
||||
currentOffset += 2;
|
||||
builder.addBytesNOP(currentOffset++, 1);
|
||||
builder.addBytesReturn(currentOffset);
|
||||
currentOffset += 2;
|
||||
builder.addBytesNOP(currentOffset++, 1);
|
||||
builder.disassemble(Integer.toHexString(baseOffset),
|
||||
(int) (currentOffset - baseOffset));
|
||||
}
|
||||
finally {
|
||||
builder.getProgram().endTransaction(txID, true);
|
||||
}
|
||||
program = builder.getProgram();
|
||||
baseAddress = program.getAddressFactory().getDefaultAddressSpace().getAddress(baseOffset);
|
||||
InstructionIterator instIter = program.getListing().getInstructions(baseAddress, true);
|
||||
ret2_1 = instIter.next();
|
||||
nop1_1 = instIter.next();
|
||||
ret2_2 = instIter.next();
|
||||
nop1_2 = instIter.next();
|
||||
ret2_3 = instIter.next();
|
||||
nop1_3 = instIter.next();
|
||||
ret2_4 = instIter.next();
|
||||
nop1_4 = instIter.next();
|
||||
sourceManager = program.getSourceFileManager();
|
||||
|
||||
source1 = new SourceFile(path1);
|
||||
source2 = new SourceFile(path2);
|
||||
source3 = new SourceFile(path3);
|
||||
//leave path4 as String without a corresponding source file
|
||||
|
||||
txID = program.startTransaction("adding source files");
|
||||
try {
|
||||
sourceManager.addSourceFile(source1);
|
||||
sourceManager.addSourceFile(source2);
|
||||
sourceManager.addSourceFile(source3);
|
||||
}
|
||||
finally {
|
||||
program.endTransaction(txID, true);
|
||||
}
|
||||
builder.dispose();
|
||||
}
|
||||
|
||||
protected AddressRange getBody(CodeUnit cu) {
|
||||
return new AddressRangeImpl(cu.getMinAddress(), cu.getMaxAddress());
|
||||
}
|
||||
|
||||
}
|
||||
+131
@@ -0,0 +1,131 @@
|
||||
/* ###
|
||||
* IP: GHIDRA
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package ghidra.program.database.sourcemap;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
import ghidra.framework.store.LockException;
|
||||
import ghidra.program.model.sourcemap.SourceMapEntry;
|
||||
|
||||
public class GetSourceFilesTest extends AbstractSourceFileTest {
|
||||
|
||||
@Test
|
||||
public void testGetAllSourceFiles() throws LockException {
|
||||
List<SourceFile> sourceFiles = sourceManager.getAllSourceFiles();
|
||||
assertEquals(3, sourceFiles.size());
|
||||
assertTrue(sourceFiles.contains(source1));
|
||||
assertTrue(sourceFiles.contains(source2));
|
||||
assertTrue(sourceFiles.contains(source3));
|
||||
|
||||
int txId = program.startTransaction("deleting source file 2");
|
||||
try {
|
||||
sourceManager.removeSourceFile(source2);
|
||||
}
|
||||
finally {
|
||||
program.endTransaction(txId, true);
|
||||
}
|
||||
|
||||
sourceFiles = sourceManager.getAllSourceFiles();
|
||||
assertEquals(2, sourceFiles.size());
|
||||
assertTrue(sourceFiles.contains(source1));
|
||||
assertTrue(sourceFiles.contains(source3));
|
||||
|
||||
txId = program.startTransaction("deleting source files");
|
||||
try {
|
||||
sourceManager.removeSourceFile(source1);
|
||||
sourceManager.removeSourceFile(source3);
|
||||
}
|
||||
finally {
|
||||
program.endTransaction(txId, true);
|
||||
}
|
||||
|
||||
assertTrue(sourceManager.getAllSourceFiles().isEmpty());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetMappedSourceFiles() throws LockException {
|
||||
List<SourceFile> sourceFiles = sourceManager.getMappedSourceFiles();
|
||||
assertTrue(sourceFiles.isEmpty());
|
||||
|
||||
int txId = program.startTransaction("adding source map info");
|
||||
try {
|
||||
sourceManager.addSourceMapEntry(source1, 1, getBody(ret2_1));
|
||||
}
|
||||
finally {
|
||||
program.endTransaction(txId, true);
|
||||
}
|
||||
|
||||
sourceFiles = sourceManager.getMappedSourceFiles();
|
||||
assertEquals(1, sourceFiles.size());
|
||||
SourceFile file = sourceFiles.get(0);
|
||||
assertEquals(source1.getPath(), file.getPath());
|
||||
|
||||
txId = program.startTransaction("adding source map info");
|
||||
try {
|
||||
sourceManager.addSourceMapEntry(source2, 1, getBody(ret2_2));
|
||||
}
|
||||
finally {
|
||||
program.endTransaction(txId, true);
|
||||
}
|
||||
|
||||
sourceFiles = sourceManager.getMappedSourceFiles();
|
||||
assertEquals(2, sourceFiles.size());
|
||||
assertTrue(sourceFiles.contains(source1));
|
||||
assertTrue(sourceFiles.contains(source2));
|
||||
|
||||
txId = program.startTransaction("transferring source map entries");
|
||||
try {
|
||||
sourceManager.transferSourceMapEntries(source2, source3);
|
||||
}
|
||||
finally {
|
||||
program.endTransaction(txId, true);
|
||||
}
|
||||
|
||||
sourceFiles = sourceManager.getMappedSourceFiles();
|
||||
assertEquals(2, sourceFiles.size());
|
||||
assertTrue(sourceFiles.contains(source1));
|
||||
assertTrue(sourceFiles.contains(source3));
|
||||
|
||||
txId = program.startTransaction("deleting source1");
|
||||
try {
|
||||
sourceManager.removeSourceFile(source1);
|
||||
}
|
||||
finally {
|
||||
program.endTransaction(txId, true);
|
||||
}
|
||||
|
||||
sourceFiles = sourceManager.getMappedSourceFiles();
|
||||
assertEquals(1, sourceFiles.size());
|
||||
assertTrue(sourceFiles.contains(source3));
|
||||
|
||||
txId = program.startTransaction("clearing mapping info for source3");
|
||||
try {
|
||||
List<SourceMapEntry> entries = sourceManager.getSourceMapEntries(source3);
|
||||
for (SourceMapEntry entry : entries) {
|
||||
assertTrue(sourceManager.removeSourceMapEntry(entry));
|
||||
}
|
||||
}
|
||||
finally {
|
||||
program.endTransaction(txId, true);
|
||||
}
|
||||
sourceFiles = sourceManager.getMappedSourceFiles();
|
||||
assertTrue(sourceFiles.isEmpty());
|
||||
}
|
||||
}
|
||||
+1150
File diff suppressed because it is too large
Load Diff
+1207
File diff suppressed because it is too large
Load Diff
+508
File diff suppressed because it is too large
Load Diff
+222
@@ -0,0 +1,222 @@
|
||||
/* ###
|
||||
* IP: GHIDRA
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package ghidra.program.database.sourcemap;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
import ghidra.framework.store.LockException;
|
||||
import ghidra.program.model.address.Address;
|
||||
import ghidra.program.model.address.AddressOverflowException;
|
||||
import ghidra.program.model.sourcemap.*;
|
||||
|
||||
public class SourceMapEntryIteratorTest extends AbstractSourceFileTest {
|
||||
|
||||
@Test
|
||||
public void testInappropriateAddress() {
|
||||
assertFalse(sourceManager.getSourceMapEntryIterator(null, true).hasNext());
|
||||
assertFalse(sourceManager.getSourceMapEntryIterator(null, false).hasNext());
|
||||
assertFalse(sourceManager.getSourceMapEntryIterator(Address.NO_ADDRESS, true).hasNext());
|
||||
assertFalse(sourceManager.getSourceMapEntryIterator(Address.NO_ADDRESS, false).hasNext());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDummySourceManagerIterators() {
|
||||
Address address = ret2_1.getAddress();
|
||||
assertFalse(
|
||||
SourceFileManager.DUMMY.getSourceMapEntryIterator(address, true).hasNext());
|
||||
assertFalse(
|
||||
SourceFileManager.DUMMY.getSourceMapEntryIterator(address, false).hasNext());
|
||||
}
|
||||
|
||||
@Test(expected = NoSuchElementException.class)
|
||||
public void testNoSuchElementExceptionForward() throws AddressOverflowException, LockException {
|
||||
SourceMapEntry entry1 = null;
|
||||
|
||||
int txId = program.startTransaction("adding source map entry");
|
||||
try {
|
||||
entry1 = sourceManager.addSourceMapEntry(source1, 1, ret2_1.getAddress(), 2);
|
||||
}
|
||||
finally {
|
||||
program.endTransaction(txId, true);
|
||||
}
|
||||
|
||||
SourceMapEntryIterator iter =
|
||||
sourceManager.getSourceMapEntryIterator(ret2_1.getAddress(), true);
|
||||
assertTrue(iter.hasNext());
|
||||
assertEquals(entry1, iter.next());
|
||||
assertFalse(iter.hasNext());
|
||||
iter.next();
|
||||
}
|
||||
|
||||
@Test(expected = NoSuchElementException.class)
|
||||
public void testNoSuchElementExceptionBackward()
|
||||
throws AddressOverflowException, LockException {
|
||||
SourceMapEntry entry1 = null;
|
||||
|
||||
int txId = program.startTransaction("adding source map entry");
|
||||
try {
|
||||
entry1 = sourceManager.addSourceMapEntry(source1, 1, ret2_1.getAddress(), 2);
|
||||
}
|
||||
finally {
|
||||
program.endTransaction(txId, true);
|
||||
}
|
||||
|
||||
SourceMapEntryIterator iter =
|
||||
sourceManager.getSourceMapEntryIterator(ret2_1.getAddress(), false);
|
||||
assertTrue(iter.hasNext());
|
||||
assertEquals(entry1, iter.next());
|
||||
assertFalse(iter.hasNext());
|
||||
iter.next();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testForwardIterator() throws AddressOverflowException, LockException {
|
||||
int txId = program.startTransaction("adding first source map entry");
|
||||
SourceMapEntry entry1 = null;
|
||||
SourceMapEntry entry2 = null;
|
||||
SourceMapEntry entry3 = null;
|
||||
SourceMapEntry entry4 = null;
|
||||
SourceMapEntry entry5 = null;
|
||||
|
||||
SourceMapEntryIterator iter =
|
||||
sourceManager.getSourceMapEntryIterator(ret2_1.getAddress(), true);
|
||||
for (int i = 0; i < 10; i++) {
|
||||
assertFalse(iter.hasNext());
|
||||
}
|
||||
|
||||
try {
|
||||
entry1 = sourceManager.addSourceMapEntry(source1, 1, ret2_1.getAddress(), 2);
|
||||
entry2 = sourceManager.addSourceMapEntry(source1, 2, ret2_1.getAddress(), 2);
|
||||
entry3 = sourceManager.addSourceMapEntry(source2, 3, ret2_1.getAddress().add(1), 0);
|
||||
entry4 = sourceManager.addSourceMapEntry(source3, 4, nop1_1.getAddress(), 1);
|
||||
entry5 = sourceManager.addSourceMapEntry(source3, 5, nop1_1.getAddress(), 1);
|
||||
}
|
||||
finally {
|
||||
program.endTransaction(txId, true);
|
||||
}
|
||||
Set<SourceMapEntry> entries = new HashSet<>();
|
||||
iter = sourceManager.getSourceMapEntryIterator(ret2_1.getAddress(), true);
|
||||
|
||||
for (int i = 0; i < 10; i++) {
|
||||
assertTrue(iter.hasNext());
|
||||
}
|
||||
entries.add(iter.next());
|
||||
|
||||
assertTrue(iter.hasNext());
|
||||
entries.add(iter.next());
|
||||
assertTrue(entries.contains(entry1));
|
||||
assertTrue(entries.contains(entry2));
|
||||
|
||||
entries.clear();
|
||||
|
||||
assertTrue(iter.hasNext());
|
||||
assertEquals(entry3, iter.next());
|
||||
|
||||
assertTrue(iter.hasNext());
|
||||
entries.add(iter.next());
|
||||
assertTrue(iter.hasNext());
|
||||
entries.add(iter.next());
|
||||
assertTrue(entries.contains(entry4));
|
||||
assertTrue(entries.contains(entry5));
|
||||
assertFalse(iter.hasNext());
|
||||
entries.clear();
|
||||
|
||||
iter = sourceManager.getSourceMapEntryIterator(ret2_1.getAddress().add(1), true);
|
||||
assertTrue(iter.hasNext());
|
||||
assertEquals(entry3, iter.next());
|
||||
|
||||
assertTrue(iter.hasNext());
|
||||
entries.add(iter.next());
|
||||
assertTrue(iter.hasNext());
|
||||
entries.add(iter.next());
|
||||
assertTrue(entries.contains(entry4));
|
||||
assertTrue(entries.contains(entry5));
|
||||
assertFalse(iter.hasNext());
|
||||
|
||||
iter = sourceManager.getSourceMapEntryIterator(ret2_2.getAddress(), true);
|
||||
assertFalse(iter.hasNext());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testBackwardIterator() throws AddressOverflowException, LockException {
|
||||
int txId = program.startTransaction("adding first source map entry");
|
||||
SourceMapEntry entry1 = null;
|
||||
SourceMapEntry entry2 = null;
|
||||
SourceMapEntry entry3 = null;
|
||||
SourceMapEntry entry4 = null;
|
||||
SourceMapEntry entry5 = null;
|
||||
|
||||
SourceMapEntryIterator iter =
|
||||
sourceManager.getSourceMapEntryIterator(ret2_1.getAddress(), false);
|
||||
for (int i = 0; i < 10; i++) {
|
||||
assertFalse(iter.hasNext());
|
||||
}
|
||||
|
||||
try {
|
||||
entry1 = sourceManager.addSourceMapEntry(source1, 1, ret2_1.getAddress(), 2);
|
||||
entry2 = sourceManager.addSourceMapEntry(source1, 2, ret2_1.getAddress(), 2);
|
||||
entry3 = sourceManager.addSourceMapEntry(source2, 3, ret2_1.getAddress().add(1), 0);
|
||||
entry4 = sourceManager.addSourceMapEntry(source3, 4, nop1_1.getAddress(), 1);
|
||||
entry5 = sourceManager.addSourceMapEntry(source3, 5, nop1_1.getAddress(), 1);
|
||||
}
|
||||
finally {
|
||||
program.endTransaction(txId, true);
|
||||
}
|
||||
Set<SourceMapEntry> entries = new HashSet<>();
|
||||
iter = sourceManager.getSourceMapEntryIterator(nop1_1.getAddress(), false);
|
||||
|
||||
for (int i = 0; i < 10; i++) {
|
||||
assertTrue(iter.hasNext());
|
||||
}
|
||||
entries.add(iter.next());
|
||||
assertTrue(iter.hasNext());
|
||||
entries.add(iter.next());
|
||||
assertTrue(entries.contains(entry4));
|
||||
assertTrue(entries.contains(entry5));
|
||||
|
||||
entries.clear();
|
||||
|
||||
assertTrue(iter.hasNext());
|
||||
assertEquals(entry3, iter.next());
|
||||
|
||||
assertTrue(iter.hasNext());
|
||||
entries.add(iter.next());
|
||||
assertTrue(iter.hasNext());
|
||||
entries.add(iter.next());
|
||||
assertTrue(entries.contains(entry1));
|
||||
assertTrue(entries.contains(entry1));
|
||||
assertFalse(iter.hasNext());
|
||||
entries.clear();
|
||||
|
||||
iter = sourceManager.getSourceMapEntryIterator(ret2_1.getAddress().add(1), false);
|
||||
assertTrue(iter.hasNext());
|
||||
assertEquals(entry3, iter.next());
|
||||
|
||||
assertTrue(iter.hasNext());
|
||||
entries.add(iter.next());
|
||||
assertTrue(iter.hasNext());
|
||||
entries.add(iter.next());
|
||||
assertTrue(entries.contains(entry1));
|
||||
assertTrue(entries.contains(entry2));
|
||||
assertFalse(iter.hasNext());
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user