OpenCores
URL https://opencores.org/ocsvn/openrisc/openrisc/trunk

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [gnu-dev/] [or1k-gcc/] [libgo/] [go/] [debug/] [elf/] [file.go] - Blame information for rev 750

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 747 jeremybenn
// 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
}
35
 
36
// A File represents an open ELF file.
37
type File struct {
38
        FileHeader
39
        Sections  []*Section
40
        Progs     []*Prog
41
        closer    io.Closer
42
        gnuNeed   []verneed
43
        gnuVersym []byte
44
}
45
 
46
// A SectionHeader represents a single ELF section header.
47
type SectionHeader struct {
48
        Name      string
49
        Type      SectionType
50
        Flags     SectionFlag
51
        Addr      uint64
52
        Offset    uint64
53
        Size      uint64
54
        Link      uint32
55
        Info      uint32
56
        Addralign uint64
57
        Entsize   uint64
58
}
59
 
60
// A Section represents a single section in an ELF file.
61
type Section struct {
62
        SectionHeader
63
 
64
        // Embed ReaderAt for ReadAt method.
65
        // Do not embed SectionReader directly
66
        // to avoid having Read and Seek.
67
        // If a client wants Read and Seek it must use
68
        // Open() to avoid fighting over the seek offset
69
        // with other clients.
70
        io.ReaderAt
71
        sr *io.SectionReader
72
}
73
 
74
// Data reads and returns the contents of the ELF section.
75
func (s *Section) Data() ([]byte, error) {
76
        dat := make([]byte, s.sr.Size())
77
        n, err := s.sr.ReadAt(dat, 0)
78
        return dat[0:n], err
79
}
80
 
81
// stringTable reads and returns the string table given by the
82
// specified link value.
83
func (f *File) stringTable(link uint32) ([]byte, error) {
84
        if link <= 0 || link >= uint32(len(f.Sections)) {
85
                return nil, errors.New("section has invalid string table link")
86
        }
87
        return f.Sections[link].Data()
88
}
89
 
90
// Open returns a new ReadSeeker reading the ELF section.
91
func (s *Section) Open() io.ReadSeeker { return io.NewSectionReader(s.sr, 0, 1<<63-1) }
92
 
93
// A ProgHeader represents a single ELF program header.
94
type ProgHeader struct {
95
        Type   ProgType
96
        Flags  ProgFlag
97
        Off    uint64
98
        Vaddr  uint64
99
        Paddr  uint64
100
        Filesz uint64
101
        Memsz  uint64
102
        Align  uint64
103
}
104
 
105
// A Prog represents a single ELF program header in an ELF binary.
106
type Prog struct {
107
        ProgHeader
108
 
109
        // Embed ReaderAt for ReadAt method.
110
        // Do not embed SectionReader directly
111
        // to avoid having Read and Seek.
112
        // If a client wants Read and Seek it must use
113
        // Open() to avoid fighting over the seek offset
114
        // with other clients.
115
        io.ReaderAt
116
        sr *io.SectionReader
117
}
118
 
119
// Open returns a new ReadSeeker reading the ELF program body.
120
func (p *Prog) Open() io.ReadSeeker { return io.NewSectionReader(p.sr, 0, 1<<63-1) }
121
 
122
// A Symbol represents an entry in an ELF symbol table section.
123
type Symbol struct {
124
        Name        string
125
        Info, Other byte
126
        Section     SectionIndex
127
        Value, Size uint64
128
}
129
 
130
/*
131
 * ELF reader
132
 */
133
 
134
type FormatError struct {
135
        off int64
136
        msg string
137
        val interface{}
138
}
139
 
140
func (e *FormatError) Error() string {
141
        msg := e.msg
142
        if e.val != nil {
143
                msg += fmt.Sprintf(" '%v' ", e.val)
144
        }
145
        msg += fmt.Sprintf("in record at byte %#x", e.off)
146
        return msg
147
}
148
 
149
// Open opens the named file using os.Open and prepares it for use as an ELF binary.
150
func Open(name string) (*File, error) {
151
        f, err := os.Open(name)
152
        if err != nil {
153
                return nil, err
154
        }
155
        ff, err := NewFile(f)
156
        if err != nil {
157
                f.Close()
158
                return nil, err
159
        }
160
        ff.closer = f
161
        return ff, nil
162
}
163
 
164
// Close closes the File.
165
// If the File was created using NewFile directly instead of Open,
166
// Close has no effect.
167
func (f *File) Close() error {
168
        var err error
169
        if f.closer != nil {
170
                err = f.closer.Close()
171
                f.closer = nil
172
        }
173
        return err
174
}
175
 
