Skip to content

Commit

Permalink
cmd/link: add runtime.text.N symbols to macho symbol table in dynlink…
Browse files Browse the repository at this point in the history
… mode

In dynamic linking mode (e.g. when using plugins) on darwin, the
marker symbols runtime.text and runtime.etext are added to Textp
in an early stage, so when adding symbols to the symbol table we
don't need to explicitly add them. However, when splitting text
sections, the runtime.text.N marker symbols for the addtional
sections are not added to Textp. So we do need to add them
explicitly to the symbol table.

Fixes #66993.

Change-Id: Ic718d03cd71fc0bfb931cff82640b1f4c53b89be
Reviewed-on: https://go-review.googlesource.com/c/go/+/586555
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
Reviewed-by: Than McIntosh <thanm@google.com>
  • Loading branch information
cherrymui committed May 20, 2024
1 parent e3d87d1 commit 9a9dd72
Show file tree
Hide file tree
Showing 2 changed files with 37 additions and 14 deletions.
19 changes: 19 additions & 0 deletions src/cmd/cgo/internal/testplugin/plugin_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,7 @@ func testMain(m *testing.M) int {
}
defer os.RemoveAll(GOPATH)
tmpDir = GOPATH
fmt.Printf("TMPDIR=%s\n", tmpDir)

modRoot := filepath.Join(GOPATH, "src", "testplugin")
altRoot := filepath.Join(GOPATH, "alt", "src", "testplugin")
Expand Down Expand Up @@ -395,3 +396,21 @@ func TestIssue62430(t *testing.T) {
goCmd(t, "build", "-o", "issue62430.exe", "./issue62430/main.go")
run(t, "./issue62430.exe")
}

func TestTextSectionSplit(t *testing.T) {
globalSkip(t)
if runtime.GOOS != "darwin" || runtime.GOARCH != "arm64" {
t.Skipf("text section splitting is not done in %s/%s", runtime.GOOS, runtime.GOARCH)
}

// Use -ldflags=-debugtextsize=262144 to let the linker split text section
// at a smaller size threshold, so it actually splits for the test binary.
goCmd(nil, "build", "-ldflags=-debugtextsize=262144", "-o", "host-split.exe", "./host")
run(t, "./host-split.exe")

// Check that we did split text sections.
syms := goCmd(nil, "tool", "nm", "host-split.exe")
if !strings.Contains(syms, "runtime.text.1") {
t.Errorf("runtime.text.1 not found, text section not split?")
}
}
32 changes: 18 additions & 14 deletions src/cmd/link/internal/ld/macho.go
Original file line number Diff line number Diff line change
Expand Up @@ -195,12 +195,12 @@ const (
)

const (
PLATFORM_MACOS MachoPlatform = 1
PLATFORM_IOS MachoPlatform = 2
PLATFORM_TVOS MachoPlatform = 3
PLATFORM_WATCHOS MachoPlatform = 4
PLATFORM_BRIDGEOS MachoPlatform = 5
PLATFORM_MACCATALYST MachoPlatform = 6
PLATFORM_MACOS MachoPlatform = 1
PLATFORM_IOS MachoPlatform = 2
PLATFORM_TVOS MachoPlatform = 3
PLATFORM_WATCHOS MachoPlatform = 4
PLATFORM_BRIDGEOS MachoPlatform = 5
PLATFORM_MACCATALYST MachoPlatform = 6
)

// rebase table opcode
Expand Down Expand Up @@ -900,21 +900,25 @@ func collectmachosyms(ctxt *Link) {
// Add special runtime.text and runtime.etext symbols (which are local).
// We've already included this symbol in Textp on darwin if ctxt.DynlinkingGo().
// See data.go:/textaddress
// NOTE: runtime.text.N symbols (if we split text sections) are not added, though,
// so we handle them here.
if !*FlagS {
if !ctxt.DynlinkingGo() {
s := ldr.Lookup("runtime.text", 0)
if ldr.SymType(s) == sym.STEXT {
addsym(s)
}
for n := range Segtext.Sections[1:] {
s := ldr.Lookup(fmt.Sprintf("runtime.text.%d", n+1), 0)
if s != 0 {
addsym(s)
} else {
break
}
}
for n := range Segtext.Sections[1:] {
s := ldr.Lookup(fmt.Sprintf("runtime.text.%d", n+1), 0)
if s != 0 {
addsym(s)
} else {
break
}
s = ldr.Lookup("runtime.etext", 0)
}
if !ctxt.DynlinkingGo() {
s := ldr.Lookup("runtime.etext", 0)
if ldr.SymType(s) == sym.STEXT {
addsym(s)
}
Expand Down

0 comments on commit 9a9dd72

Please sign in to comment.