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