Skip to content

Commit d9a9007

Browse files
committed
GP-4158 adjust how DWARF handles Rust
1 parent 2fa140f commit d9a9007

File tree

5 files changed

+57
-9
lines changed

5 files changed

+57
-9
lines changed

Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/analysis/DWARFAnalyzer.java

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717

1818
import java.io.IOException;
1919

20+
import ghidra.app.plugin.core.analysis.rust.RustUtilities;
2021
import ghidra.app.services.*;
2122
import ghidra.app.util.bin.format.dwarf4.DWARFException;
2223
import ghidra.app.util.bin.format.dwarf4.DWARFPreconditionException;
@@ -99,6 +100,11 @@ public boolean added(Program program, AddressSetView set, TaskMonitor monitor, M
99100
importOptions.setPreloadAllDIEs(true);
100101
}
101102

103+
if (RustUtilities.isRustProgram(program)) {
104+
Msg.info(this, "DWARF: Enabling DIE preload for Rust binary");
105+
importOptions.setPreloadAllDIEs(true);
106+
}
107+
102108
try {
103109
try (DWARFProgram prog = new DWARFProgram(program, importOptions, monitor, dsp)) {
104110
if (prog.getRegisterMappings() == null && importOptions.isImportFuncs()) {

Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/analysis/rust/RustUtilities.java

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,18 @@ public static boolean isRust(MemoryBlock block) throws IOException {
5858
return false;
5959
}
6060

61+
/**
62+
* Returns true if the given program has earlier been tagged as having a Rust compiler by
63+
* the loader.
64+
*
65+
* @param program {@link Program}
66+
* @return boolean true if program's compiler property includes rust
67+
*/
68+
public static boolean isRustProgram(Program program) {
69+
String name = program.getCompiler();
70+
return name != null && name.contains(RustConstants.RUST_COMPILER);
71+
}
72+
6173
public static int addExtensions(Program program, TaskMonitor monitor, String subPath)
6274
throws IOException {
6375
Processor processor = program.getLanguageCompilerSpecPair().getLanguage().getProcessor();

Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/analysis/rust/demangler/RustDemangler.java

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@
1515
*/
1616
package ghidra.app.plugin.core.analysis.rust.demangler;
1717

18-
import ghidra.app.plugin.core.analysis.rust.RustConstants;
18+
import ghidra.app.plugin.core.analysis.rust.RustUtilities;
1919
import ghidra.app.util.demangler.*;
2020
import ghidra.program.model.lang.CompilerSpec;
2121
import ghidra.program.model.listing.Program;
@@ -36,8 +36,7 @@ public DemanglerOptions createDefaultOptions() {
3636

3737
@Override
3838
public boolean canDemangle(Program program) {
39-
String name = program.getCompiler();
40-
return name != null && name.contains(RustConstants.RUST_COMPILER);
39+
return RustUtilities.isRustProgram(program);
4140
}
4241

4342
@Override

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

Lines changed: 29 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -15,28 +15,51 @@
1515
*/
1616
package ghidra.app.util.bin.format.dwarf4.funcfixup;
1717

18+
import java.io.IOException;
19+
1820
import ghidra.app.util.bin.format.dwarf4.DIEAggregate;
1921
import ghidra.app.util.bin.format.dwarf4.DWARFException;
2022
import ghidra.app.util.bin.format.dwarf4.encoding.DWARFSourceLanguage;
2123
import ghidra.app.util.bin.format.dwarf4.next.DWARFFunction;
24+
import ghidra.app.util.bin.format.dwarf4.next.DWARFFunction.CommitMode;
25+
import ghidra.program.database.data.ProgramBasedDataTypeManagerDB;
26+
import ghidra.program.model.lang.CompilerSpec;
27+
import ghidra.program.model.listing.Program;
2228
import ghidra.util.classfinder.ExtensionPointProperties;
29+
import ghidra.util.exception.InvalidInputException;
2330

2431
/**
25-
* Prevent functions in a Rust compile unit from incorrectly being locked down to an empty signature.
32+
* Adjust functions in a Rust compile unit to use Rust calling convention, ignore any information
33+
* about parameter storage locations.
2634
*/
2735
@ExtensionPointProperties(priority = DWARFFunctionFixup.PRIORITY_NORMAL_EARLY)
2836
public class RustDWARFFunctionFixup implements DWARFFunctionFixup {
37+
private String rustCC;
2938

3039
@Override
3140
public void fixupDWARFFunction(DWARFFunction dfunc) throws DWARFException {
3241
DIEAggregate diea = dfunc.diea;
3342
int cuLang = diea.getCompilationUnit().getCompileUnit().getLanguage();
34-
if (cuLang == DWARFSourceLanguage.DW_LANG_Rust && dfunc.params.isEmpty()) {
35-
// if there were no defined parameters and the language is Rust, don't force an
36-
// empty param signature. Rust language emit dwarf info without types (signatures)
37-
// when used without -g.
38-
throw new DWARFException("Rust empty param list" /* string doesnt matter */);
43+
if (cuLang == DWARFSourceLanguage.DW_LANG_Rust) {
44+
dfunc.callingConventionName = getRustCC(dfunc.getProgram().getGhidraProgram());
45+
dfunc.signatureCommitMode = CommitMode.FORMAL;
3946
}
47+
4048
}
4149

50+
private String getRustCC(Program program) throws DWARFException {
51+
if (rustCC == null) {
52+
rustCC = CompilerSpec.CALLING_CONVENTION_rustcall;
53+
try {
54+
// NOTE: this has a side effect of ensuring the rust cc is present in the program
55+
ProgramBasedDataTypeManagerDB dtm =
56+
(ProgramBasedDataTypeManagerDB) program.getDataTypeManager();
57+
dtm.getCallingConventionID(CompilerSpec.CALLING_CONVENTION_rustcall, false);
58+
}
59+
catch (InvalidInputException | IOException e) {
60+
throw new DWARFException("Unable to get Rust calling convention");
61+
}
62+
}
63+
return rustCC;
64+
}
4265
}

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

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -479,6 +479,14 @@ private DWARFNameInfo getDWARFNameInfo(DIEAggregate diea, DWARFNameInfo localRoo
479479
String workingName = ensureSafeNameLength(name);
480480
workingName = GoSymbolName.fixGolangSpecialSymbolnameChars(workingName);
481481

482+
if (diea.getCompilationUnit()
483+
.getCompileUnit()
484+
.getLanguage() == DWARFSourceLanguage.DW_LANG_Rust &&
485+
workingName.startsWith("{impl#") && parentDNI != null) {
486+
// if matches a Rust {impl#NN} name, skip it and re-use the parent name
487+
return parentDNI;
488+
}
489+
482490
DWARFNameInfo result =
483491
parentDNI.createChild(origName, workingName, DWARFUtil.getSymbolTypeFromDIE(diea));
484492
return result;

0 commit comments

Comments
 (0)