176
// SectionByType returns the first section in f with the
177
// given type, or nil if there is no such section.
178
func (f *File) SectionByType(typ SectionType) *Section {
179
        for _, s := range f.Sections {
180
                if s.Type == typ {
181
                        return s
182
                }
183
        }
184
        return nil
185
}
186
 
187
// NewFile creates a new File for accessing an ELF binary in an underlying reader.
188
// The ELF binary is expected to start at position 0 in the ReaderAt.
189
func NewFile(r io.ReaderAt) (*File, error) {
190
        sr := io.NewSectionReader(r, 0, 1<<63-1)
191
        // Read and decode ELF identifier
192
        var ident [16]uint8
193
        if _, err := r.ReadAt(ident[0:], 0); err != nil {
194
                return nil, err
195
        }
196
        if ident[0] != '\x7f' || ident[1] != 'E' || ident[2] != 'L' || ident[3] != 'F' {
197
                return nil, &FormatError{0, "bad magic number", ident[0:4]}
198
        }
199
 
200
        f := new(File)
201
        f.Class = Class(ident[EI_CLASS])
202
        switch f.Class {
203
        case ELFCLASS32:
204
        case ELFCLASS64:
205
                // ok
206
        default:
207
                return nil, &FormatError{0, "unknown ELF class", f.Class}
208
        }
209
 
210
        f.Data = Data(ident[EI_DATA])
211
        switch f.Data {
212
        case ELFDATA2LSB:
213
                f.ByteOrder = binary.LittleEndian
214
        case ELFDATA2MSB:
215
                f.ByteOrder = binary.BigEndian
216
        default:
217
                return nil, &FormatError{0, "unknown ELF data encoding", f.Data}
218
        }
219
 
220
        f.Version = Version(ident[EI_VERSION])
221
        if f.Version != EV_CURRENT {
222
                return nil, &FormatError{0, "unknown ELF version", f.Version}
223
        }
224
 
225
        f.OSABI = OSABI(ident[EI_OSABI])
226
        f.ABIVersion = ident[EI_ABIVERSION]
227
 
228
        // Read ELF file header
229
        var phoff int64
230
        var phentsize, phnum int
231
        var shoff int64
232
        var shentsize, shnum, shstrndx int
233
        shstrndx = -1
234
        switch f.Class {
235
        case ELFCLASS32:
236
                hdr := new(Header32)
237
                sr.Seek(0, os.SEEK_SET)
238
                if err := binary.Read(sr, f.ByteOrder, hdr); err != nil {
239
                        return nil, err
240
                }
241
                f.Type = Type(hdr.Type)
242
                f.Machine = Machine(hdr.Machine)
243
                if v := Version(hdr.Version); v != f.Version {
244
                        return nil, &FormatError{0, "mismatched ELF version", v}
245
                }
246
                phoff = int64(hdr.Phoff)
247
                phentsize = int(hdr.Phentsize)
248
                phnum = int(hdr.Phnum)
249
                shoff = int64(hdr.Shoff)
250
                shentsize = int(hdr.Shentsize)
251
                shnum = int(hdr.Shnum)
252
                shstrndx = int(hdr.Shstrndx)
253
        case ELFCLASS64:
254
                hdr := new(Header64)
255
                sr.Seek(0, os.SEEK_SET)
256
                if err := binary.Read(sr, f.ByteOrder, hdr); err != nil {
257
                        return nil, err
258
                }
259
                f.Type = Type(hdr.Type)
260
                f.Machine = Machine(hdr.Machine)
261
                if v := Version(hdr.Version); v != f.Version {
262
                        return nil, &FormatError{0, "mismatched ELF version", v}
263
                }
264
                phoff = int64(hdr.Phoff)
265
                phentsize = int(hdr.Phentsize)
266
                phnum = int(hdr.Phnum)
267
                shoff = int64(hdr.Shoff)
268
                shentsize = int(hdr.Shentsize)
269
                shnum = int(hdr.Shnum)
270
                shstrndx = int(hdr.Shstrndx)
271
        }
272
        if shstrndx < 0 || shstrndx >= shnum {
273
                return nil, &FormatError{0, "invalid ELF shstrndx", shstrndx}
274
        }
275
 
276
        // Read program headers
277
        f.Progs = make([]*Prog, phnum)
278
        for i := 0; i < phnum; i++ {
279
                off := phoff + int64(i)*int64(phentsize)
280
                sr.Seek(off, os.SEEK_SET)
281
                p := new(Prog)
282
                switch f.Class {
283
                case ELFCLASS32:
284
                        ph := new(Prog32)
285
                        if err := binary.Read(sr, f.ByteOrder, ph); err != nil {
286
                                return nil, err
287
                        }
288
                        p.ProgHeader = ProgHeader{
289
                                Type:   ProgType(ph.Type),
290
                                Flags:  ProgFlag(ph.Flags),
291
                                Off:    uint64(ph.Off),
292
                                Vaddr:  uint64(ph.Vaddr),
293
                                Paddr:  uint64(ph.Paddr),
294
                                Filesz: uint64(ph.Filesz),
295
                                Memsz:  uint64(ph.Memsz),
296
                                Align:  uint64(ph.Align),
297
                        }
298
                case ELFCLASS64:
299
                        ph := new(Prog64)
300
                        if err := binary.Read(sr, f.ByteOrder, ph); err != nil {
301
                                return nil, err
302
                        }
303
                        p.ProgHeader = ProgHeader{
304
                                Type:   ProgType(ph.Type),
305
                                Flags:  ProgFlag(ph.Flags),
306
                                Off:    uint64(ph.Off),
307
                                Vaddr:  uint64(ph.Vaddr),
308
                                Paddr:  uint64(ph.Paddr),
309
                                Filesz: uint64(ph.Filesz),
310
                                Memsz:  uint64(ph.Memsz),
311
                                Align:  uint64(ph.Align),
312
                        }
313
                }
314
                p.sr = io.NewSectionReader(r, int64(p.Off), int64(p.Filesz))
315
                p.ReaderAt = p.sr
316
                f.Progs[i] = p
317
        }
318
 
319
        // Read section headers
320
        f.Sections = make([]*Section, shnum)
321
        names := make([]uint32, shnum)
322
        for i := 0; i < shnum; i++ {
323
                off := shoff + int64(i)*int64(shentsize)
324
                sr.Seek(off, os.SEEK_SET)
325
                s := new(Section)
326
                switch f.Class {
327
                case ELFCLASS32:
328
                        sh := new(Section32)
329
                        if err := binary.Read(sr, f.ByteOrder, sh); err != nil {
330
                                return nil, err
331
                        }
332
                        names[i] = sh.Name
333
                        s.SectionHeader = SectionHeader{
334
                                Type:      SectionType(sh.Type),
335
                                Flags:     SectionFlag(sh.Flags),
336
                                Addr:      uint64(sh.Addr),
337
                                Offset:    uint64(sh.Off),
338
                                Size:      uint64(sh.Size),
339
                                Link:      uint32(sh.Link),
340
                                Info:      uint32(sh.Info),
341
                                Addralign: uint64(sh.Addralign),
342
                                Entsize:   uint64(sh.Entsize),
343
                        }
344
                case ELFCLASS64:
345
                        sh := new(Section64)
346
                        if err := binary.Read(sr, f.ByteOrder, sh); err != nil {
347
                                return nil, err
348
                        }
349
                        names[i] = sh.Name
350
                        s.SectionHeader = SectionHeader{
351
                                Type:      SectionType(sh.Type),
352
                                Flags:     SectionFlag(sh.Flags),
353
                                Offset:    uint64(sh.Off),
354
                                Size:      uint64(sh.Size),
355
                                Addr:      uint64(sh.Addr),
356
                                Link:      uint32(sh.Link),
357
                                Info:      uint32(sh.Info),
358
                                Addralign: uint64(sh.Addralign),
359
                                Entsize:   uint64(sh.Entsize),
360
                        }
361
                }
362
                s.sr = io.NewSectionReader(r, int64(s.Offset), int64(s.Size))
363
                s.ReaderAt = s.sr
364
                f.Sections[i] = s
365
        }
366
 
367
        // Load section header string table.
368
        shstrtab, err := f.Sections[shstrndx].Data()
369
        if err != nil {
370
                return nil, err
371
        }
372
        for i, s := range f.Sections {
373
                var ok bool
374
                s.Name, ok = getString(shstrtab, int(names[i]))
375
                if !ok {
376
                        return nil, &FormatError{shoff + int64(i*shentsize), "bad section name index", names[i]}
377
                }
378
        }
379
 
380
        return f, nil
381
}
382
 
