]> Cypherpunks repositories - gostls13.git/commitdiff
liblink, cmd/6l: re-enable -shared on amd64
authorMichael Hudson-Doyle <michael.hudson@canonical.com>
Tue, 10 Feb 2015 02:56:32 +0000 (15:56 +1300)
committerIan Lance Taylor <iant@golang.org>
Wed, 4 Mar 2015 01:55:30 +0000 (01:55 +0000)
The creation of liblink and subsequent introduction of more explicit
TLS handling broke 6l's (unsupported) -shared flag.  This change adds
-shared flags to cmd/asm and 6g and changes liblink to generate shared-
library compatible instruction sequences when they are passed, and
changes 6l to emit the appropriate ELF relocation.

A proper fix probably also requires go tool changes.

Fixes #9652.

Change-Id: I7b7718fe7305c802ac994f4a5c8de68cfbe6c76b
Reviewed-on: https://go-review.googlesource.com/4321
Reviewed-by: Ian Lance Taylor <iant@golang.org>
Run-TryBot: Ian Lance Taylor <iant@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>

src/cmd/6l/asm.go
src/cmd/asm/internal/flags/flags.go
src/cmd/asm/main.go
src/cmd/internal/gc/lex.go
src/cmd/internal/obj/x86/asm6.go
src/cmd/internal/obj/x86/obj6.go

index 22776b943076fa29e76fa61a9f2cf6737a11e36f..bc95d81540841e1cc63841e83dc24f0a8f5a8dcf 100644 (file)
@@ -292,6 +292,13 @@ func elfreloc1(r *ld.Reloc, sectoff int64) int {
                        return -1
                }
 
