]> Cypherpunks repositories - gostls13.git/commitdiff
cmd/link/internal/ld: add s390x support
authorMichael Munday <munday@ca.ibm.com>
Fri, 18 Mar 2016 20:57:54 +0000 (16:57 -0400)
committerBrad Fitzpatrick <bradfitz@golang.org>
Sun, 3 Apr 2016 05:31:57 +0000 (05:31 +0000)
Introduces the new relocation variant RV_390_DBL which indicates
that the relocation value should be shifted right by 1 (to make
it 2-byte aligned).

Change-Id: I03fa96b4759ee19330c5298c3720746622fb1a03
Reviewed-on: https://go-review.googlesource.com/20878
Run-TryBot: Brad Fitzpatrick <bradfitz@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Brad Fitzpatrick <bradfitz@golang.org>
src/cmd/link/internal/ld/arch.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/ldelf.go
src/cmd/link/internal/ld/lib.go
src/cmd/link/internal/ld/link.go
src/cmd/link/internal/ld/symtab.go

index 306e2df34f74f4996b4bf736be6b8b5f74849df0..d28f37fa02bd0263cafafaaa3e10478f893c22dc 100644 (file)
@@ -86,3 +86,12 @@ var Linkmips64le = LinkArch{
        Ptrsize:   8,
        Regsize:   8,
 }
+
+var Links390x = LinkArch{
+       ByteOrder: binary.BigEndian,
+       Name:      "s390x",
+       Thechar:   'z',
+       Minlc:     2,
+       Ptrsize:   8,
+       Regsize:   8,
+}
index cacec8f8fe6c39066f9b0d141b77ccb3eebeeda4..91f0107626599e3f9eb155ca3e34dfce63a28b7a 100644 (file)
@@ -149,6 +149,9 @@ func Addpcrelplus(ctxt *Link, s *LSym, t *LSym, add int64) int64 {
        r.Add = add
        r.Type = obj.R_PCREL
        r.Siz = 4
+       if Thearch.Thechar == 'z' {
+               r.Variant = RV_390_DBL
+       }
        return i + int64(r.Siz)
 }
 
@@ -347,6 +350,17 @@ func relocsym(s *LSym) {
                        Diag("unreachable sym in relocation: %s %s", s.Name, r.Sym.Name)
                }
 