383
// getSymbols returns a slice of Symbols from parsing the symbol table
384
// with the given type, along with the associated string table.
385
func (f *File) getSymbols(typ SectionType) ([]Symbol, []byte, error) {
386
        switch f.Class {
387
        case ELFCLASS64:
388
                return f.getSymbols64(typ)
389
 
390
        case ELFCLASS32:
391
                return f.getSymbols32(typ)
392
        }
393
 
394
        return nil, nil, errors.New("not implemented")
395
}
396
 
397
func (f *File) getSymbols32(typ SectionType) ([]Symbol, []byte, error) {
398
        symtabSection := f.SectionByType(typ)
399
        if symtabSection == nil {
400
                return nil, nil, errors.New("no symbol section")
401
        }
402
 
403
        data, err := symtabSection.Data()
404
        if err != nil {
405
                return nil, nil, errors.New("cannot load symbol section")
406
        }
407
        symtab := bytes.NewBuffer(data)
408
        if symtab.Len()%Sym32Size != 0 {
409
                return nil, nil, errors.New("length of symbol section is not a multiple of SymSize")
410
        }
411
 
412
        strdata, err := f.stringTable(symtabSection.Link)
413
        if err != nil {
414
                return nil, nil, errors.New("cannot load string table section")
415
        }
416
 
417
        // The first entry is all zeros.
418
        var skip [Sym32Size]byte
419
        symtab.Read(skip[0:])
420
 
421
        symbols := make([]Symbol, symtab.Len()/Sym32Size)
422
 
423
        i := 0
424
        var sym Sym32
425
        for symtab.Len() > 0 {
426
                binary.Read(symtab, f.ByteOrder, &sym)
427
                str, _ := getString(strdata, int(sym.Name))
428
                symbols[i].Name = str
429
                symbols[i].Info = sym.Info
430
                symbols[i].Other = sym.Other
431
                symbols[i].Section = SectionIndex(sym.Shndx)
432
                symbols[i].Value = uint64(sym.Value)
433
                symbols[i].Size = uint64(sym.Size)
434
                i++
435
        }
436
 
437
        return symbols, strdata, nil
438
}
439
 
