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