diff options
Diffstat (limited to 'src/cmd/link/internal/ld')
-rw-r--r-- | src/cmd/link/internal/ld/data.go | 24 | ||||
-rw-r--r-- | src/cmd/link/internal/ld/deadcode.go | 2 | ||||
-rw-r--r-- | src/cmd/link/internal/ld/lib.go | 44 | ||||
-rw-r--r-- | src/cmd/link/internal/ld/macho.go | 41 | ||||
-rw-r--r-- | src/cmd/link/internal/ld/macho_combine_dwarf.go | 112 | ||||
-rw-r--r-- | src/cmd/link/internal/ld/symtab.go | 4 | ||||
-rw-r--r-- | src/cmd/link/internal/ld/target.go | 6 |
7 files changed, 111 insertions, 122 deletions
diff --git a/src/cmd/link/internal/ld/data.go b/src/cmd/link/internal/ld/data.go index dc7096ea8c..a730125cf2 100644 --- a/src/cmd/link/internal/ld/data.go +++ b/src/cmd/link/internal/ld/data.go @@ -930,7 +930,7 @@ func writeBlock(ctxt *Link, out *OutBuf, ldr *loader.Loader, syms []loader.Sym, break } if val < addr { - ldr.Errorf(s, "phase error: addr=%#x but sym=%#x type=%d", addr, val, ldr.SymType(s)) + ldr.Errorf(s, "phase error: addr=%#x but sym=%#x type=%v sect=%v", addr, val, ldr.SymType(s), ldr.SymSect(s).Name) errorexit() } if addr < val { @@ -1308,9 +1308,9 @@ func (state *dodataState) makeRelroForSharedLib(target *Link) { // relro Type before it reaches here. isRelro = true case sym.SFUNCTAB: - if target.IsAIX() && ldr.SymName(s) == "runtime.etypes" { + if ldr.SymName(s) == "runtime.etypes" { // runtime.etypes must be at the end of - // the relro datas. + // the relro data. isRelro = true } } @@ -1706,7 +1706,7 @@ func (state *dodataState) allocateDataSections(ctxt *Link) { ldr.SetSymSect(ldr.LookupOrCreateSym("runtime.ebss", 0), sect) bssGcEnd := state.datsize - int64(sect.Vaddr) - // Emit gcdata for bcc symbols now that symbol values have been assigned. + // Emit gcdata for bss symbols now that symbol values have been assigned. gcsToEmit := []struct { symName string symKind sym.SymKind @@ -1786,7 +1786,8 @@ func (state *dodataState) allocateDataSections(ctxt *Link) { culprit := ldr.SymName(state.data[sym.STEXT][0]) Errorf(nil, "dodata found an sym.STEXT symbol: %s", culprit) } - state.allocateSingleSymSections(&Segtext, sym.SELFRXSECT, sym.SRODATA, 04) + state.allocateSingleSymSections(&Segtext, sym.SELFRXSECT, sym.SRODATA, 05) + state.allocateSingleSymSections(&Segtext, sym.SMACHOPLT, sym.SRODATA, 05) /* read-only data */ sect = state.allocateNamedDataSection(segro, ".rodata", sym.ReadOnly, 04) @@ -1810,7 +1811,6 @@ func (state *dodataState) allocateDataSections(ctxt *Link) { /* read-only ELF, Mach-O sections */ state.allocateSingleSymSections(segro, sym.SELFROSECT, sym.SRODATA, 04) - state.allocateSingleSymSections(segro, sym.SMACHOPLT, sym.SRODATA, 04) // There is some data that are conceptually read-only but are written to by // relocations. On GNU systems, we can arrange for the dynamic linker to @@ -1826,13 +1826,16 @@ func (state *dodataState) allocateDataSections(ctxt *Link) { const fallbackPerm = 04 relroSecPerm := fallbackPerm genrelrosecname := func(suffix string) string { + if suffix == "" { + return ".rodata" + } return suffix } seg := segro if ctxt.UseRelro() { segrelro := &Segrelrodata - if ctxt.LinkMode == LinkExternal && ctxt.HeadType != objabi.Haix { + if ctxt.LinkMode == LinkExternal && !ctxt.IsAIX() && !ctxt.IsDarwin() { // Using a separate segment with an external // linker results in some programs moving // their data sections unexpectedly, which @@ -1845,9 +1848,12 @@ func (state *dodataState) allocateDataSections(ctxt *Link) { state.datsize = 0 } - genrelrosecname = func(suffix string) string { - return ".data.rel.ro" + suffix + if !ctxt.IsDarwin() { // We don't need the special names on darwin. + genrelrosecname = func(suffix string) string { + return ".data.rel.ro" + suffix + } } + relroReadOnly := []sym.SymKind{} for _, symnro := range sym.ReadOnly { symn := sym.RelROMap[symnro] diff --git a/src/cmd/link/internal/ld/deadcode.go b/src/cmd/link/internal/ld/deadcode.go index 0269429723..35545f950e 100644 --- a/src/cmd/link/internal/ld/deadcode.go +++ b/src/cmd/link/internal/ld/deadcode.go @@ -209,7 +209,7 @@ func (d *deadcodePass) mark(symIdx, parent loader.Sym) { if symIdx != 0 && !d.ldr.AttrReachable(symIdx) { d.wq.push(symIdx) d.ldr.SetAttrReachable(symIdx, true) - if objabi.Fieldtrack_enabled != 0 { + if objabi.Fieldtrack_enabled != 0 && d.ldr.Reachparent[symIdx] == 0 { d.ldr.Reachparent[symIdx] = parent } if *flagDumpDep { diff --git a/src/cmd/link/internal/ld/lib.go b/src/cmd/link/internal/ld/lib.go index 09c7bbfb53..4295b2a660 100644 --- a/src/cmd/link/internal/ld/lib.go +++ b/src/cmd/link/internal/ld/lib.go @@ -775,14 +775,6 @@ func (ctxt *Link) linksetup() { sb.SetSize(0) sb.AddUint8(uint8(objabi.GOARM)) } - - if objabi.Framepointer_enabled(objabi.GOOS, objabi.GOARCH) { - fpe := ctxt.loader.LookupOrCreateSym("runtime.framepointer_enabled", 0) - sb := ctxt.loader.MakeSymbolUpdater(fpe) - sb.SetType(sym.SNOPTRDATA) - sb.SetSize(0) - sb.AddUint8(1) - } } else { // If OTOH the module does not contain the runtime package, // create a local symbol for the moduledata. @@ -1246,15 +1238,23 @@ func (ctxt *Link) hostlink() { } } + // 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 + switch ctxt.HeadType { case objabi.Hdarwin: - if machoPlatform == PLATFORM_MACOS { + if combineDwarf { + // Leave room for DWARF combining. // -headerpad is incompatible with -fembed-bitcode. argv = append(argv, "-Wl,-headerpad,1144") } if ctxt.DynlinkingGo() && !ctxt.Arch.InFamily(sys.ARM, sys.ARM64) { argv = append(argv, "-Wl,-flat_namespace") } + if !combineDwarf { + argv = append(argv, "-Wl,-S") // suppress STAB (symbolic debugging) symbols + } case objabi.Hopenbsd: argv = append(argv, "-Wl,-nopie") case objabi.Hwindows: @@ -1288,7 +1288,7 @@ func (ctxt *Link) hostlink() { switch ctxt.BuildMode { case BuildModeExe: if ctxt.HeadType == objabi.Hdarwin { - if machoPlatform == PLATFORM_MACOS { + if machoPlatform == PLATFORM_MACOS && ctxt.IsAMD64() { argv = append(argv, "-Wl,-no_pie") argv = append(argv, "-Wl,-pagezero_size,4000000") } @@ -1525,7 +1525,7 @@ func (ctxt *Link) hostlink() { // does not work, the resulting programs will not run. See // issue #17847. To avoid this problem pass -no-pie to the // toolchain if it is supported. - if ctxt.BuildMode == BuildModeExe && !ctxt.linkShared { + if ctxt.BuildMode == BuildModeExe && !ctxt.linkShared && !(ctxt.IsDarwin() && ctxt.IsARM64()) { // GCC uses -no-pie, clang uses -nopie. for _, nopie := range []string{"-no-pie", "-nopie"} { if linkerFlagSupported(argv[0], altLinker, nopie) { @@ -1594,11 +1594,16 @@ func (ctxt *Link) hostlink() { ctxt.Logf("%s", out) } - if !*FlagS && !*FlagW && !debug_s && ctxt.HeadType == objabi.Hdarwin { + if combineDwarf { dsym := filepath.Join(*flagTmpdir, "go.dwarf") if out, err := exec.Command("dsymutil", "-f", *flagOutfile, "-o", dsym).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("strip", "-S", *flagOutfile).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 _, err := os.Stat(dsym); os.IsNotExist(err) { return @@ -1614,15 +1619,12 @@ func (ctxt *Link) hostlink() { if err != nil { Exitf("%s: parsing Mach-O header failed: %v", os.Args[0], err) } - // Only macOS supports unmapped segments such as our __DWARF segment. - if machoPlatform == PLATFORM_MACOS { - if err := machoCombineDwarf(ctxt, exef, exem, dsym, combinedOutput); err != nil { - Exitf("%s: combining dwarf failed: %v", os.Args[0], err) - } - os.Remove(*flagOutfile) - if err := os.Rename(combinedOutput, *flagOutfile); err != nil { - Exitf("%s: %v", os.Args[0], err) - } + if err := machoCombineDwarf(ctxt, exef, exem, dsym, combinedOutput); err != nil { + Exitf("%s: combining dwarf failed: %v", os.Args[0], err) + } + os.Remove(*flagOutfile) + if err := os.Rename(combinedOutput, *flagOutfile); err != nil { + Exitf("%s: %v", os.Args[0], err) } } } diff --git a/src/cmd/link/internal/ld/macho.go b/src/cmd/link/internal/ld/macho.go index f6356729a6..9765ce18d3 100644 --- a/src/cmd/link/internal/ld/macho.go +++ b/src/cmd/link/internal/ld/macho.go @@ -499,16 +499,7 @@ func machoadddynlib(lib string, linkmode LinkMode) { func machoshbits(ctxt *Link, mseg *MachoSeg, sect *sym.Section, segname string) { buf := "__" + strings.Replace(sect.Name[1:], ".", "_", -1) - var msect *MachoSect - if sect.Rwx&1 == 0 && segname != "__DWARF" && (ctxt.Arch.Family == sys.ARM64 || - (ctxt.Arch.Family == sys.AMD64 && ctxt.BuildMode != BuildModeExe)) { - // Darwin external linker on arm64, and on amd64 in c-shared/c-archive buildmode - // complains about absolute relocs in __TEXT, so if the section is not - // executable, put it in __DATA segment. - msect = newMachoSect(mseg, buf, "__DATA") - } else { - msect = newMachoSect(mseg, buf, segname) - } + msect := newMachoSect(mseg, buf, segname) if sect.Rellen > 0 { msect.reloc = uint32(sect.Reloff) @@ -633,13 +624,28 @@ func asmbMacho(ctxt *Link) { machoshbits(ctxt, ms, sect, "__TEXT") } + /* rodata */ + if ctxt.LinkMode != LinkExternal && Segrelrodata.Length > 0 { + ms = newMachoSeg("__DATA_CONST", 20) + ms.vaddr = Segrelrodata.Vaddr + ms.vsize = Segrelrodata.Length + ms.fileoffset = Segrelrodata.Fileoff + ms.filesize = Segrelrodata.Filelen + ms.prot1 = 3 + ms.prot2 = 3 + ms.flag = 0x10 // SG_READ_ONLY + } + + for _, sect := range Segrelrodata.Sections { + machoshbits(ctxt, ms, sect, "__DATA_CONST") + } + /* data */ if ctxt.LinkMode != LinkExternal { - w := int64(Segdata.Length) ms = newMachoSeg("__DATA", 20) - ms.vaddr = uint64(va) + uint64(v) - ms.vsize = uint64(w) - ms.fileoffset = uint64(v) + ms.vaddr = Segdata.Vaddr + ms.vsize = Segdata.Length + ms.fileoffset = Segdata.Fileoff ms.filesize = Segdata.Filelen ms.prot1 = 3 ms.prot2 = 3 @@ -695,7 +701,7 @@ func asmbMacho(ctxt *Link) { if ctxt.LinkMode != LinkExternal { ms := newMachoSeg("__LINKEDIT", 0) - ms.vaddr = uint64(va) + uint64(v) + uint64(Rnd(int64(Segdata.Length), int64(*FlagRound))) + ms.vaddr = uint64(Rnd(int64(Segdata.Vaddr+Segdata.Length), int64(*FlagRound))) ms.vsize = uint64(s1) + uint64(s2) + uint64(s3) + uint64(s4) ms.fileoffset = uint64(linkoff) ms.filesize = ms.vsize @@ -1008,7 +1014,7 @@ func doMachoLink(ctxt *Link) int64 { size := int(ldr.SymSize(s1) + ldr.SymSize(s2) + ldr.SymSize(s3) + ldr.SymSize(s4)) if size > 0 { - linkoff = Rnd(int64(uint64(HEADR)+Segtext.Length), int64(*FlagRound)) + Rnd(int64(Segdata.Filelen), int64(*FlagRound)) + Rnd(int64(Segdwarf.Filelen), int64(*FlagRound)) + linkoff = Rnd(int64(uint64(HEADR)+Segtext.Length), int64(*FlagRound)) + Rnd(int64(Segrelrodata.Filelen), int64(*FlagRound)) + Rnd(int64(Segdata.Filelen), int64(*FlagRound)) + Rnd(int64(Segdwarf.Filelen), int64(*FlagRound)) ctxt.Out.SeekSet(linkoff) ctxt.Out.Write(ldr.Data(s1)) @@ -1086,6 +1092,9 @@ func machoEmitReloc(ctxt *Link) { for _, sect := range Segtext.Sections[1:] { relocSect(ctxt, sect, ctxt.datap) } + for _, sect := range Segrelrodata.Sections { + relocSect(ctxt, sect, ctxt.datap) + } for _, sect := range Segdata.Sections { relocSect(ctxt, sect, ctxt.datap) } diff --git a/src/cmd/link/internal/ld/macho_combine_dwarf.go b/src/cmd/link/internal/ld/macho_combine_dwarf.go index 9d9f916b8e..77ee8a4d62 100644 --- a/src/cmd/link/internal/ld/macho_combine_dwarf.go +++ b/src/cmd/link/internal/ld/macho_combine_dwarf.go @@ -16,10 +16,6 @@ import ( "unsafe" ) -const ( - pageAlign = 12 // 4096 = 1 << 12 -) - type loadCmd struct { Cmd macho.LoadCmd Len uint32 @@ -138,7 +134,7 @@ func machoCombineDwarf(ctxt *Link, exef *os.File, exem *macho.File, dsym, outexe // Now copy the dwarf data into the output. // Kernel requires all loaded segments to be page-aligned in the file, // even though we mark this one as being 0 bytes of virtual address space. - dwarfstart := machoCalcStart(realdwarf.Offset, linkseg.Offset, pageAlign) + dwarfstart := Rnd(int64(linkseg.Offset), int64(*FlagRound)) if _, err := outf.Seek(dwarfstart, 0); err != nil { return err } @@ -166,7 +162,7 @@ func machoCombineDwarf(ctxt *Link, exef *os.File, exem *macho.File, dsym, outexe if _, err := exef.Seek(int64(linkseg.Offset), 0); err != nil { return err } - linkstart := machoCalcStart(linkseg.Offset, uint64(dwarfstart)+dwarfsize, pageAlign) + linkstart := Rnd(dwarfstart+int64(dwarfsize), int64(*FlagRound)) if _, err := outf.Seek(linkstart, 0); err != nil { return err } @@ -217,9 +213,9 @@ func machoCombineDwarf(ctxt *Link, exef *os.File, exem *macho.File, dsym, outexe linkoffset := uint64(linkstart) - linkseg.Offset switch cmd.Cmd { case macho.LoadCmdSegment64: - err = machoUpdateSegment(reader, linkseg, linkoffset, &macho.Segment64{}, &macho.Section64{}) + err = machoUpdateSegment(reader, linkseg, linkoffset) case macho.LoadCmdSegment: - err = machoUpdateSegment(reader, linkseg, linkoffset, &macho.Segment32{}, &macho.Section32{}) + panic("unexpected 32-bit segment") case LC_DYLD_INFO, LC_DYLD_INFO_ONLY: err = machoUpdateLoadCommand(reader, linkseg, linkoffset, &dyldInfoCmd{}, "RebaseOff", "BindOff", "WeakBindOff", "LazyBindOff", "ExportOff") case macho.LoadCmdSymtab: @@ -313,70 +309,56 @@ func machoCompressSection(sectBytes []byte) (compressed bool, contents []byte, e // machoUpdateSegment updates the load command for a moved segment. // Only the linkedit segment should move, and it should have 0 sections. -// seg should be a macho.Segment32 or macho.Segment64 as appropriate. -// sect should be a macho.Section32 or macho.Section64 as appropriate. -func machoUpdateSegment(r loadCmdReader, linkseg *macho.Segment, linkoffset uint64, seg, sect interface{}) error { - if err := r.ReadAt(0, seg); err != nil { +func machoUpdateSegment(r loadCmdReader, linkseg *macho.Segment, linkoffset uint64) error { + var seg macho.Segment64 + if err := r.ReadAt(0, &seg); err != nil { return err } - segValue := reflect.ValueOf(seg) - offset := reflect.Indirect(segValue).FieldByName("Offset") // Only the linkedit segment moved, anything before that is fine. - if offset.Uint() < linkseg.Offset { + if seg.Offset < linkseg.Offset { return nil } - offset.SetUint(offset.Uint() + linkoffset) - if err := r.WriteAt(0, seg); err != nil { + seg.Offset += linkoffset + if err := r.WriteAt(0, &seg); err != nil { return err } // There shouldn't be any sections, but just to make sure... - return machoUpdateSections(r, segValue, reflect.ValueOf(sect), linkoffset, nil) + return machoUpdateSections(r, &seg, linkoffset, nil) } -func machoUpdateSections(r loadCmdReader, seg, sect reflect.Value, deltaOffset uint64, compressedSects []*macho.Section) error { - iseg := reflect.Indirect(seg) - nsect := iseg.FieldByName("Nsect").Uint() +func machoUpdateSections(r loadCmdReader, seg *macho.Segment64, deltaOffset uint64, compressedSects []*macho.Section) error { + nsect := seg.Nsect if nsect == 0 { return nil } - sectOffset := int64(iseg.Type().Size()) - - isect := reflect.Indirect(sect) - offsetField := isect.FieldByName("Offset") - reloffField := isect.FieldByName("Reloff") - addrField := isect.FieldByName("Addr") - nameField := isect.FieldByName("Name") - sizeField := isect.FieldByName("Size") - sectSize := int64(isect.Type().Size()) - for i := uint64(0); i < nsect; i++ { - if err := r.ReadAt(sectOffset, sect.Interface()); err != nil { + sectOffset := int64(unsafe.Sizeof(*seg)) + + var sect macho.Section64 + sectSize := int64(unsafe.Sizeof(sect)) + for i := uint32(0); i < nsect; i++ { + if err := r.ReadAt(sectOffset, §); err != nil { return err } if compressedSects != nil { cSect := compressedSects[i] - var name [16]byte - copy(name[:], []byte(cSect.Name)) - nameField.Set(reflect.ValueOf(name)) - sizeField.SetUint(cSect.Size) + copy(sect.Name[:], cSect.Name) + sect.Size = cSect.Size if cSect.Offset != 0 { - offsetField.SetUint(uint64(cSect.Offset) + deltaOffset) + sect.Offset = cSect.Offset + uint32(deltaOffset) } if cSect.Addr != 0 { - addrField.SetUint(cSect.Addr) + sect.Addr = cSect.Addr } } else { - if offsetField.Uint() != 0 { - offsetField.SetUint(offsetField.Uint() + deltaOffset) - } - if reloffField.Uint() != 0 { - reloffField.SetUint(reloffField.Uint() + deltaOffset) + if sect.Offset != 0 { + sect.Offset += uint32(deltaOffset) } - if addrField.Uint() != 0 { - addrField.SetUint(addrField.Uint()) + if sect.Reloff != 0 { + sect.Reloff += uint32(deltaOffset) } } - if err := r.WriteAt(sectOffset, sect.Interface()); err != nil { + if err := r.WriteAt(sectOffset, §); err != nil { return err } sectOffset += sectSize @@ -386,32 +368,27 @@ func machoUpdateSections(r loadCmdReader, seg, sect reflect.Value, deltaOffset u // machoUpdateDwarfHeader updates the DWARF segment load command. func machoUpdateDwarfHeader(r *loadCmdReader, compressedSects []*macho.Section, dwarfsize uint64, dwarfstart int64, realdwarf *macho.Segment) error { - var seg, sect interface{} cmd, err := r.Next() if err != nil { return err } - if cmd.Cmd == macho.LoadCmdSegment64 { - seg = new(macho.Segment64) - sect = new(macho.Section64) - } else { - seg = new(macho.Segment32) - sect = new(macho.Section32) + if cmd.Cmd != macho.LoadCmdSegment64 { + panic("not a Segment64") } - if err := r.ReadAt(0, seg); err != nil { + var seg macho.Segment64 + if err := r.ReadAt(0, &seg); err != nil { return err } - segv := reflect.ValueOf(seg).Elem() - segv.FieldByName("Offset").SetUint(uint64(dwarfstart)) + seg.Offset = uint64(dwarfstart) if compressedSects != nil { var segSize uint64 for _, newSect := range compressedSects { segSize += newSect.Size } - segv.FieldByName("Filesz").SetUint(segSize) + seg.Filesz = segSize } else { - segv.FieldByName("Filesz").SetUint(dwarfsize) + seg.Filesz = dwarfsize } // We want the DWARF segment to be considered non-loadable, so @@ -424,14 +401,14 @@ func machoUpdateDwarfHeader(r *loadCmdReader, compressedSects []*macho.Section, // in ImageLoaderMachO.cpp (various versions can be found online, see // https://opensource.apple.com/source/dyld/dyld-519.2.2/src/ImageLoaderMachO.cpp.auto.html // as one example). - segv.FieldByName("Addr").SetUint(0) - segv.FieldByName("Memsz").SetUint(0) - segv.FieldByName("Prot").SetUint(0) + seg.Addr = 0 + seg.Memsz = 0 + seg.Prot = 0 - if err := r.WriteAt(0, seg); err != nil { + if err := r.WriteAt(0, &seg); err != nil { return err } - return machoUpdateSections(*r, segv, reflect.ValueOf(sect), uint64(dwarfstart)-realdwarf.Offset, compressedSects) + return machoUpdateSections(*r, &seg, uint64(dwarfstart)-realdwarf.Offset, compressedSects) } func machoUpdateLoadCommand(r loadCmdReader, linkseg *macho.Segment, linkoffset uint64, cmd interface{}, fields ...string) error { @@ -451,12 +428,3 @@ func machoUpdateLoadCommand(r loadCmdReader, linkseg *macho.Segment, linkoffset } return nil } - -func machoCalcStart(origAddr, newAddr uint64, alignExp uint32) int64 { - align := uint64(1 << alignExp) - origMod, newMod := origAddr%align, newAddr%align - if origMod == newMod { - return int64(newAddr) - } - return int64(newAddr + align + origMod - newMod) -} diff --git a/src/cmd/link/internal/ld/symtab.go b/src/cmd/link/internal/ld/symtab.go index bc880955b8..56363cdaae 100644 --- a/src/cmd/link/internal/ld/symtab.go +++ b/src/cmd/link/internal/ld/symtab.go @@ -681,8 +681,8 @@ func (ctxt *Link) symtab(pcln *pclntab) []sym.SymKind { itablinkSym := ldr.Lookup("runtime.itablink", 0) nitablinks := uint64(ldr.SymSize(itablinkSym)) / uint64(ctxt.Arch.PtrSize) moduledata.AddAddr(ctxt.Arch, itablinkSym) - moduledata.AddUint(ctxt.Arch, uint64(nitablinks)) - moduledata.AddUint(ctxt.Arch, uint64(nitablinks)) + moduledata.AddUint(ctxt.Arch, nitablinks) + moduledata.AddUint(ctxt.Arch, nitablinks) // The ptab slice if ptab := ldr.Lookup("go.plugin.tabs", 0); ptab != 0 && ldr.AttrReachable(ptab) { ldr.SetAttrLocal(ptab, true) diff --git a/src/cmd/link/internal/ld/target.go b/src/cmd/link/internal/ld/target.go index 102b6c5436..f68de8fff1 100644 --- a/src/cmd/link/internal/ld/target.go +++ b/src/cmd/link/internal/ld/target.go @@ -74,8 +74,12 @@ func (t *Target) IsDynlinkingGo() bool { func (t *Target) UseRelro() bool { switch t.BuildMode { case BuildModeCArchive, BuildModeCShared, BuildModeShared, BuildModePIE, BuildModePlugin: - return t.IsELF || t.HeadType == objabi.Haix + return t.IsELF || t.HeadType == objabi.Haix || t.HeadType == objabi.Hdarwin default: + if t.HeadType == objabi.Hdarwin && t.IsARM64() { + // On darwin/ARM64, everything is PIE. + return true + } return t.linkShared || (t.HeadType == objabi.Haix && t.LinkMode == LinkExternal) } } |