]> Cypherpunks repositories - gostls13.git/commitdiff
cmd/link: set .dynsym info field
authorLE Manh Cuong <cuong.manhle.vn@gmail.com>
Wed, 31 Jul 2019 04:45:32 +0000 (11:45 +0700)
committerIan Lance Taylor <iant@golang.org>
Sat, 31 Aug 2019 15:49:08 +0000 (15:49 +0000)
.dynsym section info field is the index of first non-local symbol, mean
the number of local symbols.

The go linker have never ever set it before, so just set it.

Fixes #33358

Change-Id: Ifde2deb7c15471b04d565861f5d81daffb0c0d3d
Reviewed-on: https://go-review.googlesource.com/c/go/+/187979
Run-TryBot: Cuong Manh Le <cuong.manhle.vn@gmail.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Ian Lance Taylor <iant@golang.org>
src/cmd/link/internal/ld/elf.go
src/cmd/link/internal/ld/elf_test.go [new file with mode: 0644]

index 5a3098ce854f9275cb106ec96cc71874c667d6fc..1fdba930f5796fceb0f5d73093608c6005a631a3 100644 (file)
@@ -1942,8 +1942,17 @@ func Asmbelf(ctxt *Link, symo int64) {
                sh.addralign = uint64(ctxt.Arch.RegSize)
                sh.link = uint32(elfshname(".dynstr").shnum)
 
-               // sh->info = index of first non-local symbol (number of local symbols)
-               shsym(sh, ctxt.Syms.Lookup(".dynsym", 0))
+               // sh.info is the index of first non-local symbol (number of local symbols)
+               s := ctxt.Syms.Lookup(".dynsym", 0)
+               i := uint32(0)
+               for sub := s; sub != nil; sub = sub.Sub {
+                       i++
+                       if !sub.Attr.Local() {
+                               sh.info = i
+                               break
+                       }
+               }
+               shsym(sh, s)
 
                sh = elfshname(".dynstr")
                sh.type_ = SHT_STRTAB
diff --git a/src/cmd/link/internal/ld/elf_test.go b/src/cmd/link/internal/ld/elf_test.go
new file mode 100644 (file)
index 0000000..8e86beb
--- /dev/null
@@ -0,0 +1,79 @@
+// +build cgo
+
+// Copyright 2019 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package ld
+
+import (
+       "debug/elf"
+       "internal/testenv"
+       "io/ioutil"
+       "os"
+       "os/exec"
+       "path/filepath"
+       "testing"
+)
+
+func TestDynSymShInfo(t *testing.T) {
+       t.Parallel()
+       testenv.MustHaveGoBuild(t)
+       dir, err := ioutil.TempDir("", "go-build-issue33358")
+       if err != nil {
+               t.Fatal(err)
+       }
+       defer os.RemoveAll(dir)
+
+       const prog = `
+package main
+
+import "net"
+
+func main() {
+       net.Dial("", "")
+}
+`
+       src := filepath.Join(dir, "issue33358.go")
+       if err := ioutil.WriteFile(src, []byte(prog), 0666); err != nil {
+               t.Fatal(err)
+       }
+
+       binFile := filepath.Join(dir, "issue33358")
+       cmd := exec.Command(testenv.GoToolPath(t), "build", "-o", binFile, src)
+       if out, err := cmd.CombinedOutput(); err != nil {
+               t.Fatalf("%v: %v:\n%s", cmd.Args, err, out)
+       }
+
+       fi, err := os.Open(binFile)
+       if err != nil {
+               t.Fatalf("failed to open built file: %v", err)
+       }
+
+       elfFile, err := elf.NewFile(fi)
+       if err != nil {
+               t.Skip("The system may not support ELF, skipped.")
+       }
+
+       section := elfFile.Section(".dynsym")
+       if section == nil {
+               t.Fatal("no dynsym")
+       }
+
+       symbols, err := elfFile.DynamicSymbols()
+       if err != nil {
+               t.Fatalf("failed to get dynamic symbols: %v", err)
+       }
+
+       var numLocalSymbols uint32
+       for i, s := range symbols {
+               if elf.ST_BIND(s.Info) != elf.STB_LOCAL {
+                       numLocalSymbols = uint32(i + 1)
+                       break
+               }
+       }
+
+       if section.Info != numLocalSymbols {
+               t.Fatalf("Unexpected sh info, want greater than 0, got: %d", section.Info)
+       }
+}