mirror of
https://github.com/NationalSecurityAgency/ghidra.git
synced 2026-06-02 10:47:10 +08:00
Merge remote-tracking branch
'origin/GP-6645_dev747368_fix_golang_npe_mac_1_26_firstmoduledata' (Closes #9093)
This commit is contained in:
+13
-3
@@ -302,10 +302,14 @@ public class GolangStringAnalyzer extends AbstractAnalyzer {
|
|||||||
throws IOException, CancelledException {
|
throws IOException, CancelledException {
|
||||||
// test to see if its a slice first because strings can kinda look like slices (a pointer
|
// test to see if its a slice first because strings can kinda look like slices (a pointer
|
||||||
// then a length field).
|
// then a length field).
|
||||||
boolean isUndefined3x =
|
boolean isDefPtr = isDefaultPointer(addr);
|
||||||
DataUtilities.isUndefinedRange(program, addr, addr.add(sliceStructLen));
|
boolean isUndefined3x = (isDefPtr && DataUtilities.isUndefinedRange(program,
|
||||||
|
addr.add(goBinary.getPtrSize()), addr.add(sliceStructLen - 1))) ||
|
||||||
|
DataUtilities.isUndefinedRange(program, addr, addr.add(sliceStructLen - 1));
|
||||||
boolean isUndefined2x = isUndefined3x ||
|
boolean isUndefined2x = isUndefined3x ||
|
||||||
DataUtilities.isUndefinedRange(program, addr, addr.add(stringStructLen));
|
(isDefPtr && DataUtilities.isUndefinedRange(program,
|
||||||
|
addr.add(goBinary.getPtrSize()), addr.add(stringStructLen - 1))) ||
|
||||||
|
DataUtilities.isUndefinedRange(program, addr, addr.add(stringStructLen - 1));
|
||||||
|
|
||||||
Object newObj = isUndefined3x ? tryReadSliceStruct(addr) : null;
|
Object newObj = isUndefined3x ? tryReadSliceStruct(addr) : null;
|
||||||
if (newObj == null && isUndefined2x) {
|
if (newObj == null && isUndefined2x) {
|
||||||
@@ -323,6 +327,12 @@ public class GolangStringAnalyzer extends AbstractAnalyzer {
|
|||||||
return newObj;
|
return newObj;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private boolean isDefaultPointer(Address addr) {
|
||||||
|
Data data = program.getListing().getDataAt(addr);
|
||||||
|
return data != null && data.getDataType() instanceof DataType dt &&
|
||||||
|
((dt instanceof Pointer ptr && ptr.getDataType() == null) || Undefined.isUndefined(dt));
|
||||||
|
}
|
||||||
|
|
||||||
private GoString tryReadStringStruct(AddressSetView stringDataRange, Address addr) {
|
private GoString tryReadStringStruct(AddressSetView stringDataRange, Address addr) {
|
||||||
try {
|
try {
|
||||||
GoString goString = goBinary.readStructure(GoString.class, addr);
|
GoString goString = goBinary.readStructure(GoString.class, addr);
|
||||||
|
|||||||
+12
@@ -61,6 +61,18 @@ public class GoParamStorageAllocator {
|
|||||||
lang.getLanguageDescription().getSize());
|
lang.getLanguageDescription().getSize());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public GoParamStorageAllocator(GoRegisterInfo callspecInfo, Program program) {
|
||||||
|
Language lang = program.getLanguage();
|
||||||
|
|
||||||
|
this.callspecInfo = callspecInfo;
|
||||||
|
this.stackOffset = callspecInfo.getStackInitialOffset();
|
||||||
|
this.regs = List.of(callspecInfo.getIntRegisters(), callspecInfo.getFloatRegisters());
|
||||||
|
this.isBigEndian = lang.isBigEndian();
|
||||||
|
this.archDescription =
|
||||||
|
"%s_%d".formatted(lang.getLanguageDescription().getProcessor().toString(),
|
||||||
|
lang.getLanguageDescription().getSize());
|
||||||
|
}
|
||||||
|
|
||||||
private GoParamStorageAllocator(List<List<Register>> regs, int[] nextReg,
|
private GoParamStorageAllocator(List<List<Register>> regs, int[] nextReg,
|
||||||
GoRegisterInfo callspecInfo, long stackOffset, boolean isBigEndian,
|
GoRegisterInfo callspecInfo, long stackOffset, boolean isBigEndian,
|
||||||
String archDescription) {
|
String archDescription) {
|
||||||
|
|||||||
+1
-1
@@ -414,7 +414,7 @@ public class GoModuledata implements StructureMarkup<GoModuledata> {
|
|||||||
*/
|
*/
|
||||||
/* package */ static GoModuledata getFirstModuledata(GoRttiMapper context) throws IOException {
|
/* package */ static GoModuledata getFirstModuledata(GoRttiMapper context) throws IOException {
|
||||||
Program program = context.getProgram();
|
Program program = context.getProgram();
|
||||||
MemoryBlock memblk = context.getGoSection("go.module");
|
MemoryBlock memblk = context.getFirstGoSection("go.module", "go_module");
|
||||||
if (memblk != null) {
|
if (memblk != null) {
|
||||||
return context.readStructure(GoModuledata.class, memblk.getStart());
|
return context.readStructure(GoModuledata.class, memblk.getStart());
|
||||||
}
|
}
|
||||||
|
|||||||
+13
-4
@@ -236,8 +236,8 @@ public class GoRttiMapper extends DataTypeMapper implements DataTypeMapperContex
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static MemoryBlock getFirstGoSection(Program program, String... blockNames) {
|
public static MemoryBlock getFirstGoSection(Program program, String... sectionNames) {
|
||||||
for (String blockToSearch : blockNames) {
|
for (String blockToSearch : sectionNames) {
|
||||||
MemoryBlock memBlock = getGoSection(program, blockToSearch);
|
MemoryBlock memBlock = getGoSection(program, blockToSearch);
|
||||||
if (memBlock != null) {
|
if (memBlock != null) {
|
||||||
return memBlock;
|
return memBlock;
|
||||||
@@ -522,7 +522,7 @@ public class GoRttiMapper extends DataTypeMapper implements DataTypeMapperContex
|
|||||||
* {@return new {@link GoParamStorageAllocator} param storage allocator instance}
|
* {@return new {@link GoParamStorageAllocator} param storage allocator instance}
|
||||||
*/
|
*/
|
||||||
public GoParamStorageAllocator newStorageAllocator() {
|
public GoParamStorageAllocator newStorageAllocator() {
|
||||||
GoParamStorageAllocator storageAllocator = new GoParamStorageAllocator(program, goVer);
|
GoParamStorageAllocator storageAllocator = new GoParamStorageAllocator(regInfo, program);
|
||||||
return storageAllocator;
|
return storageAllocator;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -709,7 +709,12 @@ public class GoRttiMapper extends DataTypeMapper implements DataTypeMapperContex
|
|||||||
GoFuncDef snapshotFuncdef =
|
GoFuncDef snapshotFuncdef =
|
||||||
apiSnapshot.getFuncdef(symbolName.getStrippedSymbolString());
|
apiSnapshot.getFuncdef(symbolName.getStrippedSymbolString());
|
||||||
if (snapshotFuncdef != null) {
|
if (snapshotFuncdef != null) {
|
||||||
return createFuncDefFromApiSnapshot(symbolName, recvType, snapshotFuncdef);
|
try {
|
||||||
|
return createFuncDefFromApiSnapshot(symbolName, recvType, snapshotFuncdef);
|
||||||
|
}
|
||||||
|
catch (IOException e) {
|
||||||
|
// fail, fall thru to catch-all at bottom
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1197,4 +1202,8 @@ public class GoRttiMapper extends DataTypeMapper implements DataTypeMapperContex
|
|||||||
public MemoryBlock getGoSection(String sectionName) {
|
public MemoryBlock getGoSection(String sectionName) {
|
||||||
return getGoSection(program, sectionName);
|
return getGoSection(program, sectionName);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public MemoryBlock getFirstGoSection(String... sectionNames) {
|
||||||
|
return getFirstGoSection(program, sectionNames);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+54
-8
@@ -53,6 +53,14 @@ public class GoTypeManager {
|
|||||||
")" + // group=1
|
")" + // group=1
|
||||||
"(.*)" // everything else, group=2
|
"(.*)" // everything else, group=2
|
||||||
);
|
);
|
||||||
|
|
||||||
|
private static final Pattern CHAN_TYPENAME_REGEX = Pattern.compile(
|
||||||
|
"(<-)?" + // maybe <-
|
||||||
|
"chan" + // 'chan'
|
||||||
|
"(<-)?" + // maybe <-
|
||||||
|
" " + // mandatory ' '
|
||||||
|
"(.+)" // everything else, group 3
|
||||||
|
);
|
||||||
//@formatter:on
|
//@formatter:on
|
||||||
|
|
||||||
static class TypeRec {
|
static class TypeRec {
|
||||||
@@ -194,8 +202,7 @@ public class GoTypeManager {
|
|||||||
long gapStart = t1.end;
|
long gapStart = t1.end;
|
||||||
while (t2.start - gapStart > typeStructMinSize) {
|
while (t2.start - gapStart > typeStructMinSize) {
|
||||||
GoType goType = readTypeUnchecked(gapStart);
|
GoType goType = readTypeUnchecked(gapStart);
|
||||||
if (goType == null ||
|
if (goType == null) {
|
||||||
!(goType instanceof GoStructType && goType.getSymbolName().isAnonType())) {
|
|
||||||
gapStart += typeStructAlign;
|
gapStart += typeStructAlign;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@@ -440,6 +447,9 @@ public class GoTypeManager {
|
|||||||
else if (typeName.startsWith("map[")) { // not handled by splitTypeName()
|
else if (typeName.startsWith("map[")) { // not handled by splitTypeName()
|
||||||
result = newTypeRecFromDT(typeName, createSpecializedMapDT(typeName));
|
result = newTypeRecFromDT(typeName, createSpecializedMapDT(typeName));
|
||||||
}
|
}
|
||||||
|
else if (CHAN_TYPENAME_REGEX.matcher(typeName) instanceof Matcher m && m.matches()) {
|
||||||
|
result = newTypeRecFromDT(typeName, createSpecializedChanDT(typeName, m.group(3)));
|
||||||
|
}
|
||||||
else {
|
else {
|
||||||
GoKind primitiveTypeKind = GoKind.parseTypename(typeName);
|
GoKind primitiveTypeKind = GoKind.parseTypename(typeName);
|
||||||
GoTypeDef typeDef;
|
GoTypeDef typeDef;
|
||||||
@@ -475,6 +485,8 @@ public class GoTypeManager {
|
|||||||
return convertStructDef(typeName, struct);
|
return convertStructDef(typeName, struct);
|
||||||
case GoFuncTypeDef func:
|
case GoFuncTypeDef func:
|
||||||
return convertFuncDef(typeName, func);
|
return convertFuncDef(typeName, func);
|
||||||
|
case GoInterfaceDef iface:
|
||||||
|
return convertIfaceDef(typeName, iface);
|
||||||
default:
|
default:
|
||||||
throw new IOException("Go unhandled type definition: " + typeDef.toString());
|
throw new IOException("Go unhandled type definition: " + typeDef.toString());
|
||||||
}
|
}
|
||||||
@@ -512,11 +524,15 @@ public class GoTypeManager {
|
|||||||
returnDT = findDataType(func.Results.get(0).DataType);
|
returnDT = findDataType(func.Results.get(0).DataType);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
List<DataType> paramDataTypes = new ArrayList<>();
|
List<DataType> returnDataTypes = new ArrayList<>();
|
||||||
for (GoNameTypePair outParam : func.Results) {
|
for (GoNameTypePair outParam : func.Results) {
|
||||||
paramDataTypes.add(findDataType(outParam.DataType));
|
DataType dt = findDataType(outParam.DataType);
|
||||||
|
if (dt == null) {
|
||||||
|
dt = new StructureDataType(cp, ".missing_" + outParam.DataType, 0);
|
||||||
|
}
|
||||||
|
returnDataTypes.add(dt);
|
||||||
}
|
}
|
||||||
returnDT = getFuncMultiReturn(paramDataTypes);
|
returnDT = getFuncMultiReturn(returnDataTypes);
|
||||||
}
|
}
|
||||||
|
|
||||||
funcDef.setArguments(params.toArray(ParameterDefinition[]::new));
|
funcDef.setArguments(params.toArray(ParameterDefinition[]::new));
|
||||||
@@ -525,6 +541,21 @@ public class GoTypeManager {
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private TypeRec convertIfaceDef(GoSymbolName typeName, GoInterfaceDef iface)
|
||||||
|
throws IOException {
|
||||||
|
TypeRec baseIface = findTypeRec("interface {}");
|
||||||
|
if (baseIface == null) {
|
||||||
|
throw new IOException("Missing type info for base interface {}");
|
||||||
|
}
|
||||||
|
String name = typeName.asString();
|
||||||
|
if (baseIface.name.equals(name)) {
|
||||||
|
return baseIface;
|
||||||
|
}
|
||||||
|
CategoryPath cp = getCP(typeName);
|
||||||
|
TypeDef td = new TypedefDataType(cp, name, baseIface.recoveredDT);
|
||||||
|
return newTypeRecFromDT(name, td);
|
||||||
|
}
|
||||||
|
|
||||||
private TypeRec convertBasicDef(GoSymbolName typeName, GoBasicDef basicDef) throws IOException {
|
private TypeRec convertBasicDef(GoSymbolName typeName, GoBasicDef basicDef) throws IOException {
|
||||||
GoKind kind = GoKind.parseTypename(basicDef.DataType);
|
GoKind kind = GoKind.parseTypename(basicDef.DataType);
|
||||||
if (kind == null) {
|
if (kind == null) {
|
||||||
@@ -581,6 +612,7 @@ public class GoTypeManager {
|
|||||||
GoNameTypePair field = structDef.Fields.get(i);
|
GoNameTypePair field = structDef.Fields.get(i);
|
||||||
DataType dtcDT = findDataType(field.DataType);
|
DataType dtcDT = findDataType(field.DataType);
|
||||||
if (dtcDT == null) {
|
if (dtcDT == null) {
|
||||||
|
dtcDT = findDataType(field.DataType);
|
||||||
throw new IOException("Failed to get type for field [%d %s: %s] in %s"
|
throw new IOException("Failed to get type for field [%d %s: %s] in %s"
|
||||||
.formatted(i, field.Name, field.DataType, typeName));
|
.formatted(i, field.Name, field.DataType, typeName));
|
||||||
}
|
}
|
||||||
@@ -879,6 +911,21 @@ public class GoTypeManager {
|
|||||||
return voidPtrDT;
|
return voidPtrDT;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public DataType createSpecializedChanDT(String fullChanTypeName, String elementTypeName) {
|
||||||
|
try {
|
||||||
|
Structure hchanStruct = findDataType("runtime.hchan", Structure.class);
|
||||||
|
if (hchanStruct != null) {
|
||||||
|
GoSymbolName typeSymbolName = GoSymbolName.parseTypeName(elementTypeName);
|
||||||
|
return new TypedefDataType(getCP(typeSymbolName), fullChanTypeName,
|
||||||
|
dtm.getPointer(hchanStruct), dtm);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (IOException e) {
|
||||||
|
// fall thru
|
||||||
|
}
|
||||||
|
return voidPtrDT;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* {@return data type that represents a generic Go slice}
|
* {@return data type that represents a generic Go slice}
|
||||||
* @throws IOException
|
* @throws IOException
|
||||||
@@ -1076,7 +1123,7 @@ public class GoTypeManager {
|
|||||||
}
|
}
|
||||||
throw new IOException("Unknown type prefix: " + name);
|
throw new IOException("Unknown type prefix: " + name);
|
||||||
}
|
}
|
||||||
else if (name.startsWith("map[") || name.startsWith("chan ")) {
|
else if (name.startsWith("map[") || CHAN_TYPENAME_REGEX.matcher(name).matches()) {
|
||||||
return new LengthAlignment(ptrSize, align(ptrSize));
|
return new LengthAlignment(ptrSize, align(ptrSize));
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
@@ -1112,8 +1159,7 @@ public class GoTypeManager {
|
|||||||
return new LengthAlignment(ptrSize * 2, align(ptrSize));
|
return new LengthAlignment(ptrSize * 2, align(ptrSize));
|
||||||
}
|
}
|
||||||
|
|
||||||
private LengthAlignment getDataTypeLength(GoStructDef structDef)
|
private LengthAlignment getDataTypeLength(GoStructDef structDef) throws IOException {
|
||||||
throws IOException {
|
|
||||||
int len = 0;
|
int len = 0;
|
||||||
int align = 1;
|
int align = 1;
|
||||||
for (GoNameTypePair field : structDef.Fields) {
|
for (GoNameTypePair field : structDef.Fields) {
|
||||||
|
|||||||
Reference in New Issue
Block a user