github.com/zach-klippenstein/go@v0.0.0-20150108044943-fcfbeb3adf58/src/liblink/list6.c (about) 1 // Inferno utils/6c/list.c 2 // http://code.google.com/p/inferno-os/source/browse/utils/6c/list.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 <bio.h> 34 #include <link.h> 35 #include "../cmd/6l/6.out.h" 36 37 // 38 // Format conversions 39 // %A int Opcodes (instruction mnemonics) 40 // 41 // %D Addr* Addresses (instruction operands) 42 // Flags: "%lD": seperate the high and low words of a constant by "-" 43 // 44 // %P Prog* Instructions 45 // 46 // %R int Registers 47 // 48 // %$ char* String constant addresses (for internal use only) 49 50 static int Aconv(Fmt *fp); 51 static int Dconv(Fmt *fp); 52 static int Pconv(Fmt *fp); 53 static int Rconv(Fmt *fp); 54 static int DSconv(Fmt *fp); 55 56 enum 57 { 58 STRINGSZ = 1000 59 }; 60 61 #pragma varargck type "$" char* 62 63 void 64 listinit6(void) 65 { 66 fmtinstall('A', Aconv); 67 fmtinstall('D', Dconv); 68 fmtinstall('P', Pconv); 69 fmtinstall('R', Rconv); 70 71 // for internal use 72 fmtinstall('$', DSconv); 73 } 74 75 static Prog* bigP; 76 77 static int 78 Pconv(Fmt *fp) 79 { 80 char str[STRINGSZ]; 81 Prog *p; 82 83 p = va_arg(fp->args, Prog*); 84 bigP = p; 85 86 if(fp->flags & FmtSharp) { 87 char *s = str; 88 s += sprint(s, "%.5lld (%L) %A", p->pc, p->lineno, p->as); 89 if(p->from.type != D_NONE) 90 s += sprint(s, " from={%#D}", &p->from); 91 if(p->reg) 92 s += sprint(s, " reg=%d", p->reg); 93 if(p->to.type != D_NONE) 94 sprint(s, " to={%#D}", &p->to); 95 return fmtstrcpy(fp, str); 96 } 97 98 switch(p->as) { 99 case ADATA: 100 sprint(str, "%.5lld (%L) %A %D/%d,%D", 101 p->pc, p->lineno, p->as, &p->from, p->from.scale, &p->to); 102 break; 103 104 case ATEXT: 105 if(p->from.scale) { 106 sprint(str, "%.5lld (%L) %A %D,%d,%lD", 107 p->pc, p->lineno, p->as, &p->from, p->from.scale, &p->to); 108 break; 109 } 110 sprint(str, "%.5lld (%L) %A %D,%lD", 111 p->pc, p->lineno, p->as, &p->from, &p->to); 112 break; 113 114 default: 115 sprint(str, "%.5lld (%L) %A %D,%D", 116 p->pc, p->lineno, p->as, &p->from, &p->to); 117 break; 118 } 119 bigP = nil; 120 return fmtstrcpy(fp, str); 121 } 122 123 static int 124 Aconv(Fmt *fp) 125 { 126 int i; 127 128 i = va_arg(fp->args, int); 129 return fmtstrcpy(fp, anames6[i]); 130 } 131 132 static int 133 Dconv(Fmt *fp) 134 { 135 char str[STRINGSZ], s[STRINGSZ]; 136 Addr *a; 137 int i; 138 139 a = va_arg(fp->args, Addr*); 140 i = a->type; 141 142 if(fp->flags & FmtSharp) { 143 char *s = str; 144 s += sprint(s, "type="); 145 if(i == D_NONE) { 146 sprint(s, "NONE"); 147 goto brk; 148 } 149 if(i >= D_INDIR) { 150 i -= D_INDIR; 151 s += sprint(s, "INDIR+"); 152 } 153 if(i >= 0 && i < D_LAST && dnames6[i] != nil) 154 s += sprint(s, "%s ", dnames6[i]); 155 else 156 s += sprint(s, "%d ", i); 157 s += sprint(s, "offset=%lld etype=%E width=%lld", a->offset, a->etype, a->width); 158 if(a->sym != nil) 159 s += sprint(s, " sym=%s", a->sym->name); 160 if(a->type == D_BRANCH && a->u.branch != nil) 161 sprint(s, " branch=%.5lld", a->u.branch->pc); 162 goto brk; 163 } 164 165 if(fp->flags & FmtLong) { 166 if(i == D_CONST) 167 sprint(str, "$%lld-%lld", a->offset&0xffffffffLL, a->offset>>32); 168 else { 169 // ATEXT dst is not constant 170 sprint(str, "!!%D", a); 171 } 172 goto brk; 173 } 174 175 if(i >= D_INDIR) { 176 if(a->offset) 177 sprint(str, "%lld(%R)", a->offset, i-D_INDIR); 178 else 179 sprint(str, "(%R)", i-D_INDIR); 180 goto brk; 181 } 182 switch(i) { 183 default: 184 if(a->offset) 185 sprint(str, "$%lld,%R", a->offset, i); 186 else 187 sprint(str, "%R", i); 188 break; 189 190 case D_NONE: 191 str[0] = 0; 192 break; 193 194 case D_BRANCH: 195 if(a->sym != nil) 196 sprint(str, "%s(SB)", a->sym->name); 197 else if(bigP != nil && bigP->pcond != nil) 198 sprint(str, "%lld", bigP->pcond->pc); 199 else if(a->u.branch != nil) 200 sprint(str, "%lld", a->u.branch->pc); 201 else 202 sprint(str, "%lld(PC)", a->offset); 203 break; 204 205 case D_EXTERN: 206 sprint(str, "%s+%lld(SB)", a->sym->name, a->offset); 207 break; 208 209 case D_STATIC: 210 sprint(str, "%s<>+%lld(SB)", a->sym->name, a->offset); 211 break; 212 213 case D_AUTO: 214 if(a->sym) 215 sprint(str, "%s+%lld(SP)", a->sym->name, a->offset); 216 else 217 sprint(str, "%lld(SP)", a->offset); 218 break; 219 220 case D_PARAM: 221 if(a->sym) 222 sprint(str, "%s+%lld(FP)", a->sym->name, a->offset); 223 else 224 sprint(str, "%lld(FP)", a->offset); 225 break; 226 227 case D_CONST: 228 sprint(str, "$%lld", a->offset); 229 break; 230 231 case D_FCONST: 232 sprint(str, "$(%.17g)", a->u.dval); 233 break; 234 235 case D_SCONST: 236 sprint(str, "$\"%$\"", a->u.sval); 237 break; 238 239 case D_ADDR: 240 a->type = a->index; 241 a->index = D_NONE; 242 sprint(str, "$%D", a); 243 a->index = a->type; 244 a->type = D_ADDR; 245 goto conv; 246 } 247 brk: 248 if(a->index != D_NONE) { 249 sprint(s, "(%R*%d)", (int)a->index, (int)a->scale); 250 strcat(str, s); 251 } 252 conv: 253 return fmtstrcpy(fp, str); 254 } 255 256 static char* regstr[] = 257 { 258 "AL", /* [D_AL] */ 259 "CL", 260 "DL", 261 "BL", 262 "SPB", 263 "BPB", 264 "SIB", 265 "DIB", 266 "R8B", 267 "R9B", 268 "R10B", 269 "R11B", 270 "R12B", 271 "R13B", 272 "R14B", 273 "R15B", 274 275 "AX", /* [D_AX] */ 276 "CX", 277 "DX", 278 "BX", 279 "SP", 280 "BP", 281 "SI", 282 "DI", 283 "R8", 284 "R9", 285 "R10", 286 "R11", 287 "R12", 288 "R13", 289 "R14", 290 "R15", 291 292 "AH", 293 "CH", 294 "DH", 295 "BH", 296 297 "F0", /* [D_F0] */ 298 "F1", 299 "F2", 300 "F3", 301 "F4", 302 "F5", 303 "F6", 304 "F7", 305 306 "M0", 307 "M1", 308 "M2", 309 "M3", 310 "M4", 311 "M5", 312 "M6", 313 "M7", 314 315 "X0", 316 "X1", 317 "X2", 318 "X3", 319 "X4", 320 "X5", 321 "X6", 322 "X7", 323 "X8", 324 "X9", 325 "X10", 326 "X11", 327 "X12", 328 "X13", 329 "X14", 330 "X15", 331 332 "CS", /* [D_CS] */ 333 "SS", 334 "DS", 335 "ES", 336 "FS", 337 "GS", 338 339 "GDTR", /* [D_GDTR] */ 340 "IDTR", /* [D_IDTR] */ 341 "LDTR", /* [D_LDTR] */ 342 "MSW", /* [D_MSW] */ 343 "TASK", /* [D_TASK] */ 344 345 "CR0", /* [D_CR] */ 346 "CR1", 347 "CR2", 348 "CR3", 349 "CR4", 350 "CR5", 351 "CR6", 352 "CR7", 353 "CR8", 354 "CR9", 355 "CR10", 356 "CR11", 357 "CR12", 358 "CR13", 359 "CR14", 360 "CR15", 361 362 "DR0", /* [D_DR] */ 363 "DR1", 364 "DR2", 365 "DR3", 366 "DR4", 367 "DR5", 368 "DR6", 369 "DR7", 370 371 "TR0", /* [D_TR] */ 372 "TR1", 373 "TR2", 374 "TR3", 375 "TR4", 376 "TR5", 377 "TR6", 378 "TR7", 379 380 "TLS", /* [D_TLS] */ 381 "NONE", /* [D_NONE] */ 382 }; 383 384 static int 385 Rconv(Fmt *fp) 386 { 387 char str[STRINGSZ]; 388 int r; 389 390 r = va_arg(fp->args, int); 391 if(r >= D_AL && r <= D_NONE) 392 sprint(str, "%s", regstr[r-D_AL]); 393 else 394 sprint(str, "gok(%d)", r); 395 396 return fmtstrcpy(fp, str); 397 } 398 399 static int 400 DSconv(Fmt *fp) 401 { 402 int i, c; 403 char str[STRINGSZ], *p, *a; 404 405 a = va_arg(fp->args, char*); 406 p = str; 407 for(i=0; i<sizeof(double); i++) { 408 c = a[i] & 0xff; 409 if(c >= 'a' && c <= 'z' || 410 c >= 'A' && c <= 'Z' || 411 c >= '0' && c <= '9') { 412 *p++ = c; 413 continue; 414 } 415 *p++ = '\\'; 416 switch(c) { 417 default: 418 if(c < 040 || c >= 0177) 419 break; /* not portable */ 420 p[-1] = c; 421 continue; 422 case 0: 423 *p++ = 'z'; 424 continue; 425 case '\\': 426 case '"': 427 *p++ = c; 428 continue; 429 case '\n': 430 *p++ = 'n'; 431 continue; 432 case '\t': 433 *p++ = 't'; 434 continue; 435 } 436 *p++ = (c>>6) + '0'; 437 *p++ = ((c>>3) & 7) + '0'; 438 *p++ = (c & 7) + '0'; 439 } 440 *p = 0; 441 return fmtstrcpy(fp, str); 442 }