github.com/4ad/go@v0.0.0-20161219182952-69a12818b605/src/cmd/link/internal/ld/sym.go (about) 1 // Derived from Inferno utils/6l/obj.c and utils/6l/span.c 2 // http://code.google.com/p/inferno-os/source/browse/utils/6l/obj.c 3 // http://code.google.com/p/inferno-os/source/browse/utils/6l/span.c 4 // 5 // Copyright © 1994-1999 Lucent Technologies Inc. All rights reserved. 6 // Portions Copyright © 1995-1997 C H Forsyth (forsyth@terzarima.net) 7 // Portions Copyright © 1997-1999 Vita Nuova Limited 8 // Portions Copyright © 2000-2007 Vita Nuova Holdings Limited (www.vitanuova.com) 9 // Portions Copyright © 2004,2006 Bruce Ellis 10 // Portions Copyright © 2005-2007 C H Forsyth (forsyth@terzarima.net) 11 // Revisions Copyright © 2000-2007 Lucent Technologies Inc. and others 12 // Portions Copyright © 2009 The Go Authors. All rights reserved. 13 // 14 // Permission is hereby granted, free of charge, to any person obtaining a copy 15 // of this software and associated documentation files (the "Software"), to deal 16 // in the Software without restriction, including without limitation the rights 17 // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 18 // copies of the Software, and to permit persons to whom the Software is 19 // furnished to do so, subject to the following conditions: 20 // 21 // The above copyright notice and this permission notice shall be included in 22 // all copies or substantial portions of the Software. 23 // 24 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 25 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 26 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 27 // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 28 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 29 // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 30 // THE SOFTWARE. 31 32 package ld 33 34 import ( 35 "cmd/internal/obj" 36 "cmd/internal/sys" 37 "log" 38 "strconv" 39 ) 40 41 var headers = []struct { 42 name string 43 val int 44 }{ 45 {"darwin", obj.Hdarwin}, 46 {"dragonfly", obj.Hdragonfly}, 47 {"freebsd", obj.Hfreebsd}, 48 {"linux", obj.Hlinux}, 49 {"android", obj.Hlinux}, // must be after "linux" entry or else headstr(Hlinux) == "android" 50 {"nacl", obj.Hnacl}, 51 {"netbsd", obj.Hnetbsd}, 52 {"openbsd", obj.Hopenbsd}, 53 {"plan9", obj.Hplan9}, 54 {"solaris", obj.Hsolaris}, 55 {"windows", obj.Hwindows}, 56 {"windowsgui", obj.Hwindows}, 57 } 58 59 func linknew(arch *sys.Arch) *Link { 60 ctxt := &Link{ 61 Hash: []map[string]*LSym{ 62 // preallocate about 2mb for hash of 63 // non static symbols 64 make(map[string]*LSym, 100000), 65 }, 66 Allsym: make([]*LSym, 0, 100000), 67 Arch: arch, 68 Goroot: obj.Getgoroot(), 69 } 70 71 p := obj.Getgoarch() 72 if p != arch.Name { 73 log.Fatalf("invalid goarch %s (want %s)", p, arch.Name) 74 } 75 76 ctxt.Headtype = headtype(obj.Getgoos()) 77 if ctxt.Headtype < 0 { 78 log.Fatalf("unknown goos %s", obj.Getgoos()) 79 } 80 81 // Record thread-local storage offset. 82 // TODO(rsc): Move tlsoffset back into the linker. 83 switch ctxt.Headtype { 84 default: 85 log.Fatalf("unknown thread-local storage offset for %s", Headstr(ctxt.Headtype)) 86 87 case obj.Hplan9, obj.Hwindows: 88 break 89 90 /* 91 * ELF uses TLS offset negative from FS. 92 * Translate 0(FS) and 8(FS) into -16(FS) and -8(FS). 93 * Known to low-level assembly in package runtime and runtime/cgo. 94 */ 95 case obj.Hlinux, 96 obj.Hfreebsd, 97 obj.Hnetbsd, 98 obj.Hopenbsd, 99 obj.Hdragonfly, 100 obj.Hsolaris: 101 if obj.Getgoos() == "android" { 102 switch ctxt.Arch.Family { 103 case sys.AMD64: 104 // Android/amd64 constant - offset from 0(FS) to our TLS slot. 105 // Explained in src/runtime/cgo/gcc_android_*.c 106 ctxt.Tlsoffset = 0x1d0 107 case sys.I386: 108 // Android/386 constant - offset from 0(GS) to our TLS slot. 109 ctxt.Tlsoffset = 0xf8 110 default: 111 ctxt.Tlsoffset = -1 * ctxt.Arch.PtrSize 112 } 113 } else { 114 ctxt.Tlsoffset = -1 * ctxt.Arch.PtrSize 115 } 116 117 case obj.Hnacl: 118 switch ctxt.Arch.Family { 119 default: 120 log.Fatalf("unknown thread-local storage offset for nacl/%s", ctxt.Arch.Name) 121 122 case sys.ARM: 123 ctxt.Tlsoffset = 0 124 125 case sys.AMD64: 126 ctxt.Tlsoffset = 0 127 128 case sys.I386: 129 ctxt.Tlsoffset = -8 130 } 131 132 /* 133 * OS X system constants - offset from 0(GS) to our TLS. 134 * Explained in src/runtime/cgo/gcc_darwin_*.c. 135 */ 136 case obj.Hdarwin: 137 switch ctxt.Arch.Family { 138 default: 139 log.Fatalf("unknown thread-local storage offset for darwin/%s", ctxt.Arch.Name) 140 141 case sys.ARM: 142 ctxt.Tlsoffset = 0 // dummy value, not needed 143 144 case sys.AMD64: 145 ctxt.Tlsoffset = 0x8a0 146 147 case sys.ARM64: 148 ctxt.Tlsoffset = 0 // dummy value, not needed 149 150 case sys.I386: 151 ctxt.Tlsoffset = 0x468 152 } 153 } 154 155 // On arm, record goarm. 156 if ctxt.Arch.Family == sys.ARM { 157 ctxt.Goarm = obj.Getgoarm() 158 } 159 160 return ctxt 161 } 162 163 func linknewsym(ctxt *Link, name string, v int) *LSym { 164 batch := ctxt.LSymBatch 165 if len(batch) == 0 { 166 batch = make([]LSym, 1000) 167 } 168 s := &batch[0] 169 ctxt.LSymBatch = batch[1:] 170 171 s.Dynid = -1 172 s.Plt = -1 173 s.Got = -1 174 s.Name = name 175 s.Version = int16(v) 176 ctxt.Allsym = append(ctxt.Allsym, s) 177 178 return s 179 } 180 181 func Linklookup(ctxt *Link, name string, v int) *LSym { 182 m := ctxt.Hash[v] 183 s := m[name] 184 if s != nil { 185 return s 186 } 187 s = linknewsym(ctxt, name, v) 188 s.Extname = s.Name 189 m[name] = s 190 return s 191 } 192 193 // read-only lookup 194 func Linkrlookup(ctxt *Link, name string, v int) *LSym { 195 return ctxt.Hash[v][name] 196 } 197 198 func Headstr(v int) string { 199 for i := 0; i < len(headers); i++ { 200 if v == headers[i].val { 201 return headers[i].name 202 } 203 } 204 return strconv.Itoa(v) 205 } 206 207 func headtype(name string) int { 208 for i := 0; i < len(headers); i++ { 209 if name == headers[i].name { 210 return headers[i].val 211 } 212 } 213 return -1 214 }