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