Source file src/pkg/debug/elf/file.go
1
2
3
4
5
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
21
22
23
24
25 const (
26 seekStart int = 0
27 seekCurrent int = 1
28 seekEnd int = 2
29 )
30
31
32
33
36
37
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
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
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
74
75
76
77 FileSize uint64
78 }
79
80
81 type Section struct {
82 SectionHeader
83
84
85
86
87
88
89
90
91
92
93
94 io.ReaderAt
95 sr *io.SectionReader
96
97 compressionType CompressionType
98 compressionOffset int64
99 }
100
101
102
103
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
111
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
120
121
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
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
152 type Prog struct {
153 ProgHeader
154
155
156
157
158
159
160
161 io.ReaderAt
162 sr *io.SectionReader
163 }
164
165
166 func (p *Prog) Open() io.ReadSeeker { return io.NewSectionReader(p.sr, 0, 1<<63-1) }
167
168
169 type Symbol struct {
170 Name string
171 Info, Other byte
172 Section SectionIndex
173 Value, Size uint64
174
175
176
177 Version string
178 Library string
179 }
180
181
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
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
216
217
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
228
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
239
240 func NewFile(r io.ReaderAt) (*File, error) {
241 sr := io.NewSectionReader(r, 0, 1<<63-1)
242
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
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
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
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
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
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
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
472
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
486
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
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
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
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
590
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
601
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
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
656 continue
657 }
658
659
660
661
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
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
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
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
780 continue
781 }
782
783
784
785
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
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
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
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
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
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
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
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
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
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
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
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
1135
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
1178
1179
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
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
1223
1224
1225
1226
1227
1228 func (f *File) Symbols() ([]Symbol, error) {
1229 sym, _, err := f.getSymbols(SHT_SYMTAB)
1230 return sym, err
1231 }
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
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
1262
1263
1264
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
1288
1289 func (f *File) gnuVersionInit(str []byte) bool {
1290 if f.gnuNeed != nil {
1291
1292 return true
1293 }
1294
1295
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
1325
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
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
1363
1364 func (f *File) gnuVersion(i int) (library string, version string) {
1365
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
1379
1380
1381 func (f *File) ImportedLibraries() ([]string, error) {
1382 return f.DynString(DT_NEEDED)
1383 }
1384
1385
1386
1387
1388
1389
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
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