github.com/tcnksm/go@v0.0.0-20141208075154-439b32936367/src/liblink/sym.c (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 #include <u.h> 33 #include <libc.h> 34 #include <bio.h> 35 #include <link.h> 36 37 static int 38 yy_isalpha(int c) 39 { 40 return c >= 0 && c <= 0xFF && isalpha(c); 41 } 42 43 static struct { 44 char *name; 45 int val; 46 } headers[] = { 47 {"android", Hlinux}, 48 {"darwin", Hdarwin}, 49 {"dragonfly", Hdragonfly}, 50 {"elf", Helf}, 51 {"freebsd", Hfreebsd}, 52 {"linux", Hlinux}, 53 {"nacl", Hnacl}, 54 {"netbsd", Hnetbsd}, 55 {"openbsd", Hopenbsd}, 56 {"plan9", Hplan9}, 57 {"solaris", Hsolaris}, 58 {"windows", Hwindows}, 59 {"windowsgui", Hwindows}, 60 {0, 0}, 61 }; 62 63 int 64 headtype(char *name) 65 { 66 int i; 67 68 for(i=0; headers[i].name; i++) 69 if(strcmp(name, headers[i].name) == 0) 70 return headers[i].val; 71 return -1; 72 } 73 74 char* 75 headstr(int v) 76 { 77 static char buf[20]; 78 int i; 79 80 for(i=0; headers[i].name; i++) 81 if(v == headers[i].val) 82 return headers[i].name; 83 snprint(buf, sizeof buf, "%d", v); 84 return buf; 85 } 86 87 Link* 88 linknew(LinkArch *arch) 89 { 90 Link *ctxt; 91 char *p; 92 char buf[1024]; 93 94 nuxiinit(arch); 95 96 ctxt = emallocz(sizeof *ctxt); 97 ctxt->arch = arch; 98 ctxt->version = HistVersion; 99 ctxt->goroot = getgoroot(); 100 ctxt->goroot_final = getenv("GOROOT_FINAL"); 101 if(ctxt->goroot_final != nil && ctxt->goroot_final[0] == '\0') 102 ctxt->goroot_final = nil; 103 104 p = getgoarch(); 105 if(strcmp(p, arch->name) != 0) 106 sysfatal("invalid goarch %s (want %s)", p, arch->name); 107 108 if(getwd(buf, sizeof buf) == 0) 109 strcpy(buf, "/???"); 110 if(yy_isalpha(buf[0]) && buf[1] == ':') { 111 // On Windows. 112 ctxt->windows = 1; 113 114 // Canonicalize path by converting \ to / (Windows accepts both). 115 for(p=buf; *p; p++) 116 if(*p == '\\') 117 *p = '/'; 118 } 119 ctxt->pathname = strdup(buf); 120 121 ctxt->headtype = headtype(getgoos()); 122 if(ctxt->headtype < 0) 123 sysfatal("unknown goos %s", getgoos()); 124 125 // Record thread-local storage offset. 126 // TODO(rsc): Move tlsoffset back into the linker. 127 switch(ctxt->headtype) { 128 default: 129 sysfatal("unknown thread-local storage offset for %s", headstr(ctxt->headtype)); 130 case Hplan9: 131 case Hwindows: 132 break; 133 case Hlinux: 134 case Hfreebsd: 135 case Hnetbsd: 136 case Hopenbsd: 137 case Hdragonfly: 138 case Hsolaris: 139 /* 140 * ELF uses TLS offset negative from FS. 141 * Translate 0(FS) and 8(FS) into -16(FS) and -8(FS). 142 * Known to low-level assembly in package runtime and runtime/cgo. 143 */ 144 ctxt->tlsoffset = -2*ctxt->arch->ptrsize; 145 break; 146 147 case Hnacl: 148 switch(ctxt->arch->thechar) { 149 default: 150 sysfatal("unknown thread-local storage offset for nacl/%s", ctxt->arch->name); 151 case '6': 152 ctxt->tlsoffset = 0; 153 break; 154 case '8': 155 ctxt->tlsoffset = -8; 156 break; 157 case '5': 158 ctxt->tlsoffset = 0; 159 break; 160 } 161 break; 162 163 case Hdarwin: 164 /* 165 * OS X system constants - offset from 0(GS) to our TLS. 166 * Explained in ../../runtime/cgo/gcc_darwin_*.c. 167 */ 168 switch(ctxt->arch->thechar) { 169 default: 170 sysfatal("unknown thread-local storage offset for darwin/%s", ctxt->arch->name); 171 case '6': 172 ctxt->tlsoffset = 0x8a0; 173 break; 174 case '8': 175 ctxt->tlsoffset = 0x468; 176 break; 177 } 178 break; 179 } 180 181 // On arm, record goarm. 182 if(ctxt->arch->thechar == '5') { 183 p = getgoarm(); 184 if(p != nil) 185 ctxt->goarm = atoi(p); 186 else 187 ctxt->goarm = 6; 188 } 189 190 return ctxt; 191 } 192 193 LSym* 194 linknewsym(Link *ctxt, char *symb, int v) 195 { 196 LSym *s; 197 198 s = malloc(sizeof(*s)); 199 memset(s, 0, sizeof(*s)); 200 201 s->dynid = -1; 202 s->plt = -1; 203 s->got = -1; 204 s->name = estrdup(symb); 205 s->type = 0; 206 s->version = v; 207 s->value = 0; 208 s->sig = 0; 209 s->size = 0; 210 ctxt->nsymbol++; 211 212 s->allsym = ctxt->allsym; 213 ctxt->allsym = s; 214 215 return s; 216 } 217 218 static LSym* 219 _lookup(Link *ctxt, char *symb, int v, int creat) 220 { 221 LSym *s; 222 char *p; 223 uint32 h; 224 int c; 225 226 h = v; 227 for(p=symb; c = *p; p++) 228 h = h+h+h + c; 229 h &= 0xffffff; 230 h %= LINKHASH; 231 for(s = ctxt->hash[h]; s != nil; s = s->hash) 232 if(s->version == v && strcmp(s->name, symb) == 0) 233 return s; 234 if(!creat) 235 return nil; 236 237 s = linknewsym(ctxt, symb, v); 238 s->extname = s->name; 239 s->hash = ctxt->hash[h]; 240 ctxt->hash[h] = s; 241 242 return s; 243 } 244 245 LSym* 246 linklookup(Link *ctxt, char *name, int v) 247 { 248 return _lookup(ctxt, name, v, 1); 249 } 250 251 // read-only lookup 252 LSym* 253 linkrlookup(Link *ctxt, char *name, int v) 254 { 255 return _lookup(ctxt, name, v, 0); 256 } 257 258 int 259 linksymfmt(Fmt *f) 260 { 261 LSym *s; 262 263 s = va_arg(f->args, LSym*); 264 if(s == nil) 265 return fmtstrcpy(f, "<nil>"); 266 267 return fmtstrcpy(f, s->name); 268 }