]> Cypherpunks repositories - gostls13.git/commitdiff
cmd/link: improve XCOFF symbol table
authorClément Chigot <clement.chigot@atos.net>
Wed, 20 Feb 2019 14:48:22 +0000 (15:48 +0100)
committerIan Lance Taylor <iant@golang.org>
Wed, 27 Feb 2019 22:49:58 +0000 (22:49 +0000)
This commit improves symbol table for XCOFF format.
It adds symbol alignment, TLS symbols and move the whole symbol table at
the end of the FILE. As relocations in the future external linking will
need symbols' index, we cannot write the symbol table when it's
generated.

Change-Id: I5dcae85b95e538b65f1a128faf56d4e2aa15baf1
Reviewed-on: https://go-review.googlesource.com/c/163998
Run-TryBot: Ian Lance Taylor <iant@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Ian Lance Taylor <iant@golang.org>
src/cmd/link/internal/ld/data.go
src/cmd/link/internal/ld/xcoff.go

index 0bd7d82b544b0e826b7dc6231b622e2d9f51ec77..e72ad40ce95fb4a6825549264cd049944cef571b 100644 (file)
@@ -994,6 +994,7 @@ func symalign(s *sym.Symbol) int32 {
        for int64(align) > s.Size && align > min {
                align >>= 1
        }
+       s.Align = align
        return align
 }
 
index 1561ce8cd0d17eb75e6552f0b31873e1e42a53bf..e565a3588d6e77cf720e93bdf72ab979b2400132 100644 (file)
@@ -9,6 +9,7 @@ import (
        "cmd/internal/objabi"
        "cmd/link/internal/sym"
        "encoding/binary"
+       "math/bits"
        "strings"
 )
 
@@ -155,6 +156,10 @@ const (
        LDSYMSZ_64     = 24
 )
 
