diff options
Diffstat (limited to 'go-patches/0002-cmd-link-handle-grouped-resource-sections.patch')
-rw-r--r-- | go-patches/0002-cmd-link-handle-grouped-resource-sections.patch | 339 |
1 files changed, 0 insertions, 339 deletions
diff --git a/go-patches/0002-cmd-link-handle-grouped-resource-sections.patch b/go-patches/0002-cmd-link-handle-grouped-resource-sections.patch deleted file mode 100644 index 85fbc3e9..00000000 --- a/go-patches/0002-cmd-link-handle-grouped-resource-sections.patch +++ /dev/null @@ -1,339 +0,0 @@ -From f7465aae6e0e8bc4c90c3b8386f5a2a574a15de0 Mon Sep 17 00:00:00 2001 -From: "Jason A. Donenfeld" <Jason@zx2c4.com> -Date: Sun, 8 Nov 2020 11:57:42 +0100 -Subject: [PATCH 2/2] cmd/link: handle grouped resource sections - -The Go PE linker does not support enough generalized PE logic to -properly handle .rsrc sections gracefully. Instead a few things are -special cased for these. The linker also does not support PE's "grouped -sections" features, in which input objects have several named sections -that are sorted, merged, and renamed in the output file. In the past, -more sophisticated support for resources or for PE features like grouped -sections have not been necessary, as Go's own object formats are pretty -vanilla, and GNU binutils also produces pretty vanilla objects where all -sections are already merged. - -However, GNU binutils is lagging with arm support, and here LLVM has -picked up the slack. In particular, LLVM has its own rc/cvtres combo, -which are glued together in mingw LLVM distributions as windres, a -command line compatible tool with binutils' windres, which supports arm -and arm64. But there's a key difference between binutils' windres and -LLVM's windres: the LLVM one uses proper grouped sections. - -So, this commit adds grouped sections support for resource sections to -the linker. We don't attempt to plumb generic support for grouped -sections, just as there isn't generic support already for what resources -require. Instead we augment the resource handling logic to deal with -standard two-section resource objects. - -We also add a test for this, akin to the current test for more vanilla -binutils resource objects, and make sure that the rsrc tests are always -performed. - -Fixes #42866. -Fixes #43182. - -Change-Id: I059450021405cdf2ef1c195ddbab3960764ad711 -Reviewed-on: https://go-review.googlesource.com/c/go/+/268337 -Run-TryBot: Jason A. Donenfeld <Jason@zx2c4.com> -TryBot-Result: Go Bot <gobot@golang.org> -Reviewed-by: Cherry Zhang <cherryyz@google.com> -Trust: Alex Brainman <alex.brainman@gmail.com> -Trust: Jason A. Donenfeld <Jason@zx2c4.com> ---- - src/cmd/link/internal/ld/lib.go | 2 +- - src/cmd/link/internal/ld/pe.go | 60 ++++++++++-------- - src/cmd/link/internal/loadpe/ldpe.go | 49 +++++++------- - src/cmd/link/link_test.go | 19 ++++++ - .../link/testdata/testPErsrc-complex/main.go | 43 +++++++++++++ - .../testdata/testPErsrc-complex/rsrc.syso | Bin 0 -> 352 bytes - 6 files changed, 124 insertions(+), 49 deletions(-) - create mode 100644 src/cmd/link/testdata/testPErsrc-complex/main.go - create mode 100644 src/cmd/link/testdata/testPErsrc-complex/rsrc.syso - -diff --git a/src/cmd/link/internal/ld/lib.go b/src/cmd/link/internal/ld/lib.go -index f3c301cc9b..9c2231a34e 100644 ---- a/src/cmd/link/internal/ld/lib.go -+++ b/src/cmd/link/internal/ld/lib.go -@@ -1808,7 +1808,7 @@ func ldobj(ctxt *Link, f *bio.Reader, lib *sym.Library, length int64, pn string, - Errorf(nil, "%v", err) - return - } -- if rsrc != 0 { -+ if len(rsrc) != 0 { - setpersrc(ctxt, rsrc) - } - ctxt.Textp = append(ctxt.Textp, textp...) -diff --git a/src/cmd/link/internal/ld/pe.go b/src/cmd/link/internal/ld/pe.go -index adbf516d5c..5edaf54dd2 100644 ---- a/src/cmd/link/internal/ld/pe.go -+++ b/src/cmd/link/internal/ld/pe.go -@@ -253,7 +253,7 @@ type Dll struct { - } - - var ( -- rsrcsym loader.Sym -+ rsrcsyms []loader.Sym - PESECTHEADR int32 - PEFILEHEADR int32 - pe64 int -@@ -1508,46 +1508,56 @@ func (ctxt *Link) dope() { - initdynexport(ctxt) - } - --func setpersrc(ctxt *Link, sym loader.Sym) { -- if rsrcsym != 0 { -+func setpersrc(ctxt *Link, syms []loader.Sym) { -+ if len(rsrcsyms) != 0 { - Errorf(nil, "too many .rsrc sections") - } -- -- rsrcsym = sym -+ rsrcsyms = syms - } - - func addpersrc(ctxt *Link) { -- if rsrcsym == 0 { -+ if len(rsrcsyms) == 0 { - return - } - -- data := ctxt.loader.Data(rsrcsym) -- size := len(data) -- h := pefile.addSection(".rsrc", size, size) -+ var size int64 -+ for _, rsrcsym := range rsrcsyms { -+ size += ctxt.loader.SymSize(rsrcsym) -+ } -+ h := pefile.addSection(".rsrc", int(size), int(size)) - h.characteristics = IMAGE_SCN_MEM_READ | IMAGE_SCN_CNT_INITIALIZED_DATA - h.checkOffset(ctxt.Out.Offset()) - -- // relocation -- relocs := ctxt.loader.Relocs(rsrcsym) -- for i := 0; i < relocs.Count(); i++ { -- r := relocs.At(i) -- p := data[r.Off():] -- val := uint32(int64(h.virtualAddress) + r.Add()) -- -- // 32-bit little-endian -- p[0] = byte(val) -- -- p[1] = byte(val >> 8) -- p[2] = byte(val >> 16) -- p[3] = byte(val >> 24) -+ for _, rsrcsym := range rsrcsyms { -+ // A split resource happens when the actual resource data and its relocations are -+ // split across multiple sections, denoted by a $01 or $02 at the end of the .rsrc -+ // section name. -+ splitResources := strings.Contains(ctxt.loader.SymName(rsrcsym), ".rsrc$") -+ relocs := ctxt.loader.Relocs(rsrcsym) -+ data := ctxt.loader.Data(rsrcsym) -+ for ri := 0; ri < relocs.Count(); ri++ { -+ r := relocs.At(ri) -+ p := data[r.Off():] -+ val := uint32(int64(h.virtualAddress) + r.Add()) -+ if splitResources { -+ // If we're a split resource section, and that section has relocation -+ // symbols, then the data that it points to doesn't actually begin at -+ // the virtual address listed in this current section, but rather -+ // begins at the section immediately after this one. So, in order to -+ // calculate the proper virtual address of the data it's pointing to, -+ // we have to add the length of this section to the virtual address. -+ // This works because .rsrc sections are divided into two (but not more) -+ // of these sections. -+ val += uint32(len(data)) -+ } -+ binary.LittleEndian.PutUint32(p, val) -+ } -+ ctxt.Out.Write(data) - } -- -- ctxt.Out.Write(data) - h.pad(ctxt.Out, uint32(size)) - - // update data directory - pefile.dataDirectory[pe.IMAGE_DIRECTORY_ENTRY_RESOURCE].VirtualAddress = h.virtualAddress -- - pefile.dataDirectory[pe.IMAGE_DIRECTORY_ENTRY_RESOURCE].Size = h.virtualSize - } - -diff --git a/src/cmd/link/internal/loadpe/ldpe.go b/src/cmd/link/internal/loadpe/ldpe.go -index 1e6f978531..a5c025de8f 100644 ---- a/src/cmd/link/internal/loadpe/ldpe.go -+++ b/src/cmd/link/internal/loadpe/ldpe.go -@@ -157,8 +157,9 @@ func makeUpdater(l *loader.Loader, bld *loader.SymbolBuilder, s loader.Sym) *loa - - // Load loads the PE file pn from input. - // Symbols are written into syms, and a slice of the text symbols is returned. --// If an .rsrc section is found, its symbol is returned as rsrc. --func Load(l *loader.Loader, arch *sys.Arch, localSymVersion int, input *bio.Reader, pkg string, length int64, pn string) (textp []loader.Sym, rsrc loader.Sym, err error) { -+// If an .rsrc section or set of .rsrc$xx sections is found, its symbols are -+// returned as rsrc. -+func Load(l *loader.Loader, arch *sys.Arch, localSymVersion int, input *bio.Reader, pkg string, length int64, pn string) (textp []loader.Sym, rsrc []loader.Sym, err error) { - lookup := func(name string, version int) (*loader.SymbolBuilder, loader.Sym) { - s := l.LookupOrCreateSym(name, version) - sb := l.MakeSymbolUpdater(s) -@@ -176,7 +177,7 @@ func Load(l *loader.Loader, arch *sys.Arch, localSymVersion int, input *bio.Read - // TODO: replace pe.NewFile with pe.Load (grep for "add Load function" in debug/pe for details) - f, err := pe.NewFile(sr) - if err != nil { -- return nil, 0, err -+ return nil, nil, err - } - defer f.Close() - -@@ -211,21 +212,21 @@ func Load(l *loader.Loader, arch *sys.Arch, localSymVersion int, input *bio.Read - bld.SetType(sym.STEXT) - - default: -- return nil, 0, fmt.Errorf("unexpected flags %#06x for PE section %s", sect.Characteristics, sect.Name) -+ return nil, nil, fmt.Errorf("unexpected flags %#06x for PE section %s", sect.Characteristics, sect.Name) - } - - if bld.Type() != sym.SNOPTRBSS { - data, err := sect.Data() - if err != nil { -- return nil, 0, err -+ return nil, nil, err - } - sectdata[sect] = data - bld.SetData(data) - } - bld.SetSize(int64(sect.Size)) - sectsyms[sect] = s -- if sect.Name == ".rsrc" { -- rsrc = s -+ if sect.Name == ".rsrc" || strings.HasPrefix(sect.Name, ".rsrc$") { -+ rsrc = append(rsrc, s) - } - } - -@@ -246,22 +247,23 @@ func Load(l *loader.Loader, arch *sys.Arch, localSymVersion int, input *bio.Read - continue - } - -+ splitResources := strings.HasPrefix(rsect.Name, ".rsrc$") - sb := l.MakeSymbolUpdater(sectsyms[rsect]) - for j, r := range rsect.Relocs { - if int(r.SymbolTableIndex) >= len(f.COFFSymbols) { -- return nil, 0, fmt.Errorf("relocation number %d symbol index idx=%d cannot be large then number of symbols %d", j, r.SymbolTableIndex, len(f.COFFSymbols)) -+ return nil, nil, fmt.Errorf("relocation number %d symbol index idx=%d cannot be large then number of symbols %d", j, r.SymbolTableIndex, len(f.COFFSymbols)) - } - pesym := &f.COFFSymbols[r.SymbolTableIndex] - _, gosym, err := readpesym(l, arch, l.LookupOrCreateSym, f, pesym, sectsyms, localSymVersion) - if err != nil { -- return nil, 0, err -+ return nil, nil, err - } - if gosym == 0 { - name, err := pesym.FullName(f.StringTable) - if err != nil { - name = string(pesym.Name[:]) - } -- return nil, 0, fmt.Errorf("reloc of invalid sym %s idx=%d type=%d", name, r.SymbolTableIndex, pesym.Type) -+ return nil, nil, fmt.Errorf("reloc of invalid sym %s idx=%d type=%d", name, r.SymbolTableIndex, pesym.Type) - } - - rSym := gosym -@@ -271,11 +273,11 @@ func Load(l *loader.Loader, arch *sys.Arch, localSymVersion int, input *bio.Read - var rType objabi.RelocType - switch arch.Family { - default: -- return nil, 0, fmt.Errorf("%s: unsupported arch %v", pn, arch.Family) -+ return nil, nil, fmt.Errorf("%s: unsupported arch %v", pn, arch.Family) - case sys.I386, sys.AMD64: - switch r.Type { - default: -- return nil, 0, fmt.Errorf("%s: %v: unknown relocation type %v", pn, sectsyms[rsect], r.Type) -+ return nil, nil, fmt.Errorf("%s: %v: unknown relocation type %v", pn, sectsyms[rsect], r.Type) - - case IMAGE_REL_I386_REL32, IMAGE_REL_AMD64_REL32, - IMAGE_REL_AMD64_ADDR32, // R_X86_64_PC32 -@@ -302,7 +304,7 @@ func Load(l *loader.Loader, arch *sys.Arch, localSymVersion int, input *bio.Read - case sys.ARM: - switch r.Type { - default: -- return nil, 0, fmt.Errorf("%s: %v: unknown ARM relocation type %v", pn, sectsyms[rsect], r.Type) -+ return nil, nil, fmt.Errorf("%s: %v: unknown ARM relocation type %v", pn, sectsyms[rsect], r.Type) - - case IMAGE_REL_ARM_SECREL: - rType = objabi.R_PCREL -@@ -323,8 +325,9 @@ func Load(l *loader.Loader, arch *sys.Arch, localSymVersion int, input *bio.Read - - // ld -r could generate multiple section symbols for the - // same section but with different values, we have to take -- // that into account -- if issect(pesym) { -+ // that into account, or in the case of split resources, -+ // the section and its symbols are split into two sections. -+ if issect(pesym) || splitResources { - rAdd += int64(pesym.Value) - } - -@@ -346,7 +349,7 @@ func Load(l *loader.Loader, arch *sys.Arch, localSymVersion int, input *bio.Read - - name, err := pesym.FullName(f.StringTable) - if err != nil { -- return nil, 0, err -+ return nil, nil, err - } - if name == "" { - continue -@@ -384,7 +387,7 @@ func Load(l *loader.Loader, arch *sys.Arch, localSymVersion int, input *bio.Read - - bld, s, err := readpesym(l, arch, l.LookupOrCreateSym, f, pesym, sectsyms, localSymVersion) - if err != nil { -- return nil, 0, err -+ return nil, nil, err - } - - if pesym.SectionNumber == 0 { // extern -@@ -402,14 +405,14 @@ func Load(l *loader.Loader, arch *sys.Arch, localSymVersion int, input *bio.Read - } else if pesym.SectionNumber > 0 && int(pesym.SectionNumber) <= len(f.Sections) { - sect = f.Sections[pesym.SectionNumber-1] - if _, found := sectsyms[sect]; !found { -- return nil, 0, fmt.Errorf("%s: %v: missing sect.sym", pn, s) -+ return nil, nil, fmt.Errorf("%s: %v: missing sect.sym", pn, s) - } - } else { -- return nil, 0, fmt.Errorf("%s: %v: sectnum < 0!", pn, s) -+ return nil, nil, fmt.Errorf("%s: %v: sectnum < 0!", pn, s) - } - - if sect == nil { -- return nil, 0, nil -+ return nil, nil, nil - } - - if l.OuterSym(s) != 0 { -@@ -418,7 +421,7 @@ func Load(l *loader.Loader, arch *sys.Arch, localSymVersion int, input *bio.Read - } - outerName := l.SymName(l.OuterSym(s)) - sectName := l.SymName(sectsyms[sect]) -- return nil, 0, fmt.Errorf("%s: duplicate symbol reference: %s in both %s and %s", pn, l.SymName(s), outerName, sectName) -+ return nil, nil, fmt.Errorf("%s: duplicate symbol reference: %s in both %s and %s", pn, l.SymName(s), outerName, sectName) - } - - bld = makeUpdater(l, bld, s) -@@ -429,7 +432,7 @@ func Load(l *loader.Loader, arch *sys.Arch, localSymVersion int, input *bio.Read - bld.SetSize(4) - if l.SymType(sectsym) == sym.STEXT { - if bld.External() && !bld.DuplicateOK() { -- return nil, 0, fmt.Errorf("%s: duplicate symbol definition", l.SymName(s)) -+ return nil, nil, fmt.Errorf("%s: duplicate symbol definition", l.SymName(s)) - } - bld.SetExternal(true) - } -@@ -446,7 +449,7 @@ func Load(l *loader.Loader, arch *sys.Arch, localSymVersion int, input *bio.Read - if l.SymType(s) == sym.STEXT { - for ; s != 0; s = l.SubSym(s) { - if l.AttrOnList(s) { -- return nil, 0, fmt.Errorf("symbol %s listed multiple times", l.SymName(s)) -+ return nil, nil, fmt.Errorf("symbol %s listed multiple times", l.SymName(s)) - } - l.SetAttrOnList(s, true) - textp = append(textp, s) --- -2.29.2 - |