Merge remote-tracking branch 'origin/GP-4870_dev747368_golang_1.23--SQUASHED'

This commit is contained in:
Ryan Kurtz
2024-12-27 06:07:08 -05:00
18 changed files with 190 additions and 104 deletions

View File

@@ -99,6 +99,7 @@ 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/golang_1.22_anybit_any.gdt||GHIDRA||||END|
data/typeinfo/golang/golang_1.23_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|

View File

@@ -4,9 +4,9 @@
* 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.
@@ -224,7 +224,7 @@ public class GolangSymbolAnalyzer extends AbstractAnalyzer {
markupSession.appendComment(func, "Golang function info: ",
AddressAnnotatedStringHandler.createAddressAnnotationString(
funcdata.getStructureContext().getStructureAddress(),
"Flags: %s, ID: %s".formatted(funcdata.getFlags(), funcdata.getFuncIDEnum())));
"Flags: %s".formatted(funcdata.getFlags())));
if (!funcSymbolNameInfo.getSymbolName().equals(funcname)) {
markupSession.appendComment(func, "Golang original name: ",
@@ -238,7 +238,7 @@ public class GolangSymbolAnalyzer extends AbstractAnalyzer {
if (funcdata.getFlags().isEmpty() /* dont try to get arg info for ASM funcs*/) {
markupSession.appendComment(func, null,
"Golang recovered signature: " + funcdata.recoverFunctionSignature());
"Golang stacktrace signature: " + funcdata.recoverFunctionSignature());
}
// Try to get a function definition signature from:
@@ -648,7 +648,7 @@ public class GolangSymbolAnalyzer extends AbstractAnalyzer {
goType != null ? callsite.returnTypeMapper.apply(goType) : null;
if (newReturnType != null) {
// Create a funcdef for this call site, where the return value is a
// specific glang type instead of the void* it was before.
// specific golang type instead of the void* it was before.
FunctionDefinitionDataType signature =
new FunctionDefinitionDataType(callsite.calledFunc, true);
signature.setReturnType(newReturnType);

View File

@@ -4,9 +4,9 @@
* 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.
@@ -447,7 +447,8 @@ public class DWARFVariable {
public List<Varnode> getVarnodes() {
List<Varnode> tmp = new ArrayList<>(storage);
if (stackStorage != null) {
tmp.add(stackStorage);
// add stack storage to the front for LE and back of the list for BE
tmp.add(program.isBigEndian() ? tmp.size() : 0, stackStorage);
}
return tmp;
}

View File

@@ -4,9 +4,9 @@
* 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.
@@ -25,6 +25,7 @@ import java.util.*;
import ghidra.app.util.bin.*;
import ghidra.app.util.bin.format.elf.info.ElfInfoItem;
import ghidra.app.util.bin.format.golang.rtti.GoRttiMapper;
import ghidra.app.util.opinion.*;
import ghidra.framework.options.Options;
import ghidra.program.model.address.Address;
import ghidra.program.model.data.*;
@@ -59,6 +60,17 @@ public class GoBuildInfo implements ElfInfoItem {
private static final int FLAG_ENDIAN = (1 << 0);
private static final int FLAG_INLINE_STRING = (1 << 1);
// map from ghidra arch string to golang arch name
private static final Map<String, String> GHIDRA_GOARCH_MAP = Map.of(
"aarch64_64", "arm64",
"arm_32", "arm",
"mips_64", "mips64",
"mips_32", "mips",
"x86_64", "amd64",
"x86_32", "386");
private static final Set<String> GOLANG_DUALENDIAN_ARCH = Set.of("mips", "mips64", "ppc64");
/**
* Reads a GoBuildInfo ".go.buildinfo" section from the specified Program, if present.
*
@@ -209,6 +221,85 @@ public class GoBuildInfo implements ElfInfoItem {
return buildSettings;
}
public GoBuildSettings getBuildSetting(String key) {
return buildSettings
.stream()
.filter(buildSetting -> buildSetting.key().equals(key))
.findFirst()
.orElse(null);
}
/**
* Returns the Golang OS string for the specified program, either from previously parsed
* metadata value, or from a static Ghidra-loader to golang mapping.
*
* @param program {@link Program}
* @return golang GOOS string, see https://go.dev/doc/install/source#environment
*/
public String getGOOS(Program program) {
GoBuildSettings goos = getBuildSetting("GOOS");
return goos != null ? goos.value() : getProgramGOOS(program);
}
/**
* Returns a Golang "GOOS" string created by a mapping from the Ghidra program's loader type.
*
* @param program {@link Program}
* @return Golang "GOOS" string
*/
public static String getProgramGOOS(Program program) {
// TODO: this mapping needs more logic
String loaderName = program.getExecutableFormat();
if (ElfLoader.ELF_NAME.equals(loaderName)) {
// TODO: this will require additional work to map all Golang OSs to Ghidra loader info
return "linux";
}
else if (PeLoader.PE_NAME.equals(loaderName)) {
return "windows";
}
else if (MachoLoader.MACH_O_NAME.equals(loaderName)) {
return "darwin";
}
return "unknown";
}
/**
* Returns the Golang Arch string for the specified program, either from previously parsed
* metadata value, or from a static Ghidra language to golang mapping.
*
* @param program {@link Program}
* @return golang GOARCH string, see https://go.dev/doc/install/source#environment
*/
public String getGOARCH(Program program) {
GoBuildSettings goos = getBuildSetting("GOARCH");
return goos != null ? goos.value() : getProgramGOARCH(program);
}
/**
* Returns a Golang "GOARCH" string created by a mapping from the Ghidra program's language (arch).
*
* @param program {@link Program}
* @return Golang "GOARCH" string
*/
public static String getProgramGOARCH(Program program) {
String langArch =
"%s_%d".formatted(
getLanguageArch(program.getLanguageID().getIdAsString()).toLowerCase(),
program.getDefaultPointerSize() * 8);
String goarch = GHIDRA_GOARCH_MAP.getOrDefault(langArch, "unknown");
if (GOLANG_DUALENDIAN_ARCH.contains(goarch) && !program.getMemory().isBigEndian()) {
// golang seems to mark the LE variant and assumes BE as the default if not marked
goarch += "le";
}
return goarch;
}
private static String getLanguageArch(String langId) {
int firstColon = langId.indexOf(':');
return firstColon > 0 ? langId.substring(0, firstColon) : langId;
}
@Override
public void markupProgram(Program program, Address address) {
decorateProgramInfo(program.getOptions(Program.PROGRAM_INFO));

View File

@@ -69,8 +69,7 @@ public class GoFuncData implements StructureMarkup<GoFuncData> {
private long cuOffset = -1;
@FieldMapping
@EOLComment("getFuncIDEnum")
private byte funcID; // see GoFuncID enum
private byte funcID;
@FieldMapping(presentWhen = "1.17+")
@EOLComment("flags")
@@ -344,14 +343,6 @@ public class GoFuncData implements StructureMarkup<GoFuncData> {
return GoFuncFlag.ASM.isSet(flag);
}
/**
* Returns the {@link GoFuncID} enum that categorizes this function
* @return the {@link GoFuncID} enum that categorizes this function
*/
public GoFuncID getFuncIDEnum() {
return GoFuncID.parseIDByte(funcID);
}
/**
* Returns information about the source file that this function was defined in.
*
@@ -407,6 +398,11 @@ public class GoFuncData implements StructureMarkup<GoFuncData> {
return getName();
}
@Override
public String getStructureNamespace() throws IOException {
return getSymbolName().packagePath();
}
@Override
public void additionalMarkup(MarkupSession session) throws IOException, CancelledException {
if (npcdata > 0) {
@@ -414,14 +410,14 @@ public class GoFuncData implements StructureMarkup<GoFuncData> {
-1, programContext.getDTM());
Address addr = context.getStructureAddress().add(getPcDataStartOffset(0));
session.markupAddress(addr, pcdataArrayDT);
session.labelAddress(addr, getStructureLabel() + "___pcdata");
session.labelAddress(addr, getStructureLabel() + "___pcdata", getStructureNamespace());
}
if (nfuncdata > 0) {
ArrayDataType funcdataArrayDT = new ArrayDataType(programContext.getUint32DT(),
nfuncdata, -1, programContext.getDTM());
Address addr = context.getStructureAddress().add(getPcDataStartOffset(npcdata));
session.markupAddress(addr, funcdataArrayDT);
session.labelAddress(addr, getStructureLabel() + "___funcdata");
session.labelAddress(addr, getStructureLabel() + "___funcdata", getStructureNamespace());
}
}

View File

@@ -1,49 +0,0 @@
/* ###
* 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.rtti;
/**
* List of function ids for runtime._func (GoFuncData) funcID field.
*/
public enum GoFuncID {
NORMAL,
ABORT,
ASMCGOCALL,
ASYNCPREEMPT,
CGOCALLBACK,
DEBUGCALLV2,
GCBGMARKWORKER,
GOEXIT,
GOGO,
GOPANIC,
HANDLEASYNCEVENT,
MCALL,
MORESTACK,
MSTART,
PANICWRAP,
RT0_GO,
RUNFINQ,
RUNTIME_MAIN,
SIGPANIC,
SYSTEMSTACK,
SYSTEMSTACK_SWITCH,
WRAPPER;
public static GoFuncID parseIDByte(int b) {
GoFuncID[] values = values();
return 0 <= b && b < values.length ? values[b] : null;
}
}

View File

@@ -4,9 +4,9 @@
* 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.
@@ -32,7 +32,7 @@ import ghidra.util.Msg;
* the interface.
*/
@PlateComment
@StructureMapping(structureName = "runtime.itab")
@StructureMapping(structureName = {"runtime.itab", "internal/abi.ITab"})
public class GoItab implements StructureMarkup<GoItab> {
@ContextField
private GoRttiMapper programContext;
@@ -40,11 +40,11 @@ public class GoItab implements StructureMarkup<GoItab> {
@ContextField
private StructureContext<GoItab> context;
@FieldMapping
@FieldMapping(fieldName = {"inter", "Inter"})
@MarkupReference("getInterfaceType")
long inter; // runtime.interfacetype *
@FieldMapping
@FieldMapping(fieldName = {"_type", "Type"})
@MarkupReference("getType")
long _type; // runtime._type *
@@ -59,7 +59,8 @@ public class GoItab implements StructureMarkup<GoItab> {
*/
@Markup
public GoInterfaceType getInterfaceType() throws IOException {
return programContext.readStructure(GoInterfaceType.class, inter);
GoType result = programContext.getGoType(inter);
return result instanceof GoInterfaceType ifaceType ? ifaceType : null;
}
/**
@@ -172,6 +173,11 @@ public class GoItab implements StructureMarkup<GoItab> {
return context;
}
@Override
public String getStructureNamespace() throws IOException {
return getType().getStructureNamespace();
}
@Override
public void additionalMarkup(MarkupSession session) throws IOException {
GoSlice funSlice = getFunSlice();
@@ -185,8 +191,8 @@ public class GoItab implements StructureMarkup<GoItab> {
GoSlice extraFunSlice =
funSlice.getSubSlice(1, funSlice.getLen() - 1, programContext.getPtrSize());
extraFunSlice.markupArray(getStructureName() + "_extra_itab_functions", null,
(DataType) null, true, session);
extraFunSlice.markupArray(getStructureName() + "_extra_itab_functions",
getStructureNamespace(), (DataType) null, true, session);
}
@Override

View File

@@ -82,7 +82,7 @@ import ghidra.util.task.UnknownProgressWrappingTaskMonitor;
*/
public class GoRttiMapper extends DataTypeMapper implements DataTypeMapperContext {
public static final GoVer SUPPORTED_MIN_VER = new GoVer(1, 15);
public static final GoVer SUPPORTED_MAX_VER = new GoVer(1, 22);
public static final GoVer SUPPORTED_MAX_VER = new GoVer(1, 23);
private static final List<String> SYMBOL_SEARCH_PREFIXES = List.of("", "_" /* macho symbols */);
private static final List<String> SECTION_PREFIXES =
@@ -1162,6 +1162,13 @@ public class GoRttiMapper extends DataTypeMapper implements DataTypeMapperContex
GoType type = it.next();
type.discoverGoTypes(discoveredTypes);
}
for (GoItab itab : module.getItabs()) {
upwtm.checkCancelled();
upwtm.setProgress(discoveredTypes.size());
itab.getInterfaceType().discoverGoTypes(discoveredTypes);
itab.getType().discoverGoTypes(discoveredTypes);
}
}
// Fix non-unique type names, which can happen when types are embedded inside a function,

View File

@@ -4,9 +4,9 @@
* 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.
@@ -81,6 +81,23 @@ public class GoArrayType extends GoType {
private boolean isValidLength() {
return 0 <= len && len <= Integer.MAX_VALUE;
}
@Override
public String getPackagePathString() {
String ppStr = super.getPackagePathString();
if (ppStr == null || ppStr.isEmpty()) {
try {
GoType elemType = getElement();
if (elemType != null) {
ppStr = elemType.getPackagePathString();
}
}
catch (IOException e) {
// fall thru
}
}
return ppStr;
}
@Override
public boolean discoverGoTypes(Set<Long> discoveredTypes) throws IOException {

View File

@@ -4,9 +4,9 @@
* 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.
@@ -23,6 +23,7 @@ import ghidra.app.util.bin.format.golang.rtti.GoSlice;
import ghidra.app.util.bin.format.golang.structmapping.*;
import ghidra.program.model.address.Address;
import ghidra.program.model.data.*;
import ghidra.util.exception.CancelledException;
/**
* A {@link GoType} structure that defines a function type.
@@ -117,7 +118,8 @@ public class GoFuncType extends GoType {
}
@Override
public void additionalMarkup(MarkupSession session) throws IOException {
public void additionalMarkup(MarkupSession session) throws IOException, CancelledException {
super.additionalMarkup(session);
GoSlice slice = getParamListSlice();
slice.markupArray(getStructureLabel() + "_paramlist", getStructureNamespace(),
GoBaseType.class, true, session);

View File

@@ -4,9 +4,9 @@
* 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.
@@ -73,6 +73,7 @@ public class GoInterfaceType extends GoType {
@Override
public void additionalMarkup(MarkupSession session) throws IOException, CancelledException {
super.additionalMarkup(session);
mhdr.markupArray(null, getStructureNamespace(), GoIMethod.class, false, session);
mhdr.markupArrayElements(GoIMethod.class, session);
}

View File

@@ -4,9 +4,9 @@
* 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.
@@ -68,6 +68,22 @@ public class GoPointerType extends GoType {
}
return true;
}
@Override
public String getPackagePathString() {
String ppStr = super.getPackagePathString();
if ( ppStr == null || ppStr.isEmpty() ) {
try {
GoType elemType = getElement();
if ( elemType != null ) {
ppStr = elemType.getPackagePathString();
}
} catch (IOException e) {
// fall thru
}
}
return ppStr;
}
@Override
public String getStructureNamespace() throws IOException {

View File

@@ -4,9 +4,9 @@
* 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.
@@ -93,7 +93,7 @@ public class GoSliceType extends GoType {
@Override
public String getStructureNamespace() throws IOException {
String packagePath = getPackagePathString();
if (packagePath != null) {
if (packagePath != null && !packagePath.isEmpty() ) {
return packagePath;
}
GoType elementType = getElement();

View File

@@ -4,9 +4,9 @@
* 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.
@@ -190,14 +190,10 @@ public abstract class GoType implements StructureMarkup<GoType> {
GoUncommonType ut = getUncommonType();
if (ut != null) {
GoSlice slice = ut.getMethodsSlice();
slice.markupArray(getStructureName() + "_methods", getStructureNamespace(),
slice.markupArray(getStructureLabel() + "_methods", getStructureNamespace(),
GoMethod.class, false, session);
slice.markupArrayElements(GoMethod.class, session);
session.labelStructure(ut,
typ.getName() + "_" +
programContext.getStructureDataTypeName(GoUncommonType.class),
getStructureNamespace());
session.labelStructure(ut, getStructureLabel() + "_uncommon", getStructureNamespace());
}
}

View File

@@ -4,9 +4,9 @@
* 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.
@@ -53,6 +53,7 @@ public class DataTypeArchiveIDTest extends AbstractGenericTest {
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/golang/golang_1.22_anybit_any.gdt", "3596108668808850319"),
Map.entry("typeinfo/golang/golang_1.23_anybit_any.gdt", "3629085086035854850"),
Map.entry("typeinfo/rust/rust-common.gdt", "3557867258392862055"));
//@formatter:on

View File

@@ -1,6 +1,6 @@
<golang>
<!-- see https://github.com/golang/go/blob/master/src/internal/abi/abi_arm64.go -->
<register_info versions="V1_17,V1_18,V1_19,V1_20,V1_21,V1_22">
<register_info versions="V1_17,V1_18,V1_19,V1_20,V1_21,V1_22,V1_23">
<int_registers list="x0,x1,x2,x3,x4,x5,x6,x7,x8,x9,x10,x11,x12,x13,x14,x15"/>
<float_registers list="q0,q1,q2,q3,q4,q5,q6,q7,q8,q9,q10,q11,q12,q13,q14,q15"/>
<stack initialoffset="8" maxalign="8"/>

View File

@@ -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,V1_21,V1_22"> <!-- "all", or comma list of: V1_2,V1_16,etc -->
<register_info versions="V1_17,V1_18,V1_19,V1_20,V1_21,V1_22,V1_23"> <!-- "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"/>