mirror of
https://github.com/NationalSecurityAgency/ghidra.git
synced 2026-08-08 07:40:39 -09:00
Merge branch 'GP-0_ryanmkurtz_PR-9427_mi11ione_fix-lsda-ttype-base'
This commit is contained in:
@@ -150,8 +150,8 @@ public class LSDAHeader extends GccAnalysisClass {
|
|||||||
|
|
||||||
LEB128Info uleb128 = GccAnalysisUtils.readULEB128Info(program, addr);
|
LEB128Info uleb128 = GccAnalysisUtils.readULEB128Info(program, addr);
|
||||||
|
|
||||||
// this offset it based from *here*..
|
// this offset is based from the end of *this* field, and the base is the table's last byte
|
||||||
ttypeOffset = uleb128.asLong() + curSize;
|
ttypeOffset = uleb128.asLong() + curSize + uleb128.getLength() - 1;
|
||||||
|
|
||||||
createAndCommentData(program, addr, UnsignedLeb128DataType.dataType, comment,
|
createAndCommentData(program, addr, UnsignedLeb128DataType.dataType, comment,
|
||||||
CommentType.EOL);
|
CommentType.EOL);
|
||||||
@@ -306,7 +306,7 @@ public class LSDAHeader extends GccAnalysisClass {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The offset from the type offset field to get to the base address of the type table.
|
* The offset from the start of the LSDA to the base address of the type table.
|
||||||
* @return the type table offset
|
* @return the type table offset
|
||||||
*/
|
*/
|
||||||
public int getTTypeOffset() {
|
public int getTTypeOffset() {
|
||||||
|
|||||||
@@ -20,7 +20,7 @@ import java.util.List;
|
|||||||
|
|
||||||
import ghidra.app.cmd.comments.SetCommentCmd;
|
import ghidra.app.cmd.comments.SetCommentCmd;
|
||||||
import ghidra.app.plugin.exceptionhandlers.gcc.*;
|
import ghidra.app.plugin.exceptionhandlers.gcc.*;
|
||||||
import ghidra.program.model.address.Address;
|
import ghidra.program.model.address.*;
|
||||||
import ghidra.program.model.data.*;
|
import ghidra.program.model.data.*;
|
||||||
import ghidra.program.model.listing.CommentType;
|
import ghidra.program.model.listing.CommentType;
|
||||||
import ghidra.program.model.listing.Program;
|
import ghidra.program.model.listing.Program;
|
||||||
@@ -100,7 +100,8 @@ public class LSDATypeTable extends GccAnalysisClass {
|
|||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
catch (MemoryAccessException mae) {
|
catch (MemoryAccessException | AddressOutOfBoundsException e) {
|
||||||
|
// a pc-relative entry landing outside the address space throws the unchecked one
|
||||||
SetCommentCmd commentCmd =
|
SetCommentCmd commentCmd =
|
||||||
new SetCommentCmd(addr, CommentType.EOL, "Unable to resolve pointer");
|
new SetCommentCmd(addr, CommentType.EOL, "Unable to resolve pointer");
|
||||||
commentCmd.applyTo(program);
|
commentCmd.applyTo(program);
|
||||||
|
|||||||
@@ -0,0 +1,113 @@
|
|||||||
|
/* ###
|
||||||
|
* 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.app.plugin.exceptionhandlers.gcc.structures.gccexcepttable;
|
||||||
|
|
||||||
|
import static org.junit.Assert.*;
|
||||||
|
|
||||||
|
import org.junit.*;
|
||||||
|
|
||||||
|
import generic.test.AbstractGenericTest;
|
||||||
|
import ghidra.app.plugin.exceptionhandlers.gcc.RegionDescriptor;
|
||||||
|
import ghidra.program.database.ProgramBuilder;
|
||||||
|
import ghidra.program.model.address.*;
|
||||||
|
import ghidra.program.model.listing.Program;
|
||||||
|
import ghidra.util.task.TaskMonitor;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tests that the LSDA header locates the type table correctly however many bytes the TType
|
||||||
|
* offset ULEB128 occupies. Each LSDA below runs LPStart encoding (omitted), TType encoding
|
||||||
|
* (pcrel|sdata4), TType offset, call site encoding (uleb128) and table length, call site
|
||||||
|
* records, action table, then a single type table entry ending at the type table base.
|
||||||
|
*/
|
||||||
|
public class LSDAHeaderTest extends AbstractGenericTest {
|
||||||
|
|
||||||
|
private ProgramBuilder builder;
|
||||||
|
private Program program;
|
||||||
|
|
||||||
|
@Before
|
||||||
|
public void setUp() throws Exception {
|
||||||
|
builder = new ProgramBuilder("lsda", ProgramBuilder._X64);
|
||||||
|
builder.createMemory("lsda", "0x1000", 0x400);
|
||||||
|
program = builder.getProgram();
|
||||||
|
}
|
||||||
|
|
||||||
|
@After
|
||||||
|
public void tearDown() {
|
||||||
|
builder.dispose();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testSingleByteTTypeOffset() throws Exception {
|
||||||
|
builder.setBytes("0x1000", "ff 1b 0d 01 04 00 02 02 01 01 00 00 f4 02 00 00");
|
||||||
|
|
||||||
|
LSDATable table = createTable();
|
||||||
|
|
||||||
|
assertEquals(addr(0x100f), table.getHeader().getTTypeBaseAddress());
|
||||||
|
assertEquals(addr(0x1300), table.getTypeTable().getTypeInfoAddress(1));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testTwoByteTTypeOffset() throws Exception {
|
||||||
|
builder.setBytes("0x1000",
|
||||||
|
"ff 1b 80 01 01 78 " + "00 02 02 01 ".repeat(30) + "01 00 80 02 00 00");
|
||||||
|
|
||||||
|
LSDATable table = createTable();
|
||||||
|
|
||||||
|
assertEquals(addr(0x1083), table.getHeader().getTTypeBaseAddress());
|
||||||
|
assertEquals(addr(0x1300), table.getTypeTable().getTypeInfoAddress(1));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testThreeByteTTypeOffset() throws Exception {
|
||||||
|
builder.setBytes("0x1000", "ff 1b 80 80 01 01 00");
|
||||||
|
|
||||||
|
LSDAHeader header = new LSDAHeader(TaskMonitor.DUMMY, program, region());
|
||||||
|
int id = program.startTransaction("lsda");
|
||||||
|
try {
|
||||||
|
header.create(addr(0x1000));
|
||||||
|
}
|
||||||
|
finally {
|
||||||
|
program.endTransaction(id, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
assertEquals(addr(0x5004), header.getTTypeBaseAddress());
|
||||||
|
}
|
||||||
|
|
||||||
|
private LSDATable createTable() throws Exception {
|
||||||
|
RegionDescriptor region = region();
|
||||||
|
region.setLSDAAddress(addr(0x1000));
|
||||||
|
|
||||||
|
int id = program.startTransaction("lsda");
|
||||||
|
try {
|
||||||
|
LSDATable table = new LSDATable(TaskMonitor.DUMMY, program);
|
||||||
|
table.create(addr(0x1000), region);
|
||||||
|
return table;
|
||||||
|
}
|
||||||
|
finally {
|
||||||
|
program.endTransaction(id, true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private RegionDescriptor region() {
|
||||||
|
RegionDescriptor region = new RegionDescriptor(program.getMemory().getBlock(addr(0x1000)));
|
||||||
|
region.setIPRange(new AddressRangeImpl(addr(0x1000), addr(0x1100)));
|
||||||
|
return region;
|
||||||
|
}
|
||||||
|
|
||||||
|
private Address addr(long offset) {
|
||||||
|
return program.getAddressFactory().getDefaultAddressSpace().getAddress(offset);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,76 @@
|
|||||||
|
/* ###
|
||||||
|
* 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.app.plugin.exceptionhandlers.gcc.structures.gccexcepttable;
|
||||||
|
|
||||||
|
import static org.junit.Assert.*;
|
||||||
|
|
||||||
|
import org.junit.*;
|
||||||
|
|
||||||
|
import generic.test.AbstractGenericTest;
|
||||||
|
import ghidra.app.plugin.exceptionhandlers.gcc.RegionDescriptor;
|
||||||
|
import ghidra.program.database.ProgramBuilder;
|
||||||
|
import ghidra.program.model.address.*;
|
||||||
|
import ghidra.program.model.listing.Program;
|
||||||
|
import ghidra.util.task.TaskMonitor;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tests that an entry the type table cannot resolve costs only that entry. The type table is
|
||||||
|
* built last, so an exception escaping it would discard the call site and action tables that
|
||||||
|
* {@link LSDATable#create} has already finished.
|
||||||
|
*/
|
||||||
|
public class LSDATypeTableTest extends AbstractGenericTest {
|
||||||
|
|
||||||
|
private ProgramBuilder builder;
|
||||||
|
private Program program;
|
||||||
|
|
||||||
|
@Before
|
||||||
|
public void setUp() throws Exception {
|
||||||
|
builder = new ProgramBuilder("lsda", ProgramBuilder._X64);
|
||||||
|
builder.createMemory("lsda", "0x1000", 0x400);
|
||||||
|
program = builder.getProgram();
|
||||||
|
}
|
||||||
|
|
||||||
|
@After
|
||||||
|
public void tearDown() {
|
||||||
|
builder.dispose();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testUnresolvableTypeEntryKeepsCallSiteTable() throws Exception {
|
||||||
|
// the sole type table entry is a pc-relative displacement that leaves the address space
|
||||||
|
builder.setBytes("0x1000", "ff 1b 0d 01 04 00 02 02 01 01 00 00 01 00 00 80");
|
||||||
|
|
||||||
|
Address lsda = addr(0x1000);
|
||||||
|
RegionDescriptor region = new RegionDescriptor(program.getMemory().getBlock(lsda));
|
||||||
|
region.setIPRange(new AddressRangeImpl(lsda, addr(0x1100)));
|
||||||
|
region.setLSDAAddress(lsda);
|
||||||
|
|
||||||
|
LSDATable table = new LSDATable(TaskMonitor.DUMMY, program);
|
||||||
|
int id = program.startTransaction("lsda");
|
||||||
|
try {
|
||||||
|
table.create(lsda, region);
|
||||||
|
}
|
||||||
|
finally {
|
||||||
|
program.endTransaction(id, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
assertEquals(1, table.getCallSiteTable().getCallSiteRecords().size());
|
||||||
|
}
|
||||||
|
|
||||||
|
private Address addr(long offset) {
|
||||||
|
return program.getAddressFactory().getDefaultAddressSpace().getAddress(offset);
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user