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