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