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 afa45271f7..03e970061a 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 @@ -472,17 +472,21 @@ public class GoModuledata implements StructureMarkup { int ptrSize = context.getPtrSize(); byte[] searchBytes = new byte[ptrSize]; context.getDataConverter().putValue(pcHeaderAddress.getOffset(), ptrSize, searchBytes, 0); - Address moduleAddr = memory.findBytes(range.getMinAddress(), range.getMaxAddress(), - searchBytes, null, true, monitor); - if (moduleAddr == null) { - return null; + + Address moduleAddr; + while ((moduleAddr = memory.findBytes(range.getMinAddress(), range.getMaxAddress(), + searchBytes, null, true, monitor)) != null) { + + GoModuledata moduleData = context.readStructure(GoModuledata.class, moduleAddr); + + // Verify that we read a good GoModuledata struct by comparing some of its values to + // the pclntab structure. + if (moduleData.matchesPcHeader(pcHeader)) { + return moduleData; + } + range = new AddressRangeImpl(moduleAddr.next(), range.getMaxAddress()); } - - GoModuledata moduleData = context.readStructure(GoModuledata.class, moduleAddr); - - // Verify that we read a good GoModuledata struct by comparing some of its values to - // the pclntab structure. - return moduleData.matchesPcHeader(pcHeader) ? moduleData : 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 20103fa8b5..9d3fb072e7 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 @@ -20,8 +20,7 @@ import java.io.IOException; import ghidra.app.util.bin.*; import ghidra.app.util.bin.format.golang.GoVer; 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.lang.Endian; import ghidra.program.model.listing.Program; @@ -47,6 +46,7 @@ public class GoPcHeader { 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; + public static final int GO_1_20_MAGIC = 0xfffffff1; /** * Returns the {@link Address} (if present) of the go pclntab section or symbol. @@ -112,15 +112,18 @@ public class GoPcHeader { (byte) 0xff // ptrSize }; Memory memory = programContext.getProgram().getMemory(); - Address pcHeaderAddr = memory.findBytes(range.getMinAddress(), range.getMaxAddress(), - searchBytes, searchMask, true, monitor); - if (pcHeaderAddr == null) { - return null; - } - try (MemoryByteProvider bp = - new MemoryByteProvider(memory, pcHeaderAddr, range.getMaxAddress())) { - return isPcHeader(bp) ? pcHeaderAddr : null; + Address pcHeaderAddr; + while ((pcHeaderAddr = memory.findBytes(range.getMinAddress(), range.getMaxAddress(), + searchBytes, searchMask, true, monitor)) != null) { + try (MemoryByteProvider bp = + new MemoryByteProvider(memory, pcHeaderAddr, range.getMaxAddress())) { + if (isPcHeader(bp)) { + return pcHeaderAddr; + } + } + range = new AddressRangeImpl(pcHeaderAddr.next(), range.getMaxAddress()); } + return null; } /** @@ -286,6 +289,10 @@ public class GoPcHeader { return ptrSize; } + public int getMagic() { + return magic; + } + //-------------------------------------------------------------------------------------------- record GoVerEndian(GoVer goVer, Endian endian) { GoVerEndian(GoVer goVer, boolean isLittleEndian) { @@ -314,6 +321,7 @@ public class GoPcHeader { case GO_1_2_MAGIC -> new GoVer(1, 2, 0); case GO_1_16_MAGIC -> new GoVer(1, 16, 0); case GO_1_18_MAGIC -> new GoVer(1, 18, 0); + case GO_1_20_MAGIC -> new GoVer(1, 20, 0); default -> GoVer.INVALID; }; 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 d65999d9fb..48797d7de9 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 @@ -507,6 +507,12 @@ public class GoRttiMapper extends DataTypeMapper implements DataTypeMapperContex throw new IOException( "Mismatched ptrSize: %d vs %d".formatted(pcHeader.getPtrSize(), ptrSize)); } + if (pcHeader.getGoVersion().isInvalid()) { + // we can get here if the firstmoduledata was located via symbolname instead of + // relying on bootstraping via the pcheader + Msg.warn(this, + "Unknown golang pcheader magic value: 0x%x".formatted(pcHeader.getMagic())); + } } addModule(firstModule); }