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