Source file src/debug/dwarf/open.go

     1  // 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 dwarf provides access to DWARF debugging information loaded from
     6  // executable files, as defined in the DWARF 2.0 Standard at
     7  // http://dwarfstd.org/doc/dwarf-2.0.0.pdf
     8  package dwarf
     9  
    10  import (
    11  	"encoding/binary"
    12  	"errors"
    13  )
    14  
    15  // Data represents the DWARF debugging information
    16  // loaded from an executable file (for example, an ELF or Mach-O executable).
    17  type Data struct {
    18  	// raw data
    19  	abbrev   []byte
    20  	aranges  []byte
    21  	frame    []byte
    22  	info     []byte
    23  	line     []byte
    24  	pubnames []byte
    25  	ranges   []byte
    26  	str      []byte
    27  
    28  	// New sections added in DWARF 5.
    29  	addr       []byte
    30  	lineStr    []byte
    31  	strOffsets []byte
    32  	rngLists   []byte
    33  
    34  	// parsed data
    35  	abbrevCache map[uint64]abbrevTable
    36  	bigEndian   bool
    37  	order       binary.ByteOrder
    38  	typeCache   map[Offset]Type
    39  	typeSigs    map[uint64]*typeUnit
    40  	unit        []unit
    41  }
    42  
    43  var errSegmentSelector = errors.New("non-zero segment_selector size not supported")
    44  
    45  // New returns a new Data object initialized from the given parameters.
    46  // Rather than calling this function directly, clients should typically use
    47  // the DWARF method of the File type of the appropriate package debug/elf,
    48  // debug/macho, or debug/pe.
    49  //
    50  // The []byte arguments are the data from the corresponding debug section
    51  // in the object file; for example, for an ELF object, abbrev is the contents of
    52  // the ".debug_abbrev" section.
    53  func New(abbrev, aranges, frame, info, line, pubnames, ranges, str []byte) (*Data, error) {
    54  	d := &Data{
    55  		abbrev:      abbrev,
    56  		aranges:     aranges,
    57  		frame:       frame,
    58  		info:        info,
    59  		line:        line,
    60  		pubnames:    pubnames,
    61  		ranges:      ranges,
    62  		str:         str,
    63  		abbrevCache: make(map[uint64]abbrevTable),
    64  		typeCache:   make(map[Offset]Type),
    65  		typeSigs:    make(map[uint64]*typeUnit),
    66  	}
    67  
    68  	// Sniff .debug_info to figure out byte order.
    69  	// 32-bit DWARF: 4 byte length, 2 byte version.
    70  	// 64-bit DWARf: 4 bytes of 0xff, 8 byte length, 2 byte version.
    71  	if len(d.info) < 6 {
    72  		return nil, DecodeError{"info", Offset(len(d.info)), "too short"}
    73  	}
    74  	offset := 4
    75  	if d.info[0] == 0xff && d.info[1] == 0xff && d.info[2] == 0xff && d.info[3] == 0xff {
    76  		if len(d.info) < 14 {
    77  			return nil, DecodeError{"info", Offset(len(d.info)), "too short"}
    78  		}
    79  		offset = 12
    80  	}
    81  	// Fetch the version, a tiny 16-bit number (1, 2, 3, 4, 5).
    82  	x, y := d.info[offset], d.info[offset+1]
    83  	switch {
    84  	case x == 0 && y == 0:
    85  		return nil, DecodeError{"info", 4, "unsupported version 0"}
    86  	case x == 0:
    87  		d.bigEndian = true
    88  		d.order = binary.BigEndian
    89  	case y == 0:
    90  		d.bigEndian = false
    91  		d.order = binary.LittleEndian
    92  	default:
    93  		return nil, DecodeError{"info", 4, "cannot determine byte order"}
    94  	}
    95  
    96  	u, err := d.parseUnits()
    97  	if err != nil {
    98  		return nil, err
    99  	}
   100  	d.unit = u
   101  	return d, nil
   102  }
   103  
   104  // AddTypes will add one .debug_types section to the DWARF data. A
   105  // typical object with DWARF version 4 debug info will have multiple
   106  // .debug_types sections. The name is used for error reporting only,
   107  // and serves to distinguish one .debug_types section from another.
   108  func (d *Data) AddTypes(name string, types []byte) error {
   109  	return d.parseTypes(name, types)
   110  }
   111  
   112  // AddSection adds another DWARF section by name. The name should be a
   113  // DWARF section name such as ".debug_addr", ".debug_str_offsets", and
   114  // so forth. This approach is used for new DWARF sections added in
   115  // DWARF 5 and later.
   116  func (d *Data) AddSection(name string, contents []byte) error {
   117  	var err error
   118  	switch name {
   119  	case ".debug_addr":
   120  		d.addr = contents
   121  	case ".debug_line_str":
   122  		d.lineStr = contents
   123  	case ".debug_str_offsets":
   124  		d.strOffsets = contents
   125  	case ".debug_rnglists":
   126  		d.rngLists = contents
   127  	}
   128  	// Just ignore names that we don't yet support.
   129  	return err
   130  }
   131  

View as plain text