]> Cypherpunks repositories - gostls13.git/commitdiff
cmd/link: move type name mangling after deadcode elimination
authorAlessandro Arzilli <alessandro.arzilli@gmail.com>
Thu, 23 Aug 2018 12:01:59 +0000 (14:01 +0200)
committerHeschi Kreinick <heschi@google.com>
Tue, 28 Aug 2018 20:56:26 +0000 (20:56 +0000)
Moves type name mangling after deadcode elimination. The motivation for
doing this is to create a space between deadcode elimination and type name
mangling where DWARF generation for types and variables can exist, to fix
issue #23733.

Change-Id: I9db8ecc0f4efe3df6c1e4025f02642fd452f9a39
Reviewed-on: https://go-review.googlesource.com/111236
Reviewed-by: Heschi Kreinick <heschi@google.com>
Reviewed-by: Cherry Zhang <cherryyz@google.com>
Run-TryBot: Heschi Kreinick <heschi@google.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>

src/cmd/link/internal/ld/lib.go
src/cmd/link/internal/ld/main.go
src/cmd/link/internal/sym/symbols.go

index bfb9d9b772388a3189665e05f30854fb4c7a83e3..1b6d5d17047129b4712d826e9946c54179c5ec77 100644 (file)
@@ -577,27 +577,6 @@ func (ctxt *Link) loadlib() {
                }
        }
 
-       // If type. symbols are visible in the symbol table, rename them
-       // using a SHA-1 prefix. This reduces binary size (the full
-       // string of a type symbol can be multiple kilobytes) and removes
-       // characters that upset external linkers.
-       //
-       // Keep the type.. prefix, which parts of the linker (like the
-       // DWARF generator) know means the symbol is not decodable.
-       //
-       // Leave type.runtime. symbols alone, because other parts of
-       // the linker manipulates them, and also symbols whose names
-       // would not be shortened by this process.
-       if typeSymbolMangling(ctxt) {
-               *FlagW = true // disable DWARF generation
-               for _, s := range ctxt.Syms.Allsym {
-                       newName := typeSymbolMangle(s.Name)
-                       if newName != s.Name {
-                               ctxt.Syms.Rename(s.Name, newName, int(s.Version))
-                       }
-               }
-       }
-
        // If package versioning is required, generate a hash of the
        // packages used in the link.
        if ctxt.BuildMode == BuildModeShared || ctxt.BuildMode == BuildModePlugin || ctxt.CanUsePlugins() {
@@ -657,23 +636,39 @@ func (ctxt *Link) loadlib() {
        }
 }
 
-// typeSymbolMangling reports whether the linker should shorten the
-// names of symbols that represent Go types.
+// mangleTypeSym shortens the names of symbols that represent Go types
+// if they are visible in the symbol table.
 //
 // As the names of these symbols are derived from the string of
 // the type, they can run to many kilobytes long. So we shorten
 // them using a SHA-1 when the name appears in the final binary.
+// This also removes characters that upset external linkers.
 //
 // These are the symbols that begin with the prefix 'type.' and
 // contain run-time type information used by the runtime and reflect
 // packages. All Go binaries contain these symbols, but only only
 // those programs loaded dynamically in multiple parts need these
 // symbols to have entries in the symbol table.
-func typeSymbolMangling(ctxt *Link) bool {
-       return ctxt.BuildMode == BuildModeShared || ctxt.linkShared || ctxt.BuildMode == BuildModePlugin || ctxt.Syms.ROLookup("plugin.Open", 0) != nil
+func (ctxt *Link) mangleTypeSym() {
+       if ctxt.BuildMode != BuildModeShared && !ctxt.linkShared && ctxt.BuildMode != BuildModePlugin && ctxt.Syms.ROLookup("plugin.Open", 0) == nil {
+               return
+       }
+
+       *FlagW = true // disable DWARF generation
+       for _, s := range ctxt.Syms.Allsym {
+               newName := typeSymbolMangle(s.Name)
+               if newName != s.Name {
+                       ctxt.Syms.Rename(s.Name, newName, int(s.Version), ctxt.Reachparent)
+               }
+       }
 }
 
 // typeSymbolMangle mangles the given symbol name into something shorter.
+//
+// Keep the type.. prefix, which parts of the linker (like the
+// DWARF generator) know means the symbol is not decodable.
+// Leave type.runtime. symbols alone, because other parts of
+// the linker manipulates them.
 func typeSymbolMangle(name string) string {
        if !strings.HasPrefix(name, "type.") {
                return name
index 23462f1154b7ea766f22b4d070d9cbf31d8d05b6..0c5ac470438adbdbbd0fe4135fc9d73183f2aad1 100644 (file)
@@ -211,6 +211,7 @@ func Main(arch *sys.Arch, theArch Arch) {
        if objabi.Fieldtrack_enabled != 0 {
                fieldtrack(ctxt)
        }
+       ctxt.mangleTypeSym()
        ctxt.callgraph()
 
        ctxt.doelf()
index 98a5ae67b8bd3a5b2229e7669e551d570bcbcb51..f9405db185373b5d69ed3de029d86e01879641a1 100644 (file)
@@ -95,7 +95,7 @@ func (syms *Symbols) IncVersion() int {
 }
 
 // Rename renames a symbol.
-func (syms *Symbols) Rename(old, new string, v int) {
+func (syms *Symbols) Rename(old, new string, v int, reachparent map[*Symbol]*Symbol) {
        s := syms.hash[v][old]
        s.Name = new
        if s.Extname == old {
@@ -108,8 +108,16 @@ func (syms *Symbols) Rename(old, new string, v int) {
                syms.hash[v][new] = s
        } else {
                if s.Type == 0 {
+                       dup.Attr |= s.Attr
+                       if s.Attr.Reachable() && reachparent != nil {
+                               reachparent[dup] = reachparent[s]
+                       }
                        *s = *dup
                } else if dup.Type == 0 {
+                       s.Attr |= dup.Attr
+                       if dup.Attr.Reachable() && reachparent != nil {
+                               reachparent[s] = reachparent[dup]
+                       }
                        *dup = *s
                        syms.hash[v][new] = s
                }