github.com/bgentry/go@v0.0.0-20150121062915-6cf5a733d54d/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 switch(p->as) { 87 case ADATA: 88 sprint(str, "%.5lld (%L) %A %D/%d,%D", 89 p->pc, p->lineno, p->as, &p->from, p->from.scale, &p->to); 90 break; 91 92 case ATEXT: 93 if(p->from.scale) { 94 sprint(str, "%.5lld (%L) %A %D,%d,%lD", 95 p->pc, p->lineno, p->as, &p->from, p->from.scale, &p->to); 96 break; 97 } 98 sprint(str, "%.5lld (%L) %A %D,%lD", 99 p->pc, p->lineno, p->as, &p->from, &p->to); 100 break; 101 102 default: 103 sprint(str, "%.5lld (%L) %A %D,%D", 104 p->pc, p->lineno, p->as, &p->from, &p->to); 105 break; 106 } 107 bigP = nil; 108 return fmtstrcpy(fp, str); 109 } 110 111 static int 112 Aconv(Fmt *fp) 113 { 114 int i; 115 116 i = va_arg(fp->args, int); 117 return fmtstrcpy(fp, anames6[i]); 118 } 119 120 static int 121 Dconv(Fmt *fp) 122 { 123 char str[STRINGSZ], s[STRINGSZ]; 124 Addr *a; 125 int i; 126 127 a = va_arg(fp->args, Addr*); 128 i = a->type; 129 130 if(fp->flags & FmtLong) { 131 if(i == D_CONST) 132 sprint(str, "$%lld-%lld", a->offset&0xffffffffLL, a->offset>>32); 133 else { 134 // ATEXT dst is not constant 135 sprint(str, "!!%D", a); 136 } 137 goto brk; 138 } 139 140 if(i >= D_INDIR) { 141 if(a->offset) 142 sprint(str, "%lld(%R)", a->offset, i-D_INDIR); 143 else 144 sprint(str, "(%R)", i-D_INDIR); 145 goto brk; 146 } 147 switch(i) { 148 default: 149 if(a->offset) 150 sprint(str, "$%lld,%R", a->offset, i); 151 else 152 sprint(str, "%R", i); 153 break; 154 155 case D_NONE: 156 str[0] = 0; 157 break; 158 159 case D_BRANCH: 160 if(a->sym != nil) 161 sprint(str, "%s(SB)", a->sym->name); 162 else if(bigP != nil && bigP->pcond != nil) 163 sprint(str, "%lld", bigP->pcond->pc); 164 else if(a->u.branch != nil) 165 sprint(str, "%lld", a->u.branch->pc); 166 else 167 sprint(str, "%lld(PC)", a->offset); 168 break; 169 170 case D_EXTERN: 171 sprint(str, "%s+%lld(SB)", a->sym->name, a->offset); 172 break; 173 174 case D_STATIC: 175 sprint(str, "%s<>+%lld(SB)", a->sym->name, a->offset); 176 break; 177 178 case D_AUTO: 179 if(a->sym) 180 sprint(str, "%s+%lld(SP)", a->sym->name, a->offset); 181 else 182 sprint(str, "%lld(SP)", a->offset); 183 break; 184 185 case D_PARAM: 186 if(a->sym) 187 sprint(str, "%s+%lld(FP)", a->sym->name, a->offset); 188 else 189 sprint(str, "%lld(FP)", a->offset); 190 break; 191 192 case D_CONST: 193 sprint(str, "$%lld", a->offset); 194 break; 195 196 case D_FCONST: 197 sprint(str, "$(%.17g)", a->u.dval); 198 break; 199 200 case D_SCONST: 201 sprint(str, "$\"%$\"", a->u.sval); 202 break; 203 204 case D_ADDR: 205 a->type = a->index; 206 a->index = D_NONE; 207 sprint(str, "$%D", a); 208 a->index = a->type; 209 a->type = D_ADDR; 210 goto conv; 211 } 212 brk: 213 if(a->index != D_NONE) { 214 sprint(s, "(%R*%d)", (int)a->index, (int)a->scale); 215 strcat(str, s); 216 } 217 conv: 218 return fmtstrcpy(fp, str); 219 } 220 221 static char* regstr[] = 222 { 223 "AL", /* [D_AL] */ 224 "CL", 225 "DL", 226 "BL", 227 "SPB", 228 "BPB", 229 "SIB", 230 "DIB", 231 "R8B", 232 "R9B", 233 "R10B", 234 "R11B", 235 "R12B", 236 "R13B", 237 "R14B", 238 "R15B", 239 240 "AX", /* [D_AX] */ 241 "CX", 242 "DX", 243 "BX", 244 "SP", 245 "BP", 246 "SI", 247 "DI", 248 "R8", 249 "R9", 250 "R10", 251 "R11", 252 "R12", 253 "R13", 254 "R14", 255 "R15", 256 257 "AH", 258 "CH", 259 "DH", 260 "BH", 261 262 "F0", /* [D_F0] */ 263 "F1", 264 "F2", 265 "F3", 266 "F4", 267 "F5", 268 "F6", 269 "F7", 270 271 "M0", 272 "M1", 273 "M2", 274 "M3", 275 "M4", 276 "M5", 277 "M6", 278 "M7", 279 280 "X0", 281 "X1", 282 "X2", 283 "X3", 284 "X4", 285 "X5", 286 "X6", 287 "X7", 288 "X8", 289 "X9", 290 "X10", 291 "X11", 292 "X12", 293 "X13", 294 "X14", 295 "X15", 296 297 "CS", /* [D_CS] */ 298 "SS", 299 "DS", 300 "ES", 301 "FS", 302 "GS", 303 304 "GDTR", /* [D_GDTR] */ 305 "IDTR", /* [D_IDTR] */ 306 "LDTR", /* [D_LDTR] */ 307 "MSW", /* [D_MSW] */ 308 "TASK", /* [D_TASK] */ 309 310 "CR0", /* [D_CR] */ 311 "CR1", 312 "CR2", 313 "CR3", 314 "CR4", 315 "CR5", 316 "CR6", 317 "CR7", 318 "CR8", 319 "CR9", 320 "CR10", 321 "CR11", 322 "CR12", 323 "CR13", 324 "CR14", 325 "CR15", 326 327 "DR0", /* [D_DR] */ 328 "DR1", 329 "DR2", 330 "DR3", 331 "DR4", 332 "DR5", 333 "DR6", 334 "DR7", 335 336 "TR0", /* [D_TR] */ 337 "TR1", 338 "TR2", 339 "TR3", 340 "TR4", 341 "TR5", 342 "TR6", 343 "TR7", 344 345 "TLS", /* [D_TLS] */ 346 "NONE", /* [D_NONE] */ 347 }; 348 349 static int 350 Rconv(Fmt *fp) 351 { 352 char str[STRINGSZ]; 353 int r; 354 355 r = va_arg(fp->args, int); 356 if(r >= D_AL && r <= D_NONE) 357 sprint(str, "%s", regstr[r-D_AL]); 358 else 359 sprint(str, "gok(%d)", r); 360 361 return fmtstrcpy(fp, str); 362 } 363 364 static int 365 DSconv(Fmt *fp) 366 { 367 int i, c; 368 char str[STRINGSZ], *p, *a; 369 370 a = va_arg(fp->args, char*); 371 p = str; 372 for(i=0; i<sizeof(double); i++) { 373 c = a[i] & 0xff; 374 if(c >= 'a' && c <= 'z' || 375 c >= 'A' && c <= 'Z' || 376 c >= '0' && c <= '9') { 377 *p++ = c; 378 continue; 379 } 380 *p++ = '\\'; 381 switch(c) { 382 default: 383 if(c < 040 || c >= 0177) 384 break; /* not portable */ 385 p[-1] = c; 386 continue; 387 case 0: 388 *p++ = 'z'; 389 continue; 390 case '\\': 391 case '"': 392 *p++ = c; 393 continue; 394 case '\n': 395 *p++ = 'n'; 396 continue; 397 case '\t': 398 *p++ = 't'; 399 continue; 400 } 401 *p++ = (c>>6) + '0'; 402 *p++ = ((c>>3) & 7) + '0'; 403 *p++ = (c & 7) + '0'; 404 } 405 *p = 0; 406 return fmtstrcpy(fp, str); 407 }