open.mx raw

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