1implement Dis; 2 3# 4# Derived by Vita Nuova Limited 1998 from /appl/wm/rt.b, which is 5# Copyright © 1996-1999 Lucent Technologies Inc. All rights reserved. 6# 7 8include "sys.m"; 9 sys: Sys; 10 sprint: import sys; 11 12include "math.m"; 13 math: Math; 14 15include "dis.m"; 16 17disptr: int; 18disobj: array of byte; 19 20optab := array[] of { 21 "nop", 22 "alt", 23 "nbalt", 24 "goto", 25 "call", 26 "frame", 27 "spawn", 28 "runt", 29 "load", 30 "mcall", 31 "mspawn", 32 "mframe", 33 "ret", 34 "jmp", 35 "case", 36 "exit", 37 "new", 38 "newa", 39 "newcb", 40 "newcw", 41 "newcf", 42 "newcp", 43 "newcm", 44 "newcmp", 45 "send", 46 "recv", 47 "consb", 48 "consw", 49 "consp", 50 "consf", 51 "consm", 52 "consmp", 53 "headb", 54 "headw", 55 "headp", 56 "headf", 57 "headm", 58 "headmp", 59 "tail", 60 "lea", 61 "indx", 62 "movp", 63 "movm", 64 "movmp", 65 "movb", 66 "movw", 67 "movf", 68 "cvtbw", 69 "cvtwb", 70 "cvtfw", 71 "cvtwf", 72 "cvtca", 73 "cvtac", 74 "cvtwc", 75 "cvtcw", 76 "cvtfc", 77 "cvtcf", 78 "addb", 79 "addw", 80 "addf", 81 "subb", 82 "subw", 83 "subf", 84 "mulb", 85 "mulw", 86 "mulf", 87 "divb", 88 "divw", 89 "divf", 90 "modw", 91 "modb", 92 "andb", 93 "andw", 94 "orb", 95 "orw", 96 "xorb", 97 "xorw", 98 "shlb", 99 "shlw", 100 "shrb", 101 "shrw", 102 "insc", 103 "indc", 104 "addc", 105 "lenc", 106 "lena", 107 "lenl", 108 "beqb", 109 "bneb", 110 "bltb", 111 "bleb", 112 "bgtb", 113 "bgeb", 114 "beqw", 115 "bnew", 116 "bltw", 117 "blew", 118 "bgtw", 119 "bgew", 120 "beqf", 121 "bnef", 122 "bltf", 123 "blef", 124 "bgtf", 125 "bgef", 126 "beqc", 127 "bnec", 128 "bltc", 129 "blec", 130 "bgtc", 131 "bgec", 132 "slicea", 133 "slicela", 134 "slicec", 135 "indw", 136 "indf", 137 "indb", 138 "negf", 139 "movl", 140 "addl", 141 "subl", 142 "divl", 143 "modl", 144 "mull", 145 "andl", 146 "orl", 147 "xorl", 148 "shll", 149 "shrl", 150 "bnel", 151 "bltl", 152 "blel", 153 "bgtl", 154 "bgel", 155 "beql", 156 "cvtlf", 157 "cvtfl", 158 "cvtlw", 159 "cvtwl", 160 "cvtlc", 161 "cvtcl", 162 "headl", 163 "consl", 164 "newcl", 165 "casec", 166 "indl", 167 "movpc", 168 "tcmp", 169 "mnewz", 170 "cvtrf", 171 "cvtfr", 172 "cvtws", 173 "cvtsw", 174 "lsrw", 175 "lsrl", 176 "eclr", 177 "newz", 178 "newaz", 179 "raise", 180 "casel", 181 "mulx", 182 "divx", 183 "cvtxx", 184 "mulx0", 185 "divx0", 186 "cvtxx0", 187 "mulx1", 188 "divx1", 189 "cvtxx1", 190 "cvtfx", 191 "cvtxf", 192 "expw", 193 "expl", 194 "expf", 195 "self", 196}; 197 198init() 199{ 200 sys = load Sys Sys->PATH; 201 math = load Math Math->PATH; # optional 202} 203 204loadobj(disfile: string): (ref Mod, string) 205{ 206 fd := sys->open(disfile, sys->OREAD); 207 if(fd == nil) 208 return (nil, "open failed: "+sprint("%r")); 209 210 (ok, d) := sys->fstat(fd); 211 if(ok < 0) 212 return (nil, "stat failed: "+sprint("%r")); 213 214 objlen := int d.length; 215 disobj = array[objlen] of byte; 216 217 if(sys->read(fd, disobj, objlen) != objlen){ 218 disobj = nil; 219 return (nil, "read failed: "+sprint("%r")); 220 } 221 222 disptr = 0; 223 m := ref Mod; 224 m.magic = operand(); 225 if(m.magic == SMAGIC) { 226 n := operand(); 227 m.sign = disobj[disptr:disptr+n]; 228 disptr += n; 229 m.magic = operand(); 230 } 231 if(m.magic != XMAGIC){ 232 disobj = nil; 233 return (nil, "bad magic number"); 234 } 235 236 m.rt = operand(); 237 m.ssize = operand(); 238 m.isize = operand(); 239 m.dsize = operand(); 240 m.tsize = operand(); 241 m.lsize = operand(); 242 m.entry = operand(); 243 m.entryt = operand(); 244 245 m.inst = array[m.isize] of ref Inst; 246 for(i := 0; i < m.isize; i++) { 247 o := ref Inst; 248 o.op = int disobj[disptr++]; 249 o.addr = int disobj[disptr++]; 250 case o.addr & ARM { 251 AXIMM or 252 AXINF or 253 AXINM => 254 o.mid = operand(); 255 } 256 257 case (o.addr>>3) & 7 { 258 AFP or 259 AMP or 260 AIMM => 261 o.src = operand(); 262 AIND|AFP or 263 AIND|AMP => 264 o.src = operand()<<16; 265 o.src |= operand(); 266 } 267 268 case o.addr & 7 { 269 AFP or 270 AMP or 271 AIMM => 272 o.dst = operand(); 273 AIND|AFP or 274 AIND|AMP => 275 o.dst = operand()<<16; 276 o.dst |= operand(); 277 } 278 m.inst[i] = o; 279 } 280 281 m.types = array[m.tsize] of ref Type; 282 for(i = 0; i < m.tsize; i++) { 283 h := ref Type; 284 id := operand(); 285 h.size = operand(); 286 h.np = operand(); 287 h.map = disobj[disptr:disptr+h.np]; 288 disptr += h.np; 289 m.types[i] = h; 290 } 291 292 for(;;) { 293 op := int disobj[disptr++]; 294 if(op == 0) 295 break; 296 297 n := op & (DMAX-1); 298 if(n == 0) 299 n = operand(); 300 301 offset := operand(); 302 303 dat: ref Data; 304 case op>>4 { 305 DEFB => 306 dat = ref Data.Bytes(op, n, offset, disobj[disptr:disptr+n]); 307 disptr += n; 308 DEFW => 309 words := array[n] of int; 310 for(i = 0; i < n; i++) 311 words[i] = getw(); 312 dat = ref Data.Words(op, n, offset, words); 313 DEFS => 314 dat = ref Data.String(op, n, offset, string disobj[disptr:disptr+n]); 315 disptr += n; 316 DEFF => 317 if(math != nil){ 318 reals := array[n] of real; 319 for(i = 0; i < n; i++) 320 reals[i] = math->bits64real(getl()); 321 dat = ref Data.Reals(op, n, offset, reals); 322 } else { 323 disptr += 8*n; # skip it 324 dat = ref Data.Reals(op, n, offset, nil); 325 } 326 break; 327 DEFA => 328 typex := getw(); 329 length := getw(); 330 dat = ref Data.Array(op, n, offset, typex, length); 331 DIND => 332 dat = ref Data.Aindex(op, n, offset, getw()); 333 DAPOP => 334 dat = ref Data.Arestore(op, n, offset); 335 DEFL => 336 bigs := array[n] of big; 337 for(i = 0; i < n; i++) 338 bigs[i] = getl(); 339 dat = ref Data.Bigs(op, n, offset, bigs); 340 * => 341 dat = ref Data.Zero(op, n, offset); 342 } 343 m.data = dat :: m.data; 344 } 345 346 m.data = revdat(m.data); 347 348 m.name = gets(); 349 350 m.links = array[m.lsize] of ref Link; 351 for(i = 0; i < m.lsize; i++) { 352 l := ref Link; 353 l.pc = operand(); 354 l.desc = operand(); 355 l.sig = getw(); 356 l.name = gets(); 357 358 m.links[i] = l; 359 } 360 361 if(m.rt & Dis->HASLDT0) 362 raise "obsolete dis"; 363 364 if(m.rt & Dis->HASLDT){ 365 nl := operand(); 366 imps := array[nl] of array of ref Import; 367 for(i = 0; i < nl; i++){ 368 n := operand(); 369 imps[i] = array[n] of ref Import; 370 for(j := 0; j < n; j++){ 371 imps[i][j] = im := ref Import; 372 im.sig = getw(); 373 im.name = gets(); 374 } 375 } 376 disptr++; 377 m.imports = imps; 378 } 379 380 if(m.rt & Dis->HASEXCEPT){ 381 nh := operand(); # number of handlers 382 hs := array[nh] of ref Handler; 383 for(i = 0; i < nh; i++){ 384 h := hs[i] = ref Handler; 385 h.eoff = operand(); 386 h.pc1 = operand(); 387 h.pc2 = operand(); 388 t := operand(); 389 if(t >= 0) 390 h.t = m.types[t]; 391 n := operand(); 392 h.ne = n>>16; 393 n &= 16rffff; # number of cases 394 h.etab = array[n+1] of ref Except; 395 for(j := 0; j < n; j++){ 396 e := h.etab[j] = ref Except; 397 k := disptr; 398 while(int disobj[disptr++]) # pattern 399 ; 400 e.s = string disobj[k: disptr-1]; 401 e.pc = operand(); 402 } 403 e := h.etab[j] = ref Except; 404 e.pc = operand(); # * pc 405 } 406 disptr++; # 0 byte 407 m.handlers = hs; 408 } 409 410 m.srcpath = gets(); 411 412 disobj = nil; 413 return (m, nil); 414} 415 416operand(): int 417{ 418 if(disptr >= len disobj) 419 return -1; 420 421 b := int disobj[disptr++]; 422 423 case b & 16rC0 { 424 16r00 => 425 return b; 426 16r40 => 427 return b | ~16r7F; 428 16r80 => 429 if(disptr >= len disobj) 430 return -1; 431 if(b & 16r20) 432 b |= ~16r3F; 433 else 434 b &= 16r3F; 435 return (b<<8) | int disobj[disptr++]; 436 16rC0 => 437 if(disptr+2 >= len disobj) 438 return -1; 439 if(b & 16r20) 440 b |= ~16r3F; 441 else 442 b &= 16r3F; 443 b = b<<24 | 444 (int disobj[disptr]<<16) | 445 (int disobj[disptr+1]<<8)| 446 int disobj[disptr+2]; 447 disptr += 3; 448 return b; 449 } 450 return 0; 451} 452 453get4(a: array of byte, i: int): int 454{ 455 return (int a[i+0] << 24) | (int a[i+1] << 16) | (int a[i+2] << 8) | int a[i+3]; 456} 457 458getw(): int 459{ 460 if(disptr+3 >= len disobj) 461 return -1; 462 i := (int disobj[disptr+0]<<24) | 463 (int disobj[disptr+1]<<16) | 464 (int disobj[disptr+2]<<8) | 465 int disobj[disptr+3]; 466 467 disptr += 4; 468 return i; 469} 470 471getl(): big 472{ 473 if(disptr+7 >= len disobj) 474 return big -1; 475 i := (big disobj[disptr+0]<<56) | 476 (big disobj[disptr+1]<<48) | 477 (big disobj[disptr+2]<<40) | 478 (big disobj[disptr+3]<<32) | 479 (big disobj[disptr+4]<<24) | 480 (big disobj[disptr+5]<<16) | 481 (big disobj[disptr+6]<<8) | 482 big disobj[disptr+7]; 483 484 disptr += 8; 485 return i; 486} 487 488gets(): string 489{ 490 s := disptr; 491 while(disptr < len disobj && disobj[disptr] != byte 0) 492 disptr++; 493 494 v := string disobj[s:disptr]; 495 disptr++; 496 return v; 497} 498 499revdat(d: list of ref Data): list of ref Data 500{ 501 t: list of ref Data; 502 503 while(d != nil) { 504 t = hd d :: t; 505 d = tl d; 506 } 507 return t; 508} 509 510op2s(op: int): string 511{ 512 if(op < 0 || op >= len optab) 513 return sys->sprint("OP%d", op); 514 return optab[op]; 515} 516 517inst2s(o: ref Inst): string 518{ 519 fi := 0; 520 si := 0; 521 s := sprint("%-10s", optab[o.op]); 522 src := ""; 523 dst := ""; 524 mid := ""; 525 case (o.addr>>3) & 7 { 526 AFP => 527 src = sprint("%d(fp)", o.src); 528 AMP => 529 src = sprint("%d(mp)", o.src); 530 AIMM => 531 src = sprint("$%d", o.src); 532 AIND|AFP => 533 fi = (o.src>>16) & 16rFFFF; 534 si = o.src & 16rFFFF; 535 src = sprint("%d(%d(fp))", si, fi); 536 AIND|AMP => 537 fi = (o.src>>16) & 16rFFFF; 538 si = o.src & 16rFFFF; 539 src = sprint("%d(%d(mp))", si, fi); 540 } 541 542 case o.addr & ARM { 543 AXIMM => 544 mid = sprint("$%d", o.mid); 545 AXINF => 546 mid = sprint("%d(fp)", o.mid); 547 AXINM => 548 mid = sprint("%d(mp)", o.mid); 549 } 550 551 case o.addr & 7 { 552 AFP => 553 dst = sprint("%d(fp)", o.dst); 554 AMP => 555 dst = sprint("%d(mp)", o.dst); 556 AIMM => 557 dst = sprint("$%d", o.dst); 558 AIND|AFP => 559 fi = (o.dst>>16) & 16rFFFF; 560 si = o.dst & 16rFFFF; 561 dst = sprint("%d(%d(fp))", si, fi); 562 AIND|AMP => 563 fi = (o.dst>>16) & 16rFFFF; 564 si = o.dst & 16rFFFF; 565 dst = sprint("%d(%d(mp))", si, fi); 566 } 567 if(mid == "") { 568 if(src == "") 569 s += sprint("%s", dst); 570 else if(dst == "") 571 s += sprint("%s", src); 572 else 573 s += sprint("%s, %s", src, dst); 574 } 575 else 576 s += sprint("%s, %s, %s", src, mid, dst); 577 578 return s; 579} 580 581getsb(fd: ref Sys->FD, o: int): (string, int) 582{ 583 b := array[1] of byte; 584 buf := array[8192] of byte; 585 p := len buf; 586 for( ; ; o++){ 587 sys->seek(fd, big -o, Sys->SEEKEND); 588 if(sys->read(fd, b, 1) != 1) 589 return (nil, 0); 590 if(b[0] == byte 0){ 591 if(p < len buf) 592 break; 593 } 594 else if(p > 0) 595 buf[--p] = b[0]; 596 } 597 return (string buf[p: ], o); 598} 599 600src(disf: string): string 601{ 602 fd := sys->open(disf, sys->OREAD); 603 if(fd == nil) 604 return nil; 605 (s, nil) := getsb(fd, 1); 606 if(s != nil && s[0] == '/') 607 return s; 608 return nil; 609} 610