Commit 48e22da1 authored by Keith Randall's avatar Keith Randall Committed by Keith Randall

cmd/link: fix deferreturn location on wasm

On wasm, pcln tables are indexed by "resumption point ID" instead of
by pc offset. When finding a deferreturn call, we must find the
associated resumption point ID for the deferreturn call.

Update #27518
Fixes wasm bug introduced in CL 134637.

Change-Id: I3d178a3f5203a06c0180a1aa2309bfb7f3014f0f
Reviewed-on: https://go-review.googlesource.com/c/139898Reviewed-by: default avatarCherry Zhang <cherryyz@google.com>
parent 1bca6cec
...@@ -7,6 +7,7 @@ package ld ...@@ -7,6 +7,7 @@ package ld
import ( import (
"cmd/internal/objabi" "cmd/internal/objabi"
"cmd/internal/src" "cmd/internal/src"
"cmd/internal/sys"
"cmd/link/internal/sym" "cmd/link/internal/sym"
"log" "log"
"os" "os"
...@@ -314,13 +315,26 @@ func (ctxt *Link) pclntab() { ...@@ -314,13 +315,26 @@ func (ctxt *Link) pclntab() {
// deferreturn // deferreturn
deferreturn := uint32(0) deferreturn := uint32(0)
lastWasmAddr := uint32(0)
for _, r := range s.R { for _, r := range s.R {
if ctxt.Arch.Family == sys.Wasm && r.Type == objabi.R_ADDR {
// Wasm does not have a live variable set at the deferreturn
// call itself. Instead it has one identified by the
// resumption point immediately preceding the deferreturn.
// The wasm code has a R_ADDR relocation which is used to
// set the resumption point to PC_B.
lastWasmAddr = uint32(r.Add)
}
if r.Sym != nil && r.Sym.Name == "runtime.deferreturn" && r.Add == 0 { if r.Sym != nil && r.Sym.Name == "runtime.deferreturn" && r.Add == 0 {
if ctxt.Arch.Family == sys.Wasm {
deferreturn = lastWasmAddr
} else {
// Note: the relocation target is in the call instruction, but // Note: the relocation target is in the call instruction, but
// is not necessarily the whole instruction (for instance, on // is not necessarily the whole instruction (for instance, on
// x86 the relocation applies to bytes [1:5] of the 5 byte call // x86 the relocation applies to bytes [1:5] of the 5 byte call
// instruction). // instruction).
deferreturn = uint32(r.Off) deferreturn = uint32(r.Off)
}
break // only need one break // only need one
} }
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment