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;
}
Msg.info(this, "Go version %s".formatted(goBinary.getGoVer()));
goTypes = goBinary.getGoTypes();
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.FileSystemService;
import ghidra.framework.Application;
import ghidra.util.Msg;
import ghidra.util.exception.CancelledException;
import ghidra.util.task.TaskMonitor;
@@ -124,30 +125,44 @@ public class GoApiSnapshot {
return null;
}
ByteProvider bp = null;
if (goVer.getPatch() == 0) {
// doesn't need diffpatching
bp = fsService.getByteProvider(fsService.getLocalFSRL(jsonFile), false, monitor);
File patchDiffFile = getPatchVerDiffFile(goVer);
if (patchDiffFile == null) {
return 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 {
File patchDiffFile = getApiSnapshotFile(goVer, "patchverdiffs/", ".diff");
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);
}
Msg.info(GoApiSnapshot.class, "Using Go API snapshot for %s".formatted(goVer));
}
return bp;
return patchDiffFile;
}
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)
throws IOException {
Gson gson = new GsonBuilder()
Gson gson = new GsonBuilder() // register postfix handler
.registerTypeAdapter(GoTypeDef.class, new GoTypeDefDeserializer())
.registerTypeAdapterFactory(new GsonPostFixupAdapter())
.create();
@@ -418,6 +433,7 @@ public class GoApiSnapshot {
TypeParams = List.of();
}
}
@Override
public String toString() {
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
* binary
* @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
*/
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 apiSnapshot json func signatures and data types
* @throws IOException if error linking a structure mapped structure to its matching
* ghidra structure, which is a programming error or a corrupted bootstrap gdt
* @throws BootstrapInfoException if there is no matching bootstrap gdt for this specific
* type of Go binary
* ghidra structure, which is a programming error or invalid bootstrap info
* @throws BootstrapInfoException if there is no bootstrap info for this specific
* type and version of Go binary
*/
public GoRttiMapper(Program program, GoBuildInfo buildInfo, int ptrSize, GoVer goVer,
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() {
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() {
return size;
@@ -2227,6 +2227,9 @@ public class DefaultPdbApplicator implements PdbApplicator {
//==============================================================================================
void predefineClass(SymbolPath classPath) {
if (classPath == null) {
return;
}
isClassByNamespace.put(classPath, true);
for (SymbolPath path = classPath.getParent(); path != null; path = path.getParent()) {
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
* Java JKS (*.jks) form.
* @param path keystore file path
* @param pwd keystore password
* @return keystore instance
* @throws IOException
@@ -1,6 +1,6 @@
distributionBase=GRADLE_USER_HOME
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
validateDistributionUrl=true
zipStoreBase=GRADLE_USER_HOME