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