"os/exec"
"path/filepath"
"runtime"
+ "sort"
"strings"
"sync"
Segdata sym.Segment
Segdwarf sym.Segment
Segpdata sym.Segment // windows-only
+ Segxdata sym.Segment // windows-only
- Segments = []*sym.Segment{&Segtext, &Segrodata, &Segrelrodata, &Segdata, &Segdwarf, &Segpdata}
+ Segments = []*sym.Segment{&Segtext, &Segrodata, &Segrelrodata, &Segdata, &Segdwarf, &Segpdata, &Segxdata}
)
const pkgdef = "__.PKGDEF"
default:
log.Fatalf("invalid -strictdups flag value %d", *FlagStrictDups)
}
- elfsetstring1 := func(str string, off int) { elfsetstring(ctxt, 0, str, off) }
- ctxt.loader = loader.NewLoader(flags, elfsetstring1, &ctxt.ErrorReporter.ErrorReporter)
+ ctxt.loader = loader.NewLoader(flags, &ctxt.ErrorReporter.ErrorReporter)
ctxt.ErrorReporter.SymName = func(s loader.Sym) string {
return ctxt.loader.SymName(s)
}
// Leave type:runtime. symbols alone, because other parts of
// the linker manipulates them.
func typeSymbolMangle(name string) string {
- if !strings.HasPrefix(name, "type:") {
+ isType := strings.HasPrefix(name, "type:")
+ if !isType && !strings.Contains(name, "@") {
+ // Issue 58800: instantiated symbols may include a type name, which may contain "@"
return name
}
if strings.HasPrefix(name, "type:runtime.") {
return name
}
+ if strings.HasPrefix(name, "go:string.") {
+ // String symbols will be grouped to a single go:string.* symbol.
+ // No need to mangle individual symbol names.
+ return name
+ }
if len(name) <= 14 && !strings.Contains(name, "@") { // Issue 19529
return name
}
- hash := notsha256.Sum256([]byte(name))
- prefix := "type:"
- if name[5] == '.' {
- prefix = "type:."
+ if isType {
+ hash := notsha256.Sum256([]byte(name[5:]))
+ prefix := "type:"
+ if name[5] == '.' {
+ prefix = "type:."
+ }
+ return prefix + base64.StdEncoding.EncodeToString(hash[:6])
+ }
+ // instantiated symbol, replace type name in []
+ i := strings.IndexByte(name, '[')
+ j := strings.LastIndexByte(name, ']')
+ if j == -1 || j <= i {
+ j = len(name)
}
- return prefix + base64.StdEncoding.EncodeToString(hash[:6])
+ hash := notsha256.Sum256([]byte(name[i+1 : j]))
+ return name[:i+1] + base64.StdEncoding.EncodeToString(hash[:6]) + name[j:]
}
/*
if ctxt.HeadType == objabi.Hdarwin {
// Recent versions of macOS print
// ld: warning: option -s is obsolete and being ignored
- // so do not pass any arguments.
+ // so do not pass any arguments (but we strip symbols below).
} else {
argv = append(argv, "-s")
}
// On darwin, whether to combine DWARF into executable.
// Only macOS supports unmapped segments such as our __DWARF segment.
- combineDwarf := ctxt.IsDarwin() && !*FlagS && !*FlagW && !debug_s && machoPlatform == PLATFORM_MACOS
+ combineDwarf := ctxt.IsDarwin() && !*FlagW && machoPlatform == PLATFORM_MACOS
switch ctxt.HeadType {
case objabi.Hdarwin:
}
if !combineDwarf {
argv = append(argv, "-Wl,-S") // suppress STAB (symbolic debugging) symbols
+ if debug_s {
+ // We are generating a binary with symbol table suppressed.
+ // Suppress local symbols. We need to keep dynamically exported
+ // and referenced symbols so the dynamic linker can resolve them.
+ argv = append(argv, "-Wl,-x")
+ }
}
case objabi.Hopenbsd:
argv = append(argv, "-Wl,-nopie")
if ctxt.DynlinkingGo() || ctxt.BuildMode == BuildModeCShared || !linkerFlagSupported(ctxt.Arch, argv[0], altLinker, "-Wl,--export-dynamic-symbol=main") {
argv = append(argv, "-rdynamic")
} else {
+ var exports []string
ctxt.loader.ForAllCgoExportDynamic(func(s loader.Sym) {
- argv = append(argv, "-Wl,--export-dynamic-symbol="+ctxt.loader.SymExtname(s))
+ exports = append(exports, "-Wl,--export-dynamic-symbol="+ctxt.loader.SymExtname(s))
})
+ sort.Strings(exports)
+ argv = append(argv, exports...)
}
}
if ctxt.HeadType == objabi.Haix {
out = append(out[:i], out[i+len(noPieWarning):]...)
}
}
+ if ctxt.IsDarwin() {
+ const bindAtLoadWarning = "ld: warning: -bind_at_load is deprecated on macOS\n"
+ if i := bytes.Index(out, []byte(bindAtLoadWarning)); i >= 0 {
+ // -bind_at_load is deprecated with ld-prime, but needed for
+ // correctness with older versions of ld64. Swallow the warning.
+ // TODO: maybe pass -bind_at_load conditionally based on C
+ // linker version.
+ out = append(out[:i], out[i+len(bindAtLoadWarning):]...)
+ }
+ }
ctxt.Logf("%s", out)
}
stripCmd := strings.TrimSuffix(string(out), "\n")
dsym := filepath.Join(*flagTmpdir, "go.dwarf")
- if out, err := exec.Command(dsymutilCmd, "-f", *flagOutfile, "-o", dsym).CombinedOutput(); err != nil {
+ cmd := exec.Command(dsymutilCmd, "-f", *flagOutfile, "-o", dsym)
+ // dsymutil may not clean up its temp directory at exit.
+ // Set DSYMUTIL_REPRODUCER_PATH to work around. see issue 59026.
+ cmd.Env = append(os.Environ(), "DSYMUTIL_REPRODUCER_PATH="+*flagTmpdir)
+ if ctxt.Debugvlog != 0 {
+ ctxt.Logf("host link dsymutil:")
+ for _, v := range cmd.Args {
+ ctxt.Logf(" %q", v)
+ }
+ ctxt.Logf("\n")
+ }
+ if out, err := cmd.CombinedOutput(); err != nil {
Exitf("%s: running dsymutil failed: %v\n%s", os.Args[0], err, out)
}
// Remove STAB (symbolic debugging) symbols after we are done with them (by dsymutil).
// They contain temporary file paths and make the build not reproducible.
- if out, err := exec.Command(stripCmd, "-S", *flagOutfile).CombinedOutput(); err != nil {
+ var stripArgs = []string{"-S"}
+ if debug_s {
+ // We are generating a binary with symbol table suppressed.
+ // Suppress local symbols. We need to keep dynamically exported
+ // and referenced symbols so the dynamic linker can resolve them.
+ stripArgs = append(stripArgs, "-x")
+ }
+ stripArgs = append(stripArgs, *flagOutfile)
+ if ctxt.Debugvlog != 0 {
+ ctxt.Logf("host link strip: %q", stripCmd)
+ for _, v := range stripArgs {
+ ctxt.Logf(" %q", v)
+ }
+ ctxt.Logf("\n")
+ }
+ if out, err := exec.Command(stripCmd, stripArgs...).CombinedOutput(); err != nil {
Exitf("%s: running strip failed: %v\n%s", os.Args[0], err, out)
}
// Skip combining if `dsymutil` didn't generate a file. See #11994.
if altLinker != "" {
flags = append(flags, "-fuse-ld="+altLinker)
}
- flags = append(flags, flag, "trivial.c")
+ trivialPath := filepath.Join(*flagTmpdir, "trivial.c")
+ outPath := filepath.Join(*flagTmpdir, "a.out")
+ flags = append(flags, "-o", outPath, flag, trivialPath)
cmd := exec.Command(linker, flags...)
- cmd.Dir = *flagTmpdir
cmd.Env = append([]string{"LC_ALL=C"}, os.Environ()...)
out, err := cmd.CombinedOutput()
// GCC says "unrecognized command line option ‘-no-pie’"
0xc401, // arm
0x64aa: // arm64
ldpe := func(ctxt *Link, f *bio.Reader, pkg string, length int64, pn string) {
- textp, rsrc, err := loadpe.Load(ctxt.loader, ctxt.Arch, ctxt.IncVersion(), f, pkg, length, pn)
+ ls, err := loadpe.Load(ctxt.loader, ctxt.Arch, ctxt.IncVersion(), f, pkg, length, pn)
if err != nil {
Errorf(nil, "%v", err)
return
}
- if len(rsrc) != 0 {
- setpersrc(ctxt, rsrc)
+ if len(ls.Resources) != 0 {
+ setpersrc(ctxt, ls.Resources)
}
- ctxt.Textp = append(ctxt.Textp, textp...)
+ if ls.PData != 0 {
+ sehp.pdata = append(sehp.pdata, ls.PData)
+ }
+ if ls.XData != 0 {
+ sehp.xdata = append(sehp.xdata, ls.XData)
+ }
+ ctxt.Textp = append(ctxt.Textp, ls.Textp...)
}
return ldhostobj(ldpe, ctxt.HeadType, f, pkg, length, pn, file)
}