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