440
func (f *File) getSymbols64(typ SectionType) ([]Symbol, []byte, error) {
441
        symtabSection := f.SectionByType(typ)
442
        if symtabSection == nil {
443
                return nil, nil, errors.New("no symbol section")
444
        }
445
 
446
        data, err := symtabSection.Data()
447
        if err != nil {
448
                return nil, nil, errors.New("cannot load symbol section")
449
        }
450
        symtab := bytes.NewBuffer(data)
451
        if symtab.Len()%Sym64Size != 0 {
452
                return nil, nil, errors.New("length of symbol section is not a multiple of Sym64Size")
453
        }
454
 
455
        strdata, err := f.stringTable(symtabSection.Link)
456
        if err != nil {
457
                return nil, nil, errors.New("cannot load string table section")
458
        }
459
 
460
        // The first entry is all zeros.
461
        var skip [Sym64Size]byte
462
        symtab.Read(skip[0:])
463
 
464
        symbols := make([]Symbol, symtab.Len()/Sym64Size)
465
 
466
        i := 0
467
        var sym Sym64
468
        for symtab.Len() > 0 {
469
                binary.Read(symtab, f.ByteOrder, &sym)
470
                str, _ := getString(strdata, int(sym.Name))
471
                symbols[i].Name = str
472
                symbols[i].Info = sym.Info
473
                symbols[i].Other = sym.Other
474
                symbols[i].Section = SectionIndex(sym.Shndx)
475
                symbols[i].Value = sym.Value
476
                symbols[i].Size = sym.Size
477
                i++
478
        }
479
 
480
        return symbols, strdata, nil
481
}
482
 
483
// getString extracts a string from an ELF string table.
484
func getString(section []byte, start int) (string, bool) {
485
        if start < 0 || start >= len(section) {
486
                return "", false
487
        }
488
 
489
        for end := start; end < len(section); end++ {
490
                if section[end] == 0 {
491
                        return string(section[start:end]), true
492
                }
493
        }
494
        return "", false
495
}
496
 
497
// Section returns a section with the given name, or nil if no such
498
// section exists.
499
func (f *File) Section(name string) *Section {
500
        for _, s := range f.Sections {
501
                if s.Name == name {
502
                        return s
503
                }
504
        }
505
        return nil
506
}
507
 
508
// applyRelocations applies relocations to dst. rels is a relocations section
509
// in RELA format.
510
func (f *File) applyRelocations(dst []byte, rels []byte) error {
511
        if f.Class == ELFCLASS64 && f.Machine == EM_X86_64 {
512
                return f.applyRelocationsAMD64(dst, rels)
513
        }
514
 
515
        return errors.New("not implemented")
516
}
517
 
