]> Cypherpunks.ru repositories - gostls13.git/commitdiff
cmd/link: default generic ABI compression for ELF
authorMeng Zhuo <mzh@golangcn.org>
Wed, 26 Jan 2022 02:23:48 +0000 (10:23 +0800)
committermzh <mzh@golangcn.org>
Wed, 16 Mar 2022 05:32:52 +0000 (05:32 +0000)
This CL change all debug dwarf headers to generic ABI
"Compression header" for ELF
(http://www.sco.com/developers/gabi/latest/ch4.sheader.html#compression_header)

Fixes #50796

Change-Id: I188625e596f11cd120dbd802ac2d79341d5eaf41
Reviewed-on: https://go-review.googlesource.com/c/go/+/380755
Trust: mzh <mzh@golangcn.org>
Run-TryBot: mzh <mzh@golangcn.org>
TryBot-Result: Gopher Robot <gobot@golang.org>
Reviewed-by: Than McIntosh <thanm@google.com>
Reviewed-by: Cherry Mui <cherryyz@google.com>
src/cmd/link/elf_test.go
src/cmd/link/internal/ld/data.go
src/cmd/link/internal/ld/dwarf.go
src/cmd/link/internal/ld/elf.go
src/cmd/link/internal/ld/lib.go
src/cmd/link/internal/sym/segment.go
src/debug/elf/file.go

index 760d9ea60d92d53555a271800350dcc3988ab1a0..318bd76abae07c52346d35e5d81eb43b67dc8f48 100644 (file)
@@ -455,6 +455,9 @@ func TestPIESize(t *testing.T) {
                        extraexe := extrasize(elfexe)
                        extrapie := extrasize(elfpie)
 
+                       if sizepie < sizeexe || sizepie-extrapie < sizeexe-extraexe {
+                               return
+                       }
                        diffReal := (sizepie - extrapie) - (sizeexe - extraexe)
                        diffExpected := (textpie + dynpie) - (textexe + dynexe)
 
index 95a8e0facb41f92253a05b4ac2acdb68aa44e9d3..0ec1e526a9840d0201fc8776c3e20874613a56cd 100644 (file)
@@ -2778,10 +2778,29 @@ func compressSyms(ctxt *Link, syms []loader.Sym) []byte {
        }
 
        var buf bytes.Buffer
-       buf.Write([]byte("ZLIB"))
-       var sizeBytes [8]byte
-       binary.BigEndian.PutUint64(sizeBytes[:], uint64(total))
-       buf.Write(sizeBytes[:])
+       if ctxt.IsELF {
+               switch ctxt.Arch.PtrSize {
+               case 8:
+                       binary.Write(&buf, ctxt.Arch.ByteOrder, elf.Chdr64{
+                               Type:      uint32(elf.COMPRESS_ZLIB),
+                               Size:      uint64(total),
+                               Addralign: uint64(ctxt.Arch.Alignment),
+                       })
+               case 4:
+                       binary.Write(&buf, ctxt.Arch.ByteOrder, elf.Chdr32{
+                               Type:      uint32(elf.COMPRESS_ZLIB),
+                               Size:      uint32(total),
+                               Addralign: uint32(ctxt.Arch.Alignment),
+                       })
+               default:
+                       log.Fatalf("can't compress header size:%d", ctxt.Arch.PtrSize)
+               }
+       } else {
+               buf.Write([]byte("ZLIB"))
+               var sizeBytes [8]byte
+               binary.BigEndian.PutUint64(sizeBytes[:], uint64(total))
+               buf.Write(sizeBytes[:])
+       }
 
        var relocbuf []byte // temporary buffer for applying relocations
 
index 4aaed7baf04ff18d90e46de3171342b5e077936e..289ebcb59580e66c8356ad34f8d19b784eb1c3d1 100644 (file)
@@ -2227,11 +2227,18 @@ func dwarfcompress(ctxt *Link) {
                        newDwarfp = append(newDwarfp, ds)
                        Segdwarf.Sections = append(Segdwarf.Sections, ldr.SymSect(s))
                } else {
-                       compressedSegName := ".zdebug_" + ldr.SymSect(s).Name[len(".debug_"):]
+                       var compressedSegName string
+                       if ctxt.IsELF {
+                               compressedSegName = ldr.SymSect(s).Name
+                       } else {
+                               compressedSegName = ".zdebug_" + ldr.SymSect(s).Name[len(".debug_"):]
+                       }
                        sect := addsection(ctxt.loader, ctxt.Arch, &Segdwarf, compressedSegName, 04)
                        sect.Align = 1
                        sect.Length = uint64(len(z.compressed))
-                       newSym := ldr.CreateSymForUpdate(compressedSegName, 0)
+                       sect.Compressed = true
+                       newSym := ldr.MakeSymbolBuilder(compressedSegName)
+                       ldr.SetAttrReachable(s, true)
                        newSym.SetData(z.compressed)
                        newSym.SetSize(int64(len(z.compressed)))
                        ldr.SetSymSect(newSym.Sym(), sect)
index 1bdfb3369c7bbb120a5810ad1254d279c93b0b9e..7f45a8fce5ee8d4707a450f5ee1e2e68a1a259fb 100644 (file)
@@ -1102,6 +1102,9 @@ func elfshbits(linkmode LinkMode, sect *sym.Section) *ElfShdr {
        }
        if strings.HasPrefix(sect.Name, ".debug") || strings.HasPrefix(sect.Name, ".zdebug") {
                sh.Flags = 0
+               if sect.Compressed {
+                       sh.Flags |= uint64(elf.SHF_COMPRESSED)
+               }
        }
 
        if linkmode != LinkExternal {
index f1a37e955e93706e2324d1d476041616fd939c29..a81232b2a4908eb1e4aeceabdc6fb38bfa6f2239 100644 (file)
@@ -1477,7 +1477,7 @@ func (ctxt *Link) hostlink() {
                argv = append(argv, unusedArguments)
        }
 
-       const compressDWARF = "-Wl,--compress-debug-sections=zlib-gnu"
+       const compressDWARF = "-Wl,--compress-debug-sections=zlib"
        if ctxt.compressDWARF && linkerFlagSupported(ctxt.Arch, argv[0], altLinker, compressDWARF) {
                argv = append(argv, compressDWARF)
        }
index 97853b9355f4e908c69436c1d6741b92a5d7d982..c889e71ad64b8baf7cb6a581a7a98ac3f79ca1cd 100644 (file)
@@ -63,4 +63,6 @@ type Section struct {
        Relcount uint32
        Sym      LoaderSym // symbol for the section, if any
        Index    uint16    // each section has a unique index, used internally
+
+       Compressed bool
 }
index 8c84661c5f7de6e5dffba4b06d6a0e5bbb662dac..e93200a11d733ea94a780764c7ca0fb6348169d5 100644 (file)
@@ -1150,11 +1150,37 @@ func (f *File) DWARF() (*dwarf.Data, error) {
                if err != nil && uint64(len(b)) < s.Size {
                        return nil, err
                }
-
+               var (
+                       dlen uint64
+                       dbuf []byte
+               )
                if len(b) >= 12 && string(b[:4]) == "ZLIB" {
-                       dlen := binary.BigEndian.Uint64(b[4:12])
-                       dbuf := make([]byte, dlen)
-                       r, err := zlib.NewReader(bytes.NewBuffer(b[12:]))
+                       dlen = binary.BigEndian.Uint64(b[4:12])
+                       s.compressionOffset = 12
+               }
+               if dlen == 0 && len(b) >= 12 && s.Flags&SHF_COMPRESSED != 0 &&
+                       s.Flags&SHF_ALLOC == 0 &&
+                       f.FileHeader.ByteOrder.Uint32(b[:]) == uint32(COMPRESS_ZLIB) {
+                       s.compressionType = COMPRESS_ZLIB
+                       switch f.FileHeader.Class {
+                       case ELFCLASS32:
+                               // Chdr32.Size offset
+                               dlen = uint64(f.FileHeader.ByteOrder.Uint32(b[4:]))
+                               s.compressionOffset = 12
+                       case ELFCLASS64:
+                               if len(b) < 24 {
+                                       return nil, errors.New("invalid compress header 64")
+                               }
+                               // Chdr64.Size offset
+                               dlen = f.FileHeader.ByteOrder.Uint64(b[8:])
+                               s.compressionOffset = 24
+                       default:
+                               return nil, fmt.Errorf("unsupported compress header:%s", f.FileHeader.Class)
+                       }
+               }
+               if dlen > 0 {
+                       dbuf = make([]byte, dlen)
+                       r, err := zlib.NewReader(bytes.NewBuffer(b[s.compressionOffset:]))
                        if err != nil {
                                return nil, err
                        }