cmd/link: add info.plist support via plist linker option

This change adds a flag to the linker to allow it to embed info.plist
data into the resulting binaries. This can, for example, be used to
add code signing properties to binaries.
This commit is contained in:
Ed Schouten 2023-08-14 11:16:29 +02:00
parent 5c15498609
commit 29b7c5c393
3 changed files with 37 additions and 0 deletions

View File

@ -2360,6 +2360,30 @@ func appendString(data []byte, s string) []byte {
return data
}
// addPlist will add an info.Plist file, as segment __TEXT and section __info_plist.
// This is used when using the internal linker. Search in lib.go for __info_plist to find
// the external linker handling of this. Adding a section with an info.plist file allows
// Go executables to be code-signed for macOS.
func (ctxt *Link) addPlist(fn string) {
if fn == "" {
return
}
b, err := os.ReadFile(fn)
if err != nil {
Exitf("reading %s: %s", fn, err)
}
ldr := ctxt.loader
sect := Segtext.Sections[len(Segtext.Sections)-1]
builder := ldr.MakeSymbolBuilder(".info.plist") // __info_list
builder.Addstring(string(b) + "\x00") // asciiz
builder.SetType(sym.SELFRXSECT) // Produces standalone section, without fixups
builder.SetAlign(16) // Sections don't seem to strictly require this
builder.SetReachable(true) // Don't let the linker drop it
builder.SetSect(sect)
ldr.SetSymSect(builder.Sym(), sect)
}
// assign addresses to text
func (ctxt *Link) textaddress() {
addsection(ctxt.loader, ctxt.Arch, &Segtext, ".text", 05)

View File

@ -1811,6 +1811,15 @@ func (ctxt *Link) hostlink() {
argv = append(argv, p)
checkStatic(p)
}
// this will add an info.Plist file, as segment __TEXT and section __info_plist.
// This is used when using the external linker. Search in data.go for __info_plist to find
// the internal linker handling of this. Adding a section with an info.plist file allows
// Go executables to be code-signed for macOS.
if ctxt.LinkMode == LinkExternal && ctxt.IsDarwin() && *flagPlist != "" {
argv = append(argv, "-extldflags", fmt.Sprintf(`-sectcreate __TEXT __info_plist %q`, *flagPlist))
}
if ctxt.HeadType == objabi.Hwindows {
// Determine which linker we're using. Add in the extldflags in
// case used has specified "-fuse-ld=...".

View File

@ -82,6 +82,8 @@ var (
flagCaptureHostObjs = flag.String("capturehostobjs", "", "capture host object files loaded during internal linking to specified dir")
flagPlist = flag.String("plist", "", "filename of info.plist to include")
flagA = flag.Bool("a", false, "no-op (deprecated)")
FlagC = flag.Bool("c", false, "dump call graph")
FlagD = flag.Bool("d", false, "disable dynamic executable")
@ -357,6 +359,8 @@ func Main(arch *sys.Arch, theArch Arch) {
dwarfcompress(ctxt)
bench.Start("layout")
filesize := ctxt.layout(order)
bench.Start("plist")
ctxt.addPlist(*flagPlist)
// Write out the output file.
// It is split into two parts (Asmb and Asmb2). The first