Merge remote-tracking branch 'origin/Ghidra_12.0'

This commit is contained in:
Ryan Kurtz
2025-11-17 06:26:58 -05:00
8 changed files with 50 additions and 30 deletions
@@ -130,6 +130,8 @@ public class GolangSymbolAnalyzer extends AbstractAnalyzer {
return false; return false;
} }
Msg.info(this, "Go version %s".formatted(goBinary.getGoVer()));
goTypes = goBinary.getGoTypes(); goTypes = goBinary.getGoTypes();
markupSession = goBinary.createMarkupSession(monitor); markupSession = goBinary.createMarkupSession(monitor);
@@ -31,6 +31,7 @@ import ghidra.app.util.bin.format.golang.GoVer;
import ghidra.formats.gfilesystem.FSRL; import ghidra.formats.gfilesystem.FSRL;
import ghidra.formats.gfilesystem.FileSystemService; import ghidra.formats.gfilesystem.FileSystemService;
import ghidra.framework.Application; import ghidra.framework.Application;
import ghidra.util.Msg;
import ghidra.util.exception.CancelledException; import ghidra.util.exception.CancelledException;
import ghidra.util.task.TaskMonitor; import ghidra.util.task.TaskMonitor;
@@ -124,30 +125,44 @@ public class GoApiSnapshot {
return null; return null;
} }
ByteProvider bp = null; File patchDiffFile = getPatchVerDiffFile(goVer);
if (goVer.getPatch() == 0) { if (patchDiffFile == null) {
// doesn't need diffpatching return fsService.getByteProvider(fsService.getLocalFSRL(jsonFile), false, monitor);
bp = fsService.getByteProvider(fsService.getLocalFSRL(jsonFile), false, monitor); }
FSRL fsrl = fsService.getFullyQualifiedFSRL(fsService.getLocalFSRL(jsonFile), monitor);
ByteProvider bp = fsService.getDerivedByteProviderPush(fsrl, null,
"go%s.json".formatted(goVer), -1, os -> {
JsonPatch jsonPatch = JsonPatch.read(patchDiffFile);
JsonPatchApplier jpa = new JsonPatchApplier(jsonFile);
monitor.initialize(jsonPatch.getSectionCount(),
"Patching Go API snapshot %s -> %s".formatted(baseVer, goVer));
jpa.apply(jsonPatch, monitor);
OutputStreamWriter osw = new OutputStreamWriter(os, StandardCharsets.UTF_8);
new Gson().toJson(jpa.getJson(), osw);
osw.flush(); // don't close outputstream, handled by caller
}, monitor);
return bp;
}
static File getPatchVerDiffFile(GoVer goVer) {
// returns the closest patch file that is present, or null if patch-ver-num is already 0
// or no patch diff files are found for the specified major.minor version.
GoVer patchVer = goVer;
File patchDiffFile = null;
while (patchVer.getPatch() > 0 &&
(patchDiffFile = getApiSnapshotFile(patchVer, "patchverdiffs/", ".diff")) == null) {
patchVer = patchVer.prevPatch();
}
if (patchVer.getPatch() != goVer.getPatch()) {
Msg.warn(GoApiSnapshot.class,
"Falling back from %s to %s for Go API snapshot".formatted(goVer, patchVer));
} }
else { else {
File patchDiffFile = getApiSnapshotFile(goVer, "patchverdiffs/", ".diff"); Msg.info(GoApiSnapshot.class, "Using Go API snapshot for %s".formatted(goVer));
if (patchDiffFile != null) {
FSRL fsrl =
fsService.getFullyQualifiedFSRL(fsService.getLocalFSRL(jsonFile), monitor);
bp = fsService.getDerivedByteProviderPush(fsrl, null,
"go%s.json".formatted(goVer), -1, os -> {
JsonPatch jsonPatch = JsonPatch.read(patchDiffFile);
JsonPatchApplier jpa = new JsonPatchApplier(jsonFile);
monitor.initialize(jsonPatch.getSectionCount(),
"Patching Go API snapshot %s -> %s".formatted(baseVer, goVer));
jpa.apply(jsonPatch, monitor);
OutputStreamWriter osw = new OutputStreamWriter(os, StandardCharsets.UTF_8);
new Gson().toJson(jpa.getJson(), osw);
osw.flush(); // don't close outputstream, handled by caller
}, monitor);
}
} }
return bp; return patchDiffFile;
} }
static File getApiSnapshotFile(GoVer goVer, String subdir, String suffix) { static File getApiSnapshotFile(GoVer goVer, String subdir, String suffix) {
@@ -189,7 +204,7 @@ public class GoApiSnapshot {
*/ */
private static GoApiSnapshot read(InputStream is, List<String> archNames, GoVer ver) private static GoApiSnapshot read(InputStream is, List<String> archNames, GoVer ver)
throws IOException { throws IOException {
Gson gson = new GsonBuilder() Gson gson = new GsonBuilder() // register postfix handler
.registerTypeAdapter(GoTypeDef.class, new GoTypeDefDeserializer()) .registerTypeAdapter(GoTypeDef.class, new GoTypeDefDeserializer())
.registerTypeAdapterFactory(new GsonPostFixupAdapter()) .registerTypeAdapterFactory(new GsonPostFixupAdapter())
.create(); .create();
@@ -418,6 +433,7 @@ public class GoApiSnapshot {
TypeParams = List.of(); TypeParams = List.of();
} }
} }
@Override @Override
public String toString() { public String toString() {
return "GoFuncTypeDef [Params=" + Params + ", Results=" + Results + ", TypeParams=" + return "GoFuncTypeDef [Params=" + Params + ", Results=" + Results + ", TypeParams=" +
@@ -155,7 +155,7 @@ public class GoRttiMapper extends DataTypeMapper implements DataTypeMapperContex
* @return new {@link GoRttiMapper}, or null if basic Go information is not found in the * @return new {@link GoRttiMapper}, or null if basic Go information is not found in the
* binary * binary
* @throws BootstrapInfoException if it is a Go binary and has an unsupported or * @throws BootstrapInfoException if it is a Go binary and has an unsupported or
* unparseable version number or if there was a missing Go bootstrap .gdt file * unparseable version number or if Go bootstrap info was missing
* @throws IOException if there was an error in the Ghidra Go RTTI reading logic * @throws IOException if there was an error in the Ghidra Go RTTI reading logic
*/ */
public static GoRttiMapper getGoBinary(Program program, TaskMonitor monitor) public static GoRttiMapper getGoBinary(Program program, TaskMonitor monitor)
@@ -326,9 +326,9 @@ public class GoRttiMapper extends DataTypeMapper implements DataTypeMapperContex
* @param goVer version of Go * @param goVer version of Go
* @param apiSnapshot json func signatures and data types * @param apiSnapshot json func signatures and data types
* @throws IOException if error linking a structure mapped structure to its matching * @throws IOException if error linking a structure mapped structure to its matching
* ghidra structure, which is a programming error or a corrupted bootstrap gdt * ghidra structure, which is a programming error or invalid bootstrap info
* @throws BootstrapInfoException if there is no matching bootstrap gdt for this specific * @throws BootstrapInfoException if there is no bootstrap info for this specific
* type of Go binary * type and version of Go binary
*/ */
public GoRttiMapper(Program program, GoBuildInfo buildInfo, int ptrSize, GoVer goVer, public GoRttiMapper(Program program, GoBuildInfo buildInfo, int ptrSize, GoVer goVer,
GoApiSnapshot apiSnapshot) throws IOException, BootstrapInfoException { GoApiSnapshot apiSnapshot) throws IOException, BootstrapInfoException {
@@ -452,7 +452,7 @@ public class SomDynamicLoaderHeader implements StructConverter {
} }
/** /**
* {@return the {@link List} of {@link SomExportEntryExt export entry extensions} * {@return the {@link List} of {@link SomExportEntryExt export entry extensions}}
*/ */
public List<SomExportEntryExt> getExportExtensions() { public List<SomExportEntryExt> getExportExtensions() {
return exportExtensions; return exportExtensions;
@@ -53,7 +53,7 @@ public class SomExportEntryExt implements StructConverter {
} }
/** /**
* {@return the size of the export symbol and is only valid for exports of type {@code ST_DATA} * {@return the size of the export symbol and is only valid for exports of type {@code ST_DATA}}
*/ */
public int getSize() { public int getSize() {
return size; return size;
@@ -2227,6 +2227,9 @@ public class DefaultPdbApplicator implements PdbApplicator {
//============================================================================================== //==============================================================================================
void predefineClass(SymbolPath classPath) { void predefineClass(SymbolPath classPath) {
if (classPath == null) {
return;
}
isClassByNamespace.put(classPath, true); isClassByNamespace.put(classPath, true);
for (SymbolPath path = classPath.getParent(); path != null; path = path.getParent()) { for (SymbolPath path = classPath.getParent(); path != null; path = path.getParent()) {
if (!isClassByNamespace.containsKey(path)) { if (!isClassByNamespace.containsKey(path)) {
@@ -95,7 +95,6 @@ public class ApplicationKeyStore {
/** /**
* Attempt to load a client/server keystore in a PKCS12 form (*.p12, *.pks, *.pfx) or * Attempt to load a client/server keystore in a PKCS12 form (*.p12, *.pks, *.pfx) or
* Java JKS (*.jks) form. * Java JKS (*.jks) form.
* @param path keystore file path
* @param pwd keystore password * @param pwd keystore password
* @return keystore instance * @return keystore instance
* @throws IOException * @throws IOException
@@ -1,6 +1,6 @@
distributionBase=GRADLE_USER_HOME distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-9.1.0-bin.zip distributionUrl=https\://services.gradle.org/distributions/gradle-9.2.0-bin.zip
networkTimeout=10000 networkTimeout=10000
validateDistributionUrl=true validateDistributionUrl=true
zipStoreBase=GRADLE_USER_HOME zipStoreBase=GRADLE_USER_HOME