github.com/gocuntian/go@v0.0.0-20160610041250-fee02d270bf8/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 default: 602 return errors.New("applyRelocations: not implemented") 603 } 604 } 605 606 func (f *File) applyRelocationsAMD64(dst []byte, rels []byte) error { 607 // 24 is the size of Rela64. 608 if len(rels)%24 != 0 { 609 return errors.New("length of relocation section is not a multiple of 24") 610 } 611 612 symbols, _, err := f.getSymbols(SHT_SYMTAB) 613 if err != nil { 614 return err 615 } 616 617 b := bytes.NewReader(rels) 618 var rela Rela64 619 620 for b.Len() > 0 { 621 binary.Read(b, f.ByteOrder, &rela) 622 symNo := rela.Info >> 32 623 t := R_X86_64(rela.Info & 0xffff) 624 625 if symNo == 0 || symNo > uint64(len(symbols)) { 626 continue 627 } 628 sym := &symbols[symNo-1] 629 if SymType(sym.Info&0xf) != STT_SECTION { 630 // We don't handle non-section relocations for now. 631 continue 632 } 633 634 // There are relocations, so this must be a normal 635 // object file, and we only look at section symbols, 636 // so we assume that the symbol value is 0. 637 638 switch t { 639 case R_X86_64_64: 640 if rela.Off+8 >= uint64(len(dst)) || rela.Addend < 0 { 641 continue 642 } 643 f.ByteOrder.PutUint64(dst[rela.Off:rela.Off+8], uint64(rela.Addend)) 644 case R_X86_64_32: 645 if rela.Off+4 >= uint64(len(dst)) || rela.Addend < 0 { 646 continue 647 } 648 f.ByteOrder.PutUint32(dst[rela.Off:rela.Off+4], uint32(rela.Addend)) 649 } 650 } 651 652 return nil 653 } 654 655 func (f *File) applyRelocations386(dst []byte, rels []byte) error { 656 // 8 is the size of Rel32. 657 if len(rels)%8 != 0 { 658 return errors.New("length of relocation section is not a multiple of 8") 659 } 660 661 symbols, _, err := f.getSymbols(SHT_SYMTAB) 662 if err != nil { 663 return err 664 } 665 666 b := bytes.NewReader(rels) 667 var rel Rel32 668 669 for b.Len() > 0 { 670 binary.Read(b, f.ByteOrder, &rel) 671 symNo := rel.Info >> 8 672 t := R_386(rel.Info & 0xff) 673 674 if symNo == 0 || symNo > uint32(len(symbols)) { 675 continue 676 } 677 sym := &symbols[symNo-1] 678 679 if t == R_386_32 { 680 if rel.Off+4 >= uint32(len(dst)) { 681 continue 682 } 683 val := f.ByteOrder.Uint32(dst[rel.Off : rel.Off+4]) 684 val += uint32(sym.Value) 685 f.ByteOrder.PutUint32(dst[rel.Off:rel.Off+4], val) 686 } 687 } 688 689 return nil 690 } 691 692 func (f *File) applyRelocationsARM(dst []byte, rels []byte) error { 693 // 8 is the size of Rel32. 694 if len(rels)%8 != 0 { 695 return errors.New("length of relocation section is not a multiple of 8") 696 } 697 698 symbols, _, err := f.getSymbols(SHT_SYMTAB) 699 if err != nil { 700 return err 701 } 702 703 b := bytes.NewReader(rels) 704 var rel Rel32 705 706 for b.Len() > 0 { 707 binary.Read(b, f.ByteOrder, &rel) 708 symNo := rel.Info >> 8 709 t := R_ARM(rel.Info & 0xff) 710 711 if symNo == 0 || symNo > uint32(len(symbols)) { 712 continue 713 } 714 sym := &symbols[symNo-1] 715 716 switch t { 717 case R_ARM_ABS32: 718 if rel.Off+4 >= uint32(len(dst)) { 719 continue 720 } 721 val := f.ByteOrder.Uint32(dst[rel.Off : rel.Off+4]) 722 val += uint32(sym.Value) 723 f.ByteOrder.PutUint32(dst[rel.Off:rel.Off+4], val) 724 } 725 } 726 727 return nil 728 } 729 730 func (f *File) applyRelocationsARM64(dst []byte, rels []byte) error { 731 // 24 is the size of Rela64. 732 if len(rels)%24 != 0 { 733 return errors.New("length of relocation section is not a multiple of 24") 734 } 735 736 symbols, _, err := f.getSymbols(SHT_SYMTAB) 737 if err != nil { 738 return err 739 } 740 741 b := bytes.NewReader(rels) 742 var rela Rela64 743 744 for b.Len() > 0 { 745 binary.Read(b, f.ByteOrder, &rela) 746 symNo := rela.Info >> 32 747 t := R_AARCH64(rela.Info & 0xffff) 748 749 if symNo == 0 || symNo > uint64(len(symbols)) { 750 continue 751 } 752 sym := &symbols[symNo-1] 753 if SymType(sym.Info&0xf) != STT_SECTION { 754 // We don't handle non-section relocations for now. 755 continue 756 } 757 758 // There are relocations, so this must be a normal 759 // object file, and we only look at section symbols, 760 // so we assume that the symbol value is 0. 761 762 switch t { 763 case R_AARCH64_ABS64: 764 if rela.Off+8 >= uint64(len(dst)) || rela.Addend < 0 { 765 continue 766 } 767 f.ByteOrder.PutUint64(dst[rela.Off:rela.Off+8], uint64(rela.Addend)) 768 case R_AARCH64_ABS32: 769 if rela.Off+4 >= uint64(len(dst)) || rela.Addend < 0 { 770 continue 771 } 772 f.ByteOrder.PutUint32(dst[rela.Off:rela.Off+4], uint32(rela.Addend)) 773 } 774 } 775 776 return nil 777 } 778 779 func (f *File) applyRelocationsPPC(dst []byte, rels []byte) error { 780 // 12 is the size of Rela32. 781 if len(rels)%12 != 0 { 782 return errors.New("length of relocation section is not a multiple of 12") 783 } 784 785 symbols, _, err := f.getSymbols(SHT_SYMTAB) 786 if err != nil { 787 return err 788 } 789 790 b := bytes.NewReader(rels) 791 var rela Rela32 792 793 for b.Len() > 0 { 794 binary.Read(b, f.ByteOrder, &rela) 795 symNo := rela.Info >> 8 796 t := R_PPC(rela.Info & 0xff) 797 798 if symNo == 0 || symNo > uint32(len(symbols)) { 799 continue 800 } 801 sym := &symbols[symNo-1] 802 if SymType(sym.Info&0xf) != STT_SECTION { 803 // We don't handle non-section relocations for now. 804 continue 805 } 806 807 switch t { 808 case R_PPC_ADDR32: 809 if rela.Off+4 >= uint32(len(dst)) || rela.Addend < 0 { 810 continue 811 } 812 f.ByteOrder.PutUint32(dst[rela.Off:rela.Off+4], uint32(rela.Addend)) 813 } 814 } 815 816 return nil 817 } 818 819 func (f *File) applyRelocationsPPC64(dst []byte, rels []byte) error { 820 // 24 is the size of Rela64. 821 if len(rels)%24 != 0 { 822 return errors.New("length of relocation section is not a multiple of 24") 823 } 824 825 symbols, _, err := f.getSymbols(SHT_SYMTAB) 826 if err != nil { 827 return err 828 } 829 830 b := bytes.NewReader(rels) 831 var rela Rela64 832 833 for b.Len() > 0 { 834 binary.Read(b, f.ByteOrder, &rela) 835 symNo := rela.Info >> 32 836 t := R_PPC64(rela.Info & 0xffff) 837 838 if symNo == 0 || symNo > uint64(len(symbols)) { 839 continue 840 } 841 sym := &symbols[symNo-1] 842 if SymType(sym.Info&0xf) != STT_SECTION { 843 // We don't handle non-section relocations for now. 844 continue 845 } 846 847 switch t { 848 case R_PPC64_ADDR64: 849 if rela.Off+8 >= uint64(len(dst)) || rela.Addend < 0 { 850 continue 851 } 852 f.ByteOrder.PutUint64(dst[rela.Off:rela.Off+8], uint64(rela.Addend)) 853 case R_PPC64_ADDR32: 854 if rela.Off+4 >= uint64(len(dst)) || rela.Addend < 0 { 855 continue 856 } 857 f.ByteOrder.PutUint32(dst[rela.Off:rela.Off+4], uint32(rela.Addend)) 858 } 859 } 860 861 return nil 862 } 863 864 func (f *File) applyRelocationsMIPS64(dst []byte, rels []byte) error { 865 // 24 is the size of Rela64. 866 if len(rels)%24 != 0 { 867 return errors.New("length of relocation section is not a multiple of 24") 868 } 869 870 symbols, _, err := f.getSymbols(SHT_SYMTAB) 871 if err != nil { 872 return err 873 } 874 875 b := bytes.NewReader(rels) 876 var rela Rela64 877 878 for b.Len() > 0 { 879 binary.Read(b, f.ByteOrder, &rela) 880 var symNo uint64 881 var t R_MIPS 882 if f.ByteOrder == binary.BigEndian { 883 symNo = rela.Info >> 32 884 t = R_MIPS(rela.Info & 0xff) 885 } else { 886 symNo = rela.Info & 0xffffffff 887 t = R_MIPS(rela.Info >> 56) 888 } 889 890 if symNo == 0 || symNo > uint64(len(symbols)) { 891 continue 892 } 893 sym := &symbols[symNo-1] 894 if SymType(sym.Info&0xf) != STT_SECTION { 895 // We don't handle non-section relocations for now. 896 continue 897 } 898 899 switch t { 900 case R_MIPS_64: 901 if rela.Off+8 >= uint64(len(dst)) || rela.Addend < 0 { 902 continue 903 } 904 f.ByteOrder.PutUint64(dst[rela.Off:rela.Off+8], uint64(rela.Addend)) 905 case R_MIPS_32: 906 if rela.Off+4 >= uint64(len(dst)) || rela.Addend < 0 { 907 continue 908 } 909 f.ByteOrder.PutUint32(dst[rela.Off:rela.Off+4], uint32(rela.Addend)) 910 } 911 } 912 913 return nil 914 } 915 916 func (f *File) applyRelocationss390x(dst []byte, rels []byte) error { 917 // 24 is the size of Rela64. 918 if len(rels)%24 != 0 { 919 return errors.New("length of relocation section is not a multiple of 24") 920 } 921 922 symbols, _, err := f.getSymbols(SHT_SYMTAB) 923 if err != nil { 924 return err 925 } 926 927 b := bytes.NewReader(rels) 928 var rela Rela64 929 930 for b.Len() > 0 { 931 binary.Read(b, f.ByteOrder, &rela) 932 symNo := rela.Info >> 32 933 t := R_390(rela.Info & 0xffff) 934 935 if symNo == 0 || symNo > uint64(len(symbols)) { 936 continue 937 } 938 sym := &symbols[symNo-1] 939 switch SymType(sym.Info & 0xf) { 940 case STT_SECTION, STT_NOTYPE: 941 break 942 default: 943 continue 944 } 945 946 switch t { 947 case R_390_64: 948 if rela.Off+8 >= uint64(len(dst)) || rela.Addend < 0 { 949 continue 950 } 951 val := sym.Value + uint64(rela.Addend) 952 f.ByteOrder.PutUint64(dst[rela.Off:rela.Off+8], val) 953 case R_390_32: 954 if rela.Off+4 >= uint64(len(dst)) || rela.Addend < 0 { 955 continue 956 } 957 val := uint32(sym.Value) + uint32(rela.Addend) 958 f.ByteOrder.PutUint32(dst[rela.Off:rela.Off+4], val) 959 } 960 } 961 962 return nil 963 } 964 965 func (f *File) DWARF() (*dwarf.Data, error) { 966 // sectionData gets the data for s, checks its size, and 967 // applies any applicable relations. 968 sectionData := func(i int, s *Section) ([]byte, error) { 969 b, err := s.Data() 970 if err != nil && uint64(len(b)) < s.Size { 971 return nil, err 972 } 973 974 if len(b) >= 12 && string(b[:4]) == "ZLIB" { 975 dlen := binary.BigEndian.Uint64(b[4:12]) 976 dbuf := make([]byte, dlen) 977 r, err := zlib.NewReader(bytes.NewBuffer(b[12:])) 978 if err != nil { 979 return nil, err 980 } 981 if _, err := io.ReadFull(r, dbuf); err != nil { 982 return nil, err 983 } 984 if err := r.Close(); err != nil { 985 return nil, err 986 } 987 b = dbuf 988 } 989 990 for _, r := range f.Sections { 991 if r.Type != SHT_RELA && r.Type != SHT_REL { 992 continue 993 } 994 if int(r.Info) != i { 995 continue 996 } 997 rd, err := r.Data() 998 if err != nil { 999 return nil, err 1000 } 1001 err = f.applyRelocations(b, rd) 1002 if err != nil { 1003 return nil, err 1004 } 1005 } 1006 return b, nil 1007 } 1008 1009 // There are many other DWARF sections, but these 1010 // are the ones the debug/dwarf package uses. 1011 // Don't bother loading others. 1012 var dat = map[string][]byte{"abbrev": nil, "info": nil, "str": nil, "line": nil, "ranges": nil} 1013 for i, s := range f.Sections { 1014 suffix := "" 1015 switch { 1016 case strings.HasPrefix(s.Name, ".debug_"): 1017 suffix = s.Name[7:] 1018 case strings.HasPrefix(s.Name, ".zdebug_"): 1019 suffix = s.Name[8:] 1020 default: 1021 continue 1022 } 1023 if _, ok := dat[suffix]; !ok { 1024 continue 1025 } 1026 b, err := sectionData(i, s) 1027 if err != nil { 1028 return nil, err 1029 } 1030 dat[suffix] = b 1031 } 1032 1033 d, err := dwarf.New(dat["abbrev"], nil, nil, dat["info"], dat["line"], nil, dat["ranges"], dat["str"]) 1034 if err != nil { 1035 return nil, err 1036 } 1037 1038 // Look for DWARF4 .debug_types sections. 1039 for i, s := range f.Sections { 1040 if s.Name == ".debug_types" { 1041 b, err := sectionData(i, s) 1042 if err != nil { 1043 return nil, err 1044 } 1045 1046 err = d.AddTypes(fmt.Sprintf("types-%d", i), b) 1047 if err != nil { 1048 return nil, err 1049 } 1050 } 1051 } 1052 1053 return d, nil 1054 } 1055 1056 // Symbols returns the symbol table for f. The symbols will be listed in the order 1057 // they appear in f. 1058 // 1059 // For compatibility with Go 1.0, Symbols omits the null symbol at index 0. 1060 // After retrieving the symbols as symtab, an externally supplied index x 1061 // corresponds to symtab[x-1], not symtab[x]. 1062 func (f *File) Symbols() ([]Symbol, error) { 1063 sym, _, err := f.getSymbols(SHT_SYMTAB) 1064 return sym, err 1065 } 1066 1067 // DynamicSymbols returns the dynamic symbol table for f. The symbols 1068 // will be listed in the order they appear in f. 1069 // 1070 // For compatibility with Symbols, DynamicSymbols omits the null symbol at index 0. 1071 // After retrieving the symbols as symtab, an externally supplied index x 1072 // corresponds to symtab[x-1], not symtab[x]. 1073 func (f *File) DynamicSymbols() ([]Symbol, error) { 1074 sym, _, err := f.getSymbols(SHT_DYNSYM) 1075 return sym, err 1076 } 1077 1078 type ImportedSymbol struct { 1079 Name string 1080 Version string 1081 Library string 1082 } 1083 1084 // ImportedSymbols returns the names of all symbols 1085 // referred to by the binary f that are expected to be 1086 // satisfied by other libraries at dynamic load time. 1087 // It does not return weak symbols. 1088 func (f *File) ImportedSymbols() ([]ImportedSymbol, error) { 1089 sym, str, err := f.getSymbols(SHT_DYNSYM) 1090 if err != nil { 1091 return nil, err 1092 } 1093 f.gnuVersionInit(str) 1094 var all []ImportedSymbol 1095 for i, s := range sym { 1096 if ST_BIND(s.Info) == STB_GLOBAL && s.Section == SHN_UNDEF { 1097 all = append(all, ImportedSymbol{Name: s.Name}) 1098 f.gnuVersion(i, &all[len(all)-1]) 1099 } 1100 } 1101 return all, nil 1102 } 1103 1104 type verneed struct { 1105 File string 1106 Name string 1107 } 1108 1109 // gnuVersionInit parses the GNU version tables 1110 // for use by calls to gnuVersion. 1111 func (f *File) gnuVersionInit(str []byte) { 1112 // Accumulate verneed information. 1113 vn := f.SectionByType(SHT_GNU_VERNEED) 1114 if vn == nil { 1115 return 1116 } 1117 d, _ := vn.Data() 1118 1119 var need []verneed 1120 i := 0 1121 for { 1122 if i+16 > len(d) { 1123 break 1124 } 1125 vers := f.ByteOrder.Uint16(d[i : i+2]) 1126 if vers != 1 { 1127 break 1128 } 1129 cnt := f.ByteOrder.Uint16(d[i+2 : i+4]) 1130 fileoff := f.ByteOrder.Uint32(d[i+4 : i+8]) 1131 aux := f.ByteOrder.Uint32(d[i+8 : i+12]) 1132 next := f.ByteOrder.Uint32(d[i+12 : i+16]) 1133 file, _ := getString(str, int(fileoff)) 1134 1135 var name string 1136 j := i + int(aux) 1137 for c := 0; c < int(cnt); c++ { 1138 if j+16 > len(d) { 1139 break 1140 } 1141 // hash := f.ByteOrder.Uint32(d[j:j+4]) 1142 // flags := f.ByteOrder.Uint16(d[j+4:j+6]) 1143 other := f.ByteOrder.Uint16(d[j+6 : j+8]) 1144 nameoff := f.ByteOrder.Uint32(d[j+8 : j+12]) 1145 next := f.ByteOrder.Uint32(d[j+12 : j+16]) 1146 name, _ = getString(str, int(nameoff)) 1147 ndx := int(other) 1148 if ndx >= len(need) { 1149 a := make([]verneed, 2*(ndx+1)) 1150 copy(a, need) 1151 need = a 1152 } 1153 1154 need[ndx] = verneed{file, name} 1155 if next == 0 { 1156 break 1157 } 1158 j += int(next) 1159 } 1160 1161 if next == 0 { 1162 break 1163 } 1164 i += int(next) 1165 } 1166 1167 // Versym parallels symbol table, indexing into verneed. 1168 vs := f.SectionByType(SHT_GNU_VERSYM) 1169 if vs == nil { 1170 return 1171 } 1172 d, _ = vs.Data() 1173 1174 f.gnuNeed = need 1175 f.gnuVersym = d 1176 } 1177 1178 // gnuVersion adds Library and Version information to sym, 1179 // which came from offset i of the symbol table. 1180 func (f *File) gnuVersion(i int, sym *ImportedSymbol) { 1181 // Each entry is two bytes. 1182 i = (i + 1) * 2 1183 if i >= len(f.gnuVersym) { 1184 return 1185 } 1186 j := int(f.ByteOrder.Uint16(f.gnuVersym[i:])) 1187 if j < 2 || j >= len(f.gnuNeed) { 1188 return 1189 } 1190 n := &f.gnuNeed[j] 1191 sym.Library = n.File 1192 sym.Version = n.Name 1193 } 1194 1195 // ImportedLibraries returns the names of all libraries 1196 // referred to by the binary f that are expected to be 1197 // linked with the binary at dynamic link time. 1198 func (f *File) ImportedLibraries() ([]string, error) { 1199 return f.DynString(DT_NEEDED) 1200 } 1201 1202 // DynString returns the strings listed for the given tag in the file's dynamic 1203 // section. 1204 // 1205 // The tag must be one that takes string values: DT_NEEDED, DT_SONAME, DT_RPATH, or 1206 // DT_RUNPATH. 1207 func (f *File) DynString(tag DynTag) ([]string, error) { 1208 switch tag { 1209 case DT_NEEDED, DT_SONAME, DT_RPATH, DT_RUNPATH: 1210 default: 1211 return nil, fmt.Errorf("non-string-valued tag %v", tag) 1212 } 1213 ds := f.SectionByType(SHT_DYNAMIC) 1214 if ds == nil { 1215 // not dynamic, so no libraries 1216 return nil, nil 1217 } 1218 d, err := ds.Data() 1219 if err != nil { 1220 return nil, err 1221 } 1222 str, err := f.stringTable(ds.Link) 1223 if err != nil { 1224 return nil, err 1225 } 1226 var all []string 1227 for len(d) > 0 { 1228 var t DynTag 1229 var v uint64 1230 switch f.Class { 1231 case ELFCLASS32: 1232 t = DynTag(f.ByteOrder.Uint32(d[0:4])) 1233 v = uint64(f.ByteOrder.Uint32(d[4:8])) 1234 d = d[8:] 1235 case ELFCLASS64: 1236 t = DynTag(f.ByteOrder.Uint64(d[0:8])) 1237 v = f.ByteOrder.Uint64(d[8:16]) 1238 d = d[16:] 1239 } 1240 if t == tag { 1241 s, ok := getString(str, int(v)) 1242 if ok { 1243 all = append(all, s) 1244 } 1245 } 1246 } 1247 return all, nil 1248 }