Merge remote-tracking branch 'origin/GP-6528_dev747368_golang_1.26'

(Closes #9013)
This commit is contained in:
Ryan Kurtz
2026-03-04 13:02:01 -05:00
10 changed files with 79 additions and 34 deletions
@@ -102,6 +102,7 @@ data/typeinfo/golang/go1.22.0.json||GHIDRA||||END|
data/typeinfo/golang/go1.23.0.json||GHIDRA||||END|
data/typeinfo/golang/go1.24.0.json||GHIDRA||||END|
data/typeinfo/golang/go1.25.0.json||GHIDRA||||END|
data/typeinfo/golang/go1.26.0.json||GHIDRA||||END|
data/typeinfo/golang/golang_1.15_anybit_any.gdt||GHIDRA||||END|
data/typeinfo/golang/golang_1.16_anybit_any.gdt||GHIDRA||||END|
data/typeinfo/golang/golang_1.17_anybit_any.gdt||GHIDRA||||END|
File diff suppressed because one or more lines are too long
@@ -37,10 +37,14 @@ import ghidra.util.Msg;
* <p>
* Similar to {@link NoteGoBuildId}, but re-implemented here because of the different
* serialization used.
*
* TODO: stop using 83 byte fixed len for buildid string, use leading / trailing quotes
*/
public class GoBuildId {
private static final byte[] GO_BUILDID_MAGIC =
"\u00ff Go build ID: \"".getBytes(StandardCharsets.ISO_8859_1);
private static final byte[] GO_BUIlDID_TRAILING_MAGIC =
"\"\n \u00ff".getBytes(StandardCharsets.ISO_8859_1);
private static final int BUILDID_STR_LEN = 83;
public static ItemWithAddress<GoBuildId> findBuildId(Program program) {
@@ -64,7 +68,14 @@ public class GoBuildId {
if (!Arrays.equals(magic, GO_BUILDID_MAGIC)) {
return null;
}
String buildIdStr = br.readNextAsciiString(BUILDID_STR_LEN);
byte[] trailingMagic = br.readNextByteArray(GO_BUIlDID_TRAILING_MAGIC.length);
if (!Arrays.equals(trailingMagic, GO_BUIlDID_TRAILING_MAGIC)) {
return null;
}
return new GoBuildId(buildIdStr);
}
catch (IOException e) {
@@ -81,7 +92,8 @@ public class GoBuildId {
* @return GoBuildId instance, or null if not present
*/
public static GoBuildId read(InputStream is) {
byte[] buffer = new byte[GO_BUILDID_MAGIC.length + BUILDID_STR_LEN];
byte[] buffer =
new byte[GO_BUILDID_MAGIC.length + BUILDID_STR_LEN + GO_BUIlDID_TRAILING_MAGIC.length];
try {
int bytesRead = is.read(buffer);
if (bytesRead == buffer.length) {
@@ -127,6 +139,8 @@ public class GoBuildId {
new StructureDataType(GoConstants.GOLANG_CATEGORYPATH, "GoBuildId", 0, dtm);
result.add(StringDataType.dataType, GO_BUILDID_MAGIC.length, "magic", null);
result.add(StringDataType.dataType, BUILDID_STR_LEN, "buildId", null);
result.add(StringDataType.dataType, GO_BUIlDID_TRAILING_MAGIC.length, "trailing_magic",
null);
return result;
}
@@ -412,14 +412,17 @@ public class GoModuledata implements StructureMarkup<GoModuledata> {
* @return new GoModuledata instance, or null if not found
* @throws IOException if error reading found structure
*/
/* package */ static GoModuledata getFirstModuledata(GoRttiMapper context)
throws IOException {
/* package */ static GoModuledata getFirstModuledata(GoRttiMapper context) throws IOException {
Program program = context.getProgram();
Symbol firstModuleDataSymbol = GoRttiMapper.getGoSymbol(program, "runtime.firstmoduledata");
if (firstModuleDataSymbol == null) {
return null;
MemoryBlock memblk = context.getGoSection("go.module");
if (memblk != null) {
return context.readStructure(GoModuledata.class, memblk.getStart());
}
return context.readStructure(GoModuledata.class, firstModuleDataSymbol.getAddress());
Symbol firstModuleDataSymbol = GoRttiMapper.getGoSymbol(program, "runtime.firstmoduledata");
if (firstModuleDataSymbol != null) {
return context.readStructure(GoModuledata.class, firstModuleDataSymbol.getAddress());
}
return null;
}
/**
@@ -177,7 +177,7 @@ public class GoPcHeader {
@FieldMapping
private byte ptrSize;
@FieldMapping(presentWhen = "1.18+")
@FieldMapping(presentWhen = "1.18-1.25")
@MarkupReference
private long textStart; // should be same as offset of ".text"
@@ -216,7 +216,7 @@ public class GoPcHeader {
* {@return the address of where the text area starts}
*/
public Address getTextStart() {
return programContext.getDataAddress(textStart);
return textStart != 0 ? programContext.getDataAddress(textStart) : null;
}
/**
@@ -76,7 +76,7 @@ import ghidra.util.task.UnknownProgressWrappingTaskMonitor;
* </ul>
*/
public class GoRttiMapper extends DataTypeMapper implements DataTypeMapperContext {
public static final GoVerRange SUPPORTED_VERSIONS = GoVerRange.parse("1.15-1.25");
public static final GoVerRange SUPPORTED_VERSIONS = GoVerRange.parse("1.15-1.26");
private static final List<String> SYMBOL_SEARCH_PREFIXES = List.of("", "_" /* macho symbols */);
private static final List<String> SECTION_PREFIXES =
@@ -83,7 +83,7 @@ public class GoBaseType implements StructureVerifier {
* {@return the {@link GoTypeFlag}s assigned to this type definition}
*/
public Set<GoTypeFlag> getFlags() {
return GoTypeFlag.parseFlags(tflag);
return GoTypeFlag.parseFlags(tflag, programContext.getGoVer());
}
/**
@@ -98,7 +98,7 @@ public class GoBaseType implements StructureVerifier {
* structure}
*/
public boolean hasUncommonType() {
return GoTypeFlag.Uncommon.isSet(tflag);
return GoTypeFlag.Uncommon.isSet(tflag, programContext.getGoVer());
}
/**
@@ -115,7 +115,9 @@ public class GoBaseType implements StructureVerifier {
*/
public String getName() {
String s = programContext.getSafeName(this::getGoName, this, "").getName();
return GoTypeFlag.ExtraStar.isSet(tflag) && s.startsWith("*") ? s.substring(1) : s;
return GoTypeFlag.ExtraStar.isSet(tflag, programContext.getGoVer()) && s.startsWith("*")
? s.substring(1)
: s;
}
/**
@@ -42,20 +42,24 @@ public class GoMapType extends GoType {
@MarkupReference("getElement")
private long elem; // ptr to type
@FieldMapping
@FieldMapping(presentWhen = "-1.25")
@MarkupReference("getBucket")
private long bucket; // ptr to type
@FieldMapping(presentWhen = "1.26-")
@MarkupReference("getGroup")
private long group; // ptr to group type
@FieldMapping
private long hasher; // pointer to "func(Pointer, pointer) pointer"
@FieldMapping
@FieldMapping(presentWhen = "-1.25")
private int keysize;
@FieldMapping(fieldName = {"elemsize", "ValueSize"})
@FieldMapping(fieldName = { "elemsize", "ValueSize" }, presentWhen = "-1.25")
private int elemsize;
@FieldMapping
@FieldMapping(presentWhen = "-1.25")
private int bucketsize;
@FieldMapping
@@ -95,7 +99,18 @@ public class GoMapType extends GoType {
*/
@Markup
public GoType getBucket() throws IOException {
return programContext.getGoTypes().getType(bucket);
return bucket != 0 ? programContext.getGoTypes().getType(bucket) : null;
}
/**
* Returns the GoType that defines the map's group, referenced by the group field's markup annotation
*
* @return GoType that defines the map's group
* @throws IOException if error reading data
*/
@Markup
public GoType getGroup() throws IOException {
return group != 0 ? programContext.getGoTypes().getType(group) : null;
}
@Override
@@ -26,11 +26,16 @@ import ghidra.app.util.bin.format.golang.GoVerRange;
*/
public enum GoTypeFlag {
Uncommon(1 << 0, GoVerRange.ALL), // 1
ExtraStar(1 << 1, GoVerRange.ALL), // 2
Named(1 << 2, GoVerRange.ALL), // 4
RegularMemory(1 << 3, GoVerRange.ALL), // 8
UnrolledBitmap(1 << 4, GoVerRange.parse("1.22-")); // 16
Uncommon(1 << 0, GoVerRange.ALL), // 1
ExtraStar(1 << 1, GoVerRange.ALL), // 2
Named(1 << 2, GoVerRange.ALL), // 4
RegularMemory(1 << 3, GoVerRange.ALL), // 8
UnrolledBitmap(1 << 4, GoVerRange.parse("1.22-1.23")), // 16
GCMaskOnDemand(1 << 4, GoVerRange.parse("1.24-")), // 16
// FUTURE: "value of this type is stored directly in the data field of an interface instead of
// indirectly", same as testing Size_ == PtrBytes == goarch.PtrSize
DirectIFace(1 << 5, GoVerRange.parse("1.24-")); // 32
private final int value;
private GoVerRange validVersions;
@@ -44,8 +49,16 @@ public enum GoTypeFlag {
return value;
}
public boolean isSet(int i) {
return (i & value) != 0;
/**
* Returns true if this enum instance is set in the supplied integer
* (for the specified go version)
*
* @param i int packed flag
* @param ver version of this binary
* @return boolean true if this flag is set
*/
public boolean isSet(int i, GoVer ver) {
return validVersions.contains(ver) && (i & value) != 0;
}
//----------------------------------------------------------
@@ -53,19 +66,18 @@ public enum GoTypeFlag {
private static final GoTypeFlag[] lookupvalues = values();
public static boolean isValid(int b, GoVer ver) {
int maxMask = 0;
for (GoTypeFlag flag : lookupvalues) {
if (flag.validVersions.contains(ver)) {
maxMask |= flag.value;
b &= ~flag.value;
}
}
return b <= maxMask;
return b == 0;
}
public static Set<GoTypeFlag> parseFlags(int b) {
public static Set<GoTypeFlag> parseFlags(int b, GoVer ver) {
EnumSet<GoTypeFlag> result = EnumSet.noneOf(GoTypeFlag.class);
for (GoTypeFlag flag : lookupvalues) {
if (flag.isSet(b)) {
if (flag.isSet(b, ver)) {
result.add(flag);
}
}
@@ -331,14 +331,11 @@ public class GoApiSnapshotGeneratorTest extends AbstractGenericTest {
* Build a frankenstein goroot directory using the guts of a go install (liveGoRoot) and
* the src directory from a specific tagged version of a go git repo directory.
*
* @param goRepoDir path to a golang git repo
* @param liveGoRoot path to an installed golang instance
* @param ver go version to checkout from the git repo and copy to the new directory
* @return path to newly created goroot directory (under the workDir)
* @throws IOException if failure
*/
File createVersionedGoRoot(GoVer ver)
throws IOException {
File createVersionedGoRoot(GoVer ver) throws IOException {
String verTagName = getGoRepoTagName(GOLANG_REPO_DIR, ver);
execGitCmd(GOLANG_REPO_DIR, null, "checkout", "-q", verTagName);