github.com/sean-/go@v0.0.0-20151219100004-97f854cd7bb6/src/cmd/link/internal/ld/ldelf.go (about) 1 package ld 2 3 import ( 4 "bytes" 5 "cmd/internal/obj" 6 "encoding/binary" 7 "fmt" 8 "io" 9 "log" 10 "sort" 11 "strings" 12 ) 13 14 /* 15 Derived from Plan 9 from User Space's src/libmach/elf.h, elf.c 16 http://code.swtch.com/plan9port/src/tip/src/libmach/ 17 18 Copyright © 2004 Russ Cox. 19 Portions Copyright © 2008-2010 Google Inc. 20 Portions Copyright © 2010 The Go Authors. 21 22 Permission is hereby granted, free of charge, to any person obtaining a copy 23 of this software and associated documentation files (the "Software"), to deal 24 in the Software without restriction, including without limitation the rights 25 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 26 copies of the Software, and to permit persons to whom the Software is 27 furnished to do so, subject to the following conditions: 28 29 The above copyright notice and this permission notice shall be included in 30 all copies or substantial portions of the Software. 31 32 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 33 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 34 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 35 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 36 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 37 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 38 THE SOFTWARE. 39 */ 40 const ( 41 ElfClassNone = 0 42 ElfClass32 = 1 43 ElfClass64 = 2 44 ) 45 46 const ( 47 ElfDataNone = 0 48 ElfDataLsb = 1 49 ElfDataMsb = 2 50 ) 51 52 const ( 53 ElfTypeNone = 0 54 ElfTypeRelocatable = 1 55 ElfTypeExecutable = 2 56 ElfTypeSharedObject = 3 57 ElfTypeCore = 4 58 ) 59 60 const ( 61 ElfMachNone = 0 62 ElfMach32100 = 1 63 ElfMachSparc = 2 64 ElfMach386 = 3 65 ElfMach68000 = 4 66 ElfMach88000 = 5 67 ElfMach486 = 6 68 ElfMach860 = 7 69 ElfMachMips = 8 70 ElfMachS370 = 9 71 ElfMachMipsLe = 10 72 ElfMachParisc = 15 73 ElfMachVpp500 = 17 74 ElfMachSparc32Plus = 18 75 ElfMach960 = 19 76 ElfMachPower = 20 77 ElfMachPower64 = 21 78 ElfMachS390 = 22 79 ElfMachV800 = 36 80 ElfMachFr20 = 37 81 ElfMachRh32 = 38 82 ElfMachRce = 39 83 ElfMachArm = 40 84 ElfMachAlpha = 41 85 ElfMachSH = 42 86 ElfMachSparc9 = 43 87 ElfMachAmd64 = 62 88 ElfMachArm64 = 183 89 ) 90 91 const ( 92 ElfAbiNone = 0 93 ElfAbiSystemV = 0 94 ElfAbiHPUX = 1 95 ElfAbiNetBSD = 2 96 ElfAbiLinux = 3 97 ElfAbiSolaris = 6 98 ElfAbiAix = 7 99 ElfAbiIrix = 8 100 ElfAbiFreeBSD = 9 101 ElfAbiTru64 = 10 102 ElfAbiModesto = 11 103 ElfAbiOpenBSD = 12 104 ElfAbiARM = 97 105 ElfAbiEmbedded = 255 106 ) 107 108 const ( 109 ElfSectNone = 0 110 ElfSectProgbits = 1 111 ElfSectSymtab = 2 112 ElfSectStrtab = 3 113 ElfSectRela = 4 114 ElfSectHash = 5 115 ElfSectDynamic = 6 116 ElfSectNote = 7 117 ElfSectNobits = 8 118 ElfSectRel = 9 119 ElfSectShlib = 10 120 ElfSectDynsym = 11 121 ElfSectFlagWrite = 0x1 122 ElfSectFlagAlloc = 0x2 123 ElfSectFlagExec = 0x4 124 ) 125 126 const ( 127 ElfSymBindLocal = 0 128 ElfSymBindGlobal = 1 129 ElfSymBindWeak = 2 130 ) 131 132 const ( 133 ElfSymTypeNone = 0 134 ElfSymTypeObject = 1 135 ElfSymTypeFunc = 2 136 ElfSymTypeSection = 3 137 ElfSymTypeFile = 4 138 ) 139 140 const ( 141 ElfSymShnNone = 0 142 ElfSymShnAbs = 0xFFF1 143 ElfSymShnCommon = 0xFFF2 144 ) 145 146 const ( 147 ElfProgNone = 0 148 ElfProgLoad = 1 149 ElfProgDynamic = 2 150 ElfProgInterp = 3 151 ElfProgNote = 4 152 ElfProgShlib = 5 153 ElfProgPhdr = 6 154 ElfProgFlagExec = 0x1 155 ElfProgFlagWrite = 0x2 156 ElfProgFlagRead = 0x4 157 ) 158 159 const ( 160 ElfNotePrStatus = 1 161 ElfNotePrFpreg = 2 162 ElfNotePrPsinfo = 3 163 ElfNotePrTaskstruct = 4 164 ElfNotePrAuxv = 6 165 ElfNotePrXfpreg = 0x46e62b7f 166 ) 167 168 type ElfHdrBytes struct { 169 Ident [16]uint8 170 Type [2]uint8 171 Machine [2]uint8 172 Version [4]uint8 173 Entry [4]uint8 174 Phoff [4]uint8 175 Shoff [4]uint8 176 Flags [4]uint8 177 Ehsize [2]uint8 178 Phentsize [2]uint8 179 Phnum [2]uint8 180 Shentsize [2]uint8 181 Shnum [2]uint8 182 Shstrndx [2]uint8 183 } 184 185 type ElfSectBytes struct { 186 Name [4]uint8 187 Type [4]uint8 188 Flags [4]uint8 189 Addr [4]uint8 190 Off [4]uint8 191 Size [4]uint8 192 Link [4]uint8 193 Info [4]uint8 194 Align [4]uint8 195 Entsize [4]uint8 196 } 197 198 type ElfProgBytes struct { 199 } 200 201 type ElfSymBytes struct { 202 Name [4]uint8 203 Value [4]uint8 204 Size [4]uint8 205 Info uint8 206 Other uint8 207 Shndx [2]uint8 208 } 209 210 type ElfHdrBytes64 struct { 211 Ident [16]uint8 212 Type [2]uint8 213 Machine [2]uint8 214 Version [4]uint8 215 Entry [8]uint8 216 Phoff [8]uint8 217 Shoff [8]uint8 218 Flags [4]uint8 219 Ehsize [2]uint8 220 Phentsize [2]uint8 221 Phnum [2]uint8 222 Shentsize [2]uint8 223 Shnum [2]uint8 224 Shstrndx [2]uint8 225 } 226 227 type ElfSectBytes64 struct { 228 Name [4]uint8 229 Type [4]uint8 230 Flags [8]uint8 231 Addr [8]uint8 232 Off [8]uint8 233 Size [8]uint8 234 Link [4]uint8 235 Info [4]uint8 236 Align [8]uint8 237 Entsize [8]uint8 238 } 239 240 type ElfProgBytes64 struct { 241 } 242 243 type ElfSymBytes64 struct { 244 Name [4]uint8 245 Info uint8 246 Other uint8 247 Shndx [2]uint8 248 Value [8]uint8 249 Size [8]uint8 250 } 251 252 type ElfSect struct { 253 name string 254 nameoff uint32 255 type_ uint32 256 flags uint64 257 addr uint64 258 off uint64 259 size uint64 260 link uint32 261 info uint32 262 align uint64 263 entsize uint64 264 base []byte 265 sym *LSym 266 } 267 268 type ElfObj struct { 269 f *obj.Biobuf 270 base int64 // offset in f where ELF begins 271 length int64 // length of ELF 272 is64 int 273 name string 274 e binary.ByteOrder 275 sect []ElfSect 276 nsect uint 277 shstrtab string 278 nsymtab int 279 symtab *ElfSect 280 symstr *ElfSect 281 type_ uint32 282 machine uint32 283 version uint32 284 entry uint64 285 phoff uint64 286 shoff uint64 287 flags uint32 288 ehsize uint32 289 phentsize uint32 290 phnum uint32 291 shentsize uint32 292 shnum uint32 293 shstrndx uint32 294 } 295 296 type ElfSym struct { 297 name string 298 value uint64 299 size uint64 300 bind uint8 301 type_ uint8 302 other uint8 303 shndx uint16 304 sym *LSym 305 } 306 307 var ElfMagic = [4]uint8{0x7F, 'E', 'L', 'F'} 308 309 func valuecmp(a *LSym, b *LSym) int { 310 if a.Value < b.Value { 311 return -1 312 } 313 if a.Value > b.Value { 314 return +1 315 } 316 return 0 317 } 318 319 const ( 320 Tag_file = 1 321 Tag_CPU_name = 4 322 Tag_CPU_raw_name = 5 323 Tag_compatibility = 32 324 Tag_nodefaults = 64 325 Tag_also_compatible_with = 65 326 Tag_ABI_VFP_args = 28 327 ) 328 329 type elfAttribute struct { 330 tag uint64 331 sval string 332 ival uint64 333 } 334 335 type elfAttributeList struct { 336 data []byte 337 err error 338 } 339 340 func (a *elfAttributeList) string() string { 341 if a.err != nil { 342 return "" 343 } 344 nul := bytes.IndexByte(a.data, 0) 345 if nul < 0 { 346 a.err = io.EOF 347 return "" 348 } 349 s := string(a.data[:nul]) 350 a.data = a.data[nul+1:] 351 return s 352 } 353 354 func (a *elfAttributeList) uleb128() uint64 { 355 if a.err != nil { 356 return 0 357 } 358 v, size := binary.Uvarint(a.data) 359 a.data = a.data[size:] 360 return v 361 } 362 363 // Read an elfAttribute from the list following the rules used on ARM systems. 364 func (a *elfAttributeList) armAttr() elfAttribute { 365 attr := elfAttribute{tag: a.uleb128()} 366 switch { 367 case attr.tag == Tag_compatibility: 368 attr.ival = a.uleb128() 369 attr.sval = a.string() 370 371 case attr.tag == 64: // Tag_nodefaults has no argument 372 373 case attr.tag == 65: // Tag_also_compatible_with 374 // Not really, but we don't actually care about this tag. 375 attr.sval = a.string() 376 377 // Tag with string argument 378 case attr.tag == Tag_CPU_name || attr.tag == Tag_CPU_raw_name || (attr.tag >= 32 && attr.tag&1 != 0): 379 attr.sval = a.string() 380 381 default: // Tag with integer argument 382 attr.ival = a.uleb128() 383 } 384 return attr 385 } 386 387 func (a *elfAttributeList) done() bool { 388 if a.err != nil || len(a.data) == 0 { 389 return true 390 } 391 return false 392 } 393 394 // Look for the attribute that indicates the object uses the hard-float ABI (a 395 // file-level attribute with tag Tag_VFP_arch and value 1). Unfortunately the 396 // format used means that we have to parse all of the file-level attributes to 397 // find the one we are looking for. This format is slightly documented in "ELF 398 // for the ARM Architecture" but mostly this is derived from reading the source 399 // to gold and readelf. 400 func parseArmAttributes(e binary.ByteOrder, data []byte) { 401 // We assume the soft-float ABI unless we see a tag indicating otherwise. 402 if ehdr.flags == 0x5000002 { 403 ehdr.flags = 0x5000202 404 } 405 if data[0] != 'A' { 406 fmt.Fprintf(&Bso, ".ARM.attributes has unexpected format %c\n", data[0]) 407 return 408 } 409 data = data[1:] 410 for len(data) != 0 { 411 sectionlength := e.Uint32(data) 412 sectiondata := data[4:sectionlength] 413 data = data[sectionlength:] 414 415 nulIndex := bytes.IndexByte(sectiondata, 0) 416 if nulIndex < 0 { 417 fmt.Fprintf(&Bso, "corrupt .ARM.attributes (section name not NUL-terminated)\n") 418 return 419 } 420 name := string(sectiondata[:nulIndex]) 421 sectiondata = sectiondata[nulIndex+1:] 422 423 if name != "aeabi" { 424 continue 425 } 426 for len(sectiondata) != 0 { 427 subsectiontag, sz := binary.Uvarint(sectiondata) 428 subsectionsize := e.Uint32(sectiondata[sz:]) 429 subsectiondata := sectiondata[sz+4 : subsectionsize] 430 sectiondata = sectiondata[subsectionsize:] 431 432 if subsectiontag == Tag_file { 433 attrList := elfAttributeList{data: subsectiondata} 434 for !attrList.done() { 435 attr := attrList.armAttr() 436 if attr.tag == Tag_ABI_VFP_args && attr.ival == 1 { 437 ehdr.flags = 0x5000402 // has entry point, Version5 EABI, hard-float ABI 438 } 439 } 440 if attrList.err != nil { 441 fmt.Fprintf(&Bso, "could not parse .ARM.attributes\n") 442 } 443 } 444 } 445 } 446 } 447 448 func ldelf(f *obj.Biobuf, pkg string, length int64, pn string) { 449 if Debug['v'] != 0 { 450 fmt.Fprintf(&Bso, "%5.2f ldelf %s\n", obj.Cputime(), pn) 451 } 452 453 Ctxt.Version++ 454 base := int32(obj.Boffset(f)) 455 456 var add uint64 457 var e binary.ByteOrder 458 var elfobj *ElfObj 459 var err error 460 var flag int 461 var hdr *ElfHdrBytes 462 var hdrbuf [64]uint8 463 var info uint64 464 var is64 int 465 var j int 466 var n int 467 var name string 468 var p []byte 469 var r []Reloc 470 var rela int 471 var rp *Reloc 472 var rsect *ElfSect 473 var s *LSym 474 var sect *ElfSect 475 var sym ElfSym 476 var symbols []*LSym 477 if obj.Bread(f, hdrbuf[:]) != len(hdrbuf) { 478 goto bad 479 } 480 hdr = new(ElfHdrBytes) 481 binary.Read(bytes.NewReader(hdrbuf[:]), binary.BigEndian, hdr) // only byte arrays; byte order doesn't matter 482 if string(hdr.Ident[:4]) != "\x7FELF" { 483 goto bad 484 } 485 switch hdr.Ident[5] { 486 case ElfDataLsb: 487 e = binary.LittleEndian 488 489 case ElfDataMsb: 490 e = binary.BigEndian 491 492 default: 493 goto bad 494 } 495 496 // read header 497 elfobj = new(ElfObj) 498 499 elfobj.e = e 500 elfobj.f = f 501 elfobj.base = int64(base) 502 elfobj.length = length 503 elfobj.name = pn 504 505 is64 = 0 506 if hdr.Ident[4] == ElfClass64 { 507 is64 = 1 508 hdr := new(ElfHdrBytes64) 509 binary.Read(bytes.NewReader(hdrbuf[:]), binary.BigEndian, hdr) // only byte arrays; byte order doesn't matter 510 elfobj.type_ = uint32(e.Uint16(hdr.Type[:])) 511 elfobj.machine = uint32(e.Uint16(hdr.Machine[:])) 512 elfobj.version = e.Uint32(hdr.Version[:]) 513 elfobj.phoff = e.Uint64(hdr.Phoff[:]) 514 elfobj.shoff = e.Uint64(hdr.Shoff[:]) 515 elfobj.flags = e.Uint32(hdr.Flags[:]) 516 elfobj.ehsize = uint32(e.Uint16(hdr.Ehsize[:])) 517 elfobj.phentsize = uint32(e.Uint16(hdr.Phentsize[:])) 518 elfobj.phnum = uint32(e.Uint16(hdr.Phnum[:])) 519 elfobj.shentsize = uint32(e.Uint16(hdr.Shentsize[:])) 520 elfobj.shnum = uint32(e.Uint16(hdr.Shnum[:])) 521 elfobj.shstrndx = uint32(e.Uint16(hdr.Shstrndx[:])) 522 } else { 523 elfobj.type_ = uint32(e.Uint16(hdr.Type[:])) 524 elfobj.machine = uint32(e.Uint16(hdr.Machine[:])) 525 elfobj.version = e.Uint32(hdr.Version[:]) 526 elfobj.entry = uint64(e.Uint32(hdr.Entry[:])) 527 elfobj.phoff = uint64(e.Uint32(hdr.Phoff[:])) 528 elfobj.shoff = uint64(e.Uint32(hdr.Shoff[:])) 529 elfobj.flags = e.Uint32(hdr.Flags[:]) 530 elfobj.ehsize = uint32(e.Uint16(hdr.Ehsize[:])) 531 elfobj.phentsize = uint32(e.Uint16(hdr.Phentsize[:])) 532 elfobj.phnum = uint32(e.Uint16(hdr.Phnum[:])) 533 elfobj.shentsize = uint32(e.Uint16(hdr.Shentsize[:])) 534 elfobj.shnum = uint32(e.Uint16(hdr.Shnum[:])) 535 elfobj.shstrndx = uint32(e.Uint16(hdr.Shstrndx[:])) 536 } 537 538 elfobj.is64 = is64 539 540 if uint32(hdr.Ident[6]) != elfobj.version { 541 goto bad 542 } 543 544 if e.Uint16(hdr.Type[:]) != ElfTypeRelocatable { 545 Diag("%s: elf but not elf relocatable object", pn) 546 return 547 } 548 549 switch Thearch.Thechar { 550 default: 551 Diag("%s: elf %s unimplemented", pn, Thestring) 552 return 553 554 case '0': 555 if elfobj.machine != ElfMachMips || hdr.Ident[4] != ElfClass64 { 556 Diag("%s: elf object but not mips64", pn) 557 return 558 } 559 560 case '5': 561 if e != binary.LittleEndian || elfobj.machine != ElfMachArm || hdr.Ident[4] != ElfClass32 { 562 Diag("%s: elf object but not arm", pn) 563 return 564 } 565 566 case '6': 567 if e != binary.LittleEndian || elfobj.machine != ElfMachAmd64 || hdr.Ident[4] != ElfClass64 { 568 Diag("%s: elf object but not amd64", pn) 569 return 570 } 571 572 case '7': 573 if e != binary.LittleEndian || elfobj.machine != ElfMachArm64 || hdr.Ident[4] != ElfClass64 { 574 Diag("%s: elf object but not arm64", pn) 575 return 576 } 577 578 case '8': 579 if e != binary.LittleEndian || elfobj.machine != ElfMach386 || hdr.Ident[4] != ElfClass32 { 580 Diag("%s: elf object but not 386", pn) 581 return 582 } 583 584 case '9': 585 if elfobj.machine != ElfMachPower64 || hdr.Ident[4] != ElfClass64 { 586 Diag("%s: elf object but not ppc64", pn) 587 return 588 } 589 } 590 591 // load section list into memory. 592 elfobj.sect = make([]ElfSect, elfobj.shnum) 593 594 elfobj.nsect = uint(elfobj.shnum) 595 for i := 0; uint(i) < elfobj.nsect; i++ { 596 if obj.Bseek(f, int64(uint64(base)+elfobj.shoff+uint64(int64(i)*int64(elfobj.shentsize))), 0) < 0 { 597 goto bad 598 } 599 sect = &elfobj.sect[i] 600 if is64 != 0 { 601 var b ElfSectBytes64 602 603 if err = binary.Read(f, e, &b); err != nil { 604 goto bad 605 } 606 607 sect.nameoff = uint32(e.Uint32(b.Name[:])) 608 sect.type_ = e.Uint32(b.Type[:]) 609 sect.flags = e.Uint64(b.Flags[:]) 610 sect.addr = e.Uint64(b.Addr[:]) 611 sect.off = e.Uint64(b.Off[:]) 612 sect.size = e.Uint64(b.Size[:]) 613 sect.link = e.Uint32(b.Link[:]) 614 sect.info = e.Uint32(b.Info[:]) 615 sect.align = e.Uint64(b.Align[:]) 616 sect.entsize = e.Uint64(b.Entsize[:]) 617 } else { 618 var b ElfSectBytes 619 620 if err = binary.Read(f, e, &b); err != nil { 621 goto bad 622 } 623 624 sect.nameoff = uint32(e.Uint32(b.Name[:])) 625 sect.type_ = e.Uint32(b.Type[:]) 626 sect.flags = uint64(e.Uint32(b.Flags[:])) 627 sect.addr = uint64(e.Uint32(b.Addr[:])) 628 sect.off = uint64(e.Uint32(b.Off[:])) 629 sect.size = uint64(e.Uint32(b.Size[:])) 630 sect.link = e.Uint32(b.Link[:]) 631 sect.info = e.Uint32(b.Info[:]) 632 sect.align = uint64(e.Uint32(b.Align[:])) 633 sect.entsize = uint64(e.Uint32(b.Entsize[:])) 634 } 635 } 636 637 // read section string table and translate names 638 if elfobj.shstrndx >= uint32(elfobj.nsect) { 639 err = fmt.Errorf("shstrndx out of range %d >= %d", elfobj.shstrndx, elfobj.nsect) 640 goto bad 641 } 642 643 sect = &elfobj.sect[elfobj.shstrndx] 644 if err = elfmap(elfobj, sect); err != nil { 645 goto bad 646 } 647 for i := 0; uint(i) < elfobj.nsect; i++ { 648 if elfobj.sect[i].nameoff != 0 { 649 elfobj.sect[i].name = cstring(sect.base[elfobj.sect[i].nameoff:]) 650 } 651 } 652 653 // load string table for symbols into memory. 654 elfobj.symtab = section(elfobj, ".symtab") 655 656 if elfobj.symtab == nil { 657 // our work is done here - no symbols means nothing can refer to this file 658 return 659 } 660 661 if elfobj.symtab.link <= 0 || elfobj.symtab.link >= uint32(elfobj.nsect) { 662 Diag("%s: elf object has symbol table with invalid string table link", pn) 663 return 664 } 665 666 elfobj.symstr = &elfobj.sect[elfobj.symtab.link] 667 if is64 != 0 { 668 elfobj.nsymtab = int(elfobj.symtab.size / ELF64SYMSIZE) 669 } else { 670 elfobj.nsymtab = int(elfobj.symtab.size / ELF32SYMSIZE) 671 } 672 673 if err = elfmap(elfobj, elfobj.symtab); err != nil { 674 goto bad 675 } 676 if err = elfmap(elfobj, elfobj.symstr); err != nil { 677 goto bad 678 } 679 680 // load text and data segments into memory. 681 // they are not as small as the section lists, but we'll need 682 // the memory anyway for the symbol images, so we might 683 // as well use one large chunk. 684 685 // create symbols for elfmapped sections 686 for i := 0; uint(i) < elfobj.nsect; i++ { 687 sect = &elfobj.sect[i] 688 if sect.type_ == SHT_ARM_ATTRIBUTES && sect.name == ".ARM.attributes" { 689 if err = elfmap(elfobj, sect); err != nil { 690 goto bad 691 } 692 parseArmAttributes(e, sect.base[:sect.size]) 693 } 694 if (sect.type_ != ElfSectProgbits && sect.type_ != ElfSectNobits) || sect.flags&ElfSectFlagAlloc == 0 { 695 continue 696 } 697 if sect.type_ != ElfSectNobits { 698 if err = elfmap(elfobj, sect); err != nil { 699 goto bad 700 } 701 } 702 703 name = fmt.Sprintf("%s(%s)", pkg, sect.name) 704 s = Linklookup(Ctxt, name, Ctxt.Version) 705 706 switch int(sect.flags) & (ElfSectFlagAlloc | ElfSectFlagWrite | ElfSectFlagExec) { 707 default: 708 err = fmt.Errorf("unexpected flags for ELF section %s", sect.name) 709 goto bad 710 711 case ElfSectFlagAlloc: 712 s.Type = obj.SRODATA 713 714 case ElfSectFlagAlloc + ElfSectFlagWrite: 715 if sect.type_ == ElfSectNobits { 716 s.Type = obj.SNOPTRBSS 717 } else { 718 s.Type = obj.SNOPTRDATA 719 } 720 721 case ElfSectFlagAlloc + ElfSectFlagExec: 722 s.Type = obj.STEXT 723 } 724 725 if sect.name == ".got" || sect.name == ".toc" { 726 s.Type = obj.SELFGOT 727 } 728 if sect.type_ == ElfSectProgbits { 729 s.P = sect.base 730 s.P = s.P[:sect.size] 731 } 732 733 s.Size = int64(sect.size) 734 s.Align = int32(sect.align) 735 sect.sym = s 736 } 737 738 // enter sub-symbols into symbol table. 739 // symbol 0 is the null symbol. 740 symbols = make([]*LSym, elfobj.nsymtab) 741 742 for i := 1; i < elfobj.nsymtab; i++ { 743 if err = readelfsym(elfobj, i, &sym, 1); err != nil { 744 goto bad 745 } 746 symbols[i] = sym.sym 747 if sym.type_ != ElfSymTypeFunc && sym.type_ != ElfSymTypeObject && sym.type_ != ElfSymTypeNone { 748 continue 749 } 750 if sym.shndx == ElfSymShnCommon { 751 s = sym.sym 752 if uint64(s.Size) < sym.size { 753 s.Size = int64(sym.size) 754 } 755 if s.Type == 0 || s.Type == obj.SXREF { 756 s.Type = obj.SNOPTRBSS 757 } 758 continue 759 } 760 761 if uint(sym.shndx) >= elfobj.nsect || sym.shndx == 0 { 762 continue 763 } 764 765 // even when we pass needSym == 1 to readelfsym, it might still return nil to skip some unwanted symbols 766 if sym.sym == nil { 767 continue 768 } 769 sect = &elfobj.sect[sym.shndx:][0] 770 if sect.sym == nil { 771 if strings.HasPrefix(sym.name, ".Linfo_string") { // clang does this 772 continue 773 } 774 775 if sym.name == "" && sym.type_ == 0 && sect.name == ".debug_str" { 776 // This reportedly happens with clang 3.7 on ARM. 777 // See issue 13139. 778 continue 779 } 780 781 Diag("%s: sym#%d: ignoring %s in section %d (type %d)", pn, i, sym.name, sym.shndx, sym.type_) 782 continue 783 } 784 785 s = sym.sym 786 if s.Outer != nil { 787 if s.Dupok != 0 { 788 continue 789 } 790 Exitf("%s: duplicate symbol reference: %s in both %s and %s", pn, s.Name, s.Outer.Name, sect.sym.Name) 791 } 792 793 s.Sub = sect.sym.Sub 794 sect.sym.Sub = s 795 s.Type = sect.sym.Type | s.Type&^obj.SMASK | obj.SSUB 796 if s.Cgoexport&CgoExportDynamic == 0 { 797 s.Dynimplib = "" // satisfy dynimport 798 } 799 s.Value = int64(sym.value) 800 s.Size = int64(sym.size) 801 s.Outer = sect.sym 802 if sect.sym.Type == obj.STEXT { 803 if s.External != 0 && s.Dupok == 0 { 804 Diag("%s: duplicate definition of %s", pn, s.Name) 805 } 806 s.External = 1 807 } 808 809 if elfobj.machine == ElfMachPower64 { 810 flag = int(sym.other) >> 5 811 if 2 <= flag && flag <= 6 { 812 s.Localentry = 1 << uint(flag-2) 813 } else if flag == 7 { 814 Diag("%s: invalid sym.other 0x%x for %s", pn, sym.other, s.Name) 815 } 816 } 817 } 818 819 // Sort outer lists by address, adding to textp. 820 // This keeps textp in increasing address order. 821 for i := 0; uint(i) < elfobj.nsect; i++ { 822 s = elfobj.sect[i].sym 823 if s == nil { 824 continue 825 } 826 if s.Sub != nil { 827 s.Sub = listsort(s.Sub, valuecmp, listsubp) 828 } 829 if s.Type == obj.STEXT { 830 if s.Onlist != 0 { 831 log.Fatalf("symbol %s listed multiple times", s.Name) 832 } 833 s.Onlist = 1 834 if Ctxt.Etextp != nil { 835 Ctxt.Etextp.Next = s 836 } else { 837 Ctxt.Textp = s 838 } 839 Ctxt.Etextp = s 840 for s = s.Sub; s != nil; s = s.Sub { 841 if s.Onlist != 0 { 842 log.Fatalf("symbol %s listed multiple times", s.Name) 843 } 844 s.Onlist = 1 845 Ctxt.Etextp.Next = s 846 Ctxt.Etextp = s 847 } 848 } 849 } 850 851 // load relocations 852 for i := 0; uint(i) < elfobj.nsect; i++ { 853 rsect = &elfobj.sect[i] 854 if rsect.type_ != ElfSectRela && rsect.type_ != ElfSectRel { 855 continue 856 } 857 if rsect.info >= uint32(elfobj.nsect) || elfobj.sect[rsect.info].base == nil { 858 continue 859 } 860 sect = &elfobj.sect[rsect.info] 861 if err = elfmap(elfobj, rsect); err != nil { 862 goto bad 863 } 864 rela = 0 865 if rsect.type_ == ElfSectRela { 866 rela = 1 867 } 868 n = int(rsect.size / uint64(4+4*is64) / uint64(2+rela)) 869 r = make([]Reloc, n) 870 p = rsect.base 871 for j = 0; j < n; j++ { 872 add = 0 873 rp = &r[j] 874 if is64 != 0 { 875 // 64-bit rel/rela 876 rp.Off = int32(e.Uint64(p)) 877 878 p = p[8:] 879 info = e.Uint64(p) 880 p = p[8:] 881 if rela != 0 { 882 add = e.Uint64(p) 883 p = p[8:] 884 } 885 } else { 886 // 32-bit rel/rela 887 rp.Off = int32(e.Uint32(p)) 888 889 p = p[4:] 890 info = uint64(e.Uint32(p)) 891 info = info>>8<<32 | info&0xff // convert to 64-bit info 892 p = p[4:] 893 if rela != 0 { 894 add = uint64(e.Uint32(p)) 895 p = p[4:] 896 } 897 } 898 899 if info&0xffffffff == 0 { // skip R_*_NONE relocation 900 j-- 901 n-- 902 continue 903 } 904 905 if info>>32 == 0 { // absolute relocation, don't bother reading the null symbol 906 rp.Sym = nil 907 } else { 908 if err = readelfsym(elfobj, int(info>>32), &sym, 0); err != nil { 909 goto bad 910 } 911 sym.sym = symbols[info>>32] 912 if sym.sym == nil { 913 err = fmt.Errorf("%s#%d: reloc of invalid sym #%d %s shndx=%d type=%d", sect.sym.Name, j, int(info>>32), sym.name, sym.shndx, sym.type_) 914 goto bad 915 } 916 917 rp.Sym = sym.sym 918 } 919 920 rp.Type = int32(reltype(pn, int(uint32(info)), &rp.Siz)) 921 if rela != 0 { 922 rp.Add = int64(add) 923 } else { 924 // load addend from image 925 if rp.Siz == 4 { 926 rp.Add = int64(e.Uint32(sect.base[rp.Off:])) 927 } else if rp.Siz == 8 { 928 rp.Add = int64(e.Uint64(sect.base[rp.Off:])) 929 } else { 930 Diag("invalid rela size %d", rp.Siz) 931 } 932 } 933 934 if rp.Siz == 2 { 935 rp.Add = int64(int16(rp.Add)) 936 } 937 if rp.Siz == 4 { 938 rp.Add = int64(int32(rp.Add)) 939 } 940 } 941 942 //print("rel %s %d %d %s %#llx\n", sect->sym->name, rp->type, rp->siz, rp->sym->name, rp->add); 943 sort.Sort(rbyoff(r[:n])) 944 // just in case 945 946 s = sect.sym 947 s.R = r 948 s.R = s.R[:n] 949 } 950 951 return 952 953 bad: 954 Diag("%s: malformed elf file: %v", pn, err) 955 } 956 957 func section(elfobj *ElfObj, name string) *ElfSect { 958 for i := 0; uint(i) < elfobj.nsect; i++ { 959 if elfobj.sect[i].name != "" && name != "" && elfobj.sect[i].name == name { 960 return &elfobj.sect[i] 961 } 962 } 963 return nil 964 } 965 966 func elfmap(elfobj *ElfObj, sect *ElfSect) (err error) { 967 if sect.base != nil { 968 return nil 969 } 970 971 if sect.off+sect.size > uint64(elfobj.length) { 972 err = fmt.Errorf("elf section past end of file") 973 return err 974 } 975 976 sect.base = make([]byte, sect.size) 977 err = fmt.Errorf("short read") 978 if obj.Bseek(elfobj.f, int64(uint64(elfobj.base)+sect.off), 0) < 0 || obj.Bread(elfobj.f, sect.base) != len(sect.base) { 979 return err 980 } 981 982 return nil 983 } 984 985 func readelfsym(elfobj *ElfObj, i int, sym *ElfSym, needSym int) (err error) { 986 if i >= elfobj.nsymtab || i < 0 { 987 err = fmt.Errorf("invalid elf symbol index") 988 return err 989 } 990 991 if i == 0 { 992 Diag("readym: read null symbol!") 993 } 994 995 if elfobj.is64 != 0 { 996 b := new(ElfSymBytes64) 997 binary.Read(bytes.NewReader(elfobj.symtab.base[i*ELF64SYMSIZE:(i+1)*ELF64SYMSIZE]), elfobj.e, b) 998 sym.name = cstring(elfobj.symstr.base[elfobj.e.Uint32(b.Name[:]):]) 999 sym.value = elfobj.e.Uint64(b.Value[:]) 1000 sym.size = elfobj.e.Uint64(b.Size[:]) 1001 sym.shndx = elfobj.e.Uint16(b.Shndx[:]) 1002 sym.bind = b.Info >> 4 1003 sym.type_ = b.Info & 0xf 1004 sym.other = b.Other 1005 } else { 1006 b := new(ElfSymBytes) 1007 binary.Read(bytes.NewReader(elfobj.symtab.base[i*ELF32SYMSIZE:(i+1)*ELF32SYMSIZE]), elfobj.e, b) 1008 sym.name = cstring(elfobj.symstr.base[elfobj.e.Uint32(b.Name[:]):]) 1009 sym.value = uint64(elfobj.e.Uint32(b.Value[:])) 1010 sym.size = uint64(elfobj.e.Uint32(b.Size[:])) 1011 sym.shndx = elfobj.e.Uint16(b.Shndx[:]) 1012 sym.bind = b.Info >> 4 1013 sym.type_ = b.Info & 0xf 1014 sym.other = b.Other 1015 } 1016 1017 var s *LSym 1018 if sym.name == "_GLOBAL_OFFSET_TABLE_" { 1019 sym.name = ".got" 1020 } 1021 if sym.name == ".TOC." { 1022 // Magic symbol on ppc64. Will be set to this object 1023 // file's .got+0x8000. 1024 sym.bind = ElfSymBindLocal 1025 } 1026 1027 switch sym.type_ { 1028 case ElfSymTypeSection: 1029 s = elfobj.sect[sym.shndx].sym 1030 1031 case ElfSymTypeObject, ElfSymTypeFunc, ElfSymTypeNone: 1032 switch sym.bind { 1033 case ElfSymBindGlobal: 1034 if needSym != 0 { 1035 s = Linklookup(Ctxt, sym.name, 0) 1036 1037 // for global scoped hidden symbols we should insert it into 1038 // symbol hash table, but mark them as hidden. 1039 // __i686.get_pc_thunk.bx is allowed to be duplicated, to 1040 // workaround that we set dupok. 1041 // TODO(minux): correctly handle __i686.get_pc_thunk.bx without 1042 // set dupok generally. See http://codereview.appspot.com/5823055/ 1043 // comment #5 for details. 1044 if s != nil && sym.other == 2 { 1045 s.Type |= obj.SHIDDEN 1046 s.Dupok = 1 1047 } 1048 } 1049 1050 case ElfSymBindLocal: 1051 if Thearch.Thechar == '5' && (strings.HasPrefix(sym.name, "$a") || strings.HasPrefix(sym.name, "$d")) { 1052 // binutils for arm generate these mapping 1053 // symbols, ignore these 1054 break 1055 } 1056 1057 if sym.name == ".TOC." { 1058 // We need to be able to look this up, 1059 // so put it in the hash table. 1060 if needSym != 0 { 1061 s = Linklookup(Ctxt, sym.name, Ctxt.Version) 1062 s.Type |= obj.SHIDDEN 1063 } 1064 1065 break 1066 } 1067 1068 if needSym != 0 { 1069 // local names and hidden visiblity global names are unique 1070 // and should only reference by its index, not name, so we 1071 // don't bother to add them into hash table 1072 s = linknewsym(Ctxt, sym.name, Ctxt.Version) 1073 1074 s.Type |= obj.SHIDDEN 1075 } 1076 1077 case ElfSymBindWeak: 1078 if needSym != 0 { 1079 s = Linklookup(Ctxt, sym.name, 0) 1080 if sym.other == 2 { 1081 s.Type |= obj.SHIDDEN 1082 } 1083 } 1084 1085 default: 1086 err = fmt.Errorf("%s: invalid symbol binding %d", sym.name, sym.bind) 1087 return err 1088 } 1089 } 1090 1091 if s != nil && s.Type == 0 && sym.type_ != ElfSymTypeSection { 1092 s.Type = obj.SXREF 1093 } 1094 sym.sym = s 1095 1096 return nil 1097 } 1098 1099 type rbyoff []Reloc 1100 1101 func (x rbyoff) Len() int { 1102 return len(x) 1103 } 1104 1105 func (x rbyoff) Swap(i, j int) { 1106 x[i], x[j] = x[j], x[i] 1107 } 1108 1109 func (x rbyoff) Less(i, j int) bool { 1110 a := &x[i] 1111 b := &x[j] 1112 if a.Off < b.Off { 1113 return true 1114 } 1115 if a.Off > b.Off { 1116 return false 1117 } 1118 return false 1119 } 1120 1121 func reltype(pn string, elftype int, siz *uint8) int { 1122 switch uint32(Thearch.Thechar) | uint32(elftype)<<24 { 1123 default: 1124 Diag("%s: unknown relocation type %d; compiled without -fpic?", pn, elftype) 1125 fallthrough 1126 1127 case '9' | R_PPC64_TOC16<<24, 1128 '9' | R_PPC64_TOC16_LO<<24, 1129 '9' | R_PPC64_TOC16_HI<<24, 1130 '9' | R_PPC64_TOC16_HA<<24, 1131 '9' | R_PPC64_TOC16_DS<<24, 1132 '9' | R_PPC64_TOC16_LO_DS<<24, 1133 '9' | R_PPC64_REL16_LO<<24, 1134 '9' | R_PPC64_REL16_HI<<24, 1135 '9' | R_PPC64_REL16_HA<<24: 1136 *siz = 2 1137 1138 case '5' | R_ARM_ABS32<<24, 1139 '5' | R_ARM_GOT32<<24, 1140 '5' | R_ARM_PLT32<<24, 1141 '5' | R_ARM_GOTOFF<<24, 1142 '5' | R_ARM_GOTPC<<24, 1143 '5' | R_ARM_THM_PC22<<24, 1144 '5' | R_ARM_REL32<<24, 1145 '5' | R_ARM_CALL<<24, 1146 '5' | R_ARM_V4BX<<24, 1147 '5' | R_ARM_GOT_PREL<<24, 1148 '5' | R_ARM_PC24<<24, 1149 '5' | R_ARM_JUMP24<<24, 1150 '6' | R_X86_64_PC32<<24, 1151 '6' | R_X86_64_PLT32<<24, 1152 '6' | R_X86_64_GOTPCREL<<24, 1153 '6' | R_X86_64_GOTPCRELX<<24, 1154 '6' | R_X86_64_REX_GOTPCRELX<<24, 1155 '8' | R_386_32<<24, 1156 '8' | R_386_PC32<<24, 1157 '8' | R_386_GOT32<<24, 1158 '8' | R_386_PLT32<<24, 1159 '8' | R_386_GOTOFF<<24, 1160 '8' | R_386_GOTPC<<24, 1161 '8' | R_386_GOT32X<<24, 1162 '9' | R_PPC64_REL24<<24, 1163 '9' | R_PPC_REL32<<24: 1164 *siz = 4 1165 1166 case '6' | R_X86_64_64<<24, 1167 '9' | R_PPC64_ADDR64<<24: 1168 *siz = 8 1169 } 1170 1171 return 256 + elftype 1172 }