518
func (f *File) applyRelocationsAMD64(dst []byte, rels []byte) error {
519
        if len(rels)%Sym64Size != 0 {
520
                return errors.New("length of relocation section is not a multiple of Sym64Size")
521
        }
522
 
523
        symbols, _, err := f.getSymbols(SHT_SYMTAB)
524
        if err != nil {
525
                return err
526
        }
527
 
528
        b := bytes.NewBuffer(rels)
529
        var rela Rela64
530
 
531
        for b.Len() > 0 {
532
                binary.Read(b, f.ByteOrder, &rela)
533
                symNo := rela.Info >> 32
534
                t := R_X86_64(rela.Info & 0xffff)
535
 
536
                if symNo >= uint64(len(symbols)) {
537
                        continue
538
                }
539
                sym := &symbols[symNo]
540
                if SymType(sym.Info&0xf) != STT_SECTION {
541
                        // We don't handle non-section relocations for now.
542
                        continue
543
                }
544
 
545
                switch t {
546
                case R_X86_64_64:
547
                        if rela.Off+8 >= uint64(len(dst)) || rela.Addend < 0 {
548
                                continue
549
                        }
550
                        f.ByteOrder.PutUint64(dst[rela.Off:rela.Off+8], uint64(rela.Addend))
551
                case R_X86_64_32:
552
                        if rela.Off+4 >= uint64(len(dst)) || rela.Addend < 0 {
553
                                continue
554
                        }
555
                        f.ByteOrder.PutUint32(dst[rela.Off:rela.Off+4], uint32(rela.Addend))
556
                }
557
        }
558
 
559
        return nil
560
}
561
 
562
func (f *File) DWARF() (*dwarf.Data, error) {
563
        // There are many other DWARF sections, but these
564
        // are the required ones, and the debug/dwarf package
565
        // does not use the others, so don't bother loading them.
566
        var names = [...]string{"abbrev", "info", "str"}
567
        var dat [len(names)][]byte
568
        for i, name := range names {
569
                name = ".debug_" + name
570
                s := f.Section(name)
571
                if s == nil {
572
                        continue
573
                }
574
                b, err := s.Data()
575
                if err != nil && uint64(len(b)) < s.Size {
576
                        return nil, err
577
                }
578
                dat[i] = b
579
        }
580
 
581
        // If there's a relocation table for .debug_info, we have to process it
582
        // now otherwise the data in .debug_info is invalid for x86-64 objects.
583
        rela := f.Section(".rela.debug_info")
584
        if rela != nil && rela.Type == SHT_RELA && f.Machine == EM_X86_64 {
585
                data, err := rela.Data()
586
                if err != nil {
587
                        return nil, err
588
                }
589
                err = f.applyRelocations(dat[1], data)
590
                if err != nil {
591
                        return nil, err
592
                }
593
        }
594
 
595
        abbrev, info, str := dat[0], dat[1], dat[2]
596
        return dwarf.New(abbrev, nil, nil, info, nil, nil, nil, str)
597
}
598
 
599
// Symbols returns the symbol table for f.
600
func (f *File) Symbols() ([]Symbol, error) {
601
        sym, _, err := f.getSymbols(SHT_SYMTAB)
602
        return sym, err
603
}
604
 
605
type ImportedSymbol struct {
606
        Name    string
607
        Version string
608
        Library string
609
}
610
 
611
// ImportedSymbols returns the names of all symbols
612
// referred to by the binary f that are expected to be
613
// satisfied by other libraries at dynamic load time.
614
// It does not return weak symbols.
615
func (f *File) ImportedSymbols() ([]ImportedSymbol, error) {
616
        sym, str, err := f.getSymbols(SHT_DYNSYM)
617
        if err != nil {
618
                return nil, err
619
        }
620
        f.gnuVersionInit(str)
621
        var all []ImportedSymbol
622
        for i, s := range sym {
623
                if ST_BIND(s.Info) == STB_GLOBAL && s.Section == SHN_UNDEF {
624
                        all = append(all, ImportedSymbol{Name: s.Name})
625
                        f.gnuVersion(i, &all[len(all)-1])
626
                }
627
        }
628
        return all, nil
629
}
630
 
631
type verneed struct {
632
        File string
633
        Name string
634
}
635
 
