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 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 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(lookup(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 } 540 541 sb.SetSize(int64(sect.size)) 542 sb.SetAlign(int32(sect.align)) 543 sb.SetReadOnly(sect.readOnlyMem) 544 545 sect.sym = sb.Sym() 546 } 547 548 // enter sub-symbols into symbol table. 549 // symbol 0 is the null symbol. 550 symbols := make([]loader.Sym, elfobj.nsymtab) 551 552 for i := 1; i < elfobj.nsymtab; i++ { 553 var elfsym ElfSym 554 if err := readelfsym(newSym, lookup, l, arch, elfobj, i, &elfsym, 1, localSymVersion); err != nil { 555 return errorf("%s: malformed elf file: %v", pn, err) 556 } 557 symbols[i] = elfsym.sym 558 if elfsym.type_ != elf.STT_FUNC && elfsym.type_ != elf.STT_OBJECT && elfsym.type_ != elf.STT_NOTYPE && elfsym.type_ != elf.STT_COMMON { 559 continue 560 } 561 if elfsym.shndx == elf.SHN_COMMON || elfsym.type_ == elf.STT_COMMON { 562 sb := l.MakeSymbolUpdater(elfsym.sym) 563 if uint64(sb.Size()) < elfsym.size { 564 sb.SetSize(int64(elfsym.size)) 565 } 566 if sb.Type() == 0 || sb.Type() == sym.SXREF { 567 sb.SetType(sym.SNOPTRBSS) 568 } 569 continue 570 } 571 572 if uint(elfsym.shndx) >= elfobj.nsect || elfsym.shndx == 0 { 573 continue 574 } 575 576 // even when we pass needSym == 1 to readelfsym, it might still return nil to skip some unwanted symbols 577 if elfsym.sym == 0 { 578 continue 579 } 580 sect = &elfobj.sect[elfsym.shndx] 581 if sect.sym == 0 { 582 if strings.HasPrefix(elfsym.name, ".Linfo_string") { // clang does this 583 continue 584 } 585 586 if elfsym.name == "" && elfsym.type_ == 0 && sect.name == ".debug_str" { 587 // This reportedly happens with clang 3.7 on ARM. 588 // See issue 13139. 589 continue 590 } 591 592 if strings.HasPrefix(elfsym.name, "$d") && elfsym.type_ == 0 && sect.name == ".debug_frame" { 593 // "$d" is a marker, not a real symbol. 594 // This happens with gcc on ARM64. 595 // See https://sourceware.org/bugzilla/show_bug.cgi?id=21809 596 continue 597 } 598 599 if strings.HasPrefix(elfsym.name, ".LASF") { // gcc on s390x does this 600 continue 601 } 602 return errorf("%v: sym#%d (%s): ignoring symbol in section %d (type %d)", elfsym.sym, i, elfsym.name, elfsym.shndx, elfsym.type_) 603 } 604 605 s := elfsym.sym 606 if l.OuterSym(s) != 0 { 607 if l.AttrDuplicateOK(s) { 608 continue 609 } 610 return errorf("duplicate symbol reference: %s in both %s and %s", 611 l.SymName(s), l.SymName(l.OuterSym(s)), l.SymName(sect.sym)) 612 } 613 614 sectsb := l.MakeSymbolUpdater(sect.sym) 615 sb := l.MakeSymbolUpdater(s) 616 617 sb.SetType(sectsb.Type()) 618 sectsb.AddInteriorSym(s) 619 if !l.AttrCgoExportDynamic(s) { 620 sb.SetDynimplib("") // satisfy dynimport 621 } 622 sb.SetValue(int64(elfsym.value)) 623 sb.SetSize(int64(elfsym.size)) 624 if sectsb.Type() == sym.STEXT { 625 if l.AttrExternal(s) && !l.AttrDuplicateOK(s) { 626 return errorf("%s: duplicate symbol definition", sb.Name()) 627 } 628 l.SetAttrExternal(s, true) 629 } 630 631 if elf.Machine(elfobj.machine) == elf.EM_PPC64 { 632 flag := int(elfsym.other) >> 5 633 if 2 <= flag && flag <= 6 { 634 l.SetSymLocalentry(s, 1<<uint(flag-2)) 635 } else if flag == 7 { 636 return errorf("%s: invalid sym.other 0x%x", sb.Name(), elfsym.other) 637 } 638 } 639 } 640 641 // Sort outer lists by address, adding to textp. 642 // This keeps textp in increasing address order. 643 for i := uint(0); i < elfobj.nsect; i++ { 644 s := elfobj.sect[i].sym 645 if s == 0 { 646 continue 647 } 648 sb := l.MakeSymbolUpdater(s) 649 if l.SubSym(s) != 0 { 650 sb.SortSub() 651 } 652 if sb.Type() == sym.STEXT { 653 if l.AttrOnList(s) { 654 return errorf("symbol %s listed multiple times", 655 l.SymName(s)) 656 } 657 l.SetAttrOnList(s, true) 658 textp = append(textp, s) 659 for ss := l.SubSym(s); ss != 0; ss = l.SubSym(ss) { 660 if l.AttrOnList(ss) { 661 return errorf("symbol %s listed multiple times", 662 l.SymName(ss)) 663 } 664 l.SetAttrOnList(ss, true) 665 textp = append(textp, ss) 666 } 667 } 668 } 669 670 // load relocations 671 for i := uint(0); i < elfobj.nsect; i++ { 672 rsect := &elfobj.sect[i] 673 if rsect.type_ != elf.SHT_RELA && rsect.type_ != elf.SHT_REL { 674 continue 675 } 676 if rsect.info >= uint32(elfobj.nsect) || elfobj.sect[rsect.info].base == nil { 677 continue 678 } 679 sect = &elfobj.sect[rsect.info] 680 if err := elfmap(elfobj, rsect); err != nil { 681 return errorf("malformed elf file: %v", err) 682 } 683 rela := 0 684 if rsect.type_ == elf.SHT_RELA { 685 rela = 1 686 } 687 n := int(rsect.size / uint64(4+4*is64) / uint64(2+rela)) 688 p := rsect.base 689 sb := l.MakeSymbolUpdater(sect.sym) 690 for j := 0; j < n; j++ { 691 var add uint64 692 var symIdx int 693 var relocType uint64 694 var rOff int32 695 var rAdd int64 696 var rSym loader.Sym 697 698 if is64 != 0 { 699 // 64-bit rel/rela 700 rOff = int32(e.Uint64(p)) 701 702 p = p[8:] 703 switch arch.Family { 704 case sys.MIPS64: 705 // https://www.linux-mips.org/pub/linux/mips/doc/ABI/elf64-2.4.pdf 706 // The doc shows it's different with general Linux ELF 707 symIdx = int(e.Uint32(p)) 708 relocType = uint64(p[7]) 709 default: 710 info := e.Uint64(p) 711 relocType = info & 0xffffffff 712 symIdx = int(info >> 32) 713 } 714 p = p[8:] 715 if rela != 0 { 716 add = e.Uint64(p) 717 p = p[8:] 718 } 719 } else { 720 // 32-bit rel/rela 721 rOff = int32(e.Uint32(p)) 722 723 p = p[4:] 724 info := e.Uint32(p) 725 relocType = uint64(info & 0xff) 726 symIdx = int(info >> 8) 727 p = p[4:] 728 if rela != 0 { 729 add = uint64(e.Uint32(p)) 730 p = p[4:] 731 } 732 } 733 734 if relocType == 0 { // skip R_*_NONE relocation 735 j-- 736 n-- 737 continue 738 } 739 740 if symIdx == 0 { // absolute relocation, don't bother reading the null symbol 741 rSym = 0 742 } else { 743 var elfsym ElfSym 744 if err := readelfsym(newSym, lookup, l, arch, elfobj, int(symIdx), &elfsym, 0, 0); err != nil { 745 return errorf("malformed elf file: %v", err) 746 } 747 elfsym.sym = symbols[symIdx] 748 if elfsym.sym == 0 { 749 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_) 750 } 751 752 rSym = elfsym.sym 753 } 754 755 rType := objabi.ElfRelocOffset + objabi.RelocType(relocType) 756 rSize, addendSize, err := relSize(arch, pn, uint32(relocType)) 757 if err != nil { 758 return nil, 0, err 759 } 760 if rela != 0 { 761 rAdd = int64(add) 762 } else { 763 // load addend from image 764 if rSize == 4 { 765 rAdd = int64(e.Uint32(sect.base[rOff:])) 766 } else if rSize == 8 { 767 rAdd = int64(e.Uint64(sect.base[rOff:])) 768 } else { 769 return errorf("invalid rela size %d", rSize) 770 } 771 } 772 773 if addendSize == 2 { 774 rAdd = int64(int16(rAdd)) 775 } 776 if addendSize == 4 { 777 rAdd = int64(int32(rAdd)) 778 } 779 780 r, _ := sb.AddRel(rType) 781 r.SetOff(rOff) 782 r.SetSiz(rSize) 783 r.SetSym(rSym) 784 r.SetAdd(rAdd) 785 } 786 787 sb.SortRelocs() // just in case 788 } 789 790 return textp, ehdrFlags, nil 791} 792 793func section(elfobj *ElfObj, name string) *ElfSect { 794 for i := 0; uint(i) < elfobj.nsect; i++ { 795 if elfobj.sect[i].name != "" && name != "" && elfobj.sect[i].name == name { 796 return &elfobj.sect[i] 797 } 798 } 799 return nil 800} 801 802func elfmap(elfobj *ElfObj, sect *ElfSect) (err error) { 803 if sect.base != nil { 804 return nil 805 } 806 807 if sect.off+sect.size > uint64(elfobj.length) { 808 err = fmt.Errorf("elf section past end of file") 809 return err 810 } 811 812 elfobj.f.MustSeek(int64(uint64(elfobj.base)+sect.off), 0) 813 sect.base, sect.readOnlyMem, err = elfobj.f.Slice(uint64(sect.size)) 814 if err != nil { 815 return fmt.Errorf("short read: %v", err) 816 } 817 818 return nil 819} 820 821func 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) { 822 if i >= elfobj.nsymtab || i < 0 { 823 err = fmt.Errorf("invalid elf symbol index") 824 return err 825 } 826 827 if i == 0 { 828 return fmt.Errorf("readym: read null symbol!") 829 } 830 831 if elfobj.is64 != 0 { 832 b := new(elf.Sym64) 833 binary.Read(bytes.NewReader(elfobj.symtab.base[i*elf.Sym64Size:(i+1)*elf.Sym64Size]), elfobj.e, b) 834 elfsym.name = cstring(elfobj.symstr.base[b.Name:]) 835 elfsym.value = b.Value 836 elfsym.size = b.Size 837 elfsym.shndx = elf.SectionIndex(b.Shndx) 838 elfsym.bind = elf.ST_BIND(b.Info) 839 elfsym.type_ = elf.ST_TYPE(b.Info) 840 elfsym.other = b.Other 841 } else { 842 b := new(elf.Sym32) 843 binary.Read(bytes.NewReader(elfobj.symtab.base[i*elf.Sym32Size:(i+1)*elf.Sym32Size]), elfobj.e, b) 844 elfsym.name = cstring(elfobj.symstr.base[b.Name:]) 845 elfsym.value = uint64(b.Value) 846 elfsym.size = uint64(b.Size) 847 elfsym.shndx = elf.SectionIndex(b.Shndx) 848 elfsym.bind = elf.ST_BIND(b.Info) 849 elfsym.type_ = elf.ST_TYPE(b.Info) 850 elfsym.other = b.Other 851 } 852 853 var s loader.Sym 854 855 if elfsym.name == "_GLOBAL_OFFSET_TABLE_" { 856 elfsym.name = ".got" 857 } 858 if elfsym.name == ".TOC." { 859 // Magic symbol on ppc64. Will be set to this object 860 // file's .got+0x8000. 861 elfsym.bind = elf.STB_LOCAL 862 } 863 864 switch elfsym.type_ { 865 case elf.STT_SECTION: 866 s = elfobj.sect[elfsym.shndx].sym 867 868 case elf.STT_OBJECT, elf.STT_FUNC, elf.STT_NOTYPE, elf.STT_COMMON: 869 switch elfsym.bind { 870 case elf.STB_GLOBAL: 871 if needSym != 0 { 872 s = lookup(elfsym.name, 0) 873 874 // for global scoped hidden symbols we should insert it into 875 // symbol hash table, but mark them as hidden. 876 // __i686.get_pc_thunk.bx is allowed to be duplicated, to 877 // workaround that we set dupok. 878 // TODO(minux): correctly handle __i686.get_pc_thunk.bx without 879 // set dupok generally. See https://golang.org/cl/5823055 880 // comment #5 for details. 881 if s != 0 && elfsym.other == 2 { 882 if !l.IsExternal(s) { 883 l.MakeSymbolUpdater(s) 884 } 885 l.SetAttrDuplicateOK(s, true) 886 l.SetAttrVisibilityHidden(s, true) 887 } 888 } 889 890 case elf.STB_LOCAL: 891 if (arch.Family == sys.ARM || arch.Family == sys.ARM64) && (strings.HasPrefix(elfsym.name, "$a") || strings.HasPrefix(elfsym.name, "$d") || strings.HasPrefix(elfsym.name, "$x")) { 892 // binutils for arm and arm64 generate these mapping 893 // symbols, ignore these 894 break 895 } 896 897 if elfsym.name == ".TOC." { 898 // We need to be able to look this up, 899 // so put it in the hash table. 900 if needSym != 0 { 901 s = lookup(elfsym.name, localSymVersion) 902 l.SetAttrVisibilityHidden(s, true) 903 } 904 break 905 } 906 907 if needSym != 0 { 908 // local names and hidden global names are unique 909 // and should only be referenced by their index, not name, so we 910 // don't bother to add them into the hash table 911 // FIXME: pass empty string here for name? This would 912 // reduce mem use, but also (possibly) make it harder 913 // to debug problems. 914 s = newSym(elfsym.name, localSymVersion) 915 l.SetAttrVisibilityHidden(s, true) 916 } 917 918 case elf.STB_WEAK: 919 if needSym != 0 { 920 s = lookup(elfsym.name, 0) 921 if elfsym.other == 2 { 922 l.SetAttrVisibilityHidden(s, true) 923 } 924 925 // Allow weak symbols to be duplicated when already defined. 926 if l.OuterSym(s) != 0 { 927 l.SetAttrDuplicateOK(s, true) 928 } 929 } 930 931 default: 932 err = fmt.Errorf("%s: invalid symbol binding %d", elfsym.name, elfsym.bind) 933 return err 934 } 935 } 936 937 // TODO(mwhudson): the test of VisibilityHidden here probably doesn't make 938 // sense and should be removed when someone has thought about it properly. 939 if s != 0 && l.SymType(s) == 0 && !l.AttrVisibilityHidden(s) && elfsym.type_ != elf.STT_SECTION { 940 sb := l.MakeSymbolUpdater(s) 941 sb.SetType(sym.SXREF) 942 } 943 elfsym.sym = s 944 945 return nil 946} 947 948// Return the size of the relocated field, and the size of the addend as the first 949// and second values. Note, the addend may be larger than the relocation field in 950// some cases when a relocated value is split across multiple relocations. 951func relSize(arch *sys.Arch, pn string, elftype uint32) (uint8, uint8, error) { 952 // TODO(mdempsky): Replace this with a struct-valued switch statement 953 // once golang.org/issue/15164 is fixed or found to not impair cmd/link 954 // performance. 955 956 const ( 957 AMD64 = uint32(sys.AMD64) 958 ARM = uint32(sys.ARM) 959 ARM64 = uint32(sys.ARM64) 960 I386 = uint32(sys.I386) 961 MIPS = uint32(sys.MIPS) 962 MIPS64 = uint32(sys.MIPS64) 963 PPC64 = uint32(sys.PPC64) 964 RISCV64 = uint32(sys.RISCV64) 965 S390X = uint32(sys.S390X) 966 ) 967 968 switch uint32(arch.Family) | elftype<<16 { 969 default: 970 return 0, 0, fmt.Errorf("%s: unknown relocation type %d; compiled without -fpic?", pn, elftype) 971 972 case MIPS | uint32(elf.R_MIPS_HI16)<<16, 973 MIPS | uint32(elf.R_MIPS_LO16)<<16, 974 MIPS | uint32(elf.R_MIPS_GOT16)<<16, 975 MIPS | uint32(elf.R_MIPS_GOT_HI16)<<16, 976 MIPS | uint32(elf.R_MIPS_GOT_LO16)<<16, 977 MIPS | uint32(elf.R_MIPS_GPREL16)<<16, 978 MIPS | uint32(elf.R_MIPS_GOT_PAGE)<<16, 979 MIPS | uint32(elf.R_MIPS_JALR)<<16, 980 MIPS | uint32(elf.R_MIPS_GOT_OFST)<<16, 981 MIPS64 | uint32(elf.R_MIPS_HI16)<<16, 982 MIPS64 | uint32(elf.R_MIPS_LO16)<<16, 983 MIPS64 | uint32(elf.R_MIPS_GOT16)<<16, 984 MIPS64 | uint32(elf.R_MIPS_GOT_HI16)<<16, 985 MIPS64 | uint32(elf.R_MIPS_GOT_LO16)<<16, 986 MIPS64 | uint32(elf.R_MIPS_GPREL16)<<16, 987 MIPS64 | uint32(elf.R_MIPS_GOT_PAGE)<<16, 988 MIPS64 | uint32(elf.R_MIPS_JALR)<<16, 989 MIPS64 | uint32(elf.R_MIPS_GOT_OFST)<<16, 990 MIPS64 | uint32(elf.R_MIPS_CALL16)<<16, 991 MIPS64 | uint32(elf.R_MIPS_GPREL32)<<16, 992 MIPS64 | uint32(elf.R_MIPS_64)<<16, 993 MIPS64 | uint32(elf.R_MIPS_GOT_DISP)<<16: 994 return 4, 4, nil 995 996 case S390X | uint32(elf.R_390_8)<<16: 997 return 1, 1, nil 998 999 case PPC64 | uint32(elf.R_PPC64_TOC16)<<16, 1000 S390X | uint32(elf.R_390_16)<<16, 1001 S390X | uint32(elf.R_390_GOT16)<<16, 1002 S390X | uint32(elf.R_390_PC16)<<16, 1003 S390X | uint32(elf.R_390_PC16DBL)<<16, 1004 S390X | uint32(elf.R_390_PLT16DBL)<<16: 1005 return 2, 2, nil 1006 1007 case ARM | uint32(elf.R_ARM_ABS32)<<16, 1008 ARM | uint32(elf.R_ARM_GOT32)<<16, 1009 ARM | uint32(elf.R_ARM_PLT32)<<16, 1010 ARM | uint32(elf.R_ARM_GOTOFF)<<16, 1011 ARM | uint32(elf.R_ARM_GOTPC)<<16, 1012 ARM | uint32(elf.R_ARM_THM_PC22)<<16, 1013 ARM | uint32(elf.R_ARM_REL32)<<16, 1014 ARM | uint32(elf.R_ARM_CALL)<<16, 1015 ARM | uint32(elf.R_ARM_V4BX)<<16, 1016 ARM | uint32(elf.R_ARM_GOT_PREL)<<16, 1017 ARM | uint32(elf.R_ARM_PC24)<<16, 1018 ARM | uint32(elf.R_ARM_JUMP24)<<16, 1019 ARM64 | uint32(elf.R_AARCH64_CALL26)<<16, 1020 ARM64 | uint32(elf.R_AARCH64_ADR_GOT_PAGE)<<16, 1021 ARM64 | uint32(elf.R_AARCH64_LD64_GOT_LO12_NC)<<16, 1022 ARM64 | uint32(elf.R_AARCH64_ADR_PREL_PG_HI21)<<16, 1023 ARM64 | uint32(elf.R_AARCH64_ADD_ABS_LO12_NC)<<16, 1024 ARM64 | uint32(elf.R_AARCH64_LDST8_ABS_LO12_NC)<<16, 1025 ARM64 | uint32(elf.R_AARCH64_LDST16_ABS_LO12_NC)<<16, 1026 ARM64 | uint32(elf.R_AARCH64_LDST32_ABS_LO12_NC)<<16, 1027 ARM64 | uint32(elf.R_AARCH64_LDST64_ABS_LO12_NC)<<16, 1028 ARM64 | uint32(elf.R_AARCH64_LDST128_ABS_LO12_NC)<<16, 1029 ARM64 | uint32(elf.R_AARCH64_PREL32)<<16, 1030 ARM64 | uint32(elf.R_AARCH64_JUMP26)<<16, 1031 AMD64 | uint32(elf.R_X86_64_PC32)<<16, 1032 AMD64 | uint32(elf.R_X86_64_PLT32)<<16, 1033 AMD64 | uint32(elf.R_X86_64_GOTPCREL)<<16, 1034 AMD64 | uint32(elf.R_X86_64_GOTPCRELX)<<16, 1035 AMD64 | uint32(elf.R_X86_64_REX_GOTPCRELX)<<16, 1036 I386 | uint32(elf.R_386_32)<<16, 1037 I386 | uint32(elf.R_386_PC32)<<16, 1038 I386 | uint32(elf.R_386_GOT32)<<16, 1039 I386 | uint32(elf.R_386_PLT32)<<16, 1040 I386 | uint32(elf.R_386_GOTOFF)<<16, 1041 I386 | uint32(elf.R_386_GOTPC)<<16, 1042 I386 | uint32(elf.R_386_GOT32X)<<16, 1043 PPC64 | uint32(elf.R_PPC64_REL24)<<16, 1044 PPC64 | uint32(elf.R_PPC_REL32)<<16, 1045 S390X | uint32(elf.R_390_32)<<16, 1046 S390X | uint32(elf.R_390_PC32)<<16, 1047 S390X | uint32(elf.R_390_GOT32)<<16, 1048 S390X | uint32(elf.R_390_PLT32)<<16, 1049 S390X | uint32(elf.R_390_PC32DBL)<<16, 1050 S390X | uint32(elf.R_390_PLT32DBL)<<16, 1051 S390X | uint32(elf.R_390_GOTPCDBL)<<16, 1052 S390X | uint32(elf.R_390_GOTENT)<<16: 1053 return 4, 4, nil 1054 1055 case AMD64 | uint32(elf.R_X86_64_64)<<16, 1056 AMD64 | uint32(elf.R_X86_64_PC64)<<16, 1057 ARM64 | uint32(elf.R_AARCH64_ABS64)<<16, 1058 ARM64 | uint32(elf.R_AARCH64_PREL64)<<16, 1059 PPC64 | uint32(elf.R_PPC64_ADDR64)<<16, 1060 S390X | uint32(elf.R_390_GLOB_DAT)<<16, 1061 S390X | uint32(elf.R_390_RELATIVE)<<16, 1062 S390X | uint32(elf.R_390_GOTOFF)<<16, 1063 S390X | uint32(elf.R_390_GOTPC)<<16, 1064 S390X | uint32(elf.R_390_64)<<16, 1065 S390X | uint32(elf.R_390_PC64)<<16, 1066 S390X | uint32(elf.R_390_GOT64)<<16, 1067 S390X | uint32(elf.R_390_PLT64)<<16: 1068 return 8, 8, nil 1069 1070 case RISCV64 | uint32(elf.R_RISCV_RVC_BRANCH)<<16, 1071 RISCV64 | uint32(elf.R_RISCV_RVC_JUMP)<<16: 1072 return 2, 2, nil 1073 1074 case RISCV64 | uint32(elf.R_RISCV_32)<<16, 1075 RISCV64 | uint32(elf.R_RISCV_BRANCH)<<16, 1076 RISCV64 | uint32(elf.R_RISCV_HI20)<<16, 1077 RISCV64 | uint32(elf.R_RISCV_LO12_I)<<16, 1078 RISCV64 | uint32(elf.R_RISCV_LO12_S)<<16, 1079 RISCV64 | uint32(elf.R_RISCV_GOT_HI20)<<16, 1080 RISCV64 | uint32(elf.R_RISCV_PCREL_HI20)<<16, 1081 RISCV64 | uint32(elf.R_RISCV_PCREL_LO12_I)<<16, 1082 RISCV64 | uint32(elf.R_RISCV_PCREL_LO12_S)<<16, 1083 RISCV64 | uint32(elf.R_RISCV_RELAX)<<16: 1084 return 4, 4, nil 1085 1086 case RISCV64 | uint32(elf.R_RISCV_64)<<16, 1087 RISCV64 | uint32(elf.R_RISCV_CALL)<<16, 1088 RISCV64 | uint32(elf.R_RISCV_CALL_PLT)<<16: 1089 return 8, 8, nil 1090 1091 case PPC64 | uint32(elf.R_PPC64_TOC16_LO)<<16, 1092 PPC64 | uint32(elf.R_PPC64_TOC16_HI)<<16, 1093 PPC64 | uint32(elf.R_PPC64_TOC16_HA)<<16, 1094 PPC64 | uint32(elf.R_PPC64_TOC16_DS)<<16, 1095 PPC64 | uint32(elf.R_PPC64_TOC16_LO_DS)<<16, 1096 PPC64 | uint32(elf.R_PPC64_REL16_LO)<<16, 1097 PPC64 | uint32(elf.R_PPC64_REL16_HI)<<16, 1098 PPC64 | uint32(elf.R_PPC64_REL16_HA)<<16: 1099 return 2, 4, nil 1100 } 1101} 1102 1103func cstring(x []byte) string { 1104 i := bytes.IndexByte(x, '\x00') 1105 if i >= 0 { 1106 x = x[:i] 1107 } 1108 return string(x) 1109} 1110