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