aboutsummaryrefslogtreecommitdiff
path: root/src/runtime/symtab.go
diff options
context:
space:
mode:
authorCherry Mui <cherryyz@google.com>2023-12-26 15:35:56 -0500
committerCherry Mui <cherryyz@google.com>2025-07-16 07:15:42 -0700
commit9c507e794297c9a7f160f71b9910d5de27b9a517 (patch)
tree95842c626540db2792171d7f705df8f537e8f202 /src/runtime/symtab.go
parent9782dcfd16bcf10f576504bacf67eb41a6cef88f (diff)
downloadgo-9c507e794297c9a7f160f71b9910d5de27b9a517.tar.xz
cmd/link, runtime: on Wasm, put only function index in method table and func table
In the type descriptor's method table, it contains relative PCs of the methods (relative to the start of the text section) stored as 32-bit offsets. On Wasm, a PC is PC_F<<16 + PC_B, where PC_F is the function index, and PC_B is the block index. When there are more than 65536 functions, the PC will not fit into 32-bit (and relative to the section start doesn't help). Since there are no more bits for the function index, and the method table always targets the entry of a method, we put just the PC_F there, and rewrite back to a full PC at run time when we need the PC. This way we can have more than 65536 functions. The func table also contains 32-bit relative PCs, and it also always points to function entries. Do the same there, as well as other places where we use relative text offsets. Also add the relocation type in the relocation overflow error message. Also add check for function too big on Wasm. If a function has more than 65536 blocks, PC_B will overflow and PC = PC_F<<16 + PC_B will points to the wrong function. Fixes #64856. Change-Id: If9c307e9fb1641f367a5f19c39f88f455805d0bb Reviewed-on: https://go-review.googlesource.com/c/go/+/552835 Reviewed-by: Than McIntosh <thanm@google.com> Reviewed-by: Dmitri Shuralyov <dmitshur@google.com> LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
Diffstat (limited to 'src/runtime/symtab.go')
-rw-r--r--src/runtime/symtab.go32
1 files changed, 29 insertions, 3 deletions
diff --git a/src/runtime/symtab.go b/src/runtime/symtab.go
index 866c46a83d..56f2a00d76 100644
--- a/src/runtime/symtab.go
+++ b/src/runtime/symtab.go
@@ -647,8 +647,15 @@ func moduledataverify1(datap *moduledata) {
min := datap.textAddr(datap.ftab[0].entryoff)
max := datap.textAddr(datap.ftab[nftab].entryoff)
- if datap.minpc != min || datap.maxpc != max {
- println("minpc=", hex(datap.minpc), "min=", hex(min), "maxpc=", hex(datap.maxpc), "max=", hex(max))
+ minpc := datap.minpc
+ maxpc := datap.maxpc
+ if GOARCH == "wasm" {
+ // On Wasm, the func table contains the function index, whereas
+ // the "PC" is function index << 16 + block index.
+ maxpc = alignUp(maxpc, 1<<16) // round up for end PC
+ }
+ if minpc != min || maxpc != max {
+ println("minpc=", hex(minpc), "min=", hex(min), "maxpc=", hex(maxpc), "max=", hex(max))
throw("minpc or maxpc invalid")
}
@@ -694,6 +701,11 @@ func (md *moduledata) textAddr(off32 uint32) uintptr {
throw("runtime: text offset out of range")
}
}
+ if GOARCH == "wasm" {
+ // On Wasm, a text offset (e.g. in the method table) is function index, whereas
+ // the "PC" is function index << 16 + block index.
+ res <<= 16
+ }
return res
}
@@ -704,8 +716,17 @@ func (md *moduledata) textAddr(off32 uint32) uintptr {
//
//go:nosplit
func (md *moduledata) textOff(pc uintptr) (uint32, bool) {
- res := uint32(pc - md.text)
+ off := pc - md.text
+ if GOARCH == "wasm" {
+ // On Wasm, the func table contains the function index, whereas
+ // the "PC" is function index << 16 + block index.
+ off >>= 16
+ }
+ res := uint32(off)
if len(md.textsectmap) > 1 {
+ if GOARCH == "wasm" {
+ fatal("unexpected multiple text sections on Wasm")
+ }
for i, sect := range md.textsectmap {
if sect.baseaddr > pc {
// pc is not in any section.
@@ -904,6 +925,11 @@ func findfunc(pc uintptr) funcInfo {
}
x := uintptr(pcOff) + datap.text - datap.minpc // TODO: are datap.text and datap.minpc always equal?
+ if GOARCH == "wasm" {
+ // On Wasm, pcOff is the function index, whereas
+ // the "PC" is function index << 16 + block index.
+ x = uintptr(pcOff)<<16 + datap.text - datap.minpc
+ }
b := x / abi.FuncTabBucketSize
i := x % abi.FuncTabBucketSize / (abi.FuncTabBucketSize / nsub)