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 *obj.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 *obj.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(obj.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 obj.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 obj.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 = obj.SRODATA 571 572 case ElfSectFlagAlloc + ElfSectFlagWrite: 573 if sect.type_ == ElfSectNobits { 574 s.Type = obj.SNOPTRBSS 575 } else { 576 s.Type = obj.SNOPTRDATA 577 } 578 579 case ElfSectFlagAlloc + ElfSectFlagExec: 580 s.Type = obj.STEXT 581 } 582 583 if sect.name == ".got" || sect.name == ".toc" { 584 s.Type = obj.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 for i := 1; i < elfobj.nsymtab; i++ { 601 if err = readelfsym(elfobj, i, &sym, 1); err != nil { 602 goto bad 603 } 604 symbols[i] = sym.sym 605 if sym.type_ != ElfSymTypeFunc && sym.type_ != ElfSymTypeObject && sym.type_ != ElfSymTypeNone { 606 continue 607 } 608 if sym.shndx == ElfSymShnCommon { 609 s = sym.sym 610 if uint64(s.Size) < sym.size { 611 s.Size = int64(sym.size) 612 } 613 if s.Type == 0 || s.Type == obj.SXREF { 614 s.Type = obj.SNOPTRBSS 615 } 616 continue 617 } 618 619 if uint(sym.shndx) >= elfobj.nsect || sym.shndx == 0 { 620 continue 621 } 622 623 // even when we pass needSym == 1 to readelfsym, it might still return nil to skip some unwanted symbols 624 if sym.sym == nil { 625 continue 626 } 627 sect = &elfobj.sect[sym.shndx:][0] 628 if sect.sym == nil { 629 if strings.HasPrefix(sym.name, ".Linfo_string") { // clang does this 630 continue 631 } 632 Diag("%s: sym#%d: ignoring %s in section %d (type %d)", pn, i, sym.name, sym.shndx, sym.type_) 633 continue 634 } 635 636 s = sym.sym 637 if s.Outer != nil { 638 if s.Dupok != 0 { 639 continue 640 } 641 Exitf("%s: duplicate symbol reference: %s in both %s and %s", pn, s.Name, s.Outer.Name, sect.sym.Name) 642 } 643 644 s.Sub = sect.sym.Sub 645 sect.sym.Sub = s 646 s.Type = sect.sym.Type | s.Type&^obj.SMASK | obj.SSUB 647 if s.Cgoexport&CgoExportDynamic == 0 { 648 s.Dynimplib = "" // satisfy dynimport 649 } 650 s.Value = int64(sym.value) 651 s.Size = int64(sym.size) 652 s.Outer = sect.sym 653 if sect.sym.Type == obj.STEXT { 654 if s.External != 0 && s.Dupok == 0 { 655 Diag("%s: duplicate definition of %s", pn, s.Name) 656 } 657 s.External = 1 658 } 659 660 if elfobj.machine == ElfMachPower64 { 661 flag = int(sym.other) >> 5 662 if 2 <= flag && flag <= 6 { 663 s.Localentry = 1 << uint(flag-2) 664 } else if flag == 7 { 665 Diag("%s: invalid sym.other 0x%x for %s", pn, sym.other, s.Name) 666 } 667 } 668 } 669 670 // Sort outer lists by address, adding to textp. 671 // This keeps textp in increasing address order. 672 for i := 0; uint(i) < elfobj.nsect; i++ { 673 s = elfobj.sect[i].sym 674 if s == nil { 675 continue 676 } 677 if s.Sub != nil { 678 s.Sub = listsort(s.Sub, valuecmp, listsubp) 679 } 680 if s.Type == obj.STEXT { 681 if s.Onlist != 0 { 682 log.Fatalf("symbol %s listed multiple times", s.Name) 683 } 684 s.Onlist = 1 685 if Ctxt.Etextp != nil { 686 Ctxt.Etextp.Next = s 687 } else { 688 Ctxt.Textp = s 689 } 690 Ctxt.Etextp = s 691 for s = s.Sub; s != nil; s = s.Sub { 692 if s.Onlist != 0 { 693 log.Fatalf("symbol %s listed multiple times", s.Name) 694 } 695 s.Onlist = 1 696 Ctxt.Etextp.Next = s 697 Ctxt.Etextp = s 698 } 699 } 700 } 701 702 // load relocations 703 for i := 0; uint(i) < elfobj.nsect; i++ { 704 rsect = &elfobj.sect[i] 705 if rsect.type_ != ElfSectRela && rsect.type_ != ElfSectRel { 706 continue 707 } 708 if rsect.info >= uint32(elfobj.nsect) || elfobj.sect[rsect.info].base == nil { 709 continue 710 } 711 sect = &elfobj.sect[rsect.info] 712 if err = elfmap(elfobj, rsect); err != nil { 713 goto bad 714 } 715 rela = 0 716 if rsect.type_ == ElfSectRela { 717 rela = 1 718 } 719 n = int(rsect.size / uint64(4+4*is64) / uint64(2+rela)) 720 r = make([]Reloc, n) 721 p = rsect.base 722 for j = 0; j < n; j++ { 723 add = 0 724 rp = &r[j] 725 if is64 != 0 { 726 // 64-bit rel/rela 727 rp.Off = int32(e.Uint64(p)) 728 729 p = p[8:] 730 info = e.Uint64(p) 731 p = p[8:] 732 if rela != 0 { 733 add = e.Uint64(p) 734 p = p[8:] 735 } 736 } else { 737 // 32-bit rel/rela 738 rp.Off = int32(e.Uint32(p)) 739 740 p = p[4:] 741 info = uint64(e.Uint32(p)) 742 info = info>>8<<32 | info&0xff // convert to 64-bit info 743 p = p[4:] 744 if rela != 0 { 745 add = uint64(e.Uint32(p)) 746 p = p[4:] 747 } 748 } 749 750 if info&0xffffffff == 0 { // skip R_*_NONE relocation 751 j-- 752 n-- 753 continue 754 } 755 756 if info>>32 == 0 { // absolute relocation, don't bother reading the null symbol 757 rp.Sym = nil 758 } else { 759 if err = readelfsym(elfobj, int(info>>32), &sym, 0); err != nil { 760 goto bad 761 } 762 sym.sym = symbols[info>>32] 763 if sym.sym == nil { 764 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_) 765 goto bad 766 } 767 768 rp.Sym = sym.sym 769 } 770 771 rp.Type = int32(reltype(pn, int(uint32(info)), &rp.Siz)) 772 if rela != 0 { 773 rp.Add = int64(add) 774 } else { 775 // load addend from image 776 if rp.Siz == 4 { 777 rp.Add = int64(e.Uint32(sect.base[rp.Off:])) 778 } else if rp.Siz == 8 { 779 rp.Add = int64(e.Uint64(sect.base[rp.Off:])) 780 } else { 781 Diag("invalid rela size %d", rp.Siz) 782 } 783 } 784 785 if rp.Siz == 2 { 786 rp.Add = int64(int16(rp.Add)) 787 } 788 if rp.Siz == 4 { 789 rp.Add = int64(int32(rp.Add)) 790 } 791 } 792 793 //print("rel %s %d %d %s %#llx\n", sect->sym->name, rp->type, rp->siz, rp->sym->name, rp->add); 794 sort.Sort(rbyoff(r[:n])) 795 // just in case 796 797 s = sect.sym 798 s.R = r 799 s.R = s.R[:n] 800 } 801 802 return 803 804 bad: 805 Diag("%s: malformed elf file: %v", pn, err) 806 } 807 808 func section(elfobj *ElfObj, name string) *ElfSect { 809 for i := 0; uint(i) < elfobj.nsect; i++ { 810 if elfobj.sect[i].name != "" && name != "" && elfobj.sect[i].name == name { 811 return &elfobj.sect[i] 812 } 813 } 814 return nil 815 } 816 817 func elfmap(elfobj *ElfObj, sect *ElfSect) (err error) { 818 if sect.base != nil { 819 return nil 820 } 821 822 if sect.off+sect.size > uint64(elfobj.length) { 823 err = fmt.Errorf("elf section past end of file") 824 return err 825 } 826 827 sect.base = make([]byte, sect.size) 828 err = fmt.Errorf("short read") 829 if obj.Bseek(elfobj.f, int64(uint64(elfobj.base)+sect.off), 0) < 0 || obj.Bread(elfobj.f, sect.base) != len(sect.base) { 830 return err 831 } 832 833 return nil 834 } 835 836 func readelfsym(elfobj *ElfObj, i int, sym *ElfSym, needSym int) (err error) { 837 if i >= elfobj.nsymtab || i < 0 { 838 err = fmt.Errorf("invalid elf symbol index") 839 return err 840 } 841 842 if i == 0 { 843 Diag("readym: read null symbol!") 844 } 845 846 if elfobj.is64 != 0 { 847 b := new(ElfSymBytes64) 848 binary.Read(bytes.NewReader(elfobj.symtab.base[i*ELF64SYMSIZE:(i+1)*ELF64SYMSIZE]), elfobj.e, b) 849 sym.name = cstring(elfobj.symstr.base[elfobj.e.Uint32(b.Name[:]):]) 850 sym.value = elfobj.e.Uint64(b.Value[:]) 851 sym.size = elfobj.e.Uint64(b.Size[:]) 852 sym.shndx = elfobj.e.Uint16(b.Shndx[:]) 853 sym.bind = b.Info >> 4 854 sym.type_ = b.Info & 0xf 855 sym.other = b.Other 856 } else { 857 b := new(ElfSymBytes) 858 binary.Read(bytes.NewReader(elfobj.symtab.base[i*ELF32SYMSIZE:(i+1)*ELF32SYMSIZE]), elfobj.e, b) 859 sym.name = cstring(elfobj.symstr.base[elfobj.e.Uint32(b.Name[:]):]) 860 sym.value = uint64(elfobj.e.Uint32(b.Value[:])) 861 sym.size = uint64(elfobj.e.Uint32(b.Size[:])) 862 sym.shndx = elfobj.e.Uint16(b.Shndx[:]) 863 sym.bind = b.Info >> 4 864 sym.type_ = b.Info & 0xf 865 sym.other = b.Other 866 } 867 868 var s *LSym 869 if sym.name == "_GLOBAL_OFFSET_TABLE_" { 870 sym.name = ".got" 871 } 872 if sym.name == ".TOC." { 873 // Magic symbol on ppc64. Will be set to this object 874 // file's .got+0x8000. 875 sym.bind = ElfSymBindLocal 876 } 877 878 switch sym.type_ { 879 case ElfSymTypeSection: 880 s = elfobj.sect[sym.shndx].sym 881 882 case ElfSymTypeObject, ElfSymTypeFunc, ElfSymTypeNone: 883 switch sym.bind { 884 case ElfSymBindGlobal: 885 if needSym != 0 { 886 s = Linklookup(Ctxt, sym.name, 0) 887 888 // for global scoped hidden symbols we should insert it into 889 // symbol hash table, but mark them as hidden. 890 // __i686.get_pc_thunk.bx is allowed to be duplicated, to 891 // workaround that we set dupok. 892 // TODO(minux): correctly handle __i686.get_pc_thunk.bx without 893 // set dupok generally. See http://codereview.appspot.com/5823055/ 894 // comment #5 for details. 895 if s != nil && sym.other == 2 { 896 s.Type |= obj.SHIDDEN 897 s.Dupok = 1 898 } 899 } 900 901 case ElfSymBindLocal: 902 if Thearch.Thechar == '5' && (strings.HasPrefix(sym.name, "$a") || strings.HasPrefix(sym.name, "$d")) { 903 // binutils for arm generate these mapping 904 // symbols, ignore these 905 break 906 } 907 908 if sym.name == ".TOC." { 909 // We need to be able to look this up, 910 // so put it in the hash table. 911 if needSym != 0 { 912 s = Linklookup(Ctxt, sym.name, Ctxt.Version) 913 s.Type |= obj.SHIDDEN 914 } 915 916 break 917 } 918 919 if needSym != 0 { 920 // local names and hidden visiblity global names are unique 921 // and should only reference by its index, not name, so we 922 // don't bother to add them into hash table 923 s = linknewsym(Ctxt, sym.name, Ctxt.Version) 924 925 s.Type |= obj.SHIDDEN 926 } 927 928 case ElfSymBindWeak: 929 if needSym != 0 { 930 s = linknewsym(Ctxt, sym.name, 0) 931 if sym.other == 2 { 932 s.Type |= obj.SHIDDEN 933 } 934 } 935 936 default: 937 err = fmt.Errorf("%s: invalid symbol binding %d", sym.name, sym.bind) 938 return err 939 } 940 } 941 942 if s != nil && s.Type == 0 && sym.type_ != ElfSymTypeSection { 943 s.Type = obj.SXREF 944 } 945 sym.sym = s 946 947 return nil 948 } 949 950 type rbyoff []Reloc 951 952 func (x rbyoff) Len() int { 953 return len(x) 954 } 955 956 func (x rbyoff) Swap(i, j int) { 957 x[i], x[j] = x[j], x[i] 958 } 959 960 func (x rbyoff) Less(i, j int) bool { 961 a := &x[i] 962 b := &x[j] 963 if a.Off < b.Off { 964 return true 965 } 966 if a.Off > b.Off { 967 return false 968 } 969 return false 970 } 971 972 func reltype(pn string, elftype int, siz *uint8) int { 973 switch uint32(Thearch.Thechar) | uint32(elftype)<<24 { 974 default: 975 Diag("%s: unknown relocation type %d; compiled without -fpic?", pn, elftype) 976 fallthrough 977 978 case '9' | R_PPC64_TOC16<<24, 979 '9' | R_PPC64_TOC16_LO<<24, 980 '9' | R_PPC64_TOC16_HI<<24, 981 '9' | R_PPC64_TOC16_HA<<24, 982 '9' | R_PPC64_TOC16_DS<<24, 983 '9' | R_PPC64_TOC16_LO_DS<<24, 984 '9' | R_PPC64_REL16_LO<<24, 985 '9' | R_PPC64_REL16_HI<<24, 986 '9' | R_PPC64_REL16_HA<<24: 987 *siz = 2 988 989 case '5' | R_ARM_ABS32<<24, 990 '5' | R_ARM_GOT32<<24, 991 '5' | R_ARM_PLT32<<24, 992 '5' | R_ARM_GOTOFF<<24, 993 '5' | R_ARM_GOTPC<<24, 994 '5' | R_ARM_THM_PC22<<24, 995 '5' | R_ARM_REL32<<24, 996 '5' | R_ARM_CALL<<24, 997 '5' | R_ARM_V4BX<<24, 998 '5' | R_ARM_GOT_PREL<<24, 999 '5' | R_ARM_PC24<<24, 1000 '5' | R_ARM_JUMP24<<24, 1001 '6' | R_X86_64_PC32<<24, 1002 '6' | R_X86_64_PLT32<<24, 1003 '6' | R_X86_64_GOTPCREL<<24, 1004 '8' | R_386_32<<24, 1005 '8' | R_386_PC32<<24, 1006 '8' | R_386_GOT32<<24, 1007 '8' | R_386_PLT32<<24, 1008 '8' | R_386_GOTOFF<<24, 1009 '8' | R_386_GOTPC<<24, 1010 '9' | R_PPC64_REL24<<24: 1011 *siz = 4 1012 1013 case '6' | R_X86_64_64<<24, 1014 '9' | R_PPC64_ADDR64<<24: 1015 *siz = 8 1016 } 1017 1018 return 256 + elftype 1019 } 1020