github.com/spotify/syslog-redirector-golang@v0.0.0-20140320174030-4859f03d829a/src/cmd/8g/gobj.c (about) 1 // Derived from Inferno utils/8c/swt.c 2 // http://code.google.com/p/inferno-os/source/browse/utils/8c/swt.c 3 // 4 // Copyright © 1994-1999 Lucent Technologies Inc. All rights reserved. 5 // Portions Copyright © 1995-1997 C H Forsyth (forsyth@terzarima.net) 6 // Portions Copyright © 1997-1999 Vita Nuova Limited 7 // Portions Copyright © 2000-2007 Vita Nuova Holdings Limited (www.vitanuova.com) 8 // Portions Copyright © 2004,2006 Bruce Ellis 9 // Portions Copyright © 2005-2007 C H Forsyth (forsyth@terzarima.net) 10 // Revisions Copyright © 2000-2007 Lucent Technologies Inc. and others 11 // Portions Copyright © 2009 The Go Authors. All rights reserved. 12 // 13 // Permission is hereby granted, free of charge, to any person obtaining a copy 14 // of this software and associated documentation files (the "Software"), to deal 15 // in the Software without restriction, including without limitation the rights 16 // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 17 // copies of the Software, and to permit persons to whom the Software is 18 // furnished to do so, subject to the following conditions: 19 // 20 // The above copyright notice and this permission notice shall be included in 21 // all copies or substantial portions of the Software. 22 // 23 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 24 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 25 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 26 // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 27 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 28 // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 29 // THE SOFTWARE. 30 31 #include <u.h> 32 #include <libc.h> 33 #include "gg.h" 34 35 void 36 zname(Biobuf *b, Sym *s, int t) 37 { 38 BPUTLE2(b, ANAME); /* as */ 39 BPUTC(b, t); /* type */ 40 BPUTC(b, s->sym); /* sym */ 41 42 Bputname(b, s); 43 } 44 45 void 46 zfile(Biobuf *b, char *p, int n) 47 { 48 BPUTLE2(b, ANAME); 49 BPUTC(b, D_FILE); 50 BPUTC(b, 1); 51 BPUTC(b, '<'); 52 Bwrite(b, p, n); 53 BPUTC(b, 0); 54 } 55 56 void 57 zhist(Biobuf *b, int line, vlong offset) 58 { 59 Addr a; 60 61 BPUTLE2(b, AHISTORY); 62 BPUTLE4(b, line); 63 zaddr(b, &zprog.from, 0, 0); 64 a = zprog.to; 65 if(offset != 0) { 66 a.offset = offset; 67 a.type = D_CONST; 68 } 69 zaddr(b, &a, 0, 0); 70 } 71 72 void 73 zaddr(Biobuf *b, Addr *a, int s, int gotype) 74 { 75 int32 l; 76 uint64 e; 77 int i, t; 78 char *n; 79 80 t = 0; 81 if(a->index != D_NONE || a->scale != 0) 82 t |= T_INDEX; 83 if(s != 0) 84 t |= T_SYM; 85 if(gotype != 0) 86 t |= T_GOTYPE; 87 88 switch(a->type) { 89 90 case D_BRANCH: 91 if(a->u.branch == nil) 92 fatal("unpatched branch"); 93 a->offset = a->u.branch->loc; 94 95 default: 96 t |= T_TYPE; 97 98 case D_NONE: 99 if(a->offset != 0) 100 t |= T_OFFSET; 101 if(a->offset2 != 0) 102 t |= T_OFFSET2; 103 break; 104 case D_FCONST: 105 t |= T_FCONST; 106 break; 107 case D_SCONST: 108 t |= T_SCONST; 109 break; 110 } 111 BPUTC(b, t); 112 113 if(t & T_INDEX) { /* implies index, scale */ 114 BPUTC(b, a->index); 115 BPUTC(b, a->scale); 116 } 117 if(t & T_OFFSET) { /* implies offset */ 118 l = a->offset; 119 BPUTLE4(b, l); 120 } 121 if(t & T_OFFSET2) { /* implies offset */ 122 l = a->offset2; 123 BPUTLE4(b, l); 124 } 125 if(t & T_SYM) /* implies sym */ 126 BPUTC(b, s); 127 if(t & T_FCONST) { 128 ieeedtod(&e, a->u.dval); 129 BPUTLE4(b, e); 130 BPUTLE4(b, e >> 32); 131 return; 132 } 133 if(t & T_SCONST) { 134 n = a->u.sval; 135 for(i=0; i<NSNAME; i++) { 136 BPUTC(b, *n); 137 n++; 138 } 139 return; 140 } 141 if(t & T_TYPE) 142 BPUTC(b, a->type); 143 if(t & T_GOTYPE) 144 BPUTC(b, gotype); 145 } 146 147 static struct { 148 struct { Sym *sym; short type; } h[NSYM]; 149 int sym; 150 } z; 151 152 static void 153 zsymreset(void) 154 { 155 for(z.sym=0; z.sym<NSYM; z.sym++) { 156 z.h[z.sym].sym = S; 157 z.h[z.sym].type = 0; 158 } 159 z.sym = 1; 160 } 161 162 static int 163 zsym(Sym *s, int t, int *new) 164 { 165 int i; 166 167 *new = 0; 168 if(s == S) 169 return 0; 170 171 i = s->sym; 172 if(i < 0 || i >= NSYM) 173 i = 0; 174 if(z.h[i].type == t && z.h[i].sym == s) 175 return i; 176 i = z.sym; 177 s->sym = i; 178 zname(bout, s, t); 179 z.h[i].sym = s; 180 z.h[i].type = t; 181 if(++z.sym >= NSYM) 182 z.sym = 1; 183 *new = 1; 184 return i; 185 } 186 187 static int 188 zsymaddr(Addr *a, int *new) 189 { 190 int t; 191 192 t = a->type; 193 if(t == D_ADDR) 194 t = a->index; 195 return zsym(a->sym, t, new); 196 } 197 198 void 199 dumpfuncs(void) 200 { 201 Plist *pl; 202 int sf, st, gf, gt, new; 203 Sym *s; 204 Prog *p; 205 206 zsymreset(); 207 208 // fix up pc 209 pcloc = 0; 210 for(pl=plist; pl!=nil; pl=pl->link) { 211 if(isblank(pl->name)) 212 continue; 213 for(p=pl->firstpc; p!=P; p=p->link) { 214 p->loc = pcloc; 215 if(p->as != ADATA && p->as != AGLOBL) 216 pcloc++; 217 } 218 } 219 220 // put out functions 221 for(pl=plist; pl!=nil; pl=pl->link) { 222 if(isblank(pl->name)) 223 continue; 224 225 // -S prints code; -SS prints code and data 226 if(debug['S'] && (pl->name || debug['S']>1)) { 227 s = S; 228 if(pl->name != N) 229 s = pl->name->sym; 230 print("\n--- prog list \"%S\" ---\n", s); 231 for(p=pl->firstpc; p!=P; p=p->link) 232 print("%P\n", p); 233 } 234 235 for(p=pl->firstpc; p!=P; p=p->link) { 236 for(;;) { 237 sf = zsymaddr(&p->from, &new); 238 gf = zsym(p->from.gotype, D_EXTERN, &new); 239 if(new && sf == gf) 240 continue; 241 st = zsymaddr(&p->to, &new); 242 if(new && (st == sf || st == gf)) 243 continue; 244 gt = zsym(p->to.gotype, D_EXTERN, &new); 245 if(new && (gt == sf || gt == gf || gt == st)) 246 continue; 247 break; 248 } 249 250 BPUTLE2(bout, p->as); 251 BPUTLE4(bout, p->lineno); 252 zaddr(bout, &p->from, sf, gf); 253 zaddr(bout, &p->to, st, gt); 254 } 255 } 256 } 257 258 int 259 dsname(Sym *s, int off, char *t, int n) 260 { 261 Prog *p; 262 263 p = gins(ADATA, N, N); 264 p->from.type = D_EXTERN; 265 p->from.index = D_NONE; 266 p->from.offset = off; 267 p->from.scale = n; 268 p->from.sym = s; 269 270 p->to.type = D_SCONST; 271 p->to.index = D_NONE; 272 memmove(p->to.u.sval, t, n); 273 return off + n; 274 } 275 276 /* 277 * make a refer to the data s, s+len 278 * emitting DATA if needed. 279 */ 280 void 281 datastring(char *s, int len, Addr *a) 282 { 283 Sym *sym; 284 285 sym = stringsym(s, len); 286 a->type = D_EXTERN; 287 a->sym = sym; 288 a->node = sym->def; 289 a->offset = widthptr+4; // skip header 290 a->etype = TINT32; 291 } 292 293 /* 294 * make a refer to the string sval, 295 * emitting DATA if needed. 296 */ 297 void 298 datagostring(Strlit *sval, Addr *a) 299 { 300 Sym *sym; 301 302 sym = stringsym(sval->s, sval->len); 303 a->type = D_EXTERN; 304 a->sym = sym; 305 a->node = sym->def; 306 a->offset = 0; // header 307 a->etype = TINT32; 308 } 309 310 void 311 gdata(Node *nam, Node *nr, int wid) 312 { 313 Prog *p; 314 vlong v; 315 316 if(nr->op == OLITERAL) { 317 switch(nr->val.ctype) { 318 case CTCPLX: 319 gdatacomplex(nam, nr->val.u.cval); 320 return; 321 case CTSTR: 322 gdatastring(nam, nr->val.u.sval); 323 return; 324 } 325 } 326 327 if(wid == 8 && is64(nr->type)) { 328 v = mpgetfix(nr->val.u.xval); 329 p = gins(ADATA, nam, nodintconst(v)); 330 p->from.scale = 4; 331 p = gins(ADATA, nam, nodintconst(v>>32)); 332 p->from.scale = 4; 333 p->from.offset += 4; 334 return; 335 } 336 p = gins(ADATA, nam, nr); 337 p->from.scale = wid; 338 } 339 340 void 341 gdatacomplex(Node *nam, Mpcplx *cval) 342 { 343 Prog *p; 344 int w; 345 346 w = cplxsubtype(nam->type->etype); 347 w = types[w]->width; 348 349 p = gins(ADATA, nam, N); 350 p->from.scale = w; 351 p->to.type = D_FCONST; 352 p->to.u.dval = mpgetflt(&cval->real); 353 354 p = gins(ADATA, nam, N); 355 p->from.scale = w; 356 p->from.offset += w; 357 p->to.type = D_FCONST; 358 p->to.u.dval = mpgetflt(&cval->imag); 359 } 360 361 void 362 gdatastring(Node *nam, Strlit *sval) 363 { 364 Prog *p; 365 Node nod1; 366 367 p = gins(ADATA, nam, N); 368 datastring(sval->s, sval->len, &p->to); 369 p->from.scale = types[tptr]->width; 370 p->to.index = p->to.type; 371 p->to.type = D_ADDR; 372 //print("%P\n", p); 373 374 nodconst(&nod1, types[TINT32], sval->len); 375 p = gins(ADATA, nam, &nod1); 376 p->from.scale = types[TINT32]->width; 377 p->from.offset += types[tptr]->width; 378 } 379 380 int 381 dstringptr(Sym *s, int off, char *str) 382 { 383 Prog *p; 384 385 off = rnd(off, widthptr); 386 p = gins(ADATA, N, N); 387 p->from.type = D_EXTERN; 388 p->from.index = D_NONE; 389 p->from.sym = s; 390 p->from.offset = off; 391 p->from.scale = widthptr; 392 393 datastring(str, strlen(str)+1, &p->to); 394 p->to.index = p->to.type; 395 p->to.type = D_ADDR; 396 p->to.etype = TINT32; 397 off += widthptr; 398 399 return off; 400 } 401 402 int 403 dgostrlitptr(Sym *s, int off, Strlit *lit) 404 { 405 Prog *p; 406 407 if(lit == nil) 408 return duintptr(s, off, 0); 409 410 off = rnd(off, widthptr); 411 p = gins(ADATA, N, N); 412 p->from.type = D_EXTERN; 413 p->from.index = D_NONE; 414 p->from.sym = s; 415 p->from.offset = off; 416 p->from.scale = widthptr; 417 datagostring(lit, &p->to); 418 p->to.index = p->to.type; 419 p->to.type = D_ADDR; 420 p->to.etype = TINT32; 421 off += widthptr; 422 423 return off; 424 } 425 426 int 427 dgostringptr(Sym *s, int off, char *str) 428 { 429 int n; 430 Strlit *lit; 431 432 if(str == nil) 433 return duintptr(s, off, 0); 434 435 n = strlen(str); 436 lit = mal(sizeof *lit + n); 437 strcpy(lit->s, str); 438 lit->len = n; 439 return dgostrlitptr(s, off, lit); 440 } 441 442 443 int 444 duintxx(Sym *s, int off, uint64 v, int wid) 445 { 446 Prog *p; 447 448 off = rnd(off, wid); 449 450 p = gins(ADATA, N, N); 451 p->from.type = D_EXTERN; 452 p->from.index = D_NONE; 453 p->from.sym = s; 454 p->from.offset = off; 455 p->from.scale = wid; 456 p->to.type = D_CONST; 457 p->to.index = D_NONE; 458 p->to.offset = v; 459 off += wid; 460 461 return off; 462 } 463 464 int 465 dsymptr(Sym *s, int off, Sym *x, int xoff) 466 { 467 Prog *p; 468 469 off = rnd(off, widthptr); 470 471 p = gins(ADATA, N, N); 472 p->from.type = D_EXTERN; 473 p->from.index = D_NONE; 474 p->from.sym = s; 475 p->from.offset = off; 476 p->from.scale = widthptr; 477 p->to.type = D_ADDR; 478 p->to.index = D_EXTERN; 479 p->to.sym = x; 480 p->to.offset = xoff; 481 off += widthptr; 482 483 return off; 484 } 485 486 void 487 nopout(Prog *p) 488 { 489 p->as = ANOP; 490 } 491