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