func (f *File) DWARF() (*dwarf.Data, error) { // There are many other DWARF sections, but these // are the ones the debug/dwarf package uses. // Don't bother loading others. var names = [...]string{"abbrev", "info", "line", "str"} var dat [len(names)][]byte for i, name := range names { name = ".debug_" + name s := f.Section(name) if s == nil { continue } b, err := s.Data() if err != nil && uint32(len(b)) < s.Size { return nil, err } if 0 < s.VirtualSize && s.VirtualSize < s.Size { b = b[:s.VirtualSize] } dat[i] = b } abbrev, info, line, str := dat[0], dat[1], dat[2], dat[3] return dwarf.New(abbrev, nil, nil, info, line, nil, nil, str) }
// DWARF returns the DWARF debug information for the Mach-O file. func (f *File) DWARF() (*dwarf.Data, error) { // There are many other DWARF sections, but these // are the required ones, and the debug/dwarf package // does not use the others, so don't bother loading them. var names = [...]string{"abbrev", "info", "str"} var dat [len(names)][]byte for i, name := range names { name = "__debug_" + name s := f.Section(name) if s == nil { return nil, errors.New("missing Mach-O section " + name) } b, err := s.Data() if err != nil && uint64(len(b)) < s.Size { return nil, err } dat[i] = b } abbrev, info, str := dat[0], dat[1], dat[2] return dwarf.New(abbrev, nil, nil, info, nil, nil, nil, str) }
func (f *File) DWARF() (*dwarf.Data, os.Error) { // There are many other DWARF sections, but these // are the required ones, and the debug/dwarf package // does not use the others, so don't bother loading them. var names = [...]string{"abbrev", "info", "str"} var dat [len(names)][]byte for i, name := range names { name = ".debug_" + name s := f.Section(name) if s == nil { continue } b, err := s.Data() if err != nil && uint64(len(b)) < s.Size { return nil, err } dat[i] = b } // If there's a relocation table for .debug_info, we have to process it // now otherwise the data in .debug_info is invalid for x86-64 objects. rela := f.Section(".rela.debug_info") if rela != nil && rela.Type == SHT_RELA && f.Machine == EM_X86_64 { data, err := rela.Data() if err != nil { return nil, err } err = f.applyRelocations(dat[1], data) if err != nil { return nil, err } } abbrev, info, str := dat[0], dat[1], dat[2] return dwarf.New(abbrev, nil, nil, info, nil, nil, nil, str) }
func (f *File) DWARF() (*dwarf.Data, error) { // sectionData gets the data for s, checks its size, and // applies any applicable relations. sectionData := func(i int, s *Section) ([]byte, error) { b, err := s.Data() if err != nil && uint64(len(b)) < s.Size { return nil, err } if len(b) >= 12 && string(b[:4]) == "ZLIB" { dlen := binary.BigEndian.Uint64(b[4:12]) dbuf := make([]byte, dlen) r, err := zlib.NewReader(bytes.NewBuffer(b[12:])) if err != nil { return nil, err } if _, err := io.ReadFull(r, dbuf); err != nil { return nil, err } if err := r.Close(); err != nil { return nil, err } b = dbuf } for _, r := range f.Sections { if r.Type != SHT_RELA && r.Type != SHT_REL { continue } if int(r.Info) != i { continue } rd, err := r.Data() if err != nil { return nil, err } err = f.applyRelocations(b, rd) if err != nil { return nil, err } } return b, nil } // There are many other DWARF sections, but these // are the ones the debug/dwarf package uses. // Don't bother loading others. var dat = map[string][]byte{"abbrev": nil, "info": nil, "str": nil, "line": nil} for i, s := range f.Sections { suffix := "" switch { case strings.HasPrefix(s.Name, ".debug_"): suffix = s.Name[7:] case strings.HasPrefix(s.Name, ".zdebug_"): suffix = s.Name[8:] default: continue } if _, ok := dat[suffix]; !ok { continue } b, err := sectionData(i, s) if err != nil { return nil, err } dat[suffix] = b } d, err := dwarf.New(dat["abbrev"], nil, nil, dat["info"], dat["line"], nil, nil, dat["str"]) if err != nil { return nil, err } // Look for DWARF4 .debug_types sections. for i, s := range f.Sections { if s.Name == ".debug_types" { b, err := sectionData(i, s) if err != nil { return nil, err } err = d.AddTypes(fmt.Sprintf("types-%d", i), b) if err != nil { return nil, err } } } return d, nil }
func (f *File) DWARF() (*dwarf.Data, error) { // There are many other DWARF sections, but these // are the required ones, and the debug/dwarf package // does not use the others, so don't bother loading them. var names = [...]string{"abbrev", "info", "str"} var dat [len(names)][]byte for i, name := range names { name = ".debug_" + name s := f.Section(name) if s == nil { continue } b, err := s.Data() if err != nil && uint64(len(b)) < s.Size { return nil, err } dat[i] = b } // If there's a relocation table for .debug_info, we have to process it // now otherwise the data in .debug_info is invalid for x86-64 objects. rela := f.Section(".rela.debug_info") if rela != nil && rela.Type == SHT_RELA && f.Machine == EM_X86_64 { data, err := rela.Data() if err != nil { return nil, err } err = f.applyRelocations(dat[1], data) if err != nil { return nil, err } } // When using clang we need to process relocations even for 386. rel := f.Section(".rel.debug_info") if rel != nil && rel.Type == SHT_REL && f.Machine == EM_386 { data, err := rel.Data() if err != nil { return nil, err } err = f.applyRelocations(dat[1], data) if err != nil { return nil, err } } abbrev, info, str := dat[0], dat[1], dat[2] d, err := dwarf.New(abbrev, nil, nil, info, nil, nil, nil, str) if err != nil { return nil, err } // Look for DWARF4 .debug_types sections. for i, s := range f.Sections { if s.Name == ".debug_types" { b, err := s.Data() if err != nil && uint64(len(b)) < s.Size { return nil, err } for _, r := range f.Sections { if r.Type != SHT_RELA && r.Type != SHT_REL { continue } if int(r.Info) != i { continue } rd, err := r.Data() if err != nil { return nil, err } err = f.applyRelocations(b, rd) if err != nil { return nil, err } } err = d.AddTypes(fmt.Sprintf("types-%d", i), b) if err != nil { return nil, err } } } return d, nil }
func (f *File) DWARF() (*dwarf.Data, error) { // sectionData gets the data for s, checks its size, and // applies any applicable relations. sectionData := func(i int, s *Section) ([]byte, error) { b, err := s.Data() if err != nil && uint64(len(b)) < s.Size { return nil, err } for _, r := range f.Sections { if r.Type != SHT_RELA && r.Type != SHT_REL { continue } if int(r.Info) != i { continue } rd, err := r.Data() if err != nil { return nil, err } err = f.applyRelocations(b, rd) if err != nil { return nil, err } } return b, nil } // There are many other DWARF sections, but these // are the ones the debug/dwarf package uses. // Don't bother loading others. var dat = map[string][]byte{"abbrev": nil, "info": nil, "str": nil, "line": nil} for i, s := range f.Sections { if !strings.HasPrefix(s.Name, ".debug_") { continue } if _, ok := dat[s.Name[7:]]; !ok { continue } b, err := sectionData(i, s) if err != nil { return nil, err } dat[s.Name[7:]] = b } d, err := dwarf.New(dat["abbrev"], nil, nil, dat["info"], dat["line"], nil, nil, dat["str"]) if err != nil { return nil, err } // Look for DWARF4 .debug_types sections. for i, s := range f.Sections { if s.Name == ".debug_types" { b, err := sectionData(i, s) if err != nil { return nil, err } err = d.AddTypes(fmt.Sprintf("types-%d", i), b) if err != nil { return nil, err } } } return d, nil }