github.com/go-asm/go@v1.21.1-0.20240213172139-40c5ead50c48/cmd/link/loadelf/ldelf.go (about) 1 // Copyright 2019 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 "debug/elf" 11 "encoding/binary" 12 "fmt" 13 "io" 14 "log" 15 "strings" 16 17 "github.com/go-asm/go/cmd/bio" 18 "github.com/go-asm/go/cmd/link/loader" 19 "github.com/go-asm/go/cmd/link/sym" 20 "github.com/go-asm/go/cmd/objabi" 21 "github.com/go-asm/go/cmd/sys" 22 ) 23 24 /* 25 Derived from Plan 9 from User Space's src/libmach/elf.h, elf.c 26 https://github.com/9fans/plan9port/tree/master/src/libmach/ 27 28 Copyright © 2004 Russ Cox. 29 Portions Copyright © 2008-2010 Google Inc. 30 Portions Copyright © 2010 The Go Authors. 31 32 Permission is hereby granted, free of charge, to any person obtaining a copy 33 of this software and associated documentation files (the "Software"), to deal 34 in the Software without restriction, including without limitation the rights 35 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 36 copies of the Software, and to permit persons to whom the Software is 37 furnished to do so, subject to the following conditions: 38 39 The above copyright notice and this permission notice shall be included in 40 all copies or substantial portions of the Software. 41 42 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 43 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 44 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 45 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 46 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 47 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 48 THE SOFTWARE. 49 */ 50 51 const ( 52 SHT_ARM_ATTRIBUTES = 0x70000003 53 ) 54 55 type ElfSect struct { 56 name string 57 nameoff uint32 58 type_ elf.SectionType 59 flags elf.SectionFlag 60 addr uint64 61 off uint64 62 size uint64 63 link uint32 64 info uint32 65 align uint64 66 entsize uint64 67 base []byte 68 readOnlyMem bool // Is this section in readonly memory? 69 sym loader.Sym 70 } 71 72 type ElfObj struct { 73 f *bio.Reader 74 base int64 // offset in f where ELF begins 75 length int64 // length of ELF 76 is64 int 77 name string 78 e binary.ByteOrder 79 sect []ElfSect 80 nsect uint 81 nsymtab int 82 symtab *ElfSect 83 symstr *ElfSect 84 type_ uint32 85 machine uint32 86 version uint32 87 entry uint64 88 phoff uint64 89 shoff uint64 90 flags uint32 91 ehsize uint32 92 phentsize uint32 93 phnum uint32 94 shentsize uint32 95 shnum uint32 96 shstrndx uint32 97 } 98 99 type ElfSym struct { 100 name string 101 value uint64 102 size uint64 103 bind elf.SymBind 104 type_ elf.SymType 105 other uint8 106 shndx elf.SectionIndex 107 sym loader.Sym 108 } 109 110 const ( 111 TagFile = 1 112 TagCPUName = 4 113 TagCPURawName = 5 114 TagCompatibility = 32 115 TagNoDefaults = 64 116 TagAlsoCompatibleWith = 65 117 TagABIVFPArgs = 28 118 ) 119 120 type elfAttribute struct { 121 tag uint64 122 sval string 123 ival uint64 124 } 125 126 type elfAttributeList struct { 127 data []byte 128 err error 129 } 130 131 func (a *elfAttributeList) string() string { 132 if a.err != nil { 133 return "" 134 } 135 nul := bytes.IndexByte(a.data, 0) 136 if nul < 0 { 137 a.err = io.EOF 138 return "" 139 } 140 s := string(a.data[:nul]) 141 a.data = a.data[nul+1:] 142 return s 143 } 144 145 func (a *elfAttributeList) uleb128() uint64 { 146 if a.err != nil { 147 return 0 148 } 149 v, size := binary.Uvarint(a.data) 150 a.data = a.data[size:] 151 return v 152 } 153 154 // Read an elfAttribute from the list following the rules used on ARM systems. 155 func (a *elfAttributeList) armAttr() elfAttribute { 156 attr := elfAttribute{tag: a.uleb128()} 157 switch { 158 case attr.tag == TagCompatibility: 159 attr.ival = a.uleb128() 160 attr.sval = a.string() 161 162 case attr.tag == TagNoDefaults: // Tag_nodefaults has no argument 163 164 case attr.tag == TagAlsoCompatibleWith: 165 // Not really, but we don't actually care about this tag. 166 attr.sval = a.string() 167 168 // Tag with string argument 169 case attr.tag == TagCPUName || attr.tag == TagCPURawName || (attr.tag >= 32 && attr.tag&1 != 0): 170 attr.sval = a.string() 171 172 default: // Tag with integer argument 173 attr.ival = a.uleb128() 174 } 175 return attr 176 } 177 178 func (a *elfAttributeList) done() bool { 179 if a.err != nil || len(a.data) == 0 { 180 return true 181 } 182 return false 183 } 184 185 // Look for the attribute that indicates the object uses the hard-float ABI (a 186 // file-level attribute with tag Tag_VFP_arch and value 1). Unfortunately the 187 // format used means that we have to parse all of the file-level attributes to 188 // find the one we are looking for. This format is slightly documented in "ELF 189 // for the ARM Architecture" but mostly this is derived from reading the source 190 // to gold and readelf. 191 func parseArmAttributes(e binary.ByteOrder, data []byte) (found bool, ehdrFlags uint32, err error) { 192 found = false 193 if data[0] != 'A' { 194 return false, 0, fmt.Errorf(".ARM.attributes has unexpected format %c\n", data[0]) 195 } 196 data = data[1:] 197 for len(data) != 0 { 198 sectionlength := e.Uint32(data) 199 sectiondata := data[4:sectionlength] 200 data = data[sectionlength:] 201 202 nulIndex := bytes.IndexByte(sectiondata, 0) 203 if nulIndex < 0 { 204 return false, 0, fmt.Errorf("corrupt .ARM.attributes (section name not NUL-terminated)\n") 205 } 206 name := string(sectiondata[:nulIndex]) 207 sectiondata = sectiondata[nulIndex+1:] 208 209 if name != "aeabi" { 210 continue 211 } 212 for len(sectiondata) != 0 { 213 subsectiontag, sz := binary.Uvarint(sectiondata) 214 subsectionsize := e.Uint32(sectiondata[sz:]) 215 subsectiondata := sectiondata[sz+4 : subsectionsize] 216 sectiondata = sectiondata[subsectionsize:] 217 218 if subsectiontag != TagFile { 219 continue 220 } 221 attrList := elfAttributeList{data: subsectiondata} 222 for !attrList.done() { 223 attr := attrList.armAttr() 224 if attr.tag == TagABIVFPArgs && attr.ival == 1 { 225 found = true 226 ehdrFlags = 0x5000402 // has entry point, Version5 EABI, hard-float ABI 227 } 228 } 229 if attrList.err != nil { 230 return false, 0, fmt.Errorf("could not parse .ARM.attributes\n") 231 } 232 } 233 } 234 return found, ehdrFlags, nil 235 } 236 237 // Load loads the ELF file pn from f. 238 // Symbols are installed into the loader, and a slice of the text symbols is returned. 239 // 240 // On ARM systems, Load will attempt to determine what ELF header flags to 241 // emit by scanning the attributes in the ELF file being loaded. The 242 // parameter initEhdrFlags contains the current header flags for the output 243 // object, and the returned ehdrFlags contains what this Load function computes. 244 // TODO: find a better place for this logic. 245 func Load(l *loader.Loader, arch *sys.Arch, localSymVersion int, f *bio.Reader, pkg string, length int64, pn string, initEhdrFlags uint32) (textp []loader.Sym, ehdrFlags uint32, err error) { 246 newSym := func(name string, version int) loader.Sym { 247 return l.CreateStaticSym(name) 248 } 249 lookup := l.LookupOrCreateCgoExport 250 errorf := func(str string, args ...interface{}) ([]loader.Sym, uint32, error) { 251 return nil, 0, fmt.Errorf("loadelf: %s: %v", pn, fmt.Sprintf(str, args...)) 252 } 253 254 ehdrFlags = initEhdrFlags 255 256 base := f.Offset() 257 258 var hdrbuf [64]byte 259 if _, err := io.ReadFull(f, hdrbuf[:]); err != nil { 260 return errorf("malformed elf file: %v", err) 261 } 262 263 var e binary.ByteOrder 264 switch elf.Data(hdrbuf[elf.EI_DATA]) { 265 case elf.ELFDATA2LSB: 266 e = binary.LittleEndian 267 268 case elf.ELFDATA2MSB: 269 e = binary.BigEndian 270 271 default: 272 return errorf("malformed elf file, unknown header") 273 } 274 275 hdr := new(elf.Header32) 276 binary.Read(bytes.NewReader(hdrbuf[:]), e, hdr) 277 278 if string(hdr.Ident[:elf.EI_CLASS]) != elf.ELFMAG { 279 return errorf("malformed elf file, bad header") 280 } 281 282 // read header 283 elfobj := new(ElfObj) 284 285 elfobj.e = e 286 elfobj.f = f 287 elfobj.base = base 288 elfobj.length = length 289 elfobj.name = pn 290 291 is64 := 0 292 class := elf.Class(hdrbuf[elf.EI_CLASS]) 293 if class == elf.ELFCLASS64 { 294 is64 = 1 295 hdr := new(elf.Header64) 296 binary.Read(bytes.NewReader(hdrbuf[:]), e, hdr) 297 elfobj.type_ = uint32(hdr.Type) 298 elfobj.machine = uint32(hdr.Machine) 299 elfobj.version = hdr.Version 300 elfobj.entry = hdr.Entry 301 elfobj.phoff = hdr.Phoff 302 elfobj.shoff = hdr.Shoff 303 elfobj.flags = hdr.Flags 304 elfobj.ehsize = uint32(hdr.Ehsize) 305 elfobj.phentsize = uint32(hdr.Phentsize) 306 elfobj.phnum = uint32(hdr.Phnum) 307 elfobj.shentsize = uint32(hdr.Shentsize) 308 elfobj.shnum = uint32(hdr.Shnum) 309 elfobj.shstrndx = uint32(hdr.Shstrndx) 310 } else { 311 elfobj.type_ = uint32(hdr.Type) 312 elfobj.machine = uint32(hdr.Machine) 313 elfobj.version = hdr.Version 314 elfobj.entry = uint64(hdr.Entry) 315 elfobj.phoff = uint64(hdr.Phoff) 316 elfobj.shoff = uint64(hdr.Shoff) 317 elfobj.flags = hdr.Flags 318 elfobj.ehsize = uint32(hdr.Ehsize) 319 elfobj.phentsize = uint32(hdr.Phentsize) 320 elfobj.phnum = uint32(hdr.Phnum) 321 elfobj.shentsize = uint32(hdr.Shentsize) 322 elfobj.shnum = uint32(hdr.Shnum) 323 elfobj.shstrndx = uint32(hdr.Shstrndx) 324 } 325 326 elfobj.is64 = is64 327 328 if v := uint32(hdrbuf[elf.EI_VERSION]); v != elfobj.version { 329 return errorf("malformed elf version: got %d, want %d", v, elfobj.version) 330 } 331 332 if elf.Type(elfobj.type_) != elf.ET_REL { 333 return errorf("elf but not elf relocatable object") 334 } 335 336 mach := elf.Machine(elfobj.machine) 337 switch arch.Family { 338 default: 339 return errorf("elf %s unimplemented", arch.Name) 340 341 case sys.MIPS: 342 if mach != elf.EM_MIPS || class != elf.ELFCLASS32 { 343 return errorf("elf object but not mips") 344 } 345 346 case sys.MIPS64: 347 if mach != elf.EM_MIPS || class != elf.ELFCLASS64 { 348 return errorf("elf object but not mips64") 349 } 350 case sys.Loong64: 351 if mach != elf.EM_LOONGARCH || class != elf.ELFCLASS64 { 352 return errorf("elf object but not loong64") 353 } 354 355 case sys.ARM: 356 if e != binary.LittleEndian || mach != elf.EM_ARM || class != elf.ELFCLASS32 { 357 return errorf("elf object but not arm") 358 } 359 360 case sys.AMD64: 361 if e != binary.LittleEndian || mach != elf.EM_X86_64 || class != elf.ELFCLASS64 { 362 return errorf("elf object but not amd64") 363 } 364 365 case sys.ARM64: 366 if e != binary.LittleEndian || mach != elf.EM_AARCH64 || class != elf.ELFCLASS64 { 367 return errorf("elf object but not arm64") 368 } 369 370 case sys.I386: 371 if e != binary.LittleEndian || mach != elf.EM_386 || class != elf.ELFCLASS32 { 372 return errorf("elf object but not 386") 373 } 374 375 case sys.PPC64: 376 if mach != elf.EM_PPC64 || class != elf.ELFCLASS64 { 377 return errorf("elf object but not ppc64") 378 } 379 380 case sys.RISCV64: 381 if mach != elf.EM_RISCV || class != elf.ELFCLASS64 { 382 return errorf("elf object but not riscv64") 383 } 384 385 case sys.S390X: 386 if mach != elf.EM_S390 || class != elf.ELFCLASS64 { 387 return errorf("elf object but not s390x") 388 } 389 } 390 391 // load section list into memory. 392 elfobj.sect = make([]ElfSect, elfobj.shnum) 393 394 elfobj.nsect = uint(elfobj.shnum) 395 for i := 0; uint(i) < elfobj.nsect; i++ { 396 f.MustSeek(int64(uint64(base)+elfobj.shoff+uint64(int64(i)*int64(elfobj.shentsize))), 0) 397 sect := &elfobj.sect[i] 398 if is64 != 0 { 399 var b elf.Section64 400 if err := binary.Read(f, e, &b); err != nil { 401 return errorf("malformed elf file: %v", err) 402 } 403 404 sect.nameoff = b.Name 405 sect.type_ = elf.SectionType(b.Type) 406 sect.flags = elf.SectionFlag(b.Flags) 407 sect.addr = b.Addr 408 sect.off = b.Off 409 sect.size = b.Size 410 sect.link = b.Link 411 sect.info = b.Info 412 sect.align = b.Addralign 413 sect.entsize = b.Entsize 414 } else { 415 var b elf.Section32 416 417 if err := binary.Read(f, e, &b); err != nil { 418 return errorf("malformed elf file: %v", err) 419 } 420 sect.nameoff = b.Name 421 sect.type_ = elf.SectionType(b.Type) 422 sect.flags = elf.SectionFlag(b.Flags) 423 sect.addr = uint64(b.Addr) 424 sect.off = uint64(b.Off) 425 sect.size = uint64(b.Size) 426 sect.link = b.Link 427 sect.info = b.Info 428 sect.align = uint64(b.Addralign) 429 sect.entsize = uint64(b.Entsize) 430 } 431 } 432 433 // read section string table and translate names 434 if elfobj.shstrndx >= uint32(elfobj.nsect) { 435 return errorf("malformed elf file: shstrndx out of range %d >= %d", elfobj.shstrndx, elfobj.nsect) 436 } 437 438 sect := &elfobj.sect[elfobj.shstrndx] 439 if err := elfmap(elfobj, sect); err != nil { 440 return errorf("malformed elf file: %v", err) 441 } 442 for i := 0; uint(i) < elfobj.nsect; i++ { 443 if elfobj.sect[i].nameoff != 0 { 444 elfobj.sect[i].name = cstring(sect.base[elfobj.sect[i].nameoff:]) 445 } 446 } 447 448 // load string table for symbols into memory. 449 elfobj.symtab = section(elfobj, ".symtab") 450 451 if elfobj.symtab == nil { 452 // our work is done here - no symbols means nothing can refer to this file 453 return 454 } 455 456 if elfobj.symtab.link <= 0 || elfobj.symtab.link >= uint32(elfobj.nsect) { 457 return errorf("elf object has symbol table with invalid string table link") 458 } 459 460 elfobj.symstr = &elfobj.sect[elfobj.symtab.link] 461 if is64 != 0 { 462 elfobj.nsymtab = int(elfobj.symtab.size / elf.Sym64Size) 463 } else { 464 elfobj.nsymtab = int(elfobj.symtab.size / elf.Sym32Size) 465 } 466 467 if err := elfmap(elfobj, elfobj.symtab); err != nil { 468 return errorf("malformed elf file: %v", err) 469 } 470 if err := elfmap(elfobj, elfobj.symstr); err != nil { 471 return errorf("malformed elf file: %v", err) 472 } 473 474 // load text and data segments into memory. 475 // they are not as small as the section lists, but we'll need 476 // the memory anyway for the symbol images, so we might 477 // as well use one large chunk. 478 479 // create symbols for elfmapped sections 480 sectsymNames := make(map[string]bool) 481 counter := 0 482 for i := 0; uint(i) < elfobj.nsect; i++ { 483 sect = &elfobj.sect[i] 484 if sect.type_ == SHT_ARM_ATTRIBUTES && sect.name == ".ARM.attributes" { 485 if err := elfmap(elfobj, sect); err != nil { 486 return errorf("%s: malformed elf file: %v", pn, err) 487 } 488 // We assume the soft-float ABI unless we see a tag indicating otherwise. 489 if initEhdrFlags == 0x5000002 { 490 ehdrFlags = 0x5000202 491 } else { 492 ehdrFlags = initEhdrFlags 493 } 494 found, newEhdrFlags, err := parseArmAttributes(e, sect.base[:sect.size]) 495 if err != nil { 496 // TODO(dfc) should this return an error? 497 log.Printf("%s: %v", pn, err) 498 } 499 if found { 500 ehdrFlags = newEhdrFlags 501 } 502 } 503 if (sect.type_ != elf.SHT_PROGBITS && sect.type_ != elf.SHT_NOBITS) || sect.flags&elf.SHF_ALLOC == 0 { 504 continue 505 } 506 if sect.type_ != elf.SHT_NOBITS { 507 if err := elfmap(elfobj, sect); err != nil { 508 return errorf("%s: malformed elf file: %v", pn, err) 509 } 510 } 511 512 name := fmt.Sprintf("%s(%s)", pkg, sect.name) 513 for sectsymNames[name] { 514 counter++ 515 name = fmt.Sprintf("%s(%s%d)", pkg, sect.name, counter) 516 } 517 sectsymNames[name] = true 518 519 sb := l.MakeSymbolUpdater(lookup(name, localSymVersion)) 520 521 switch sect.flags & (elf.SHF_ALLOC | elf.SHF_WRITE | elf.SHF_EXECINSTR) { 522 default: 523 return errorf("%s: unexpected flags for ELF section %s", pn, sect.name) 524 525 case elf.SHF_ALLOC: 526 sb.SetType(sym.SRODATA) 527 528 case elf.SHF_ALLOC + elf.SHF_WRITE: 529 if sect.type_ == elf.SHT_NOBITS { 530 sb.SetType(sym.SNOPTRBSS) 531 } else { 532 sb.SetType(sym.SNOPTRDATA) 533 } 534 535 case elf.SHF_ALLOC + elf.SHF_EXECINSTR: 536 sb.SetType(sym.STEXT) 537 } 538 539 if sect.name == ".got" || sect.name == ".toc" { 540 sb.SetType(sym.SELFGOT) 541 } 542 if sect.type_ == elf.SHT_PROGBITS { 543 sb.SetData(sect.base[:sect.size]) 544 sb.SetExternal(true) 545 } 546 547 sb.SetSize(int64(sect.size)) 548 sb.SetAlign(int32(sect.align)) 549 sb.SetReadOnly(sect.readOnlyMem) 550 551 sect.sym = sb.Sym() 552 } 553 554 // enter sub-symbols into symbol table. 555 // symbol 0 is the null symbol. 556 symbols := make([]loader.Sym, elfobj.nsymtab) 557 558 for i := 1; i < elfobj.nsymtab; i++ { 559 var elfsym ElfSym 560 if err := readelfsym(newSym, lookup, l, arch, elfobj, i, &elfsym, 1, localSymVersion); err != nil { 561 return errorf("%s: malformed elf file: %v", pn, err) 562 } 563 symbols[i] = elfsym.sym 564 if elfsym.type_ != elf.STT_FUNC && elfsym.type_ != elf.STT_OBJECT && elfsym.type_ != elf.STT_NOTYPE && elfsym.type_ != elf.STT_COMMON { 565 continue 566 } 567 if elfsym.shndx == elf.SHN_COMMON || elfsym.type_ == elf.STT_COMMON { 568 sb := l.MakeSymbolUpdater(elfsym.sym) 569 if uint64(sb.Size()) < elfsym.size { 570 sb.SetSize(int64(elfsym.size)) 571 } 572 if sb.Type() == 0 || sb.Type() == sym.SXREF { 573 sb.SetType(sym.SNOPTRBSS) 574 } 575 continue 576 } 577 578 if uint(elfsym.shndx) >= elfobj.nsect || elfsym.shndx == 0 { 579 continue 580 } 581 582 // even when we pass needSym == 1 to readelfsym, it might still return nil to skip some unwanted symbols 583 if elfsym.sym == 0 { 584 continue 585 } 586 sect = &elfobj.sect[elfsym.shndx] 587 if sect.sym == 0 { 588 if elfsym.type_ == 0 { 589 if strings.HasPrefix(sect.name, ".debug_") && elfsym.name == "" { 590 // clang on arm and riscv64. 591 // This reportedly happens with clang 3.7 on ARM. 592 // See issue 13139. 593 continue 594 } 595 if strings.HasPrefix(elfsym.name, ".Ldebug_") || elfsym.name == ".L0 " { 596 // gcc on riscv64. 597 continue 598 } 599 if elfsym.name == ".Lline_table_start0" { 600 // clang on riscv64. 601 continue 602 } 603 604 if strings.HasPrefix(elfsym.name, "$d") && sect.name == ".debug_frame" { 605 // "$d" is a marker, not a real symbol. 606 // This happens with gcc on ARM64. 607 // See https://sourceware.org/bugzilla/show_bug.cgi?id=21809 608 continue 609 } 610 } 611 612 if strings.HasPrefix(elfsym.name, ".Linfo_string") { 613 // clang does this 614 continue 615 } 616 617 if strings.HasPrefix(elfsym.name, ".LASF") || strings.HasPrefix(elfsym.name, ".LLRL") || strings.HasPrefix(elfsym.name, ".LLST") { 618 // gcc on s390x and riscv64 does this. 619 continue 620 } 621 622 return errorf("%v: sym#%d (%q): ignoring symbol in section %d (%q) (type %d)", elfsym.sym, i, elfsym.name, elfsym.shndx, sect.name, elfsym.type_) 623 } 624 625 s := elfsym.sym 626 if l.OuterSym(s) != 0 { 627 if l.AttrDuplicateOK(s) { 628 continue 629 } 630 return errorf("duplicate symbol reference: %s in both %s and %s", 631 l.SymName(s), l.SymName(l.OuterSym(s)), l.SymName(sect.sym)) 632 } 633 634 sectsb := l.MakeSymbolUpdater(sect.sym) 635 sb := l.MakeSymbolUpdater(s) 636 637 sb.SetType(sectsb.Type()) 638 sectsb.AddInteriorSym(s) 639 if !l.AttrCgoExportDynamic(s) { 640 sb.SetDynimplib("") // satisfy dynimport 641 } 642 sb.SetValue(int64(elfsym.value)) 643 sb.SetSize(int64(elfsym.size)) 644 if sectsb.Type() == sym.STEXT { 645 if l.AttrExternal(s) && !l.AttrDuplicateOK(s) { 646 return errorf("%s: duplicate symbol definition", sb.Name()) 647 } 648 l.SetAttrExternal(s, true) 649 } 650 651 if elf.Machine(elfobj.machine) == elf.EM_PPC64 { 652 flag := int(elfsym.other) >> 5 653 switch flag { 654 case 0: 655 // No local entry. R2 is preserved. 656 case 1: 657 // This is kind of a hack, but pass the hint about this symbol's 658 // usage of R2 (R2 is a caller-save register not a TOC pointer, and 659 // this function does not have a distinct local entry) by setting 660 // its SymLocalentry to 1. 661 l.SetSymLocalentry(s, 1) 662 case 7: 663 return errorf("%s: invalid sym.other 0x%x", sb.Name(), elfsym.other) 664 default: 665 // Convert the word sized offset into bytes. 666 l.SetSymLocalentry(s, 4<<uint(flag-2)) 667 } 668 } 669 } 670 671 // Sort outer lists by address, adding to textp. 672 // This keeps textp in increasing address order. 673 for i := uint(0); i < elfobj.nsect; i++ { 674 s := elfobj.sect[i].sym 675 if s == 0 { 676 continue 677 } 678 sb := l.MakeSymbolUpdater(s) 679 if l.SubSym(s) != 0 { 680 sb.SortSub() 681 } 682 if sb.Type() == sym.STEXT { 683 if l.AttrOnList(s) { 684 return errorf("symbol %s listed multiple times", 685 l.SymName(s)) 686 } 687 l.SetAttrOnList(s, true) 688 textp = append(textp, s) 689 for ss := l.SubSym(s); ss != 0; ss = l.SubSym(ss) { 690 if l.AttrOnList(ss) { 691 return errorf("symbol %s listed multiple times", 692 l.SymName(ss)) 693 } 694 l.SetAttrOnList(ss, true) 695 textp = append(textp, ss) 696 } 697 } 698 } 699 700 // load relocations 701 for i := uint(0); i < elfobj.nsect; i++ { 702 rsect := &elfobj.sect[i] 703 if rsect.type_ != elf.SHT_RELA && rsect.type_ != elf.SHT_REL { 704 continue 705 } 706 if rsect.info >= uint32(elfobj.nsect) || elfobj.sect[rsect.info].base == nil { 707 continue 708 } 709 sect = &elfobj.sect[rsect.info] 710 if err := elfmap(elfobj, rsect); err != nil { 711 return errorf("malformed elf file: %v", err) 712 } 713 rela := 0 714 if rsect.type_ == elf.SHT_RELA { 715 rela = 1 716 } 717 n := int(rsect.size / uint64(4+4*is64) / uint64(2+rela)) 718 p := rsect.base 719 sb := l.MakeSymbolUpdater(sect.sym) 720 for j := 0; j < n; j++ { 721 var add uint64 722 var symIdx int 723 var relocType uint64 724 var rOff int32 725 var rAdd int64 726 var rSym loader.Sym 727 728 if is64 != 0 { 729 // 64-bit rel/rela 730 rOff = int32(e.Uint64(p)) 731 732 p = p[8:] 733 switch arch.Family { 734 case sys.MIPS64: 735 // https://www.linux-mips.org/pub/linux/mips/doc/ABI/elf64-2.4.pdf 736 // The doc shows it's different with general Linux ELF 737 symIdx = int(e.Uint32(p)) 738 relocType = uint64(p[7]) 739 default: 740 info := e.Uint64(p) 741 relocType = info & 0xffffffff 742 symIdx = int(info >> 32) 743 } 744 p = p[8:] 745 if rela != 0 { 746 add = e.Uint64(p) 747 p = p[8:] 748 } 749 } else { 750 // 32-bit rel/rela 751 rOff = int32(e.Uint32(p)) 752 753 p = p[4:] 754 info := e.Uint32(p) 755 relocType = uint64(info & 0xff) 756 symIdx = int(info >> 8) 757 p = p[4:] 758 if rela != 0 { 759 add = uint64(e.Uint32(p)) 760 p = p[4:] 761 } 762 } 763 764 if relocType == 0 { // skip R_*_NONE relocation 765 j-- 766 n-- 767 continue 768 } 769 770 if symIdx == 0 { // absolute relocation, don't bother reading the null symbol 771 rSym = 0 772 } else { 773 var elfsym ElfSym 774 if err := readelfsym(newSym, lookup, l, arch, elfobj, int(symIdx), &elfsym, 0, 0); err != nil { 775 return errorf("malformed elf file: %v", err) 776 } 777 elfsym.sym = symbols[symIdx] 778 if elfsym.sym == 0 { 779 return errorf("malformed elf file: %s#%d: reloc of invalid sym #%d %s shndx=%d type=%d", l.SymName(sect.sym), j, int(symIdx), elfsym.name, elfsym.shndx, elfsym.type_) 780 } 781 782 rSym = elfsym.sym 783 } 784 785 rType := objabi.ElfRelocOffset + objabi.RelocType(relocType) 786 rSize, addendSize, err := relSize(arch, pn, uint32(relocType)) 787 if err != nil { 788 return nil, 0, err 789 } 790 if rela != 0 { 791 rAdd = int64(add) 792 } else { 793 // load addend from image 794 if rSize == 4 { 795 rAdd = int64(e.Uint32(sect.base[rOff:])) 796 } else if rSize == 8 { 797 rAdd = int64(e.Uint64(sect.base[rOff:])) 798 } else { 799 return errorf("invalid rela size %d", rSize) 800 } 801 } 802 803 if addendSize == 2 { 804 rAdd = int64(int16(rAdd)) 805 } 806 if addendSize == 4 { 807 rAdd = int64(int32(rAdd)) 808 } 809 810 r, _ := sb.AddRel(rType) 811 r.SetOff(rOff) 812 r.SetSiz(rSize) 813 r.SetSym(rSym) 814 r.SetAdd(rAdd) 815 } 816 817 sb.SortRelocs() // just in case 818 } 819 820 return textp, ehdrFlags, nil 821 } 822 823 func section(elfobj *ElfObj, name string) *ElfSect { 824 for i := 0; uint(i) < elfobj.nsect; i++ { 825 if elfobj.sect[i].name != "" && name != "" && elfobj.sect[i].name == name { 826 return &elfobj.sect[i] 827 } 828 } 829 return nil 830 } 831 832 func elfmap(elfobj *ElfObj, sect *ElfSect) (err error) { 833 if sect.base != nil { 834 return nil 835 } 836 837 if sect.off+sect.size > uint64(elfobj.length) { 838 err = fmt.Errorf("elf section past end of file") 839 return err 840 } 841 842 elfobj.f.MustSeek(int64(uint64(elfobj.base)+sect.off), 0) 843 sect.base, sect.readOnlyMem, err = elfobj.f.Slice(uint64(sect.size)) 844 if err != nil { 845 return fmt.Errorf("short read: %v", err) 846 } 847 848 return nil 849 } 850 851 func readelfsym(newSym, lookup func(string, int) loader.Sym, l *loader.Loader, arch *sys.Arch, elfobj *ElfObj, i int, elfsym *ElfSym, needSym int, localSymVersion int) (err error) { 852 if i >= elfobj.nsymtab || i < 0 { 853 err = fmt.Errorf("invalid elf symbol index") 854 return err 855 } 856 857 if i == 0 { 858 return fmt.Errorf("readym: read null symbol!") 859 } 860 861 if elfobj.is64 != 0 { 862 b := new(elf.Sym64) 863 binary.Read(bytes.NewReader(elfobj.symtab.base[i*elf.Sym64Size:(i+1)*elf.Sym64Size]), elfobj.e, b) 864 elfsym.name = cstring(elfobj.symstr.base[b.Name:]) 865 elfsym.value = b.Value 866 elfsym.size = b.Size 867 elfsym.shndx = elf.SectionIndex(b.Shndx) 868 elfsym.bind = elf.ST_BIND(b.Info) 869 elfsym.type_ = elf.ST_TYPE(b.Info) 870 elfsym.other = b.Other 871 } else { 872 b := new(elf.Sym32) 873 binary.Read(bytes.NewReader(elfobj.symtab.base[i*elf.Sym32Size:(i+1)*elf.Sym32Size]), elfobj.e, b) 874 elfsym.name = cstring(elfobj.symstr.base[b.Name:]) 875 elfsym.value = uint64(b.Value) 876 elfsym.size = uint64(b.Size) 877 elfsym.shndx = elf.SectionIndex(b.Shndx) 878 elfsym.bind = elf.ST_BIND(b.Info) 879 elfsym.type_ = elf.ST_TYPE(b.Info) 880 elfsym.other = b.Other 881 } 882 883 var s loader.Sym 884 885 if elfsym.name == "_GLOBAL_OFFSET_TABLE_" { 886 elfsym.name = ".got" 887 } 888 if elfsym.name == ".TOC." { 889 // Magic symbol on ppc64. Will be set to this object 890 // file's .got+0x8000. 891 elfsym.bind = elf.STB_LOCAL 892 } 893 894 switch elfsym.type_ { 895 case elf.STT_SECTION: 896 s = elfobj.sect[elfsym.shndx].sym 897 898 case elf.STT_OBJECT, elf.STT_FUNC, elf.STT_NOTYPE, elf.STT_COMMON: 899 switch elfsym.bind { 900 case elf.STB_GLOBAL: 901 if needSym != 0 { 902 s = lookup(elfsym.name, 0) 903 904 // for global scoped hidden symbols we should insert it into 905 // symbol hash table, but mark them as hidden. 906 // __i686.get_pc_thunk.bx is allowed to be duplicated, to 907 // workaround that we set dupok. 908 // TODO(minux): correctly handle __i686.get_pc_thunk.bx without 909 // set dupok generally. See https://golang.org/cl/5823055 910 // comment #5 for details. 911 if s != 0 && elfsym.other == 2 { 912 if !l.IsExternal(s) { 913 l.MakeSymbolUpdater(s) 914 } 915 l.SetAttrDuplicateOK(s, true) 916 l.SetAttrVisibilityHidden(s, true) 917 } 918 } 919 920 case elf.STB_LOCAL: 921 if (arch.Family == sys.ARM || arch.Family == sys.ARM64) && (strings.HasPrefix(elfsym.name, "$a") || strings.HasPrefix(elfsym.name, "$d") || strings.HasPrefix(elfsym.name, "$x")) { 922 // binutils for arm and arm64 generate these mapping 923 // symbols, ignore these 924 break 925 } 926 927 if elfsym.name == ".TOC." { 928 // We need to be able to look this up, 929 // so put it in the hash table. 930 if needSym != 0 { 931 s = lookup(elfsym.name, localSymVersion) 932 l.SetAttrVisibilityHidden(s, true) 933 } 934 break 935 } 936 937 if needSym != 0 { 938 // local names and hidden global names are unique 939 // and should only be referenced by their index, not name, so we 940 // don't bother to add them into the hash table 941 // FIXME: pass empty string here for name? This would 942 // reduce mem use, but also (possibly) make it harder 943 // to debug problems. 944 s = newSym(elfsym.name, localSymVersion) 945 l.SetAttrVisibilityHidden(s, true) 946 } 947 948 case elf.STB_WEAK: 949 if needSym != 0 { 950 s = lookup(elfsym.name, 0) 951 if elfsym.other == 2 { 952 l.SetAttrVisibilityHidden(s, true) 953 } 954 955 // Allow weak symbols to be duplicated when already defined. 956 if l.OuterSym(s) != 0 { 957 l.SetAttrDuplicateOK(s, true) 958 } 959 } 960 961 default: 962 err = fmt.Errorf("%s: invalid symbol binding %d", elfsym.name, elfsym.bind) 963 return err 964 } 965 } 966 967 if s != 0 && l.SymType(s) == 0 && elfsym.type_ != elf.STT_SECTION { 968 sb := l.MakeSymbolUpdater(s) 969 sb.SetType(sym.SXREF) 970 } 971 elfsym.sym = s 972 973 return nil 974 } 975 976 // Return the size of the relocated field, and the size of the addend as the first 977 // and second values. Note, the addend may be larger than the relocation field in 978 // some cases when a relocated value is split across multiple relocations. 979 func relSize(arch *sys.Arch, pn string, elftype uint32) (uint8, uint8, error) { 980 // TODO(mdempsky): Replace this with a struct-valued switch statement 981 // once golang.org/issue/15164 is fixed or found to not impair cmd/link 982 // performance. 983 984 const ( 985 AMD64 = uint32(sys.AMD64) 986 ARM = uint32(sys.ARM) 987 ARM64 = uint32(sys.ARM64) 988 I386 = uint32(sys.I386) 989 LOONG64 = uint32(sys.Loong64) 990 MIPS = uint32(sys.MIPS) 991 MIPS64 = uint32(sys.MIPS64) 992 PPC64 = uint32(sys.PPC64) 993 RISCV64 = uint32(sys.RISCV64) 994 S390X = uint32(sys.S390X) 995 ) 996 997 switch uint32(arch.Family) | elftype<<16 { 998 default: 999 return 0, 0, fmt.Errorf("%s: unknown relocation type %d; compiled without -fpic?", pn, elftype) 1000 1001 case MIPS | uint32(elf.R_MIPS_HI16)<<16, 1002 MIPS | uint32(elf.R_MIPS_LO16)<<16, 1003 MIPS | uint32(elf.R_MIPS_GOT16)<<16, 1004 MIPS | uint32(elf.R_MIPS_GOT_HI16)<<16, 1005 MIPS | uint32(elf.R_MIPS_GOT_LO16)<<16, 1006 MIPS | uint32(elf.R_MIPS_GPREL16)<<16, 1007 MIPS | uint32(elf.R_MIPS_GOT_PAGE)<<16, 1008 MIPS | uint32(elf.R_MIPS_JALR)<<16, 1009 MIPS | uint32(elf.R_MIPS_GOT_OFST)<<16, 1010 MIPS64 | uint32(elf.R_MIPS_HI16)<<16, 1011 MIPS64 | uint32(elf.R_MIPS_LO16)<<16, 1012 MIPS64 | uint32(elf.R_MIPS_GOT16)<<16, 1013 MIPS64 | uint32(elf.R_MIPS_GOT_HI16)<<16, 1014 MIPS64 | uint32(elf.R_MIPS_GOT_LO16)<<16, 1015 MIPS64 | uint32(elf.R_MIPS_GPREL16)<<16, 1016 MIPS64 | uint32(elf.R_MIPS_GOT_PAGE)<<16, 1017 MIPS64 | uint32(elf.R_MIPS_JALR)<<16, 1018 MIPS64 | uint32(elf.R_MIPS_GOT_OFST)<<16, 1019 MIPS64 | uint32(elf.R_MIPS_CALL16)<<16, 1020 MIPS64 | uint32(elf.R_MIPS_GPREL32)<<16, 1021 MIPS64 | uint32(elf.R_MIPS_64)<<16, 1022 MIPS64 | uint32(elf.R_MIPS_GOT_DISP)<<16, 1023 MIPS64 | uint32(elf.R_MIPS_PC32)<<16: 1024 return 4, 4, nil 1025 1026 case LOONG64 | uint32(elf.R_LARCH_ADD8)<<16, 1027 LOONG64 | uint32(elf.R_LARCH_SUB8)<<16: 1028 return 1, 1, nil 1029 1030 case LOONG64 | uint32(elf.R_LARCH_ADD16)<<16, 1031 LOONG64 | uint32(elf.R_LARCH_SUB16)<<16: 1032 return 2, 2, nil 1033 1034 case LOONG64 | uint32(elf.R_LARCH_SOP_PUSH_PCREL)<<16, 1035 LOONG64 | uint32(elf.R_LARCH_SOP_PUSH_GPREL)<<16, 1036 LOONG64 | uint32(elf.R_LARCH_SOP_PUSH_ABSOLUTE)<<16, 1037 LOONG64 | uint32(elf.R_LARCH_MARK_LA)<<16, 1038 LOONG64 | uint32(elf.R_LARCH_SOP_POP_32_S_0_10_10_16_S2)<<16, 1039 LOONG64 | uint32(elf.R_LARCH_MARK_PCREL)<<16, 1040 LOONG64 | uint32(elf.R_LARCH_ADD24)<<16, 1041 LOONG64 | uint32(elf.R_LARCH_ADD32)<<16, 1042 LOONG64 | uint32(elf.R_LARCH_SUB24)<<16, 1043 LOONG64 | uint32(elf.R_LARCH_SUB32)<<16, 1044 LOONG64 | uint32(elf.R_LARCH_B26)<<16, 1045 LOONG64 | uint32(elf.R_LARCH_32_PCREL)<<16: 1046 return 4, 4, nil 1047 1048 case LOONG64 | uint32(elf.R_LARCH_64)<<16, 1049 LOONG64 | uint32(elf.R_LARCH_ADD64)<<16, 1050 LOONG64 | uint32(elf.R_LARCH_SUB64)<<16, 1051 LOONG64 | uint32(elf.R_LARCH_64_PCREL)<<16: 1052 return 8, 8, nil 1053 1054 case S390X | uint32(elf.R_390_8)<<16: 1055 return 1, 1, nil 1056 1057 case PPC64 | uint32(elf.R_PPC64_TOC16)<<16, 1058 S390X | uint32(elf.R_390_16)<<16, 1059 S390X | uint32(elf.R_390_GOT16)<<16, 1060 S390X | uint32(elf.R_390_PC16)<<16, 1061 S390X | uint32(elf.R_390_PC16DBL)<<16, 1062 S390X | uint32(elf.R_390_PLT16DBL)<<16: 1063 return 2, 2, nil 1064 1065 case ARM | uint32(elf.R_ARM_ABS32)<<16, 1066 ARM | uint32(elf.R_ARM_GOT32)<<16, 1067 ARM | uint32(elf.R_ARM_PLT32)<<16, 1068 ARM | uint32(elf.R_ARM_GOTOFF)<<16, 1069 ARM | uint32(elf.R_ARM_GOTPC)<<16, 1070 ARM | uint32(elf.R_ARM_THM_PC22)<<16, 1071 ARM | uint32(elf.R_ARM_REL32)<<16, 1072 ARM | uint32(elf.R_ARM_CALL)<<16, 1073 ARM | uint32(elf.R_ARM_V4BX)<<16, 1074 ARM | uint32(elf.R_ARM_GOT_PREL)<<16, 1075 ARM | uint32(elf.R_ARM_PC24)<<16, 1076 ARM | uint32(elf.R_ARM_JUMP24)<<16, 1077 ARM64 | uint32(elf.R_AARCH64_CALL26)<<16, 1078 ARM64 | uint32(elf.R_AARCH64_ADR_GOT_PAGE)<<16, 1079 ARM64 | uint32(elf.R_AARCH64_LD64_GOT_LO12_NC)<<16, 1080 ARM64 | uint32(elf.R_AARCH64_ADR_PREL_PG_HI21)<<16, 1081 ARM64 | uint32(elf.R_AARCH64_ADD_ABS_LO12_NC)<<16, 1082 ARM64 | uint32(elf.R_AARCH64_LDST8_ABS_LO12_NC)<<16, 1083 ARM64 | uint32(elf.R_AARCH64_LDST16_ABS_LO12_NC)<<16, 1084 ARM64 | uint32(elf.R_AARCH64_LDST32_ABS_LO12_NC)<<16, 1085 ARM64 | uint32(elf.R_AARCH64_LDST64_ABS_LO12_NC)<<16, 1086 ARM64 | uint32(elf.R_AARCH64_LDST128_ABS_LO12_NC)<<16, 1087 ARM64 | uint32(elf.R_AARCH64_PREL32)<<16, 1088 ARM64 | uint32(elf.R_AARCH64_JUMP26)<<16, 1089 AMD64 | uint32(elf.R_X86_64_PC32)<<16, 1090 AMD64 | uint32(elf.R_X86_64_PLT32)<<16, 1091 AMD64 | uint32(elf.R_X86_64_GOTPCREL)<<16, 1092 AMD64 | uint32(elf.R_X86_64_GOTPCRELX)<<16, 1093 AMD64 | uint32(elf.R_X86_64_REX_GOTPCRELX)<<16, 1094 I386 | uint32(elf.R_386_32)<<16, 1095 I386 | uint32(elf.R_386_PC32)<<16, 1096 I386 | uint32(elf.R_386_GOT32)<<16, 1097 I386 | uint32(elf.R_386_PLT32)<<16, 1098 I386 | uint32(elf.R_386_GOTOFF)<<16, 1099 I386 | uint32(elf.R_386_GOTPC)<<16, 1100 I386 | uint32(elf.R_386_GOT32X)<<16, 1101 PPC64 | uint32(elf.R_PPC64_REL24)<<16, 1102 PPC64 | uint32(elf.R_PPC64_REL24_NOTOC)<<16, 1103 PPC64 | uint32(elf.R_PPC64_REL24_P9NOTOC)<<16, 1104 PPC64 | uint32(elf.R_PPC_REL32)<<16, 1105 S390X | uint32(elf.R_390_32)<<16, 1106 S390X | uint32(elf.R_390_PC32)<<16, 1107 S390X | uint32(elf.R_390_GOT32)<<16, 1108 S390X | uint32(elf.R_390_PLT32)<<16, 1109 S390X | uint32(elf.R_390_PC32DBL)<<16, 1110 S390X | uint32(elf.R_390_PLT32DBL)<<16, 1111 S390X | uint32(elf.R_390_GOTPCDBL)<<16, 1112 S390X | uint32(elf.R_390_GOTENT)<<16: 1113 return 4, 4, nil 1114 1115 case AMD64 | uint32(elf.R_X86_64_64)<<16, 1116 AMD64 | uint32(elf.R_X86_64_PC64)<<16, 1117 ARM64 | uint32(elf.R_AARCH64_ABS64)<<16, 1118 ARM64 | uint32(elf.R_AARCH64_PREL64)<<16, 1119 PPC64 | uint32(elf.R_PPC64_ADDR64)<<16, 1120 PPC64 | uint32(elf.R_PPC64_PCREL34)<<16, 1121 PPC64 | uint32(elf.R_PPC64_GOT_PCREL34)<<16, 1122 PPC64 | uint32(elf.R_PPC64_PLT_PCREL34_NOTOC)<<16, 1123 S390X | uint32(elf.R_390_GLOB_DAT)<<16, 1124 S390X | uint32(elf.R_390_RELATIVE)<<16, 1125 S390X | uint32(elf.R_390_GOTOFF)<<16, 1126 S390X | uint32(elf.R_390_GOTPC)<<16, 1127 S390X | uint32(elf.R_390_64)<<16, 1128 S390X | uint32(elf.R_390_PC64)<<16, 1129 S390X | uint32(elf.R_390_GOT64)<<16, 1130 S390X | uint32(elf.R_390_PLT64)<<16: 1131 return 8, 8, nil 1132 1133 case RISCV64 | uint32(elf.R_RISCV_SET6)<<16, 1134 RISCV64 | uint32(elf.R_RISCV_SUB6)<<16, 1135 RISCV64 | uint32(elf.R_RISCV_SET8)<<16, 1136 RISCV64 | uint32(elf.R_RISCV_SUB8)<<16: 1137 return 1, 1, nil 1138 1139 case RISCV64 | uint32(elf.R_RISCV_RVC_BRANCH)<<16, 1140 RISCV64 | uint32(elf.R_RISCV_RVC_JUMP)<<16, 1141 RISCV64 | uint32(elf.R_RISCV_SET16)<<16, 1142 RISCV64 | uint32(elf.R_RISCV_SUB16)<<16: 1143 return 2, 2, nil 1144 1145 case RISCV64 | uint32(elf.R_RISCV_32)<<16, 1146 RISCV64 | uint32(elf.R_RISCV_BRANCH)<<16, 1147 RISCV64 | uint32(elf.R_RISCV_HI20)<<16, 1148 RISCV64 | uint32(elf.R_RISCV_LO12_I)<<16, 1149 RISCV64 | uint32(elf.R_RISCV_LO12_S)<<16, 1150 RISCV64 | uint32(elf.R_RISCV_GOT_HI20)<<16, 1151 RISCV64 | uint32(elf.R_RISCV_PCREL_HI20)<<16, 1152 RISCV64 | uint32(elf.R_RISCV_PCREL_LO12_I)<<16, 1153 RISCV64 | uint32(elf.R_RISCV_PCREL_LO12_S)<<16, 1154 RISCV64 | uint32(elf.R_RISCV_ADD32)<<16, 1155 RISCV64 | uint32(elf.R_RISCV_SET32)<<16, 1156 RISCV64 | uint32(elf.R_RISCV_SUB32)<<16, 1157 RISCV64 | uint32(elf.R_RISCV_32_PCREL)<<16, 1158 RISCV64 | uint32(elf.R_RISCV_RELAX)<<16: 1159 return 4, 4, nil 1160 1161 case RISCV64 | uint32(elf.R_RISCV_64)<<16, 1162 RISCV64 | uint32(elf.R_RISCV_CALL)<<16, 1163 RISCV64 | uint32(elf.R_RISCV_CALL_PLT)<<16: 1164 return 8, 8, nil 1165 1166 case PPC64 | uint32(elf.R_PPC64_TOC16_LO)<<16, 1167 PPC64 | uint32(elf.R_PPC64_TOC16_HI)<<16, 1168 PPC64 | uint32(elf.R_PPC64_TOC16_HA)<<16, 1169 PPC64 | uint32(elf.R_PPC64_TOC16_DS)<<16, 1170 PPC64 | uint32(elf.R_PPC64_TOC16_LO_DS)<<16, 1171 PPC64 | uint32(elf.R_PPC64_REL16_LO)<<16, 1172 PPC64 | uint32(elf.R_PPC64_REL16_HI)<<16, 1173 PPC64 | uint32(elf.R_PPC64_REL16_HA)<<16, 1174 PPC64 | uint32(elf.R_PPC64_PLT16_HA)<<16, 1175 PPC64 | uint32(elf.R_PPC64_PLT16_LO_DS)<<16: 1176 return 2, 4, nil 1177 1178 // PPC64 inline PLT sequence hint relocations (-fno-plt) 1179 // These are informational annotations to assist linker optimizations. 1180 case PPC64 | uint32(elf.R_PPC64_PLTSEQ)<<16, 1181 PPC64 | uint32(elf.R_PPC64_PLTCALL)<<16, 1182 PPC64 | uint32(elf.R_PPC64_PLTCALL_NOTOC)<<16, 1183 PPC64 | uint32(elf.R_PPC64_PLTSEQ_NOTOC)<<16: 1184 return 0, 0, nil 1185 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 }