636
// gnuVersionInit parses the GNU version tables
637
// for use by calls to gnuVersion.
638
func (f *File) gnuVersionInit(str []byte) {
639
        // Accumulate verneed information.
640
        vn := f.SectionByType(SHT_GNU_VERNEED)
641
        if vn == nil {
642
                return
643
        }
644
        d, _ := vn.Data()
645
 
646
        var need []verneed
647
        i := 0
648
        for {
649
                if i+16 > len(d) {
650
                        break
651
                }
652
                vers := f.ByteOrder.Uint16(d[i : i+2])
653
                if vers != 1 {
654
                        break
655
                }
656
                cnt := f.ByteOrder.Uint16(d[i+2 : i+4])
657
                fileoff := f.ByteOrder.Uint32(d[i+4 : i+8])
658
                aux := f.ByteOrder.Uint32(d[i+8 : i+12])
659
                next := f.ByteOrder.Uint32(d[i+12 : i+16])
660
                file, _ := getString(str, int(fileoff))
661
 
662
                var name string
663
                j := i + int(aux)
664
                for c := 0; c < int(cnt); c++ {
665
                        if j+16 > len(d) {
666
                                break
667
                        }
668
                        // hash := f.ByteOrder.Uint32(d[j:j+4])
669
                        // flags := f.ByteOrder.Uint16(d[j+4:j+6])
670
                        other := f.ByteOrder.Uint16(d[j+6 : j+8])
671
                        nameoff := f.ByteOrder.Uint32(d[j+8 : j+12])
672
                        next := f.ByteOrder.Uint32(d[j+12 : j+16])
673
                        name, _ = getString(str, int(nameoff))
674
                        ndx := int(other)
675
                        if ndx >= len(need) {
676
                                a := make([]verneed, 2*(ndx+1))
677
                                copy(a, need)
678
                                need = a
679
                        }
680
 
681
                        need[ndx] = verneed{file, name}
682
                        if next == 0 {
683
                                break
684
                        }
685
                        j += int(next)
686
                }
687
 
688
                if next == 0 {
689
                        break
690
                }
691
                i += int(next)
692
        }
693
 
694
        // Versym parallels symbol table, indexing into verneed.
695
        vs := f.SectionByType(SHT_GNU_VERSYM)
696
        if vs == nil {
697
                return
698
        }
699
        d, _ = vs.Data()
700
 
701
        f.gnuNeed = need
702
        f.gnuVersym = d
703
}
704
 
705
// gnuVersion adds Library and Version information to sym,
706
// which came from offset i of the symbol table.
707
func (f *File) gnuVersion(i int, sym *ImportedSymbol) {
708
        // Each entry is two bytes; skip undef entry at beginning.
709
        i = (i + 1) * 2
710
        if i >= len(f.gnuVersym) {
711
                return
712
        }
713
        j := int(f.ByteOrder.Uint16(f.gnuVersym[i:]))
714
        if j < 2 || j >= len(f.gnuNeed) {
715
                return
716
        }
717
        n := &f.gnuNeed[j]
718
        sym.Library = n.File
719
        sym.Version = n.Name
720
}
721
 
722
// ImportedLibraries returns the names of all libraries
723
// referred to by the binary f that are expected to be
724
// linked with the binary at dynamic link time.
725
func (f *File) ImportedLibraries() ([]string, error) {
726
        ds := f.SectionByType(SHT_DYNAMIC)
727
        if ds == nil {
728
                // not dynamic, so no libraries
729
                return nil, nil
730
        }
731
        d, err := ds.Data()
732
        if err != nil {
733
                return nil, err
734
        }
735
        str, err := f.stringTable(ds.Link)
736
        if err != nil {
737
                return nil, err
738
        }
739
        var all []string
740
        for len(d) > 0 {
741
                var tag DynTag
742
                var value uint64
743
                switch f.Class {
744
                case ELFCLASS32:
745
                        tag = DynTag(f.ByteOrder.Uint32(d[0:4]))
746
                        value = uint64(f.ByteOrder.Uint32(d[4:8]))
747
                        d = d[8:]
748
                case ELFCLASS64:
749
                        tag = DynTag(f.ByteOrder.Uint64(d[0:8]))
750
                        value = f.ByteOrder.Uint64(d[8:16])
751
                        d = d[16:]
752
                }
753
                if tag == DT_NEEDED {
754
                        s, ok := getString(str, int(value))
755
                        if ok {
756
                                all = append(all, s)
757
                        }
758
                }
759
        }
760
 
761
        return all, nil
762
}

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.