mirror of
https://github.com/NationalSecurityAgency/ghidra.git
synced 2025-10-06 12:00:04 +02:00
Merge remote-tracking branch
'origin/GP-4183_dev747368_PR-6072_astrelsky_golang_1.21' (Closes #6072)
This commit is contained in:
commit
676e60f71b
29 changed files with 219 additions and 138 deletions
|
@ -91,6 +91,7 @@ data/typeinfo/golang/golang_1.17_anybit_any.gdt||GHIDRA||||END|
|
||||||
data/typeinfo/golang/golang_1.18_anybit_any.gdt||GHIDRA||||END|
|
data/typeinfo/golang/golang_1.18_anybit_any.gdt||GHIDRA||||END|
|
||||||
data/typeinfo/golang/golang_1.19_anybit_any.gdt||GHIDRA||||END|
|
data/typeinfo/golang/golang_1.19_anybit_any.gdt||GHIDRA||||END|
|
||||||
data/typeinfo/golang/golang_1.20_anybit_any.gdt||GHIDRA||||END|
|
data/typeinfo/golang/golang_1.20_anybit_any.gdt||GHIDRA||||END|
|
||||||
|
data/typeinfo/golang/golang_1.21_anybit_any.gdt||GHIDRA||||END|
|
||||||
data/typeinfo/golang/runtimesnapshot.go||GHIDRA||||END|
|
data/typeinfo/golang/runtimesnapshot.go||GHIDRA||||END|
|
||||||
data/typeinfo/mac_10.9/mac_osx.gdt||GHIDRA||||END|
|
data/typeinfo/mac_10.9/mac_osx.gdt||GHIDRA||||END|
|
||||||
data/typeinfo/rust/rust-common.gdt||GHIDRA||||END|
|
data/typeinfo/rust/rust-common.gdt||GHIDRA||||END|
|
||||||
|
|
Binary file not shown.
|
@ -99,7 +99,7 @@ public class GolangStringAnalyzer extends AbstractAnalyzer {
|
||||||
|
|
||||||
goBinary = GoRttiMapper.getSharedGoBinary(program, monitor);
|
goBinary = GoRttiMapper.getSharedGoBinary(program, monitor);
|
||||||
if (goBinary == null) {
|
if (goBinary == null) {
|
||||||
Msg.error(this, "Golang analyzer error: unable to get GoRttiMapper");
|
Msg.error(this, "Golang string analyzer error: unable to get GoRttiMapper");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
markupSession = goBinary.createMarkupSession(monitor);
|
markupSession = goBinary.createMarkupSession(monitor);
|
||||||
|
|
|
@ -112,7 +112,7 @@ public class GolangSymbolAnalyzer extends AbstractAnalyzer {
|
||||||
|
|
||||||
goBinary = GoRttiMapper.getSharedGoBinary(program, monitor);
|
goBinary = GoRttiMapper.getSharedGoBinary(program, monitor);
|
||||||
if (goBinary == null) {
|
if (goBinary == null) {
|
||||||
Msg.error(this, "Golang analyzer error: unable to get GoRttiMapper");
|
Msg.error(this, "Golang symbol analyzer error: unable to get GoRttiMapper");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -136,6 +136,7 @@ public class GolangSymbolAnalyzer extends AbstractAnalyzer {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (analyzerOptions.propagateRtti) {
|
if (analyzerOptions.propagateRtti) {
|
||||||
|
Msg.info(this, "Golang symbol analyzer: scheduling RTTI propagation after reference analysis");
|
||||||
aam.schedule(new PropagateRttiBackgroundCommand(goBinary),
|
aam.schedule(new PropagateRttiBackgroundCommand(goBinary),
|
||||||
AnalysisPriority.REFERENCE_ANALYSIS.after().priority());
|
AnalysisPriority.REFERENCE_ANALYSIS.after().priority());
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,38 @@
|
||||||
|
/* ###
|
||||||
|
* IP: GHIDRA
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
package ghidra.app.util.bin.format.golang;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
|
||||||
|
public class BootstrapInfoException extends IOException {
|
||||||
|
|
||||||
|
public BootstrapInfoException() {
|
||||||
|
// empty
|
||||||
|
}
|
||||||
|
|
||||||
|
public BootstrapInfoException(String message) {
|
||||||
|
super(message);
|
||||||
|
}
|
||||||
|
|
||||||
|
public BootstrapInfoException(Throwable cause) {
|
||||||
|
super(cause);
|
||||||
|
}
|
||||||
|
|
||||||
|
public BootstrapInfoException(String message, Throwable cause) {
|
||||||
|
super(message, cause);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -28,12 +28,14 @@ public enum GoVer {
|
||||||
V1_17(1, 17),
|
V1_17(1, 17),
|
||||||
V1_18(1, 18),
|
V1_18(1, 18),
|
||||||
V1_19(1, 19),
|
V1_19(1, 19),
|
||||||
V1_20(1, 20);
|
V1_20(1, 20),
|
||||||
|
V1_21(1, 21),
|
||||||
|
V1_22(1, 22);
|
||||||
|
|
||||||
private final int major;
|
private final int major;
|
||||||
private final int minor;
|
private final int minor;
|
||||||
|
|
||||||
private GoVer(int major, int minor) {
|
GoVer(int major, int minor) {
|
||||||
this.major = major;
|
this.major = major;
|
||||||
this.minor = minor;
|
this.minor = minor;
|
||||||
}
|
}
|
||||||
|
@ -89,7 +91,7 @@ public enum GoVer {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch (NumberFormatException e) {
|
catch (NumberFormatException e) {
|
||||||
return UNKNOWN;
|
// fall thru, return unknown
|
||||||
}
|
}
|
||||||
return UNKNOWN;
|
return UNKNOWN;
|
||||||
}
|
}
|
||||||
|
|
|
@ -112,54 +112,63 @@ public class GoRttiMapper extends DataTypeMapper {
|
||||||
GoRttiMapper supplier_result = getGoBinary(program);
|
GoRttiMapper supplier_result = getGoBinary(program);
|
||||||
if (supplier_result != null) {
|
if (supplier_result != null) {
|
||||||
supplier_result.init(monitor);
|
supplier_result.init(monitor);
|
||||||
|
return supplier_result;
|
||||||
}
|
}
|
||||||
return supplier_result;
|
|
||||||
}
|
}
|
||||||
catch (IllegalArgumentException | IOException e) {
|
catch (BootstrapInfoException mbie) {
|
||||||
TransientProgramProperties.getProperty(program, FAILED_FLAG,
|
Msg.warn(GoRttiMapper.class, mbie.getMessage());
|
||||||
TransientProgramProperties.SCOPE.PROGRAM, Boolean.class, () -> true); // also sets it
|
logAnalyzerMsg(program, mbie.getMessage());
|
||||||
|
|
||||||
if (e instanceof IOException) {
|
|
||||||
// this is a more serious error, and the stack trace should be written
|
|
||||||
// to the application log
|
|
||||||
Msg.error(GoRttiMapper.class,
|
|
||||||
"Failed to read golang info for: " + program.getName(), e);
|
|
||||||
|
|
||||||
}
|
|
||||||
AutoAnalysisManager aam = AutoAnalysisManager.getAnalysisManager(program);
|
|
||||||
if (aam.isAnalyzing()) {
|
|
||||||
// should cause a modal popup at end of analysis that the go binary wasn't
|
|
||||||
// supported
|
|
||||||
MessageLog log = aam.getMessageLog();
|
|
||||||
log.appendMsg(e.getMessage());
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
Msg.warn(GoRttiMapper.class, "Golang program: " + e.getMessage());
|
|
||||||
}
|
|
||||||
|
|
||||||
return null;
|
|
||||||
}
|
}
|
||||||
|
catch (IOException e) {
|
||||||
|
// this is a more serious error, and the stack trace should be written
|
||||||
|
// to the application log
|
||||||
|
Msg.error(GoRttiMapper.class, "Failed to read golang info", e);
|
||||||
|
logAnalyzerMsg(program, e.getMessage());
|
||||||
|
}
|
||||||
|
|
||||||
|
// this sets the failed flag
|
||||||
|
TransientProgramProperties.getProperty(program, FAILED_FLAG,
|
||||||
|
TransientProgramProperties.SCOPE.PROGRAM, Boolean.class, () -> true);
|
||||||
|
|
||||||
|
return null;
|
||||||
});
|
});
|
||||||
|
|
||||||
return goBinary;
|
return goBinary;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static void logAnalyzerMsg(Program program, String msg) {
|
||||||
|
AutoAnalysisManager aam = AutoAnalysisManager.getAnalysisManager(program);
|
||||||
|
if (aam.isAnalyzing()) {
|
||||||
|
// should cause a modal popup at end of analysis that will show the message
|
||||||
|
MessageLog log = aam.getMessageLog();
|
||||||
|
log.appendMsg(msg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a {@link GoRttiMapper} representing the specified program.
|
* Creates a {@link GoRttiMapper} representing the specified program.
|
||||||
*
|
*
|
||||||
* @param program {@link Program}
|
* @param program {@link Program}
|
||||||
* @return new {@link GoRttiMapper}, or null if basic golang information is not found in the
|
* @return new {@link GoRttiMapper}, or null if basic golang information is not found in the
|
||||||
* binary
|
* binary
|
||||||
* @throws IllegalArgumentException if the golang binary is an unsupported version
|
* @throws BootstrapInfoException if it is a golang binary and has an unsupported or
|
||||||
|
* unparseable version number or if there was a missing golang bootstrap .gdt file
|
||||||
* @throws IOException if there was an error in the Ghidra golang rtti reading logic
|
* @throws IOException if there was an error in the Ghidra golang rtti reading logic
|
||||||
*/
|
*/
|
||||||
public static GoRttiMapper getGoBinary(Program program)
|
public static GoRttiMapper getGoBinary(Program program)
|
||||||
throws IllegalArgumentException, IOException {
|
throws BootstrapInfoException, IOException {
|
||||||
GoBuildInfo buildInfo = GoBuildInfo.fromProgram(program);
|
GoBuildInfo buildInfo = GoBuildInfo.fromProgram(program);
|
||||||
GoVer goVer;
|
if (buildInfo == null) {
|
||||||
if (buildInfo == null || (goVer = buildInfo.getVerEnum()) == GoVer.UNKNOWN) {
|
// probably not a golang binary
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
GoVer goVer = buildInfo.getVerEnum();
|
||||||
|
if (goVer == GoVer.UNKNOWN) {
|
||||||
|
throw new BootstrapInfoException(
|
||||||
|
"Unsupported Golang version, version info: '%s'".formatted(buildInfo.getVersion()));
|
||||||
|
}
|
||||||
|
|
||||||
ResourceFile gdtFile =
|
ResourceFile gdtFile =
|
||||||
findGolangBootstrapGDT(goVer, buildInfo.getPointerSize(), getGolangOSString(program));
|
findGolangBootstrapGDT(goVer, buildInfo.getPointerSize(), getGolangOSString(program));
|
||||||
if (gdtFile == null) {
|
if (gdtFile == null) {
|
||||||
|
@ -324,11 +333,11 @@ public class GoRttiMapper extends DataTypeMapper {
|
||||||
* if not present and types recovered via DWARF should be used instead
|
* if not present and types recovered via DWARF should be used instead
|
||||||
* @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 a corrupted bootstrap gdt
|
||||||
* @throws IllegalArgumentException if there is no matching bootstrap gdt for this specific
|
* @throws BootstrapInfoException if there is no matching bootstrap gdt for this specific
|
||||||
* type of golang binary
|
* type of golang binary
|
||||||
*/
|
*/
|
||||||
public GoRttiMapper(Program program, int ptrSize, Endian endian, GoVer goVersion,
|
public GoRttiMapper(Program program, int ptrSize, Endian endian, GoVer goVersion,
|
||||||
ResourceFile archiveGDT) throws IOException, IllegalArgumentException {
|
ResourceFile archiveGDT) throws IOException, BootstrapInfoException {
|
||||||
super(program, archiveGDT);
|
super(program, archiveGDT);
|
||||||
|
|
||||||
this.goVersion = goVersion;
|
this.goVersion = goVersion;
|
||||||
|
@ -357,13 +366,15 @@ public class GoRttiMapper extends DataTypeMapper {
|
||||||
if (archiveGDT == null) {
|
if (archiveGDT == null) {
|
||||||
// a normal'ish situation where there isn't a .gdt for this arch/binary and there
|
// a normal'ish situation where there isn't a .gdt for this arch/binary and there
|
||||||
// isn't any DWARF.
|
// isn't any DWARF.
|
||||||
throw new IllegalArgumentException(
|
throw new BootstrapInfoException(
|
||||||
"Missing golang .gdt archive for %s, no fallback DWARF info, unable to extract golang RTTI info."
|
"Missing golang .gdt archive for %s, no fallback DWARF info, unable to extract Golang RTTI info."
|
||||||
.formatted(goVersion));
|
.formatted(goVersion));
|
||||||
}
|
}
|
||||||
// a bad situation where the data type info is corrupted
|
|
||||||
throw new IOException("Invalid or missing Golang bootstrap GDT file: %s"
|
// we have a .gdt, but something failed.
|
||||||
.formatted(archiveGDT.getAbsolutePath()));
|
throw new IOException("Invalid Golang bootstrap GDT file or struct mapping info: %s"
|
||||||
|
.formatted(archiveGDT.getAbsolutePath()),
|
||||||
|
e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -26,7 +26,7 @@ import ghidra.program.model.data.DataType;
|
||||||
/**
|
/**
|
||||||
* {@link GoType} structure that defines an array.
|
* {@link GoType} structure that defines an array.
|
||||||
*/
|
*/
|
||||||
@StructureMapping(structureName = "runtime.arraytype")
|
@StructureMapping(structureName = {"runtime.arraytype", "internal/abi.ArrayType"})
|
||||||
public class GoArrayType extends GoType {
|
public class GoArrayType extends GoType {
|
||||||
|
|
||||||
@FieldMapping
|
@FieldMapping
|
||||||
|
|
|
@ -35,7 +35,7 @@ import ghidra.app.util.bin.format.golang.structmapping.*;
|
||||||
* struct specialized_type { basetype_struct; (various_fields)* } struct uncommon;
|
* struct specialized_type { basetype_struct; (various_fields)* } struct uncommon;
|
||||||
* </pre>
|
* </pre>
|
||||||
*/
|
*/
|
||||||
@StructureMapping(structureName = "runtime._type")
|
@StructureMapping(structureName = {"runtime._type", "internal/abi.Type"})
|
||||||
public class GoBaseType {
|
public class GoBaseType {
|
||||||
|
|
||||||
@ContextField
|
@ContextField
|
||||||
|
@ -44,17 +44,17 @@ public class GoBaseType {
|
||||||
@ContextField
|
@ContextField
|
||||||
private GoRttiMapper programContext;
|
private GoRttiMapper programContext;
|
||||||
|
|
||||||
@FieldMapping(signedness = Signedness.Unsigned)
|
@FieldMapping(fieldName = {"size", "Size_"}, signedness = Signedness.Unsigned)
|
||||||
private long size;
|
private long size;
|
||||||
|
|
||||||
@FieldMapping
|
@FieldMapping(fieldName = {"ptrdata", "PtrBytes"})
|
||||||
private long ptrdata;
|
private long ptrdata;
|
||||||
|
|
||||||
@FieldMapping
|
@FieldMapping
|
||||||
@EOLComment("flags")
|
@EOLComment("flags")
|
||||||
private int tflag;
|
private int tflag;
|
||||||
|
|
||||||
@FieldMapping
|
@FieldMapping(fieldName = {"kind", "Kind_"})
|
||||||
@EOLComment
|
@EOLComment
|
||||||
private int kind;
|
private int kind;
|
||||||
|
|
||||||
|
|
|
@ -25,7 +25,7 @@ import ghidra.util.Msg;
|
||||||
/**
|
/**
|
||||||
* A {@link GoType} structure that defines a go channel
|
* A {@link GoType} structure that defines a go channel
|
||||||
*/
|
*/
|
||||||
@StructureMapping(structureName = "runtime.chantype")
|
@StructureMapping(structureName = {"runtime.chantype", "internal/abi.ChanType"})
|
||||||
public class GoChanType extends GoType {
|
public class GoChanType extends GoType {
|
||||||
|
|
||||||
@FieldMapping
|
@FieldMapping
|
||||||
|
|
|
@ -27,7 +27,7 @@ import ghidra.program.model.data.*;
|
||||||
/**
|
/**
|
||||||
* A {@link GoType} structure that defines a function type.
|
* A {@link GoType} structure that defines a function type.
|
||||||
*/
|
*/
|
||||||
@StructureMapping(structureName = "runtime.functype")
|
@StructureMapping(structureName = {"runtime.functype", "internal/abi.FuncType"})
|
||||||
public class GoFuncType extends GoType {
|
public class GoFuncType extends GoType {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -22,7 +22,7 @@ import ghidra.app.util.bin.format.golang.structmapping.*;
|
||||||
import ghidra.program.model.address.Address;
|
import ghidra.program.model.address.Address;
|
||||||
import ghidra.program.model.data.FunctionDefinition;
|
import ghidra.program.model.data.FunctionDefinition;
|
||||||
|
|
||||||
@StructureMapping(structureName = "runtime.imethod")
|
@StructureMapping(structureName = {"runtime.imethod", "internal/abi.Imethod"})
|
||||||
public class GoIMethod implements StructureMarkup<GoIMethod> {
|
public class GoIMethod implements StructureMarkup<GoIMethod> {
|
||||||
|
|
||||||
@ContextField
|
@ContextField
|
||||||
|
@ -36,7 +36,7 @@ public class GoIMethod implements StructureMarkup<GoIMethod> {
|
||||||
@EOLComment("getName")
|
@EOLComment("getName")
|
||||||
private long name;
|
private long name;
|
||||||
|
|
||||||
@FieldMapping
|
@FieldMapping(fieldName = {"ityp", "Typ"})
|
||||||
@MarkupReference("getType")
|
@MarkupReference("getType")
|
||||||
private long ityp;
|
private long ityp;
|
||||||
|
|
||||||
|
|
|
@ -28,14 +28,14 @@ import ghidra.util.exception.CancelledException;
|
||||||
/**
|
/**
|
||||||
* A {@link GoType} structure that defines a golang interface.
|
* A {@link GoType} structure that defines a golang interface.
|
||||||
*/
|
*/
|
||||||
@StructureMapping(structureName = "runtime.interfacetype")
|
@StructureMapping(structureName = {"runtime.interfacetype", "internal/abi.InterfaceType"})
|
||||||
public class GoInterfaceType extends GoType {
|
public class GoInterfaceType extends GoType {
|
||||||
|
|
||||||
@FieldMapping
|
@FieldMapping
|
||||||
@MarkupReference("getPkgPath")
|
@MarkupReference("getPkgPath")
|
||||||
private long pkgpath; // pointer to name
|
private long pkgpath; // pointer to name
|
||||||
|
|
||||||
@FieldMapping
|
@FieldMapping(fieldName = {"mhdr", "Methods"})
|
||||||
private GoSlice mhdr;
|
private GoSlice mhdr;
|
||||||
|
|
||||||
public GoInterfaceType() {
|
public GoInterfaceType() {
|
||||||
|
|
|
@ -30,7 +30,7 @@ import ghidra.util.Msg;
|
||||||
* See {@link GoRttiMapper#getMapGoType()} or the "runtime.hmap" type for the definition of
|
* See {@link GoRttiMapper#getMapGoType()} or the "runtime.hmap" type for the definition of
|
||||||
* a instance of a map variable in memory.
|
* a instance of a map variable in memory.
|
||||||
*/
|
*/
|
||||||
@StructureMapping(structureName = "runtime.maptype")
|
@StructureMapping(structureName = {"runtime.maptype", "internal/abi.MapType"})
|
||||||
public class GoMapType extends GoType {
|
public class GoMapType extends GoType {
|
||||||
|
|
||||||
@FieldMapping
|
@FieldMapping
|
||||||
|
@ -51,7 +51,7 @@ public class GoMapType extends GoType {
|
||||||
@FieldMapping
|
@FieldMapping
|
||||||
private int keysize;
|
private int keysize;
|
||||||
|
|
||||||
@FieldMapping
|
@FieldMapping(fieldName = {"elemsize", "ValueSize"})
|
||||||
private int elemsize;
|
private int elemsize;
|
||||||
|
|
||||||
@FieldMapping
|
@FieldMapping
|
||||||
|
|
|
@ -28,7 +28,7 @@ import ghidra.util.NumericUtilities;
|
||||||
/**
|
/**
|
||||||
* Structure that defines a method for a GoType, found in the type's {@link GoUncommonType} struct.
|
* Structure that defines a method for a GoType, found in the type's {@link GoUncommonType} struct.
|
||||||
*/
|
*/
|
||||||
@StructureMapping(structureName = "runtime.method")
|
@StructureMapping(structureName = {"runtime.method", "internal/abi.Method"})
|
||||||
public class GoMethod implements StructureMarkup<GoMethod> {
|
public class GoMethod implements StructureMarkup<GoMethod> {
|
||||||
@ContextField
|
@ContextField
|
||||||
private GoRttiMapper programContext;
|
private GoRttiMapper programContext;
|
||||||
|
|
|
@ -32,7 +32,7 @@ import ghidra.util.Msg;
|
||||||
* <p>
|
* <p>
|
||||||
* {@link GoType} structure that defines a built-in primitive type.
|
* {@link GoType} structure that defines a built-in primitive type.
|
||||||
*/
|
*/
|
||||||
@StructureMapping(structureName = "runtime._type")
|
@StructureMapping(structureName = {"runtime._type", "internal/abi.Type"})
|
||||||
public class GoPlainType extends GoType implements StructureReader<GoType> {
|
public class GoPlainType extends GoType implements StructureReader<GoType> {
|
||||||
@Override
|
@Override
|
||||||
public void readStructure() throws IOException {
|
public void readStructure() throws IOException {
|
||||||
|
|
|
@ -26,7 +26,7 @@ import ghidra.program.model.data.PointerDataType;
|
||||||
/**
|
/**
|
||||||
* {@link GoType} structure that defines a pointer.
|
* {@link GoType} structure that defines a pointer.
|
||||||
*/
|
*/
|
||||||
@StructureMapping(structureName = "runtime.ptrtype")
|
@StructureMapping(structureName = {"runtime.ptrtype", "internal/abi.PtrType"})
|
||||||
public class GoPointerType extends GoType {
|
public class GoPointerType extends GoType {
|
||||||
@FieldMapping
|
@FieldMapping
|
||||||
@MarkupReference("getElement")
|
@MarkupReference("getElement")
|
||||||
|
|
|
@ -29,7 +29,7 @@ import ghidra.program.model.data.*;
|
||||||
* See {@link GoRttiMapper#getGenericSliceDT()} or the "runtime.slice" type for the definition of
|
* See {@link GoRttiMapper#getGenericSliceDT()} or the "runtime.slice" type for the definition of
|
||||||
* a instance of a slice variable in memory.
|
* a instance of a slice variable in memory.
|
||||||
*/
|
*/
|
||||||
@StructureMapping(structureName = "runtime.slicetype")
|
@StructureMapping(structureName = {"runtime.slicetype", "internal/abi.SliceType"})
|
||||||
public class GoSliceType extends GoType {
|
public class GoSliceType extends GoType {
|
||||||
|
|
||||||
@FieldMapping
|
@FieldMapping
|
||||||
|
|
|
@ -24,7 +24,7 @@ import ghidra.app.util.bin.format.golang.structmapping.*;
|
||||||
/**
|
/**
|
||||||
* Structure used to define a field in a {@link GoStructType struct type}.
|
* Structure used to define a field in a {@link GoStructType struct type}.
|
||||||
*/
|
*/
|
||||||
@StructureMapping(structureName = "runtime.structfield")
|
@StructureMapping(structureName = {"runtime.structfield", "internal/abi.StructField"})
|
||||||
public class GoStructField {
|
public class GoStructField {
|
||||||
|
|
||||||
@ContextField
|
@ContextField
|
||||||
|
|
|
@ -29,7 +29,7 @@ import ghidra.util.exception.CancelledException;
|
||||||
/**
|
/**
|
||||||
* Golang type information about a specific structure type.
|
* Golang type information about a specific structure type.
|
||||||
*/
|
*/
|
||||||
@StructureMapping(structureName = "runtime.structtype")
|
@StructureMapping(structureName = {"runtime.structtype", "internal/abi.StructType"})
|
||||||
public class GoStructType extends GoType {
|
public class GoStructType extends GoType {
|
||||||
|
|
||||||
@FieldMapping
|
@FieldMapping
|
||||||
|
|
|
@ -69,7 +69,7 @@ public abstract class GoType implements StructureMarkup<GoType> {
|
||||||
@ContextField
|
@ContextField
|
||||||
protected StructureContext<GoType> context;
|
protected StructureContext<GoType> context;
|
||||||
|
|
||||||
@FieldMapping
|
@FieldMapping(fieldName = {"typ", "Type"})
|
||||||
@Markup
|
@Markup
|
||||||
@FieldOutput
|
@FieldOutput
|
||||||
protected GoBaseType typ;
|
protected GoBaseType typ;
|
||||||
|
|
|
@ -21,9 +21,9 @@ import ghidra.app.util.bin.format.golang.structmapping.StructureMapping;
|
||||||
/**
|
/**
|
||||||
* Small stub that is only used to fetch the "kind" field so that the real gotype can be detected
|
* Small stub that is only used to fetch the "kind" field so that the real gotype can be detected
|
||||||
*/
|
*/
|
||||||
@StructureMapping(structureName = "runtime._type")
|
@StructureMapping(structureName = {"runtime._type", "internal/abi.Type"})
|
||||||
public class GoTypeDetector {
|
public class GoTypeDetector {
|
||||||
@FieldMapping
|
@FieldMapping(fieldName = {"kind", "Kind_"})
|
||||||
private int kind;
|
private int kind;
|
||||||
|
|
||||||
public GoKind getKind() {
|
public GoKind getKind() {
|
||||||
|
|
|
@ -26,7 +26,7 @@ import ghidra.util.Msg;
|
||||||
* Structure found immediately after a {@link GoType} structure, if it has the uncommon flag
|
* Structure found immediately after a {@link GoType} structure, if it has the uncommon flag
|
||||||
* set.
|
* set.
|
||||||
*/
|
*/
|
||||||
@StructureMapping(structureName = "runtime.uncommontype")
|
@StructureMapping(structureName = {"runtime.uncommontype", "internal/abi.UncommonType"})
|
||||||
public class GoUncommonType {
|
public class GoUncommonType {
|
||||||
|
|
||||||
@ContextField
|
@ContextField
|
||||||
|
|
|
@ -169,21 +169,30 @@ public class DataTypeMapper implements AutoCloseable {
|
||||||
* @throws IOException if the class's Ghidra structure data type could not be found
|
* @throws IOException if the class's Ghidra structure data type could not be found
|
||||||
*/
|
*/
|
||||||
public <T> void registerStructure(Class<T> clazz) throws IOException {
|
public <T> void registerStructure(Class<T> clazz) throws IOException {
|
||||||
Structure structDT = null;
|
StructureMapping sma = clazz.getAnnotation(StructureMapping.class);
|
||||||
String structName = StructureMappingInfo.getStructureDataTypeNameForClass(clazz);
|
List<String> structNames = sma != null ? Arrays.asList(sma.structureName()) : List.of();
|
||||||
if (structName != null && !structName.isBlank()) {
|
Structure structDT = getType(structNames, Structure.class);
|
||||||
structDT = getType(structName, Structure.class);
|
if (structDT == null) {
|
||||||
}
|
String dtName = structNames.isEmpty() ? "<missing>" : String.join("|", structNames);
|
||||||
if (!StructureReader.class.isAssignableFrom(clazz) && structDT == null) {
|
if (!StructureReader.class.isAssignableFrom(clazz)) {
|
||||||
if (structName == null || structName.isBlank()) {
|
throw new IOException("Missing struct definition for class %s, structure name: [%s]"
|
||||||
structName = "<missing>";
|
.formatted(clazz.getSimpleName(), dtName));
|
||||||
|
}
|
||||||
|
if (structNames.size() != 1) {
|
||||||
|
throw new IOException(
|
||||||
|
"Bad StructMapping,StructureReader definition for class %s, structure name: [%s]"
|
||||||
|
.formatted(clazz.getSimpleName(), dtName));
|
||||||
}
|
}
|
||||||
throw new IOException(
|
|
||||||
"Missing struct definition %s - %s".formatted(clazz.getSimpleName(), structName));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
StructureMappingInfo<T> structMappingInfo = StructureMappingInfo.fromClass(clazz, structDT);
|
try {
|
||||||
mappingInfo.put(clazz, structMappingInfo);
|
StructureMappingInfo<T> structMappingInfo =
|
||||||
|
StructureMappingInfo.fromClass(clazz, structDT);
|
||||||
|
mappingInfo.put(clazz, structMappingInfo);
|
||||||
|
}
|
||||||
|
catch (IllegalArgumentException e) {
|
||||||
|
throw new IOException(e.getMessage());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -282,7 +291,32 @@ public class DataTypeMapper implements AutoCloseable {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns a named {@link DataType}, searching the registered
|
* Returns a named {@link DataType}, searching the registered
|
||||||
|
* {@link #addProgramSearchCategoryPath(CategoryPath...) program}
|
||||||
|
* and {@link #addArchiveSearchCategoryPath(CategoryPath...) archive} category paths.
|
||||||
|
* <p>
|
||||||
|
* DataTypes that were found in the attached archive gdt manager will be copied into the
|
||||||
|
* program's data type manager before being returned.
|
||||||
|
*
|
||||||
|
* @param <T> DataType or derived type
|
||||||
|
* @param names list containing the data type name and any alternates
|
||||||
|
* @param clazz expected DataType class
|
||||||
|
* @return DataType or null if not found
|
||||||
|
*/
|
||||||
|
public <T extends DataType> T getType(List<String> names, Class<T> clazz) {
|
||||||
|
for (String dtName : names) {
|
||||||
|
if (dtName != null && !dtName.isBlank()) {
|
||||||
|
T result = getType(dtName, clazz);
|
||||||
|
if (result != null) {
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a named {@link DataType}, searching the registered
|
||||||
* {@link #addProgramSearchCategoryPath(CategoryPath...) program}
|
* {@link #addProgramSearchCategoryPath(CategoryPath...) program}
|
||||||
* and {@link #addArchiveSearchCategoryPath(CategoryPath...) archive} category paths.
|
* and {@link #addArchiveSearchCategoryPath(CategoryPath...) archive} category paths.
|
||||||
* <p>
|
* <p>
|
||||||
|
|
|
@ -15,8 +15,8 @@
|
||||||
*/
|
*/
|
||||||
package ghidra.app.util.bin.format.golang.structmapping;
|
package ghidra.app.util.bin.format.golang.structmapping;
|
||||||
|
|
||||||
import static java.lang.annotation.ElementType.FIELD;
|
import static java.lang.annotation.ElementType.*;
|
||||||
import static java.lang.annotation.RetentionPolicy.RUNTIME;
|
import static java.lang.annotation.RetentionPolicy.*;
|
||||||
|
|
||||||
import java.lang.annotation.Retention;
|
import java.lang.annotation.Retention;
|
||||||
import java.lang.annotation.Target;
|
import java.lang.annotation.Target;
|
||||||
|
@ -44,10 +44,10 @@ public @interface FieldMapping {
|
||||||
* Overrides the field name that is matched in the structure.
|
* Overrides the field name that is matched in the structure.
|
||||||
* <p>
|
* <p>
|
||||||
* Can be a single name, or a list of names that will be used to find the structure
|
* Can be a single name, or a list of names that will be used to find the structure
|
||||||
* field.
|
* field. The name is case-insensitive.
|
||||||
*
|
*
|
||||||
* @return name, or list of names, of the structure field to map, or unset to use the
|
* @return name, or list of names (case insensitive), of the structure field to map,
|
||||||
* java field's name
|
* or unset to use the java field's name
|
||||||
*/
|
*/
|
||||||
String[] fieldName() default "";
|
String[] fieldName() default "";
|
||||||
|
|
||||||
|
|
|
@ -21,54 +21,54 @@ import java.lang.annotation.*;
|
||||||
* Indicates that the tagged class corresponds to a Ghidra structure.
|
* Indicates that the tagged class corresponds to a Ghidra structure.
|
||||||
* <p>
|
* <p>
|
||||||
* For fixed/static length structures, an existing Ghidra structure data type will be found and
|
* For fixed/static length structures, an existing Ghidra structure data type will be found and
|
||||||
* then bound to the tagged class, and it will control how instances of the tagged class
|
* then bound to the tagged class, and it will control how instances of the tagged class
|
||||||
* are deserialized. Only fields that are interesting / relevant need to be tagged with
|
* are deserialized. Only fields that are interesting / relevant need to be tagged with
|
||||||
* a {@link FieldMapping} annotation, which causes them to be pulled into the java structure.
|
* a {@link FieldMapping} annotation, which causes them to be pulled into the java class.
|
||||||
* <p>
|
* <p>
|
||||||
* For {@link FieldOutput#isVariableLength() variable} length structures, a unique Ghidra
|
* For {@link FieldOutput#isVariableLength() variable} length structures, a unique Ghidra
|
||||||
* structure data type will be created for each combination of field lengths, and the tagged
|
* structure data type will be created for each combination of field lengths, and the tagged
|
||||||
* class must deserialize itself by implementing the {@link StructureReader} interface. (each
|
* class must deserialize itself by implementing the {@link StructureReader} interface. (each
|
||||||
* field that needs to be mapped into the Ghidra structure must be tagged with a {@link FieldOutput}
|
* field that needs to be mapped into the Ghidra structure must be tagged with a {@link FieldOutput}
|
||||||
* annotation)
|
* annotation)
|
||||||
* <p>
|
* <p>
|
||||||
* In either case, various annotations on fields and methods will control how this structure
|
* In either case, various annotations on fields and methods will control how this structure
|
||||||
* will be marked up in the Ghidra program.
|
* will be marked up in the Ghidra program.
|
||||||
* <p>
|
* <p>
|
||||||
* The tagged class must be {@link DataTypeMapper#registerStructure(Class) registered} with
|
* The tagged class must be {@link DataTypeMapper#registerStructure(Class) registered} with
|
||||||
* the {@link DataTypeMapper program context} to enable the suite of structure mapped classes
|
* the {@link DataTypeMapper program context} to enable the suite of structure mapped classes
|
||||||
* to work together when applied to a Ghidra binary.
|
* to work together when applied to a Ghidra binary.
|
||||||
* <p>
|
* <p>
|
||||||
* For variable length structure classes, when the struct mapping system creates a custom-fitted
|
* For variable length structure classes, when the struct mapping system creates a custom-fitted
|
||||||
* structure to markup a specific location with its specific data, the new struct data type's name
|
* structure to markup a specific location with its specific data, the new struct data type's name
|
||||||
* will be patterned as "structurename_NN_MM_...", where NN and MM and etc are the lengths of the
|
* will be patterned as "structurename_NN_MM_...", where NN and MM and etc are the lengths of the
|
||||||
* variable length fields found in the structure.
|
* variable length fields found in the structure.
|
||||||
* <p>
|
* <p>
|
||||||
* Structure mapped classes must have a {@link StructureContext} member variable that is tagged
|
* Structure mapped classes must have a {@link StructureContext} member variable that is tagged
|
||||||
* with the {@link ContextField} annotation, and probably should have a {@link DataTypeMapper}
|
* with the {@link ContextField} annotation, and probably should have a {@link DataTypeMapper}
|
||||||
* member variable (that corresponds to a more specific type of DataTypeMapper) that is also
|
* member variable (that corresponds to a more specific type of DataTypeMapper) that is also
|
||||||
* tagged with the ContextField annotation.
|
* tagged with the ContextField annotation.
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
@Retention(RetentionPolicy.RUNTIME)
|
@Retention(RetentionPolicy.RUNTIME)
|
||||||
@Target(ElementType.TYPE)
|
@Target(ElementType.TYPE)
|
||||||
public @interface StructureMapping {
|
public @interface StructureMapping {
|
||||||
/**
|
/**
|
||||||
* Specifies the name of a Ghidra structure that the tagged class represents. For fixed
|
* Specifies the name, and optionally alternate names, of a Ghidra structure that the tagged
|
||||||
* length structures, the {@link DataTypeMapper} will search for this Ghidra data type
|
* class represents. For fixed length structures, the {@link DataTypeMapper} will search
|
||||||
* in it's configured
|
* for this Ghidra data type in it's configured
|
||||||
* {@link DataTypeMapper#addArchiveSearchCategoryPath(ghidra.program.model.data.CategoryPath...) archive}
|
* {@link DataTypeMapper#addArchiveSearchCategoryPath(ghidra.program.model.data.CategoryPath...) archive}
|
||||||
* and
|
* and
|
||||||
* {@link DataTypeMapper#addProgramSearchCategoryPath(ghidra.program.model.data.CategoryPath...) program}
|
* {@link DataTypeMapper#addProgramSearchCategoryPath(ghidra.program.model.data.CategoryPath...) program}
|
||||||
* search paths.
|
* search paths.
|
||||||
*
|
*
|
||||||
* @return name of a Ghidra structure data type
|
* @return name(s) of a Ghidra structure data type
|
||||||
*/
|
*/
|
||||||
String structureName();
|
String[] structureName();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Optional reference to a 'function' (implemented via a class) that will be called to do
|
* Optional reference to a 'function' (implemented via a class) that will be called to do
|
||||||
* custom markup.
|
* custom markup.
|
||||||
*
|
*
|
||||||
* @return {@link StructureMarkupFunction} class
|
* @return {@link StructureMarkupFunction} class
|
||||||
*/
|
*/
|
||||||
@SuppressWarnings("rawtypes")
|
@SuppressWarnings("rawtypes")
|
||||||
|
|
|
@ -32,18 +32,6 @@ import ghidra.util.exception.DuplicateNameException;
|
||||||
*/
|
*/
|
||||||
public class StructureMappingInfo<T> {
|
public class StructureMappingInfo<T> {
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the name of the structure data type that will define the binary layout
|
|
||||||
* of the mapped fields in the target class.
|
|
||||||
*
|
|
||||||
* @param targetClass structure mapped class
|
|
||||||
* @return the structure name
|
|
||||||
*/
|
|
||||||
public static String getStructureDataTypeNameForClass(Class<?> targetClass) {
|
|
||||||
StructureMapping sma = targetClass.getAnnotation(StructureMapping.class);
|
|
||||||
return sma != null ? sma.structureName() : null;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the mapping info for a class, using annotations found in that class.
|
* Returns the mapping info for a class, using annotations found in that class.
|
||||||
*
|
*
|
||||||
|
@ -70,6 +58,7 @@ public class StructureMappingInfo<T> {
|
||||||
|
|
||||||
private final String structureName;
|
private final String structureName;
|
||||||
private final Structure structureDataType; // null if variable length fields
|
private final Structure structureDataType; // null if variable length fields
|
||||||
|
private final Map<String, DataTypeComponent> fieldNameLookup; // case insensitive lookup
|
||||||
|
|
||||||
private final List<FieldMappingInfo<T>> fields = new ArrayList<>();
|
private final List<FieldMappingInfo<T>> fields = new ArrayList<>();
|
||||||
private final List<FieldOutputInfo<T>> outputFields = new ArrayList<>();
|
private final List<FieldOutputInfo<T>> outputFields = new ArrayList<>();
|
||||||
|
@ -85,7 +74,8 @@ public class StructureMappingInfo<T> {
|
||||||
this.structureDataType = structDataType;
|
this.structureDataType = structDataType;
|
||||||
this.structureName = structureDataType != null
|
this.structureName = structureDataType != null
|
||||||
? structureDataType.getName()
|
? structureDataType.getName()
|
||||||
: sma.structureName();
|
: sma.structureName()[0];
|
||||||
|
this.fieldNameLookup = indexStructFields(structDataType);
|
||||||
this.useFieldMappingInfo = !StructureReader.class.isAssignableFrom(targetClass);
|
this.useFieldMappingInfo = !StructureReader.class.isAssignableFrom(targetClass);
|
||||||
this.instanceCreator = findInstanceCreator();
|
this.instanceCreator = findInstanceCreator();
|
||||||
|
|
||||||
|
@ -259,18 +249,6 @@ public class StructureMappingInfo<T> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private DataTypeComponent getField(String name) {
|
|
||||||
if (!useFieldMappingInfo || name == null || name.isBlank()) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
for (DataTypeComponent dtc : structureDataType.getDefinedComponents()) {
|
|
||||||
if (name.equals(dtc.getFieldName())) {
|
|
||||||
return dtc;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void readFieldInfo(Class<?> clazz) {
|
private void readFieldInfo(Class<?> clazz) {
|
||||||
Class<?> superclass = clazz.getSuperclass();
|
Class<?> superclass = clazz.getSuperclass();
|
||||||
if (superclass != null) {
|
if (superclass != null) {
|
||||||
|
@ -316,8 +294,9 @@ public class StructureMappingInfo<T> {
|
||||||
if (fma.optional()) {
|
if (fma.optional()) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
throw new IllegalArgumentException("Missing structure field: %s in %s"
|
throw new IllegalArgumentException(
|
||||||
.formatted(Arrays.toString(fieldNames), targetClass.getSimpleName()));
|
"Missing structure field: %s.%s for %s.%s".formatted(structureName,
|
||||||
|
Arrays.toString(fieldNames), targetClass.getSimpleName(), field.getName()));
|
||||||
}
|
}
|
||||||
|
|
||||||
Signedness signedness = fma != null ? fma.signedness() : Signedness.Unspecified;
|
Signedness signedness = fma != null ? fma.signedness() : Signedness.Unspecified;
|
||||||
|
@ -346,7 +325,7 @@ public class StructureMappingInfo<T> {
|
||||||
|
|
||||||
private DataTypeComponent getFirstMatchingField(String[] fieldNames) {
|
private DataTypeComponent getFirstMatchingField(String[] fieldNames) {
|
||||||
for (String fieldName : fieldNames) {
|
for (String fieldName : fieldNames) {
|
||||||
DataTypeComponent dtc = getField(fieldName);
|
DataTypeComponent dtc = fieldNameLookup.get(fieldName.toLowerCase());
|
||||||
if (dtc != null) {
|
if (dtc != null) {
|
||||||
return dtc;
|
return dtc;
|
||||||
}
|
}
|
||||||
|
@ -400,6 +379,20 @@ public class StructureMappingInfo<T> {
|
||||||
return struct.isZeroLength() ? 0 : struct.getLength();
|
return struct.isZeroLength() ? 0 : struct.getLength();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static Map<String, DataTypeComponent> indexStructFields(Structure struct) {
|
||||||
|
if (struct == null) {
|
||||||
|
return Map.of();
|
||||||
|
}
|
||||||
|
Map<String, DataTypeComponent> result = new HashMap<>();
|
||||||
|
for (DataTypeComponent dtc : struct.getDefinedComponents()) {
|
||||||
|
String fieldName = dtc.getFieldName();
|
||||||
|
if (fieldName != null) {
|
||||||
|
result.put(fieldName.toLowerCase(), dtc);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
//---------------------------------------------------------------------------------------------
|
//---------------------------------------------------------------------------------------------
|
||||||
interface ReadFromStructureFunction<T> {
|
interface ReadFromStructureFunction<T> {
|
||||||
T readStructure(StructureContext<T> context) throws IOException;
|
T readStructure(StructureContext<T> context) throws IOException;
|
||||||
|
|
|
@ -39,17 +39,18 @@ public class DataTypeArchiveIDTest extends AbstractGenericTest {
|
||||||
private static final String MAC_OS_10_9_GDT_PATH = "typeinfo/mac_10.9/mac_osx.gdt";
|
private static final String MAC_OS_10_9_GDT_PATH = "typeinfo/mac_10.9/mac_osx.gdt";
|
||||||
|
|
||||||
//@formatter:off
|
//@formatter:off
|
||||||
private static final Map<String, String> archiveIdMap = Map.of(
|
private static final Map<String, String> archiveIdMap = Map.ofEntries(
|
||||||
WIN_VS12_32_GDT_PATH, "2644092282468053077",
|
Map.entry(WIN_VS12_32_GDT_PATH, "2644092282468053077"),
|
||||||
WIN_VS12_64_GDT_PATH, "3193696833254024484",
|
Map.entry(WIN_VS12_64_GDT_PATH, "3193696833254024484"),
|
||||||
GENERIC_CLIB_32_GDT_PATH, "2644097909188870631",
|
Map.entry(GENERIC_CLIB_32_GDT_PATH, "2644097909188870631"),
|
||||||
GENERIC_CLIB_64_GDT_PATH, "3193699959493190971",
|
Map.entry(GENERIC_CLIB_64_GDT_PATH, "3193699959493190971"),
|
||||||
MAC_OS_10_9_GDT_PATH, "2650667045259492112",
|
Map.entry(MAC_OS_10_9_GDT_PATH, "2650667045259492112"),
|
||||||
"typeinfo/golang/golang_1.17_anybit_any.gdt", "3533627828569507753",
|
Map.entry("typeinfo/golang/golang_1.17_anybit_any.gdt", "3533627828569507753"),
|
||||||
"typeinfo/golang/golang_1.18_anybit_any.gdt", "3528902399865061936",
|
Map.entry("typeinfo/golang/golang_1.18_anybit_any.gdt", "3528902399865061936"),
|
||||||
"typeinfo/golang/golang_1.19_anybit_any.gdt", "3533812166493410774",
|
Map.entry("typeinfo/golang/golang_1.19_anybit_any.gdt", "3533812166493410774"),
|
||||||
"typeinfo/golang/golang_1.20_anybit_any.gdt", "3533817003441909616",
|
Map.entry("typeinfo/golang/golang_1.20_anybit_any.gdt", "3533817003441909616"),
|
||||||
"typeinfo/rust/rust-common.gdt","3557867258392862055");
|
Map.entry("typeinfo/golang/golang_1.21_anybit_any.gdt", "3574190573109087960"),
|
||||||
|
Map.entry("typeinfo/rust/rust-common.gdt", "3557867258392862055"));
|
||||||
//@formatter:on
|
//@formatter:on
|
||||||
|
|
||||||
private Map<ResourceFile, String> getCurrentGdts() {
|
private Map<ResourceFile, String> getCurrentGdts() {
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
<golang>
|
<golang>
|
||||||
<!-- see https://github.com/golang/go/blob/master/src/internal/abi/abi_amd64.go -->
|
<!-- see https://github.com/golang/go/blob/master/src/internal/abi/abi_amd64.go -->
|
||||||
<register_info versions="V1_17,V1_18,V1_19,V1_20"> <!-- "all", or comma list of: V1_2,V1_16,V1_17,V1_18 -->
|
<register_info versions="V1_17,V1_18,V1_19,V1_20,V1_21"> <!-- "all", or comma list of: V1_2,V1_16,etc -->
|
||||||
<int_registers list="RAX,RBX,RCX,RDI,RSI,R8,R9,R10,R11"/>
|
<int_registers list="RAX,RBX,RCX,RDI,RSI,R8,R9,R10,R11"/>
|
||||||
<float_registers list="XMM0,XMM1,XMM2,XMM3,XMM4,XMM5,XMM6,XMM7,XMM8,XMM9,XMM10,XMM11,XMM12,XMM13,XMM14"/>
|
<float_registers list="XMM0,XMM1,XMM2,XMM3,XMM4,XMM5,XMM6,XMM7,XMM8,XMM9,XMM10,XMM11,XMM12,XMM13,XMM14"/>
|
||||||
<stack initialoffset="8" maxalign="8"/>
|
<stack initialoffset="8" maxalign="8"/>
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue