diff --git a/pwndbg/aglib/godbg.py b/pwndbg/aglib/godbg.py index 6fe916100..d77a497d6 100644 --- a/pwndbg/aglib/godbg.py +++ b/pwndbg/aglib/godbg.py @@ -51,16 +51,48 @@ def word_size() -> int: """ Gets the Go word size for the current architecture. - Values taken from https://github.com/golang/go/blob/20b79fd5775c39061d949569743912ad5e58b0e7/src/go/types/sizes.go#L233-L252 + Values taken from https://github.com/golang/go/blob/49cdf0c42e320dfed044baa551610f081eafb781/src/cmd/compile/internal/types2/sizes.go#L230-L249 """ return { - "i386": 4, "x86-64": 8, - "aarch64": 8, + "i386": 4, + # Go cannot target i8086 "arm": 4, + # Go cannot target armcm + "aarch64": 8, + "powerpc": 8, + "sparc": 8, + # Go cannot target rv32 (but gccgo can) "rv64": 8, + "mips": pwndbg.aglib.arch.ptrsize, # pwndbg uses mips for both 32 and 64 bit + "loongarch64": 8, + "s390x": 8, + }[pwndbg.aglib.arch.name] + + +@pwndbg.lib.cache.cache_until("start", "stop", "objfile") +def max_align() -> int: + """ + Gets the Go maximum alignment for the current architecture. + + Values taken from https://github.com/golang/go/blob/49cdf0c42e320dfed044baa551610f081eafb781/src/cmd/compile/internal/types2/sizes.go#L230-L249 + """ + # Note: gccgo has max alignment 8 for arm and mips, which is different from the default compiler + # Currently, no attempt is made to support gccgo, but it may be worth pursuing in the future + return { + "x86-64": 8, + "i386": 4, + # Go cannot target i8086 + "arm": 4, + # Go cannot target armcm + "aarch64": 8, "powerpc": 8, "sparc": 8, + # Go cannot target rv32 (but gccgo can) + "rv64": 8, + "mips": pwndbg.aglib.arch.ptrsize, # pwndbg uses mips for both 32 and 64 bit + "loongarch64": 8, + "s390x": 8, }[pwndbg.aglib.arch.name] @@ -828,7 +860,7 @@ class BasicType(Type): return self.sz def align(self) -> int: - return self.algn + return min(self.algn, max_align()) def get_typename(self) -> str: return self.name @@ -932,7 +964,7 @@ class PointerType(Type): return word_size() def align(self) -> int: - return word_size() + return min(word_size(), max_align()) def get_typename(self) -> str: return f"*{self.inner}" @@ -1216,7 +1248,7 @@ class MapType(Type): return self.field_offsets()["$size"] def align(self) -> int: - return 8 + return min(8, max_align()) def get_typename(self) -> str: return f"map[{self.key}]{self.val}" @@ -1266,7 +1298,9 @@ class StructType(Type): def align(self) -> int: if self.algn is None: - return max(ty.align() for (_, ty, _) in self.fields if isinstance(ty, Type)) + return max( + (ty.align() for (_, ty, _) in self.fields if isinstance(ty, Type)), default=1 + ) return self.algn def get_typename(self) -> str: diff --git a/tests/binaries/host/gosample.go b/tests/binaries/host/gosample.go index a8920e4bb..d5de19b46 100644 --- a/tests/binaries/host/gosample.go +++ b/tests/binaries/host/gosample.go @@ -8,6 +8,7 @@ func testFunc(x interface{}) *interface{} { } func main() { + testFunc(map[uint8]uint64{1: 2, 3: 4, 5: 6}) testFunc(map[string]int{"a": 1, "b": 2, "c": 3}) testFunc([]struct { a int diff --git a/tests/library/gdb/tests/test_go.py b/tests/library/gdb/tests/test_go.py index bb12a45f2..8127dabd1 100644 --- a/tests/library/gdb/tests/test_go.py +++ b/tests/library/gdb/tests/test_go.py @@ -35,17 +35,24 @@ def helper_test_dump(start_binary, filename): start_binary(filename) gdb.execute("break gosample.go:6", to_string=True) gdb.execute("continue") - first = gdb.execute("go-dump any &x", to_string=True) - assert first.strip() == """(map[string]int) &{"a": 1, "b": 2, "c": 3}""" + + dump = gdb.execute("go-dump any &x", to_string=True) + assert dump.strip() == """(map[uint8]uint64) &{1: 2, 3: 4, 5: 6}""" + gdb.execute("continue") + + dump = gdb.execute("go-dump any &x", to_string=True) + assert dump.strip() == """(map[string]int) &{"a": 1, "b": 2, "c": 3}""" gdb.execute("continue") - second = gdb.execute("go-dump any &x", to_string=True) + + dump = gdb.execute("go-dump any &x", to_string=True) assert ( - second.strip() + dump.strip() == """([]struct { a int; b string }) [struct {a: 1, b: "first"}, struct {a: 2, b: "second"}]""" ) gdb.execute("continue") - third = gdb.execute("go-dump -f 1 any &x", to_string=True) - assert third.strip() == """([3]complex64) [(1.1 + 2.2i), (-2.5 - 5.0i), (4.2 - 2.1i)]""" + + dump = gdb.execute("go-dump -f 1 any &x", to_string=True) + assert dump.strip() == """([3]complex64) [(1.1 + 2.2i), (-2.5 - 5.0i), (4.2 - 2.1i)]""" def test_go_dumping_x64(start_binary):