1 // Copyright 2015 The Go Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style 3 // license that can be found in the LICENSE file. 4 5 package obj 6 7 import ( 8 "bufio" 9 "bytes" 10 "fmt" 11 "io" 12 "log" 13 "os" 14 "strconv" 15 "strings" 16 "time" 17 ) 18 19 const REG_NONE = 0 20 21 var start time.Time 22 23 func Cputime() float64 { 24 if start.IsZero() { 25 start = time.Now() 26 } 27 return time.Since(start).Seconds() 28 } 29 30 type Biobuf struct { 31 f *os.File 32 r *bufio.Reader 33 w *bufio.Writer 34 linelen int 35 } 36 37 func Bopenw(name string) (*Biobuf, error) { 38 f, err := os.Create(name) 39 if err != nil { 40 return nil, err 41 } 42 return &Biobuf{f: f, w: bufio.NewWriter(f)}, nil 43 } 44 45 func Bopenr(name string) (*Biobuf, error) { 46 f, err := os.Open(name) 47 if err != nil { 48 return nil, err 49 } 50 return &Biobuf{f: f, r: bufio.NewReader(f)}, nil 51 } 52 53 func Binitw(w io.Writer) *Biobuf { 54 return &Biobuf{w: bufio.NewWriter(w)} 55 } 56 57 func (b *Biobuf) Write(p []byte) (int, error) { 58 return b.w.Write(p) 59 } 60 61 func Bwritestring(b *Biobuf, p string) (int, error) { 62 return b.w.WriteString(p) 63 } 64 65 func Bseek(b *Biobuf, offset int64, whence int) int64 { 66 if b.w != nil { 67 if err := b.w.Flush(); err != nil { 68 log.Fatalf("writing output: %v", err) 69 } 70 } else if b.r != nil { 71 if whence == 1 { 72 offset -= int64(b.r.Buffered()) 73 } 74 } 75 off, err := b.f.Seek(offset, whence) 76 if err != nil { 77 log.Fatalf("seeking in output: %v", err) 78 } 79 if b.r != nil { 80 b.r.Reset(b.f) 81 } 82 return off 83 } 84 85 func Boffset(b *Biobuf) int64 { 86 if b.w != nil { 87 if err := b.w.Flush(); err != nil { 88 log.Fatalf("writing output: %v", err) 89 } 90 } 91 off, err := b.f.Seek(0, 1) 92 if err != nil { 93 log.Fatalf("seeking in output [0, 1]: %v", err) 94 } 95 if b.r != nil { 96 off -= int64(b.r.Buffered()) 97 } 98 return off 99 } 100 101 func (b *Biobuf) Flush() error { 102 return b.w.Flush() 103 } 104 105 func Bputc(b *Biobuf, c byte) { 106 b.w.WriteByte(c) 107 } 108 109 const Beof = -1 110 111 func Bread(b *Biobuf, p []byte) int { 112 n, err := io.ReadFull(b.r, p) 113 if n == 0 { 114 if err != nil && err != io.EOF { 115 n = -1 116 } 117 } 118 return n 119 } 120 121 func Bgetc(b *Biobuf) int { 122 c, err := b.r.ReadByte() 123 if err != nil { 124 return -1 125 } 126 return int(c) 127 } 128 129 func Bgetrune(b *Biobuf) int { 130 r, _, err := b.r.ReadRune() 131 if err != nil { 132 return -1 133 } 134 return int(r) 135 } 136 137 func Bungetrune(b *Biobuf) { 138 b.r.UnreadRune() 139 } 140 141 func (b *Biobuf) Read(p []byte) (int, error) { 142 return b.r.Read(p) 143 } 144 145 func (b *Biobuf) Peek(n int) ([]byte, error) { 146 return b.r.Peek(n) 147 } 148 149 func Brdline(b *Biobuf, delim int) string { 150 s, err := b.r.ReadBytes(byte(delim)) 151 if err != nil { 152 log.Fatalf("reading input: %v", err) 153 } 154 b.linelen = len(s) 155 return string(s) 156 } 157 158 func Brdstr(b *Biobuf, delim int, cut int) string { 159 s, err := b.r.ReadString(byte(delim)) 160 if err != nil { 161 log.Fatalf("reading input: %v", err) 162 } 163 if len(s) > 0 && cut > 0 { 164 s = s[:len(s)-1] 165 } 166 return s 167 } 168 169 func Access(name string, mode int) int { 170 if mode != 0 { 171 panic("bad access") 172 } 173 _, err := os.Stat(name) 174 if err != nil { 175 return -1 176 } 177 return 0 178 } 179 180 func Blinelen(b *Biobuf) int { 181 return b.linelen 182 } 183 184 func Bterm(b *Biobuf) error { 185 var err error 186 if b.w != nil { 187 err = b.w.Flush() 188 } 189 err1 := b.f.Close() 190 if err == nil { 191 err = err1 192 } 193 return err 194 } 195 196 func envOr(key, value string) string { 197 if x := os.Getenv(key); x != "" { 198 return x 199 } 200 return value 201 } 202 203 func Getgoroot() string { 204 return envOr("GOROOT", defaultGOROOT) 205 } 206 207 func Getgoarch() string { 208 return envOr("GOARCH", defaultGOARCH) 209 } 210 211 func Getgoos() string { 212 return envOr("GOOS", defaultGOOS) 213 } 214 215 func Getgoarm() string { 216 switch v := envOr("GOARM", defaultGOARM); v { 217 case "5", "6", "7": 218 return v 219 } 220 // Fail here, rather than validate at multiple call sites. 221 log.Fatalf("Invalid GOARM value. Must be 5, 6, or 7.") 222 panic("unreachable") 223 } 224 225 func Getgo386() string { 226 // Validated by cmd/compile. 227 return envOr("GO386", defaultGO386) 228 } 229 230 func Getgoextlinkenabled() string { 231 return envOr("GO_EXTLINK_ENABLED", defaultGO_EXTLINK_ENABLED) 232 } 233 234 func Getgoversion() string { 235 return version 236 } 237 238 func Atoi(s string) int { 239 i, _ := strconv.Atoi(s) 240 return i 241 } 242 243 func (p *Prog) Line() string { 244 return p.Ctxt.LineHist.LineString(int(p.Lineno)) 245 } 246 247 var armCondCode = []string{ 248 ".EQ", 249 ".NE", 250 ".CS", 251 ".CC", 252 ".MI", 253 ".PL", 254 ".VS", 255 ".VC", 256 ".HI", 257 ".LS", 258 ".GE", 259 ".LT", 260 ".GT", 261 ".LE", 262 "", 263 ".NV", 264 } 265 266 /* ARM scond byte */ 267 const ( 268 C_SCOND = (1 << 4) - 1 269 C_SBIT = 1 << 4 270 C_PBIT = 1 << 5 271 C_WBIT = 1 << 6 272 C_FBIT = 1 << 7 273 C_UBIT = 1 << 7 274 C_SCOND_XOR = 14 275 ) 276 277 // CConv formats ARM condition codes. 278 func CConv(s uint8) string { 279 if s == 0 { 280 return "" 281 } 282 sc := armCondCode[(s&C_SCOND)^C_SCOND_XOR] 283 if s&C_SBIT != 0 { 284 sc += ".S" 285 } 286 if s&C_PBIT != 0 { 287 sc += ".P" 288 } 289 if s&C_WBIT != 0 { 290 sc += ".W" 291 } 292 if s&C_UBIT != 0 { /* ambiguous with FBIT */ 293 sc += ".U" 294 } 295 return sc 296 } 297 298 func (p *Prog) String() string { 299 if p.Ctxt == nil { 300 return "<Prog without ctxt>" 301 } 302 303 sc := CConv(p.Scond) 304 305 var buf bytes.Buffer 306 307 fmt.Fprintf(&buf, "%.5d (%v)\t%v%s", p.Pc, p.Line(), Aconv(int(p.As)), sc) 308 sep := "\t" 309 if p.From.Type != TYPE_NONE { 310 fmt.Fprintf(&buf, "%s%v", sep, Dconv(p, &p.From)) 311 sep = ", " 312 } 313 if p.Reg != REG_NONE { 314 // Should not happen but might as well show it if it does. 315 fmt.Fprintf(&buf, "%s%v", sep, Rconv(int(p.Reg))) 316 sep = ", " 317 } 318 if p.From3Type() != TYPE_NONE { 319 if p.From3.Type == TYPE_CONST && (p.As == ADATA || p.As == ATEXT || p.As == AGLOBL) { 320 // Special case - omit $. 321 fmt.Fprintf(&buf, "%s%d", sep, p.From3.Offset) 322 } else { 323 fmt.Fprintf(&buf, "%s%v", sep, Dconv(p, p.From3)) 324 } 325 sep = ", " 326 } 327 if p.To.Type != TYPE_NONE { 328 fmt.Fprintf(&buf, "%s%v", sep, Dconv(p, &p.To)) 329 } 330 if p.RegTo2 != REG_NONE { 331 fmt.Fprintf(&buf, "%s%v", sep, Rconv(int(p.RegTo2))) 332 } 333 return buf.String() 334 } 335 336 func (ctxt *Link) NewProg() *Prog { 337 p := new(Prog) // should be the only call to this; all others should use ctxt.NewProg 338 p.Ctxt = ctxt 339 return p 340 } 341 342 func (ctxt *Link) Line(n int) string { 343 return ctxt.LineHist.LineString(n) 344 } 345 346 func Getcallerpc(interface{}) uintptr { 347 return 1 348 } 349 350 func (ctxt *Link) Dconv(a *Addr) string { 351 return Dconv(nil, a) 352 } 353 354 func Dconv(p *Prog, a *Addr) string { 355 var str string 356 357 switch a.Type { 358 default: 359 str = fmt.Sprintf("type=%d", a.Type) 360 361 case TYPE_NONE: 362 str = "" 363 if a.Name != NAME_NONE || a.Reg != 0 || a.Sym != nil { 364 str = fmt.Sprintf("%v(%v)(NONE)", Mconv(a), Rconv(int(a.Reg))) 365 } 366 367 case TYPE_REG: 368 // TODO(rsc): This special case is for x86 instructions like 369 // PINSRQ CX,$1,X6 370 // where the $1 is included in the p->to Addr. 371 // Move into a new field. 372 if a.Offset != 0 { 373 str = fmt.Sprintf("$%d,%v", a.Offset, Rconv(int(a.Reg))) 374 break 375 } 376 377 str = Rconv(int(a.Reg)) 378 if a.Name != TYPE_NONE || a.Sym != nil { 379 str = fmt.Sprintf("%v(%v)(REG)", Mconv(a), Rconv(int(a.Reg))) 380 } 381 382 case TYPE_BRANCH: 383 if a.Sym != nil { 384 str = fmt.Sprintf("%s(SB)", a.Sym.Name) 385 } else if p != nil && p.Pcond != nil { 386 str = fmt.Sprint(p.Pcond.Pc) 387 } else if a.Val != nil { 388 str = fmt.Sprint(a.Val.(*Prog).Pc) 389 } else { 390 str = fmt.Sprintf("%d(PC)", a.Offset) 391 } 392 393 case TYPE_INDIR: 394 str = fmt.Sprintf("*%s", Mconv(a)) 395 396 case TYPE_MEM: 397 str = Mconv(a) 398 if a.Index != REG_NONE { 399 str += fmt.Sprintf("(%v*%d)", Rconv(int(a.Index)), int(a.Scale)) 400 } 401 402 case TYPE_CONST: 403 if a.Reg != 0 { 404 str = fmt.Sprintf("$%v(%v)", Mconv(a), Rconv(int(a.Reg))) 405 } else { 406 str = fmt.Sprintf("$%v", Mconv(a)) 407 } 408 409 case TYPE_TEXTSIZE: 410 if a.Val.(int32) == ArgsSizeUnknown { 411 str = fmt.Sprintf("$%d", a.Offset) 412 } else { 413 str = fmt.Sprintf("$%d-%d", a.Offset, a.Val.(int32)) 414 } 415 416 case TYPE_FCONST: 417 str = fmt.Sprintf("%.17g", a.Val.(float64)) 418 // Make sure 1 prints as 1.0 419 if !strings.ContainsAny(str, ".e") { 420 str += ".0" 421 } 422 str = fmt.Sprintf("$(%s)", str) 423 424 case TYPE_SCONST: 425 str = fmt.Sprintf("$%q", a.Val.(string)) 426 427 case TYPE_ADDR: 428 str = fmt.Sprintf("$%s", Mconv(a)) 429 430 case TYPE_SHIFT: 431 v := int(a.Offset) 432 op := string("<<>>->@>"[((v>>5)&3)<<1:]) 433 if v&(1<<4) != 0 { 434 str = fmt.Sprintf("R%d%c%cR%d", v&15, op[0], op[1], (v>>8)&15) 435 } else { 436 str = fmt.Sprintf("R%d%c%c%d", v&15, op[0], op[1], (v>>7)&31) 437 } 438 if a.Reg != 0 { 439 str += fmt.Sprintf("(%v)", Rconv(int(a.Reg))) 440 } 441 442 case TYPE_REGREG: 443 str = fmt.Sprintf("(%v, %v)", Rconv(int(a.Reg)), Rconv(int(a.Offset))) 444 445 case TYPE_REGREG2: 446 str = fmt.Sprintf("%v, %v", Rconv(int(a.Reg)), Rconv(int(a.Offset))) 447 448 case TYPE_REGLIST: 449 str = regListConv(int(a.Offset)) 450 } 451 452 return str 453 } 454 455 func Mconv(a *Addr) string { 456 var str string 457 458 switch a.Name { 459 default: 460 str = fmt.Sprintf("name=%d", a.Name) 461 462 case NAME_NONE: 463 switch { 464 case a.Reg == REG_NONE: 465 str = fmt.Sprint(a.Offset) 466 case a.Offset == 0: 467 str = fmt.Sprintf("(%v)", Rconv(int(a.Reg))) 468 case a.Offset != 0: 469 str = fmt.Sprintf("%d(%v)", a.Offset, Rconv(int(a.Reg))) 470 } 471 472 case NAME_EXTERN: 473 str = fmt.Sprintf("%s%s(SB)", a.Sym.Name, offConv(a.Offset)) 474 475 case NAME_GOTREF: 476 str = fmt.Sprintf("%s%s@GOT(SB)", a.Sym.Name, offConv(a.Offset)) 477 478 case NAME_STATIC: 479 str = fmt.Sprintf("%s<>%s(SB)", a.Sym.Name, offConv(a.Offset)) 480 481 case NAME_AUTO: 482 if a.Sym != nil { 483 str = fmt.Sprintf("%s%s(SP)", a.Sym.Name, offConv(a.Offset)) 484 } else { 485 str = fmt.Sprintf("%s(SP)", offConv(a.Offset)) 486 } 487 488 case NAME_PARAM: 489 if a.Sym != nil { 490 str = fmt.Sprintf("%s%s(FP)", a.Sym.Name, offConv(a.Offset)) 491 } else { 492 str = fmt.Sprintf("%s(FP)", offConv(a.Offset)) 493 } 494 } 495 return str 496 } 497 498 func offConv(off int64) string { 499 if off == 0 { 500 return "" 501 } 502 return fmt.Sprintf("%+d", off) 503 } 504 505 type regSet struct { 506 lo int 507 hi int 508 Rconv func(int) string 509 } 510 511 // Few enough architectures that a linear scan is fastest. 512 // Not even worth sorting. 513 var regSpace []regSet 514 515 /* 516 Each architecture defines a register space as a unique 517 integer range. 518 Here is the list of architectures and the base of their register spaces. 519 */ 520 521 const ( 522 // Because of masking operations in the encodings, each register 523 // space should start at 0 modulo some power of 2. 524 RBase386 = 1 * 1024 525 RBaseAMD64 = 2 * 1024 526 RBaseARM = 3 * 1024 527 RBasePPC64 = 4 * 1024 // range [4k, 8k) 528 RBaseARM64 = 8 * 1024 // range [8k, 12k) 529 ) 530 531 // RegisterRegister binds a pretty-printer (Rconv) for register 532 // numbers to a given register number range. Lo is inclusive, 533 // hi exclusive (valid registers are lo through hi-1). 534 func RegisterRegister(lo, hi int, Rconv func(int) string) { 535 regSpace = append(regSpace, regSet{lo, hi, Rconv}) 536 } 537 538 func Rconv(reg int) string { 539 if reg == REG_NONE { 540 return "NONE" 541 } 542 for i := range regSpace { 543 rs := ®Space[i] 544 if rs.lo <= reg && reg < rs.hi { 545 return rs.Rconv(reg) 546 } 547 } 548 return fmt.Sprintf("R???%d", reg) 549 } 550 551 func regListConv(list int) string { 552 str := "" 553 554 for i := 0; i < 16; i++ { // TODO: 16 is ARM-specific. 555 if list&(1<<uint(i)) != 0 { 556 if str == "" { 557 str += "[" 558 } else { 559 str += "," 560 } 561 // This is ARM-specific; R10 is g. 562 if i == 10 { 563 str += "g" 564 } else { 565 str += fmt.Sprintf("R%d", i) 566 } 567 } 568 } 569 570 str += "]" 571 return str 572 } 573 574 /* 575 Each architecture defines an instruction (A*) space as a unique 576 integer range. 577 Global opcodes like CALL start at 0; the architecture-specific ones 578 start at a distinct, big-maskable offsets. 579 Here is the list of architectures and the base of their opcode spaces. 580 */ 581 582 const ( 583 ABase386 = (1 + iota) << 12 584 ABaseARM 585 ABaseAMD64 586 ABasePPC64 587 ABaseARM64 588 AMask = 1<<12 - 1 // AND with this to use the opcode as an array index. 589 ) 590 591 type opSet struct { 592 lo int 593 names []string 594 } 595 596 // Not even worth sorting 597 var aSpace []opSet 598 599 // RegisterOpcode binds a list of instruction names 600 // to a given instruction number range. 601 func RegisterOpcode(lo int, Anames []string) { 602 aSpace = append(aSpace, opSet{lo, Anames}) 603 } 604 605 func Aconv(a int) string { 606 if a < A_ARCHSPECIFIC { 607 return Anames[a] 608 } 609 for i := range aSpace { 610 as := &aSpace[i] 611 if as.lo <= a && a < as.lo+len(as.names) { 612 return as.names[a-as.lo] 613 } 614 } 615 return fmt.Sprintf("A???%d", a) 616 } 617 618 var Anames = []string{ 619 "XXX", 620 "CALL", 621 "CHECKNIL", 622 "DATA", 623 "DUFFCOPY", 624 "DUFFZERO", 625 "END", 626 "FUNCDATA", 627 "GLOBL", 628 "JMP", 629 "NOP", 630 "PCDATA", 631 "RET", 632 "TEXT", 633 "TYPE", 634 "UNDEF", 635 "USEFIELD", 636 "VARDEF", 637 "VARKILL", 638 } 639 640 func Bool2int(b bool) int { 641 if b { 642 return 1 643 } 644 return 0 645 } 646