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