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