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