Black Lives Matter. Support the Equal Justice Initiative.

Source file src/debug/dwarf/open.go

Documentation: debug/dwarf

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

View as plain text