func hasDynTag(f *elf.File, tag elf.DynTag) bool { ds := f.SectionByType(elf.SHT_DYNAMIC) if ds == nil { return false } d, err := ds.Data() if err != nil { return false } for len(d) > 0 { var t elf.DynTag switch f.Class { case elf.ELFCLASS32: t = elf.DynTag(f.ByteOrder.Uint32(d[0:4])) d = d[8:] case elf.ELFCLASS64: t = elf.DynTag(f.ByteOrder.Uint64(d[0:8])) d = d[16:] } if t == tag { return true } } return false }
func hasDynTag(t *testing.T, f *elf.File, tag elf.DynTag) bool { ds := f.SectionByType(elf.SHT_DYNAMIC) if ds == nil { t.Error("no SHT_DYNAMIC section") return false } d, err := ds.Data() if err != nil { t.Errorf("can't read SHT_DYNAMIC contents: %v", err) return false } for len(d) > 0 { var t elf.DynTag switch f.Class { case elf.ELFCLASS32: t = elf.DynTag(f.ByteOrder.Uint32(d[:4])) d = d[8:] case elf.ELFCLASS64: t = elf.DynTag(f.ByteOrder.Uint64(d[:8])) d = d[16:] } if t == tag { return true } } return false }
// The shared library contains a note containing the ABI hash that is mapped into // memory and there is a local symbol called go.link.abihashbytes that points 16 // bytes into it. func testABIHashNote(t *testing.T, f *elf.File, note *note) { if note.section.Flags != elf.SHF_ALLOC { t.Errorf("abi hash section has flags %v", note.section.Flags) } if !isOffsetLoaded(f, note.section.Offset) { t.Errorf("abihash section not contained in PT_LOAD segment") } var hashbytes elf.Symbol symbols, err := f.Symbols() if err != nil { t.Errorf("error reading symbols %v", err) return } for _, sym := range symbols { if sym.Name == "go.link.abihashbytes" { hashbytes = sym } } if hashbytes.Name == "" { t.Errorf("no symbol called go.link.abihashbytes") return } if elf.ST_BIND(hashbytes.Info) != elf.STB_LOCAL { t.Errorf("%s has incorrect binding %v", hashbytes.Name, elf.ST_BIND(hashbytes.Info)) } if f.Sections[hashbytes.Section] != note.section { t.Errorf("%s has incorrect section %v", hashbytes.Name, f.Sections[hashbytes.Section].Name) } if hashbytes.Value-note.section.Addr != 16 { t.Errorf("%s has incorrect offset into section %d", hashbytes.Name, hashbytes.Value-note.section.Addr) } }
func haveDynTag(file *elf.File, tag elf.DynTag) bool { if section := file.Section(".dynamic"); section != nil { reader := io.NewSectionReader(section, 0, int64(section.Size)) switch file.Machine { case elf.EM_X86_64: for { var entry elf.Dyn64 if err := binary.Read(reader, binary.LittleEndian, &entry); err != io.EOF { if elf.DynTag(entry.Tag) == tag { return true } } else { break } } case elf.EM_386: for { var entry elf.Dyn32 if err := binary.Read(reader, binary.LittleEndian, &entry); err != io.EOF { if elf.DynTag(entry.Tag) == tag { return true } } else { break } } } } return false }
func dump_symbols(file *elf.File) { fmt.Printf("Symbols:\n") symbols, _ := file.Symbols() for _, e := range symbols { if !strings.EqualFold(e.Name, "") { fmt.Printf("\t%s\n", e.Name) } } }
func producer(debugfile *elf.File, dwzfile *elf.File, debug_package string, debug_file string) []string { var output []string // iterate over all CUs present in debugfile d, e := debugfile.DWARF() // increases memory usage by 2x to 3x! if e != nil { log.Println(e, debug_package, debug_file) return output } reader := d.Reader() for { entry, err := reader.Next() if err != nil { log.Println(err, debug_file, debug_package) break } if entry == nil { break } if entry.Tag == dwarf.TagCompileUnit { for _, f := range entry.Field { if f.Attr == dwarf.AttrName { switch f.Val.(type) { case string: output = append(output, f.Val.(string)) case dwarf.OffsetStrpAlt: output = append(output, (string)(f.Val.(dwarf.OffsetStrpAlt))) case dwarf.OffsetRefAlt: log.Panic("DW_FORM_GNU_ref_alt handling missing for dwarf.AttrName ;(") default: panic("form unhandled for dwarf.AttrName, expect the unexpected ;(") } } else if f.Attr == dwarf.AttrProducer { switch f.Val.(type) { case string: output = append(output, f.Val.(string)) case dwarf.OffsetStrpAlt: output = append(output, dwzparser(dwzfile, (int64)(f.Val.(dwarf.OffsetStrpAlt)), debug_package, debug_file)) case dwarf.OffsetRefAlt: log.Panic("DW_FORM_GNU_ref_alt handling missing for dwarf.AttrProducer ;(") default: panic("form unhandled for dwarf.AttrProducer, expect the unexpected ;(") } } } } } // log.Println(output) return output }
func getSectionData(f *elf.File, name string) []byte { section := f.Section(name) if section == nil { log.Fatalf("failed getting section %s", name) } data, err := section.Data() if err != nil { log.Fatalf("failed getting section %s data: %s", name, err) } return data }
func GetSymbols(e *elf.File) map[ds.Range]*ds.Symbol { res := make(map[ds.Range]*ds.Symbol) symbols, err := e.Symbols() if err != nil { log.WithFields(log.Fields{"error": err}).Info("Failed to Parse Symbols") return res } for _, sym := range symbols { sym_type := elfSymbolTypeToSymbolType(uint(sym.Info)) symbol := ds.NewSymbol(sym.Name, sym_type) res[ds.NewRange(sym.Value, sym.Value+sym.Size)] = symbol } return res }
func processGoInformation(f *elf.File) { gosymtab := getSectionData(f, ".gosymtab") gopclntab := getSectionData(f, ".gopclntab") lineTable := gosym.NewLineTable(gopclntab, f.Section(".text").Addr) table, err := gosym.NewTable(gosymtab, lineTable) if err != nil { log.Fatalf("failed making table: %s", err) } printSyms(table.Syms) printFuncs(table.Funcs) printFiles(table.Files) }
func (dbp *Process) parseDebugLineInfo(exe *elf.File, wg *sync.WaitGroup) { defer wg.Done() if sec := exe.Section(".debug_line"); sec != nil { debugLine, err := exe.Section(".debug_line").Data() if err != nil { fmt.Println("could not get .debug_line section", err) os.Exit(1) } dbp.lineInfo = line.Parse(debugLine) } else { fmt.Println("could not find .debug_line section in binary") os.Exit(1) } }
func (dbp *Process) parseDebugFrame(exe *elf.File, wg *sync.WaitGroup) { defer wg.Done() if sec := exe.Section(".debug_frame"); sec != nil { debugFrame, err := exe.Section(".debug_frame").Data() if err != nil { fmt.Println("could not get .debug_frame section", err) os.Exit(1) } dbp.frameEntries = frame.Parse(debugFrame) } else { fmt.Println("could not find .debug_frame section in binary") os.Exit(1) } }
func dwzparser(dwzfile *elf.File, offset int64, debug_package string, debug_file string) string { if section := dwzfile.Section(".debug_str"); section != nil { reader := io.NewSectionReader(section, 0, int64(section.Size)) reader.Seek(offset, 1) bufreader := bufio.NewReader(reader) // http://golang.org/pkg/bufio/#Reader.ReadString str, err := bufreader.ReadString('\x00') if err != nil { log.Println(err, debug_package, debug_file) } return strings.TrimSuffix(str, "\x00") } panic("dwzparser ran into problems ;(") }
func canary(file *elf.File) string { if symbols, e := file.Symbols(); e == nil { for _, sym := range symbols { if bytes.HasPrefix([]byte(sym.Name), []byte(STACK_CHK)) { return ENABLED } } } if importedSymbols, e := file.ImportedSymbols(); e == nil { for _, imp := range importedSymbols { if bytes.HasPrefix([]byte(imp.Name), []byte(STACK_CHK)) { return ENABLED } } } return DISABLED }
func elfGoSyms(f *elf.File) (*gosym.Table, os.Error) { text := f.Section(".text") symtab := f.Section(".gosymtab") pclntab := f.Section(".gopclntab") if text == nil || symtab == nil || pclntab == nil { return nil, nil } symdat, err := symtab.Data() if err != nil { return nil, err } pclndat, err := pclntab.Data() if err != nil { return nil, err } pcln := gosym.NewLineTable(pclndat, text.Addr) tab, err := gosym.NewTable(symdat, pcln) if err != nil { return nil, err } return tab, nil }
func (dbp *Process) obtainGoSymbols(exe *elf.File, wg *sync.WaitGroup) { defer wg.Done() var ( symdat []byte pclndat []byte err error ) if sec := exe.Section(".gosymtab"); sec != nil { symdat, err = sec.Data() if err != nil { fmt.Println("could not get .gosymtab section", err) os.Exit(1) } } if sec := exe.Section(".gopclntab"); sec != nil { pclndat, err = sec.Data() if err != nil { fmt.Println("could not get .gopclntab section", err) os.Exit(1) } } pcln := gosym.NewLineTable(pclndat, exe.Section(".text").Addr) tab, err := gosym.NewTable(symdat, pcln) if err != nil { fmt.Println("could not get initialize line table", err) os.Exit(1) } dbp.goSymTable = tab }
func blacklisted(file string, obj *elf.File) (bool, error) { lib := regexp.MustCompile(`^.*/lib([\w-]+)\.so[\d.]*$`) glcore := regexp.MustCompile(`libnvidia-e?glcore\.so`) gldispatch := regexp.MustCompile(`libGLdispatch\.so`) if m := lib.FindStringSubmatch(file); m != nil { switch m[1] { // Blacklist EGL/OpenGL libraries issued by other vendors case "EGL": fallthrough case "GLESv1_CM": fallthrough case "GLESv2": fallthrough case "GL": deps, err := obj.DynString(elf.DT_NEEDED) if err != nil { return false, err } for _, d := range deps { if glcore.MatchString(d) || gldispatch.MatchString(d) { return false, nil } } return true, nil // Blacklist TLS libraries using the old ABI (!= 2.3.99) case "nvidia-tls": const abi = 0x6300000003 s, err := obj.Section(".note.ABI-tag").Data() if err != nil { return false, err } return binary.LittleEndian.Uint64(s[24:]) != abi, nil } } return false, nil }
func printFileInformation(f *elf.File) { printHeader(&f.FileHeader) printSections(f.Sections) printProgs(f.Progs) printImportedLibraries(f.ImportedLibraries()) printSymbols(f.Symbols()) printImportedSymbols(f.ImportedSymbols()) }
func printDwarfInformation(f *elf.File) { dwarf, err := f.DWARF() if err != nil { log.Printf("failed getting DWARF info: %s", err) return } rd := dwarf.Reader() for { entry, err := rd.Next() if err != nil { log.Printf("failed getting next DWARF entry: %s", err) return } if entry == nil { // All done return } log.Printf("got entry with tag: %s, and offset %d", entry.Tag, entry.Offset) for _, field := range entry.Field { log.Printf("\t%s: %v", field.Attr, field.Val) } } }
func dump_dynstr(file *elf.File) { fmt.Printf("DynStrings:\n") dynstrs, _ := file.DynString(elf.DT_NEEDED) for _, e := range dynstrs { fmt.Printf("\t%s\n", e) } dynstrs, _ = file.DynString(elf.DT_SONAME) for _, e := range dynstrs { fmt.Printf("\t%s\n", e) } dynstrs, _ = file.DynString(elf.DT_RPATH) for _, e := range dynstrs { fmt.Printf("\t%s\n", e) } dynstrs, _ = file.DynString(elf.DT_RUNPATH) for _, e := range dynstrs { fmt.Printf("\t%s\n", e) } }
func parse(file string, f *elf.File, t *testing.T) (*elf.File, *Table) { symdat, err := f.Section(".gosymtab").Data() if err != nil { f.Close() t.Fatalf("reading %s gosymtab: %v", file, err) } pclndat, err := f.Section(".gopclntab").Data() if err != nil { f.Close() t.Fatalf("reading %s gopclntab: %v", file, err) } pcln := NewLineTable(pclndat, f.Section(".text").Addr) tab, err := NewTable(symdat, pcln) if err != nil { f.Close() t.Fatalf("parsing %s gosymtab: %v", file, err) } return f, tab }
func producer(debugfile *elf.File, dwzfile *elf.File, debug_package string, debug_file string) []string { var output []string // iterate over all CUs present in debugfile d, e := debugfile.DWARF() // increases memory usage by 2x to 3x! if e != nil { log.Println(e, debug_package, debug_file) return output } reader := d.Reader() for { entry, err := reader.Next() if err != nil { log.Println(err, debug_file, debug_package) break } if entry == nil { break } if entry.Tag == dwarf.TagCompileUnit { for _, f := range entry.Field { if f.Attr == dwarf.AttrName { switch f.Val.(type) { case string: output = append(output, f.Val.(string)) default: // distinguish between dwarf.OffsetStrpAlt, and dwarf.OffsetRefAlt switch f.Class { case dwarf.ClassStringAlt: output = append(output, dwzparser(dwzfile, (int64)(f.Val.(int64)), debug_package, debug_file)) // this are filenames! dummy := 0 _ = dummy // panic("dwarf.ClassStringAlt is not handled currently in dwarf.AttrName, expect the unexpected ;(") case dwarf.ClassReferenceAlt: panic("dwarf.ClassReferenceAlt is not handled currently in dwarf.AttrName, expect the unexpected ;(") default: panic("form unhandled for dwarf.AttrName, expect the unexpected ;(") } } } else if f.Attr == dwarf.AttrProducer { switch f.Val.(type) { case string: output = append(output, f.Val.(string)) default: // distinguish between dwarf.OffsetStrpAlt, and dwarf.OffsetRefAlt switch f.Class { case dwarf.ClassStringAlt: output = append(output, dwzparser(dwzfile, (int64)(f.Val.(int64)), debug_package, debug_file)) case dwarf.ClassReferenceAlt: panic("dwarf.ClassReferenceAlt is not handled currently in dwarf.AttrProducer, expect the unexpected ;(") default: panic("form unhandled for dwarf.AttrProducer, expect the unexpected ;(") } } } } } } // log.Println(output) return output }