+               // TODO(mundaym): remove this special case - see issue 14218.
+               if Thearch.Thechar == 'z' {
+                       switch r.Type {
+                       case obj.R_PCRELDBL:
+                               r.Type = obj.R_PCREL
+                               r.Variant = RV_390_DBL
+                       case obj.R_CALL:
+                               r.Variant = RV_390_DBL
+                       }
+               }
+
                switch r.Type {
                default:
                        switch siz {
@@ -1020,7 +1034,7 @@ func symalign(s *LSym) int32 {
        if strings.HasPrefix(s.Name, "go.string.") && !strings.HasPrefix(s.Name, "go.string.hdr.") {
                // String data is just bytes.
                // If we align it, we waste a lot of space to padding.
-               return 1
+               return min
        }
        align := int32(Thearch.Maxalign)
        for int64(align) > s.Size && align > min {
index 8e0394bdbeb97bf9470ace92752ac59f98de0db9..fd177cfef0895a64daf7c082508bb01ef5777746 100644 (file)
@@ -2170,7 +2170,7 @@ func dwarfaddshstrings(shstrtab *LSym) {
        elfstrdbg[ElfStrGDBScripts] = Addstring(shstrtab, ".debug_gdb_scripts")
        if Linkmode == LinkExternal {
                switch Thearch.Thechar {
-               case '0', '6', '7', '9':
+               case '0', '6', '7', '9', 'z':
                        elfstrdbg[ElfStrRelDebugInfo] = Addstring(shstrtab, ".rela.debug_info")
                        elfstrdbg[ElfStrRelDebugAranges] = Addstring(shstrtab, ".rela.debug_aranges")
                        elfstrdbg[ElfStrRelDebugLine] = Addstring(shstrtab, ".rela.debug_line")
@@ -2223,7 +2223,7 @@ func dwarfaddelfsectionsyms() {
 func dwarfaddelfrelocheader(elfstr int, shdata *ElfShdr, off int64, size int64) {
        sh := newElfShdr(elfstrdbg[elfstr])
        switch Thearch.Thechar {
-       case '0', '6', '7', '9':
+       case '0', '6', '7', '9', 'z':
                sh.type_ = SHT_RELA
        default:
                sh.type_ = SHT_REL
index 6db7898624fc3614dc08316142bbaead482c30a8..cf518a799e1a4d9df194e79d4a9efe780a67983c 100644 (file)
@@ -647,6 +647,68 @@ const (
        R_SPARC_UA64     = 54
        R_SPARC_UA16     = 55
 
+       R_390_NONE        = 0
+       R_390_8           = 1
+       R_390_12          = 2
+       R_390_16          = 3
+       R_390_32          = 4
+       R_390_PC32        = 5
+       R_390_GOT12       = 6
+       R_390_GOT32       = 7
+       R_390_PLT32       = 8
+       R_390_COPY        = 9
+       R_390_GLOB_DAT    = 10
+       R_390_JMP_SLOT    = 11
+       R_390_RELATIVE    = 12
+       R_390_GOTOFF      = 13
+       R_390_GOTPC       = 14
+       R_390_GOT16       = 15
+       R_390_PC16        = 16
+       R_390_PC16DBL     = 17
+       R_390_PLT16DBL    = 18
+       R_390_PC32DBL     = 19
+       R_390_PLT32DBL    = 20
+       R_390_GOTPCDBL    = 21
+       R_390_64          = 22
+       R_390_PC64        = 23
+       R_390_GOT64       = 24
+       R_390_PLT64       = 25
+       R_390_GOTENT      = 26
+       R_390_GOTOFF16    = 27
+       R_390_GOTOFF64    = 28
+       R_390_GOTPLT12    = 29
+       R_390_GOTPLT16    = 30
+       R_390_GOTPLT32    = 31
+       R_390_GOTPLT64    = 32
+       R_390_GOTPLTENT   = 33
+       R_390_GOTPLTOFF16 = 34
+       R_390_GOTPLTOFF32 = 35
+       R_390_GOTPLTOFF64 = 36
+       R_390_TLS_LOAD    = 37
+       R_390_TLS_GDCALL  = 38
+       R_390_TLS_LDCALL  = 39
+       R_390_TLS_GD32    = 40
+       R_390_TLS_GD64    = 41
+       R_390_TLS_GOTIE12 = 42
+       R_390_TLS_GOTIE32 = 43
+       R_390_TLS_GOTIE64 = 44
+       R_390_TLS_LDM32   = 45
+       R_390_TLS_LDM64   = 46
+       R_390_TLS_IE32    = 47
+       R_390_TLS_IE64    = 48
+       R_390_TLS_IEENT   = 49
+       R_390_TLS_LE32    = 50
+       R_390_TLS_LE64    = 51
+       R_390_TLS_LDO32   = 52
+       R_390_TLS_LDO64   = 53
+       R_390_TLS_DTPMOD  = 54
+       R_390_TLS_DTPOFF  = 55
+       R_390_TLS_TPOFF   = 56
+       R_390_20          = 57
+       R_390_GOT20       = 58
+       R_390_GOTPLT20    = 59
+       R_390_TLS_GOTIE20 = 60
+
        ARM_MAGIC_TRAMP_NUMBER = 0x5c000003
 )
 
@@ -804,7 +866,7 @@ func Elfinit() {
 
        switch Thearch.Thechar {
        // 64-bit architectures
-       case '9':
+       case '9', 'z':
                if Ctxt.Arch.ByteOrder == binary.BigEndian {
                        ehdr.flags = 1 /* Version 1 ABI */
                } else {
@@ -1360,13 +1422,25 @@ func elfdynhash() {
                buckets[b] = uint32(sy.Dynid)
        }
 
-       Adduint32(Ctxt, s, uint32(nbucket))
-       Adduint32(Ctxt, s, uint32(nsym))
-       for i := 0; i < nbucket; i++ {
-               Adduint32(Ctxt, s, buckets[i])
-       }
-       for i := 0; i < nsym; i++ {
-               Adduint32(Ctxt, s, chain[i])
+       // s390x (ELF64) hash table entries are 8 bytes
+       if Thearch.Thechar == 'z' {
+               Adduint64(Ctxt, s, uint64(nbucket))
+               Adduint64(Ctxt, s, uint64(nsym))
+               for i := 0; i < nbucket; i++ {
+                       Adduint64(Ctxt, s, uint64(buckets[i]))
+               }
+               for i := 0; i < nsym; i++ {
+                       Adduint64(Ctxt, s, uint64(chain[i]))
+               }
+       } else {
+               Adduint32(Ctxt, s, uint32(nbucket))
+               Adduint32(Ctxt, s, uint32(nsym))
+               for i := 0; i < nbucket; i++ {
+                       Adduint32(Ctxt, s, buckets[i])
+               }
+               for i := 0; i < nsym; i++ {
+                       Adduint32(Ctxt, s, chain[i])
+               }
        }
 
        // version symbols
@@ -1434,7 +1508,7 @@ func elfdynhash() {
        }
 
        switch Thearch.Thechar {
-       case '0', '6', '7', '9':
+       case '0', '6', '7', '9', 'z':
                sy := Linklookup(Ctxt, ".rela.plt", 0)
                if sy.Size > 0 {
                        Elfwritedynent(s, DT_PLTREL, DT_RELA)
@@ -1574,7 +1648,7 @@ func elfshreloc(sect *Section) *ElfShdr {
        var prefix string
        var typ int
        switch Thearch.Thechar {
-       case '0', '6', '7', '9':
+       case '0', '6', '7', '9', 'z':
                prefix = ".rela"
                typ = SHT_RELA
        default:
@@ -1748,7 +1822,7 @@ func doelf() {
                Debug['d'] = 1
 
                switch Thearch.Thechar {
-               case '0', '6', '7', '9':
+               case '0', '6', '7', '9', 'z':
                        Addstring(shstrtab, ".rela.text")
                        Addstring(shstrtab, ".rela.rodata")
                        Addstring(shstrtab, ".rela"+relro_prefix+".typelink")
@@ -1796,7 +1870,7 @@ func doelf() {
        if hasinitarr {
                Addstring(shstrtab, ".init_array")
                switch Thearch.Thechar {
-               case '0', '6', '7', '9':
+               case '0', '6', '7', '9', 'z':
                        Addstring(shstrtab, ".rela.init_array")
                default:
                        Addstring(shstrtab, ".rel.init_array")
@@ -1823,7 +1897,7 @@ func doelf() {
                Addstring(shstrtab, ".dynsym")
                Addstring(shstrtab, ".dynstr")
                switch Thearch.Thechar {
-               case '0', '6', '7', '9':
+               case '0', '6', '7', '9', 'z':
                        Addstring(shstrtab, ".rela")
                        Addstring(shstrtab, ".rela.plt")
                default:
@@ -1841,7 +1915,7 @@ func doelf() {
                s.Type = obj.SELFROSECT
                s.Attr |= AttrReachable
                switch Thearch.Thechar {
-               case '0', '6', '7', '9':
+               case '0', '6', '7', '9', 'z':
                        s.Size += ELF64SYMSIZE
                default:
                        s.Size += ELF32SYMSIZE
@@ -1859,7 +1933,7 @@ func doelf() {
 
                /* relocation table */
                switch Thearch.Thechar {
-               case '0', '6', '7', '9':
+               case '0', '6', '7', '9', 'z':
                        s = Linklookup(Ctxt, ".rela", 0)
                default:
                        s = Linklookup(Ctxt, ".rel", 0)
@@ -1904,7 +1978,7 @@ func doelf() {
                Thearch.Elfsetupplt()
 
                switch Thearch.Thechar {
-               case '0', '6', '7', '9':
+               case '0', '6', '7', '9', 'z':
                        s = Linklookup(Ctxt, ".rela.plt", 0)
                default:
                        s = Linklookup(Ctxt, ".rel.plt", 0)
@@ -1933,7 +2007,7 @@ func doelf() {
 
                elfwritedynentsym(s, DT_SYMTAB, Linklookup(Ctxt, ".dynsym", 0))
                switch Thearch.Thechar {
-               case '0', '6', '7', '9':
+               case '0', '6', '7', '9', 'z':
                        Elfwritedynent(s, DT_SYMENT, ELF64SYMSIZE)
                default:
                        Elfwritedynent(s, DT_SYMENT, ELF32SYMSIZE)
@@ -1941,7 +2015,7 @@ func doelf() {
                elfwritedynentsym(s, DT_STRTAB, Linklookup(Ctxt, ".dynstr", 0))
                elfwritedynentsymsize(s, DT_STRSZ, Linklookup(Ctxt, ".dynstr", 0))
                switch Thearch.Thechar {
-               case '0', '6', '7', '9':
+               case '0', '6', '7', '9', 'z':
                        elfwritedynentsym(s, DT_RELA, Linklookup(Ctxt, ".rela", 0))
                        elfwritedynentsymsize(s, DT_RELASZ, Linklookup(Ctxt, ".rela", 0))
                        Elfwritedynent(s, DT_RELAENT, ELF64RELASIZE)
@@ -1957,6 +2031,8 @@ func doelf() {
 
                if Thearch.Thechar == '9' {
                        elfwritedynentsym(s, DT_PLTGOT, Linklookup(Ctxt, ".plt", 0))
+               } else if Thearch.Thechar == 'z' {
+                       elfwritedynentsym(s, DT_PLTGOT, Linklookup(Ctxt, ".got", 0))
                } else {
                        elfwritedynentsym(s, DT_PLTGOT, Linklookup(Ctxt, ".got.plt", 0))
                }
@@ -2052,6 +2128,8 @@ func Asmbelf(symo int64) {
                eh.machine = EM_386
        case '9':
                eh.machine = EM_PPC64
+       case 'z':
+               eh.machine = EM_S390
        }
 
        elfreserve := int64(ELFRESERVE)
@@ -2237,7 +2315,7 @@ func Asmbelf(symo int64) {
                }
 
                switch eh.machine {
-               case EM_X86_64, EM_PPC64, EM_AARCH64:
+               case EM_X86_64, EM_PPC64, EM_AARCH64, EM_S390:
                        sh := elfshname(".rela.plt")
                        sh.type_ = SHT_RELA
                        sh.flags = SHF_ALLOC
@@ -2286,6 +2364,8 @@ func Asmbelf(symo int64) {
                sh.flags = SHF_ALLOC + SHF_EXECINSTR
                if eh.machine == EM_X86_64 {
                        sh.entsize = 16
+               } else if eh.machine == EM_S390 {
+                       sh.entsize = 32
                } else if eh.machine == EM_PPC64 {
                        // On ppc64, this is just a table of addresses
                        // filled by the dynamic linker
index a68c473a388740f3076c2c0cdf5d29595a7d472f..0255331ac65a2f1dacd578cbd6d395ed89c4eafa 100644 (file)
@@ -586,6 +586,11 @@ func ldelf(f *obj.Biobuf, pkg string, length int64, pn string) {
                        Diag("%s: elf object but not ppc64", pn)
                        return
                }
+       case 'z':
+               if elfobj.machine != ElfMachS390 || hdr.Ident[4] != ElfClass64 {
+                       Diag("%s: elf object but not s390x", pn)
+                       return
+               }
        }
 
        // load section list into memory.
@@ -778,6 +783,9 @@ func ldelf(f *obj.Biobuf, pkg string, length int64, pn string) {
                                continue
                        }
 
+                       if strings.HasPrefix(sym.name, ".LASF") { // gcc on s390x does this
+                               continue
+                       }
                        Diag("%s: sym#%d: ignoring %s in section %d (type %d)", pn, i, sym.name, sym.shndx, sym.type_)
                        continue
                }
@@ -1124,6 +1132,9 @@ func reltype(pn string, elftype int, siz *uint8) int {
                Diag("%s: unknown relocation type %d; compiled without -fpic?", pn, elftype)
                fallthrough
 
+       case 'z' | R_390_8:
+               *siz = 1
+
        case '9' | R_PPC64_TOC16<<24,
                '9' | R_PPC64_TOC16_LO<<24,
                '9' | R_PPC64_TOC16_HI<<24,
@@ -1132,7 +1143,12 @@ func reltype(pn string, elftype int, siz *uint8) int {
                '9' | R_PPC64_TOC16_LO_DS<<24,
                '9' | R_PPC64_REL16_LO<<24,
                '9' | R_PPC64_REL16_HI<<24,
-               '9' | R_PPC64_REL16_HA<<24:
+               '9' | R_PPC64_REL16_HA<<24,
+               'z' | R_390_16<<24,
+               'z' | R_390_GOT16<<24,
+               'z' | R_390_PC16<<24,
+               'z' | R_390_PC16DBL<<24,
+               'z' | R_390_PLT16DBL<<24:
                *siz = 2
 
        case '5' | R_ARM_ABS32<<24,
@@ -1160,11 +1176,27 @@ func reltype(pn string, elftype int, siz *uint8) int {
                '8' | R_386_GOTPC<<24,
                '8' | R_386_GOT32X<<24,
                '9' | R_PPC64_REL24<<24,
-               '9' | R_PPC_REL32<<24:
+               '9' | R_PPC_REL32<<24,
+               'z' | R_390_32<<24,
+               'z' | R_390_PC32<<24,
+               'z' | R_390_GOT32<<24,
+               'z' | R_390_PLT32<<24,
+               'z' | R_390_PC32DBL<<24,
+               'z' | R_390_PLT32DBL<<24,
+               'z' | R_390_GOTPCDBL<<24,
+               'z' | R_390_GOTENT<<24:
                *siz = 4
 
        case '6' | R_X86_64_64<<24,
-               '9' | R_PPC64_ADDR64<<24:
+               '9' | R_PPC64_ADDR64<<24,
+               'z' | R_390_GLOB_DAT<<24,
+               'z' | R_390_RELATIVE<<24,
+               'z' | R_390_GOTOFF<<24,
+               'z' | R_390_GOTPC<<24,
+               'z' | R_390_64<<24,
+               'z' | R_390_PC64<<24,
+               'z' | R_390_GOT64<<24,
+               'z' | R_390_PLT64<<24:
                *siz = 8
        }
 
index fcaa8a026aa638d87a5ecd3e3587610f50de8e7b..2f5d155f18a8f0e492c07c01f28db1bbf6c18bc1 100644 (file)
@@ -339,7 +339,7 @@ func (mode *BuildMode) Set(s string) error {
                switch goos {
                case "linux":
                        switch goarch {
-                       case "386", "amd64", "arm", "arm64", "ppc64le":
+                       case "386", "amd64", "arm", "arm64", "ppc64le", "s390x":
                        default:
                                return badmode()
                        }
@@ -1242,7 +1242,7 @@ func hostlinkArchArgs() []string {
        switch Thearch.Thechar {
        case '8':
                return []string{"-m32"}
-       case '6', '9':
+       case '6', '9', 'z':
                return []string{"-m64"}
        case '5':
                return []string{"-marm"}
index b00f80abbd5fa0456291c309a4fe9797310eeb2d..e11b5dc900f75f68edbd94e23aebd2dd8856a9c8 100644 (file)
@@ -264,6 +264,12 @@ const (
        RV_POWER_HI
        RV_POWER_HA
        RV_POWER_DS
+
+       // RV_390_DBL is a s390x-specific relocation variant that indicates that
+       // the value to be placed into the relocatable field should first be
+       // divided by 2.
+       RV_390_DBL
+
        RV_CHECK_OVERFLOW = 1 << 8
        RV_TYPE_MASK      = RV_CHECK_OVERFLOW - 1
 )
index c44b67d50dace73aae09d835363288cb43a625a0..3f8784f996474b8e1cf78e89fe001dea571e558e 100644 (file)
@@ -67,7 +67,7 @@ func putelfstr(s string) int {
 
 func putelfsyment(off int, addr int64, size int64, info int, shndx int, other int) {
        switch Thearch.Thechar {
-       case '0', '6', '7', '9':
+       case '0', '6', '7', '9', 'z':
                Thearch.Lput(uint32(off))
                Cput(uint8(info))
                Cput(uint8(other))
@@ -593,6 +593,7 @@ func symtab() {
                adduint(Ctxt, moduledata, uint64(len(Ctxt.Shlibs)))
                adduint(Ctxt, moduledata, uint64(len(Ctxt.Shlibs)))
        }
+
        // The rest of moduledata is zero initialized.
        // When linking an object that does not contain the runtime we are
        // creating the moduledata from scratch and it does not have a