...

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 (
		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