diff --git a/src/cmd/link/internal/ld/data.go b/src/cmd/link/internal/ld/data.go index 04fe3cb3b5..7f4fe71cb4 100644 --- a/src/cmd/link/internal/ld/data.go +++ b/src/cmd/link/internal/ld/data.go @@ -2385,6 +2385,12 @@ func compressSyms(ctxt *Link, syms []*sym.Symbol) []byte { log.Fatalf("NewWriterLevel failed: %s", err) } for _, sym := range syms { + // sym.P may be read-only. Apply relocations in a + // temporary buffer, and immediately write it out. + oldP := sym.P + ctxt.relocbuf = append(ctxt.relocbuf[:0], sym.P...) + sym.P = ctxt.relocbuf + relocsym(ctxt, sym) if _, err := z.Write(sym.P); err != nil { log.Fatalf("compression failed: %s", err) } @@ -2399,6 +2405,14 @@ func compressSyms(ctxt *Link, syms []*sym.Symbol) []byte { } i -= int64(n) } + // Restore sym.P, for 1. not holding temp buffer live + // unnecessarily, 2. if compression is not beneficial, + // we'll go back to use the uncompressed contents, in + // which case we still need sym.P. + sym.P = oldP + for i := range sym.R { + sym.R[i].Done = false + } } if err := z.Close(); err != nil { log.Fatalf("compression failed: %s", err) diff --git a/src/cmd/link/internal/ld/dwarf.go b/src/cmd/link/internal/ld/dwarf.go index 9e7fea0101..974c7ed329 100644 --- a/src/cmd/link/internal/ld/dwarf.go +++ b/src/cmd/link/internal/ld/dwarf.go @@ -2125,9 +2125,9 @@ func dwarfaddelfsectionsyms(ctxt *Link) { } } -// dwarfcompress compresses the DWARF sections. This must happen after -// relocations are applied. After this, dwarfp will contain a -// different (new) set of symbols, and sections may have been replaced. +// dwarfcompress compresses the DWARF sections. Relocations are applied +// on the fly. After this, dwarfp will contain a different (new) set of +// symbols, and sections may have been replaced. func dwarfcompress(ctxt *Link) { supported := ctxt.IsELF || ctxt.HeadType == objabi.Hwindows || ctxt.HeadType == objabi.Hdarwin if !ctxt.compressDWARF || !supported || ctxt.LinkMode != LinkInternal { @@ -2161,6 +2161,7 @@ func dwarfcompress(ctxt *Link) { } } dwarfp = newDwarfp + ctxt.relocbuf = nil // no longer needed, don't hold it live // Re-compute the locations of the compressed DWARF symbols // and sections, since the layout of these within the file is diff --git a/src/cmd/link/internal/ld/link.go b/src/cmd/link/internal/ld/link.go index a7609b9c7c..d3ffacf54e 100644 --- a/src/cmd/link/internal/ld/link.go +++ b/src/cmd/link/internal/ld/link.go @@ -93,6 +93,8 @@ type Link struct { compUnits []*compilationUnit // DWARF compilation units compUnitByPackage map[*sym.Library]*compilationUnit + + relocbuf []byte // temporary buffer for applying relocations } type unresolvedSymKey struct { diff --git a/src/cmd/link/internal/ld/main.go b/src/cmd/link/internal/ld/main.go index 1b2d376fd4..aac37883e1 100644 --- a/src/cmd/link/internal/ld/main.go +++ b/src/cmd/link/internal/ld/main.go @@ -239,8 +239,8 @@ func Main(arch *sys.Arch, theArch Arch) { ctxt.symtab() ctxt.dodata() order := ctxt.address() - ctxt.reloc() dwarfcompress(ctxt) + ctxt.reloc() filesize := ctxt.layout(order) // Write out the output file.