GT-3330 DWARF address double relocation fixup

DWARF was applying a fixup value to address values in the DWARF data to
compensate for the Ghidra base-address being different than the
program's requested base address.

In binaries (mostly .o files) that contain Elf fixups that reach into
the DWARF debug sections and rewrite the address values, the Ghidra
importer would handle fixing the address values to point to the
non-standard Ghidra base-address, and then the global fixup would be
applied to the already correct value, causing it to be incorrect.

This change checks to see if any relocations are present in the DWARF
debug data and disables its address fixups if found.
This commit is contained in:
dev747368 2019-11-29 16:05:04 -05:00
parent 76bd653deb
commit c7cdaaf07a
3 changed files with 47 additions and 18 deletions

View file

@ -46,6 +46,17 @@ public class MemoryByteProvider implements ByteProvider {
this.baseAddress = baseAddress;
}
/**
* Converts an index into this ByteProvider into an {@link Address}.
* <p>
*
* @param index absolute index in this ByteProvider to convert into an Address
* @return {@link Address}
*/
public Address getAddress(long index) {
return baseAddress.add(index);
}
@Override
public InputStream getInputStream(long index) throws IOException {
return new MemoryByteProviderInputStream(memory, baseAddress.add(index));

View file

@ -21,7 +21,6 @@ import java.util.*;
import org.apache.commons.lang3.ArrayUtils;
import ghidra.app.util.bin.BinaryReader;
import ghidra.app.util.bin.ByteProvider;
import ghidra.app.util.bin.format.dwarf4.attribs.*;
import ghidra.app.util.bin.format.dwarf4.encoding.*;
import ghidra.app.util.bin.format.dwarf4.expression.*;
@ -804,10 +803,7 @@ public class DIEAggregate {
*/
public List<DWARFRange> parseDebugRange(int attribute) throws IOException {
byte pointerSize = getCompilationUnit().getPointerSize();
boolean isLittleEndian = getCompilationUnit().getProgram().isLittleEndian();
ByteProvider debug_ranges = getCompilationUnit().getProgram().getDebugRanges();
BinaryReader reader = new BinaryReader(debug_ranges, isLittleEndian);
BinaryReader reader = getCompilationUnit().getProgram().getDebugRanges();
long offset = getUnsignedLong(attribute, -1);
if (offset == -1) {

View file

@ -22,8 +22,7 @@ import java.util.*;
import org.apache.commons.collections4.ListValuedMap;
import org.apache.commons.collections4.multimap.ArrayListValuedHashMap;
import ghidra.app.util.bin.BinaryReader;
import ghidra.app.util.bin.ByteProvider;
import ghidra.app.util.bin.*;
import ghidra.app.util.bin.format.dwarf4.*;
import ghidra.app.util.bin.format.dwarf4.attribs.DWARFAttributeFactory;
import ghidra.app.util.bin.format.dwarf4.encoding.*;
@ -31,6 +30,8 @@ import ghidra.app.util.bin.format.dwarf4.expression.DWARFExpressionException;
import ghidra.app.util.bin.format.dwarf4.next.sectionprovider.*;
import ghidra.app.util.opinion.ElfLoader;
import ghidra.app.util.opinion.MachoLoader;
import ghidra.program.model.address.Address;
import ghidra.program.model.address.AddressSet;
import ghidra.program.model.data.CategoryPath;
import ghidra.program.model.listing.Program;
import ghidra.program.model.symbol.SymbolUtilities;
@ -108,7 +109,7 @@ public class DWARFProgram implements Closeable {
new HashMap<>();
private BinaryReader debugLocation;
private ByteProvider debugRanges;
private BinaryReader debugRanges;
private BinaryReader debugInfoBR;
private BinaryReader debugLineBR;
private BinaryReader debugAbbrBR;
@ -185,10 +186,7 @@ public class DWARFProgram implements Closeable {
this.importOptions = importOptions;
this.nameLengthCutoffSize = Math.max(MIN_NAME_LENGTH_CUTOFF,
Math.min(importOptions.getNameLengthCutoff(), MAX_NAME_LENGTH_CUTOFF));
Long oib = ElfLoader.getElfOriginalImageBase(program);
if (oib != null && oib.longValue() != program.getImageBase().getOffset()) {
this.programBaseAddressFixup = program.getImageBase().getOffset() - oib.longValue();
}
monitor.setMessage("Reading DWARF debug string table");
this.debugStrings = StringTable.readStringTable(
@ -201,7 +199,17 @@ public class DWARFProgram implements Closeable {
this.debugInfoBR = getBinaryReaderFor(DWARFSectionNames.DEBUG_INFO);
this.debugLineBR = getBinaryReaderFor(DWARFSectionNames.DEBUG_LINE);
this.debugAbbrBR = getBinaryReaderFor(DWARFSectionNames.DEBUG_ABBREV);
this.debugRanges = sectionProvider.getSectionAsByteProvider(DWARFSectionNames.DEBUG_RANGES);
this.debugRanges = getBinaryReaderFor(DWARFSectionNames.DEBUG_RANGES);// sectionProvider.getSectionAsByteProvider(DWARFSectionNames.DEBUG_RANGES);
// if there are relocations (already handled by the ghidra loader) anywhere in the debuginfo or debugrange sections, then
// we don't need to manually fix up addresses extracted from DWARF data.
boolean hasRelocations = hasRelocations(debugInfoBR) || hasRelocations(debugRanges);
if (!hasRelocations) {
Long oib = ElfLoader.getElfOriginalImageBase(program);
if (oib != null && oib.longValue() != program.getImageBase().getOffset()) {
this.programBaseAddressFixup = program.getImageBase().getOffset() - oib.longValue();
}
}
dwarfRegisterMappings =
DWARFRegisterMappingsManager.hasDWARFRegisterMapping(program.getLanguage())
@ -219,10 +227,7 @@ public class DWARFProgram implements Closeable {
debugInfoBR = null;
debugLineBR = null;
debugLocation = null;
if (debugRanges != null) {
debugRanges.close();
debugRanges = null;
}
debugStrings.clear();
dniCache.clear();
clearDIEIndexes();
@ -249,6 +254,23 @@ public class DWARFProgram implements Closeable {
return (bp != null) ? new BinaryReader(bp, !isBigEndian()) : null;
}
private boolean hasRelocations(BinaryReader br) throws IOException {
if (br == null) {
return false;
}
ByteProvider bp = br.getByteProvider();
if (bp instanceof MemoryByteProvider && bp.length() > 0) {
MemoryByteProvider mbp = (MemoryByteProvider) bp;
Address startAddr = mbp.getAddress(0);
Address endAddr = mbp.getAddress(mbp.length() - 1);
if (program.getRelocationTable().getRelocations(
new AddressSet(startAddr, endAddr)).hasNext()) {
return true;
}
}
return false;
}
//-------------------------------------------------------------------------
private static boolean isAnonDWARFName(String name) {
return (name == null) || name.startsWith("._") || name.startsWith("<anonymous");
@ -594,7 +616,7 @@ public class DWARFProgram implements Closeable {
return debugLocation;
}
public ByteProvider getDebugRanges() {
public BinaryReader getDebugRanges() {
return debugRanges;
}