* tree-vect-loop-manip.c (vect_do_peeling): Do not use
[official-gcc.git] / libgo / go / debug / elf / file.go
blobb415bb1bbc9e5d1aebb937e13ee9805597ccee95
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.
5 // Package elf implements access to ELF object files.
6 package elf
8 import (
9 "bytes"
10 "compress/zlib"
11 "debug/dwarf"
12 "encoding/binary"
13 "errors"
14 "fmt"
15 "io"
16 "os"
17 "strings"
20 // TODO: error reporting detail
23 * Internal ELF representation
26 // A FileHeader represents an ELF file header.
27 type FileHeader struct {
28 Class Class
29 Data Data
30 Version Version
31 OSABI OSABI
32 ABIVersion uint8
33 ByteOrder binary.ByteOrder
34 Type Type
35 Machine Machine
36 Entry uint64
39 // A File represents an open ELF file.
40 type File struct {
41 FileHeader
42 Sections []*Section
43 Progs []*Prog
44 closer io.Closer
45 gnuNeed []verneed
46 gnuVersym []byte
49 // A SectionHeader represents a single ELF section header.
50 type SectionHeader struct {
51 Name string
52 Type SectionType
53 Flags SectionFlag
54 Addr uint64
55 Offset uint64
56 Size uint64
57 Link uint32
58 Info uint32
59 Addralign uint64
60 Entsize uint64
62 // FileSize is the size of this section in the file in bytes.
63 // If a section is compressed, FileSize is the size of the
64 // compressed data, while Size (above) is the size of the
65 // uncompressed data.
66 FileSize uint64
69 // A Section represents a single section in an ELF file.
70 type Section struct {
71 SectionHeader
73 // Embed ReaderAt for ReadAt method.
74 // Do not embed SectionReader directly
75 // to avoid having Read and Seek.
76 // If a client wants Read and Seek it must use
77 // Open() to avoid fighting over the seek offset
78 // with other clients.
80 // ReaderAt may be nil if the section is not easily available
81 // in a random-access form. For example, a compressed section
82 // may have a nil ReaderAt.
83 io.ReaderAt
84 sr *io.SectionReader
86 compressionType CompressionType
87 compressionOffset int64
90 // Data reads and returns the contents of the ELF section.
91 // Even if the section is stored compressed in the ELF file,
92 // Data returns uncompressed data.
93 func (s *Section) Data() ([]byte, error) {
94 dat := make([]byte, s.Size)
95 n, err := io.ReadFull(s.Open(), dat)
96 return dat[0:n], err
99 // stringTable reads and returns the string table given by the
100 // specified link value.
101 func (f *File) stringTable(link uint32) ([]byte, error) {
102 if link <= 0 || link >= uint32(len(f.Sections)) {
103 return nil, errors.New("section has invalid string table link")
105 return f.Sections[link].Data()
108 // Open returns a new ReadSeeker reading the ELF section.
109 // Even if the section is stored compressed in the ELF file,
110 // the ReadSeeker reads uncompressed data.
111 func (s *Section) Open() io.ReadSeeker {
112 if s.Flags&SHF_COMPRESSED == 0 {
113 return io.NewSectionReader(s.sr, 0, 1<<63-1)
115 if s.compressionType == COMPRESS_ZLIB {
116 return &readSeekerFromReader{
117 reset: func() (io.Reader, error) {
118 fr := io.NewSectionReader(s.sr, s.compressionOffset, int64(s.FileSize)-s.compressionOffset)
119 return zlib.NewReader(fr)
121 size: int64(s.Size),
124 err := &FormatError{int64(s.Offset), "unknown compression type", s.compressionType}
125 return errorReader{err}
128 // A ProgHeader represents a single ELF program header.
129 type ProgHeader struct {
130 Type ProgType
131 Flags ProgFlag
132 Off uint64
133 Vaddr uint64
134 Paddr uint64
135 Filesz uint64
136 Memsz uint64
137 Align uint64
140 // A Prog represents a single ELF program header in an ELF binary.
141 type Prog struct {
142 ProgHeader
144 // Embed ReaderAt for ReadAt method.
145 // Do not embed SectionReader directly
146 // to avoid having Read and Seek.
147 // If a client wants Read and Seek it must use
148 // Open() to avoid fighting over the seek offset
149 // with other clients.
150 io.ReaderAt
151 sr *io.SectionReader
154 // Open returns a new ReadSeeker reading the ELF program body.
155 func (p *Prog) Open() io.ReadSeeker { return io.NewSectionReader(p.sr, 0, 1<<63-1) }
157 // A Symbol represents an entry in an ELF symbol table section.
158 type Symbol struct {
159 Name string
160 Info, Other byte
161 Section SectionIndex
162 Value, Size uint64
166 * ELF reader
169 type FormatError struct {
170 off int64
171 msg string
172 val interface{}
175 func (e *FormatError) Error() string {
176 msg := e.msg
177 if e.val != nil {
178 msg += fmt.Sprintf(" '%v' ", e.val)
180 msg += fmt.Sprintf("in record at byte %#x", e.off)
181 return msg
184 // Open opens the named file using os.Open and prepares it for use as an ELF binary.
185 func Open(name string) (*File, error) {
186 f, err := os.Open(name)
187 if err != nil {
188 return nil, err
190 ff, err := NewFile(f)
191 if err != nil {
192 f.Close()
193 return nil, err
195 ff.closer = f
196 return ff, nil
199 // Close closes the File.
200 // If the File was created using NewFile directly instead of Open,
201 // Close has no effect.
202 func (f *File) Close() error {
203 var err error
204 if f.closer != nil {
205 err = f.closer.Close()
206 f.closer = nil
208 return err
211 // SectionByType returns the first section in f with the
212 // given type, or nil if there is no such section.
213 func (f *File) SectionByType(typ SectionType) *Section {
214 for _, s := range f.Sections {
215 if s.Type == typ {
216 return s
219 return nil
222 // NewFile creates a new File for accessing an ELF binary in an underlying reader.
223 // The ELF binary is expected to start at position 0 in the ReaderAt.
224 func NewFile(r io.ReaderAt) (*File, error) {
225 sr := io.NewSectionReader(r, 0, 1<<63-1)
226 // Read and decode ELF identifier
227 var ident [16]uint8
228 if _, err := r.ReadAt(ident[0:], 0); err != nil {
229 return nil, err
231 if ident[0] != '\x7f' || ident[1] != 'E' || ident[2] != 'L' || ident[3] != 'F' {
232 return nil, &FormatError{0, "bad magic number", ident[0:4]}
235 f := new(File)
236 f.Class = Class(ident[EI_CLASS])
237 switch f.Class {
238 case ELFCLASS32:
239 case ELFCLASS64:
240 // ok
241 default:
242 return nil, &FormatError{0, "unknown ELF class", f.Class}
245 f.Data = Data(ident[EI_DATA])
246 switch f.Data {
247 case ELFDATA2LSB:
248 f.ByteOrder = binary.LittleEndian
249 case ELFDATA2MSB:
250 f.ByteOrder = binary.BigEndian
251 default:
252 return nil, &FormatError{0, "unknown ELF data encoding", f.Data}
255 f.Version = Version(ident[EI_VERSION])
256 if f.Version != EV_CURRENT {
257 return nil, &FormatError{0, "unknown ELF version", f.Version}
260 f.OSABI = OSABI(ident[EI_OSABI])
261 f.ABIVersion = ident[EI_ABIVERSION]
263 // Read ELF file header
264 var phoff int64
265 var phentsize, phnum int
266 var shoff int64
267 var shentsize, shnum, shstrndx int
268 shstrndx = -1
269 switch f.Class {
270 case ELFCLASS32:
271 hdr := new(Header32)
272 sr.Seek(0, io.SeekStart)
273 if err := binary.Read(sr, f.ByteOrder, hdr); err != nil {
274 return nil, err
276 f.Type = Type(hdr.Type)
277 f.Machine = Machine(hdr.Machine)
278 f.Entry = uint64(hdr.Entry)
279 if v := Version(hdr.Version); v != f.Version {
280 return nil, &FormatError{0, "mismatched ELF version", v}
282 phoff = int64(hdr.Phoff)
283 phentsize = int(hdr.Phentsize)
284 phnum = int(hdr.Phnum)
285 shoff = int64(hdr.Shoff)
286 shentsize = int(hdr.Shentsize)
287 shnum = int(hdr.Shnum)
288 shstrndx = int(hdr.Shstrndx)
289 case ELFCLASS64:
290 hdr := new(Header64)
291 sr.Seek(0, io.SeekStart)
292 if err := binary.Read(sr, f.ByteOrder, hdr); err != nil {
293 return nil, err
295 f.Type = Type(hdr.Type)
296 f.Machine = Machine(hdr.Machine)
297 f.Entry = hdr.Entry
298 if v := Version(hdr.Version); v != f.Version {
299 return nil, &FormatError{0, "mismatched ELF version", v}
301 phoff = int64(hdr.Phoff)
302 phentsize = int(hdr.Phentsize)
303 phnum = int(hdr.Phnum)
304 shoff = int64(hdr.Shoff)
305 shentsize = int(hdr.Shentsize)
306 shnum = int(hdr.Shnum)
307 shstrndx = int(hdr.Shstrndx)
310 if shnum > 0 && shoff > 0 && (shstrndx < 0 || shstrndx >= shnum) {
311 return nil, &FormatError{0, "invalid ELF shstrndx", shstrndx}
314 // Read program headers
315 f.Progs = make([]*Prog, phnum)
316 for i := 0; i < phnum; i++ {
317 off := phoff + int64(i)*int64(phentsize)
318 sr.Seek(off, io.SeekStart)
319 p := new(Prog)
320 switch f.Class {
321 case ELFCLASS32:
322 ph := new(Prog32)
323 if err := binary.Read(sr, f.ByteOrder, ph); err != nil {
324 return nil, err
326 p.ProgHeader = ProgHeader{
327 Type: ProgType(ph.Type),
328 Flags: ProgFlag(ph.Flags),
329 Off: uint64(ph.Off),
330 Vaddr: uint64(ph.Vaddr),
331 Paddr: uint64(ph.Paddr),
332 Filesz: uint64(ph.Filesz),
333 Memsz: uint64(ph.Memsz),
334 Align: uint64(ph.Align),
336 case ELFCLASS64:
337 ph := new(Prog64)
338 if err := binary.Read(sr, f.ByteOrder, ph); err != nil {
339 return nil, err
341 p.ProgHeader = ProgHeader{
342 Type: ProgType(ph.Type),
343 Flags: ProgFlag(ph.Flags),
344 Off: ph.Off,
345 Vaddr: ph.Vaddr,
346 Paddr: ph.Paddr,
347 Filesz: ph.Filesz,
348 Memsz: ph.Memsz,
349 Align: ph.Align,
352 p.sr = io.NewSectionReader(r, int64(p.Off), int64(p.Filesz))
353 p.ReaderAt = p.sr
354 f.Progs[i] = p
357 // Read section headers
358 f.Sections = make([]*Section, shnum)
359 names := make([]uint32, shnum)
360 for i := 0; i < shnum; i++ {
361 off := shoff + int64(i)*int64(shentsize)
362 sr.Seek(off, io.SeekStart)
363 s := new(Section)
364 switch f.Class {
365 case ELFCLASS32:
366 sh := new(Section32)
367 if err := binary.Read(sr, f.ByteOrder, sh); err != nil {
368 return nil, err
370 names[i] = sh.Name
371 s.SectionHeader = SectionHeader{
372 Type: SectionType(sh.Type),
373 Flags: SectionFlag(sh.Flags),
374 Addr: uint64(sh.Addr),
375 Offset: uint64(sh.Off),
376 FileSize: uint64(sh.Size),
377 Link: sh.Link,
378 Info: sh.Info,
379 Addralign: uint64(sh.Addralign),
380 Entsize: uint64(sh.Entsize),
382 case ELFCLASS64:
383 sh := new(Section64)
384 if err := binary.Read(sr, f.ByteOrder, sh); err != nil {
385 return nil, err
387 names[i] = sh.Name
388 s.SectionHeader = SectionHeader{
389 Type: SectionType(sh.Type),
390 Flags: SectionFlag(sh.Flags),
391 Offset: sh.Off,
392 FileSize: sh.Size,
393 Addr: sh.Addr,
394 Link: sh.Link,
395 Info: sh.Info,
396 Addralign: sh.Addralign,
397 Entsize: sh.Entsize,
400 s.sr = io.NewSectionReader(r, int64(s.Offset), int64(s.FileSize))
402 if s.Flags&SHF_COMPRESSED == 0 {
403 s.ReaderAt = s.sr
404 s.Size = s.FileSize
405 } else {
406 // Read the compression header.
407 switch f.Class {
408 case ELFCLASS32:
409 ch := new(Chdr32)
410 if err := binary.Read(s.sr, f.ByteOrder, ch); err != nil {
411 return nil, err
413 s.compressionType = CompressionType(ch.Type)
414 s.Size = uint64(ch.Size)
415 s.Addralign = uint64(ch.Addralign)
416 s.compressionOffset = int64(binary.Size(ch))
417 case ELFCLASS64:
418 ch := new(Chdr64)
419 if err := binary.Read(s.sr, f.ByteOrder, ch); err != nil {
420 return nil, err
422 s.compressionType = CompressionType(ch.Type)
423 s.Size = ch.Size
424 s.Addralign = ch.Addralign
425 s.compressionOffset = int64(binary.Size(ch))
429 f.Sections[i] = s
432 if len(f.Sections) == 0 {
433 return f, nil
436 // Load section header string table.
437 shstrtab, err := f.Sections[shstrndx].Data()
438 if err != nil {
439 return nil, err
441 for i, s := range f.Sections {
442 var ok bool
443 s.Name, ok = getString(shstrtab, int(names[i]))
444 if !ok {
445 return nil, &FormatError{shoff + int64(i*shentsize), "bad section name index", names[i]}
449 return f, nil
452 // getSymbols returns a slice of Symbols from parsing the symbol table
453 // with the given type, along with the associated string table.
454 func (f *File) getSymbols(typ SectionType) ([]Symbol, []byte, error) {
455 switch f.Class {
456 case ELFCLASS64:
457 return f.getSymbols64(typ)
459 case ELFCLASS32:
460 return f.getSymbols32(typ)
463 return nil, nil, errors.New("not implemented")
466 // ErrNoSymbols is returned by File.Symbols and File.DynamicSymbols
467 // if there is no such section in the File.
468 var ErrNoSymbols = errors.New("no symbol section")
470 func (f *File) getSymbols32(typ SectionType) ([]Symbol, []byte, error) {
471 symtabSection := f.SectionByType(typ)
472 if symtabSection == nil {
473 return nil, nil, ErrNoSymbols
476 data, err := symtabSection.Data()
477 if err != nil {
478 return nil, nil, errors.New("cannot load symbol section")
480 symtab := bytes.NewReader(data)
481 if symtab.Len()%Sym32Size != 0 {
482 return nil, nil, errors.New("length of symbol section is not a multiple of SymSize")
485 strdata, err := f.stringTable(symtabSection.Link)
486 if err != nil {
487 return nil, nil, errors.New("cannot load string table section")
490 // The first entry is all zeros.
491 var skip [Sym32Size]byte
492 symtab.Read(skip[:])
494 symbols := make([]Symbol, symtab.Len()/Sym32Size)
496 i := 0
497 var sym Sym32
498 for symtab.Len() > 0 {
499 binary.Read(symtab, f.ByteOrder, &sym)
500 str, _ := getString(strdata, int(sym.Name))
501 symbols[i].Name = str
502 symbols[i].Info = sym.Info
503 symbols[i].Other = sym.Other
504 symbols[i].Section = SectionIndex(sym.Shndx)
505 symbols[i].Value = uint64(sym.Value)
506 symbols[i].Size = uint64(sym.Size)
510 return symbols, strdata, nil
513 func (f *File) getSymbols64(typ SectionType) ([]Symbol, []byte, error) {
514 symtabSection := f.SectionByType(typ)
515 if symtabSection == nil {
516 return nil, nil, ErrNoSymbols
519 data, err := symtabSection.Data()
520 if err != nil {
521 return nil, nil, errors.New("cannot load symbol section")
523 symtab := bytes.NewReader(data)
524 if symtab.Len()%Sym64Size != 0 {
525 return nil, nil, errors.New("length of symbol section is not a multiple of Sym64Size")
528 strdata, err := f.stringTable(symtabSection.Link)
529 if err != nil {
530 return nil, nil, errors.New("cannot load string table section")
533 // The first entry is all zeros.
534 var skip [Sym64Size]byte
535 symtab.Read(skip[:])
537 symbols := make([]Symbol, symtab.Len()/Sym64Size)
539 i := 0
540 var sym Sym64
541 for symtab.Len() > 0 {
542 binary.Read(symtab, f.ByteOrder, &sym)
543 str, _ := getString(strdata, int(sym.Name))
544 symbols[i].Name = str
545 symbols[i].Info = sym.Info
546 symbols[i].Other = sym.Other
547 symbols[i].Section = SectionIndex(sym.Shndx)
548 symbols[i].Value = sym.Value
549 symbols[i].Size = sym.Size
553 return symbols, strdata, nil
556 // getString extracts a string from an ELF string table.
557 func getString(section []byte, start int) (string, bool) {
558 if start < 0 || start >= len(section) {
559 return "", false
562 for end := start; end < len(section); end++ {
563 if section[end] == 0 {
564 return string(section[start:end]), true
567 return "", false
570 // Section returns a section with the given name, or nil if no such
571 // section exists.
572 func (f *File) Section(name string) *Section {
573 for _, s := range f.Sections {
574 if s.Name == name {
575 return s
578 return nil
581 // applyRelocations applies relocations to dst. rels is a relocations section
582 // in REL or RELA format.
583 func (f *File) applyRelocations(dst []byte, rels []byte) error {
584 switch {
585 case f.Class == ELFCLASS64 && f.Machine == EM_X86_64:
586 return f.applyRelocationsAMD64(dst, rels)
587 case f.Class == ELFCLASS32 && f.Machine == EM_386:
588 return f.applyRelocations386(dst, rels)
589 case f.Class == ELFCLASS32 && f.Machine == EM_ARM:
590 return f.applyRelocationsARM(dst, rels)
591 case f.Class == ELFCLASS64 && f.Machine == EM_AARCH64:
592 return f.applyRelocationsARM64(dst, rels)
593 case f.Class == ELFCLASS32 && f.Machine == EM_PPC:
594 return f.applyRelocationsPPC(dst, rels)
595 case f.Class == ELFCLASS64 && f.Machine == EM_PPC64:
596 return f.applyRelocationsPPC64(dst, rels)
597 case f.Class == ELFCLASS32 && f.Machine == EM_MIPS:
598 return f.applyRelocationsMIPS(dst, rels)
599 case f.Class == ELFCLASS64 && f.Machine == EM_MIPS:
600 return f.applyRelocationsMIPS64(dst, rels)
601 case f.Class == ELFCLASS64 && f.Machine == EM_S390:
602 return f.applyRelocationss390x(dst, rels)
603 case f.Class == ELFCLASS32 && (f.Machine == EM_SPARC || f.Machine == EM_SPARC32PLUS):
604 return f.applyRelocationsSPARC(dst, rels)
605 case f.Class == ELFCLASS64 && f.Machine == EM_SPARCV9:
606 return f.applyRelocationsSPARC64(dst, rels)
607 case f.Class == ELFCLASS64 && f.Machine == EM_ALPHA:
608 return f.applyRelocationsALPHA(dst, rels)
609 default:
610 return errors.New("applyRelocations: not implemented")
614 func (f *File) applyRelocationsAMD64(dst []byte, rels []byte) error {
615 // 24 is the size of Rela64.
616 if len(rels)%24 != 0 {
617 return errors.New("length of relocation section is not a multiple of 24")
620 symbols, _, err := f.getSymbols(SHT_SYMTAB)
621 if err != nil {
622 return err
625 b := bytes.NewReader(rels)
626 var rela Rela64
628 for b.Len() > 0 {
629 binary.Read(b, f.ByteOrder, &rela)
630 symNo := rela.Info >> 32
631 t := R_X86_64(rela.Info & 0xffff)
633 if symNo == 0 || symNo > uint64(len(symbols)) {
634 continue
636 sym := &symbols[symNo-1]
637 if SymType(sym.Info&0xf) != STT_SECTION {
638 // We don't handle non-section relocations for now.
639 continue
642 // There are relocations, so this must be a normal
643 // object file, and we only look at section symbols,
644 // so we assume that the symbol value is 0.
646 switch t {
647 case R_X86_64_64:
648 if rela.Off+8 >= uint64(len(dst)) || rela.Addend < 0 {
649 continue
651 f.ByteOrder.PutUint64(dst[rela.Off:rela.Off+8], uint64(rela.Addend))
652 case R_X86_64_32:
653 if rela.Off+4 >= uint64(len(dst)) || rela.Addend < 0 {
654 continue
656 f.ByteOrder.PutUint32(dst[rela.Off:rela.Off+4], uint32(rela.Addend))
660 return nil
663 func (f *File) applyRelocations386(dst []byte, rels []byte) error {
664 // 8 is the size of Rel32.
665 if len(rels)%8 != 0 {
666 return errors.New("length of relocation section is not a multiple of 8")
669 symbols, _, err := f.getSymbols(SHT_SYMTAB)
670 if err != nil {
671 return err
674 b := bytes.NewReader(rels)
675 var rel Rel32
677 for b.Len() > 0 {
678 binary.Read(b, f.ByteOrder, &rel)
679 symNo := rel.Info >> 8
680 t := R_386(rel.Info & 0xff)
682 if symNo == 0 || symNo > uint32(len(symbols)) {
683 continue
685 sym := &symbols[symNo-1]
687 if t == R_386_32 {
688 if rel.Off+4 >= uint32(len(dst)) {
689 continue
691 val := f.ByteOrder.Uint32(dst[rel.Off : rel.Off+4])
692 val += uint32(sym.Value)
693 f.ByteOrder.PutUint32(dst[rel.Off:rel.Off+4], val)
697 return nil
700 func (f *File) applyRelocationsARM(dst []byte, rels []byte) error {
701 // 8 is the size of Rel32.
702 if len(rels)%8 != 0 {
703 return errors.New("length of relocation section is not a multiple of 8")
706 symbols, _, err := f.getSymbols(SHT_SYMTAB)
707 if err != nil {
708 return err
711 b := bytes.NewReader(rels)
712 var rel Rel32
714 for b.Len() > 0 {
715 binary.Read(b, f.ByteOrder, &rel)
716 symNo := rel.Info >> 8
717 t := R_ARM(rel.Info & 0xff)
719 if symNo == 0 || symNo > uint32(len(symbols)) {
720 continue
722 sym := &symbols[symNo-1]
724 switch t {
725 case R_ARM_ABS32:
726 if rel.Off+4 >= uint32(len(dst)) {
727 continue
729 val := f.ByteOrder.Uint32(dst[rel.Off : rel.Off+4])
730 val += uint32(sym.Value)
731 f.ByteOrder.PutUint32(dst[rel.Off:rel.Off+4], val)
735 return nil
738 func (f *File) applyRelocationsARM64(dst []byte, rels []byte) error {
739 // 24 is the size of Rela64.
740 if len(rels)%24 != 0 {
741 return errors.New("length of relocation section is not a multiple of 24")
744 symbols, _, err := f.getSymbols(SHT_SYMTAB)
745 if err != nil {
746 return err
749 b := bytes.NewReader(rels)
750 var rela Rela64
752 for b.Len() > 0 {
753 binary.Read(b, f.ByteOrder, &rela)
754 symNo := rela.Info >> 32
755 t := R_AARCH64(rela.Info & 0xffff)
757 if symNo == 0 || symNo > uint64(len(symbols)) {
758 continue
760 sym := &symbols[symNo-1]
761 if SymType(sym.Info&0xf) != STT_SECTION {
762 // We don't handle non-section relocations for now.
763 continue
766 // There are relocations, so this must be a normal
767 // object file, and we only look at section symbols,
768 // so we assume that the symbol value is 0.
770 switch t {
771 case R_AARCH64_ABS64:
772 if rela.Off+8 >= uint64(len(dst)) || rela.Addend < 0 {
773 continue
775 f.ByteOrder.PutUint64(dst[rela.Off:rela.Off+8], uint64(rela.Addend))
776 case R_AARCH64_ABS32:
777 if rela.Off+4 >= uint64(len(dst)) || rela.Addend < 0 {
778 continue
780 f.ByteOrder.PutUint32(dst[rela.Off:rela.Off+4], uint32(rela.Addend))
784 return nil
787 func (f *File) applyRelocationsPPC(dst []byte, rels []byte) error {
788 // 12 is the size of Rela32.
789 if len(rels)%12 != 0 {
790 return errors.New("length of relocation section is not a multiple of 12")
793 symbols, _, err := f.getSymbols(SHT_SYMTAB)
794 if err != nil {
795 return err
798 b := bytes.NewReader(rels)
799 var rela Rela32
801 for b.Len() > 0 {
802 binary.Read(b, f.ByteOrder, &rela)
803 symNo := rela.Info >> 8
804 t := R_PPC(rela.Info & 0xff)
806 if symNo == 0 || symNo > uint32(len(symbols)) {
807 continue
809 sym := &symbols[symNo-1]
810 if SymType(sym.Info&0xf) != STT_SECTION {
811 // We don't handle non-section relocations for now.
812 continue
815 switch t {
816 case R_PPC_ADDR32:
817 if rela.Off+4 >= uint32(len(dst)) || rela.Addend < 0 {
818 continue
820 f.ByteOrder.PutUint32(dst[rela.Off:rela.Off+4], uint32(rela.Addend))
824 return nil
827 func (f *File) applyRelocationsPPC64(dst []byte, rels []byte) error {
828 // 24 is the size of Rela64.
829 if len(rels)%24 != 0 {
830 return errors.New("length of relocation section is not a multiple of 24")
833 symbols, _, err := f.getSymbols(SHT_SYMTAB)
834 if err != nil {
835 return err
838 b := bytes.NewReader(rels)
839 var rela Rela64
841 for b.Len() > 0 {
842 binary.Read(b, f.ByteOrder, &rela)
843 symNo := rela.Info >> 32
844 t := R_PPC64(rela.Info & 0xffff)
846 if symNo == 0 || symNo > uint64(len(symbols)) {
847 continue
849 sym := &symbols[symNo-1]
850 if SymType(sym.Info&0xf) != STT_SECTION {
851 // We don't handle non-section relocations for now.
852 continue
855 switch t {
856 case R_PPC64_ADDR64:
857 if rela.Off+8 >= uint64(len(dst)) || rela.Addend < 0 {
858 continue
860 f.ByteOrder.PutUint64(dst[rela.Off:rela.Off+8], uint64(rela.Addend))
861 case R_PPC64_ADDR32:
862 if rela.Off+4 >= uint64(len(dst)) || rela.Addend < 0 {
863 continue
865 f.ByteOrder.PutUint32(dst[rela.Off:rela.Off+4], uint32(rela.Addend))
869 return nil
872 func (f *File) applyRelocationsMIPS(dst []byte, rels []byte) error {
873 // 8 is the size of Rel32.
874 if len(rels)%8 != 0 {
875 return errors.New("length of relocation section is not a multiple of 8")
878 symbols, _, err := f.getSymbols(SHT_SYMTAB)
879 if err != nil {
880 return err
883 b := bytes.NewReader(rels)
884 var rel Rel32
886 for b.Len() > 0 {
887 binary.Read(b, f.ByteOrder, &rel)
888 symNo := rel.Info >> 8
889 t := R_MIPS(rel.Info & 0xff)
891 if symNo == 0 || symNo > uint32(len(symbols)) {
892 continue
894 sym := &symbols[symNo-1]
896 switch t {
897 case R_MIPS_32:
898 if rel.Off+4 >= uint32(len(dst)) {
899 continue
901 val := f.ByteOrder.Uint32(dst[rel.Off : rel.Off+4])
902 val += uint32(sym.Value)
903 f.ByteOrder.PutUint32(dst[rel.Off:rel.Off+4], val)
907 return nil
910 func (f *File) applyRelocationsMIPS64(dst []byte, rels []byte) error {
911 // 24 is the size of Rela64.
912 if len(rels)%24 != 0 {
913 return errors.New("length of relocation section is not a multiple of 24")
916 symbols, _, err := f.getSymbols(SHT_SYMTAB)
917 if err != nil {
918 return err
921 b := bytes.NewReader(rels)
922 var rela Rela64
924 for b.Len() > 0 {
925 binary.Read(b, f.ByteOrder, &rela)
926 var symNo uint64
927 var t R_MIPS
928 if f.ByteOrder == binary.BigEndian {
929 symNo = rela.Info >> 32
930 t = R_MIPS(rela.Info & 0xff)
931 } else {
932 symNo = rela.Info & 0xffffffff
933 t = R_MIPS(rela.Info >> 56)
936 if symNo == 0 || symNo > uint64(len(symbols)) {
937 continue
939 sym := &symbols[symNo-1]
940 if SymType(sym.Info&0xf) != STT_SECTION {
941 // We don't handle non-section relocations for now.
942 continue
945 switch t {
946 case R_MIPS_64:
947 if rela.Off+8 >= uint64(len(dst)) || rela.Addend < 0 {
948 continue
950 f.ByteOrder.PutUint64(dst[rela.Off:rela.Off+8], uint64(rela.Addend))
951 case R_MIPS_32:
952 if rela.Off+4 >= uint64(len(dst)) || rela.Addend < 0 {
953 continue
955 f.ByteOrder.PutUint32(dst[rela.Off:rela.Off+4], uint32(rela.Addend))
959 return nil
962 func (f *File) applyRelocationss390x(dst []byte, rels []byte) error {
963 // 24 is the size of Rela64.
964 if len(rels)%24 != 0 {
965 return errors.New("length of relocation section is not a multiple of 24")
968 symbols, _, err := f.getSymbols(SHT_SYMTAB)
969 if err != nil {
970 return err
973 b := bytes.NewReader(rels)
974 var rela Rela64
976 for b.Len() > 0 {
977 binary.Read(b, f.ByteOrder, &rela)
978 symNo := rela.Info >> 32
979 t := R_390(rela.Info & 0xffff)
981 if symNo == 0 || symNo > uint64(len(symbols)) {
982 continue
984 sym := &symbols[symNo-1]
985 switch SymType(sym.Info & 0xf) {
986 case STT_SECTION, STT_NOTYPE:
987 break
988 default:
989 continue
992 switch t {
993 case R_390_64:
994 if rela.Off+8 >= uint64(len(dst)) || rela.Addend < 0 {
995 continue
997 val := sym.Value + uint64(rela.Addend)
998 f.ByteOrder.PutUint64(dst[rela.Off:rela.Off+8], val)
999 case R_390_32:
1000 if rela.Off+4 >= uint64(len(dst)) || rela.Addend < 0 {
1001 continue
1003 val := uint32(sym.Value) + uint32(rela.Addend)
1004 f.ByteOrder.PutUint32(dst[rela.Off:rela.Off+4], val)
1008 return nil
1011 func (f *File) applyRelocationsSPARC(dst []byte, rels []byte) error {
1012 // 12 is the size of Rela32.
1013 if len(rels)%12 != 0 {
1014 return errors.New("length of relocation section is not a multiple of 12")
1017 symbols, _, err := f.getSymbols(SHT_SYMTAB)
1018 if err != nil {
1019 return err
1022 b := bytes.NewReader(rels)
1023 var rela Rela32
1025 for b.Len() > 0 {
1026 binary.Read(b, f.ByteOrder, &rela)
1027 symNo := rela.Info >> 32
1028 t := R_SPARC(rela.Info & 0xff)
1030 if symNo == 0 || symNo > uint32(len(symbols)) {
1031 continue
1033 sym := &symbols[symNo-1]
1034 if SymType(sym.Info&0xf) != STT_SECTION {
1035 // We don't handle non-section relocations for now.
1036 continue
1039 switch t {
1040 case R_SPARC_32, R_SPARC_UA32:
1041 if rela.Off+4 >= uint32(len(dst)) || rela.Addend < 0 {
1042 continue
1044 f.ByteOrder.PutUint32(dst[rela.Off:rela.Off+4], uint32(rela.Addend))
1048 return nil
1051 func (f *File) applyRelocationsSPARC64(dst []byte, rels []byte) error {
1052 // 24 is the size of Rela64.
1053 if len(rels)%24 != 0 {
1054 return errors.New("length of relocation section is not a multiple of 24")
1057 symbols, _, err := f.getSymbols(SHT_SYMTAB)
1058 if err != nil {
1059 return err
1062 b := bytes.NewReader(rels)
1063 var rela Rela64
1065 for b.Len() > 0 {
1066 binary.Read(b, f.ByteOrder, &rela)
1067 symNo := rela.Info >> 32
1068 t := R_SPARC(rela.Info & 0xff)
1070 if symNo == 0 || symNo > uint64(len(symbols)) {
1071 continue
1073 sym := &symbols[symNo-1]
1074 if SymType(sym.Info&0xf) != STT_SECTION {
1075 // We don't handle non-section relocations for now.
1076 continue
1079 switch t {
1080 case R_SPARC_64, R_SPARC_UA64:
1081 if rela.Off+8 >= uint64(len(dst)) || rela.Addend < 0 {
1082 continue
1084 f.ByteOrder.PutUint64(dst[rela.Off:rela.Off+8], uint64(rela.Addend))
1085 case R_SPARC_32, R_SPARC_UA32:
1086 if rela.Off+4 >= uint64(len(dst)) || rela.Addend < 0 {
1087 continue
1089 f.ByteOrder.PutUint32(dst[rela.Off:rela.Off+4], uint32(rela.Addend))
1093 return nil
1096 func (f *File) applyRelocationsALPHA(dst []byte, rels []byte) error {
1097 // 24 is the size of Rela64.
1098 if len(rels)%24 != 0 {
1099 return errors.New("length of relocation section is not a multiple of 24")
1102 symbols, _, err := f.getSymbols(SHT_SYMTAB)
1103 if err != nil {
1104 return err
1107 b := bytes.NewReader(rels)
1108 var rela Rela64
1110 for b.Len() > 0 {
1111 binary.Read(b, f.ByteOrder, &rela)
1112 symNo := rela.Info >> 32
1113 t := R_ALPHA(rela.Info & 0xffff)
1115 if symNo == 0 || symNo > uint64(len(symbols)) {
1116 continue
1118 sym := &symbols[symNo-1]
1119 if SymType(sym.Info&0xf) != STT_SECTION {
1120 // We don't handle non-section relocations for now.
1121 continue
1124 // There are relocations, so this must be a normal
1125 // object file, and we only look at section symbols,
1126 // so we assume that the symbol value is 0.
1128 switch t {
1129 case R_ALPHA_REFQUAD:
1130 if rela.Off+8 >= uint64(len(dst)) || rela.Addend < 0 {
1131 continue
1133 f.ByteOrder.PutUint64(dst[rela.Off:rela.Off+8], uint64(rela.Addend))
1134 case R_ALPHA_REFLONG:
1135 if rela.Off+4 >= uint64(len(dst)) || rela.Addend < 0 {
1136 continue
1138 f.ByteOrder.PutUint32(dst[rela.Off:rela.Off+4], uint32(rela.Addend))
1142 return nil
1145 func (f *File) DWARF() (*dwarf.Data, error) {
1146 // sectionData gets the data for s, checks its size, and
1147 // applies any applicable relations.
1148 sectionData := func(i int, s *Section) ([]byte, error) {
1149 b, err := s.Data()
1150 if err != nil && uint64(len(b)) < s.Size {
1151 return nil, err
1154 if len(b) >= 12 && string(b[:4]) == "ZLIB" {
1155 dlen := binary.BigEndian.Uint64(b[4:12])
1156 dbuf := make([]byte, dlen)
1157 r, err := zlib.NewReader(bytes.NewBuffer(b[12:]))
1158 if err != nil {
1159 return nil, err
1161 if _, err := io.ReadFull(r, dbuf); err != nil {
1162 return nil, err
1164 if err := r.Close(); err != nil {
1165 return nil, err
1167 b = dbuf
1170 for _, r := range f.Sections {
1171 if r.Type != SHT_RELA && r.Type != SHT_REL {
1172 continue
1174 if int(r.Info) != i {
1175 continue
1177 rd, err := r.Data()
1178 if err != nil {
1179 return nil, err
1181 err = f.applyRelocations(b, rd)
1182 if err != nil {
1183 return nil, err
1186 return b, nil
1189 // There are many other DWARF sections, but these
1190 // are the ones the debug/dwarf package uses.
1191 // Don't bother loading others.
1192 var dat = map[string][]byte{"abbrev": nil, "info": nil, "str": nil, "line": nil, "ranges": nil}
1193 for i, s := range f.Sections {
1194 suffix := ""
1195 switch {
1196 case strings.HasPrefix(s.Name, ".debug_"):
1197 suffix = s.Name[7:]
1198 case strings.HasPrefix(s.Name, ".zdebug_"):
1199 suffix = s.Name[8:]
1200 default:
1201 continue
1203 if _, ok := dat[suffix]; !ok {
1204 continue
1206 b, err := sectionData(i, s)
1207 if err != nil {
1208 return nil, err
1210 dat[suffix] = b
1213 d, err := dwarf.New(dat["abbrev"], nil, nil, dat["info"], dat["line"], nil, dat["ranges"], dat["str"])
1214 if err != nil {
1215 return nil, err
1218 // Look for DWARF4 .debug_types sections.
1219 for i, s := range f.Sections {
1220 if s.Name == ".debug_types" {
1221 b, err := sectionData(i, s)
1222 if err != nil {
1223 return nil, err
1226 err = d.AddTypes(fmt.Sprintf("types-%d", i), b)
1227 if err != nil {
1228 return nil, err
1233 return d, nil
1236 // Symbols returns the symbol table for f. The symbols will be listed in the order
1237 // they appear in f.
1239 // For compatibility with Go 1.0, Symbols 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) Symbols() ([]Symbol, error) {
1243 sym, _, err := f.getSymbols(SHT_SYMTAB)
1244 return sym, err
1247 // DynamicSymbols returns the dynamic symbol table for f. The symbols
1248 // will be listed in the order they appear in f.
1250 // For compatibility with Symbols, DynamicSymbols omits the null symbol at index 0.
1251 // After retrieving the symbols as symtab, an externally supplied index x
1252 // corresponds to symtab[x-1], not symtab[x].
1253 func (f *File) DynamicSymbols() ([]Symbol, error) {
1254 sym, _, err := f.getSymbols(SHT_DYNSYM)
1255 return sym, err
1258 type ImportedSymbol struct {
1259 Name string
1260 Version string
1261 Library string
1264 // ImportedSymbols returns the names of all symbols
1265 // referred to by the binary f that are expected to be
1266 // satisfied by other libraries at dynamic load time.
1267 // It does not return weak symbols.
1268 func (f *File) ImportedSymbols() ([]ImportedSymbol, error) {
1269 sym, str, err := f.getSymbols(SHT_DYNSYM)
1270 if err != nil {
1271 return nil, err
1273 f.gnuVersionInit(str)
1274 var all []ImportedSymbol
1275 for i, s := range sym {
1276 if ST_BIND(s.Info) == STB_GLOBAL && s.Section == SHN_UNDEF {
1277 all = append(all, ImportedSymbol{Name: s.Name})
1278 f.gnuVersion(i, &all[len(all)-1])
1281 return all, nil
1284 type verneed struct {
1285 File string
1286 Name string
1289 // gnuVersionInit parses the GNU version tables
1290 // for use by calls to gnuVersion.
1291 func (f *File) gnuVersionInit(str []byte) {
1292 // Accumulate verneed information.
1293 vn := f.SectionByType(SHT_GNU_VERNEED)
1294 if vn == nil {
1295 return
1297 d, _ := vn.Data()
1299 var need []verneed
1300 i := 0
1301 for {
1302 if i+16 > len(d) {
1303 break
1305 vers := f.ByteOrder.Uint16(d[i : i+2])
1306 if vers != 1 {
1307 break
1309 cnt := f.ByteOrder.Uint16(d[i+2 : i+4])
1310 fileoff := f.ByteOrder.Uint32(d[i+4 : i+8])
1311 aux := f.ByteOrder.Uint32(d[i+8 : i+12])
1312 next := f.ByteOrder.Uint32(d[i+12 : i+16])
1313 file, _ := getString(str, int(fileoff))
1315 var name string
1316 j := i + int(aux)
1317 for c := 0; c < int(cnt); c++ {
1318 if j+16 > len(d) {
1319 break
1321 // hash := f.ByteOrder.Uint32(d[j:j+4])
1322 // flags := f.ByteOrder.Uint16(d[j+4:j+6])
1323 other := f.ByteOrder.Uint16(d[j+6 : j+8])
1324 nameoff := f.ByteOrder.Uint32(d[j+8 : j+12])
1325 next := f.ByteOrder.Uint32(d[j+12 : j+16])
1326 name, _ = getString(str, int(nameoff))
1327 ndx := int(other)
1328 if ndx >= len(need) {
1329 a := make([]verneed, 2*(ndx+1))
1330 copy(a, need)
1331 need = a
1334 need[ndx] = verneed{file, name}
1335 if next == 0 {
1336 break
1338 j += int(next)
1341 if next == 0 {
1342 break
1344 i += int(next)
1347 // Versym parallels symbol table, indexing into verneed.
1348 vs := f.SectionByType(SHT_GNU_VERSYM)
1349 if vs == nil {
1350 return
1352 d, _ = vs.Data()
1354 f.gnuNeed = need
1355 f.gnuVersym = d
1358 // gnuVersion adds Library and Version information to sym,
1359 // which came from offset i of the symbol table.
1360 func (f *File) gnuVersion(i int, sym *ImportedSymbol) {
1361 // Each entry is two bytes.
1362 i = (i + 1) * 2
1363 if i >= len(f.gnuVersym) {
1364 return
1366 j := int(f.ByteOrder.Uint16(f.gnuVersym[i:]))
1367 if j < 2 || j >= len(f.gnuNeed) {
1368 return
1370 n := &f.gnuNeed[j]
1371 sym.Library = n.File
1372 sym.Version = n.Name
1375 // ImportedLibraries returns the names of all libraries
1376 // referred to by the binary f that are expected to be
1377 // linked with the binary at dynamic link time.
1378 func (f *File) ImportedLibraries() ([]string, error) {
1379 return f.DynString(DT_NEEDED)
1382 // DynString returns the strings listed for the given tag in the file's dynamic
1383 // section.
1385 // The tag must be one that takes string values: DT_NEEDED, DT_SONAME, DT_RPATH, or
1386 // DT_RUNPATH.
1387 func (f *File) DynString(tag DynTag) ([]string, error) {
1388 switch tag {
1389 case DT_NEEDED, DT_SONAME, DT_RPATH, DT_RUNPATH:
1390 default:
1391 return nil, fmt.Errorf("non-string-valued tag %v", tag)
1393 ds := f.SectionByType(SHT_DYNAMIC)
1394 if ds == nil {
1395 // not dynamic, so no libraries
1396 return nil, nil
1398 d, err := ds.Data()
1399 if err != nil {
1400 return nil, err
1402 str, err := f.stringTable(ds.Link)
1403 if err != nil {
1404 return nil, err
1406 var all []string
1407 for len(d) > 0 {
1408 var t DynTag
1409 var v uint64
1410 switch f.Class {
1411 case ELFCLASS32:
1412 t = DynTag(f.ByteOrder.Uint32(d[0:4]))
1413 v = uint64(f.ByteOrder.Uint32(d[4:8]))
1414 d = d[8:]
1415 case ELFCLASS64:
1416 t = DynTag(f.ByteOrder.Uint64(d[0:8]))
1417 v = f.ByteOrder.Uint64(d[8:16])
1418 d = d[16:]
1420 if t == tag {
1421 s, ok := getString(str, int(v))
1422 if ok {
1423 all = append(all, s)
1427 return all, nil