github.com/sbinet/go@v0.0.0-20160827155028-54d7de7dd62b/src/cmd/internal/objfile/elf.go (about) 1 // Copyright 2013 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 // Parsing of ELF executables (Linux, FreeBSD, and so on). 6 7 package objfile 8 9 import ( 10 "debug/dwarf" 11 "debug/elf" 12 "fmt" 13 "os" 14 ) 15 16 type elfFile struct { 17 elf *elf.File 18 } 19 20 func openElf(r *os.File) (rawFile, error) { 21 f, err := elf.NewFile(r) 22 if err != nil { 23 return nil, err 24 } 25 return &elfFile{f}, nil 26 } 27 28 func (f *elfFile) symbols() ([]Sym, error) { 29 elfSyms, err := f.elf.Symbols() 30 if err != nil { 31 return nil, err 32 } 33 34 var syms []Sym 35 for _, s := range elfSyms { 36 sym := Sym{Addr: s.Value, Name: s.Name, Size: int64(s.Size), Code: '?'} 37 switch s.Section { 38 case elf.SHN_UNDEF: 39 sym.Code = 'U' 40 case elf.SHN_COMMON: 41 sym.Code = 'B' 42 default: 43 i := int(s.Section) 44 if i < 0 || i >= len(f.elf.Sections) { 45 break 46 } 47 sect := f.elf.Sections[i] 48 switch sect.Flags & (elf.SHF_WRITE | elf.SHF_ALLOC | elf.SHF_EXECINSTR) { 49 case elf.SHF_ALLOC | elf.SHF_EXECINSTR: 50 sym.Code = 'T' 51 case elf.SHF_ALLOC: 52 sym.Code = 'R' 53 case elf.SHF_ALLOC | elf.SHF_WRITE: 54 sym.Code = 'D' 55 } 56 } 57 if elf.ST_BIND(s.Info) == elf.STB_LOCAL { 58 sym.Code += 'a' - 'A' 59 } 60 syms = append(syms, sym) 61 } 62 63 return syms, nil 64 } 65 66 func (f *elfFile) pcln() (textStart uint64, symtab, pclntab []byte, err error) { 67 if sect := f.elf.Section(".text"); sect != nil { 68 textStart = sect.Addr 69 } 70 if sect := f.elf.Section(".gosymtab"); sect != nil { 71 if symtab, err = sect.Data(); err != nil { 72 return 0, nil, nil, err 73 } 74 } 75 if sect := f.elf.Section(".gopclntab"); sect != nil { 76 if pclntab, err = sect.Data(); err != nil { 77 return 0, nil, nil, err 78 } 79 } 80 return textStart, symtab, pclntab, nil 81 } 82 83 func (f *elfFile) text() (textStart uint64, text []byte, err error) { 84 sect := f.elf.Section(".text") 85 if sect == nil { 86 return 0, nil, fmt.Errorf("text section not found") 87 } 88 textStart = sect.Addr 89 text, err = sect.Data() 90 return 91 } 92 93 func (f *elfFile) goarch() string { 94 switch f.elf.Machine { 95 case elf.EM_386: 96 return "386" 97 case elf.EM_X86_64: 98 return "amd64" 99 case elf.EM_ARM: 100 return "arm" 101 case elf.EM_PPC64: 102 return "ppc64" 103 case elf.EM_S390: 104 return "s390x" 105 } 106 return "" 107 } 108 109 func (f *elfFile) loadAddress() (uint64, error) { 110 for _, p := range f.elf.Progs { 111 if p.Type == elf.PT_LOAD { 112 return p.Vaddr, nil 113 } 114 } 115 return 0, fmt.Errorf("unknown load address") 116 } 117 118 func (f *elfFile) dwarf() (*dwarf.Data, error) { 119 return f.elf.DWARF() 120 }