github.com/dannin/go@v0.0.0-20161031215817-d35dfd405eaa/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 *Symbol 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 *Symbol 307 } 308 309 var ElfMagic = [4]uint8{0x7F, 'E', 'L', 'F'} 310 311 const ( 312 TagFile = 1 313 TagCPUName = 4 314 TagCPURawName = 5 315 TagCompatibility = 32 316 TagNoDefaults = 64 317 TagAlsoCompatibleWith = 65 318 TagABIVFPArgs = 28 319 ) 320 321 type elfAttribute struct { 322 tag uint64 323 sval string 324 ival uint64 325 } 326 327 type elfAttributeList struct { 328 data []byte 329 err error 330 } 331 332 func (a *elfAttributeList) string() string { 333 if a.err != nil { 334 return "" 335 } 336 nul := bytes.IndexByte(a.data, 0) 337 if nul < 0 { 338 a.err = io.EOF 339 return "" 340 } 341 s := string(a.data[:nul]) 342 a.data = a.data[nul+1:] 343 return s 344 } 345 346 func (a *elfAttributeList) uleb128() uint64 { 347 if a.err != nil { 348 return 0 349 } 350 v, size := binary.Uvarint(a.data) 351 a.data = a.data[size:] 352 return v 353 } 354 355 // Read an elfAttribute from the list following the rules used on ARM systems. 356 func (a *elfAttributeList) armAttr() elfAttribute { 357 attr := elfAttribute{tag: a.uleb128()} 358 switch { 359 case attr.tag == TagCompatibility: 360 attr.ival = a.uleb128() 361 attr.sval = a.string() 362 363 case attr.tag == 64: // Tag_nodefaults has no argument 364 365 case attr.tag == 65: // Tag_also_compatible_with 366 // Not really, but we don't actually care about this tag. 367 attr.sval = a.string() 368 369 // Tag with string argument 370 case attr.tag == TagCPUName || attr.tag == TagCPURawName || (attr.tag >= 32 && attr.tag&1 != 0): 371 attr.sval = a.string() 372 373 default: // Tag with integer argument 374 attr.ival = a.uleb128() 375 } 376 return attr 377 } 378 379 func (a *elfAttributeList) done() bool { 380 if a.err != nil || len(a.data) == 0 { 381 return true 382 } 383 return false 384 } 385 386 // Look for the attribute that indicates the object uses the hard-float ABI (a 387 // file-level attribute with tag Tag_VFP_arch and value 1). Unfortunately the 388 // format used means that we have to parse all of the file-level attributes to 389 // find the one we are looking for. This format is slightly documented in "ELF 390 // for the ARM Architecture" but mostly this is derived from reading the source 391 // to gold and readelf. 392 func parseArmAttributes(ctxt *Link, e binary.ByteOrder, data []byte) { 393 // We assume the soft-float ABI unless we see a tag indicating otherwise. 394 if ehdr.flags == 0x5000002 { 395 ehdr.flags = 0x5000202 396 } 397 if data[0] != 'A' { 398 // TODO(dfc) should this be ctxt.Diag ? 399 ctxt.Logf(".ARM.attributes has unexpected format %c\n", data[0]) 400 return 401 } 402 data = data[1:] 403 for len(data) != 0 { 404 sectionlength := e.Uint32(data) 405 sectiondata := data[4:sectionlength] 406 data = data[sectionlength:] 407 408 nulIndex := bytes.IndexByte(sectiondata, 0) 409 if nulIndex < 0 { 410 // TODO(dfc) should this be ctxt.Diag ? 411 ctxt.Logf("corrupt .ARM.attributes (section name not NUL-terminated)\n") 412 return 413 } 414 name := string(sectiondata[:nulIndex]) 415 sectiondata = sectiondata[nulIndex+1:] 416 417 if name != "aeabi" { 418 continue 419 } 420 for len(sectiondata) != 0 { 421 subsectiontag, sz := binary.Uvarint(sectiondata) 422 subsectionsize := e.Uint32(sectiondata[sz:]) 423 subsectiondata := sectiondata[sz+4 : subsectionsize] 424 sectiondata = sectiondata[subsectionsize:] 425 426 if subsectiontag == TagFile { 427 attrList := elfAttributeList{data: subsectiondata} 428 for !attrList.done() { 429 attr := attrList.armAttr() 430 if attr.tag == TagABIVFPArgs && attr.ival == 1 { 431 ehdr.flags = 0x5000402 // has entry point, Version5 EABI, hard-float ABI 432 } 433 } 434 if attrList.err != nil { 435 // TODO(dfc) should this be ctxt.Diag ? 436 ctxt.Logf("could not parse .ARM.attributes\n") 437 } 438 } 439 } 440 } 441 } 442 443 func ldelf(ctxt *Link, f *bio.Reader, pkg string, length int64, pn string) { 444 if ctxt.Debugvlog != 0 { 445 ctxt.Logf("%5.2f ldelf %s\n", obj.Cputime(), pn) 446 } 447 448 localSymVersion := ctxt.Syms.IncVersion() 449 base := f.Offset() 450 451 var add uint64 452 var e binary.ByteOrder 453 var elfobj *ElfObj 454 var err error 455 var flag int 456 var hdr *ElfHdrBytes 457 var hdrbuf [64]uint8 458 var info uint64 459 var is64 int 460 var j int 461 var n int 462 var name string 463 var p []byte 464 var r []Reloc 465 var rela int 466 var rp *Reloc 467 var rsect *ElfSect 468 var s *Symbol 469 var sect *ElfSect 470 var sym ElfSym 471 var symbols []*Symbol 472 if _, err := io.ReadFull(f, hdrbuf[:]); err != nil { 473 goto bad 474 } 475 hdr = new(ElfHdrBytes) 476 binary.Read(bytes.NewReader(hdrbuf[:]), binary.BigEndian, hdr) // only byte arrays; byte order doesn't matter 477 if string(hdr.Ident[:4]) != "\x7FELF" { 478 goto bad 479 } 480 switch hdr.Ident[5] { 481 case ElfDataLsb: 482 e = binary.LittleEndian 483 484 case ElfDataMsb: 485 e = binary.BigEndian 486 487 default: 488 goto bad 489 } 490 491 // read header 492 elfobj = new(ElfObj) 493 494 elfobj.e = e 495 elfobj.f = f 496 elfobj.base = base 497 elfobj.length = length 498 elfobj.name = pn 499 500 is64 = 0 501 if hdr.Ident[4] == ElfClass64 { 502 is64 = 1 503 hdr := new(ElfHdrBytes64) 504 binary.Read(bytes.NewReader(hdrbuf[:]), binary.BigEndian, hdr) // only byte arrays; byte order doesn't matter 505 elfobj.type_ = uint32(e.Uint16(hdr.Type[:])) 506 elfobj.machine = uint32(e.Uint16(hdr.Machine[:])) 507 elfobj.version = e.Uint32(hdr.Version[:]) 508 elfobj.phoff = e.Uint64(hdr.Phoff[:]) 509 elfobj.shoff = e.Uint64(hdr.Shoff[:]) 510 elfobj.flags = e.Uint32(hdr.Flags[:]) 511 elfobj.ehsize = uint32(e.Uint16(hdr.Ehsize[:])) 512 elfobj.phentsize = uint32(e.Uint16(hdr.Phentsize[:])) 513 elfobj.phnum = uint32(e.Uint16(hdr.Phnum[:])) 514 elfobj.shentsize = uint32(e.Uint16(hdr.Shentsize[:])) 515 elfobj.shnum = uint32(e.Uint16(hdr.Shnum[:])) 516 elfobj.shstrndx = uint32(e.Uint16(hdr.Shstrndx[:])) 517 } else { 518 elfobj.type_ = uint32(e.Uint16(hdr.Type[:])) 519 elfobj.machine = uint32(e.Uint16(hdr.Machine[:])) 520 elfobj.version = e.Uint32(hdr.Version[:]) 521 elfobj.entry = uint64(e.Uint32(hdr.Entry[:])) 522 elfobj.phoff = uint64(e.Uint32(hdr.Phoff[:])) 523 elfobj.shoff = uint64(e.Uint32(hdr.Shoff[:])) 524 elfobj.flags = e.Uint32(hdr.Flags[:]) 525 elfobj.ehsize = uint32(e.Uint16(hdr.Ehsize[:])) 526 elfobj.phentsize = uint32(e.Uint16(hdr.Phentsize[:])) 527 elfobj.phnum = uint32(e.Uint16(hdr.Phnum[:])) 528 elfobj.shentsize = uint32(e.Uint16(hdr.Shentsize[:])) 529 elfobj.shnum = uint32(e.Uint16(hdr.Shnum[:])) 530 elfobj.shstrndx = uint32(e.Uint16(hdr.Shstrndx[:])) 531 } 532 533 elfobj.is64 = is64 534 535 if uint32(hdr.Ident[6]) != elfobj.version { 536 goto bad 537 } 538 539 if e.Uint16(hdr.Type[:]) != ElfTypeRelocatable { 540 Errorf(nil, "%s: elf but not elf relocatable object", pn) 541 return 542 } 543 544 switch SysArch.Family { 545 default: 546 Errorf(nil, "%s: elf %s unimplemented", pn, SysArch.Name) 547 return 548 549 case sys.MIPS64: 550 if elfobj.machine != ElfMachMips || hdr.Ident[4] != ElfClass64 { 551 Errorf(nil, "%s: elf object but not mips64", pn) 552 return 553 } 554 555 case sys.ARM: 556 if e != binary.LittleEndian || elfobj.machine != ElfMachArm || hdr.Ident[4] != ElfClass32 { 557 Errorf(nil, "%s: elf object but not arm", pn) 558 return 559 } 560 561 case sys.AMD64: 562 if e != binary.LittleEndian || elfobj.machine != ElfMachAmd64 || hdr.Ident[4] != ElfClass64 { 563 Errorf(nil, "%s: elf object but not amd64", pn) 564 return 565 } 566 567 case sys.ARM64: 568 if e != binary.LittleEndian || elfobj.machine != ElfMachArm64 || hdr.Ident[4] != ElfClass64 { 569 Errorf(nil, "%s: elf object but not arm64", pn) 570 return 571 } 572 573 case sys.I386: 574 if e != binary.LittleEndian || elfobj.machine != ElfMach386 || hdr.Ident[4] != ElfClass32 { 575 Errorf(nil, "%s: elf object but not 386", pn) 576 return 577 } 578 579 case sys.PPC64: 580 if elfobj.machine != ElfMachPower64 || hdr.Ident[4] != ElfClass64 { 581 Errorf(nil, "%s: elf object but not ppc64", pn) 582 return 583 } 584 585 case sys.S390X: 586 if elfobj.machine != ElfMachS390 || hdr.Ident[4] != ElfClass64 { 587 Errorf(nil, "%s: elf object but not s390x", pn) 588 return 589 } 590 } 591 592 // load section list into memory. 593 elfobj.sect = make([]ElfSect, elfobj.shnum) 594 595 elfobj.nsect = uint(elfobj.shnum) 596 for i := 0; uint(i) < elfobj.nsect; i++ { 597 if f.Seek(int64(uint64(base)+elfobj.shoff+uint64(int64(i)*int64(elfobj.shentsize))), 0) < 0 { 598 goto bad 599 } 600 sect = &elfobj.sect[i] 601 if is64 != 0 { 602 var b ElfSectBytes64 603 604 if err = binary.Read(f, e, &b); err != nil { 605 goto bad 606 } 607 608 sect.nameoff = e.Uint32(b.Name[:]) 609 sect.type_ = e.Uint32(b.Type[:]) 610 sect.flags = e.Uint64(b.Flags[:]) 611 sect.addr = e.Uint64(b.Addr[:]) 612 sect.off = e.Uint64(b.Off[:]) 613 sect.size = e.Uint64(b.Size[:]) 614 sect.link = e.Uint32(b.Link[:]) 615 sect.info = e.Uint32(b.Info[:]) 616 sect.align = e.Uint64(b.Align[:]) 617 sect.entsize = e.Uint64(b.Entsize[:]) 618 } else { 619 var b ElfSectBytes 620 621 if err = binary.Read(f, e, &b); err != nil { 622 goto bad 623 } 624 625 sect.nameoff = e.Uint32(b.Name[:]) 626 sect.type_ = e.Uint32(b.Type[:]) 627 sect.flags = uint64(e.Uint32(b.Flags[:])) 628 sect.addr = uint64(e.Uint32(b.Addr[:])) 629 sect.off = uint64(e.Uint32(b.Off[:])) 630 sect.size = uint64(e.Uint32(b.Size[:])) 631 sect.link = e.Uint32(b.Link[:]) 632 sect.info = e.Uint32(b.Info[:]) 633 sect.align = uint64(e.Uint32(b.Align[:])) 634 sect.entsize = uint64(e.Uint32(b.Entsize[:])) 635 } 636 } 637 638 // read section string table and translate names 639 if elfobj.shstrndx >= uint32(elfobj.nsect) { 640 err = fmt.Errorf("shstrndx out of range %d >= %d", elfobj.shstrndx, elfobj.nsect) 641 goto bad 642 } 643 644 sect = &elfobj.sect[elfobj.shstrndx] 645 if err = elfmap(elfobj, sect); err != nil { 646 goto bad 647 } 648 for i := 0; uint(i) < elfobj.nsect; i++ { 649 if elfobj.sect[i].nameoff != 0 { 650 elfobj.sect[i].name = cstring(sect.base[elfobj.sect[i].nameoff:]) 651 } 652 } 653 654 // load string table for symbols into memory. 655 elfobj.symtab = section(elfobj, ".symtab") 656 657 if elfobj.symtab == nil { 658 // our work is done here - no symbols means nothing can refer to this file 659 return 660 } 661 662 if elfobj.symtab.link <= 0 || elfobj.symtab.link >= uint32(elfobj.nsect) { 663 Errorf(nil, "%s: elf object has symbol table with invalid string table link", pn) 664 return 665 } 666 667 elfobj.symstr = &elfobj.sect[elfobj.symtab.link] 668 if is64 != 0 { 669 elfobj.nsymtab = int(elfobj.symtab.size / ELF64SYMSIZE) 670 } else { 671 elfobj.nsymtab = int(elfobj.symtab.size / ELF32SYMSIZE) 672 } 673 674 if err = elfmap(elfobj, elfobj.symtab); err != nil { 675 goto bad 676 } 677 if err = elfmap(elfobj, elfobj.symstr); err != nil { 678 goto bad 679 } 680 681 // load text and data segments into memory. 682 // they are not as small as the section lists, but we'll need 683 // the memory anyway for the symbol images, so we might 684 // as well use one large chunk. 685 686 // create symbols for elfmapped sections 687 for i := 0; uint(i) < elfobj.nsect; i++ { 688 sect = &elfobj.sect[i] 689 if sect.type_ == SHT_ARM_ATTRIBUTES && sect.name == ".ARM.attributes" { 690 if err = elfmap(elfobj, sect); err != nil { 691 goto bad 692 } 693 parseArmAttributes(ctxt, e, sect.base[:sect.size]) 694 } 695 if (sect.type_ != ElfSectProgbits && sect.type_ != ElfSectNobits) || sect.flags&ElfSectFlagAlloc == 0 { 696 continue 697 } 698 if sect.type_ != ElfSectNobits { 699 if err = elfmap(elfobj, sect); err != nil { 700 goto bad 701 } 702 } 703 704 name = fmt.Sprintf("%s(%s)", pkg, sect.name) 705 s = ctxt.Syms.Lookup(name, localSymVersion) 706 707 switch int(sect.flags) & (ElfSectFlagAlloc | ElfSectFlagWrite | ElfSectFlagExec) { 708 default: 709 err = fmt.Errorf("unexpected flags for ELF section %s", sect.name) 710 goto bad 711 712 case ElfSectFlagAlloc: 713 s.Type = obj.SRODATA 714 715 case ElfSectFlagAlloc + ElfSectFlagWrite: 716 if sect.type_ == ElfSectNobits { 717 s.Type = obj.SNOPTRBSS 718 } else { 719 s.Type = obj.SNOPTRDATA 720 } 721 722 case ElfSectFlagAlloc + ElfSectFlagExec: 723 s.Type = obj.STEXT 724 } 725 726 if sect.name == ".got" || sect.name == ".toc" { 727 s.Type = obj.SELFGOT 728 } 729 if sect.type_ == ElfSectProgbits { 730 s.P = sect.base 731 s.P = s.P[:sect.size] 732 } 733 734 s.Size = int64(sect.size) 735 s.Align = int32(sect.align) 736 sect.sym = s 737 } 738 739 // enter sub-symbols into symbol table. 740 // symbol 0 is the null symbol. 741 symbols = make([]*Symbol, elfobj.nsymtab) 742 743 for i := 1; i < elfobj.nsymtab; i++ { 744 if err = readelfsym(ctxt, elfobj, i, &sym, 1, localSymVersion); err != nil { 745 goto bad 746 } 747 symbols[i] = sym.sym 748 if sym.type_ != ElfSymTypeFunc && sym.type_ != ElfSymTypeObject && sym.type_ != ElfSymTypeNone { 749 continue 750 } 751 if sym.shndx == ElfSymShnCommon { 752 s = sym.sym 753 if uint64(s.Size) < sym.size { 754 s.Size = int64(sym.size) 755 } 756 if s.Type == 0 || s.Type == obj.SXREF { 757 s.Type = obj.SNOPTRBSS 758 } 759 continue 760 } 761 762 if uint(sym.shndx) >= elfobj.nsect || sym.shndx == 0 { 763 continue 764 } 765 766 // even when we pass needSym == 1 to readelfsym, it might still return nil to skip some unwanted symbols 767 if sym.sym == nil { 768 continue 769 } 770 sect = &elfobj.sect[sym.shndx] 771 if sect.sym == nil { 772 if strings.HasPrefix(sym.name, ".Linfo_string") { // clang does this 773 continue 774 } 775 776 if sym.name == "" && sym.type_ == 0 && sect.name == ".debug_str" { 777 // This reportedly happens with clang 3.7 on ARM. 778 // See issue 13139. 779 continue 780 } 781 782 if strings.HasPrefix(sym.name, ".LASF") { // gcc on s390x does this 783 continue 784 } 785 Errorf(sym.sym, "%s: sym#%d: ignoring symbol in section %d (type %d)", pn, i, sym.shndx, sym.type_) 786 continue 787 } 788 789 s = sym.sym 790 if s.Outer != nil { 791 if s.Attr.DuplicateOK() { 792 continue 793 } 794 Exitf("%s: duplicate symbol reference: %s in both %s and %s", pn, s.Name, s.Outer.Name, sect.sym.Name) 795 } 796 797 s.Sub = sect.sym.Sub 798 sect.sym.Sub = s 799 s.Type = sect.sym.Type | s.Type&^obj.SMASK | obj.SSUB 800 if !s.Attr.CgoExportDynamic() { 801 s.Dynimplib = "" // satisfy dynimport 802 } 803 s.Value = int64(sym.value) 804 s.Size = int64(sym.size) 805 s.Outer = sect.sym 806 if sect.sym.Type == obj.STEXT { 807 if s.Attr.External() && !s.Attr.DuplicateOK() { 808 Errorf(s, "%s: duplicate symbol definition", pn) 809 } 810 s.Attr |= AttrExternal 811 } 812 813 if elfobj.machine == ElfMachPower64 { 814 flag = int(sym.other) >> 5 815 if 2 <= flag && flag <= 6 { 816 s.Localentry = 1 << uint(flag-2) 817 } else if flag == 7 { 818 Errorf(s, "%s: invalid sym.other 0x%x", pn, sym.other) 819 } 820 } 821 } 822 823 // Sort outer lists by address, adding to textp. 824 // This keeps textp in increasing address order. 825 for i := 0; uint(i) < elfobj.nsect; i++ { 826 s = elfobj.sect[i].sym 827 if s == nil { 828 continue 829 } 830 if s.Sub != nil { 831 s.Sub = listsort(s.Sub) 832 } 833 if s.Type == obj.STEXT { 834 if s.Attr.OnList() { 835 log.Fatalf("symbol %s listed multiple times", s.Name) 836 } 837 s.Attr |= AttrOnList 838 ctxt.Textp = append(ctxt.Textp, s) 839 for s = s.Sub; s != nil; s = s.Sub { 840 if s.Attr.OnList() { 841 log.Fatalf("symbol %s listed multiple times", s.Name) 842 } 843 s.Attr |= AttrOnList 844 ctxt.Textp = append(ctxt.Textp, s) 845 } 846 } 847 } 848 849 // load relocations 850 for i := 0; uint(i) < elfobj.nsect; i++ { 851 rsect = &elfobj.sect[i] 852 if rsect.type_ != ElfSectRela && rsect.type_ != ElfSectRel { 853 continue 854 } 855 if rsect.info >= uint32(elfobj.nsect) || elfobj.sect[rsect.info].base == nil { 856 continue 857 } 858 sect = &elfobj.sect[rsect.info] 859 if err = elfmap(elfobj, rsect); err != nil { 860 goto bad 861 } 862 rela = 0 863 if rsect.type_ == ElfSectRela { 864 rela = 1 865 } 866 n = int(rsect.size / uint64(4+4*is64) / uint64(2+rela)) 867 r = make([]Reloc, n) 868 p = rsect.base 869 for j = 0; j < n; j++ { 870 add = 0 871 rp = &r[j] 872 if is64 != 0 { 873 // 64-bit rel/rela 874 rp.Off = int32(e.Uint64(p)) 875 876 p = p[8:] 877 info = e.Uint64(p) 878 p = p[8:] 879 if rela != 0 { 880 add = e.Uint64(p) 881 p = p[8:] 882 } 883 } else { 884 // 32-bit rel/rela 885 rp.Off = int32(e.Uint32(p)) 886 887 p = p[4:] 888 info = uint64(e.Uint32(p)) 889 info = info>>8<<32 | info&0xff // convert to 64-bit info 890 p = p[4:] 891 if rela != 0 { 892 add = uint64(e.Uint32(p)) 893 p = p[4:] 894 } 895 } 896 897 if info&0xffffffff == 0 { // skip R_*_NONE relocation 898 j-- 899 n-- 900 continue 901 } 902 903 if info>>32 == 0 { // absolute relocation, don't bother reading the null symbol 904 rp.Sym = nil 905 } else { 906 if err = readelfsym(ctxt, elfobj, int(info>>32), &sym, 0, 0); err != nil { 907 goto bad 908 } 909 sym.sym = symbols[info>>32] 910 if sym.sym == nil { 911 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_) 912 goto bad 913 } 914 915 rp.Sym = sym.sym 916 } 917 918 rp.Type = 256 + obj.RelocType(info) 919 rp.Siz = relSize(ctxt, pn, uint32(info)) 920 if rela != 0 { 921 rp.Add = int64(add) 922 } else { 923 // load addend from image 924 if rp.Siz == 4 { 925 rp.Add = int64(e.Uint32(sect.base[rp.Off:])) 926 } else if rp.Siz == 8 { 927 rp.Add = int64(e.Uint64(sect.base[rp.Off:])) 928 } else { 929 Errorf(nil, "invalid rela size %d", rp.Siz) 930 } 931 } 932 933 if rp.Siz == 2 { 934 rp.Add = int64(int16(rp.Add)) 935 } 936 if rp.Siz == 4 { 937 rp.Add = int64(int32(rp.Add)) 938 } 939 } 940 941 //print("rel %s %d %d %s %#llx\n", sect->sym->name, rp->type, rp->siz, rp->sym->name, rp->add); 942 sort.Sort(rbyoff(r[:n])) 943 // just in case 944 945 s = sect.sym 946 s.R = r 947 s.R = s.R[:n] 948 } 949 950 return 951 952 bad: 953 Errorf(nil, "%s: malformed elf file: %v", pn, err) 954 } 955 956 func section(elfobj *ElfObj, name string) *ElfSect { 957 for i := 0; uint(i) < elfobj.nsect; i++ { 958 if elfobj.sect[i].name != "" && name != "" && elfobj.sect[i].name == name { 959 return &elfobj.sect[i] 960 } 961 } 962 return nil 963 } 964 965 func elfmap(elfobj *ElfObj, sect *ElfSect) (err error) { 966 if sect.base != nil { 967 return nil 968 } 969 970 if sect.off+sect.size > uint64(elfobj.length) { 971 err = fmt.Errorf("elf section past end of file") 972 return err 973 } 974 975 sect.base = make([]byte, sect.size) 976 if elfobj.f.Seek(int64(uint64(elfobj.base)+sect.off), 0) < 0 { 977 return fmt.Errorf("short read: seek not successful") 978 } 979 if _, err := io.ReadFull(elfobj.f, sect.base); err != nil { 980 return fmt.Errorf("short read: %v", err) 981 } 982 983 return nil 984 } 985 986 func readelfsym(ctxt *Link, elfobj *ElfObj, i int, sym *ElfSym, needSym int, localSymVersion int) (err error) { 987 if i >= elfobj.nsymtab || i < 0 { 988 err = fmt.Errorf("invalid elf symbol index") 989 return err 990 } 991 992 if i == 0 { 993 Errorf(nil, "readym: read null symbol!") 994 } 995 996 if elfobj.is64 != 0 { 997 b := new(ElfSymBytes64) 998 binary.Read(bytes.NewReader(elfobj.symtab.base[i*ELF64SYMSIZE:(i+1)*ELF64SYMSIZE]), elfobj.e, b) 999 sym.name = cstring(elfobj.symstr.base[elfobj.e.Uint32(b.Name[:]):]) 1000 sym.value = elfobj.e.Uint64(b.Value[:]) 1001 sym.size = elfobj.e.Uint64(b.Size[:]) 1002 sym.shndx = elfobj.e.Uint16(b.Shndx[:]) 1003 sym.bind = b.Info >> 4 1004 sym.type_ = b.Info & 0xf 1005 sym.other = b.Other 1006 } else { 1007 b := new(ElfSymBytes) 1008 binary.Read(bytes.NewReader(elfobj.symtab.base[i*ELF32SYMSIZE:(i+1)*ELF32SYMSIZE]), elfobj.e, b) 1009 sym.name = cstring(elfobj.symstr.base[elfobj.e.Uint32(b.Name[:]):]) 1010 sym.value = uint64(elfobj.e.Uint32(b.Value[:])) 1011 sym.size = uint64(elfobj.e.Uint32(b.Size[:])) 1012 sym.shndx = elfobj.e.Uint16(b.Shndx[:]) 1013 sym.bind = b.Info >> 4 1014 sym.type_ = b.Info & 0xf 1015 sym.other = b.Other 1016 } 1017 1018 var s *Symbol 1019 if sym.name == "_GLOBAL_OFFSET_TABLE_" { 1020 sym.name = ".got" 1021 } 1022 if sym.name == ".TOC." { 1023 // Magic symbol on ppc64. Will be set to this object 1024 // file's .got+0x8000. 1025 sym.bind = ElfSymBindLocal 1026 } 1027 1028 switch sym.type_ { 1029 case ElfSymTypeSection: 1030 s = elfobj.sect[sym.shndx].sym 1031 1032 case ElfSymTypeObject, ElfSymTypeFunc, ElfSymTypeNone: 1033 switch sym.bind { 1034 case ElfSymBindGlobal: 1035 if needSym != 0 { 1036 s = ctxt.Syms.Lookup(sym.name, 0) 1037 1038 // for global scoped hidden symbols we should insert it into 1039 // symbol hash table, but mark them as hidden. 1040 // __i686.get_pc_thunk.bx is allowed to be duplicated, to 1041 // workaround that we set dupok. 1042 // TODO(minux): correctly handle __i686.get_pc_thunk.bx without 1043 // set dupok generally. See http://codereview.appspot.com/5823055/ 1044 // comment #5 for details. 1045 if s != nil && sym.other == 2 { 1046 s.Type |= obj.SHIDDEN 1047 s.Attr |= AttrDuplicateOK 1048 } 1049 } 1050 1051 case ElfSymBindLocal: 1052 if SysArch.Family == sys.ARM && (strings.HasPrefix(sym.name, "$a") || strings.HasPrefix(sym.name, "$d")) { 1053 // binutils for arm generate these mapping 1054 // symbols, ignore these 1055 break 1056 } 1057 1058 if sym.name == ".TOC." { 1059 // We need to be able to look this up, 1060 // so put it in the hash table. 1061 if needSym != 0 { 1062 s = ctxt.Syms.Lookup(sym.name, localSymVersion) 1063 s.Type |= obj.SHIDDEN 1064 } 1065 1066 break 1067 } 1068 1069 if needSym != 0 { 1070 // local names and hidden global names are unique 1071 // and should only be referenced by their index, not name, so we 1072 // don't bother to add them into the hash table 1073 s = ctxt.Syms.newsym(sym.name, localSymVersion) 1074 1075 s.Type |= obj.SHIDDEN 1076 } 1077 1078 case ElfSymBindWeak: 1079 if needSym != 0 { 1080 s = ctxt.Syms.Lookup(sym.name, 0) 1081 if sym.other == 2 { 1082 s.Type |= obj.SHIDDEN 1083 } 1084 } 1085 1086 default: 1087 err = fmt.Errorf("%s: invalid symbol binding %d", sym.name, sym.bind) 1088 return err 1089 } 1090 } 1091 1092 if s != nil && s.Type == 0 && sym.type_ != ElfSymTypeSection { 1093 s.Type = obj.SXREF 1094 } 1095 sym.sym = s 1096 1097 return nil 1098 } 1099 1100 type rbyoff []Reloc 1101 1102 func (x rbyoff) Len() int { 1103 return len(x) 1104 } 1105 1106 func (x rbyoff) Swap(i, j int) { 1107 x[i], x[j] = x[j], x[i] 1108 } 1109 1110 func (x rbyoff) Less(i, j int) bool { 1111 a := &x[i] 1112 b := &x[j] 1113 if a.Off < b.Off { 1114 return true 1115 } 1116 if a.Off > b.Off { 1117 return false 1118 } 1119 return false 1120 } 1121 1122 func relSize(ctxt *Link, pn string, elftype uint32) uint8 { 1123 // TODO(mdempsky): Replace this with a struct-valued switch statement 1124 // once golang.org/issue/15164 is fixed or found to not impair cmd/link 1125 // performance. 1126 1127 const ( 1128 AMD64 = uint32(sys.AMD64) 1129 ARM = uint32(sys.ARM) 1130 I386 = uint32(sys.I386) 1131 PPC64 = uint32(sys.PPC64) 1132 S390X = uint32(sys.S390X) 1133 ) 1134 1135 switch uint32(SysArch.Family) | elftype<<24 { 1136 default: 1137 Errorf(nil, "%s: unknown relocation type %d; compiled without -fpic?", pn, elftype) 1138 fallthrough 1139 1140 case S390X | R_390_8<<24: 1141 return 1 1142 1143 case PPC64 | R_PPC64_TOC16<<24, 1144 PPC64 | R_PPC64_TOC16_LO<<24, 1145 PPC64 | R_PPC64_TOC16_HI<<24, 1146 PPC64 | R_PPC64_TOC16_HA<<24, 1147 PPC64 | R_PPC64_TOC16_DS<<24, 1148 PPC64 | R_PPC64_TOC16_LO_DS<<24, 1149 PPC64 | R_PPC64_REL16_LO<<24, 1150 PPC64 | R_PPC64_REL16_HI<<24, 1151 PPC64 | R_PPC64_REL16_HA<<24, 1152 S390X | R_390_16<<24, 1153 S390X | R_390_GOT16<<24, 1154 S390X | R_390_PC16<<24, 1155 S390X | R_390_PC16DBL<<24, 1156 S390X | R_390_PLT16DBL<<24: 1157 return 2 1158 1159 case ARM | R_ARM_ABS32<<24, 1160 ARM | R_ARM_GOT32<<24, 1161 ARM | R_ARM_PLT32<<24, 1162 ARM | R_ARM_GOTOFF<<24, 1163 ARM | R_ARM_GOTPC<<24, 1164 ARM | R_ARM_THM_PC22<<24, 1165 ARM | R_ARM_REL32<<24, 1166 ARM | R_ARM_CALL<<24, 1167 ARM | R_ARM_V4BX<<24, 1168 ARM | R_ARM_GOT_PREL<<24, 1169 ARM | R_ARM_PC24<<24, 1170 ARM | R_ARM_JUMP24<<24, 1171 AMD64 | R_X86_64_PC32<<24, 1172 AMD64 | R_X86_64_PLT32<<24, 1173 AMD64 | R_X86_64_GOTPCREL<<24, 1174 AMD64 | R_X86_64_GOTPCRELX<<24, 1175 AMD64 | R_X86_64_REX_GOTPCRELX<<24, 1176 I386 | R_386_32<<24, 1177 I386 | R_386_PC32<<24, 1178 I386 | R_386_GOT32<<24, 1179 I386 | R_386_PLT32<<24, 1180 I386 | R_386_GOTOFF<<24, 1181 I386 | R_386_GOTPC<<24, 1182 I386 | R_386_GOT32X<<24, 1183 PPC64 | R_PPC64_REL24<<24, 1184 PPC64 | R_PPC_REL32<<24, 1185 S390X | R_390_32<<24, 1186 S390X | R_390_PC32<<24, 1187 S390X | R_390_GOT32<<24, 1188 S390X | R_390_PLT32<<24, 1189 S390X | R_390_PC32DBL<<24, 1190 S390X | R_390_PLT32DBL<<24, 1191 S390X | R_390_GOTPCDBL<<24, 1192 S390X | R_390_GOTENT<<24: 1193 return 4 1194 1195 case AMD64 | R_X86_64_64<<24, 1196 PPC64 | R_PPC64_ADDR64<<24, 1197 S390X | R_390_GLOB_DAT<<24, 1198 S390X | R_390_RELATIVE<<24, 1199 S390X | R_390_GOTOFF<<24, 1200 S390X | R_390_GOTPC<<24, 1201 S390X | R_390_64<<24, 1202 S390X | R_390_PC64<<24, 1203 S390X | R_390_GOT64<<24, 1204 S390X | R_390_PLT64<<24: 1205 return 8 1206 } 1207 }