mirror of
https://github.com/NationalSecurityAgency/ghidra
synced 2024-09-19 10:11:55 +00:00
GP-4183 add golang 1.21 support
This commit is contained in:
parent
514fc2fc54
commit
5e18efdd0d
|
@ -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.19_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/mac_10.9/mac_osx.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);
|
||||
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;
|
||||
}
|
||||
markupSession = goBinary.createMarkupSession(monitor);
|
||||
|
|
|
@ -112,7 +112,7 @@ public class GolangSymbolAnalyzer extends AbstractAnalyzer {
|
|||
|
||||
goBinary = GoRttiMapper.getSharedGoBinary(program, monitor);
|
||||
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;
|
||||
}
|
||||
|
||||
|
@ -136,6 +136,7 @@ public class GolangSymbolAnalyzer extends AbstractAnalyzer {
|
|||
}
|
||||
|
||||
if (analyzerOptions.propagateRtti) {
|
||||
Msg.info(this, "Golang symbol analyzer: scheduling RTTI propagation after reference analysis");
|
||||
aam.schedule(new PropagateRttiBackgroundCommand(goBinary),
|
||||
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);
|
||||
}
|
||||
|
||||
}
|
|
@ -35,7 +35,7 @@ public enum GoVer {
|
|||
private final int major;
|
||||
private final int minor;
|
||||
|
||||
private GoVer(int major, int minor) {
|
||||
GoVer(int major, int minor) {
|
||||
this.major = major;
|
||||
this.minor = minor;
|
||||
}
|
||||
|
@ -91,7 +91,7 @@ public enum GoVer {
|
|||
}
|
||||
}
|
||||
catch (NumberFormatException e) {
|
||||
return UNKNOWN;
|
||||
// fall thru, return unknown
|
||||
}
|
||||
return UNKNOWN;
|
||||
}
|
||||
|
|
|
@ -112,54 +112,63 @@ public class GoRttiMapper extends DataTypeMapper {
|
|||
GoRttiMapper supplier_result = getGoBinary(program);
|
||||
if (supplier_result != null) {
|
||||
supplier_result.init(monitor);
|
||||
return supplier_result;
|
||||
}
|
||||
return supplier_result;
|
||||
}
|
||||
catch (IllegalArgumentException | IOException e) {
|
||||
TransientProgramProperties.getProperty(program, FAILED_FLAG,
|
||||
TransientProgramProperties.SCOPE.PROGRAM, Boolean.class, () -> true); // also sets it
|
||||
|
||||
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 (BootstrapInfoException mbie) {
|
||||
Msg.warn(GoRttiMapper.class, mbie.getMessage());
|
||||
logAnalyzerMsg(program, mbie.getMessage());
|
||||
}
|
||||
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;
|
||||
}
|
||||
|
||||
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.
|
||||
*
|
||||
* @param program {@link Program}
|
||||
* @return new {@link GoRttiMapper}, or null if basic golang information is not found in the
|
||||
* 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
|
||||
*/
|
||||
public static GoRttiMapper getGoBinary(Program program)
|
||||
throws IllegalArgumentException, IOException {
|
||||
throws BootstrapInfoException, IOException {
|
||||
GoBuildInfo buildInfo = GoBuildInfo.fromProgram(program);
|
||||
GoVer goVer;
|
||||
if (buildInfo == null || (goVer = buildInfo.getVerEnum()) == GoVer.UNKNOWN) {
|
||||
if (buildInfo == null) {
|
||||
// probably not a golang binary
|
||||
return null;
|
||||
}
|
||||
|
||||
GoVer goVer = buildInfo.getVerEnum();
|
||||
if (goVer == GoVer.UNKNOWN) {
|
||||
throw new BootstrapInfoException(
|
||||
"Unsupported Golang version, version info: '%s'".formatted(buildInfo.getVersion()));
|
||||
}
|
||||
|
||||
ResourceFile gdtFile =
|
||||
findGolangBootstrapGDT(goVer, buildInfo.getPointerSize(), getGolangOSString(program));
|
||||
if (gdtFile == null) {
|
||||
|
@ -324,11 +333,11 @@ public class GoRttiMapper extends DataTypeMapper {
|
|||
* if not present and types recovered via DWARF should be used instead
|
||||
* @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 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
|
||||
*/
|
||||
public GoRttiMapper(Program program, int ptrSize, Endian endian, GoVer goVersion,
|
||||
ResourceFile archiveGDT) throws IOException, IllegalArgumentException {
|
||||
ResourceFile archiveGDT) throws IOException, BootstrapInfoException {
|
||||
super(program, archiveGDT);
|
||||
|
||||
this.goVersion = goVersion;
|
||||
|
@ -357,13 +366,15 @@ public class GoRttiMapper extends DataTypeMapper {
|
|||
if (archiveGDT == null) {
|
||||
// a normal'ish situation where there isn't a .gdt for this arch/binary and there
|
||||
// isn't any DWARF.
|
||||
throw new IllegalArgumentException(
|
||||
"Missing golang .gdt archive for %s, no fallback DWARF info, unable to extract golang RTTI info."
|
||||
throw new BootstrapInfoException(
|
||||
"Missing golang .gdt archive for %s, no fallback DWARF info, unable to extract Golang RTTI info."
|
||||
.formatted(goVersion));
|
||||
}
|
||||
// a bad situation where the data type info is corrupted
|
||||
throw new IOException("Invalid or missing Golang bootstrap GDT file: %s"
|
||||
.formatted(archiveGDT.getAbsolutePath()));
|
||||
|
||||
// we have a .gdt, but something failed.
|
||||
throw new IOException("Invalid Golang bootstrap GDT file or struct mapping info: %s"
|
||||
.formatted(archiveGDT.getAbsolutePath()),
|
||||
e);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -169,26 +169,30 @@ public class DataTypeMapper implements AutoCloseable {
|
|||
* @throws IOException if the class's Ghidra structure data type could not be found
|
||||
*/
|
||||
public <T> void registerStructure(Class<T> clazz) throws IOException {
|
||||
Structure structDT = null;
|
||||
for (String structName : StructureMappingInfo.getStructureDataTypeNameForClass(clazz)) {
|
||||
if (structName != null && !structName.isBlank()) {
|
||||
structDT = getType(structName, Structure.class);
|
||||
if (structDT != null) {
|
||||
break;
|
||||
}
|
||||
StructureMapping sma = clazz.getAnnotation(StructureMapping.class);
|
||||
List<String> structNames = sma != null ? Arrays.asList(sma.structureName()) : List.of();
|
||||
Structure structDT = getType(structNames, Structure.class);
|
||||
if (structDT == null) {
|
||||
String dtName = structNames.isEmpty() ? "<missing>" : String.join("|", structNames);
|
||||
if (!StructureReader.class.isAssignableFrom(clazz)) {
|
||||
throw new IOException("Missing struct definition for class %s, structure name: [%s]"
|
||||
.formatted(clazz.getSimpleName(), dtName));
|
||||
}
|
||||
}
|
||||
if (!StructureReader.class.isAssignableFrom(clazz) && structDT == null) {
|
||||
String structName = StructureMappingInfo.getStructureDataTypeNameForClass(clazz)[0];
|
||||
if (structName == null || structName.isBlank()) {
|
||||
structName = "<missing>";
|
||||
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);
|
||||
mappingInfo.put(clazz, structMappingInfo);
|
||||
try {
|
||||
StructureMappingInfo<T> structMappingInfo =
|
||||
StructureMappingInfo.fromClass(clazz, structDT);
|
||||
mappingInfo.put(clazz, structMappingInfo);
|
||||
}
|
||||
catch (IllegalArgumentException e) {
|
||||
throw new IOException(e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -287,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}
|
||||
* and {@link #addArchiveSearchCategoryPath(CategoryPath...) archive} category paths.
|
||||
* <p>
|
||||
|
|
|
@ -15,8 +15,8 @@
|
|||
*/
|
||||
package ghidra.app.util.bin.format.golang.structmapping;
|
||||
|
||||
import static java.lang.annotation.ElementType.FIELD;
|
||||
import static java.lang.annotation.RetentionPolicy.RUNTIME;
|
||||
import static java.lang.annotation.ElementType.*;
|
||||
import static java.lang.annotation.RetentionPolicy.*;
|
||||
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.Target;
|
||||
|
@ -44,10 +44,10 @@ public @interface FieldMapping {
|
|||
* Overrides the field name that is matched in the structure.
|
||||
* <p>
|
||||
* 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
|
||||
* java field's name
|
||||
* @return name, or list of names (case insensitive), of the structure field to map,
|
||||
* or unset to use the java field's name
|
||||
*/
|
||||
String[] fieldName() default "";
|
||||
|
||||
|
|
|
@ -21,54 +21,54 @@ import java.lang.annotation.*;
|
|||
* Indicates that the tagged class corresponds to a Ghidra structure.
|
||||
* <p>
|
||||
* 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
|
||||
* 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>
|
||||
* 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
|
||||
* 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}
|
||||
* annotation)
|
||||
* <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.
|
||||
* <p>
|
||||
* 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.
|
||||
* <p>
|
||||
* 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
|
||||
* 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>
|
||||
* 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}
|
||||
* 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.
|
||||
*
|
||||
*
|
||||
*/
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Target(ElementType.TYPE)
|
||||
public @interface StructureMapping {
|
||||
/**
|
||||
* Specifies the name of a Ghidra structure that the tagged class represents. For fixed
|
||||
* length structures, the {@link DataTypeMapper} will search for this Ghidra data type
|
||||
* in it's configured
|
||||
* Specifies the name, and optionally alternate names, of a Ghidra structure that the tagged
|
||||
* class represents. For fixed length structures, the {@link DataTypeMapper} will search
|
||||
* for this Ghidra data type in it's configured
|
||||
* {@link DataTypeMapper#addArchiveSearchCategoryPath(ghidra.program.model.data.CategoryPath...) archive}
|
||||
* and
|
||||
* and
|
||||
* {@link DataTypeMapper#addProgramSearchCategoryPath(ghidra.program.model.data.CategoryPath...) program}
|
||||
* search paths.
|
||||
*
|
||||
* @return name of a Ghidra structure data type
|
||||
*
|
||||
* @return name(s) of a Ghidra structure data type
|
||||
*/
|
||||
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.
|
||||
*
|
||||
*
|
||||
* @return {@link StructureMarkupFunction} class
|
||||
*/
|
||||
@SuppressWarnings("rawtypes")
|
||||
|
|
|
@ -32,18 +32,6 @@ import ghidra.util.exception.DuplicateNameException;
|
|||
*/
|
||||
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.
|
||||
*
|
||||
|
@ -68,8 +56,9 @@ public class StructureMappingInfo<T> {
|
|||
private final Class<T> targetClass;
|
||||
private final ObjectInstanceCreator<T> instanceCreator;
|
||||
|
||||
private final String[] structureName;
|
||||
private final String structureName;
|
||||
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<FieldOutputInfo<T>> outputFields = new ArrayList<>();
|
||||
|
@ -84,8 +73,9 @@ public class StructureMappingInfo<T> {
|
|||
this.targetClass = targetClass;
|
||||
this.structureDataType = structDataType;
|
||||
this.structureName = structureDataType != null
|
||||
? new String[]{structureDataType.getName()}
|
||||
: sma.structureName();
|
||||
? structureDataType.getName()
|
||||
: sma.structureName()[0];
|
||||
this.fieldNameLookup = indexStructFields(structDataType);
|
||||
this.useFieldMappingInfo = !StructureReader.class.isAssignableFrom(targetClass);
|
||||
this.instanceCreator = findInstanceCreator();
|
||||
|
||||
|
@ -109,7 +99,7 @@ public class StructureMappingInfo<T> {
|
|||
}
|
||||
|
||||
public String getDescription() {
|
||||
return "%s-%s".formatted(targetClass.getSimpleName(), structureName[0]);
|
||||
return "%s-%s".formatted(targetClass.getSimpleName(), structureName);
|
||||
}
|
||||
|
||||
public Structure getStructureDataType() {
|
||||
|
@ -117,7 +107,7 @@ public class StructureMappingInfo<T> {
|
|||
}
|
||||
|
||||
public String getStructureName() {
|
||||
return structureName[0];
|
||||
return structureName;
|
||||
}
|
||||
|
||||
public int getStructureLength() {
|
||||
|
@ -187,7 +177,7 @@ public class StructureMappingInfo<T> {
|
|||
|
||||
Structure newStruct = new StructureDataType(
|
||||
context.getDataTypeMapper().getDefaultVariableLengthStructCategoryPath(),
|
||||
structureName[0],
|
||||
structureName,
|
||||
0,
|
||||
context.getDataTypeMapper().getDTM());
|
||||
|
||||
|
@ -204,7 +194,7 @@ public class StructureMappingInfo<T> {
|
|||
}
|
||||
if (!nameSuffix.isEmpty()) {
|
||||
try {
|
||||
newStruct.setName(structureName[0] + nameSuffix);
|
||||
newStruct.setName(structureName + nameSuffix);
|
||||
}
|
||||
catch (InvalidNameException | DuplicateNameException e) {
|
||||
throw new IOException(e);
|
||||
|
@ -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.equalsIgnoreCase(dtc.getFieldName())) {
|
||||
return dtc;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private void readFieldInfo(Class<?> clazz) {
|
||||
Class<?> superclass = clazz.getSuperclass();
|
||||
if (superclass != null) {
|
||||
|
@ -316,8 +294,9 @@ public class StructureMappingInfo<T> {
|
|||
if (fma.optional()) {
|
||||
return null;
|
||||
}
|
||||
throw new IllegalArgumentException("Missing structure field: %s in %s"
|
||||
.formatted(Arrays.toString(fieldNames), targetClass.getSimpleName()));
|
||||
throw new IllegalArgumentException(
|
||||
"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;
|
||||
|
@ -346,7 +325,7 @@ public class StructureMappingInfo<T> {
|
|||
|
||||
private DataTypeComponent getFirstMatchingField(String[] fieldNames) {
|
||||
for (String fieldName : fieldNames) {
|
||||
DataTypeComponent dtc = getField(fieldName);
|
||||
DataTypeComponent dtc = fieldNameLookup.get(fieldName.toLowerCase());
|
||||
if (dtc != null) {
|
||||
return dtc;
|
||||
}
|
||||
|
@ -400,6 +379,20 @@ public class StructureMappingInfo<T> {
|
|||
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> {
|
||||
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";
|
||||
|
||||
//@formatter:off
|
||||
private static final Map<String, String> archiveIdMap = Map.of(
|
||||
WIN_VS12_32_GDT_PATH, "2644092282468053077",
|
||||
WIN_VS12_64_GDT_PATH, "3193696833254024484",
|
||||
GENERIC_CLIB_32_GDT_PATH, "2644097909188870631",
|
||||
GENERIC_CLIB_64_GDT_PATH, "3193699959493190971",
|
||||
MAC_OS_10_9_GDT_PATH, "2650667045259492112",
|
||||
"typeinfo/golang/golang_1.17_anybit_any.gdt", "3533627828569507753",
|
||||
"typeinfo/golang/golang_1.18_anybit_any.gdt", "3528902399865061936",
|
||||
"typeinfo/golang/golang_1.19_anybit_any.gdt", "3533812166493410774",
|
||||
"typeinfo/golang/golang_1.20_anybit_any.gdt", "3533817003441909616",
|
||||
"typeinfo/rust/rust-common.gdt","3557867258392862055");
|
||||
private static final Map<String, String> archiveIdMap = Map.ofEntries(
|
||||
Map.entry(WIN_VS12_32_GDT_PATH, "2644092282468053077"),
|
||||
Map.entry(WIN_VS12_64_GDT_PATH, "3193696833254024484"),
|
||||
Map.entry(GENERIC_CLIB_32_GDT_PATH, "2644097909188870631"),
|
||||
Map.entry(GENERIC_CLIB_64_GDT_PATH, "3193699959493190971"),
|
||||
Map.entry(MAC_OS_10_9_GDT_PATH, "2650667045259492112"),
|
||||
Map.entry("typeinfo/golang/golang_1.17_anybit_any.gdt", "3533627828569507753"),
|
||||
Map.entry("typeinfo/golang/golang_1.18_anybit_any.gdt", "3528902399865061936"),
|
||||
Map.entry("typeinfo/golang/golang_1.19_anybit_any.gdt", "3533812166493410774"),
|
||||
Map.entry("typeinfo/golang/golang_1.20_anybit_any.gdt", "3533817003441909616"),
|
||||
Map.entry("typeinfo/golang/golang_1.21_anybit_any.gdt", "3574190573109087960"),
|
||||
Map.entry("typeinfo/rust/rust-common.gdt", "3557867258392862055"));
|
||||
//@formatter:on
|
||||
|
||||
private Map<ResourceFile, String> getCurrentGdts() {
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
<golang>
|
||||
<!-- 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"/>
|
||||
<float_registers list="XMM0,XMM1,XMM2,XMM3,XMM4,XMM5,XMM6,XMM7,XMM8,XMM9,XMM10,XMM11,XMM12,XMM13,XMM14"/>
|
||||
<stack initialoffset="8" maxalign="8"/>
|
||||
|
|
Loading…
Reference in a new issue