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