]> Cypherpunks repositories - gostls13.git/commitdiff
cmd/link: add AIX operating system
authorClément Chigot <clement.chigot@atos.net>
Fri, 28 Sep 2018 15:02:16 +0000 (17:02 +0200)
committerIan Lance Taylor <iant@golang.org>
Wed, 24 Oct 2018 14:01:40 +0000 (14:01 +0000)
This commit adds AIX operating system to cmd/link package for ppc64
architecture.

Updates: #25893

Change-Id: I349e0a2658c31919b72117b62c4c9935c9af07c0
Reviewed-on: https://go-review.googlesource.com/c/138730
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/go.go
src/cmd/link/internal/ld/lib.go
src/cmd/link/internal/ld/main.go
src/cmd/link/internal/ld/sym.go
src/cmd/link/internal/ld/xcoff.go [new file with mode: 0644]
src/cmd/link/internal/ppc64/asm.go
src/cmd/link/internal/ppc64/obj.go

index 3cc9e294d29fe3de5b2e5706411e6e6a55f97b30..f424f1d17b279a5a601dad2cd9a08b4eaa3b1d23 100644 (file)
@@ -314,6 +314,18 @@ func relocsym(ctxt *Link, s *sym.Symbol) {
 
                                break
                        }
+                       // On AIX, if a relocated symbol is in .data, a second relocation
+                       // must be done by the loader, as the section .data will be moved.
+                       // The "default" symbol address is still needed by the loader so
+                       // the current relocation can't be skipped.
+                       // runtime.algarray is different because it will end up in .rodata section
+                       if ctxt.HeadType == objabi.Haix && r.Sym.Sect.Seg == &Segdata && r.Sym.Name != "runtime.algarray" {
+                               // It's not possible to make a loader relocation to a DWARF section.
+                               // FIXME
+                               if s.Sect.Seg != &Segdwarf {
+                                       xcoffaddloaderreloc(ctxt, s, r)
+                               }
+                       }
 
                        o = Symaddr(r.Sym) + r.Add
 
@@ -606,6 +618,7 @@ func dynrelocsym(ctxt *Link, s *sym.Symbol) {
                        thearch.Adddynrel(ctxt, s, r)
                        continue
                }
