github.com/d4l3k/go@v0.0.0-20151015000803-65fc379daeda/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 '5': 555 if e != binary.LittleEndian || elfobj.machine != ElfMachArm || hdr.Ident[4] != ElfClass32 { 556 Diag("%s: elf object but not arm", pn) 557 return 558 } 559 560 case '6': 561 if e != binary.LittleEndian || elfobj.machine != ElfMachAmd64 || hdr.Ident[4] != ElfClass64 { 562 Diag("%s: elf object but not amd64", pn) 563 return 564 } 565 566 case '7': 567 if e != binary.LittleEndian || elfobj.machine != ElfMachArm64 || hdr.Ident[4] != ElfClass64 { 568 Diag("%s: elf object but not arm64", pn) 569 return 570 } 571 572 case '8': 573 if e != binary.LittleEndian || elfobj.machine != ElfMach386 || hdr.Ident[4] != ElfClass32 { 574 Diag("%s: elf object but not 386", pn) 575 return 576 } 577 578 case '9': 579 if elfobj.machine != ElfMachPower64 || hdr.Ident[4] != ElfClass64 { 580 Diag("%s: elf object but not ppc64", pn) 581 return 582 } 583 } 584 585 // load section list into memory. 586 elfobj.sect = make([]ElfSect, elfobj.shnum) 587 588 elfobj.nsect = uint(elfobj.shnum) 589 for i := 0; uint(i) < elfobj.nsect; i++ { 590 if obj.Bseek(f, int64(uint64(base)+elfobj.shoff+uint64(int64(i)*int64(elfobj.shentsize))), 0) < 0 { 591 goto bad 592 } 593 sect = &elfobj.sect[i] 594 if is64 != 0 { 595 var b ElfSectBytes64 596 597 if err = binary.Read(f, e, &b); err != nil { 598 goto bad 599 } 600 601 sect.nameoff = uint32(e.Uint32(b.Name[:])) 602 sect.type_ = e.Uint32(b.Type[:]) 603 sect.flags = e.Uint64(b.Flags[:]) 604 sect.addr = e.Uint64(b.Addr[:]) 605 sect.off = e.Uint64(b.Off[:]) 606 sect.size = e.Uint64(b.Size[:]) 607 sect.link = e.Uint32(b.Link[:]) 608 sect.info = e.Uint32(b.Info[:]) 609 sect.align = e.Uint64(b.Align[:]) 610 sect.entsize = e.Uint64(b.Entsize[:]) 611 } else { 612 var b ElfSectBytes 613 614 if err = binary.Read(f, e, &b); err != nil { 615 goto bad 616 } 617 618 sect.nameoff = uint32(e.Uint32(b.Name[:])) 619 sect.type_ = e.Uint32(b.Type[:]) 620 sect.flags = uint64(e.Uint32(b.Flags[:])) 621 sect.addr = uint64(e.Uint32(b.Addr[:])) 622 sect.off = uint64(e.Uint32(b.Off[:])) 623 sect.size = uint64(e.Uint32(b.Size[:])) 624 sect.link = e.Uint32(b.Link[:]) 625 sect.info = e.Uint32(b.Info[:]) 626 sect.align = uint64(e.Uint32(b.Align[:])) 627 sect.entsize = uint64(e.Uint32(b.Entsize[:])) 628 } 629 } 630 631 // read section string table and translate names 632 if elfobj.shstrndx >= uint32(elfobj.nsect) { 633 err = fmt.Errorf("shstrndx out of range %d >= %d", elfobj.shstrndx, elfobj.nsect) 634 goto bad 635 } 636 637 sect = &elfobj.sect[elfobj.shstrndx] 638 if err = elfmap(elfobj, sect); err != nil { 639 goto bad 640 } 641 for i := 0; uint(i) < elfobj.nsect; i++ { 642 if elfobj.sect[i].nameoff != 0 { 643 elfobj.sect[i].name = cstring(sect.base[elfobj.sect[i].nameoff:]) 644 } 645 } 646 647 // load string table for symbols into memory. 648 elfobj.symtab = section(elfobj, ".symtab") 649 650 if elfobj.symtab == nil { 651 // our work is done here - no symbols means nothing can refer to this file 652 return 653 } 654 655 if elfobj.symtab.link <= 0 || elfobj.symtab.link >= uint32(elfobj.nsect) { 656 Diag("%s: elf object has symbol table with invalid string table link", pn) 657 return 658 } 659 660 elfobj.symstr = &elfobj.sect[elfobj.symtab.link] 661 if is64 != 0 { 662 elfobj.nsymtab = int(elfobj.symtab.size / ELF64SYMSIZE) 663 } else { 664 elfobj.nsymtab = int(elfobj.symtab.size / ELF32SYMSIZE) 665 } 666 667 if err = elfmap(elfobj, elfobj.symtab); err != nil { 668 goto bad 669 } 670 if err = elfmap(elfobj, elfobj.symstr); err != nil { 671 goto bad 672 } 673 674 // load text and data segments into memory. 675 // they are not as small as the section lists, but we'll need 676 // the memory anyway for the symbol images, so we might 677 // as well use one large chunk. 678 679 // create symbols for elfmapped sections 680 for i := 0; uint(i) < elfobj.nsect; i++ { 681 sect = &elfobj.sect[i] 682 if sect.type_ == SHT_ARM_ATTRIBUTES && sect.name == ".ARM.attributes" { 683 if err = elfmap(elfobj, sect); err != nil { 684 goto bad 685 } 686 parseArmAttributes(e, sect.base[:sect.size]) 687 } 688 if (sect.type_ != ElfSectProgbits && sect.type_ != ElfSectNobits) || sect.flags&ElfSectFlagAlloc == 0 { 689 continue 690 } 691 if sect.type_ != ElfSectNobits { 692 if err = elfmap(elfobj, sect); err != nil { 693 goto bad 694 } 695 } 696 697 name = fmt.Sprintf("%s(%s)", pkg, sect.name) 698 s = Linklookup(Ctxt, name, Ctxt.Version) 699 700 switch int(sect.flags) & (ElfSectFlagAlloc | ElfSectFlagWrite | ElfSectFlagExec) { 701 default: 702 err = fmt.Errorf("unexpected flags for ELF section %s", sect.name) 703 goto bad 704 705 case ElfSectFlagAlloc: 706 s.Type = obj.SRODATA 707 708 case ElfSectFlagAlloc + ElfSectFlagWrite: 709 if sect.type_ == ElfSectNobits { 710 s.Type = obj.SNOPTRBSS 711 } else { 712 s.Type = obj.SNOPTRDATA 713 } 714 715 case ElfSectFlagAlloc + ElfSectFlagExec: 716 s.Type = obj.STEXT 717 } 718 719 if sect.name == ".got" || sect.name == ".toc" { 720 s.Type = obj.SELFGOT 721 } 722 if sect.type_ == ElfSectProgbits { 723 s.P = sect.base 724 s.P = s.P[:sect.size] 725 } 726 727 s.Size = int64(sect.size) 728 s.Align = int32(sect.align) 729 sect.sym = s 730 } 731 732 // enter sub-symbols into symbol table. 733 // symbol 0 is the null symbol. 734 symbols = make([]*LSym, elfobj.nsymtab) 735 736 for i := 1; i < elfobj.nsymtab; i++ { 737 if err = readelfsym(elfobj, i, &sym, 1); err != nil { 738 goto bad 739 } 740 symbols[i] = sym.sym 741 if sym.type_ != ElfSymTypeFunc && sym.type_ != ElfSymTypeObject && sym.type_ != ElfSymTypeNone { 742 continue 743 } 744 if sym.shndx == ElfSymShnCommon { 745 s = sym.sym 746 if uint64(s.Size) < sym.size { 747 s.Size = int64(sym.size) 748 } 749 if s.Type == 0 || s.Type == obj.SXREF { 750 s.Type = obj.SNOPTRBSS 751 } 752 continue 753 } 754 755 if uint(sym.shndx) >= elfobj.nsect || sym.shndx == 0 { 756 continue 757 } 758 759 // even when we pass needSym == 1 to readelfsym, it might still return nil to skip some unwanted symbols 760 if sym.sym == nil { 761 continue 762 } 763 sect = &elfobj.sect[sym.shndx:][0] 764 if sect.sym == nil { 765 if strings.HasPrefix(sym.name, ".Linfo_string") { // clang does this 766 continue 767 } 768 Diag("%s: sym#%d: ignoring %s in section %d (type %d)", pn, i, sym.name, sym.shndx, sym.type_) 769 continue 770 } 771 772 s = sym.sym 773 if s.Outer != nil { 774 if s.Dupok != 0 { 775 continue 776 } 777 Exitf("%s: duplicate symbol reference: %s in both %s and %s", pn, s.Name, s.Outer.Name, sect.sym.Name) 778 } 779 780 s.Sub = sect.sym.Sub 781 sect.sym.Sub = s 782 s.Type = sect.sym.Type | s.Type&^obj.SMASK | obj.SSUB 783 if s.Cgoexport&CgoExportDynamic == 0 { 784 s.Dynimplib = "" // satisfy dynimport 785 } 786 s.Value = int64(sym.value) 787 s.Size = int64(sym.size) 788 s.Outer = sect.sym 789 if sect.sym.Type == obj.STEXT { 790 if s.External != 0 && s.Dupok == 0 { 791 Diag("%s: duplicate definition of %s", pn, s.Name) 792 } 793 s.External = 1 794 } 795 796 if elfobj.machine == ElfMachPower64 { 797 flag = int(sym.other) >> 5 798 if 2 <= flag && flag <= 6 { 799 s.Localentry = 1 << uint(flag-2) 800 } else if flag == 7 { 801 Diag("%s: invalid sym.other 0x%x for %s", pn, sym.other, s.Name) 802 } 803 } 804 } 805 806 // Sort outer lists by address, adding to textp. 807 // This keeps textp in increasing address order. 808 for i := 0; uint(i) < elfobj.nsect; i++ { 809 s = elfobj.sect[i].sym 810 if s == nil { 811 continue 812 } 813 if s.Sub != nil { 814 s.Sub = listsort(s.Sub, valuecmp, listsubp) 815 } 816 if s.Type == obj.STEXT { 817 if s.Onlist != 0 { 818 log.Fatalf("symbol %s listed multiple times", s.Name) 819 } 820 s.Onlist = 1 821 if Ctxt.Etextp != nil { 822 Ctxt.Etextp.Next = s 823 } else { 824 Ctxt.Textp = s 825 } 826 Ctxt.Etextp = s 827 for s = s.Sub; s != nil; s = s.Sub { 828 if s.Onlist != 0 { 829 log.Fatalf("symbol %s listed multiple times", s.Name) 830 } 831 s.Onlist = 1 832 Ctxt.Etextp.Next = s 833 Ctxt.Etextp = s 834 } 835 } 836 } 837 838 // load relocations 839 for i := 0; uint(i) < elfobj.nsect; i++ { 840 rsect = &elfobj.sect[i] 841 if rsect.type_ != ElfSectRela && rsect.type_ != ElfSectRel { 842 continue 843 } 844 if rsect.info >= uint32(elfobj.nsect) || elfobj.sect[rsect.info].base == nil { 845 continue 846 } 847 sect = &elfobj.sect[rsect.info] 848 if err = elfmap(elfobj, rsect); err != nil { 849 goto bad 850 } 851 rela = 0 852 if rsect.type_ == ElfSectRela { 853 rela = 1 854 } 855 n = int(rsect.size / uint64(4+4*is64) / uint64(2+rela)) 856 r = make([]Reloc, n) 857 p = rsect.base 858 for j = 0; j < n; j++ { 859 add = 0 860 rp = &r[j] 861 if is64 != 0 { 862 // 64-bit rel/rela 863 rp.Off = int32(e.Uint64(p)) 864 865 p = p[8:] 866 info = e.Uint64(p) 867 p = p[8:] 868 if rela != 0 { 869 add = e.Uint64(p) 870 p = p[8:] 871 } 872 } else { 873 // 32-bit rel/rela 874 rp.Off = int32(e.Uint32(p)) 875 876 p = p[4:] 877 info = uint64(e.Uint32(p)) 878 info = info>>8<<32 | info&0xff // convert to 64-bit info 879 p = p[4:] 880 if rela != 0 { 881 add = uint64(e.Uint32(p)) 882 p = p[4:] 883 } 884 } 885 886 if info&0xffffffff == 0 { // skip R_*_NONE relocation 887 j-- 888 n-- 889 continue 890 } 891 892 if info>>32 == 0 { // absolute relocation, don't bother reading the null symbol 893 rp.Sym = nil 894 } else { 895 if err = readelfsym(elfobj, int(info>>32), &sym, 0); err != nil { 896 goto bad 897 } 898 sym.sym = symbols[info>>32] 899 if sym.sym == nil { 900 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_) 901 goto bad 902 } 903 904 rp.Sym = sym.sym 905 } 906 907 rp.Type = int32(reltype(pn, int(uint32(info)), &rp.Siz)) 908 if rela != 0 { 909 rp.Add = int64(add) 910 } else { 911 // load addend from image 912 if rp.Siz == 4 { 913 rp.Add = int64(e.Uint32(sect.base[rp.Off:])) 914 } else if rp.Siz == 8 { 915 rp.Add = int64(e.Uint64(sect.base[rp.Off:])) 916 } else { 917 Diag("invalid rela size %d", rp.Siz) 918 } 919 } 920 921 if rp.Siz == 2 { 922 rp.Add = int64(int16(rp.Add)) 923 } 924 if rp.Siz == 4 { 925 rp.Add = int64(int32(rp.Add)) 926 } 927 } 928 929 //print("rel %s %d %d %s %#llx\n", sect->sym->name, rp->type, rp->siz, rp->sym->name, rp->add); 930 sort.Sort(rbyoff(r[:n])) 931 // just in case 932 933 s = sect.sym 934 s.R = r 935 s.R = s.R[:n] 936 } 937 938 return 939 940 bad: 941 Diag("%s: malformed elf file: %v", pn, err) 942 } 943 944 func section(elfobj *ElfObj, name string) *ElfSect { 945 for i := 0; uint(i) < elfobj.nsect; i++ { 946 if elfobj.sect[i].name != "" && name != "" && elfobj.sect[i].name == name { 947 return &elfobj.sect[i] 948 } 949 } 950 return nil 951 } 952 953 func elfmap(elfobj *ElfObj, sect *ElfSect) (err error) { 954 if sect.base != nil { 955 return nil 956 } 957 958 if sect.off+sect.size > uint64(elfobj.length) { 959 err = fmt.Errorf("elf section past end of file") 960 return err 961 } 962 963 sect.base = make([]byte, sect.size) 964 err = fmt.Errorf("short read") 965 if obj.Bseek(elfobj.f, int64(uint64(elfobj.base)+sect.off), 0) < 0 || obj.Bread(elfobj.f, sect.base) != len(sect.base) { 966 return err 967 } 968 969 return nil 970 } 971 972 func readelfsym(elfobj *ElfObj, i int, sym *ElfSym, needSym int) (err error) { 973 if i >= elfobj.nsymtab || i < 0 { 974 err = fmt.Errorf("invalid elf symbol index") 975 return err 976 } 977 978 if i == 0 { 979 Diag("readym: read null symbol!") 980 } 981 982 if elfobj.is64 != 0 { 983 b := new(ElfSymBytes64) 984 binary.Read(bytes.NewReader(elfobj.symtab.base[i*ELF64SYMSIZE:(i+1)*ELF64SYMSIZE]), elfobj.e, b) 985 sym.name = cstring(elfobj.symstr.base[elfobj.e.Uint32(b.Name[:]):]) 986 sym.value = elfobj.e.Uint64(b.Value[:]) 987 sym.size = elfobj.e.Uint64(b.Size[:]) 988 sym.shndx = elfobj.e.Uint16(b.Shndx[:]) 989 sym.bind = b.Info >> 4 990 sym.type_ = b.Info & 0xf 991 sym.other = b.Other 992 } else { 993 b := new(ElfSymBytes) 994 binary.Read(bytes.NewReader(elfobj.symtab.base[i*ELF32SYMSIZE:(i+1)*ELF32SYMSIZE]), elfobj.e, b) 995 sym.name = cstring(elfobj.symstr.base[elfobj.e.Uint32(b.Name[:]):]) 996 sym.value = uint64(elfobj.e.Uint32(b.Value[:])) 997 sym.size = uint64(elfobj.e.Uint32(b.Size[:])) 998 sym.shndx = elfobj.e.Uint16(b.Shndx[:]) 999 sym.bind = b.Info >> 4 1000 sym.type_ = b.Info & 0xf 1001 sym.other = b.Other 1002 } 1003 1004 var s *LSym 1005 if sym.name == "_GLOBAL_OFFSET_TABLE_" { 1006 sym.name = ".got" 1007 } 1008 if sym.name == ".TOC." { 1009 // Magic symbol on ppc64. Will be set to this object 1010 // file's .got+0x8000. 1011 sym.bind = ElfSymBindLocal 1012 } 1013 1014 switch sym.type_ { 1015 case ElfSymTypeSection: 1016 s = elfobj.sect[sym.shndx].sym 1017 1018 case ElfSymTypeObject, ElfSymTypeFunc, ElfSymTypeNone: 1019 switch sym.bind { 1020 case ElfSymBindGlobal: 1021 if needSym != 0 { 1022 s = Linklookup(Ctxt, sym.name, 0) 1023 1024 // for global scoped hidden symbols we should insert it into 1025 // symbol hash table, but mark them as hidden. 1026 // __i686.get_pc_thunk.bx is allowed to be duplicated, to 1027 // workaround that we set dupok. 1028 // TODO(minux): correctly handle __i686.get_pc_thunk.bx without 1029 // set dupok generally. See http://codereview.appspot.com/5823055/ 1030 // comment #5 for details. 1031 if s != nil && sym.other == 2 { 1032 s.Type |= obj.SHIDDEN 1033 s.Dupok = 1 1034 } 1035 } 1036 1037 case ElfSymBindLocal: 1038 if Thearch.Thechar == '5' && (strings.HasPrefix(sym.name, "$a") || strings.HasPrefix(sym.name, "$d")) { 1039 // binutils for arm generate these mapping 1040 // symbols, ignore these 1041 break 1042 } 1043 1044 if sym.name == ".TOC." { 1045 // We need to be able to look this up, 1046 // so put it in the hash table. 1047 if needSym != 0 { 1048 s = Linklookup(Ctxt, sym.name, Ctxt.Version) 1049 s.Type |= obj.SHIDDEN 1050 } 1051 1052 break 1053 } 1054 1055 if needSym != 0 { 1056 // local names and hidden visiblity global names are unique 1057 // and should only reference by its index, not name, so we 1058 // don't bother to add them into hash table 1059 s = linknewsym(Ctxt, sym.name, Ctxt.Version) 1060 1061 s.Type |= obj.SHIDDEN 1062 } 1063 1064 case ElfSymBindWeak: 1065 if needSym != 0 { 1066 s = linknewsym(Ctxt, sym.name, 0) 1067 if sym.other == 2 { 1068 s.Type |= obj.SHIDDEN 1069 } 1070 } 1071 1072 default: 1073 err = fmt.Errorf("%s: invalid symbol binding %d", sym.name, sym.bind) 1074 return err 1075 } 1076 } 1077 1078 if s != nil && s.Type == 0 && sym.type_ != ElfSymTypeSection { 1079 s.Type = obj.SXREF 1080 } 1081 sym.sym = s 1082 1083 return nil 1084 } 1085 1086 type rbyoff []Reloc 1087 1088 func (x rbyoff) Len() int { 1089 return len(x) 1090 } 1091 1092 func (x rbyoff) Swap(i, j int) { 1093 x[i], x[j] = x[j], x[i] 1094 } 1095 1096 func (x rbyoff) Less(i, j int) bool { 1097 a := &x[i] 1098 b := &x[j] 1099 if a.Off < b.Off { 1100 return true 1101 } 1102 if a.Off > b.Off { 1103 return false 1104 } 1105 return false 1106 } 1107 1108 func reltype(pn string, elftype int, siz *uint8) int { 1109 switch uint32(Thearch.Thechar) | uint32(elftype)<<24 { 1110 default: 1111 Diag("%s: unknown relocation type %d; compiled without -fpic?", pn, elftype) 1112 fallthrough 1113 1114 case '9' | R_PPC64_TOC16<<24, 1115 '9' | R_PPC64_TOC16_LO<<24, 1116 '9' | R_PPC64_TOC16_HI<<24, 1117 '9' | R_PPC64_TOC16_HA<<24, 1118 '9' | R_PPC64_TOC16_DS<<24, 1119 '9' | R_PPC64_TOC16_LO_DS<<24, 1120 '9' | R_PPC64_REL16_LO<<24, 1121 '9' | R_PPC64_REL16_HI<<24, 1122 '9' | R_PPC64_REL16_HA<<24: 1123 *siz = 2 1124 1125 case '5' | R_ARM_ABS32<<24, 1126 '5' | R_ARM_GOT32<<24, 1127 '5' | R_ARM_PLT32<<24, 1128 '5' | R_ARM_GOTOFF<<24, 1129 '5' | R_ARM_GOTPC<<24, 1130 '5' | R_ARM_THM_PC22<<24, 1131 '5' | R_ARM_REL32<<24, 1132 '5' | R_ARM_CALL<<24, 1133 '5' | R_ARM_V4BX<<24, 1134 '5' | R_ARM_GOT_PREL<<24, 1135 '5' | R_ARM_PC24<<24, 1136 '5' | R_ARM_JUMP24<<24, 1137 '6' | R_X86_64_PC32<<24, 1138 '6' | R_X86_64_PLT32<<24, 1139 '6' | R_X86_64_GOTPCREL<<24, 1140 '8' | R_386_32<<24, 1141 '8' | R_386_PC32<<24, 1142 '8' | R_386_GOT32<<24, 1143 '8' | R_386_PLT32<<24, 1144 '8' | R_386_GOTOFF<<24, 1145 '8' | R_386_GOTPC<<24, 1146 '9' | R_PPC64_REL24<<24: 1147 *siz = 4 1148 1149 case '6' | R_X86_64_64<<24, 1150 '9' | R_PPC64_ADDR64<<24: 1151 *siz = 8 1152 } 1153 1154 return 256 + elftype 1155 }