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