github.com/bgentry/go@v0.0.0-20150121062915-6cf5a733d54d/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/elf" 11 "fmt" 12 "os" 13 ) 14 15 type elfFile struct { 16 elf *elf.File 17 } 18 19 func openElf(r *os.File) (rawFile, error) { 20 f, err := elf.NewFile(r) 21 if err != nil { 22 return nil, err 23 } 24 return &elfFile{f}, nil 25 } 26 27 func (f *elfFile) symbols() ([]Sym, error) { 28 elfSyms, err := f.elf.Symbols() 29 if err != nil { 30 return nil, err 31 } 32 33 var syms []Sym 34 for _, s := range elfSyms { 35 sym := Sym{Addr: s.Value, Name: s.Name, Size: int64(s.Size), Code: '?'} 36 switch s.Section { 37 case elf.SHN_UNDEF: 38 sym.Code = 'U' 39 case elf.SHN_COMMON: 40 sym.Code = 'B' 41 default: 42 i := int(s.Section) 43 if i < 0 || i >= len(f.elf.Sections) { 44 break 45 } 46 sect := f.elf.Sections[i] 47 switch sect.Flags & (elf.SHF_WRITE | elf.SHF_ALLOC | elf.SHF_EXECINSTR) { 48 case elf.SHF_ALLOC | elf.SHF_EXECINSTR: 49 sym.Code = 'T' 50 case elf.SHF_ALLOC: 51 sym.Code = 'R' 52 case elf.SHF_ALLOC | elf.SHF_WRITE: 53 sym.Code = 'D' 54 } 55 } 56 if elf.ST_BIND(s.Info) == elf.STB_LOCAL { 57 sym.Code += 'a' - 'A' 58 } 59 syms = append(syms, sym) 60 } 61 62 return syms, nil 63 } 64 65 func (f *elfFile) pcln() (textStart uint64, symtab, pclntab []byte, err error) { 66 if sect := f.elf.Section(".text"); sect != nil { 67 textStart = sect.Addr 68 } 69 if sect := f.elf.Section(".gosymtab"); sect != nil { 70 if symtab, err = sect.Data(); err != nil { 71 return 0, nil, nil, err 72 } 73 } 74 if sect := f.elf.Section(".gopclntab"); sect != nil { 75 if pclntab, err = sect.Data(); err != nil { 76 return 0, nil, nil, err 77 } 78 } 79 return textStart, symtab, pclntab, nil 80 } 81 82 func (f *elfFile) text() (textStart uint64, text []byte, err error) { 83 sect := f.elf.Section(".text") 84 if sect == nil { 85 return 0, nil, fmt.Errorf("text section not found") 86 } 87 textStart = sect.Addr 88 text, err = sect.Data() 89 return 90 } 91 92 func (f *elfFile) goarch() string { 93 switch f.elf.Machine { 94 case elf.EM_386: 95 return "386" 96 case elf.EM_X86_64: 97 return "amd64" 98 case elf.EM_ARM: 99 return "arm" 100 case elf.EM_PPC64: 101 return "ppc64" 102 } 103 return "" 104 }