github.com/miolini/go@v0.0.0-20160405192216-fca68c8cb408/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 "log" 37 "strconv" 38 ) 39 40 var headers = []struct { 41 name string 42 val int 43 }{ 44 {"darwin", obj.Hdarwin}, 45 {"dragonfly", obj.Hdragonfly}, 46 {"freebsd", obj.Hfreebsd}, 47 {"linux", obj.Hlinux}, 48 {"android", obj.Hlinux}, // must be after "linux" entry or else headstr(Hlinux) == "android" 49 {"nacl", obj.Hnacl}, 50 {"netbsd", obj.Hnetbsd}, 51 {"openbsd", obj.Hopenbsd}, 52 {"plan9", obj.Hplan9}, 53 {"solaris", obj.Hsolaris}, 54 {"windows", obj.Hwindows}, 55 {"windowsgui", obj.Hwindows}, 56 } 57 58 func linknew(arch *LinkArch) *Link { 59 ctxt := &Link{ 60 Hash: []map[string]*LSym{ 61 // preallocate about 2mb for hash of 62 // non static symbols 63 make(map[string]*LSym, 100000), 64 }, 65 Allsym: make([]*LSym, 0, 100000), 66 Arch: arch, 67 Goroot: obj.Getgoroot(), 68 } 69 70 p := obj.Getgoarch() 71 if p != arch.Name { 72 log.Fatalf("invalid goarch %s (want %s)", p, arch.Name) 73 } 74 75 ctxt.Headtype = headtype(obj.Getgoos()) 76 if ctxt.Headtype < 0 { 77 log.Fatalf("unknown goos %s", obj.Getgoos()) 78 } 79 80 // Record thread-local storage offset. 81 // TODO(rsc): Move tlsoffset back into the linker. 82 switch ctxt.Headtype { 83 default: 84 log.Fatalf("unknown thread-local storage offset for %s", Headstr(ctxt.Headtype)) 85 86 case obj.Hplan9, obj.Hwindows: 87 break 88 89 /* 90 * ELF uses TLS offset negative from FS. 91 * Translate 0(FS) and 8(FS) into -16(FS) and -8(FS). 92 * Known to low-level assembly in package runtime and runtime/cgo. 93 */ 94 case obj.Hlinux, 95 obj.Hfreebsd, 96 obj.Hnetbsd, 97 obj.Hopenbsd, 98 obj.Hdragonfly, 99 obj.Hsolaris: 100 if obj.Getgoos() == "android" { 101 switch ctxt.Arch.Thechar { 102 case '6': 103 // Android/amd64 constant - offset from 0(FS) to our TLS slot. 104 // Explained in src/runtime/cgo/gcc_android_*.c 105 ctxt.Tlsoffset = 0x1d0 106 case '8': 107 // Android/386 constant - offset from 0(GS) to our TLS slot. 108 ctxt.Tlsoffset = 0xf8 109 default: 110 ctxt.Tlsoffset = -1 * ctxt.Arch.Ptrsize 111 } 112 } else { 113 ctxt.Tlsoffset = -1 * ctxt.Arch.Ptrsize 114 } 115 116 case obj.Hnacl: 117 switch ctxt.Arch.Thechar { 118 default: 119 log.Fatalf("unknown thread-local storage offset for nacl/%s", ctxt.Arch.Name) 120 121 case '5': 122 ctxt.Tlsoffset = 0 123 124 case '6': 125 ctxt.Tlsoffset = 0 126 127 case '8': 128 ctxt.Tlsoffset = -8 129 } 130 131 /* 132 * OS X system constants - offset from 0(GS) to our TLS. 133 * Explained in src/runtime/cgo/gcc_darwin_*.c. 134 */ 135 case obj.Hdarwin: 136 switch ctxt.Arch.Thechar { 137 default: 138 log.Fatalf("unknown thread-local storage offset for darwin/%s", ctxt.Arch.Name) 139 140 case '5': 141 ctxt.Tlsoffset = 0 // dummy value, not needed 142 143 case '6': 144 ctxt.Tlsoffset = 0x8a0 145 146 case '7': 147 ctxt.Tlsoffset = 0 // dummy value, not needed 148 149 case '8': 150 ctxt.Tlsoffset = 0x468 151 } 152 } 153 154 // On arm, record goarm. 155 if ctxt.Arch.Thechar == '5' { 156 ctxt.Goarm = obj.Getgoarm() 157 } 158 159 return ctxt 160 } 161 162 func linknewsym(ctxt *Link, name string, v int) *LSym { 163 batch := ctxt.LSymBatch 164 if len(batch) == 0 { 165 batch = make([]LSym, 1000) 166 } 167 s := &batch[0] 168 ctxt.LSymBatch = batch[1:] 169 170 s.Dynid = -1 171 s.Plt = -1 172 s.Got = -1 173 s.Name = name 174 s.Version = int16(v) 175 ctxt.Allsym = append(ctxt.Allsym, s) 176 177 return s 178 } 179 180 func Linklookup(ctxt *Link, name string, v int) *LSym { 181 m := ctxt.Hash[v] 182 s := m[name] 183 if s != nil { 184 return s 185 } 186 s = linknewsym(ctxt, name, v) 187 s.Extname = s.Name 188 m[name] = s 189 return s 190 } 191 192 // read-only lookup 193 func Linkrlookup(ctxt *Link, name string, v int) *LSym { 194 return ctxt.Hash[v][name] 195 } 196 197 func Headstr(v int) string { 198 for i := 0; i < len(headers); i++ { 199 if v == headers[i].val { 200 return headers[i].name 201 } 202 } 203 return strconv.Itoa(v) 204 } 205 206 func headtype(name string) int { 207 for i := 0; i < len(headers); i++ { 208 if name == headers[i].name { 209 return headers[i].val 210 } 211 } 212 return -1 213 }