github.com/x04/go/src@v0.0.0-20200202162449-3d481ceb3525/debug/elf/file.go (about) 1 // Copyright 2009 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 elf implements access to ELF object files. 6 package elf 7 8 import ( 9 "github.com/x04/go/src/bytes" 10 "github.com/x04/go/src/compress/zlib" 11 "github.com/x04/go/src/debug/dwarf" 12 "github.com/x04/go/src/encoding/binary" 13 "github.com/x04/go/src/errors" 14 "github.com/x04/go/src/fmt" 15 "github.com/x04/go/src/io" 16 "github.com/x04/go/src/os" 17 "github.com/x04/go/src/strings" 18 ) 19 20 // seekStart, seekCurrent, seekEnd are copies of 21 // io.SeekStart, io.SeekCurrent, and io.SeekEnd. 22 // We can't use the ones from package io because 23 // we want this code to build with Go 1.4 during 24 // cmd/dist bootstrap. 25 const ( 26 seekStart int = 0 27 seekCurrent int = 1 28 seekEnd int = 2 29 ) 30 31 // TODO: error reporting detail 32 33 /* 34 * Internal ELF representation 35 */ 36 37 // A FileHeader represents an ELF file header. 38 type FileHeader struct { 39 Class Class 40 Data Data 41 Version Version 42 OSABI OSABI 43 ABIVersion uint8 44 ByteOrder binary.ByteOrder 45 Type Type 46 Machine Machine 47 Entry uint64 48 } 49 50 // A File represents an open ELF file. 51 type File struct { 52 FileHeader 53 Sections []*Section 54 Progs []*Prog 55 closer io.Closer 56 gnuNeed []verneed 57 gnuVersym []byte 58 } 59 60 // A SectionHeader represents a single ELF section header. 61 type SectionHeader struct { 62 Name string 63 Type SectionType 64 Flags SectionFlag 65 Addr uint64 66 Offset uint64 67 Size uint64 68 Link uint32 69 Info uint32 70 Addralign uint64 71 Entsize uint64 72 73 // FileSize is the size of this section in the file in bytes. 74 // If a section is compressed, FileSize is the size of the 75 // compressed data, while Size (above) is the size of the 76 // uncompressed data. 77 FileSize uint64 78 } 79 80 // A Section represents a single section in an ELF file. 81 type Section struct { 82 SectionHeader 83 84 // Embed ReaderAt for ReadAt method. 85 // Do not embed SectionReader directly 86 // to avoid having Read and Seek. 87 // If a client wants Read and Seek it must use 88 // Open() to avoid fighting over the seek offset 89 // with other clients. 90 // 91 // ReaderAt may be nil if the section is not easily available 92 // in a random-access form. For example, a compressed section 93 // may have a nil ReaderAt. 94 io.ReaderAt 95 sr *io.SectionReader 96 97 compressionType CompressionType 98 compressionOffset int64 99 } 100 101 // Data reads and returns the contents of the ELF section. 102 // Even if the section is stored compressed in the ELF file, 103 // Data returns uncompressed data. 104 func (s *Section) Data() ([]byte, error) { 105 dat := make([]byte, s.Size) 106 n, err := io.ReadFull(s.Open(), dat) 107 return dat[0:n], err 108 } 109 110 // stringTable reads and returns the string table given by the 111 // specified link value. 112 func (f *File) stringTable(link uint32) ([]byte, error) { 113 if link <= 0 || link >= uint32(len(f.Sections)) { 114 return nil, errors.New("section has invalid string table link") 115 } 116 return f.Sections[link].Data() 117 } 118 119 // Open returns a new ReadSeeker reading the ELF section. 120 // Even if the section is stored compressed in the ELF file, 121 // the ReadSeeker reads uncompressed data. 122 func (s *Section) Open() io.ReadSeeker { 123 if s.Flags&SHF_COMPRESSED == 0 { 124 return io.NewSectionReader(s.sr, 0, 1<<63-1) 125 } 126 if s.compressionType == COMPRESS_ZLIB { 127 return &readSeekerFromReader{ 128 reset: func() (io.Reader, error) { 129 fr := io.NewSectionReader(s.sr, s.compressionOffset, int64(s.FileSize)-s.compressionOffset) 130 return zlib.NewReader(fr) 131 }, 132 size: int64(s.Size), 133 } 134 } 135 err := &FormatError{int64(s.Offset), "unknown compression type", s.compressionType} 136 return errorReader{err} 137 } 138 139 // A ProgHeader represents a single ELF program header. 140 type ProgHeader struct { 141 Type ProgType 142 Flags ProgFlag 143 Off uint64 144 Vaddr uint64 145 Paddr uint64 146 Filesz uint64 147 Memsz uint64 148 Align uint64 149 } 150 151 // A Prog represents a single ELF program header in an ELF binary. 152 type Prog struct { 153 ProgHeader 154 155 // Embed ReaderAt for ReadAt method. 156 // Do not embed SectionReader directly 157 // to avoid having Read and Seek. 158 // If a client wants Read and Seek it must use 159 // Open() to avoid fighting over the seek offset 160 // with other clients. 161 io.ReaderAt 162 sr *io.SectionReader 163 } 164 165 // Open returns a new ReadSeeker reading the ELF program body. 166 func (p *Prog) Open() io.ReadSeeker { return io.NewSectionReader(p.sr, 0, 1<<63-1) } 167 168 // A Symbol represents an entry in an ELF symbol table section. 169 type Symbol struct { 170 Name string 171 Info, Other byte 172 Section SectionIndex 173 Value, Size uint64 174 175 // Version and Library are present only for the dynamic symbol 176 // table. 177 Version string 178 Library string 179 } 180 181 /* 182 * ELF reader 183 */ 184 185 type FormatError struct { 186 off int64 187 msg string 188 val interface{} 189 } 190 191 func (e *FormatError) Error() string { 192 msg := e.msg 193 if e.val != nil { 194 msg += fmt.Sprintf(" '%v' ", e.val) 195 } 196 msg += fmt.Sprintf("in record at byte %#x", e.off) 197 return msg 198 } 199 200 // Open opens the named file using os.Open and prepares it for use as an ELF binary. 201 func Open(name string) (*File, error) { 202 f, err := os.Open(name) 203 if err != nil { 204 return nil, err 205 } 206 ff, err := NewFile(f) 207 if err != nil { 208 f.Close() 209 return nil, err 210 } 211 ff.closer = f 212 return ff, nil 213 } 214 215 // Close closes the File. 216 // If the File was created using NewFile directly instead of Open, 217 // Close has no effect. 218 func (f *File) Close() error { 219 var err error 220 if f.closer != nil { 221 err = f.closer.Close() 222 f.closer = nil 223 } 224 return err 225 } 226 227 // SectionByType returns the first section in f with the 228 // given type, or nil if there is no such section. 229 func (f *File) SectionByType(typ SectionType) *Section { 230 for _, s := range f.Sections { 231 if s.Type == typ { 232 return s 233 } 234 } 235 return nil 236 } 237 238 // NewFile creates a new File for accessing an ELF binary in an underlying reader. 239 // The ELF binary is expected to start at position 0 in the ReaderAt. 240 func NewFile(r io.ReaderAt) (*File, error) { 241 sr := io.NewSectionReader(r, 0, 1<<63-1) 242 // Read and decode ELF identifier 243 var ident [16]uint8 244 if _, err := r.ReadAt(ident[0:], 0); err != nil { 245 return nil, err 246 } 247 if ident[0] != '\x7f' || ident[1] != 'E' || ident[2] != 'L' || ident[3] != 'F' { 248 return nil, &FormatError{0, "bad magic number", ident[0:4]} 249 } 250 251 f := new(File) 252 f.Class = Class(ident[EI_CLASS]) 253 switch f.Class { 254 case ELFCLASS32: 255 case ELFCLASS64: 256 // ok 257 default: 258 return nil, &FormatError{0, "unknown ELF class", f.Class} 259 } 260 261 f.Data = Data(ident[EI_DATA]) 262 switch f.Data { 263 case ELFDATA2LSB: 264 f.ByteOrder = binary.LittleEndian 265 case ELFDATA2MSB: 266 f.ByteOrder = binary.BigEndian 267 default: 268 return nil, &FormatError{0, "unknown ELF data encoding", f.Data} 269 } 270 271 f.Version = Version(ident[EI_VERSION]) 272 if f.Version != EV_CURRENT { 273 return nil, &FormatError{0, "unknown ELF version", f.Version} 274 } 275 276 f.OSABI = OSABI(ident[EI_OSABI]) 277 f.ABIVersion = ident[EI_ABIVERSION] 278 279 // Read ELF file header 280 var phoff int64 281 var phentsize, phnum int 282 var shoff int64 283 var shentsize, shnum, shstrndx int 284 switch f.Class { 285 case ELFCLASS32: 286 hdr := new(Header32) 287 sr.Seek(0, seekStart) 288 if err := binary.Read(sr, f.ByteOrder, hdr); err != nil { 289 return nil, err 290 } 291 f.Type = Type(hdr.Type) 292 f.Machine = Machine(hdr.Machine) 293 f.Entry = uint64(hdr.Entry) 294 if v := Version(hdr.Version); v != f.Version { 295 return nil, &FormatError{0, "mismatched ELF version", v} 296 } 297 phoff = int64(hdr.Phoff) 298 phentsize = int(hdr.Phentsize) 299 phnum = int(hdr.Phnum) 300 shoff = int64(hdr.Shoff) 301 shentsize = int(hdr.Shentsize) 302 shnum = int(hdr.Shnum) 303 shstrndx = int(hdr.Shstrndx) 304 case ELFCLASS64: 305 hdr := new(Header64) 306 sr.Seek(0, seekStart) 307 if err := binary.Read(sr, f.ByteOrder, hdr); err != nil { 308 return nil, err 309 } 310 f.Type = Type(hdr.Type) 311 f.Machine = Machine(hdr.Machine) 312 f.Entry = hdr.Entry 313 if v := Version(hdr.Version); v != f.Version { 314 return nil, &FormatError{0, "mismatched ELF version", v} 315 } 316 phoff = int64(hdr.Phoff) 317 phentsize = int(hdr.Phentsize) 318 phnum = int(hdr.Phnum) 319 shoff = int64(hdr.Shoff) 320 shentsize = int(hdr.Shentsize) 321 shnum = int(hdr.Shnum) 322 shstrndx = int(hdr.Shstrndx) 323 } 324 325 if shoff == 0 && shnum != 0 { 326 return nil, &FormatError{0, "invalid ELF shnum for shoff=0", shnum} 327 } 328 329 if shnum > 0 && shstrndx >= shnum { 330 return nil, &FormatError{0, "invalid ELF shstrndx", shstrndx} 331 } 332 333 // Read program headers 334 f.Progs = make([]*Prog, phnum) 335 for i := 0; i < phnum; i++ { 336 off := phoff + int64(i)*int64(phentsize) 337 sr.Seek(off, seekStart) 338 p := new(Prog) 339 switch f.Class { 340 case ELFCLASS32: 341 ph := new(Prog32) 342 if err := binary.Read(sr, f.ByteOrder, ph); err != nil { 343 return nil, err 344 } 345 p.ProgHeader = ProgHeader{ 346 Type: ProgType(ph.Type), 347 Flags: ProgFlag(ph.Flags), 348 Off: uint64(ph.Off), 349 Vaddr: uint64(ph.Vaddr), 350 Paddr: uint64(ph.Paddr), 351 Filesz: uint64(ph.Filesz), 352 Memsz: uint64(ph.Memsz), 353 Align: uint64(ph.Align), 354 } 355 case ELFCLASS64: 356 ph := new(Prog64) 357 if err := binary.Read(sr, f.ByteOrder, ph); err != nil { 358 return nil, err 359 } 360 p.ProgHeader = ProgHeader{ 361 Type: ProgType(ph.Type), 362 Flags: ProgFlag(ph.Flags), 363 Off: ph.Off, 364 Vaddr: ph.Vaddr, 365 Paddr: ph.Paddr, 366 Filesz: ph.Filesz, 367 Memsz: ph.Memsz, 368 Align: ph.Align, 369 } 370 } 371 p.sr = io.NewSectionReader(r, int64(p.Off), int64(p.Filesz)) 372 p.ReaderAt = p.sr 373 f.Progs[i] = p 374 } 375 376 // Read section headers 377 f.Sections = make([]*Section, shnum) 378 names := make([]uint32, shnum) 379 for i := 0; i < shnum; i++ { 380 off := shoff + int64(i)*int64(shentsize) 381 sr.Seek(off, seekStart) 382 s := new(Section) 383 switch f.Class { 384 case ELFCLASS32: 385 sh := new(Section32) 386 if err := binary.Read(sr, f.ByteOrder, sh); err != nil { 387 return nil, err 388 } 389 names[i] = sh.Name 390 s.SectionHeader = SectionHeader{ 391 Type: SectionType(sh.Type), 392 Flags: SectionFlag(sh.Flags), 393 Addr: uint64(sh.Addr), 394 Offset: uint64(sh.Off), 395 FileSize: uint64(sh.Size), 396 Link: sh.Link, 397 Info: sh.Info, 398 Addralign: uint64(sh.Addralign), 399 Entsize: uint64(sh.Entsize), 400 } 401 case ELFCLASS64: 402 sh := new(Section64) 403 if err := binary.Read(sr, f.ByteOrder, sh); err != nil { 404 return nil, err 405 } 406 names[i] = sh.Name 407 s.SectionHeader = SectionHeader{ 408 Type: SectionType(sh.Type), 409 Flags: SectionFlag(sh.Flags), 410 Offset: sh.Off, 411 FileSize: sh.Size, 412 Addr: sh.Addr, 413 Link: sh.Link, 414 Info: sh.Info, 415 Addralign: sh.Addralign, 416 Entsize: sh.Entsize, 417 } 418 } 419 s.sr = io.NewSectionReader(r, int64(s.Offset), int64(s.FileSize)) 420 421 if s.Flags&SHF_COMPRESSED == 0 { 422 s.ReaderAt = s.sr 423 s.Size = s.FileSize 424 } else { 425 // Read the compression header. 426 switch f.Class { 427 case ELFCLASS32: 428 ch := new(Chdr32) 429 if err := binary.Read(s.sr, f.ByteOrder, ch); err != nil { 430 return nil, err 431 } 432 s.compressionType = CompressionType(ch.Type) 433 s.Size = uint64(ch.Size) 434 s.Addralign = uint64(ch.Addralign) 435 s.compressionOffset = int64(binary.Size(ch)) 436 case ELFCLASS64: 437 ch := new(Chdr64) 438 if err := binary.Read(s.sr, f.ByteOrder, ch); err != nil { 439 return nil, err 440 } 441 s.compressionType = CompressionType(ch.Type) 442 s.Size = ch.Size 443 s.Addralign = ch.Addralign 444 s.compressionOffset = int64(binary.Size(ch)) 445 } 446 } 447 448 f.Sections[i] = s 449 } 450 451 if len(f.Sections) == 0 { 452 return f, nil 453 } 454 455 // Load section header string table. 456 shstrtab, err := f.Sections[shstrndx].Data() 457 if err != nil { 458 return nil, err 459 } 460 for i, s := range f.Sections { 461 var ok bool 462 s.Name, ok = getString(shstrtab, int(names[i])) 463 if !ok { 464 return nil, &FormatError{shoff + int64(i*shentsize), "bad section name index", names[i]} 465 } 466 } 467 468 return f, nil 469 } 470 471 // getSymbols returns a slice of Symbols from parsing the symbol table 472 // with the given type, along with the associated string table. 473 func (f *File) getSymbols(typ SectionType) ([]Symbol, []byte, error) { 474 switch f.Class { 475 case ELFCLASS64: 476 return f.getSymbols64(typ) 477 478 case ELFCLASS32: 479 return f.getSymbols32(typ) 480 } 481 482 return nil, nil, errors.New("not implemented") 483 } 484 485 // ErrNoSymbols is returned by File.Symbols and File.DynamicSymbols 486 // if there is no such section in the File. 487 var ErrNoSymbols = errors.New("no symbol section") 488 489 func (f *File) getSymbols32(typ SectionType) ([]Symbol, []byte, error) { 490 symtabSection := f.SectionByType(typ) 491 if symtabSection == nil { 492 return nil, nil, ErrNoSymbols 493 } 494 495 data, err := symtabSection.Data() 496 if err != nil { 497 return nil, nil, errors.New("cannot load symbol section") 498 } 499 symtab := bytes.NewReader(data) 500 if symtab.Len()%Sym32Size != 0 { 501 return nil, nil, errors.New("length of symbol section is not a multiple of SymSize") 502 } 503 504 strdata, err := f.stringTable(symtabSection.Link) 505 if err != nil { 506 return nil, nil, errors.New("cannot load string table section") 507 } 508 509 // The first entry is all zeros. 510 var skip [Sym32Size]byte 511 symtab.Read(skip[:]) 512 513 symbols := make([]Symbol, symtab.Len()/Sym32Size) 514 515 i := 0 516 var sym Sym32 517 for symtab.Len() > 0 { 518 binary.Read(symtab, f.ByteOrder, &sym) 519 str, _ := getString(strdata, int(sym.Name)) 520 symbols[i].Name = str 521 symbols[i].Info = sym.Info 522 symbols[i].Other = sym.Other 523 symbols[i].Section = SectionIndex(sym.Shndx) 524 symbols[i].Value = uint64(sym.Value) 525 symbols[i].Size = uint64(sym.Size) 526 i++ 527 } 528 529 return symbols, strdata, nil 530 } 531 532 func (f *File) getSymbols64(typ SectionType) ([]Symbol, []byte, error) { 533 symtabSection := f.SectionByType(typ) 534 if symtabSection == nil { 535 return nil, nil, ErrNoSymbols 536 } 537 538 data, err := symtabSection.Data() 539 if err != nil { 540 return nil, nil, errors.New("cannot load symbol section") 541 } 542 symtab := bytes.NewReader(data) 543 if symtab.Len()%Sym64Size != 0 { 544 return nil, nil, errors.New("length of symbol section is not a multiple of Sym64Size") 545 } 546 547 strdata, err := f.stringTable(symtabSection.Link) 548 if err != nil { 549 return nil, nil, errors.New("cannot load string table section") 550 } 551 552 // The first entry is all zeros. 553 var skip [Sym64Size]byte 554 symtab.Read(skip[:]) 555 556 symbols := make([]Symbol, symtab.Len()/Sym64Size) 557 558 i := 0 559 var sym Sym64 560 for symtab.Len() > 0 { 561 binary.Read(symtab, f.ByteOrder, &sym) 562 str, _ := getString(strdata, int(sym.Name)) 563 symbols[i].Name = str 564 symbols[i].Info = sym.Info 565 symbols[i].Other = sym.Other 566 symbols[i].Section = SectionIndex(sym.Shndx) 567 symbols[i].Value = sym.Value 568 symbols[i].Size = sym.Size 569 i++ 570 } 571 572 return symbols, strdata, nil 573 } 574 575 // getString extracts a string from an ELF string table. 576 func getString(section []byte, start int) (string, bool) { 577 if start < 0 || start >= len(section) { 578 return "", false 579 } 580 581 for end := start; end < len(section); end++ { 582 if section[end] == 0 { 583 return string(section[start:end]), true 584 } 585 } 586 return "", false 587 } 588 589 // Section returns a section with the given name, or nil if no such 590 // section exists. 591 func (f *File) Section(name string) *Section { 592 for _, s := range f.Sections { 593 if s.Name == name { 594 return s 595 } 596 } 597 return nil 598 } 599 600 // applyRelocations applies relocations to dst. rels is a relocations section 601 // in REL or RELA format. 602 func (f *File) applyRelocations(dst []byte, rels []byte) error { 603 switch { 604 case f.Class == ELFCLASS64 && f.Machine == EM_X86_64: 605 return f.applyRelocationsAMD64(dst, rels) 606 case f.Class == ELFCLASS32 && f.Machine == EM_386: 607 return f.applyRelocations386(dst, rels) 608 case f.Class == ELFCLASS32 && f.Machine == EM_ARM: 609 return f.applyRelocationsARM(dst, rels) 610 case f.Class == ELFCLASS64 && f.Machine == EM_AARCH64: 611 return f.applyRelocationsARM64(dst, rels) 612 case f.Class == ELFCLASS32 && f.Machine == EM_PPC: 613 return f.applyRelocationsPPC(dst, rels) 614 case f.Class == ELFCLASS64 && f.Machine == EM_PPC64: 615 return f.applyRelocationsPPC64(dst, rels) 616 case f.Class == ELFCLASS32 && f.Machine == EM_MIPS: 617 return f.applyRelocationsMIPS(dst, rels) 618 case f.Class == ELFCLASS64 && f.Machine == EM_MIPS: 619 return f.applyRelocationsMIPS64(dst, rels) 620 case f.Class == ELFCLASS64 && f.Machine == EM_RISCV: 621 return f.applyRelocationsRISCV64(dst, rels) 622 case f.Class == ELFCLASS64 && f.Machine == EM_S390: 623 return f.applyRelocationss390x(dst, rels) 624 case f.Class == ELFCLASS64 && f.Machine == EM_SPARCV9: 625 return f.applyRelocationsSPARC64(dst, rels) 626 default: 627 return errors.New("applyRelocations: not implemented") 628 } 629 } 630 631 // relocSymbolTargetOK decides whether we should try to apply a 632 // relocation to a DWARF data section, given a pointer to the symbol 633 // targeted by the relocation. Most relocations in DWARF data tend to 634 // be section-relative, but some target non-section symbols (for 635 // example, low_PC attrs on subprogram or compilation unit DIEs that 636 // target function symbols), and we need to include these as well. 637 // Return value is a pair (X,Y) where X is a boolean indicating 638 // whether the relocation is needed, and Y is the symbol value in the 639 // case of a non-section relocation that needs to be applied. 640 func relocSymbolTargetOK(sym *Symbol) (bool, uint64) { 641 if ST_TYPE(sym.Info) == STT_SECTION { 642 return true, 0 643 } 644 if sym.Section != SHN_UNDEF && sym.Section < SHN_LORESERVE { 645 return true, sym.Value 646 } 647 return false, 0 648 } 649 650 func (f *File) applyRelocationsAMD64(dst []byte, rels []byte) error { 651 // 24 is the size of Rela64. 652 if len(rels)%24 != 0 { 653 return errors.New("length of relocation section is not a multiple of 24") 654 } 655 656 symbols, _, err := f.getSymbols(SHT_SYMTAB) 657 if err != nil { 658 return err 659 } 660 661 b := bytes.NewReader(rels) 662 var rela Rela64 663 664 for b.Len() > 0 { 665 binary.Read(b, f.ByteOrder, &rela) 666 symNo := rela.Info >> 32 667 t := R_X86_64(rela.Info & 0xffff) 668 669 if symNo == 0 || symNo > uint64(len(symbols)) { 670 continue 671 } 672 sym := &symbols[symNo-1] 673 needed, val := relocSymbolTargetOK(sym) 674 if !needed { 675 continue 676 } 677 678 // There are relocations, so this must be a normal 679 // object file. The code below handles only basic relocations 680 // of the form S + A (symbol plus addend). 681 682 switch t { 683 case R_X86_64_64: 684 if rela.Off+8 >= uint64(len(dst)) || rela.Addend < 0 { 685 continue 686 } 687 val64 := val + uint64(rela.Addend) 688 f.ByteOrder.PutUint64(dst[rela.Off:rela.Off+8], val64) 689 case R_X86_64_32: 690 if rela.Off+4 >= uint64(len(dst)) || rela.Addend < 0 { 691 continue 692 } 693 val32 := uint32(val) + uint32(rela.Addend) 694 f.ByteOrder.PutUint32(dst[rela.Off:rela.Off+4], val32) 695 } 696 } 697 698 return nil 699 } 700 701 func (f *File) applyRelocations386(dst []byte, rels []byte) error { 702 // 8 is the size of Rel32. 703 if len(rels)%8 != 0 { 704 return errors.New("length of relocation section is not a multiple of 8") 705 } 706 707 symbols, _, err := f.getSymbols(SHT_SYMTAB) 708 if err != nil { 709 return err 710 } 711 712 b := bytes.NewReader(rels) 713 var rel Rel32 714 715 for b.Len() > 0 { 716 binary.Read(b, f.ByteOrder, &rel) 717 symNo := rel.Info >> 8 718 t := R_386(rel.Info & 0xff) 719 720 if symNo == 0 || symNo > uint32(len(symbols)) { 721 continue 722 } 723 sym := &symbols[symNo-1] 724 725 if t == R_386_32 { 726 if rel.Off+4 >= uint32(len(dst)) { 727 continue 728 } 729 val := f.ByteOrder.Uint32(dst[rel.Off : rel.Off+4]) 730 val += uint32(sym.Value) 731 f.ByteOrder.PutUint32(dst[rel.Off:rel.Off+4], val) 732 } 733 } 734 735 return nil 736 } 737 738 func (f *File) applyRelocationsARM(dst []byte, rels []byte) error { 739 // 8 is the size of Rel32. 740 if len(rels)%8 != 0 { 741 return errors.New("length of relocation section is not a multiple of 8") 742 } 743 744 symbols, _, err := f.getSymbols(SHT_SYMTAB) 745 if err != nil { 746 return err 747 } 748 749 b := bytes.NewReader(rels) 750 var rel Rel32 751 752 for b.Len() > 0 { 753 binary.Read(b, f.ByteOrder, &rel) 754 symNo := rel.Info >> 8 755 t := R_ARM(rel.Info & 0xff) 756 757 if symNo == 0 || symNo > uint32(len(symbols)) { 758 continue 759 } 760 sym := &symbols[symNo-1] 761 762 switch t { 763 case R_ARM_ABS32: 764 if rel.Off+4 >= uint32(len(dst)) { 765 continue 766 } 767 val := f.ByteOrder.Uint32(dst[rel.Off : rel.Off+4]) 768 val += uint32(sym.Value) 769 f.ByteOrder.PutUint32(dst[rel.Off:rel.Off+4], val) 770 } 771 } 772 773 return nil 774 } 775 776 func (f *File) applyRelocationsARM64(dst []byte, rels []byte) error { 777 // 24 is the size of Rela64. 778 if len(rels)%24 != 0 { 779 return errors.New("length of relocation section is not a multiple of 24") 780 } 781 782 symbols, _, err := f.getSymbols(SHT_SYMTAB) 783 if err != nil { 784 return err 785 } 786 787 b := bytes.NewReader(rels) 788 var rela Rela64 789 790 for b.Len() > 0 { 791 binary.Read(b, f.ByteOrder, &rela) 792 symNo := rela.Info >> 32 793 t := R_AARCH64(rela.Info & 0xffff) 794 795 if symNo == 0 || symNo > uint64(len(symbols)) { 796 continue 797 } 798 sym := &symbols[symNo-1] 799 needed, val := relocSymbolTargetOK(sym) 800 if !needed { 801 continue 802 } 803 804 // There are relocations, so this must be a normal 805 // object file. The code below handles only basic relocations 806 // of the form S + A (symbol plus addend). 807 808 switch t { 809 case R_AARCH64_ABS64: 810 if rela.Off+8 >= uint64(len(dst)) || rela.Addend < 0 { 811 continue 812 } 813 val64 := uint64(val) + uint64(rela.Addend) 814 f.ByteOrder.PutUint64(dst[rela.Off:rela.Off+8], val64) 815 case R_AARCH64_ABS32: 816 if rela.Off+4 >= uint64(len(dst)) || rela.Addend < 0 { 817 continue 818 } 819 val32 := uint32(val) + uint32(rela.Addend) 820 f.ByteOrder.PutUint32(dst[rela.Off:rela.Off+4], val32) 821 } 822 } 823 824 return nil 825 } 826 827 func (f *File) applyRelocationsPPC(dst []byte, rels []byte) error { 828 // 12 is the size of Rela32. 829 if len(rels)%12 != 0 { 830 return errors.New("length of relocation section is not a multiple of 12") 831 } 832 833 symbols, _, err := f.getSymbols(SHT_SYMTAB) 834 if err != nil { 835 return err 836 } 837 838 b := bytes.NewReader(rels) 839 var rela Rela32 840 841 for b.Len() > 0 { 842 binary.Read(b, f.ByteOrder, &rela) 843 symNo := rela.Info >> 8 844 t := R_PPC(rela.Info & 0xff) 845 846 if symNo == 0 || symNo > uint32(len(symbols)) { 847 continue 848 } 849 sym := &symbols[symNo-1] 850 needed, val := relocSymbolTargetOK(sym) 851 if !needed { 852 continue 853 } 854 855 switch t { 856 case R_PPC_ADDR32: 857 if rela.Off+4 >= uint32(len(dst)) || rela.Addend < 0 { 858 continue 859 } 860 val32 := uint32(val) + uint32(rela.Addend) 861 f.ByteOrder.PutUint32(dst[rela.Off:rela.Off+4], val32) 862 } 863 } 864 865 return nil 866 } 867 868 func (f *File) applyRelocationsPPC64(dst []byte, rels []byte) error { 869 // 24 is the size of Rela64. 870 if len(rels)%24 != 0 { 871 return errors.New("length of relocation section is not a multiple of 24") 872 } 873 874 symbols, _, err := f.getSymbols(SHT_SYMTAB) 875 if err != nil { 876 return err 877 } 878 879 b := bytes.NewReader(rels) 880 var rela Rela64 881 882 for b.Len() > 0 { 883 binary.Read(b, f.ByteOrder, &rela) 884 symNo := rela.Info >> 32 885 t := R_PPC64(rela.Info & 0xffff) 886 887 if symNo == 0 || symNo > uint64(len(symbols)) { 888 continue 889 } 890 sym := &symbols[symNo-1] 891 needed, val := relocSymbolTargetOK(sym) 892 if !needed { 893 continue 894 } 895 896 switch t { 897 case R_PPC64_ADDR64: 898 if rela.Off+8 >= uint64(len(dst)) || rela.Addend < 0 { 899 continue 900 } 901 val64 := val + uint64(rela.Addend) 902 f.ByteOrder.PutUint64(dst[rela.Off:rela.Off+8], val64) 903 case R_PPC64_ADDR32: 904 if rela.Off+4 >= uint64(len(dst)) || rela.Addend < 0 { 905 continue 906 } 907 val32 := uint32(val) + uint32(rela.Addend) 908 f.ByteOrder.PutUint32(dst[rela.Off:rela.Off+4], val32) 909 } 910 } 911 912 return nil 913 } 914 915 func (f *File) applyRelocationsMIPS(dst []byte, rels []byte) error { 916 // 8 is the size of Rel32. 917 if len(rels)%8 != 0 { 918 return errors.New("length of relocation section is not a multiple of 8") 919 } 920 921 symbols, _, err := f.getSymbols(SHT_SYMTAB) 922 if err != nil { 923 return err 924 } 925 926 b := bytes.NewReader(rels) 927 var rel Rel32 928 929 for b.Len() > 0 { 930 binary.Read(b, f.ByteOrder, &rel) 931 symNo := rel.Info >> 8 932 t := R_MIPS(rel.Info & 0xff) 933 934 if symNo == 0 || symNo > uint32(len(symbols)) { 935 continue 936 } 937 sym := &symbols[symNo-1] 938 939 switch t { 940 case R_MIPS_32: 941 if rel.Off+4 >= uint32(len(dst)) { 942 continue 943 } 944 val := f.ByteOrder.Uint32(dst[rel.Off : rel.Off+4]) 945 val += uint32(sym.Value) 946 f.ByteOrder.PutUint32(dst[rel.Off:rel.Off+4], val) 947 } 948 } 949 950 return nil 951 } 952 953 func (f *File) applyRelocationsMIPS64(dst []byte, rels []byte) error { 954 // 24 is the size of Rela64. 955 if len(rels)%24 != 0 { 956 return errors.New("length of relocation section is not a multiple of 24") 957 } 958 959 symbols, _, err := f.getSymbols(SHT_SYMTAB) 960 if err != nil { 961 return err 962 } 963 964 b := bytes.NewReader(rels) 965 var rela Rela64 966 967 for b.Len() > 0 { 968 binary.Read(b, f.ByteOrder, &rela) 969 var symNo uint64 970 var t R_MIPS 971 if f.ByteOrder == binary.BigEndian { 972 symNo = rela.Info >> 32 973 t = R_MIPS(rela.Info & 0xff) 974 } else { 975 symNo = rela.Info & 0xffffffff 976 t = R_MIPS(rela.Info >> 56) 977 } 978 979 if symNo == 0 || symNo > uint64(len(symbols)) { 980 continue 981 } 982 sym := &symbols[symNo-1] 983 needed, val := relocSymbolTargetOK(sym) 984 if !needed { 985 continue 986 } 987 988 switch t { 989 case R_MIPS_64: 990 if rela.Off+8 >= uint64(len(dst)) || rela.Addend < 0 { 991 continue 992 } 993 val64 := val + uint64(rela.Addend) 994 f.ByteOrder.PutUint64(dst[rela.Off:rela.Off+8], val64) 995 case R_MIPS_32: 996 if rela.Off+4 >= uint64(len(dst)) || rela.Addend < 0 { 997 continue 998 } 999 val32 := uint32(val) + uint32(rela.Addend) 1000 f.ByteOrder.PutUint32(dst[rela.Off:rela.Off+4], val32) 1001 } 1002 } 1003 1004 return nil 1005 } 1006 1007 func (f *File) applyRelocationsRISCV64(dst []byte, rels []byte) error { 1008 // 24 is the size of Rela64. 1009 if len(rels)%24 != 0 { 1010 return errors.New("length of relocation section is not a multiple of 24") 1011 } 1012 1013 symbols, _, err := f.getSymbols(SHT_SYMTAB) 1014 if err != nil { 1015 return err 1016 } 1017 1018 b := bytes.NewReader(rels) 1019 var rela Rela64 1020 1021 for b.Len() > 0 { 1022 binary.Read(b, f.ByteOrder, &rela) 1023 symNo := rela.Info >> 32 1024 t := R_RISCV(rela.Info & 0xffff) 1025 1026 if symNo == 0 || symNo > uint64(len(symbols)) { 1027 continue 1028 } 1029 sym := &symbols[symNo-1] 1030 needed, val := relocSymbolTargetOK(sym) 1031 if !needed { 1032 continue 1033 } 1034 1035 switch t { 1036 case R_RISCV_64: 1037 if rela.Off+8 >= uint64(len(dst)) || rela.Addend < 0 { 1038 continue 1039 } 1040 val64 := val + uint64(rela.Addend) 1041 f.ByteOrder.PutUint64(dst[rela.Off:rela.Off+8], val64) 1042 case R_RISCV_32: 1043 if rela.Off+4 >= uint64(len(dst)) || rela.Addend < 0 { 1044 continue 1045 } 1046 val32 := uint32(val) + uint32(rela.Addend) 1047 f.ByteOrder.PutUint32(dst[rela.Off:rela.Off+4], val32) 1048 } 1049 } 1050 1051 return nil 1052 } 1053 1054 func (f *File) applyRelocationss390x(dst []byte, rels []byte) error { 1055 // 24 is the size of Rela64. 1056 if len(rels)%24 != 0 { 1057 return errors.New("length of relocation section is not a multiple of 24") 1058 } 1059 1060 symbols, _, err := f.getSymbols(SHT_SYMTAB) 1061 if err != nil { 1062 return err 1063 } 1064 1065 b := bytes.NewReader(rels) 1066 var rela Rela64 1067 1068 for b.Len() > 0 { 1069 binary.Read(b, f.ByteOrder, &rela) 1070 symNo := rela.Info >> 32 1071 t := R_390(rela.Info & 0xffff) 1072 1073 if symNo == 0 || symNo > uint64(len(symbols)) { 1074 continue 1075 } 1076 sym := &symbols[symNo-1] 1077 needed, val := relocSymbolTargetOK(sym) 1078 if !needed { 1079 continue 1080 } 1081 1082 switch t { 1083 case R_390_64: 1084 if rela.Off+8 >= uint64(len(dst)) || rela.Addend < 0 { 1085 continue 1086 } 1087 val64 := val + uint64(rela.Addend) 1088 f.ByteOrder.PutUint64(dst[rela.Off:rela.Off+8], val64) 1089 case R_390_32: 1090 if rela.Off+4 >= uint64(len(dst)) || rela.Addend < 0 { 1091 continue 1092 } 1093 val32 := uint32(val) + uint32(rela.Addend) 1094 f.ByteOrder.PutUint32(dst[rela.Off:rela.Off+4], val32) 1095 } 1096 } 1097 1098 return nil 1099 } 1100 1101 func (f *File) applyRelocationsSPARC64(dst []byte, rels []byte) error { 1102 // 24 is the size of Rela64. 1103 if len(rels)%24 != 0 { 1104 return errors.New("length of relocation section is not a multiple of 24") 1105 } 1106 1107 symbols, _, err := f.getSymbols(SHT_SYMTAB) 1108 if err != nil { 1109 return err 1110 } 1111 1112 b := bytes.NewReader(rels) 1113 var rela Rela64 1114 1115 for b.Len() > 0 { 1116 binary.Read(b, f.ByteOrder, &rela) 1117 symNo := rela.Info >> 32 1118 t := R_SPARC(rela.Info & 0xff) 1119 1120 if symNo == 0 || symNo > uint64(len(symbols)) { 1121 continue 1122 } 1123 sym := &symbols[symNo-1] 1124 needed, val := relocSymbolTargetOK(sym) 1125 if !needed { 1126 continue 1127 } 1128 1129 switch t { 1130 case R_SPARC_64, R_SPARC_UA64: 1131 if rela.Off+8 >= uint64(len(dst)) || rela.Addend < 0 { 1132 continue 1133 } 1134 val64 := val + uint64(rela.Addend) 1135 f.ByteOrder.PutUint64(dst[rela.Off:rela.Off+8], val64) 1136 case R_SPARC_32, R_SPARC_UA32: 1137 if rela.Off+4 >= uint64(len(dst)) || rela.Addend < 0 { 1138 continue 1139 } 1140 val32 := uint32(val) + uint32(rela.Addend) 1141 f.ByteOrder.PutUint32(dst[rela.Off:rela.Off+4], val32) 1142 } 1143 } 1144 1145 return nil 1146 } 1147 1148 func (f *File) DWARF() (*dwarf.Data, error) { 1149 dwarfSuffix := func(s *Section) string { 1150 switch { 1151 case strings.HasPrefix(s.Name, ".debug_"): 1152 return s.Name[7:] 1153 case strings.HasPrefix(s.Name, ".zdebug_"): 1154 return s.Name[8:] 1155 default: 1156 return "" 1157 } 1158 1159 } 1160 // sectionData gets the data for s, checks its size, and 1161 // applies any applicable relations. 1162 sectionData := func(i int, s *Section) ([]byte, error) { 1163 b, err := s.Data() 1164 if err != nil && uint64(len(b)) < s.Size { 1165 return nil, err 1166 } 1167 1168 if len(b) >= 12 && string(b[:4]) == "ZLIB" { 1169 dlen := binary.BigEndian.Uint64(b[4:12]) 1170 dbuf := make([]byte, dlen) 1171 r, err := zlib.NewReader(bytes.NewBuffer(b[12:])) 1172 if err != nil { 1173 return nil, err 1174 } 1175 if _, err := io.ReadFull(r, dbuf); err != nil { 1176 return nil, err 1177 } 1178 if err := r.Close(); err != nil { 1179 return nil, err 1180 } 1181 b = dbuf 1182 } 1183 1184 for _, r := range f.Sections { 1185 if r.Type != SHT_RELA && r.Type != SHT_REL { 1186 continue 1187 } 1188 if int(r.Info) != i { 1189 continue 1190 } 1191 rd, err := r.Data() 1192 if err != nil { 1193 return nil, err 1194 } 1195 err = f.applyRelocations(b, rd) 1196 if err != nil { 1197 return nil, err 1198 } 1199 } 1200 return b, nil 1201 } 1202 1203 // There are many DWARf sections, but these are the ones 1204 // the debug/dwarf package started with. 1205 var dat = map[string][]byte{"abbrev": nil, "info": nil, "str": nil, "line": nil, "ranges": nil} 1206 for i, s := range f.Sections { 1207 suffix := dwarfSuffix(s) 1208 if suffix == "" { 1209 continue 1210 } 1211 if _, ok := dat[suffix]; !ok { 1212 continue 1213 } 1214 b, err := sectionData(i, s) 1215 if err != nil { 1216 return nil, err 1217 } 1218 dat[suffix] = b 1219 } 1220 1221 d, err := dwarf.New(dat["abbrev"], nil, nil, dat["info"], dat["line"], nil, dat["ranges"], dat["str"]) 1222 if err != nil { 1223 return nil, err 1224 } 1225 1226 // Look for DWARF4 .debug_types sections and DWARF5 sections. 1227 for i, s := range f.Sections { 1228 suffix := dwarfSuffix(s) 1229 if suffix == "" { 1230 continue 1231 } 1232 if _, ok := dat[suffix]; ok { 1233 // Already handled. 1234 continue 1235 } 1236 1237 b, err := sectionData(i, s) 1238 if err != nil { 1239 return nil, err 1240 } 1241 1242 if suffix == "types" { 1243 if err := d.AddTypes(fmt.Sprintf("types-%d", i), b); err != nil { 1244 return nil, err 1245 } 1246 } else { 1247 if err := d.AddSection(".debug_"+suffix, b); err != nil { 1248 return nil, err 1249 } 1250 } 1251 } 1252 1253 return d, nil 1254 } 1255 1256 // Symbols returns the symbol table for f. The symbols will be listed in the order 1257 // they appear in f. 1258 // 1259 // For compatibility with Go 1.0, Symbols omits the null symbol at index 0. 1260 // After retrieving the symbols as symtab, an externally supplied index x 1261 // corresponds to symtab[x-1], not symtab[x]. 1262 func (f *File) Symbols() ([]Symbol, error) { 1263 sym, _, err := f.getSymbols(SHT_SYMTAB) 1264 return sym, err 1265 } 1266 1267 // DynamicSymbols returns the dynamic symbol table for f. The symbols 1268 // will be listed in the order they appear in f. 1269 // 1270 // If f has a symbol version table, the returned Symbols will have 1271 // initialized Version and Library fields. 1272 // 1273 // For compatibility with Symbols, DynamicSymbols omits the null symbol at index 0. 1274 // After retrieving the symbols as symtab, an externally supplied index x 1275 // corresponds to symtab[x-1], not symtab[x]. 1276 func (f *File) DynamicSymbols() ([]Symbol, error) { 1277 sym, str, err := f.getSymbols(SHT_DYNSYM) 1278 if err != nil { 1279 return nil, err 1280 } 1281 if f.gnuVersionInit(str) { 1282 for i := range sym { 1283 sym[i].Library, sym[i].Version = f.gnuVersion(i) 1284 } 1285 } 1286 return sym, nil 1287 } 1288 1289 type ImportedSymbol struct { 1290 Name string 1291 Version string 1292 Library string 1293 } 1294 1295 // ImportedSymbols returns the names of all symbols 1296 // referred to by the binary f that are expected to be 1297 // satisfied by other libraries at dynamic load time. 1298 // It does not return weak symbols. 1299 func (f *File) ImportedSymbols() ([]ImportedSymbol, error) { 1300 sym, str, err := f.getSymbols(SHT_DYNSYM) 1301 if err != nil { 1302 return nil, err 1303 } 1304 f.gnuVersionInit(str) 1305 var all []ImportedSymbol 1306 for i, s := range sym { 1307 if ST_BIND(s.Info) == STB_GLOBAL && s.Section == SHN_UNDEF { 1308 all = append(all, ImportedSymbol{Name: s.Name}) 1309 sym := &all[len(all)-1] 1310 sym.Library, sym.Version = f.gnuVersion(i) 1311 } 1312 } 1313 return all, nil 1314 } 1315 1316 type verneed struct { 1317 File string 1318 Name string 1319 } 1320 1321 // gnuVersionInit parses the GNU version tables 1322 // for use by calls to gnuVersion. 1323 func (f *File) gnuVersionInit(str []byte) bool { 1324 if f.gnuNeed != nil { 1325 // Already initialized 1326 return true 1327 } 1328 1329 // Accumulate verneed information. 1330 vn := f.SectionByType(SHT_GNU_VERNEED) 1331 if vn == nil { 1332 return false 1333 } 1334 d, _ := vn.Data() 1335 1336 var need []verneed 1337 i := 0 1338 for { 1339 if i+16 > len(d) { 1340 break 1341 } 1342 vers := f.ByteOrder.Uint16(d[i : i+2]) 1343 if vers != 1 { 1344 break 1345 } 1346 cnt := f.ByteOrder.Uint16(d[i+2 : i+4]) 1347 fileoff := f.ByteOrder.Uint32(d[i+4 : i+8]) 1348 aux := f.ByteOrder.Uint32(d[i+8 : i+12]) 1349 next := f.ByteOrder.Uint32(d[i+12 : i+16]) 1350 file, _ := getString(str, int(fileoff)) 1351 1352 var name string 1353 j := i + int(aux) 1354 for c := 0; c < int(cnt); c++ { 1355 if j+16 > len(d) { 1356 break 1357 } 1358 // hash := f.ByteOrder.Uint32(d[j:j+4]) 1359 // flags := f.ByteOrder.Uint16(d[j+4:j+6]) 1360 other := f.ByteOrder.Uint16(d[j+6 : j+8]) 1361 nameoff := f.ByteOrder.Uint32(d[j+8 : j+12]) 1362 next := f.ByteOrder.Uint32(d[j+12 : j+16]) 1363 name, _ = getString(str, int(nameoff)) 1364 ndx := int(other) 1365 if ndx >= len(need) { 1366 a := make([]verneed, 2*(ndx+1)) 1367 copy(a, need) 1368 need = a 1369 } 1370 1371 need[ndx] = verneed{file, name} 1372 if next == 0 { 1373 break 1374 } 1375 j += int(next) 1376 } 1377 1378 if next == 0 { 1379 break 1380 } 1381 i += int(next) 1382 } 1383 1384 // Versym parallels symbol table, indexing into verneed. 1385 vs := f.SectionByType(SHT_GNU_VERSYM) 1386 if vs == nil { 1387 return false 1388 } 1389 d, _ = vs.Data() 1390 1391 f.gnuNeed = need 1392 f.gnuVersym = d 1393 return true 1394 } 1395 1396 // gnuVersion adds Library and Version information to sym, 1397 // which came from offset i of the symbol table. 1398 func (f *File) gnuVersion(i int) (library string, version string) { 1399 // Each entry is two bytes. 1400 i = (i + 1) * 2 1401 if i >= len(f.gnuVersym) { 1402 return 1403 } 1404 j := int(f.ByteOrder.Uint16(f.gnuVersym[i:])) 1405 if j < 2 || j >= len(f.gnuNeed) { 1406 return 1407 } 1408 n := &f.gnuNeed[j] 1409 return n.File, n.Name 1410 } 1411 1412 // ImportedLibraries returns the names of all libraries 1413 // referred to by the binary f that are expected to be 1414 // linked with the binary at dynamic link time. 1415 func (f *File) ImportedLibraries() ([]string, error) { 1416 return f.DynString(DT_NEEDED) 1417 } 1418 1419 // DynString returns the strings listed for the given tag in the file's dynamic 1420 // section. 1421 // 1422 // The tag must be one that takes string values: DT_NEEDED, DT_SONAME, DT_RPATH, or 1423 // DT_RUNPATH. 1424 func (f *File) DynString(tag DynTag) ([]string, error) { 1425 switch tag { 1426 case DT_NEEDED, DT_SONAME, DT_RPATH, DT_RUNPATH: 1427 default: 1428 return nil, fmt.Errorf("non-string-valued tag %v", tag) 1429 } 1430 ds := f.SectionByType(SHT_DYNAMIC) 1431 if ds == nil { 1432 // not dynamic, so no libraries 1433 return nil, nil 1434 } 1435 d, err := ds.Data() 1436 if err != nil { 1437 return nil, err 1438 } 1439 str, err := f.stringTable(ds.Link) 1440 if err != nil { 1441 return nil, err 1442 } 1443 var all []string 1444 for len(d) > 0 { 1445 var t DynTag 1446 var v uint64 1447 switch f.Class { 1448 case ELFCLASS32: 1449 t = DynTag(f.ByteOrder.Uint32(d[0:4])) 1450 v = uint64(f.ByteOrder.Uint32(d[4:8])) 1451 d = d[8:] 1452 case ELFCLASS64: 1453 t = DynTag(f.ByteOrder.Uint64(d[0:8])) 1454 v = f.ByteOrder.Uint64(d[8:16]) 1455 d = d[16:] 1456 } 1457 if t == tag { 1458 s, ok := getString(str, int(v)) 1459 if ok { 1460 all = append(all, s) 1461 } 1462 } 1463 } 1464 return all, nil 1465 }