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