readFunc) {
if (memBlock != null) {
try (ByteProvider bp =
MemoryByteProvider.createMemoryBlockByteProvider(program.getMemory(), memBlock)) {
@@ -82,10 +87,9 @@ public interface ElfInfoItem {
}
catch (IOException e) {
Msg.warn(ElfInfoItem.class,
- "Unable to read Elf item in section: %s".formatted(sectionName), e);
+ "Unable to read Elf item in section: %s".formatted(memBlock.getName()), e);
}
}
return null;
}
-
}
diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/golang/PEGoBuildId.java b/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/golang/GoBuildId.java
similarity index 62%
rename from Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/golang/PEGoBuildId.java
rename to Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/golang/GoBuildId.java
index f8056844bb..b26cdf7cb7 100644
--- a/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/golang/PEGoBuildId.java
+++ b/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/golang/GoBuildId.java
@@ -20,49 +20,52 @@ import java.io.InputStream;
import java.nio.charset.StandardCharsets;
import java.util.Arrays;
-import ghidra.app.util.bin.BinaryReader;
-import ghidra.app.util.bin.ByteArrayProvider;
-import ghidra.app.util.bin.format.elf.info.ElfInfoItem;
+import ghidra.app.util.bin.*;
+import ghidra.app.util.bin.format.elf.info.ElfInfoItem.ItemWithAddress;
+import ghidra.app.util.bin.format.elf.info.ElfInfoItem.ReaderFunc;
+import ghidra.app.util.bin.format.golang.rtti.GoRttiMapper;
import ghidra.program.model.address.Address;
import ghidra.program.model.data.*;
import ghidra.program.model.data.DataUtilities.ClearDataMode;
import ghidra.program.model.listing.Program;
+import ghidra.program.model.mem.MemoryBlock;
import ghidra.program.model.util.CodeUnitInsertionException;
import ghidra.util.Msg;
/**
- * Similar to {@link NoteGoBuildId}, but re-implemented here because of the different
- * serialization used in PE binaries. (the logic about the buildid payload is trivial so
- * there is no worry about duplicating code)
+ * This class represents a go build id string, along with a magic header.
*
- *
+ * Similar to {@link NoteGoBuildId}, but re-implemented here because of the different
+ * serialization used.
*/
-public class PEGoBuildId implements ElfInfoItem {
+public class GoBuildId {
private static final byte[] GO_BUILDID_MAGIC =
"\u00ff Go build ID: \"".getBytes(StandardCharsets.ISO_8859_1);
private static final int BUILDID_STR_LEN = 83;
- public static ItemWithAddress findBuildId(Program program) {
- ItemWithAddress wrappedItem = ElfInfoItem.readItemFromSection(program,
- ".text", PEGoBuildId::read);
+ public static ItemWithAddress findBuildId(Program program) {
+ MemoryBlock txtBlock = GoRttiMapper.getGoSection(program, "text");
+ ItemWithAddress wrappedItem =
+ readItemFromSection(program, txtBlock, GoBuildId::read);
return wrappedItem;
}
+
/**
- * Attempts to read a PEGoBuildId from the specified stream.
+ * Attempts to read a GoBuildId from the specified stream.
*
* @param br BinaryReader stream (typically the beginning of the ".text" section)
* @param program_notused not used, but needed to match functional interface
- * @return PEGoBuildId instance, or null if not present
+ * @return GoBuildId instance, or null if not present
*/
- public static PEGoBuildId read(BinaryReader br, Program program_notused) {
+ public static GoBuildId read(BinaryReader br, Program program_notused) {
try {
byte[] magic = br.readNextByteArray(GO_BUILDID_MAGIC.length);
if (!Arrays.equals(magic, GO_BUILDID_MAGIC)) {
return null;
}
String buildIdStr = br.readNextAsciiString(BUILDID_STR_LEN);
- return new PEGoBuildId(buildIdStr);
+ return new GoBuildId(buildIdStr);
}
catch (IOException e) {
// fall thru and return null
@@ -71,13 +74,13 @@ public class PEGoBuildId implements ElfInfoItem {
}
/**
- * Attempts to read a PEGoBuildId from the specified InputStream (useful for early compiler
+ * Attempts to read a GoBuildId from the specified InputStream (useful for early compiler
* detection before file is loaded).
*
* @param is {@link InputStream} providing access to the ".text" section of a PE binary
- * @return PEGoBuildId instance, or null if not present
+ * @return GoBuildId instance, or null if not present
*/
- public static PEGoBuildId read(InputStream is) {
+ public static GoBuildId read(InputStream is) {
byte[] buffer = new byte[GO_BUILDID_MAGIC.length + BUILDID_STR_LEN];
try {
int bytesRead = is.read(buffer);
@@ -94,7 +97,7 @@ public class PEGoBuildId implements ElfInfoItem {
private final String buildId;
- public PEGoBuildId(String buildId) {
+ public GoBuildId(String buildId) {
this.buildId = buildId;
}
@@ -102,7 +105,6 @@ public class PEGoBuildId implements ElfInfoItem {
return buildId;
}
- @Override
public void markupProgram(Program program, Address address) {
program.getOptions(Program.PROGRAM_INFO)
.setString(NoteGoBuildId.PROGRAM_INFO_KEY, getBuildId());
@@ -115,7 +117,7 @@ public class PEGoBuildId implements ElfInfoItem {
}
}
catch (CodeUnitInsertionException e) {
- Msg.error(this, "Failed to markup PEGoBuildId at %s: %s".formatted(address, this));
+ Msg.error(this, "Failed to markup GoBuildId at %s: %s".formatted(address, this));
}
}
@@ -128,4 +130,24 @@ public class PEGoBuildId implements ElfInfoItem {
return result;
}
+
+ //----------------------------------------------------------------------------------------------
+ static ItemWithAddress readItemFromSection(Program program, MemoryBlock memBlock,
+ ReaderFunc readFunc) {
+ if (memBlock != null) {
+ try (ByteProvider bp =
+ MemoryByteProvider.createMemoryBlockByteProvider(program.getMemory(), memBlock)) {
+ BinaryReader br = new BinaryReader(bp, !program.getMemory().isBigEndian());
+
+ T item = readFunc.read(br, program);
+ return item != null ? new ItemWithAddress<>(item, memBlock.getStart()) : null;
+ }
+ catch (IOException e) {
+ Msg.warn(GoBuildId.class,
+ "Unable to read GoBuildId in section: %s".formatted(memBlock.getName()), e);
+ }
+ }
+ return null;
+ }
+
}
diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/golang/GoBuildInfo.java b/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/golang/GoBuildInfo.java
index 6a4cfac76e..ad978d49e0 100644
--- a/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/golang/GoBuildInfo.java
+++ b/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/golang/GoBuildInfo.java
@@ -24,12 +24,14 @@ 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.framework.options.Options;
import ghidra.program.model.address.Address;
import ghidra.program.model.data.*;
import ghidra.program.model.data.DataUtilities.ClearDataMode;
import ghidra.program.model.lang.Endian;
import ghidra.program.model.listing.Program;
+import ghidra.program.model.mem.MemoryBlock;
import ghidra.program.model.util.CodeUnitInsertionException;
import ghidra.util.*;
@@ -39,7 +41,9 @@ import ghidra.util.*;
*/
public class GoBuildInfo implements ElfInfoItem {
- public static final String SECTION_NAME = ".go.buildinfo";
+ public static final String SECTION_NAME = "go.buildinfo";
+ public static final String ELF_SECTION_NAME = ".go.buildinfo";
+ public static final String MACHO_SECTION_NAME = "go_buildinfo";
// Defined in golang src/debug/buildinfo/buildinfo.go
// NOTE: ISO_8859_1 charset is required to not mangle the \u00ff when converting to bytes
@@ -73,17 +77,32 @@ public class GoBuildInfo implements ElfInfoItem {
* @return new {@link GoBuildInfo} instance, if present, null if missing or error
*/
public static ItemWithAddress findBuildInfo(Program program) {
- // try as if binary is ELF
- ItemWithAddress wrappedItem =
- ElfInfoItem.readItemFromSection(program, SECTION_NAME, GoBuildInfo::read);
+ ItemWithAddress wrappedItem = readItemFromSection(program,
+ GoRttiMapper.getFirstGoSection(program, SECTION_NAME, MACHO_SECTION_NAME));
if (wrappedItem == null) {
- // if not present, try common PE location for buildinfo, using "ElfInfoItem" logic
- // even though this might be a PE binary, cause it doesn't matter
- wrappedItem = ElfInfoItem.readItemFromSection(program, ".data", GoBuildInfo::read);
+ // if not present, try common PE location for buildinfo
+ wrappedItem = readItemFromSection(program, GoRttiMapper.getGoSection(program, "data"));
}
return wrappedItem;
}
+ private static ItemWithAddress readItemFromSection(Program program,
+ MemoryBlock memBlock) {
+ if (memBlock != null) {
+ try (ByteProvider bp =
+ MemoryByteProvider.createMemoryBlockByteProvider(program.getMemory(), memBlock)) {
+ BinaryReader br = new BinaryReader(bp, !program.getMemory().isBigEndian());
+
+ GoBuildInfo item = read(br, program);
+ return new ItemWithAddress<>(item, memBlock.getStart());
+ }
+ catch (IOException e) {
+ // fall thru, return null
+ }
+ }
+ return null;
+ }
+
/**
* Reads a GoBuildInfo ".go.buildinfo" section from the specified stream.
*
diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/golang/GoFunctionFixup.java b/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/golang/GoFunctionFixup.java
index 4e410dd72b..8995a86f34 100644
--- a/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/golang/GoFunctionFixup.java
+++ b/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/golang/GoFunctionFixup.java
@@ -150,7 +150,7 @@ public class GoFunctionFixup {
paramDT.getLength());
VariableStorage varStorage = new VariableStorage(program, List.of(stackVarnode));
LocalVariableImpl localVar =
- new LocalVariableImpl(param.getName() + "-spill", 0, paramDT, varStorage, program);
+ new LocalVariableImpl(param.getName() + "_spill", 0, paramDT, varStorage, program);
// TODO: needs more thought
func.addLocalVariable(localVar, SourceType.USER_DEFINED);
@@ -229,12 +229,12 @@ public class GoFunctionFixup {
returnDT = multiReturn.getStruct();
for (DataTypeComponent dtc : multiReturn.getNormalStorageComponents()) {
- allocateReturnStorage(program, dtc.getFieldName() + "-return-result-alias",
+ allocateReturnStorage(program, dtc.getFieldName() + "_return_result_alias",
dtc.getDataType(), storageAllocator, varnodes, returnResultAliasVars,
false);
}
for (DataTypeComponent dtc : multiReturn.getStackStorageComponents()) {
- allocateReturnStorage(program, dtc.getFieldName() + "-return-result-alias",
+ allocateReturnStorage(program, dtc.getFieldName() + "_return_result_alias",
dtc.getDataType(), storageAllocator, varnodes, returnResultAliasVars,
false);
}
@@ -249,7 +249,7 @@ public class GoFunctionFixup {
varnodes.add(new Varnode(GoRttiMapper.getZerobaseAddress(program), 1));
}
else {
- allocateReturnStorage(program, "return-value-alias-variable", returnDT,
+ allocateReturnStorage(program, "return_value_alias_variable", returnDT,
storageAllocator, varnodes, returnResultAliasVars, true);
}
diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/golang/GolangElfInfoProducer.java b/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/golang/GolangElfInfoProducer.java
index cd2d2adc6e..2654b53efd 100644
--- a/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/golang/GolangElfInfoProducer.java
+++ b/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/golang/GolangElfInfoProducer.java
@@ -42,7 +42,7 @@ import ghidra.util.task.TaskMonitor;
*/
public class GolangElfInfoProducer implements ElfInfoProducer {
private static final Map> GOLANGINFO_READERS = Map.of(
- GoBuildInfo.SECTION_NAME, GoBuildInfo::read,
+ GoBuildInfo.ELF_SECTION_NAME, GoBuildInfo::read,
NoteGoBuildId.SECTION_NAME, NoteGoBuildId::read);
private ElfLoadHelper elfLoadHelper;
diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/golang/rtti/GoModuledata.java b/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/golang/rtti/GoModuledata.java
index 2b8eb37cc1..b307b04965 100644
--- a/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/golang/rtti/GoModuledata.java
+++ b/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/golang/rtti/GoModuledata.java
@@ -21,14 +21,12 @@ import java.util.*;
import ghidra.app.util.bin.BinaryReader;
import ghidra.app.util.bin.format.golang.rtti.types.GoType;
import ghidra.app.util.bin.format.golang.structmapping.*;
-import ghidra.program.model.address.Address;
-import ghidra.program.model.address.AddressRange;
+import ghidra.program.model.address.*;
import ghidra.program.model.data.*;
import ghidra.program.model.listing.Program;
import ghidra.program.model.mem.Memory;
import ghidra.program.model.mem.MemoryBlock;
import ghidra.program.model.symbol.Symbol;
-import ghidra.program.model.symbol.SymbolUtilities;
import ghidra.util.Msg;
import ghidra.util.exception.CancelledException;
import ghidra.util.task.TaskMonitor;
@@ -50,10 +48,25 @@ public class GoModuledata implements StructureMarkup {
@MarkupReference
private long pcHeader; // pointer to the GoPcHeader instance, useful for bootstrapping
+ @FieldMapping
+ private long data;
+
+ @FieldMapping
+ private long edata;
+
@FieldMapping
@MarkupReference
private long text;
+ @FieldMapping
+ private long etext;
+
+ @FieldMapping
+ private long noptrdata;
+
+ @FieldMapping
+ private long enoptrdata;
+
@FieldMapping(fieldName = "types")
private long typesOffset;
@@ -63,6 +76,9 @@ public class GoModuledata implements StructureMarkup {
@FieldMapping(optional = true)
private long gofunc;
+ @FieldMapping
+ private long end;
+
@FieldMapping(fieldName = "typelinks")
private GoSlice typeLinks;
@@ -120,6 +136,24 @@ public class GoModuledata implements StructureMarkup {
return programContext.getCodeAddress(text);
}
+ public AddressRange getTextRange() {
+ Address textstart = getText();
+ Address textend = programContext.getCodeAddress(etext);
+ return new AddressRangeImpl(textstart, textend);
+ }
+
+ public AddressRange getRoDataRange() {
+ Address roStart = programContext.getCodeAddress(etext); // TODO: rodata is avail in newer govers
+ Address roEnd = programContext.getCodeAddress(end);
+ return new AddressRangeImpl(roStart, roEnd);
+ }
+
+ public AddressRange getDataRange() {
+ Address dataStart = programContext.getCodeAddress(data);
+ Address dataEnd = programContext.getCodeAddress(edata);
+ return new AddressRangeImpl(dataStart, dataEnd);
+ }
+
/**
* Returns the starting offset of type info
*
@@ -190,12 +224,12 @@ public class GoModuledata implements StructureMarkup {
* @return true if this module data structure contains sane values
*/
public boolean isValid() {
- MemoryBlock txtBlock = programContext.getProgram().getMemory().getBlock(".text");
+ MemoryBlock txtBlock = programContext.getGoSection("text");
if (txtBlock != null && !txtBlock.contains(getText())) {
return false;
}
- MemoryBlock typelinkBlock = programContext.getProgram().getMemory().getBlock(".typelink");
+ MemoryBlock typelinkBlock = programContext.getGoSection("typelink");
if (typelinkBlock != null &&
typelinkBlock.getStart().getOffset() != typeLinks.getArrayOffset()) {
return false;
@@ -396,8 +430,7 @@ public class GoModuledata implements StructureMarkup {
/* package */ static GoModuledata getFirstModuledata(GoRttiMapper context)
throws IOException {
Program program = context.getProgram();
- Symbol firstModuleDataSymbol =
- SymbolUtilities.getUniqueSymbol(program, "runtime.firstmoduledata");
+ Symbol firstModuleDataSymbol = GoRttiMapper.getGoSymbol(program, "runtime.firstmoduledata");
if (firstModuleDataSymbol == null) {
return null;
}
diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/golang/rtti/GoPcHeader.java b/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/golang/rtti/GoPcHeader.java
index cc7c620105..a56b6d339f 100644
--- a/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/golang/rtti/GoPcHeader.java
+++ b/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/golang/rtti/GoPcHeader.java
@@ -27,7 +27,6 @@ import ghidra.program.model.listing.Program;
import ghidra.program.model.mem.Memory;
import ghidra.program.model.mem.MemoryBlock;
import ghidra.program.model.symbol.Symbol;
-import ghidra.program.model.symbol.SymbolUtilities;
import ghidra.util.task.TaskMonitor;
/**
@@ -39,7 +38,7 @@ import ghidra.util.task.TaskMonitor;
@StructureMapping(structureName = "runtime.pcHeader")
public class GoPcHeader {
private static final String RUNTIME_PCLNTAB_SYMBOLNAME = "runtime.pclntab";
- public static final String GOPCLNTAB_SECTION_NAME = ".gopclntab";
+ public static final String GOPCLNTAB_SECTION_NAME = "gopclntab";
public static final int GO_1_2_MAGIC = 0xfffffffb;
public static final int GO_1_16_MAGIC = 0xfffffffa;
public static final int GO_1_18_MAGIC = 0xfffffff0;
@@ -51,12 +50,12 @@ public class GoPcHeader {
* @return {@link Address} of go pclntab, or null if not present
*/
public static Address getPclntabAddress(Program program) {
- MemoryBlock pclntabBlock = program.getMemory().getBlock(GOPCLNTAB_SECTION_NAME);
+ MemoryBlock pclntabBlock = GoRttiMapper.getGoSection(program, GOPCLNTAB_SECTION_NAME);
if (pclntabBlock != null) {
return pclntabBlock.getStart();
}
// PE binaries have a symbol instead of a named section
- Symbol pclntabSymbol = SymbolUtilities.getUniqueSymbol(program, RUNTIME_PCLNTAB_SYMBOLNAME);
+ Symbol pclntabSymbol = GoRttiMapper.getGoSymbol(program, RUNTIME_PCLNTAB_SYMBOLNAME);
return pclntabSymbol != null
? pclntabSymbol.getAddress()
: null;
diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/golang/rtti/GoRttiMapper.java b/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/golang/rtti/GoRttiMapper.java
index 4a8e8853e3..34a9353539 100644
--- a/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/golang/rtti/GoRttiMapper.java
+++ b/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/golang/rtti/GoRttiMapper.java
@@ -35,8 +35,8 @@ import ghidra.app.util.bin.format.golang.*;
import ghidra.app.util.bin.format.golang.rtti.types.*;
import ghidra.app.util.bin.format.golang.structmapping.*;
import ghidra.app.util.importer.MessageLog;
-import ghidra.app.util.opinion.ElfLoader;
-import ghidra.app.util.opinion.PeLoader;
+import ghidra.app.util.opinion.*;
+import ghidra.framework.Platform;
import ghidra.framework.store.LockException;
import ghidra.program.model.address.*;
import ghidra.program.model.data.*;
@@ -44,9 +44,9 @@ import ghidra.program.model.data.DataTypeConflictHandler.ConflictResult;
import ghidra.program.model.data.StandAloneDataTypeManager.LanguageUpdateOption;
import ghidra.program.model.lang.*;
import ghidra.program.model.listing.*;
-import ghidra.program.model.mem.Memory;
import ghidra.program.model.mem.MemoryBlock;
-import ghidra.program.model.symbol.*;
+import ghidra.program.model.symbol.Symbol;
+import ghidra.program.model.symbol.SymbolType;
import ghidra.util.*;
import ghidra.util.exception.*;
import ghidra.util.task.TaskMonitor;
@@ -210,9 +210,13 @@ public class GoRttiMapper extends DataTypeMapper {
else if (PeLoader.PE_NAME.equals(loaderName)) {
return "win";
}
- else {
- return null;
+ else if (MachoLoader.MACH_O_NAME.equals(loaderName)) {
+ LanguageID languageID = program.getLanguageCompilerSpecPair().getLanguageID();
+ if ("AARCH64:LE:64:AppleSilicon".equals(languageID.getIdAsString())) {
+ return Platform.MAC_ARM_64.getDirectoryName(); // mac_arm_64
+ }
}
+ return null;
}
/**
@@ -252,6 +256,58 @@ public class GoRttiMapper extends DataTypeMapper {
program.getCompilerSpec().getCompilerSpecDescription().getCompilerSpecName());
}
+ public static boolean hasGolangSections(List sectionNames) {
+ for (String sectionName : sectionNames) {
+ if (sectionName.contains("gopclntab") ||
+ sectionName.contains(GoBuildInfo.MACHO_SECTION_NAME) ||
+ sectionName.contains(GoBuildInfo.SECTION_NAME)) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ private static final List SYMBOL_SEARCH_PREFIXES = List.of("", "_" /* macho symbols */);
+ private static final List SECTION_PREFIXES =
+ List.of("." /* ELF */, "__" /* macho sections */);
+
+ /**
+ * Returns a matching symbol from the specified program, using golang specific logic.
+ *
+ * @param program {@link Program}
+ * @param symbolName name of golang symbol
+ * @return {@link Symbol}, or null if not found
+ */
+ public static Symbol getGoSymbol(Program program, String symbolName) {
+ for (String prefix : SYMBOL_SEARCH_PREFIXES) {
+ List symbols = program.getSymbolTable().getSymbols(prefix + symbolName, null);
+ if (symbols.size() == 1) {
+ return symbols.get(0);
+ }
+ }
+ return null;
+ }
+
+ public static MemoryBlock getGoSection(Program program, String sectionName) {
+ for (String prefix : SECTION_PREFIXES) {
+ MemoryBlock memBlock = program.getMemory().getBlock(prefix + sectionName);
+ if (memBlock != null) {
+ return memBlock;
+ }
+ }
+ return null;
+ }
+
+ public static MemoryBlock getFirstGoSection(Program program, String... blockNames) {
+ for (String blockToSearch : blockNames) {
+ MemoryBlock memBlock = getGoSection(program, blockToSearch);
+ if (memBlock != null) {
+ return memBlock;
+ }
+ }
+ return null;
+ }
+
/**
* Return the address of the golang zerobase symbol, or an artificial substitute.
*
@@ -261,7 +317,7 @@ public class GoRttiMapper extends DataTypeMapper {
* @return {@link Address} of the runtime.zerobase, or artificial substitute
*/
public static Address getZerobaseAddress(Program prog) {
- Symbol zerobaseSym = SymbolUtilities.getUniqueSymbol(prog, "runtime.zerobase");
+ Symbol zerobaseSym = getGoSymbol(prog, "runtime.zerobase");
Address zerobaseAddr =
zerobaseSym != null ? zerobaseSym.getAddress() : getArtificalZerobaseAddress(prog);
if (zerobaseAddr == null) {
@@ -276,8 +332,7 @@ public class GoRttiMapper extends DataTypeMapper {
"ARTIFICIAL.runtime.zerobase";
private static Address getArtificalZerobaseAddress(Program program) {
- Symbol zerobaseSym =
- SymbolUtilities.getUniqueSymbol(program, ARTIFICIAL_RUNTIME_ZEROBASE_SYMBOLNAME);
+ Symbol zerobaseSym = getGoSymbol(program, ARTIFICIAL_RUNTIME_ZEROBASE_SYMBOLNAME);
return zerobaseSym != null ? zerobaseSym.getAddress() : null;
}
@@ -479,7 +534,7 @@ public class GoRttiMapper extends DataTypeMapper {
* @return {@link GoModuledata}
*/
public GoModuledata getFirstModule() {
- return modules.get(0);
+ return !modules.isEmpty() ? modules.get(0) : null;
}
/**
@@ -1370,14 +1425,14 @@ public class GoRttiMapper extends DataTypeMapper {
}
private AddressRange getPclntabSearchRange() {
- MemoryBlock memBlock = getFirstMemoryBlock(program, ".noptrdata", ".rdata");
+ MemoryBlock memBlock = getFirstGoSection(program, "noptrdata", "rdata");
return memBlock != null
? new AddressRangeImpl(memBlock.getStart(), memBlock.getEnd())
: null;
}
private AddressRange getModuledataSearchRange() {
- MemoryBlock memBlock = getFirstMemoryBlock(program, ".noptrdata", ".data");
+ MemoryBlock memBlock = getFirstGoSection(program, "noptrdata", "data");
return memBlock != null
? new AddressRangeImpl(memBlock.getStart(), memBlock.getEnd())
: null;
@@ -1389,15 +1444,11 @@ public class GoRttiMapper extends DataTypeMapper {
* @return {@link AddressSetView} of range that is valid to find string structs in
*/
public AddressSetView getStringStructRange() {
- MemoryBlock datamb = program.getMemory().getBlock(".data");
- MemoryBlock rodatamb = getFirstMemoryBlock(program, ".rodata", ".rdata");
-
- if (datamb == null || rodatamb == null) {
- return new AddressSet();
+ AddressSet result = new AddressSet();
+ for (GoModuledata moduledata : modules) {
+ result.add(moduledata.getDataRange());
+ result.add(moduledata.getRoDataRange());
}
-
- AddressSet result = new AddressSet(datamb.getStart(), datamb.getEnd());
- result.add(rodatamb.getStart(), rodatamb.getEnd());
return result;
}
@@ -1407,21 +1458,29 @@ public class GoRttiMapper extends DataTypeMapper {
* @return {@link AddressSetView} of range that is valid for string char[] data
*/
public AddressSetView getStringDataRange() {
- MemoryBlock rodatamb = getFirstMemoryBlock(program, ".rodata", ".rdata");
- return rodatamb != null
- ? new AddressSet(rodatamb.getStart(), rodatamb.getEnd())
- : new AddressSet();
+ // TODO: initialized []byte("stringchars") slices can have data in noptrdata section
+ AddressSet result = new AddressSet();
+ for (GoModuledata moduledata : modules) {
+ result.add(moduledata.getRoDataRange());
+ }
+ return result;
}
- private static MemoryBlock getFirstMemoryBlock(Program program, String... blockNames) {
- Memory memory = program.getMemory();
- for (String blockToSearch : blockNames) {
- MemoryBlock memBlock = memory.getBlock(blockToSearch);
- if (memBlock != null) {
- return memBlock;
- }
+ public AddressSetView getTextAddresses() {
+ AddressSet result = new AddressSet();
+ for (GoModuledata moduledata : modules) {
+ result.add(moduledata.getTextRange());
}
- return null;
+ return result;
+ }
+
+
+ public Symbol getGoSymbol(String symbolName) {
+ return getGoSymbol(program, symbolName);
+ }
+
+ public MemoryBlock getGoSection(String sectionName) {
+ return getGoSection(program, sectionName);
}
//--------------------------------------------------------------------------------------------
diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/util/opinion/MachoLoader.java b/Ghidra/Features/Base/src/main/java/ghidra/app/util/opinion/MachoLoader.java
index 964a9066d0..e968c2d351 100644
--- a/Ghidra/Features/Base/src/main/java/ghidra/app/util/opinion/MachoLoader.java
+++ b/Ghidra/Features/Base/src/main/java/ghidra/app/util/opinion/MachoLoader.java
@@ -23,6 +23,8 @@ import ghidra.app.util.MemoryBlockUtils;
import ghidra.app.util.Option;
import ghidra.app.util.bin.ByteProvider;
import ghidra.app.util.bin.ByteProviderWrapper;
+import ghidra.app.util.bin.format.golang.GoConstants;
+import ghidra.app.util.bin.format.golang.rtti.GoRttiMapper;
import ghidra.app.util.bin.format.macho.*;
import ghidra.app.util.bin.format.swift.SwiftUtils;
import ghidra.app.util.bin.format.ubi.*;
@@ -61,12 +63,7 @@ public class MachoLoader extends AbstractLibrarySupportLoader {
MachHeader machHeader = new MachHeader(provider);
String magic =
CpuTypes.getMagicString(machHeader.getCpuType(), machHeader.getCpuSubType());
- List sectionNames = machHeader.parseSegments()
- .stream()
- .flatMap(seg -> seg.getSections().stream())
- .map(section -> section.getSectionName())
- .toList();
- String compiler = SwiftUtils.isSwift(sectionNames) ? "swift" : null;
+ String compiler = detectCompilerName(machHeader);
List results = QueryOpinionService.query(MACH_O_NAME, magic, compiler);
for (QueryResult result : results) {
loadSpecs.add(new LoadSpec(this, machHeader.getImageBase(), result));
@@ -81,6 +78,19 @@ public class MachoLoader extends AbstractLibrarySupportLoader {
return loadSpecs;
}
+ private String detectCompilerName(MachHeader machHeader) throws IOException {
+ List sectionNames = machHeader.parseSegments()
+ .stream()
+ .flatMap(seg -> seg.getSections().stream())
+ .map(section -> section.getSectionName())
+ .toList();
+ String compiler = SwiftUtils.isSwift(sectionNames) ? "swift" : null;
+ compiler = compiler == null && GoRttiMapper.hasGolangSections(sectionNames)
+ ? GoConstants.GOLANG_CSPEC_NAME
+ : null;
+ return compiler;
+ }
+
@Override
public void load(ByteProvider provider, LoadSpec loadSpec, List