+// Type representing all XCOFF symbols.
+type xcoffSym interface {
+}
+
 // Symbol Table Entry
 type XcoffSymEnt64 struct {
        Nvalue  uint64 // Symbol value
@@ -214,9 +219,12 @@ const (
 
 // File Auxiliary Entry
 type XcoffAuxFile64 struct {
-       Xfname   [8]byte // Name or offset inside string table
-       Xftype   uint8   // Source file string type
-       Xauxtype uint8   // Type of auxiliary entry
+       Xzeroes  uint32 // The name is always in the string table
+       Xoffset  uint32 // Offset in the string table
+       X_pad1   [6]byte
+       Xftype   uint8 // Source file string type
+       X_pad2   [2]byte
+       Xauxtype uint8 // Type of auxiliary entry
 }
 
 // Function Auxiliary Entry
@@ -240,6 +248,13 @@ type XcoffAuxCSect64 struct {
        Xauxtype  uint8  // Type of auxiliary entry
 }
 
+// DWARF Auxiliary Entry
+type XcoffAuxDWARF64 struct {
+       Xscnlen  uint64 // Length of this symbol section
+       X_pad    [9]byte
+       Xauxtype uint8 // Type of auxiliary entry
+}
+
 // Auxiliary type
 const (
        _AUX_EXCEPT = 255
@@ -365,6 +380,7 @@ type xcoffFile struct {
        loaderSize      uint64
        symtabOffset    int64                // offset to the start of symbol table
        symbolCount     uint32               // number of symbol table records written
+       symtabSym       []xcoffSym           // XCOFF symbols for the symbol table
        dynLibraries    map[string]int       // Dynamic libraries in .loader section. The integer represents its import file number (- 1)
        loaderSymbols   []*xcoffLoaderSymbol // symbols inside .loader symbol table
        loaderReloc     []*xcoffLoaderReloc  // Reloc that must be made inside loader
@@ -504,8 +520,9 @@ func Xcoffinit(ctxt *Link) {
 // type records C_FILE information needed for genasmsym in XCOFF.
 type xcoffSymSrcFile struct {
        name       string
-       fileSymNb  uint32 // Symbol number of this C_FILE
-       csectSymNb uint64 // Symbol number for the current .csect
+       file       *XcoffSymEnt64   // Symbol of this C_FILE
+       csectAux   *XcoffAuxCSect64 // Symbol for the current .csect
+       csectSymNb uint64           // Symbol number for the current .csect
        csectSize  int64
 }
 
@@ -514,12 +531,30 @@ var (
        currSymSrcFile xcoffSymSrcFile
 )
 
-// writeSymbol writes a symbol or an auxiliary symbol entry on ctxt.out.
-func (f *xcoffFile) writeSymbol(out *OutBuf, byteOrder binary.ByteOrder, sym interface{}) {
-       binary.Write(out, byteOrder, sym)
+// addSymbol writes a symbol or an auxiliary symbol entry on ctxt.out.
+func (f *xcoffFile) addSymbol(sym xcoffSym) {
+       f.symtabSym = append(f.symtabSym, sym)
        f.symbolCount++
 }
 
+// xcoffAlign returns the log base 2 of the symbol's alignment.
+func xcoffAlign(x *sym.Symbol, t SymbolType) uint8 {
+       align := x.Align
+       if align == 0 {
+               if t == TextSym {
+                       align = int32(Funcalign)
+               } else {
+                       align = symalign(x)
+               }
+       }
+       return logBase2(int(align))
+}
+
+// logBase2 returns the log in base 2 of a.
+func logBase2(a int) uint8 {
+       return uint8(bits.Len(uint(a)) - 1)
+}
+
 // Write symbols needed when a new file appared :
 // - a C_FILE with one auxiliary entry for its name
 // - C_DWARF symbols to provide debug information
@@ -537,17 +572,16 @@ func (f *xcoffFile) writeSymbolNewFile(ctxt *Link, name string, firstEntry uint6
                Ntype:   0, // Go isn't inside predefined language.
                Nnumaux: 1,
        }
-       f.writeSymbol(ctxt.Out, ctxt.Arch.ByteOrder, s)
+       f.addSymbol(s)
+       currSymSrcFile.file = s
 
        // Auxiliary entry for file name.
-       ctxt.Out.Write32(0)
-       ctxt.Out.Write32(uint32(f.stringTable.add(name)))
-       ctxt.Out.Write32(0) // 6 bytes empty
-       ctxt.Out.Write16(0)
-       ctxt.Out.Write8(XFT_FN)
-       ctxt.Out.Write16(0) // 2 bytes empty
-       ctxt.Out.Write8(_AUX_FILE)
-       f.symbolCount++
+       auxf := &XcoffAuxFile64{
+               Xoffset:  uint32(f.stringTable.add(name)),
+               Xftype:   XFT_FN,
+               Xauxtype: _AUX_FILE,
+       }
+       f.addSymbol(auxf)
 
        /* Dwarf */
        for _, sect := range Segdwarf.Sections {
@@ -569,7 +603,7 @@ func (f *xcoffFile) writeSymbolNewFile(ctxt *Link, name string, firstEntry uint6
                        Nscnum:  f.getXCOFFscnum(sect),
                        Nnumaux: 1,
                }
-               f.writeSymbol(ctxt.Out, ctxt.Arch.ByteOrder, s)
+               f.addSymbol(s)
 
                // update the DWARF section offset in this file
                if sect.Name != ".debug_abbrev" {
@@ -577,11 +611,12 @@ func (f *xcoffFile) writeSymbolNewFile(ctxt *Link, name string, firstEntry uint6
                }
 
                // Auxiliary dwarf section
-               ctxt.Out.Write64(dwsize) // section length
-               ctxt.Out.Write64(0)      // nreloc
-               ctxt.Out.Write8(0)       // pad
-               ctxt.Out.Write8(_AUX_SECT)
-               f.symbolCount++
+               auxd := &XcoffAuxDWARF64{
+                       Xscnlen:  dwsize,
+                       Xauxtype: _AUX_SECT,
+               }
+
+               f.addSymbol(auxd)
        }
 
        /* .csect */
@@ -592,7 +627,6 @@ func (f *xcoffFile) writeSymbolNewFile(ctxt *Link, name string, firstEntry uint6
        }
 
        currSymSrcFile.csectSymNb = uint64(f.symbolCount)
-       currSymSrcFile.csectSize = 0
 
        // No offset because no name
        s = &XcoffSymEnt64{
@@ -602,15 +636,17 @@ func (f *xcoffFile) writeSymbolNewFile(ctxt *Link, name string, firstEntry uint6
                Ntype:   0, // check visibility ?
                Nnumaux: 1,
        }
-       f.writeSymbol(ctxt.Out, ctxt.Arch.ByteOrder, s)
+       f.addSymbol(s)
 
        aux := &XcoffAuxCSect64{
                Xsmclas:  XMC_PR,
-               Xsmtyp:   XTY_SD | 5<<3, // align = 5
+               Xsmtyp:   XTY_SD | logBase2(Funcalign)<<3,
                Xauxtype: _AUX_CSECT,
        }
-       f.writeSymbol(ctxt.Out, ctxt.Arch.ByteOrder, aux)
+       f.addSymbol(aux)
 
+       currSymSrcFile.csectAux = aux
+       currSymSrcFile.csectSize = 0
 }
 
 // Update values for the previous package.
@@ -618,39 +654,30 @@ func (f *xcoffFile) writeSymbolNewFile(ctxt *Link, name string, firstEntry uint6
 //  - Xsclen of the csect symbol.
 func (f *xcoffFile) updatePreviousFile(ctxt *Link, last bool) {
        // first file
-       if currSymSrcFile.fileSymNb == 0 {
+       if currSymSrcFile.file == nil {
                return
        }
 
-       prevOff := f.symtabOffset + int64(currSymSrcFile.fileSymNb*SYMESZ)
-       currOff := ctxt.Out.Offset()
-
        // Update C_FILE
-       ctxt.Out.SeekSet(prevOff)
+       cfile := currSymSrcFile.file
        if last {
-               ctxt.Out.Write64(0xFFFFFFFFFFFFFFFF)
+               cfile.Nvalue = 0xFFFFFFFFFFFFFFFF
        } else {
-               ctxt.Out.Write64(uint64(f.symbolCount))
+               cfile.Nvalue = uint64(f.symbolCount)
        }
 
        // update csect scnlen in this auxiliary entry
-       prevOff = f.symtabOffset + int64((currSymSrcFile.csectSymNb+1)*SYMESZ)
-       ctxt.Out.SeekSet(prevOff)
-       ctxt.Out.Write32(uint32(currSymSrcFile.csectSize & 0xFFFFFFFF))
-       prevOff += 12
-       ctxt.Out.SeekSet(prevOff)
-       ctxt.Out.Write32(uint32(currSymSrcFile.csectSize >> 32))
-
-       ctxt.Out.SeekSet(currOff)
-
+       aux := currSymSrcFile.csectAux
+       aux.Xscnlenlo = uint32(currSymSrcFile.csectSize & 0xFFFFFFFF)
+       aux.Xscnlenhi = uint32(currSymSrcFile.csectSize >> 32)
 }
 
 // Write symbol representing a .text function.
 // The symbol table is split with C_FILE corresponding to each package
 // and not to each source file as it should be.
-func (f *xcoffFile) writeSymbolFunc(ctxt *Link, x *sym.Symbol) []interface{} {
+func (f *xcoffFile) writeSymbolFunc(ctxt *Link, x *sym.Symbol) []xcoffSym {
        // New XCOFF symbols which will be written.
-       syms := []interface{}{}
+       syms := []xcoffSym{}
 
        // Check if a new file is detected.
        if x.File == "" { // Undefined global symbol
@@ -664,7 +691,6 @@ func (f *xcoffFile) writeSymbolFunc(ctxt *Link, x *sym.Symbol) []interface{} {
                        // update previous file values
                        xfile.updatePreviousFile(ctxt, false)
                        currSymSrcFile.name = x.File
-                       currSymSrcFile.fileSymNb = f.symbolCount
                        f.writeSymbolNewFile(ctxt, x.File, uint64(x.Value), xfile.getXCOFFscnum(x.Sect))
                }
        }
@@ -703,6 +729,8 @@ func (f *xcoffFile) writeSymbolFunc(ctxt *Link, x *sym.Symbol) []interface{} {
                Xsmtyp:    XTY_LD, // label definition (based on C)
                Xauxtype:  _AUX_CSECT,
        }
+       a4.Xsmtyp |= uint8(xcoffAlign(x, TextSym) << 3)
+
        syms = append(syms, a4)
        return syms
 }
@@ -712,7 +740,7 @@ func putaixsym(ctxt *Link, x *sym.Symbol, str string, t SymbolType, addr int64,
 
        // All XCOFF symbols generated by this GO symbols
        // Can be a symbol entry or a auxiliary entry
-       syms := []interface{}{}
+       syms := []xcoffSym{}
 
        switch t {
        default:
@@ -745,6 +773,7 @@ func putaixsym(ctxt *Link, x *sym.Symbol, str string, t SymbolType, addr int64,
                                Xsmclas:   XMC_PR,
                                Xsmtyp:    XTY_SD,
                        }
+                       a4.Xsmtyp |= uint8(xcoffAlign(x, TextSym) << 3)
                        syms = append(syms, a4)
 
                }
@@ -785,6 +814,8 @@ func putaixsym(ctxt *Link, x *sym.Symbol, str string, t SymbolType, addr int64,
                // Read only data
                if x.Type >= sym.STYPE && x.Type <= sym.SPCLNTAB {
                        a4.Xsmclas = XMC_RO
+               } else if x.Name == "TOC" {
+                       a4.Xsmclas = XMC_TC0
                } else {
                        a4.Xsmclas = XMC_RW
                }
@@ -794,6 +825,8 @@ func putaixsym(ctxt *Link, x *sym.Symbol, str string, t SymbolType, addr int64,
                        a4.Xsmtyp |= XTY_CM
                }
 
+               a4.Xsmtyp |= uint8(xcoffAlign(x, t) << 3)
+
                syms = append(syms, a4)
 
        case UndefinedSym:
@@ -820,24 +853,43 @@ func putaixsym(ctxt *Link, x *sym.Symbol, str string, t SymbolType, addr int64,
                        a4.Xsmclas = XMC_RW
                }
 
+               syms = append(syms, a4)
+
+       case TLSSym:
+               s := &XcoffSymEnt64{
+                       Nsclass: C_EXT,
+                       Noffset: uint32(xfile.stringTable.add(str)),
+                       Nscnum:  xfile.getXCOFFscnum(x.Sect),
+                       Nvalue:  uint64(x.Value),
+                       Nnumaux: 1,
+               }
+
+               x.Dynid = int32(xfile.symbolCount)
+               syms = append(syms, s)
+
+               size := uint64(x.Size)
+               a4 := &XcoffAuxCSect64{
+                       Xauxtype:  _AUX_CSECT,
+                       Xsmclas:   XMC_UL,
+                       Xsmtyp:    XTY_CM,
+                       Xscnlenlo: uint32(size & 0xFFFFFFFF),
+                       Xscnlenhi: uint32(size >> 32),
+               }
+
                syms = append(syms, a4)
        }
 
        for _, s := range syms {
-               xfile.writeSymbol(ctxt.Out, ctxt.Arch.ByteOrder, s)
+               xfile.addSymbol(s)
        }
 }
 
-// Generate XCOFF Symbol table and XCOFF String table
+// Generate XCOFF Symbol table.
+// It will be written in out file in Asmbxcoff, because it must be
+// at the very end, especially after relocation sections which needs symbols' index.
 func (f *xcoffFile) asmaixsym(ctxt *Link) {
-       // write symbol table
        genasmsym(ctxt, putaixsym)
-
-       // update last file Svalue
        xfile.updatePreviousFile(ctxt, true)
-
-       // write string table
-       xfile.stringTable.write(ctxt.Out)
 }
 
 func (f *xcoffFile) genDynSym(ctxt *Link) {
@@ -1251,8 +1303,7 @@ func (f *xcoffFile) writeFileHeader(ctxt *Link) {
                f.xahdr.Otoc = uint64(toc.Value)
                f.xahdr.Osntoc = f.getXCOFFscnum(toc.Sect)
 
-               // Based on dump -o
-               f.xahdr.Oalgntext = 0x5
+               f.xahdr.Oalgntext = int16(logBase2(int(Funcalign)))
                f.xahdr.Oalgndata = 0x5
 
                binary.Write(ctxt.Out, binary.BigEndian, &f.xfhdr)
@@ -1310,11 +1361,16 @@ func Asmbxcoff(ctxt *Link, fileoff int64) {
                // TODO: Relocation
        }
 
-       // Write symbol table
-       symo := Rnd(ctxt.Out.Offset(), int64(*FlagRound))
-       xfile.symtabOffset = symo
-       ctxt.Out.SeekSet(int64(symo))
+       // Write symtab
        xfile.asmaixsym(ctxt)
+       xfile.symtabOffset = ctxt.Out.Offset()
+       for _, s := range xfile.symtabSym {
+               binary.Write(ctxt.Out, ctxt.Arch.ByteOrder, s)
+       }
+       // write string table
+       xfile.stringTable.write(ctxt.Out)
+
+       ctxt.Out.Flush()
 
        // write headers
        xcoffwrite(ctxt)