+
                if r.Sym != nil && r.Sym.Type == sym.SDYNIMPORT || r.Type >= 256 {
                        if r.Sym != nil && !r.Sym.Attr.Reachable() {
                                Errorf(s, "dynamic relocation to unreachable symbol %s", r.Sym.Name)
@@ -1329,6 +1342,14 @@ func (ctxt *Link) dodata() {
                gc.AddSym(s)
                datsize += s.Size
        }
+       // On AIX, TOC entries must be the last of .data
+       for _, s := range data[sym.SXCOFFTOC] {
+               s.Sect = sect
+               s.Type = sym.SDATA
+               datsize = aligndatsize(datsize, s)
+               s.Value = int64(uint64(datsize) - sect.Vaddr)
+               datsize += s.Size
+       }
        checkdatsize(ctxt, datsize, sym.SDATA)
        sect.Length = uint64(datsize) - sect.Vaddr
        gc.End(int64(sect.Length))
@@ -1688,6 +1709,10 @@ func (ctxt *Link) dodata() {
        }
        for _, sect := range Segdata.Sections {
                sect.Extnum = int16(n)
+               if ctxt.HeadType == objabi.Haix && (sect.Name == ".noptrdata" || sect.Name == ".bss") {
+                       // On AIX, "noptr" sections are merged with their "ptr" section
+                       continue
+               }
                n++
        }
        for _, sect := range Segdwarf.Sections {
index f2dd799922e50df3e5082b6f5dd1ec7bfaddfc92..d6c6b53a44c524cc9f45ee2510eac7c4233790e5 100644 (file)
@@ -163,6 +163,10 @@ func loadcgo(ctxt *Link, file string, pkg string, p string) {
                                }
                                havedynamic = 1
                        }
+                       if ctxt.HeadType == objabi.Haix {
+                               xcoffadddynimpsym(ctxt, s)
+                       }
+
                        continue
 
                case "cgo_import_static":
@@ -317,7 +321,8 @@ func fieldtrack(ctxt *Link) {
 }
 
 func (ctxt *Link) addexport() {
-       if ctxt.HeadType == objabi.Hdarwin {
+       // TODO(aix)
+       if ctxt.HeadType == objabi.Hdarwin || ctxt.HeadType == objabi.Haix {
                return
        }
 
index 2284c347dc59f9a71530aeb60477f59ed3f204e6..0f5617246be730302d2d9e72f3354a03bf105a47 100644 (file)
@@ -39,6 +39,7 @@ import (
        "cmd/link/internal/loadelf"
        "cmd/link/internal/loadmacho"
        "cmd/link/internal/loadpe"
+       "cmd/link/internal/loadxcoff"
        "cmd/link/internal/objfile"
        "cmd/link/internal/sym"
        "crypto/sha1"
@@ -1517,6 +1518,18 @@ func ldobj(ctxt *Link, f *bio.Reader, lib *sym.Library, length int64, pn string,
                return ldhostobj(ldpe, ctxt.HeadType, f, pkg, length, pn, file)
        }
 
+       if c1 == 0x01 && (c2 == 0xD7 || c2 == 0xF7) {
+               ldxcoff := func(ctxt *Link, f *bio.Reader, pkg string, length int64, pn string) {
+                       textp, err := loadxcoff.Load(ctxt.Arch, ctxt.Syms, f, pkg, length, pn)
+                       if err != nil {
+                               Errorf(nil, "%v", err)
+                               return
+                       }
+                       ctxt.Textp = append(ctxt.Textp, textp...)
+               }
+               return ldhostobj(ldxcoff, ctxt.HeadType, f, pkg, length, pn, file)
+       }
+
        /* check the header */
        line, err := f.ReadString('\n')
        if err != nil {
@@ -2243,7 +2256,7 @@ func Entryvalue(ctxt *Link) int64 {
        if s.Type == 0 {
                return *FlagTextAddr
        }
-       if s.Type != sym.STEXT {
+       if ctxt.HeadType != objabi.Haix && s.Type != sym.STEXT {
                Errorf(s, "entry not text")
        }
        return s.Value
index 2c5152f2e3d63cb4fa0916374b3e4ba9af40c280..b87ee8094fb6a15be9a362f79e6816733d8dcbdd 100644 (file)
@@ -224,6 +224,10 @@ func Main(arch *sys.Arch, theArch Arch) {
                ctxt.dope()
                ctxt.windynrelocsyms()
        }
+       if ctxt.HeadType == objabi.Haix {
+               ctxt.doxcoff()
+       }
+
        ctxt.addexport()
        thearch.Gentext(ctxt) // trampolines, call stubs, etc.
        ctxt.textbuildid()
index 3aa90c17dc8a1a6fb3f74a4f78a221f76d5cef57..a487b5e5f6ca1408a16e470ab30b5c45d654ea4c 100644 (file)
@@ -66,7 +66,7 @@ func (ctxt *Link) computeTLSOffset() {
        default:
                log.Fatalf("unknown thread-local storage offset for %v", ctxt.HeadType)
 
-       case objabi.Hplan9, objabi.Hwindows, objabi.Hjs:
+       case objabi.Hplan9, objabi.Hwindows, objabi.Hjs, objabi.Haix:
                break
 
                /*
diff --git a/src/cmd/link/internal/ld/xcoff.go b/src/cmd/link/internal/ld/xcoff.go
new file mode 100644 (file)
index 0000000..f06b498
--- /dev/null
@@ -0,0 +1,1232 @@
+// Copyright 2018 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package ld
+
+import (
+       "bytes"
+       "cmd/internal/objabi"
+       "cmd/link/internal/sym"
+       "encoding/binary"
+       "strings"
+)
+
+// This file handles all algorithms related to XCOFF files generation.
+// Most of them are adaptations of the ones in  cmd/link/internal/pe.go
+// as PE and XCOFF are based on COFF files.
+// XCOFF files generated are 64 bits.
+
+// Total amount of space to reserve at the start of the file
+// for FileHeader, Auxiliary Header, and Section Headers.
+// May waste some.
+// Based on 24(fhdr) + 120(ahdr) + 23(max sections number) * 72(scnhdr)
+const (
+       XCOFFHDRRESERVE = FILHSZ_64 + AOUTHSZ_EXEC64 + SCNHSZ_64*23
+)
+
+const (
+       XCOFFSECTALIGN int64 = 32          // base on dump -o
+       XCOFFBASE            = 0x100000000 // Address on 64 bits must start at this value.
+)
+
+// File Header
+type XcoffFileHdr64 struct {
+       Fmagic   uint16 // Target machine
+       Fnscns   uint16 // Number of sections
+       Ftimedat int32  // Time and date of file creation
+       Fsymptr  uint64 // Byte offset to symbol table start
+       Fopthdr  uint16 // Number of bytes in optional header
+       Fflags   uint16 // Flags
+       Fnsyms   int32  // Number of entries in symbol table
+}
+
+const (
+       U64_TOCMAGIC = 0767 // AIX 64-bit XCOFF
+)
+
+// Flags that describe the type of the object file.
+const (
+       F_RELFLG    = 0x0001
+       F_EXEC      = 0x0002
+       F_LNNO      = 0x0004
+       F_FDPR_PROF = 0x0010
+       F_FDPR_OPTI = 0x0020
+       F_DSA       = 0x0040
+       F_VARPG     = 0x0100
+       F_DYNLOAD   = 0x1000
+       F_SHROBJ    = 0x2000
+       F_LOADONLY  = 0x4000
+)
+
+// Auxiliary Header
+type XcoffAoutHdr64 struct {
+       Omagic      int16    // Flags - Ignored If Vstamp Is 1
+       Ovstamp     int16    // Version
+       Odebugger   uint32   // Reserved For Debugger
+       Otextstart  uint64   // Virtual Address Of Text
+       Odatastart  uint64   // Virtual Address Of Data
+       Otoc        uint64   // Toc Address
+       Osnentry    int16    // Section Number For Entry Point
+       Osntext     int16    // Section Number For Text
+       Osndata     int16    // Section Number For Data
+       Osntoc      int16    // Section Number For Toc
+       Osnloader   int16    // Section Number For Loader
+       Osnbss      int16    // Section Number For Bss
+       Oalgntext   int16    // Max Text Alignment
+       Oalgndata   int16    // Max Data Alignment
+       Omodtype    [2]byte  // Module Type Field
+       Ocpuflag    uint8    // Bit Flags - Cputypes Of Objects
+       Ocputype    uint8    // Reserved for CPU type
+       Otextpsize  uint8    // Requested text page size
+       Odatapsize  uint8    // Requested data page size
+       Ostackpsize uint8    // Requested stack page size
+       Oflags      uint8    // Flags And TLS Alignment
+       Otsize      uint64   // Text Size In Bytes
+       Odsize      uint64   // Data Size In Bytes
+       Obsize      uint64   // Bss Size In Bytes
+       Oentry      uint64   // Entry Point Address
+       Omaxstack   uint64   // Max Stack Size Allowed
+       Omaxdata    uint64   // Max Data Size Allowed
+       Osntdata    int16    // Section Number For Tdata Section
+       Osntbss     int16    // Section Number For Tbss Section
+       Ox64flags   uint16   // Additional Flags For 64-Bit Objects
+       Oresv3a     int16    // Reserved
+       Oresv3      [2]int32 // Reserved
+
+}
+
+// Section Header
+type XcoffScnHdr64 struct {
+       Sname    [8]byte // Section Name
+       Spaddr   uint64  // Physical Address
+       Svaddr   uint64  // Virtual Address
+       Ssize    uint64  // Section Size
+       Sscnptr  uint64  // File Offset To Raw Data
+       Srelptr  uint64  // File Offset To Relocation
+       Slnnoptr uint64  // File Offset To Line Numbers
+       Snreloc  uint32  // Number Of Relocation Entries
+       Snlnno   uint32  // Number Of Line Number Entries
+       Sflags   uint32  // flags
+}
+
+// Flags defining the section type.
+const (
+       STYP_DWARF  = 0x0010
+       STYP_TEXT   = 0x0020
+       STYP_DATA   = 0x0040
+       STYP_BSS    = 0x0080
+       STYP_EXCEPT = 0x0100
+       STYP_INFO   = 0x0200
+       STYP_TDATA  = 0x0400
+       STYP_TBSS   = 0x0800
+       STYP_LOADER = 0x1000
+       STYP_DEBUG  = 0x2000
+       STYP_TYPCHK = 0x4000
+       STYP_OVRFLO = 0x8000
+)
+const (
+       SSUBTYP_DWINFO  = 0x10000 // DWARF info section
+       SSUBTYP_DWLINE  = 0x20000 // DWARF line-number section
+       SSUBTYP_DWPBNMS = 0x30000 // DWARF public names section
+       SSUBTYP_DWPBTYP = 0x40000 // DWARF public types section
+       SSUBTYP_DWARNGE = 0x50000 // DWARF aranges section
+       SSUBTYP_DWABREV = 0x60000 // DWARF abbreviation section
+       SSUBTYP_DWSTR   = 0x70000 // DWARF strings section
+       SSUBTYP_DWRNGES = 0x80000 // DWARF ranges section
+       SSUBTYP_DWLOC   = 0x90000 // DWARF location lists section
+       SSUBTYP_DWFRAME = 0xA0000 // DWARF frames section
+       SSUBTYP_DWMAC   = 0xB0000 // DWARF macros section
+)
+
+// Headers size
+const (
+       FILHSZ_32      = 20
+       FILHSZ_64      = 24
+       AOUTHSZ_EXEC32 = 72
+       AOUTHSZ_EXEC64 = 120
+       SCNHSZ_32      = 40
+       SCNHSZ_64      = 72
+       LDHDRSZ_32     = 32
+       LDHDRSZ_64     = 56
+       LDSYMSZ_64     = 24
+)
+
+// Symbol Table Entry
+type XcoffSymEnt64 struct {
+       Nvalue  uint64 // Symbol value
+       Noffset uint32 // Offset of the name in string table or .debug section
+       Nscnum  int16  // Section number of symbol
+       Ntype   uint16 // Basic and derived type specification
+       Nsclass uint8  // Storage class of symbol
+       Nnumaux int8   // Number of auxiliary entries
+}
+
+const SYMESZ = 18
+
+const (
+       // Nscnum
+       N_DEBUG = -2
+       N_ABS   = -1
+       N_UNDEF = 0
+
+       //Ntype
+       SYM_V_INTERNAL  = 0x1000
+       SYM_V_HIDDEN    = 0x2000
+       SYM_V_PROTECTED = 0x3000
+       SYM_V_EXPORTED  = 0x4000
+       SYM_TYPE_FUNC   = 0x0020 // is function
+)
+
+// Storage Class.
+const (
+       C_NULL    = 0   // Symbol table entry marked for deletion
+       C_EXT     = 2   // External symbol
+       C_STAT    = 3   // Static symbol
+       C_BLOCK   = 100 // Beginning or end of inner block
+       C_FCN     = 101 // Beginning or end of function
+       C_FILE    = 103 // Source file name and compiler information
+       C_HIDEXT  = 107 // Unnamed external symbol
+       C_BINCL   = 108 // Beginning of include file
+       C_EINCL   = 109 // End of include file
+       C_WEAKEXT = 111 // Weak external symbol
+       C_DWARF   = 112 // DWARF symbol
+       C_GSYM    = 128 // Global variable
+       C_LSYM    = 129 // Automatic variable allocated on stack
+       C_PSYM    = 130 // Argument to subroutine allocated on stack
+       C_RSYM    = 131 // Register variable
+       C_RPSYM   = 132 // Argument to function or procedure stored in register
+       C_STSYM   = 133 // Statically allocated symbol
+       C_BCOMM   = 135 // Beginning of common block
+       C_ECOML   = 136 // Local member of common block
+       C_ECOMM   = 137 // End of common block
+       C_DECL    = 140 // Declaration of object
+       C_ENTRY   = 141 // Alternate entry
+       C_FUN     = 142 // Function or procedure
+       C_BSTAT   = 143 // Beginning of static block
+       C_ESTAT   = 144 // End of static block
+       C_GTLS    = 145 // Global thread-local variable
+       C_STTLS   = 146 // Static thread-local variable
+)
+
+// 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
+}
+
+// Function Auxiliary Entry
+type XcoffAuxFcn64 struct {
+       Xlnnoptr uint64 // File pointer to line number
+       Xfsize   uint32 // Size of function in bytes
+       Xendndx  uint32 // Symbol table index of next entry
+       Xpad     uint8  // Unused
+       Xauxtype uint8  // Type of auxiliary entry
+}
+
+// csect Auxiliary Entry.
+type XcoffAuxCSect64 struct {
+       Xscnlenlo uint32 // Lower 4 bytes of length or symbol table index
+       Xparmhash uint32 // Offset of parameter type-check string
+       Xsnhash   uint16 // .typchk section number
+       Xsmtyp    uint8  // Symbol alignment and type
+       Xsmclas   uint8  // Storage-mapping class
+       Xscnlenhi uint32 // Upper 4 bytes of length or symbol table index
+       Xpad      uint8  // Unused
+       Xauxtype  uint8  // Type of auxiliary entry
+}
+
+// Auxiliary type
+const (
+       _AUX_EXCEPT = 255
+       _AUX_FCN    = 254
+       _AUX_SYM    = 253
+       _AUX_FILE   = 252
+       _AUX_CSECT  = 251
+       _AUX_SECT   = 250
+)
+
+// Xftype field
+const (
+       XFT_FN = 0   // Source File Name
+       XFT_CT = 1   // Compile Time Stamp
+       XFT_CV = 2   // Compiler Version Number
+       XFT_CD = 128 // Compiler Defined Information/
+
+)
+
+// Symbol type field.
+const (
+       XTY_ER  = 0    // External reference
+       XTY_SD  = 1    // Section definition
+       XTY_LD  = 2    // Label definition
+       XTY_CM  = 3    // Common csect definition
+       XTY_WK  = 0x8  // Weak symbol
+       XTY_EXP = 0x10 // Exported symbol
+       XTY_ENT = 0x20 // Entry point symbol
+       XTY_IMP = 0x40 // Imported symbol
+)
+
+// Storage-mapping class.
+const (
+       XMC_PR     = 0  // Program code
+       XMC_RO     = 1  // Read-only constant
+       XMC_DB     = 2  // Debug dictionary table
+       XMC_TC     = 3  // TOC entry
+       XMC_UA     = 4  // Unclassified
+       XMC_RW     = 5  // Read/Write data
+       XMC_GL     = 6  // Global linkage
+       XMC_XO     = 7  // Extended operation
+       XMC_SV     = 8  // 32-bit supervisor call descriptor
+       XMC_BS     = 9  // BSS class
+       XMC_DS     = 10 // Function descriptor
+       XMC_UC     = 11 // Unnamed FORTRAN common
+       XMC_TC0    = 15 // TOC anchor
+       XMC_TD     = 16 // Scalar data entry in the TOC
+       XMC_SV64   = 17 // 64-bit supervisor call descriptor
+       XMC_SV3264 = 18 // Supervisor call descriptor for both 32-bit and 64-bit
+       XMC_TL     = 20 // Read/Write thread-local data
+       XMC_UL     = 21 // Read/Write thread-local data (.tbss)
+       XMC_TE     = 22 // TOC entry
+)
+
+// Loader Header
+type XcoffLdHdr64 struct {
+       Lversion int32  // Loader section version number
+       Lnsyms   int32  // Number of symbol table entries
+       Lnreloc  int32  // Number of relocation table entries
+       Listlen  uint32 // Length of import file ID string table
+       Lnimpid  int32  // Number of import file IDs
+       Lstlen   uint32 // Length of string table
+       Limpoff  uint64 // Offset to start of import file IDs
+       Lstoff   uint64 // Offset to start of string table
+       Lsymoff  uint64 // Offset to start of symbol table
+       Lrldoff  uint64 // Offset to start of relocation entries
+}
+
+// Loader Symbol
+type XcoffLdSym64 struct {
+       Lvalue  uint64 // Address field
+       Loffset uint32 // Byte offset into string table of symbol name
+       Lscnum  int16  // Section number containing symbol
+       Lsmtype int8   // Symbol type, export, import flags
+       Lsmclas int8   // Symbol storage class
+       Lifile  int32  // Import file ID; ordinal of import file IDs
+       Lparm   uint32 // Parameter type-check field
+}
+
+type XcoffLdImportFile64 struct {
+       Limpidpath string
+       Limpidbase string
+       Limpidmem  string
+}
+
+type XcoffLdRel64 struct {
+       Lvaddr  uint64 // Address Field
+       Lrtype  uint16 // Relocation Size and Type
+       Lrsecnm int16  // Section Number being relocated
+       Lsymndx int32  // Loader-Section symbol table index
+}
+
+const (
+       XCOFF_R_POS = 0x00 // A(sym) Positive Relocation
+)
+
+type XcoffLdStr64 struct {
+       size uint16
+       name string
+}
+
+// xcoffFile is used to build XCOFF file.
+type xcoffFile struct {
+       xfhdr        XcoffFileHdr64
+       xahdr        XcoffAoutHdr64
+       sections     []*XcoffScnHdr64
+       stringTable  xcoffStringTable
+       textSect     *XcoffScnHdr64
+       dataSect     *XcoffScnHdr64
+       bssSect      *XcoffScnHdr64
+       loaderSect   *XcoffScnHdr64
+       symtabOffset int64           // offset to the start of symbol table
+       symbolCount  uint32          // number of symbol table records written
+       dynLibraries map[string]int  // Dynamic libraries in .loader section. The integer represents its import file number (- 1)
+       dynSymbols   []*sym.Symbol   // Dynamic symbols in .loader section
+       loaderReloc  []*XcoffLdRel64 // Reloc that must be made inside loader
+}
+
+// Those values will latter be computed in XcoffInit
+var (
+       XCOFFFILEHDR int
+       XCOFFSECTHDR int
+)
+
+// Var used by XCOFF Generation algorithms
+var (
+       xfile      xcoffFile
+       loaderOff  uint64
+       loaderSize uint64
+)
+
+// xcoffStringTable is a XCOFF string table.
+type xcoffStringTable struct {
+       strings    []string
+       stringsLen int
+}
+
+// size returns size of string table t.
+func (t *xcoffStringTable) size() int {
+       // string table starts with 4-byte length at the beginning
+       return t.stringsLen + 4
+}
+
+// add adds string str to string table t.
+func (t *xcoffStringTable) add(str string) int {
+       off := t.size()
+       t.strings = append(t.strings, str)
+       t.stringsLen += len(str) + 1 // each string will have 0 appended to it
+       return off
+}
+
+// write writes string table t into the output file.
+func (t *xcoffStringTable) write(out *OutBuf) {
+       out.Write32(uint32(t.size()))
+       for _, s := range t.strings {
+               out.WriteString(s)
+               out.Write8(0)
+       }
+}
+
+// write writes XCOFF section sect into the output file.
+func (sect *XcoffScnHdr64) write(ctxt *Link) {
+       binary.Write(ctxt.Out, binary.BigEndian, sect)
+       ctxt.Out.Write32(0) // Add 4 empty bytes at the end to match alignment
+}
+
+// addSection adds section to the XCOFF file f.
+func (f *xcoffFile) addSection(s *sym.Section) *XcoffScnHdr64 {
+       sect := &XcoffScnHdr64{
+               Spaddr:  s.Vaddr,
+               Svaddr:  s.Vaddr,
+               Ssize:   s.Length,
+               Sscnptr: s.Seg.Fileoff + s.Vaddr - s.Seg.Vaddr,
+       }
+       copy(sect.Sname[:], s.Name) // copy string to [8]byte ( pb if len(name) > 8 )
+       f.sections = append(f.sections, sect)
+       return sect
+}
+
+// addLoaderSection adds the loader section to the XCOFF file f.
+func (f *xcoffFile) addLoaderSection(size uint64, off uint64) *XcoffScnHdr64 {
+       sect := &XcoffScnHdr64{
+               Ssize:   size,
+               Sscnptr: off,
+               Sflags:  STYP_LOADER,
+       }
+       copy(sect.Sname[:], ".loader") // copy string to [8]byte ( pb if len(name) > 8
+       f.xahdr.Osnloader = int16(len(f.sections) + 1)
+       f.sections = append(f.sections, sect)
+       f.loaderSect = sect
+       return sect
+}
+
+// addDwarfSection adds a dwarf section to the XCOFF file f.
+// This function is similar to addSection, but Dwarf section names
+// must be modified to conventional names and they are various subtypes.
+func (f *xcoffFile) addDwarfSection(s *sym.Section) *XcoffScnHdr64 {
+       sect := &XcoffScnHdr64{
+               Ssize:   s.Length,
+               Sscnptr: s.Seg.Fileoff + s.Vaddr - s.Seg.Vaddr,
+               Sflags:  STYP_DWARF,
+       }
+       newName, subtype := xcoffGetDwarfSubtype(s.Name)
+       copy(sect.Sname[:], newName)
+       sect.Sflags |= subtype
+       f.sections = append(f.sections, sect)
+       return sect
+}
+
+// xcoffGetDwarfSubtype returns the XCOFF name of the DWARF section str
+// and its subtype constant.
+func xcoffGetDwarfSubtype(str string) (string, uint32) {
+       switch str {
+       default:
+               Exitf("unknown DWARF section name for XCOFF: %s", str)
+       case ".debug_abbrev":
+               return ".dwabrev", SSUBTYP_DWABREV
+       case ".debug_info":
+               return ".dwinfo", SSUBTYP_DWINFO
+       case ".debug_frame":
+               return ".dwframe", SSUBTYP_DWFRAME
+       case ".debug_line":
+               return ".dwline", SSUBTYP_DWLINE
+       case ".debug_loc":
+               return ".dwloc", SSUBTYP_DWLOC
+       case ".debug_pubnames":
+               return ".dwpbnms", SSUBTYP_DWPBNMS
+       case ".debug_pubtypes":
+               return ".dwpbtyp", SSUBTYP_DWPBTYP
+       case ".debug_ranges":
+               return ".dwrnge", SSUBTYP_DWRNGES
+       }
+       // never used
+       return "", 0
+}
+
+// Xcoffinit initialised some internal value and setups
+// already known header information
+func Xcoffinit(ctxt *Link) {
+       xfile.dynLibraries = make(map[string]int)
+
+       XCOFFFILEHDR = int(Rnd(XCOFFHDRRESERVE, XCOFFSECTALIGN))
+       XCOFFSECTHDR = int(Rnd(int64(XCOFFFILEHDR), XCOFFSECTALIGN))
+
+       HEADR = int32(XCOFFFILEHDR)
+       if *FlagTextAddr != -1 {
+               Errorf(nil, "-T not available on AIX")
+       }
+       *FlagTextAddr = XCOFFBASE + int64(XCOFFSECTHDR)
+       *FlagDataAddr = 0
+       if *FlagRound != -1 {
+               Errorf(nil, "-R not available on AIX")
+       }
+       *FlagRound = int(XCOFFSECTALIGN)
+
+}
+
+// SYMBOL TABLE
+
+// 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
+       csectSize  int64
+}
+
+var (
+       currDwscnoff   = make(map[string]uint64) // Needed to create C_DWARF symbols
+       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)
+       f.symbolCount++
+}
+
+// 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
+// - a C_HIDEXT which will be a csect containing all of its functions
+// It needs several parameters to create .csect symbols such as its entry point and its section number.
+//
+// Currently, a new file is in fact a new package. It seems to be OK, but it might change
+// in the future.
+func (f *xcoffFile) writeSymbolNewFile(ctxt *Link, name string, firstEntry uint64, extnum int16) {
+       /* C_FILE */
+       s := &XcoffSymEnt64{
+               Noffset: uint32(f.stringTable.add(".file")),
+               Nsclass: C_FILE,
+               Nscnum:  N_DEBUG,
+               Ntype:   0, // Go isn't inside predefined language.
+               Nnumaux: 1,
+       }
+       f.writeSymbol(ctxt.Out, ctxt.Arch.ByteOrder, 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++
+
+       /* Dwarf */
+       for _, sect := range Segdwarf.Sections {
+               // Find the size of this corresponding package DWARF compilation unit.
+               // This size is set during DWARF generation (see dwarf.go).
+               dwsize := getDwsectCUSize(sect.Name, name)
+               // .debug_abbrev is commun to all packages and not found with the previous function
+               if sect.Name == ".debug_abbrev" {
+                       s := ctxt.Syms.Lookup(sect.Name, 0)
+                       dwsize = uint64(s.Size)
+               }
+
+               // get XCOFF name
+               name, _ := xcoffGetDwarfSubtype(sect.Name)
+               s := &XcoffSymEnt64{
+                       Nvalue:  currDwscnoff[sect.Name],
+                       Noffset: uint32(f.stringTable.add(name)),
+                       Nsclass: C_DWARF,
+                       Nscnum:  sect.Extnum,
+                       Nnumaux: 1,
+               }
+               f.writeSymbol(ctxt.Out, ctxt.Arch.ByteOrder, s)
+
+               // update the DWARF section offset in this file
+               if sect.Name != ".debug_abbrev" {
+                       currDwscnoff[sect.Name] += dwsize
+               }
+
+               // 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++
+       }
+
+       /* .csect */
+       // Check if extnum is in text.
+       // This is temporary and only here to check if this algorithm is correct.
+       if extnum != 1 {
+               Exitf("XCOFF symtab: A new file was detected with its first symbol not in .text")
+       }
+
+       currSymSrcFile.csectSymNb = uint64(f.symbolCount)
+       currSymSrcFile.csectSize = 0
+
+       // No offset because no name
+       s = &XcoffSymEnt64{
+               Nvalue:  firstEntry,
+               Nscnum:  extnum,
+               Nsclass: C_HIDEXT,
+               Ntype:   0, // check visibility ?
+               Nnumaux: 1,
+       }
+       f.writeSymbol(ctxt.Out, ctxt.Arch.ByteOrder, s)
+
+       aux := &XcoffAuxCSect64{
+               Xsmclas:  XMC_PR,
+               Xsmtyp:   XTY_SD | 5<<3, // align = 5
+               Xauxtype: _AUX_CSECT,
+       }
+       f.writeSymbol(ctxt.Out, ctxt.Arch.ByteOrder, aux)
+
+}
+
+// Update values for the previous package.
+//  - Svalue of the C_FILE symbol: if it is the last one, this Svalue must be -1
+//  - Xsclen of the csect symbol.
+func (f *xcoffFile) updatePreviousFile(ctxt *Link, last bool) {
+       // first file
+       if currSymSrcFile.fileSymNb == 0 {
+               return
+       }
+
+       prevOff := f.symtabOffset + int64(currSymSrcFile.fileSymNb*SYMESZ)
+       currOff := ctxt.Out.Offset()
+
+       // Update C_FILE
+       ctxt.Out.SeekSet(prevOff)
+       if last {
+               ctxt.Out.Write64(0xFFFFFFFFFFFFFFFF)
+       } else {
+               ctxt.Out.Write64(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)
+
+}
+
+// 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{} {
+       // New XCOFF symbols which will be written.
+       syms := []interface{}{}
+
+       // Check if a new file is detected.
+       if x.File == "" { // Undefined global symbol
+               // If this happens, the algorithme must be redone.
+               if currSymSrcFile.name != "" {
+                       Exitf("undefined global symbol found inside another file")
+               }
+       } else {
+               // Current file has changed. New C_FILE, C_DWARF, etc must be generated.
+               if currSymSrcFile.name != x.File {
+                       // update previous file values
+                       xfile.updatePreviousFile(ctxt, false)
+                       currSymSrcFile.name = x.File
+                       currSymSrcFile.fileSymNb = f.symbolCount
+                       f.writeSymbolNewFile(ctxt, x.File, uint64(x.Value), x.Sect.Extnum)
+               }
+       }
+
+       s := &XcoffSymEnt64{
+               Nsclass: C_EXT,
+               Noffset: uint32(xfile.stringTable.add(x.Name)),
+               Nvalue:  uint64(x.Value),
+               Nscnum:  x.Sect.Extnum,
+               Ntype:   SYM_TYPE_FUNC,
+               Nnumaux: 2,
+       }
+
+       if x.Version != 0 || x.Attr.VisibilityHidden() || x.Attr.Local() {
+               s.Nsclass = C_HIDEXT
+       }
+
+       syms = append(syms, s)
+
+       // Update current csect size
+       currSymSrcFile.csectSize += x.Size
+
+       // create auxiliary entries
+       a2 := &XcoffAuxFcn64{
+               Xfsize:   uint32(x.Size),
+               Xlnnoptr: 0,                     // TODO
+               Xendndx:  xfile.symbolCount + 3, // this symbol + 2 aux entries
+               Xauxtype: _AUX_FCN,
+       }
+       syms = append(syms, a2)
+
+       a4 := &XcoffAuxCSect64{
+               Xscnlenlo: uint32(currSymSrcFile.csectSymNb & 0xFFFFFFFF),
+               Xscnlenhi: uint32(currSymSrcFile.csectSymNb >> 32),
+               Xsmclas:   XMC_PR, // Program Code
+               Xsmtyp:    XTY_LD, // label definition (based on C)
+               Xauxtype:  _AUX_CSECT,
+       }
+       syms = append(syms, a4)
+       return syms
+}
+
+// put function used by genasmsym to write symbol table
+func putaixsym(ctxt *Link, x *sym.Symbol, str string, t SymbolType, addr int64, go_ *sym.Symbol) {
+
+       // All XCOFF symbols generated by this GO symbols
+       // Can be a symbol entry or a auxiliary entry
+       syms := []interface{}{}
+
+       switch t {
+       default:
+               return
+
+       case TextSym:
+               if x.FuncInfo != nil {
+                       // Function within a file
+                       syms = xfile.writeSymbolFunc(ctxt, x)
+               } else {
+                       // Only runtime.text and runtime.etext come through this way
+                       if x.Name != "runtime.text" && x.Name != "runtime.etext" && x.Name != "go.buildid" {
+                               Exitf("putaixsym: unknown text symbol %s", x.Name)
+                       }
+                       s := &XcoffSymEnt64{
+                               Nsclass: C_HIDEXT,
+                               Noffset: uint32(xfile.stringTable.add(str)),
+                               Nvalue:  uint64(x.Value),
+                               Nscnum:  x.Sect.Extnum,
+                               Ntype:   SYM_TYPE_FUNC,
+                               Nnumaux: 1,
+                       }
+                       syms = append(syms, s)
+
+                       size := uint64(x.Size)
+                       a4 := &XcoffAuxCSect64{
+                               Xauxtype:  _AUX_CSECT,
+                               Xscnlenlo: uint32(size & 0xFFFFFFFF),
+                               Xscnlenhi: uint32(size >> 32),
+                               Xsmclas:   XMC_PR,
+                               Xsmtyp:    XTY_SD,
+                       }
+                       syms = append(syms, a4)
+
+               }
+
+       case DataSym, BSSSym:
+               s := &XcoffSymEnt64{
+                       Nsclass: C_EXT,
+                       Noffset: uint32(xfile.stringTable.add(str)),
+                       Nvalue:  uint64(x.Value),
+                       Nscnum:  x.Sect.Extnum,
+                       Nnumaux: 1,
+               }
+
+               if x.Version != 0 || x.Attr.VisibilityHidden() || x.Attr.Local() {
+                       // There is more symbols in the case of a global data
+                       // which are related to the assembly generated
+                       // to access such symbols.
+                       // But as Golang as its own way to check if a symbol is
+                       // global or local (the capital letter), we don't need to
+                       // implement them yet.
+                       s.Nsclass = C_HIDEXT
+               }
+
+               syms = append(syms, s)
+
+               // Create auxiliary entry
+
+               // Normally, size should be the size of csect containing all
+               // the data and bss symbols of one file/package.
+               // However, it's easier to just have a csect for each symbol.
+               // It might change
+               size := uint64(x.Size)
+               a4 := &XcoffAuxCSect64{
+                       Xauxtype:  _AUX_CSECT,
+                       Xscnlenlo: uint32(size & 0xFFFFFFFF),
+                       Xscnlenhi: uint32(size >> 32),
+               }
+               // Read only data
+               if x.Type >= sym.STYPE && x.Type <= sym.SPCLNTAB {
+                       a4.Xsmclas = XMC_RO
+               } else {
+                       a4.Xsmclas = XMC_RW
+               }
+               if t == DataSym {
+                       a4.Xsmtyp |= XTY_SD
+               } else {
+                       a4.Xsmtyp |= XTY_CM
+               }
+
+               syms = append(syms, a4)
+
+       }
+       for _, s := range syms {
+               xfile.writeSymbol(ctxt.Out, ctxt.Arch.ByteOrder, s)
+       }
+}
+
+// Generate XCOFF Symbol table and XCOFF String table
+func Asmaixsym(ctxt *Link) {
+       // write symbol table
+       xfile.symtabOffset = ctxt.Out.Offset()
+       genasmsym(ctxt, putaixsym)
+
+       // update last file Svalue
+       xfile.updatePreviousFile(ctxt, true)
+
+       // write string table
+       xfile.stringTable.write(ctxt.Out)
+}
+
+// xcoffadddynimpsym adds a dynamic symbol to a XCOFF file
+func xcoffadddynimpsym(ctxt *Link, s *sym.Symbol) {
+       xfile.adddynimpsym(ctxt, s)
+}
+
+// Add a new imported symbol and a new library if needed.
+// Currently, dynamic symbols are considered as .data symbols which will receive
+// their value by the loader. Their relocation is created during the creation
+// of the .loader section, because it needs its symbol index.
+// However, there is no writing protection on those symbols and
+// it might need to be added.
+// TODO(aix): Add writing protection.
+// TODO(aix): Handles dynamic symbols without library.
+func (f *xcoffFile) adddynimpsym(ctxt *Link, s *sym.Symbol) {
+       // Check that library name is given.
+       // Pattern is already checked when compiling.
+       if s.Dynimplib() == "" {
+               Errorf(s, "imported symbol must have a given library")
+       }
+
+       for _, sf := range f.dynSymbols {
+               if sf == s {
+                       return
+               }
+       }
+
+       f.dynSymbols = append(f.dynSymbols, s)
+       s.Type = sym.SXCOFFTOC
+       // Function descriptor value
+       s.AddUint64(ctxt.Arch, 0)
+
+       if _, ok := f.dynLibraries[s.Dynimplib()]; !ok {
+               f.dynLibraries[s.Dynimplib()] = len(f.dynLibraries)
+       }
+}
+
+// Add a relocation to .loader relocation section
+func xcoffaddloaderreloc(ctxt *Link, s *sym.Symbol, r *sym.Reloc) {
+       if s.Type <= sym.SPCLNTAB && r.Sym.Type >= sym.SELFSECT && r.Sym.Type <= sym.SXREF {
+               Errorf(s, "cannot have a relocation in a text section with a data symbol: %s ", r.Sym.Name)
+       }
+
+       ldr := &XcoffLdRel64{
+               Lvaddr:  uint64(s.Value + int64(r.Off)),
+               Lrsecnm: s.Sect.Extnum,
+       }
+
+       switch r.Type {
+       case objabi.R_ADDR:
+               // Relocation of a .data symbol
+               ldr.Lrtype = 0x3F<<8 + XCOFF_R_POS
+               ldr.Lsymndx = 1 // .data
+       default:
+               Errorf(s, "unexpected .loader relocation to symbol: %s (type: %s)", r.Sym.Name, r.Type.String())
+       }
+
+       xfile.loaderReloc = append(xfile.loaderReloc, ldr)
+
+}
+
+func (ctxt *Link) doxcoff() {
+       // Initial map used to store compilation unit size for each DWARF section (see dwarf.go).
+       dwsectCUSize = make(map[string]uint64)
+
+       // TOC
+       toc := ctxt.Syms.Lookup("TOC", 0)
+       toc.Type = sym.SXCOFFTOC
+       toc.Attr |= sym.AttrReachable
+}
+
+// Loader section
+// Currently, this section is created from scratch when assembling the XCOFF file
+// according to information retrieved in xfile object.
+
+// Create loader section and returns its size
+func Loaderblk(ctxt *Link, off uint64) uint64 {
+       xfile.writeLdrScn(ctxt, off)
+       return loaderSize
+}
+
+func (f *xcoffFile) writeLdrScn(ctxt *Link, globalOff uint64) {
+       var symtab []*XcoffLdSym64
+       var strtab []*XcoffLdStr64
+       var importtab []*XcoffLdImportFile64
+       var reloctab []*XcoffLdRel64
+       var dynimpreloc []*XcoffLdRel64
+
+       // As the string table is updated in any loader subsection,
+       //  its length must be computed at the same time.
+       stlen := uint32(0)
+
+       // Loader Header
+       hdr := &XcoffLdHdr64{
+               Lversion: 2,
+               Lsymoff:  LDHDRSZ_64,
+       }
+
+       /* Symbol table */
+       // Entry point symbol
+       ep := ctxt.Syms.ROLookup(*flagEntrySymbol, 0)
+       if !ep.Attr.Reachable() {
+               Exitf("wrong entry point")
+       }
+       lds := &XcoffLdSym64{
+               Lvalue:  uint64(ep.Value),
+               Loffset: uint32(stlen + 2), // +2 because it must have the first byte of the symbol not its size field
+               Lscnum:  ep.Sect.Extnum,
+               Lsmtype: XTY_ENT | XTY_SD,
+               Lsmclas: XMC_DS,
+               Lifile:  0,
+               Lparm:   0,
+       }
+       ldstr := &XcoffLdStr64{
+               size: uint16(len(ep.String()) + 1), // + null terminator
+               name: ep.String(),
+       }
+       stlen += uint32(2 + ldstr.size) // 2 = sizeof ldstr.size
+       symtab = append(symtab, lds)
+       strtab = append(strtab, ldstr)
+
+       nbldsym := int32(4)
+
+       // dynamic import
+       for _, s := range f.dynSymbols {
+               lds = &XcoffLdSym64{
+                       Loffset: uint32(stlen + 2),
+                       Lsmtype: XTY_IMP,
+                       Lsmclas: XMC_DS,
+                       Lifile:  int32(f.dynLibraries[s.Dynimplib()] + 1),
+               }
+               ldstr := &XcoffLdStr64{
+                       size: uint16(len(s.Extname()) + 1), // + null terminator
+                       name: s.Extname(),
+               }
+               stlen += uint32(2 + ldstr.size) // 2 = sizeof ldstr.size
+               symtab = append(symtab, lds)
+               strtab = append(strtab, ldstr)
+
+               // Create relocation entry at the same moment to get symndx
+               ldr := &XcoffLdRel64{
+                       Lvaddr:  uint64(s.Value),
+                       Lrtype:  0x3F00,
+                       Lrsecnm: s.Sect.Extnum,
+                       Lsymndx: int32(nbldsym),
+               }
+               dynimpreloc = append(dynimpreloc, ldr)
+               nbldsym++
+
+       }
+
+       hdr.Lnsyms = int32(len(symtab))
+       hdr.Lrldoff = hdr.Lsymoff + uint64(24*hdr.Lnsyms) // 24 = sizeof one symbol
+       off := hdr.Lrldoff                                // current offset is the same of reloc offset
+
+       /* Reloc */
+       ldr := &XcoffLdRel64{
+               Lvaddr:  uint64(ep.Value),
+               Lrtype:  0x3F00,
+               Lrsecnm: ep.Sect.Extnum,
+               Lsymndx: 0,
+       }
+       off += 16
+       reloctab = append(reloctab, ldr)
+
+       off += uint64(16 * len(f.loaderReloc))
+       reloctab = append(reloctab, (f.loaderReloc)...)
+
+       off += uint64(16 * len(dynimpreloc))
+       reloctab = append(reloctab, dynimpreloc...)
+
+       hdr.Lnreloc = int32(len(reloctab))
+       hdr.Limpoff = off
+
+       /* Import */
+       // Default import: /usr/lib:/lib
+       ldimpf := &XcoffLdImportFile64{
+               Limpidpath: "/usr/lib:/lib",
+       }
+       off += uint64(len(ldimpf.Limpidpath) + len(ldimpf.Limpidbase) + len(ldimpf.Limpidmem) + 3) // + null delimiter
+       importtab = append(importtab, ldimpf)
+
+       // The map created by adddynimpsym associates the name to a number
+       // This number represents the librairie index (- 1) in this import files section
+       // Therefore, they must be sorted before being put inside the section
+       libsOrdered := make([]string, len(f.dynLibraries))
+       for key, val := range f.dynLibraries {
+               if libsOrdered[val] != "" {
+                       continue
+               }
+               libsOrdered[val] = key
+       }
+
+       for _, lib := range libsOrdered {
+               // lib string is defined as base.a/mem.o or path/base.a/mem.o
+               n := strings.Split(lib, "/")
+               path := ""
+               base := n[len(n)-2]
+               mem := n[len(n)-1]
+               if len(n) > 2 {
+                       path = lib[:len(lib)-len(base)-len(mem)-2]
+
+               }
+               ldimpf = &XcoffLdImportFile64{
+                       Limpidpath: path,
+                       Limpidbase: base,
+                       Limpidmem:  mem,
+               }
+               off += uint64(len(ldimpf.Limpidpath) + len(ldimpf.Limpidbase) + len(ldimpf.Limpidmem) + 3) // + null delimiter
+               importtab = append(importtab, ldimpf)
+       }
+
+       hdr.Lnimpid = int32(len(importtab))
+       hdr.Listlen = uint32(off - hdr.Limpoff)
+       hdr.Lstoff = off
+       hdr.Lstlen = stlen
+
+       /* Writing */
+       ctxt.Out.SeekSet(int64(globalOff))
+       binary.Write(ctxt.Out, ctxt.Arch.ByteOrder, hdr)
+
+       for _, s := range symtab {
+               binary.Write(ctxt.Out, ctxt.Arch.ByteOrder, s)
+
+       }
+       for _, r := range reloctab {
+               binary.Write(ctxt.Out, ctxt.Arch.ByteOrder, r)
+       }
+       for _, f := range importtab {
+               ctxt.Out.WriteString(f.Limpidpath)
+               ctxt.Out.Write8(0)
+               ctxt.Out.WriteString(f.Limpidbase)
+               ctxt.Out.Write8(0)
+               ctxt.Out.WriteString(f.Limpidmem)
+               ctxt.Out.Write8(0)
+       }
+       for _, s := range strtab {
+               ctxt.Out.Write16(s.size)
+               ctxt.Out.WriteString(s.name)
+               ctxt.Out.Write8(0) // null terminator
+       }
+
+       loaderOff = globalOff
+       loaderSize = off + uint64(stlen)
+       ctxt.Out.Flush()
+
+       /* again for printing */
+       if !*flagA {
+               return
+       }
+
+       ctxt.Logf("\n.loader section")
+       // write in buf
+       var buf bytes.Buffer
+
+       binary.Write(&buf, ctxt.Arch.ByteOrder, hdr)
+       for _, s := range symtab {
+               binary.Write(&buf, ctxt.Arch.ByteOrder, s)
+
+       }
+       for _, f := range importtab {
+               buf.WriteString(f.Limpidpath)
+               buf.WriteByte(0)
+               buf.WriteString(f.Limpidbase)
+               buf.WriteByte(0)
+               buf.WriteString(f.Limpidmem)
+               buf.WriteByte(0)
+       }
+       for _, s := range strtab {
+               binary.Write(&buf, ctxt.Arch.ByteOrder, s.size)
+               buf.WriteString(s.name)
+               buf.WriteByte(0) // null terminator
+       }
+
+       // Log buffer
+       ctxt.Logf("\n\t%.8x|", globalOff)
+       for i, b := range buf.Bytes() {
+               if i > 0 && i%16 == 0 {
+                       ctxt.Logf("\n\t%.8x|", uint64(globalOff)+uint64(i))
+               }
+               ctxt.Logf(" %.2x", b)
+       }
+       ctxt.Logf("\n")
+
+}
+
+// XCOFF assembling and writing file
+
+func (f *xcoffFile) writeFileHeader(ctxt *Link) {
+       // File header
+       f.xfhdr.Fmagic = U64_TOCMAGIC
+       f.xfhdr.Fnscns = uint16(len(f.sections))
+       f.xfhdr.Ftimedat = 0
+
+       if !*FlagS {
+               f.xfhdr.Fsymptr = uint64(f.symtabOffset)
+               f.xfhdr.Fnsyms = int32(f.symbolCount)
+       }
+
+       if ctxt.BuildMode == BuildModeExe {
+               f.xfhdr.Fopthdr = AOUTHSZ_EXEC64
+               f.xfhdr.Fflags = F_EXEC
+
+               // auxiliary header
+               f.xahdr.Ovstamp = 1 // based on dump -o
+               f.xahdr.Omagic = 0x10b
+               copy(f.xahdr.Omodtype[:], "1L")
+               f.xahdr.Oentry = uint64(Entryvalue(ctxt))
+               f.xahdr.Otoc = uint64(ctxt.Syms.ROLookup("TOC", 0).Value)
+
+               // Based on dump -o
+               f.xahdr.Oalgntext = 0x5
+               f.xahdr.Oalgndata = 0x5
+
+               binary.Write(ctxt.Out, binary.BigEndian, &f.xfhdr)
+               binary.Write(ctxt.Out, binary.BigEndian, &f.xahdr)
+       } else {
+               f.xfhdr.Fopthdr = 0
+               binary.Write(ctxt.Out, binary.BigEndian, &f.xfhdr)
+       }
+
+}
+
+func xcoffwrite(ctxt *Link) {
+       ctxt.Out.SeekSet(0)
+
+       xfile.writeFileHeader(ctxt)
+
+       for _, sect := range xfile.sections {
+               sect.write(ctxt)
+       }
+}
+
+// Generate XCOFF assembly file
+func Asmbxcoff(ctxt *Link) {
+       // initial offset for sections
+       if ctxt.BuildMode == BuildModeExe {
+               // search entry section number
+               eaddr := uint64(Entryvalue(ctxt))
+               for _, sect := range append(Segtext.Sections, Segdata.Sections...) {
+                       if eaddr-sect.Vaddr <= sect.Length {
+                               xfile.xahdr.Osnentry = int16(sect.Extnum)
+                       }
+               }
+
+               // check
+               if xfile.xahdr.Osnentry == 0 {
+                       Exitf("internal error: Section number for entry point (addr = 0x%x) not found", eaddr)
+               }
+
+       }
+
+       // add text sections
+       for _, sect := range Segtext.Sections {
+               // ctxt.Logf(".text: %s \n", sect.Name)
+               s := xfile.addSection(sect)
+               s.Sflags = STYP_TEXT
+
+               // use sect.Name because of convertion inside scnhdr
+               if sect.Name == ".text" {
+                       xfile.xahdr.Otextstart = s.Spaddr
+                       xfile.xahdr.Otsize = s.Ssize
+                       xfile.xahdr.Osntext = sect.Extnum
+               }
+       }
+
+       // add data sections
+       var (
+               snoptrdata,
+               sdata,
+               sbss,
+               snoptrbss *sym.Section
+       )
+       for _, sect := range Segdata.Sections {
+               if sect.Name == ".noptrdata" {
+                       snoptrdata = sect
+               }
+               if sect.Name == ".noptrbss" {
+                       snoptrbss = sect
+               }
+               if sect.Name == ".data" {
+                       sdata = sect
+               }
+               if sect.Name == ".bss" {
+                       sbss = sect
+               }
+       }
+
+       // On AIX, there must be only one data and one bss section.
+       // Therefore, their noptr section is merged within them.
+       // The length of the new section must be recomputed to handle defautl gap
+       // between GO sections as AIX doesn't allow it.
+
+       // Merge .noptrdata inside .data
+       sdata.Vaddr = snoptrdata.Vaddr
+       sdata.Length = sbss.Vaddr - sdata.Vaddr
+       s := xfile.addSection(sdata)
+       s.Sflags = STYP_DATA
+       xfile.xahdr.Odatastart = s.Spaddr
+       xfile.xahdr.Odsize = s.Ssize
+       xfile.xahdr.Osndata = sdata.Extnum
+
+       // Merge .noptrbss inside .bss
+       sbss.Length = snoptrbss.Vaddr + snoptrbss.Length - sbss.Vaddr
+       s = xfile.addSection(sbss)
+       s.Sflags = STYP_BSS
+       xfile.xahdr.Obsize = s.Ssize
+       xfile.xahdr.Osnbss = sbss.Extnum
+       s.Sscnptr = 0
+
+       // add dwarf section
+       for _, sect := range Segdwarf.Sections {
+               xfile.addDwarfSection(sect)
+       }
+
+       // Loader section must be add at the end because of sect.Extnum
+       // in others sections
+       xfile.addLoaderSection(loaderSize, loaderOff)
+
+       xcoffwrite(ctxt)
+}
index 3e833b686eaa1a05c9ea962c1b1e68665b0d525f..c4a49c6a1e5952d8e19165f727442bb646115769 100644 (file)
@@ -692,6 +692,11 @@ func archreloc(ctxt *ld.Link, r *sym.Reloc, s *sym.Symbol, val int64) (int64, bo
                // Runtime Handling" of "Power Architecture 64-Bit ELF V2 ABI
                // Specification".
                v := r.Sym.Value - 0x7000
+               if ctxt.HeadType == objabi.Haix {
+                       // On AIX, the thread pointer points 0x7800 bytes after
+                       // the TLS.
+                       v -= 0x800
+               }
                if int64(int16(v)) != v {
                        ld.Errorf(s, "TLS offset out of range %d", v)
                }
@@ -941,6 +946,13 @@ func asmb(ctxt *ld.Link) {
        ctxt.Out.SeekSet(int64(ld.Segdwarf.Fileoff))
        ld.Dwarfblk(ctxt, int64(ld.Segdwarf.Vaddr), int64(ld.Segdwarf.Filelen))
 
+       loadersize := uint64(0)
+       if ctxt.HeadType == objabi.Haix && ctxt.BuildMode == ld.BuildModeExe {
+               loadero := uint64(ld.Rnd(int64(ld.Segdwarf.Fileoff+ld.Segdwarf.Filelen), int64(*ld.FlagRound)))
+               ctxt.Out.SeekSet(int64(loadero))
+               loadersize = ld.Loaderblk(ctxt, loadero)
+       }
+
        /* output symbol table */
        ld.Symsize = 0
 
@@ -960,6 +972,16 @@ func asmb(ctxt *ld.Link) {
 
                case objabi.Hplan9:
                        symo = uint32(ld.Segdata.Fileoff + ld.Segdata.Filelen)
+
+               case objabi.Haix:
+                       symo = uint32(ld.Segdwarf.Fileoff + ld.Segdwarf.Filelen)
+
+                       // Add loader size if needed
+                       if ctxt.BuildMode == ld.BuildModeExe {
+                               symo = uint32(ld.Rnd(int64(symo), int64(*ld.FlagRound)))
+                               symo += uint32(loadersize)
+                       }
+                       symo = uint32(ld.Rnd(int64(symo), int64(*ld.FlagRound)))
                }
 
                ctxt.Out.SeekSet(int64(symo))
@@ -988,6 +1010,10 @@ func asmb(ctxt *ld.Link) {
                                ctxt.Out.Write(sym.P)
                                ctxt.Out.Flush()
                        }
+
+               case objabi.Haix:
+                       ld.Asmaixsym(ctxt)
+                       ctxt.Out.Flush()
                }
        }
 
@@ -1013,6 +1039,9 @@ func asmb(ctxt *ld.Link) {
                objabi.Hopenbsd,
                objabi.Hnacl:
                ld.Asmbelf(ctxt, int64(symo))
+
+       case objabi.Haix:
+               ld.Asmbxcoff(ctxt)
        }
 
        ctxt.Out.Flush()
index 273d9b42cb9da49c451b22b259f4d572103cb2cf..e630f8c062b6bed0562937310ce14117ca8d8060 100644 (file)
@@ -121,6 +121,10 @@ func archinit(ctxt *ld.Link) {
                if *ld.FlagRound == -1 {
                        *ld.FlagRound = 0x10000
                }
+
+       case objabi.Haix:
+               ld.Xcoffinit(ctxt)
+
        }
 
        if *ld.FlagDataAddr != 0 && *ld.FlagRound != 0 {