Skip to content

Commit c7cdaaf

Browse files
committed
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.
1 parent 76bd653 commit c7cdaaf

File tree

3 files changed

+47
-18
lines changed

3 files changed

+47
-18
lines changed

Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/MemoryByteProvider.java

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,17 @@ public MemoryByteProvider(Memory memory, Address baseAddress) {
4646
this.baseAddress = baseAddress;
4747
}
4848

49+
/**
50+
* Converts an index into this ByteProvider into an {@link Address}.
51+
* <p>
52+
*
53+
* @param index absolute index in this ByteProvider to convert into an Address
54+
* @return {@link Address}
55+
*/
56+
public Address getAddress(long index) {
57+
return baseAddress.add(index);
58+
}
59+
4960
@Override
5061
public InputStream getInputStream(long index) throws IOException {
5162
return new MemoryByteProviderInputStream(memory, baseAddress.add(index));

Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/dwarf4/DIEAggregate.java

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,6 @@
2121
import org.apache.commons.lang3.ArrayUtils;
2222

2323
import ghidra.app.util.bin.BinaryReader;
24-
import ghidra.app.util.bin.ByteProvider;
2524
import ghidra.app.util.bin.format.dwarf4.attribs.*;
2625
import ghidra.app.util.bin.format.dwarf4.encoding.*;
2726
import ghidra.app.util.bin.format.dwarf4.expression.*;
@@ -804,10 +803,7 @@ public String toString() {
804803
*/
805804
public List<DWARFRange> parseDebugRange(int attribute) throws IOException {
806805
byte pointerSize = getCompilationUnit().getPointerSize();
807-
boolean isLittleEndian = getCompilationUnit().getProgram().isLittleEndian();
808-
809-
ByteProvider debug_ranges = getCompilationUnit().getProgram().getDebugRanges();
810-
BinaryReader reader = new BinaryReader(debug_ranges, isLittleEndian);
806+
BinaryReader reader = getCompilationUnit().getProgram().getDebugRanges();
811807

812808
long offset = getUnsignedLong(attribute, -1);
813809
if (offset == -1) {

Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/dwarf4/next/DWARFProgram.java

Lines changed: 35 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -22,15 +22,16 @@
2222
import org.apache.commons.collections4.ListValuedMap;
2323
import org.apache.commons.collections4.multimap.ArrayListValuedHashMap;
2424

25-
import ghidra.app.util.bin.BinaryReader;
26-
import ghidra.app.util.bin.ByteProvider;
25+
import ghidra.app.util.bin.*;
2726
import ghidra.app.util.bin.format.dwarf4.*;
2827
import ghidra.app.util.bin.format.dwarf4.attribs.DWARFAttributeFactory;
2928
import ghidra.app.util.bin.format.dwarf4.encoding.*;
3029
import ghidra.app.util.bin.format.dwarf4.expression.DWARFExpressionException;
3130
import ghidra.app.util.bin.format.dwarf4.next.sectionprovider.*;
3231
import ghidra.app.util.opinion.ElfLoader;
3332
import ghidra.app.util.opinion.MachoLoader;
33+
import ghidra.program.model.address.Address;
34+
import ghidra.program.model.address.AddressSet;
3435
import ghidra.program.model.data.CategoryPath;
3536
import ghidra.program.model.listing.Program;
3637
import ghidra.program.model.symbol.SymbolUtilities;
@@ -108,7 +109,7 @@ else if (MachoLoader.MACH_O_NAME.equals(format) &&
108109
new HashMap<>();
109110

110111
private BinaryReader debugLocation;
111-
private ByteProvider debugRanges;
112+
private BinaryReader debugRanges;
112113
private BinaryReader debugInfoBR;
113114
private BinaryReader debugLineBR;
114115
private BinaryReader debugAbbrBR;
@@ -185,10 +186,7 @@ public DWARFProgram(Program program, DWARFImportOptions importOptions, TaskMonit
185186
this.importOptions = importOptions;
186187
this.nameLengthCutoffSize = Math.max(MIN_NAME_LENGTH_CUTOFF,
187188
Math.min(importOptions.getNameLengthCutoff(), MAX_NAME_LENGTH_CUTOFF));
188-
Long oib = ElfLoader.getElfOriginalImageBase(program);
189-
if (oib != null && oib.longValue() != program.getImageBase().getOffset()) {
190-
this.programBaseAddressFixup = program.getImageBase().getOffset() - oib.longValue();
191-
}
189+
192190

193191
monitor.setMessage("Reading DWARF debug string table");
194192
this.debugStrings = StringTable.readStringTable(
@@ -201,7 +199,17 @@ public DWARFProgram(Program program, DWARFImportOptions importOptions, TaskMonit
201199
this.debugInfoBR = getBinaryReaderFor(DWARFSectionNames.DEBUG_INFO);
202200
this.debugLineBR = getBinaryReaderFor(DWARFSectionNames.DEBUG_LINE);
203201
this.debugAbbrBR = getBinaryReaderFor(DWARFSectionNames.DEBUG_ABBREV);
204-
this.debugRanges = sectionProvider.getSectionAsByteProvider(DWARFSectionNames.DEBUG_RANGES);
202+
this.debugRanges = getBinaryReaderFor(DWARFSectionNames.DEBUG_RANGES);// sectionProvider.getSectionAsByteProvider(DWARFSectionNames.DEBUG_RANGES);
203+
204+
// if there are relocations (already handled by the ghidra loader) anywhere in the debuginfo or debugrange sections, then
205+
// we don't need to manually fix up addresses extracted from DWARF data.
206+
boolean hasRelocations = hasRelocations(debugInfoBR) || hasRelocations(debugRanges);
207+
if (!hasRelocations) {
208+
Long oib = ElfLoader.getElfOriginalImageBase(program);
209+
if (oib != null && oib.longValue() != program.getImageBase().getOffset()) {
210+
this.programBaseAddressFixup = program.getImageBase().getOffset() - oib.longValue();
211+
}
212+
}
205213

206214
dwarfRegisterMappings =
207215
DWARFRegisterMappingsManager.hasDWARFRegisterMapping(program.getLanguage())
@@ -219,10 +227,7 @@ public void close() throws IOException {
219227
debugInfoBR = null;
220228
debugLineBR = null;
221229
debugLocation = null;
222-
if (debugRanges != null) {
223-
debugRanges.close();
224-
debugRanges = null;
225-
}
230+
debugRanges = null;
226231
debugStrings.clear();
227232
dniCache.clear();
228233
clearDIEIndexes();
@@ -249,6 +254,23 @@ private BinaryReader getBinaryReaderFor(String sectionName) throws IOException {
249254
return (bp != null) ? new BinaryReader(bp, !isBigEndian()) : null;
250255
}
251256

257+
private boolean hasRelocations(BinaryReader br) throws IOException {
258+
if (br == null) {
259+
return false;
260+
}
261+
ByteProvider bp = br.getByteProvider();
262+
if (bp instanceof MemoryByteProvider && bp.length() > 0) {
263+
MemoryByteProvider mbp = (MemoryByteProvider) bp;
264+
Address startAddr = mbp.getAddress(0);
265+
Address endAddr = mbp.getAddress(mbp.length() - 1);
266+
if (program.getRelocationTable().getRelocations(
267+
new AddressSet(startAddr, endAddr)).hasNext()) {
268+
return true;
269+
}
270+
}
271+
return false;
272+
}
273+
252274
//-------------------------------------------------------------------------
253275
private static boolean isAnonDWARFName(String name) {
254276
return (name == null) || name.startsWith("._") || name.startsWith("<anonymous");
@@ -594,7 +616,7 @@ public BinaryReader getDebugLocation() {
594616
return debugLocation;
595617
}
596618

597-
public ByteProvider getDebugRanges() {
619+
public BinaryReader getDebugRanges() {
598620
return debugRanges;
599621
}
600622

0 commit comments

Comments
 (0)