+       case ld.R_TLS_IE:
+               if r.Siz == 4 {
+                       ld.Thearch.Vput(ld.R_X86_64_GOTTPOFF | uint64(elfsym)<<32)
+               } else {
+                       return -1
+               }
+
        case ld.R_CALL:
                if r.Siz == 4 {
                        if r.Xsym.Type == ld.SDYNIMPORT {
index 12bd585413c90dec0740a78a43114ce6fe6ac65c..0fa997f06ece667bff053224b414cd1513874178 100644 (file)
@@ -18,6 +18,7 @@ var (
        OutputFile = flag.String("o", "", "output file; default foo.6 for /a/b/c/foo.s on amd64")
        PrintOut   = flag.Bool("S", false, "print assembly and machine code")
        TrimPath   = flag.String("trimpath", "", "remove prefix from recorded source file paths")
+       Shared     = flag.Bool("shared", false, "generate code that can be linked into a shared library")
 )
 
 var (
index 9df486e85c6caecf8a313d518778a91714179141..e8b10ce1eac710386b9e6d3df488b851f5f4f9cc 100644 (file)
@@ -41,6 +41,9 @@ func main() {
                ctxt.Debugasm = 1
        }
        ctxt.Trimpath = *flags.TrimPath
+       if *flags.Shared {
+               ctxt.Flag_shared = 1
+       }
        ctxt.Bso = obj.Binitw(os.Stdout)
        defer obj.Bflush(ctxt.Bso)
        ctxt.Diag = log.Fatalf
index 32f7240a096a604bcc3e8b41aca021172f08b092..6ff515e7b3ec3d8edfb24d75a556a5cb55b89505 100644 (file)
@@ -221,13 +221,16 @@ func Main() {
        obj.Flagcount("wb", "enable write barrier", &use_writebarrier)
        obj.Flagcount("x", "debug lexer", &Debug['x'])
        obj.Flagcount("y", "debug declarations in canned imports (with -d)", &Debug['y'])
+       var flag_shared int
        if Thearch.Thechar == '6' {
                obj.Flagcount("largemodel", "generate code that assumes a large memory model", &flag_largemodel)
+               obj.Flagcount("shared", "generate code that can be linked into a shared library", &flag_shared)
        }
 
        obj.Flagstr("cpuprofile", "file: write cpu profile to file", &cpuprofile)
        obj.Flagstr("memprofile", "file: write memory profile to file", &memprofile)
        obj.Flagparse(usage)
+       Ctxt.Flag_shared = int32(flag_shared)
        Ctxt.Debugasm = int32(Debug['S'])
        Ctxt.Debugvlog = int32(Debug['v'])
 
index 07ae72f3f0ea2acab303559663bcb2ce06079281..ee73fb9717dc8d9d18e546d60b4e35238768ab2c 100644 (file)
@@ -1838,7 +1838,7 @@ func prefixof(ctxt *obj.Link, a *obj.Addr) int {
                case REG_GS:
                        return 0x65
 
-                       // NOTE: Systems listed here should be only systems that
+               // NOTE: Systems listed here should be only systems that
                // support direct TLS references like 8(TLS) implemented as
                // direct references from FS or GS. Systems that require
                // the initial-exec model, where you load the TLS base into
@@ -1849,9 +1849,15 @@ func prefixof(ctxt *obj.Link, a *obj.Addr) int {
                        default:
                                log.Fatalf("unknown TLS base register for %s", obj.Headstr(ctxt.Headtype))
 
+                       case obj.Hlinux:
+                               if ctxt.Flag_shared != 0 {
+                                       log.Fatalf("unknown TLS base register for linux with -shared")
+                               } else {
+                                       return 0x64 // FS
+                               }
+
                        case obj.Hdragonfly,
                                obj.Hfreebsd,
-                               obj.Hlinux,
                                obj.Hnetbsd,
                                obj.Hopenbsd,
                                obj.Hsolaris:
@@ -1873,6 +1879,21 @@ func prefixof(ctxt *obj.Link, a *obj.Addr) int {
        case REG_ES:
                return 0x26
 
+       case REG_TLS:
+               if ctxt.Flag_shared != 0 {
+                       // When building for inclusion into a shared library, an instruction of the form
+                       //     MOV 0(CX)(TLS*1), AX
+                       // becomes
+                       //     mov %fs:(%rcx), %rax
+                       // which assumes that the correct TLS offset has been loaded into %rcx (today
+                       // there is only one TLS variable -- g -- so this is OK). When not building for
+                       // a shared library the instruction does not require a prefix.
+                       if a.Offset != 0 {
+                               log.Fatalf("cannot handle non-0 offsets to TLS")
+                       }
+                       return 0x64
+               }
+
        case REG_FS:
                return 0x64
 
@@ -2486,7 +2507,7 @@ func asmandsz(ctxt *obj.Link, p *obj.Prog, a *obj.Addr, r int, rex int, m64 int)
        }
 
        if REG_AX <= base && base <= REG_R15 {
-               if a.Index == REG_TLS {
+               if a.Index == REG_TLS && ctxt.Flag_shared == 0 {
                        rel = obj.Reloc{}
                        rel.Type = obj.R_TLS_IE
                        rel.Siz = 4
@@ -3488,7 +3509,7 @@ func doasm(ctxt *obj.Link, p *obj.Prog) {
                                                        }
                                                }
 
-                                               // NOTE: The systems listed here are the ones that use the "TLS initial exec" model,
+                                       // NOTE: The systems listed here are the ones that use the "TLS initial exec" model,
                                        // where you load the TLS base register into a register and then index off that
                                        // register to access the actual TLS variables. Systems that allow direct TLS access
                                        // are handled in prefixof above and should not be listed here.
index 5060049d58cef7f2aa45718d6b7d65fc88046b1f..29bed6361771295919d3fd33eba79011950468f7 100644 (file)
@@ -43,6 +43,8 @@ func canuselocaltls(ctxt *obj.Link) bool {
        case obj.Hplan9,
                obj.Hwindows:
                return false
+       case obj.Hlinux:
+               return ctxt.Flag_shared == 0
        }
 
        return true