diff options
author | Tianon Gravi <admwiggin@gmail.com> | 2015-01-15 11:54:00 -0700 |
---|---|---|
committer | Tianon Gravi <admwiggin@gmail.com> | 2015-01-15 11:54:00 -0700 |
commit | f154da9e12608589e8d5f0508f908a0c3e88a1bb (patch) | |
tree | f8255d51e10c6f1e0ed69702200b966c9556a431 /src/pkg/debug/dwarf | |
parent | 8d8329ed5dfb9622c82a9fbec6fd99a580f9c9f6 (diff) | |
download | golang-upstream/1.4.tar.gz |
Imported Upstream version 1.4upstream/1.4
Diffstat (limited to 'src/pkg/debug/dwarf')
-rw-r--r-- | src/pkg/debug/dwarf/buf.go | 181 | ||||
-rw-r--r-- | src/pkg/debug/dwarf/const.go | 454 | ||||
-rw-r--r-- | src/pkg/debug/dwarf/entry.go | 401 | ||||
-rw-r--r-- | src/pkg/debug/dwarf/open.go | 87 | ||||
-rw-r--r-- | src/pkg/debug/dwarf/testdata/typedef.c | 85 | ||||
-rwxr-xr-x | src/pkg/debug/dwarf/testdata/typedef.elf | bin | 12448 -> 0 bytes | |||
-rw-r--r-- | src/pkg/debug/dwarf/testdata/typedef.elf4 | bin | 9496 -> 0 bytes | |||
-rw-r--r-- | src/pkg/debug/dwarf/testdata/typedef.macho | bin | 5024 -> 0 bytes | |||
-rw-r--r-- | src/pkg/debug/dwarf/type.go | 659 | ||||
-rw-r--r-- | src/pkg/debug/dwarf/type_test.go | 122 | ||||
-rw-r--r-- | src/pkg/debug/dwarf/typeunit.go | 166 | ||||
-rw-r--r-- | src/pkg/debug/dwarf/unit.go | 90 |
12 files changed, 0 insertions, 2245 deletions
diff --git a/src/pkg/debug/dwarf/buf.go b/src/pkg/debug/dwarf/buf.go deleted file mode 100644 index 53c46eb4b..000000000 --- a/src/pkg/debug/dwarf/buf.go +++ /dev/null @@ -1,181 +0,0 @@ -// Copyright 2009 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// Buffered reading and decoding of DWARF data streams. - -package dwarf - -import ( - "encoding/binary" - "strconv" -) - -// Data buffer being decoded. -type buf struct { - dwarf *Data - order binary.ByteOrder - format dataFormat - name string - off Offset - data []byte - err error -} - -// Data format, other than byte order. This affects the handling of -// certain field formats. -type dataFormat interface { - // DWARF version number. Zero means unknown. - version() int - - // 64-bit DWARF format? - dwarf64() (dwarf64 bool, isKnown bool) - - // Size of an address, in bytes. Zero means unknown. - addrsize() int -} - -// Some parts of DWARF have no data format, e.g., abbrevs. -type unknownFormat struct{} - -func (u unknownFormat) version() int { - return 0 -} - -func (u unknownFormat) dwarf64() (bool, bool) { - return false, false -} - -func (u unknownFormat) addrsize() int { - return 0 -} - -func makeBuf(d *Data, format dataFormat, name string, off Offset, data []byte) buf { - return buf{d, d.order, format, name, off, data, nil} -} - -func (b *buf) uint8() uint8 { - if len(b.data) < 1 { - b.error("underflow") - return 0 - } - val := b.data[0] - b.data = b.data[1:] - b.off++ - return val -} - -func (b *buf) bytes(n int) []byte { - if len(b.data) < n { - b.error("underflow") - return nil - } - data := b.data[0:n] - b.data = b.data[n:] - b.off += Offset(n) - return data -} - -func (b *buf) skip(n int) { b.bytes(n) } - -func (b *buf) string() string { - for i := 0; i < len(b.data); i++ { - if b.data[i] == 0 { - s := string(b.data[0:i]) - b.data = b.data[i+1:] - b.off += Offset(i + 1) - return s - } - } - b.error("underflow") - return "" -} - -func (b *buf) uint16() uint16 { - a := b.bytes(2) - if a == nil { - return 0 - } - return b.order.Uint16(a) -} - -func (b *buf) uint32() uint32 { - a := b.bytes(4) - if a == nil { - return 0 - } - return b.order.Uint32(a) -} - -func (b *buf) uint64() uint64 { - a := b.bytes(8) - if a == nil { - return 0 - } - return b.order.Uint64(a) -} - -// Read a varint, which is 7 bits per byte, little endian. -// the 0x80 bit means read another byte. -func (b *buf) varint() (c uint64, bits uint) { - for i := 0; i < len(b.data); i++ { - byte := b.data[i] - c |= uint64(byte&0x7F) << bits - bits += 7 - if byte&0x80 == 0 { - b.off += Offset(i + 1) - b.data = b.data[i+1:] - return c, bits - } - } - return 0, 0 -} - -// Unsigned int is just a varint. -func (b *buf) uint() uint64 { - x, _ := b.varint() - return x -} - -// Signed int is a sign-extended varint. -func (b *buf) int() int64 { - ux, bits := b.varint() - x := int64(ux) - if x&(1<<(bits-1)) != 0 { - x |= -1 << bits - } - return x -} - -// Address-sized uint. -func (b *buf) addr() uint64 { - switch b.format.addrsize() { - case 1: - return uint64(b.uint8()) - case 2: - return uint64(b.uint16()) - case 4: - return uint64(b.uint32()) - case 8: - return uint64(b.uint64()) - } - b.error("unknown address size") - return 0 -} - -func (b *buf) error(s string) { - if b.err == nil { - b.data = nil - b.err = DecodeError{b.name, b.off, s} - } -} - -type DecodeError struct { - Name string - Offset Offset - Err string -} - -func (e DecodeError) Error() string { - return "decoding dwarf section " + e.Name + " at offset 0x" + strconv.FormatInt(int64(e.Offset), 16) + ": " + e.Err -} diff --git a/src/pkg/debug/dwarf/const.go b/src/pkg/debug/dwarf/const.go deleted file mode 100644 index 93c68881a..000000000 --- a/src/pkg/debug/dwarf/const.go +++ /dev/null @@ -1,454 +0,0 @@ -// Copyright 2009 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// Constants - -package dwarf - -import "strconv" - -// An Attr identifies the attribute type in a DWARF Entry's Field. -type Attr uint32 - -const ( - AttrSibling Attr = 0x01 - AttrLocation Attr = 0x02 - AttrName Attr = 0x03 - AttrOrdering Attr = 0x09 - AttrByteSize Attr = 0x0B - AttrBitOffset Attr = 0x0C - AttrBitSize Attr = 0x0D - AttrStmtList Attr = 0x10 - AttrLowpc Attr = 0x11 - AttrHighpc Attr = 0x12 - AttrLanguage Attr = 0x13 - AttrDiscr Attr = 0x15 - AttrDiscrValue Attr = 0x16 - AttrVisibility Attr = 0x17 - AttrImport Attr = 0x18 - AttrStringLength Attr = 0x19 - AttrCommonRef Attr = 0x1A - AttrCompDir Attr = 0x1B - AttrConstValue Attr = 0x1C - AttrContainingType Attr = 0x1D - AttrDefaultValue Attr = 0x1E - AttrInline Attr = 0x20 - AttrIsOptional Attr = 0x21 - AttrLowerBound Attr = 0x22 - AttrProducer Attr = 0x25 - AttrPrototyped Attr = 0x27 - AttrReturnAddr Attr = 0x2A - AttrStartScope Attr = 0x2C - AttrStrideSize Attr = 0x2E - AttrUpperBound Attr = 0x2F - AttrAbstractOrigin Attr = 0x31 - AttrAccessibility Attr = 0x32 - AttrAddrClass Attr = 0x33 - AttrArtificial Attr = 0x34 - AttrBaseTypes Attr = 0x35 - AttrCalling Attr = 0x36 - AttrCount Attr = 0x37 - AttrDataMemberLoc Attr = 0x38 - AttrDeclColumn Attr = 0x39 - AttrDeclFile Attr = 0x3A - AttrDeclLine Attr = 0x3B - AttrDeclaration Attr = 0x3C - AttrDiscrList Attr = 0x3D - AttrEncoding Attr = 0x3E - AttrExternal Attr = 0x3F - AttrFrameBase Attr = 0x40 - AttrFriend Attr = 0x41 - AttrIdentifierCase Attr = 0x42 - AttrMacroInfo Attr = 0x43 - AttrNamelistItem Attr = 0x44 - AttrPriority Attr = 0x45 - AttrSegment Attr = 0x46 - AttrSpecification Attr = 0x47 - AttrStaticLink Attr = 0x48 - AttrType Attr = 0x49 - AttrUseLocation Attr = 0x4A - AttrVarParam Attr = 0x4B - AttrVirtuality Attr = 0x4C - AttrVtableElemLoc Attr = 0x4D - AttrAllocated Attr = 0x4E - AttrAssociated Attr = 0x4F - AttrDataLocation Attr = 0x50 - AttrStride Attr = 0x51 - AttrEntrypc Attr = 0x52 - AttrUseUTF8 Attr = 0x53 - AttrExtension Attr = 0x54 - AttrRanges Attr = 0x55 - AttrTrampoline Attr = 0x56 - AttrCallColumn Attr = 0x57 - AttrCallFile Attr = 0x58 - AttrCallLine Attr = 0x59 - AttrDescription Attr = 0x5A -) - -var attrNames = [...]string{ - AttrSibling: "Sibling", - AttrLocation: "Location", - AttrName: "Name", - AttrOrdering: "Ordering", - AttrByteSize: "ByteSize", - AttrBitOffset: "BitOffset", - AttrBitSize: "BitSize", - AttrStmtList: "StmtList", - AttrLowpc: "Lowpc", - AttrHighpc: "Highpc", - AttrLanguage: "Language", - AttrDiscr: "Discr", - AttrDiscrValue: "DiscrValue", - AttrVisibility: "Visibility", - AttrImport: "Import", - AttrStringLength: "StringLength", - AttrCommonRef: "CommonRef", - AttrCompDir: "CompDir", - AttrConstValue: "ConstValue", - AttrContainingType: "ContainingType", - AttrDefaultValue: "DefaultValue", - AttrInline: "Inline", - AttrIsOptional: "IsOptional", - AttrLowerBound: "LowerBound", - AttrProducer: "Producer", - AttrPrototyped: "Prototyped", - AttrReturnAddr: "ReturnAddr", - AttrStartScope: "StartScope", - AttrStrideSize: "StrideSize", - AttrUpperBound: "UpperBound", - AttrAbstractOrigin: "AbstractOrigin", - AttrAccessibility: "Accessibility", - AttrAddrClass: "AddrClass", - AttrArtificial: "Artificial", - AttrBaseTypes: "BaseTypes", - AttrCalling: "Calling", - AttrCount: "Count", - AttrDataMemberLoc: "DataMemberLoc", - AttrDeclColumn: "DeclColumn", - AttrDeclFile: "DeclFile", - AttrDeclLine: "DeclLine", - AttrDeclaration: "Declaration", - AttrDiscrList: "DiscrList", - AttrEncoding: "Encoding", - AttrExternal: "External", - AttrFrameBase: "FrameBase", - AttrFriend: "Friend", - AttrIdentifierCase: "IdentifierCase", - AttrMacroInfo: "MacroInfo", - AttrNamelistItem: "NamelistItem", - AttrPriority: "Priority", - AttrSegment: "Segment", - AttrSpecification: "Specification", - AttrStaticLink: "StaticLink", - AttrType: "Type", - AttrUseLocation: "UseLocation", - AttrVarParam: "VarParam", - AttrVirtuality: "Virtuality", - AttrVtableElemLoc: "VtableElemLoc", - AttrAllocated: "Allocated", - AttrAssociated: "Associated", - AttrDataLocation: "DataLocation", - AttrStride: "Stride", - AttrEntrypc: "Entrypc", - AttrUseUTF8: "UseUTF8", - AttrExtension: "Extension", - AttrRanges: "Ranges", - AttrTrampoline: "Trampoline", - AttrCallColumn: "CallColumn", - AttrCallFile: "CallFile", - AttrCallLine: "CallLine", - AttrDescription: "Description", -} - -func (a Attr) String() string { - if int(a) < len(attrNames) { - s := attrNames[a] - if s != "" { - return s - } - } - return strconv.Itoa(int(a)) -} - -func (a Attr) GoString() string { - if int(a) < len(attrNames) { - s := attrNames[a] - if s != "" { - return "dwarf.Attr" + s - } - } - return "dwarf.Attr(" + strconv.FormatInt(int64(a), 10) + ")" -} - -// A format is a DWARF data encoding format. -type format uint32 - -const ( - // value formats - formAddr format = 0x01 - formDwarfBlock2 format = 0x03 - formDwarfBlock4 format = 0x04 - formData2 format = 0x05 - formData4 format = 0x06 - formData8 format = 0x07 - formString format = 0x08 - formDwarfBlock format = 0x09 - formDwarfBlock1 format = 0x0A - formData1 format = 0x0B - formFlag format = 0x0C - formSdata format = 0x0D - formStrp format = 0x0E - formUdata format = 0x0F - formRefAddr format = 0x10 - formRef1 format = 0x11 - formRef2 format = 0x12 - formRef4 format = 0x13 - formRef8 format = 0x14 - formRefUdata format = 0x15 - formIndirect format = 0x16 - // The following are new in DWARF 4. - formSecOffset format = 0x17 - formExprloc format = 0x18 - formFlagPresent format = 0x19 - formRefSig8 format = 0x20 - // Extensions for multi-file compression (.dwz) - // http://www.dwarfstd.org/ShowIssue.php?issue=120604.1 - formGnuRefAlt format = 0x1f20 - formGnuStrpAlt format = 0x1f21 -) - -// A Tag is the classification (the type) of an Entry. -type Tag uint32 - -const ( - TagArrayType Tag = 0x01 - TagClassType Tag = 0x02 - TagEntryPoint Tag = 0x03 - TagEnumerationType Tag = 0x04 - TagFormalParameter Tag = 0x05 - TagImportedDeclaration Tag = 0x08 - TagLabel Tag = 0x0A - TagLexDwarfBlock Tag = 0x0B - TagMember Tag = 0x0D - TagPointerType Tag = 0x0F - TagReferenceType Tag = 0x10 - TagCompileUnit Tag = 0x11 - TagStringType Tag = 0x12 - TagStructType Tag = 0x13 - TagSubroutineType Tag = 0x15 - TagTypedef Tag = 0x16 - TagUnionType Tag = 0x17 - TagUnspecifiedParameters Tag = 0x18 - TagVariant Tag = 0x19 - TagCommonDwarfBlock Tag = 0x1A - TagCommonInclusion Tag = 0x1B - TagInheritance Tag = 0x1C - TagInlinedSubroutine Tag = 0x1D - TagModule Tag = 0x1E - TagPtrToMemberType Tag = 0x1F - TagSetType Tag = 0x20 - TagSubrangeType Tag = 0x21 - TagWithStmt Tag = 0x22 - TagAccessDeclaration Tag = 0x23 - TagBaseType Tag = 0x24 - TagCatchDwarfBlock Tag = 0x25 - TagConstType Tag = 0x26 - TagConstant Tag = 0x27 - TagEnumerator Tag = 0x28 - TagFileType Tag = 0x29 - TagFriend Tag = 0x2A - TagNamelist Tag = 0x2B - TagNamelistItem Tag = 0x2C - TagPackedType Tag = 0x2D - TagSubprogram Tag = 0x2E - TagTemplateTypeParameter Tag = 0x2F - TagTemplateValueParameter Tag = 0x30 - TagThrownType Tag = 0x31 - TagTryDwarfBlock Tag = 0x32 - TagVariantPart Tag = 0x33 - TagVariable Tag = 0x34 - TagVolatileType Tag = 0x35 - // The following are new in DWARF 3. - TagDwarfProcedure Tag = 0x36 - TagRestrictType Tag = 0x37 - TagInterfaceType Tag = 0x38 - TagNamespace Tag = 0x39 - TagImportedModule Tag = 0x3A - TagUnspecifiedType Tag = 0x3B - TagPartialUnit Tag = 0x3C - TagImportedUnit Tag = 0x3D - TagMutableType Tag = 0x3E // Later removed from DWARF. - TagCondition Tag = 0x3F - TagSharedType Tag = 0x40 - // The following are new in DWARF 4. - TagTypeUnit Tag = 0x41 - TagRvalueReferenceType Tag = 0x42 - TagTemplateAlias Tag = 0x43 -) - -var tagNames = [...]string{ - TagArrayType: "ArrayType", - TagClassType: "ClassType", - TagEntryPoint: "EntryPoint", - TagEnumerationType: "EnumerationType", - TagFormalParameter: "FormalParameter", - TagImportedDeclaration: "ImportedDeclaration", - TagLabel: "Label", - TagLexDwarfBlock: "LexDwarfBlock", - TagMember: "Member", - TagPointerType: "PointerType", - TagReferenceType: "ReferenceType", - TagCompileUnit: "CompileUnit", - TagStringType: "StringType", - TagStructType: "StructType", - TagSubroutineType: "SubroutineType", - TagTypedef: "Typedef", - TagUnionType: "UnionType", - TagUnspecifiedParameters: "UnspecifiedParameters", - TagVariant: "Variant", - TagCommonDwarfBlock: "CommonDwarfBlock", - TagCommonInclusion: "CommonInclusion", - TagInheritance: "Inheritance", - TagInlinedSubroutine: "InlinedSubroutine", - TagModule: "Module", - TagPtrToMemberType: "PtrToMemberType", - TagSetType: "SetType", - TagSubrangeType: "SubrangeType", - TagWithStmt: "WithStmt", - TagAccessDeclaration: "AccessDeclaration", - TagBaseType: "BaseType", - TagCatchDwarfBlock: "CatchDwarfBlock", - TagConstType: "ConstType", - TagConstant: "Constant", - TagEnumerator: "Enumerator", - TagFileType: "FileType", - TagFriend: "Friend", - TagNamelist: "Namelist", - TagNamelistItem: "NamelistItem", - TagPackedType: "PackedType", - TagSubprogram: "Subprogram", - TagTemplateTypeParameter: "TemplateTypeParameter", - TagTemplateValueParameter: "TemplateValueParameter", - TagThrownType: "ThrownType", - TagTryDwarfBlock: "TryDwarfBlock", - TagVariantPart: "VariantPart", - TagVariable: "Variable", - TagVolatileType: "VolatileType", - TagDwarfProcedure: "DwarfProcedure", - TagRestrictType: "RestrictType", - TagInterfaceType: "InterfaceType", - TagNamespace: "Namespace", - TagImportedModule: "ImportedModule", - TagUnspecifiedType: "UnspecifiedType", - TagPartialUnit: "PartialUnit", - TagImportedUnit: "ImportedUnit", - TagMutableType: "MutableType", - TagCondition: "Condition", - TagSharedType: "SharedType", - TagTypeUnit: "TypeUnit", - TagRvalueReferenceType: "RvalueReferenceType", - TagTemplateAlias: "TemplateAlias", -} - -func (t Tag) String() string { - if int(t) < len(tagNames) { - s := tagNames[t] - if s != "" { - return s - } - } - return strconv.Itoa(int(t)) -} - -func (t Tag) GoString() string { - if int(t) < len(tagNames) { - s := tagNames[t] - if s != "" { - return "dwarf.Tag" + s - } - } - return "dwarf.Tag(" + strconv.FormatInt(int64(t), 10) + ")" -} - -// Location expression operators. -// The debug info encodes value locations like 8(R3) -// as a sequence of these op codes. -// This package does not implement full expressions; -// the opPlusUconst operator is expected by the type parser. -const ( - opAddr = 0x03 /* 1 op, const addr */ - opDeref = 0x06 - opConst1u = 0x08 /* 1 op, 1 byte const */ - opConst1s = 0x09 /* " signed */ - opConst2u = 0x0A /* 1 op, 2 byte const */ - opConst2s = 0x0B /* " signed */ - opConst4u = 0x0C /* 1 op, 4 byte const */ - opConst4s = 0x0D /* " signed */ - opConst8u = 0x0E /* 1 op, 8 byte const */ - opConst8s = 0x0F /* " signed */ - opConstu = 0x10 /* 1 op, LEB128 const */ - opConsts = 0x11 /* " signed */ - opDup = 0x12 - opDrop = 0x13 - opOver = 0x14 - opPick = 0x15 /* 1 op, 1 byte stack index */ - opSwap = 0x16 - opRot = 0x17 - opXderef = 0x18 - opAbs = 0x19 - opAnd = 0x1A - opDiv = 0x1B - opMinus = 0x1C - opMod = 0x1D - opMul = 0x1E - opNeg = 0x1F - opNot = 0x20 - opOr = 0x21 - opPlus = 0x22 - opPlusUconst = 0x23 /* 1 op, ULEB128 addend */ - opShl = 0x24 - opShr = 0x25 - opShra = 0x26 - opXor = 0x27 - opSkip = 0x2F /* 1 op, signed 2-byte constant */ - opBra = 0x28 /* 1 op, signed 2-byte constant */ - opEq = 0x29 - opGe = 0x2A - opGt = 0x2B - opLe = 0x2C - opLt = 0x2D - opNe = 0x2E - opLit0 = 0x30 - /* OpLitN = OpLit0 + N for N = 0..31 */ - opReg0 = 0x50 - /* OpRegN = OpReg0 + N for N = 0..31 */ - opBreg0 = 0x70 /* 1 op, signed LEB128 constant */ - /* OpBregN = OpBreg0 + N for N = 0..31 */ - opRegx = 0x90 /* 1 op, ULEB128 register */ - opFbreg = 0x91 /* 1 op, SLEB128 offset */ - opBregx = 0x92 /* 2 op, ULEB128 reg; SLEB128 off */ - opPiece = 0x93 /* 1 op, ULEB128 size of piece */ - opDerefSize = 0x94 /* 1-byte size of data retrieved */ - opXderefSize = 0x95 /* 1-byte size of data retrieved */ - opNop = 0x96 - /* next four new in Dwarf v3 */ - opPushObjAddr = 0x97 - opCall2 = 0x98 /* 2-byte offset of DIE */ - opCall4 = 0x99 /* 4-byte offset of DIE */ - opCallRef = 0x9A /* 4- or 8- byte offset of DIE */ - /* 0xE0-0xFF reserved for user-specific */ -) - -// Basic type encodings -- the value for AttrEncoding in a TagBaseType Entry. -const ( - encAddress = 0x01 - encBoolean = 0x02 - encComplexFloat = 0x03 - encFloat = 0x04 - encSigned = 0x05 - encSignedChar = 0x06 - encUnsigned = 0x07 - encUnsignedChar = 0x08 - encImaginaryFloat = 0x09 -) diff --git a/src/pkg/debug/dwarf/entry.go b/src/pkg/debug/dwarf/entry.go deleted file mode 100644 index 665c6840d..000000000 --- a/src/pkg/debug/dwarf/entry.go +++ /dev/null @@ -1,401 +0,0 @@ -// Copyright 2009 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// DWARF debug information entry parser. -// An entry is a sequence of data items of a given format. -// The first word in the entry is an index into what DWARF -// calls the ``abbreviation table.'' An abbreviation is really -// just a type descriptor: it's an array of attribute tag/value format pairs. - -package dwarf - -import ( - "errors" - "strconv" -) - -// a single entry's description: a sequence of attributes -type abbrev struct { - tag Tag - children bool - field []afield -} - -type afield struct { - attr Attr - fmt format -} - -// a map from entry format ids to their descriptions -type abbrevTable map[uint32]abbrev - -// ParseAbbrev returns the abbreviation table that starts at byte off -// in the .debug_abbrev section. -func (d *Data) parseAbbrev(off uint32) (abbrevTable, error) { - if m, ok := d.abbrevCache[off]; ok { - return m, nil - } - - data := d.abbrev - if off > uint32(len(data)) { - data = nil - } else { - data = data[off:] - } - b := makeBuf(d, unknownFormat{}, "abbrev", 0, data) - - // Error handling is simplified by the buf getters - // returning an endless stream of 0s after an error. - m := make(abbrevTable) - for { - // Table ends with id == 0. - id := uint32(b.uint()) - if id == 0 { - break - } - - // Walk over attributes, counting. - n := 0 - b1 := b // Read from copy of b. - b1.uint() - b1.uint8() - for { - tag := b1.uint() - fmt := b1.uint() - if tag == 0 && fmt == 0 { - break - } - n++ - } - if b1.err != nil { - return nil, b1.err - } - - // Walk over attributes again, this time writing them down. - var a abbrev - a.tag = Tag(b.uint()) - a.children = b.uint8() != 0 - a.field = make([]afield, n) - for i := range a.field { - a.field[i].attr = Attr(b.uint()) - a.field[i].fmt = format(b.uint()) - } - b.uint() - b.uint() - - m[id] = a - } - if b.err != nil { - return nil, b.err - } - d.abbrevCache[off] = m - return m, nil -} - -// An entry is a sequence of attribute/value pairs. -type Entry struct { - Offset Offset // offset of Entry in DWARF info - Tag Tag // tag (kind of Entry) - Children bool // whether Entry is followed by children - Field []Field -} - -// A Field is a single attribute/value pair in an Entry. -type Field struct { - Attr Attr - Val interface{} -} - -// Val returns the value associated with attribute Attr in Entry, -// or nil if there is no such attribute. -// -// A common idiom is to merge the check for nil return with -// the check that the value has the expected dynamic type, as in: -// v, ok := e.Val(AttrSibling).(int64); -// -func (e *Entry) Val(a Attr) interface{} { - for _, f := range e.Field { - if f.Attr == a { - return f.Val - } - } - return nil -} - -// An Offset represents the location of an Entry within the DWARF info. -// (See Reader.Seek.) -type Offset uint32 - -// Entry reads a single entry from buf, decoding -// according to the given abbreviation table. -func (b *buf) entry(atab abbrevTable, ubase Offset) *Entry { - off := b.off - id := uint32(b.uint()) - if id == 0 { - return &Entry{} - } - a, ok := atab[id] - if !ok { - b.error("unknown abbreviation table index") - return nil - } - e := &Entry{ - Offset: off, - Tag: a.tag, - Children: a.children, - Field: make([]Field, len(a.field)), - } - for i := range e.Field { - e.Field[i].Attr = a.field[i].attr - fmt := a.field[i].fmt - if fmt == formIndirect { - fmt = format(b.uint()) - } - var val interface{} - switch fmt { - default: - b.error("unknown entry attr format 0x" + strconv.FormatInt(int64(fmt), 16)) - - // address - case formAddr: - val = b.addr() - - // block - case formDwarfBlock1: - val = b.bytes(int(b.uint8())) - case formDwarfBlock2: - val = b.bytes(int(b.uint16())) - case formDwarfBlock4: - val = b.bytes(int(b.uint32())) - case formDwarfBlock: - val = b.bytes(int(b.uint())) - - // constant - case formData1: - val = int64(b.uint8()) - case formData2: - val = int64(b.uint16()) - case formData4: - val = int64(b.uint32()) - case formData8: - val = int64(b.uint64()) - case formSdata: - val = int64(b.int()) - case formUdata: - val = int64(b.uint()) - - // flag - case formFlag: - val = b.uint8() == 1 - // New in DWARF 4. - case formFlagPresent: - // The attribute is implicitly indicated as present, and no value is - // encoded in the debugging information entry itself. - val = true - - // reference to other entry - case formRefAddr: - vers := b.format.version() - if vers == 0 { - b.error("unknown version for DW_FORM_ref_addr") - } else if vers == 2 { - val = Offset(b.addr()) - } else { - is64, known := b.format.dwarf64() - if !known { - b.error("unknown size for DW_FORM_ref_addr") - } else if is64 { - val = Offset(b.uint64()) - } else { - val = Offset(b.uint32()) - } - } - case formRef1: - val = Offset(b.uint8()) + ubase - case formRef2: - val = Offset(b.uint16()) + ubase - case formRef4: - val = Offset(b.uint32()) + ubase - case formRef8: - val = Offset(b.uint64()) + ubase - case formRefUdata: - val = Offset(b.uint()) + ubase - - // string - case formString: - val = b.string() - case formStrp: - off := b.uint32() // offset into .debug_str - if b.err != nil { - return nil - } - b1 := makeBuf(b.dwarf, unknownFormat{}, "str", 0, b.dwarf.str) - b1.skip(int(off)) - val = b1.string() - if b1.err != nil { - b.err = b1.err - return nil - } - - // lineptr, loclistptr, macptr, rangelistptr - // New in DWARF 4, but clang can generate them with -gdwarf-2. - // Section reference, replacing use of formData4 and formData8. - case formSecOffset, formGnuRefAlt, formGnuStrpAlt: - is64, known := b.format.dwarf64() - if !known { - b.error("unknown size for form 0x" + strconv.FormatInt(int64(fmt), 16)) - } else if is64 { - val = int64(b.uint64()) - } else { - val = int64(b.uint32()) - } - - // exprloc - // New in DWARF 4. - case formExprloc: - val = b.bytes(int(b.uint())) - - // reference - // New in DWARF 4. - case formRefSig8: - // 64-bit type signature. - val = b.uint64() - } - e.Field[i].Val = val - } - if b.err != nil { - return nil - } - return e -} - -// A Reader allows reading Entry structures from a DWARF ``info'' section. -// The Entry structures are arranged in a tree. The Reader's Next function -// return successive entries from a pre-order traversal of the tree. -// If an entry has children, its Children field will be true, and the children -// follow, terminated by an Entry with Tag 0. -type Reader struct { - b buf - d *Data - err error - unit int - lastChildren bool // .Children of last entry returned by Next - lastSibling Offset // .Val(AttrSibling) of last entry returned by Next -} - -// Reader returns a new Reader for Data. -// The reader is positioned at byte offset 0 in the DWARF ``info'' section. -func (d *Data) Reader() *Reader { - r := &Reader{d: d} - r.Seek(0) - return r -} - -// Seek positions the Reader at offset off in the encoded entry stream. -// Offset 0 can be used to denote the first entry. -func (r *Reader) Seek(off Offset) { - d := r.d - r.err = nil - r.lastChildren = false - if off == 0 { - if len(d.unit) == 0 { - return - } - u := &d.unit[0] - r.unit = 0 - r.b = makeBuf(r.d, u, "info", u.off, u.data) - return - } - - // TODO(rsc): binary search (maybe a new package) - var i int - var u *unit - for i = range d.unit { - u = &d.unit[i] - if u.off <= off && off < u.off+Offset(len(u.data)) { - r.unit = i - r.b = makeBuf(r.d, u, "info", off, u.data[off-u.off:]) - return - } - } - r.err = errors.New("offset out of range") -} - -// maybeNextUnit advances to the next unit if this one is finished. -func (r *Reader) maybeNextUnit() { - for len(r.b.data) == 0 && r.unit+1 < len(r.d.unit) { - r.unit++ - u := &r.d.unit[r.unit] - r.b = makeBuf(r.d, u, "info", u.off, u.data) - } -} - -// Next reads the next entry from the encoded entry stream. -// It returns nil, nil when it reaches the end of the section. -// It returns an error if the current offset is invalid or the data at the -// offset cannot be decoded as a valid Entry. -func (r *Reader) Next() (*Entry, error) { - if r.err != nil { - return nil, r.err - } - r.maybeNextUnit() - if len(r.b.data) == 0 { - return nil, nil - } - u := &r.d.unit[r.unit] - e := r.b.entry(u.atable, u.base) - if r.b.err != nil { - r.err = r.b.err - return nil, r.err - } - if e != nil { - r.lastChildren = e.Children - if r.lastChildren { - r.lastSibling, _ = e.Val(AttrSibling).(Offset) - } - } else { - r.lastChildren = false - } - return e, nil -} - -// SkipChildren skips over the child entries associated with -// the last Entry returned by Next. If that Entry did not have -// children or Next has not been called, SkipChildren is a no-op. -func (r *Reader) SkipChildren() { - if r.err != nil || !r.lastChildren { - return - } - - // If the last entry had a sibling attribute, - // that attribute gives the offset of the next - // sibling, so we can avoid decoding the - // child subtrees. - if r.lastSibling >= r.b.off { - r.Seek(r.lastSibling) - return - } - - for { - e, err := r.Next() - if err != nil || e == nil || e.Tag == 0 { - break - } - if e.Children { - r.SkipChildren() - } - } -} - -// clone returns a copy of the reader. This is used by the typeReader -// interface. -func (r *Reader) clone() typeReader { - return r.d.Reader() -} - -// offset returns the current buffer offset. This is used by the -// typeReader interface. -func (r *Reader) offset() Offset { - return r.b.off -} diff --git a/src/pkg/debug/dwarf/open.go b/src/pkg/debug/dwarf/open.go deleted file mode 100644 index c1b3f37ac..000000000 --- a/src/pkg/debug/dwarf/open.go +++ /dev/null @@ -1,87 +0,0 @@ -// Copyright 2009 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// Package dwarf provides access to DWARF debugging information loaded from -// executable files, as defined in the DWARF 2.0 Standard at -// http://dwarfstd.org/doc/dwarf-2.0.0.pdf -package dwarf - -import "encoding/binary" - -// Data represents the DWARF debugging information -// loaded from an executable file (for example, an ELF or Mach-O executable). -type Data struct { - // raw data - abbrev []byte - aranges []byte - frame []byte - info []byte - line []byte - pubnames []byte - ranges []byte - str []byte - - // parsed data - abbrevCache map[uint32]abbrevTable - order binary.ByteOrder - typeCache map[Offset]Type - typeSigs map[uint64]*typeUnit - unit []unit -} - -// New returns a new Data object initialized from the given parameters. -// Rather than calling this function directly, clients should typically use -// the DWARF method of the File type of the appropriate package debug/elf, -// debug/macho, or debug/pe. -// -// The []byte arguments are the data from the corresponding debug section -// in the object file; for example, for an ELF object, abbrev is the contents of -// the ".debug_abbrev" section. -func New(abbrev, aranges, frame, info, line, pubnames, ranges, str []byte) (*Data, error) { - d := &Data{ - abbrev: abbrev, - aranges: aranges, - frame: frame, - info: info, - line: line, - pubnames: pubnames, - ranges: ranges, - str: str, - abbrevCache: make(map[uint32]abbrevTable), - typeCache: make(map[Offset]Type), - typeSigs: make(map[uint64]*typeUnit), - } - - // Sniff .debug_info to figure out byte order. - // bytes 4:6 are the version, a tiny 16-bit number (1, 2, 3). - if len(d.info) < 6 { - return nil, DecodeError{"info", Offset(len(d.info)), "too short"} - } - x, y := d.info[4], d.info[5] - switch { - case x == 0 && y == 0: - return nil, DecodeError{"info", 4, "unsupported version 0"} - case x == 0: - d.order = binary.BigEndian - case y == 0: - d.order = binary.LittleEndian - default: - return nil, DecodeError{"info", 4, "cannot determine byte order"} - } - - u, err := d.parseUnits() - if err != nil { - return nil, err - } - d.unit = u - return d, nil -} - -// AddTypes will add one .debug_types section to the DWARF data. A -// typical object with DWARF version 4 debug info will have multiple -// .debug_types sections. The name is used for error reporting only, -// and serves to distinguish one .debug_types section from another. -func (d *Data) AddTypes(name string, types []byte) error { - return d.parseTypes(name, types) -} diff --git a/src/pkg/debug/dwarf/testdata/typedef.c b/src/pkg/debug/dwarf/testdata/typedef.c deleted file mode 100644 index f05f01564..000000000 --- a/src/pkg/debug/dwarf/testdata/typedef.c +++ /dev/null @@ -1,85 +0,0 @@ -// Copyright 2009 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -/* -Linux ELF: -gcc -gdwarf-2 -m64 -c typedef.c && gcc -gdwarf-2 -m64 -o typedef.elf typedef.o - -OS X Mach-O: -gcc -gdwarf-2 -m64 -c typedef.c -o typedef.macho -*/ -#include <complex.h> - -typedef volatile int* t_ptr_volatile_int; -typedef const char *t_ptr_const_char; -typedef long t_long; -typedef unsigned short t_ushort; -typedef int t_func_int_of_float_double(float, double); -typedef int (*t_ptr_func_int_of_float_double)(float, double); -typedef int (*t_ptr_func_int_of_float_complex)(float complex); -typedef int (*t_ptr_func_int_of_double_complex)(double complex); -typedef int (*t_ptr_func_int_of_long_double_complex)(long double complex); -typedef int *t_func_ptr_int_of_char_schar_uchar(char, signed char, unsigned char); -typedef void t_func_void_of_char(char); -typedef void t_func_void_of_void(void); -typedef void t_func_void_of_ptr_char_dots(char*, ...); -typedef struct my_struct { - volatile int vi; - char x : 1; - int y : 4; - int z[0]; - long long array[40]; - int zz[0]; -} t_my_struct; -typedef struct my_struct1 { - int zz [1]; -} t_my_struct1; -typedef union my_union { - volatile int vi; - char x : 1; - int y : 4; - long long array[40]; -} t_my_union; -typedef enum my_enum { - e1 = 1, - e2 = 2, - e3 = -5, - e4 = 1000000000000000LL, -} t_my_enum; - -typedef struct list t_my_list; -struct list { - short val; - t_my_list *next; -}; - -typedef struct tree { - struct tree *left, *right; - unsigned long long val; -} t_my_tree; - -t_ptr_volatile_int *a2; -t_ptr_const_char **a3a; -t_long *a4; -t_ushort *a5; -t_func_int_of_float_double *a6; -t_ptr_func_int_of_float_double *a7; -t_func_ptr_int_of_char_schar_uchar *a8; -t_func_void_of_char *a9; -t_func_void_of_void *a10; -t_func_void_of_ptr_char_dots *a11; -t_my_struct *a12; -t_my_struct1 *a12a; -t_my_union *a12b; -t_my_enum *a13; -t_my_list *a14; -t_my_tree *a15; -t_ptr_func_int_of_float_complex *a16; -t_ptr_func_int_of_double_complex *a17; -t_ptr_func_int_of_long_double_complex *a18; - -int main() -{ - return 0; -} diff --git a/src/pkg/debug/dwarf/testdata/typedef.elf b/src/pkg/debug/dwarf/testdata/typedef.elf Binary files differdeleted file mode 100755 index b2062d2c4..000000000 --- a/src/pkg/debug/dwarf/testdata/typedef.elf +++ /dev/null diff --git a/src/pkg/debug/dwarf/testdata/typedef.elf4 b/src/pkg/debug/dwarf/testdata/typedef.elf4 Binary files differdeleted file mode 100644 index 3d5a5a1b1..000000000 --- a/src/pkg/debug/dwarf/testdata/typedef.elf4 +++ /dev/null diff --git a/src/pkg/debug/dwarf/testdata/typedef.macho b/src/pkg/debug/dwarf/testdata/typedef.macho Binary files differdeleted file mode 100644 index f75afcccb..000000000 --- a/src/pkg/debug/dwarf/testdata/typedef.macho +++ /dev/null diff --git a/src/pkg/debug/dwarf/type.go b/src/pkg/debug/dwarf/type.go deleted file mode 100644 index 68866d0b7..000000000 --- a/src/pkg/debug/dwarf/type.go +++ /dev/null @@ -1,659 +0,0 @@ -// Copyright 2009 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// DWARF type information structures. -// The format is heavily biased toward C, but for simplicity -// the String methods use a pseudo-Go syntax. - -package dwarf - -import "strconv" - -// A Type conventionally represents a pointer to any of the -// specific Type structures (CharType, StructType, etc.). -type Type interface { - Common() *CommonType - String() string - Size() int64 -} - -// A CommonType holds fields common to multiple types. -// If a field is not known or not applicable for a given type, -// the zero value is used. -type CommonType struct { - ByteSize int64 // size of value of this type, in bytes - Name string // name that can be used to refer to type -} - -func (c *CommonType) Common() *CommonType { return c } - -func (c *CommonType) Size() int64 { return c.ByteSize } - -// Basic types - -// A BasicType holds fields common to all basic types. -type BasicType struct { - CommonType - BitSize int64 - BitOffset int64 -} - -func (b *BasicType) Basic() *BasicType { return b } - -func (t *BasicType) String() string { - if t.Name != "" { - return t.Name - } - return "?" -} - -// A CharType represents a signed character type. -type CharType struct { - BasicType -} - -// A UcharType represents an unsigned character type. -type UcharType struct { - BasicType -} - -// An IntType represents a signed integer type. -type IntType struct { - BasicType -} - -// A UintType represents an unsigned integer type. -type UintType struct { - BasicType -} - -// A FloatType represents a floating point type. -type FloatType struct { - BasicType -} - -// A ComplexType represents a complex floating point type. -type ComplexType struct { - BasicType -} - -// A BoolType represents a boolean type. -type BoolType struct { - BasicType -} - -// An AddrType represents a machine address type. -type AddrType struct { - BasicType -} - -// qualifiers - -// A QualType represents a type that has the C/C++ "const", "restrict", or "volatile" qualifier. -type QualType struct { - CommonType - Qual string - Type Type -} - -func (t *QualType) String() string { return t.Qual + " " + t.Type.String() } - -func (t *QualType) Size() int64 { return t.Type.Size() } - -// An ArrayType represents a fixed size array type. -type ArrayType struct { - CommonType - Type Type - StrideBitSize int64 // if > 0, number of bits to hold each element - Count int64 // if == -1, an incomplete array, like char x[]. -} - -func (t *ArrayType) String() string { - return "[" + strconv.FormatInt(t.Count, 10) + "]" + t.Type.String() -} - -func (t *ArrayType) Size() int64 { return t.Count * t.Type.Size() } - -// A VoidType represents the C void type. -type VoidType struct { - CommonType -} - -func (t *VoidType) String() string { return "void" } - -// A PtrType represents a pointer type. -type PtrType struct { - CommonType - Type Type -} - -func (t *PtrType) String() string { return "*" + t.Type.String() } - -// A StructType represents a struct, union, or C++ class type. -type StructType struct { - CommonType - StructName string - Kind string // "struct", "union", or "class". - Field []*StructField - Incomplete bool // if true, struct, union, class is declared but not defined -} - -// A StructField represents a field in a struct, union, or C++ class type. -type StructField struct { - Name string - Type Type - ByteOffset int64 - ByteSize int64 - BitOffset int64 // within the ByteSize bytes at ByteOffset - BitSize int64 // zero if not a bit field -} - -func (t *StructType) String() string { - if t.StructName != "" { - return t.Kind + " " + t.StructName - } - return t.Defn() -} - -func (t *StructType) Defn() string { - s := t.Kind - if t.StructName != "" { - s += " " + t.StructName - } - if t.Incomplete { - s += " /*incomplete*/" - return s - } - s += " {" - for i, f := range t.Field { - if i > 0 { - s += "; " - } - s += f.Name + " " + f.Type.String() - s += "@" + strconv.FormatInt(f.ByteOffset, 10) - if f.BitSize > 0 { - s += " : " + strconv.FormatInt(f.BitSize, 10) - s += "@" + strconv.FormatInt(f.BitOffset, 10) - } - } - s += "}" - return s -} - -// An EnumType represents an enumerated type. -// The only indication of its native integer type is its ByteSize -// (inside CommonType). -type EnumType struct { - CommonType - EnumName string - Val []*EnumValue -} - -// An EnumValue represents a single enumeration value. -type EnumValue struct { - Name string - Val int64 -} - -func (t *EnumType) String() string { - s := "enum" - if t.EnumName != "" { - s += " " + t.EnumName - } - s += " {" - for i, v := range t.Val { - if i > 0 { - s += "; " - } - s += v.Name + "=" + strconv.FormatInt(v.Val, 10) - } - s += "}" - return s -} - -// A FuncType represents a function type. -type FuncType struct { - CommonType - ReturnType Type - ParamType []Type -} - -func (t *FuncType) String() string { - s := "func(" - for i, t := range t.ParamType { - if i > 0 { - s += ", " - } - s += t.String() - } - s += ")" - if t.ReturnType != nil { - s += " " + t.ReturnType.String() - } - return s -} - -// A DotDotDotType represents the variadic ... function parameter. -type DotDotDotType struct { - CommonType -} - -func (t *DotDotDotType) String() string { return "..." } - -// A TypedefType represents a named type. -type TypedefType struct { - CommonType - Type Type -} - -func (t *TypedefType) String() string { return t.Name } - -func (t *TypedefType) Size() int64 { return t.Type.Size() } - -// typeReader is used to read from either the info section or the -// types section. -type typeReader interface { - Seek(Offset) - Next() (*Entry, error) - clone() typeReader - offset() Offset -} - -// Type reads the type at off in the DWARF ``info'' section. -func (d *Data) Type(off Offset) (Type, error) { - return d.readType("info", d.Reader(), off, d.typeCache) -} - -// readType reads a type from r at off of name using and updating a -// type cache. -func (d *Data) readType(name string, r typeReader, off Offset, typeCache map[Offset]Type) (Type, error) { - if t, ok := typeCache[off]; ok { - return t, nil - } - r.Seek(off) - e, err := r.Next() - if err != nil { - return nil, err - } - if e == nil || e.Offset != off { - return nil, DecodeError{name, off, "no type at offset"} - } - - // Parse type from Entry. - // Must always set typeCache[off] before calling - // d.Type recursively, to handle circular types correctly. - var typ Type - - nextDepth := 0 - - // Get next child; set err if error happens. - next := func() *Entry { - if !e.Children { - return nil - } - // Only return direct children. - // Skip over composite entries that happen to be nested - // inside this one. Most DWARF generators wouldn't generate - // such a thing, but clang does. - // See golang.org/issue/6472. - for { - kid, err1 := r.Next() - if err1 != nil { - err = err1 - return nil - } - if kid == nil { - err = DecodeError{name, r.offset(), "unexpected end of DWARF entries"} - return nil - } - if kid.Tag == 0 { - if nextDepth > 0 { - nextDepth-- - continue - } - return nil - } - if kid.Children { - nextDepth++ - } - if nextDepth > 0 { - continue - } - return kid - } - } - - // Get Type referred to by Entry's AttrType field. - // Set err if error happens. Not having a type is an error. - typeOf := func(e *Entry) Type { - tval := e.Val(AttrType) - var t Type - switch toff := tval.(type) { - case Offset: - if t, err = d.readType(name, r.clone(), toff, typeCache); err != nil { - return nil - } - case uint64: - if t, err = d.sigToType(toff); err != nil { - return nil - } - default: - // It appears that no Type means "void". - return new(VoidType) - } - return t - } - - switch e.Tag { - case TagArrayType: - // Multi-dimensional array. (DWARF v2 §5.4) - // Attributes: - // AttrType:subtype [required] - // AttrStrideSize: size in bits of each element of the array - // AttrByteSize: size of entire array - // Children: - // TagSubrangeType or TagEnumerationType giving one dimension. - // dimensions are in left to right order. - t := new(ArrayType) - typ = t - typeCache[off] = t - if t.Type = typeOf(e); err != nil { - goto Error - } - t.StrideBitSize, _ = e.Val(AttrStrideSize).(int64) - - // Accumulate dimensions, - ndim := 0 - for kid := next(); kid != nil; kid = next() { - // TODO(rsc): Can also be TagEnumerationType - // but haven't seen that in the wild yet. - switch kid.Tag { - case TagSubrangeType: - max, ok := kid.Val(AttrUpperBound).(int64) - if !ok { - max = -2 // Count == -1, as in x[]. - } - if ndim == 0 { - t.Count = max + 1 - } else { - // Multidimensional array. - // Create new array type underneath this one. - t.Type = &ArrayType{Type: t.Type, Count: max + 1} - } - ndim++ - case TagEnumerationType: - err = DecodeError{name, kid.Offset, "cannot handle enumeration type as array bound"} - goto Error - } - } - if ndim == 0 { - // LLVM generates this for x[]. - t.Count = -1 - } - - case TagBaseType: - // Basic type. (DWARF v2 §5.1) - // Attributes: - // AttrName: name of base type in programming language of the compilation unit [required] - // AttrEncoding: encoding value for type (encFloat etc) [required] - // AttrByteSize: size of type in bytes [required] - // AttrBitOffset: for sub-byte types, size in bits - // AttrBitSize: for sub-byte types, bit offset of high order bit in the AttrByteSize bytes - name, _ := e.Val(AttrName).(string) - enc, ok := e.Val(AttrEncoding).(int64) - if !ok { - err = DecodeError{name, e.Offset, "missing encoding attribute for " + name} - goto Error - } - switch enc { - default: - err = DecodeError{name, e.Offset, "unrecognized encoding attribute value"} - goto Error - - case encAddress: - typ = new(AddrType) - case encBoolean: - typ = new(BoolType) - case encComplexFloat: - typ = new(ComplexType) - case encFloat: - typ = new(FloatType) - case encSigned: - typ = new(IntType) - case encUnsigned: - typ = new(UintType) - case encSignedChar: - typ = new(CharType) - case encUnsignedChar: - typ = new(UcharType) - } - typeCache[off] = typ - t := typ.(interface { - Basic() *BasicType - }).Basic() - t.Name = name - t.BitSize, _ = e.Val(AttrBitSize).(int64) - t.BitOffset, _ = e.Val(AttrBitOffset).(int64) - - case TagClassType, TagStructType, TagUnionType: - // Structure, union, or class type. (DWARF v2 §5.5) - // Attributes: - // AttrName: name of struct, union, or class - // AttrByteSize: byte size [required] - // AttrDeclaration: if true, struct/union/class is incomplete - // Children: - // TagMember to describe one member. - // AttrName: name of member [required] - // AttrType: type of member [required] - // AttrByteSize: size in bytes - // AttrBitOffset: bit offset within bytes for bit fields - // AttrBitSize: bit size for bit fields - // AttrDataMemberLoc: location within struct [required for struct, class] - // There is much more to handle C++, all ignored for now. - t := new(StructType) - typ = t - typeCache[off] = t - switch e.Tag { - case TagClassType: - t.Kind = "class" - case TagStructType: - t.Kind = "struct" - case TagUnionType: - t.Kind = "union" - } - t.StructName, _ = e.Val(AttrName).(string) - t.Incomplete = e.Val(AttrDeclaration) != nil - t.Field = make([]*StructField, 0, 8) - var lastFieldType Type - var lastFieldBitOffset int64 - for kid := next(); kid != nil; kid = next() { - if kid.Tag == TagMember { - f := new(StructField) - if f.Type = typeOf(kid); err != nil { - goto Error - } - switch loc := kid.Val(AttrDataMemberLoc).(type) { - case []byte: - // TODO: Should have original compilation - // unit here, not unknownFormat. - b := makeBuf(d, unknownFormat{}, "location", 0, loc) - if b.uint8() != opPlusUconst { - err = DecodeError{name, kid.Offset, "unexpected opcode"} - goto Error - } - f.ByteOffset = int64(b.uint()) - if b.err != nil { - err = b.err - goto Error - } - case int64: - f.ByteOffset = loc - } - - haveBitOffset := false - f.Name, _ = kid.Val(AttrName).(string) - f.ByteSize, _ = kid.Val(AttrByteSize).(int64) - f.BitOffset, haveBitOffset = kid.Val(AttrBitOffset).(int64) - f.BitSize, _ = kid.Val(AttrBitSize).(int64) - t.Field = append(t.Field, f) - - bito := f.BitOffset - if !haveBitOffset { - bito = f.ByteOffset * 8 - } - if bito == lastFieldBitOffset && t.Kind != "union" { - // Last field was zero width. Fix array length. - // (DWARF writes out 0-length arrays as if they were 1-length arrays.) - zeroArray(lastFieldType) - } - lastFieldType = f.Type - lastFieldBitOffset = bito - } - } - if t.Kind != "union" { - b, ok := e.Val(AttrByteSize).(int64) - if ok && b*8 == lastFieldBitOffset { - // Final field must be zero width. Fix array length. - zeroArray(lastFieldType) - } - } - - case TagConstType, TagVolatileType, TagRestrictType: - // Type modifier (DWARF v2 §5.2) - // Attributes: - // AttrType: subtype - t := new(QualType) - typ = t - typeCache[off] = t - if t.Type = typeOf(e); err != nil { - goto Error - } - switch e.Tag { - case TagConstType: - t.Qual = "const" - case TagRestrictType: - t.Qual = "restrict" - case TagVolatileType: - t.Qual = "volatile" - } - - case TagEnumerationType: - // Enumeration type (DWARF v2 §5.6) - // Attributes: - // AttrName: enum name if any - // AttrByteSize: bytes required to represent largest value - // Children: - // TagEnumerator: - // AttrName: name of constant - // AttrConstValue: value of constant - t := new(EnumType) - typ = t - typeCache[off] = t - t.EnumName, _ = e.Val(AttrName).(string) - t.Val = make([]*EnumValue, 0, 8) - for kid := next(); kid != nil; kid = next() { - if kid.Tag == TagEnumerator { - f := new(EnumValue) - f.Name, _ = kid.Val(AttrName).(string) - f.Val, _ = kid.Val(AttrConstValue).(int64) - n := len(t.Val) - if n >= cap(t.Val) { - val := make([]*EnumValue, n, n*2) - copy(val, t.Val) - t.Val = val - } - t.Val = t.Val[0 : n+1] - t.Val[n] = f - } - } - - case TagPointerType: - // Type modifier (DWARF v2 §5.2) - // Attributes: - // AttrType: subtype [not required! void* has no AttrType] - // AttrAddrClass: address class [ignored] - t := new(PtrType) - typ = t - typeCache[off] = t - if e.Val(AttrType) == nil { - t.Type = &VoidType{} - break - } - t.Type = typeOf(e) - - case TagSubroutineType: - // Subroutine type. (DWARF v2 §5.7) - // Attributes: - // AttrType: type of return value if any - // AttrName: possible name of type [ignored] - // AttrPrototyped: whether used ANSI C prototype [ignored] - // Children: - // TagFormalParameter: typed parameter - // AttrType: type of parameter - // TagUnspecifiedParameter: final ... - t := new(FuncType) - typ = t - typeCache[off] = t - if t.ReturnType = typeOf(e); err != nil { - goto Error - } - t.ParamType = make([]Type, 0, 8) - for kid := next(); kid != nil; kid = next() { - var tkid Type - switch kid.Tag { - default: - continue - case TagFormalParameter: - if tkid = typeOf(kid); err != nil { - goto Error - } - case TagUnspecifiedParameters: - tkid = &DotDotDotType{} - } - t.ParamType = append(t.ParamType, tkid) - } - - case TagTypedef: - // Typedef (DWARF v2 §5.3) - // Attributes: - // AttrName: name [required] - // AttrType: type definition [required] - t := new(TypedefType) - typ = t - typeCache[off] = t - t.Name, _ = e.Val(AttrName).(string) - t.Type = typeOf(e) - } - - if err != nil { - goto Error - } - - { - b, ok := e.Val(AttrByteSize).(int64) - if !ok { - b = -1 - } - typ.Common().ByteSize = b - } - return typ, nil - -Error: - // If the parse fails, take the type out of the cache - // so that the next call with this offset doesn't hit - // the cache and return success. - delete(typeCache, off) - return nil, err -} - -func zeroArray(t Type) { - for { - at, ok := t.(*ArrayType) - if !ok { - break - } - at.Count = 0 - t = at.Type - } -} diff --git a/src/pkg/debug/dwarf/type_test.go b/src/pkg/debug/dwarf/type_test.go deleted file mode 100644 index 2cb85e74b..000000000 --- a/src/pkg/debug/dwarf/type_test.go +++ /dev/null @@ -1,122 +0,0 @@ -// Copyright 2009 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package dwarf_test - -import ( - . "debug/dwarf" - "debug/elf" - "debug/macho" - "testing" -) - -var typedefTests = map[string]string{ - "t_ptr_volatile_int": "*volatile int", - "t_ptr_const_char": "*const char", - "t_long": "long int", - "t_ushort": "short unsigned int", - "t_func_int_of_float_double": "func(float, double) int", - "t_ptr_func_int_of_float_double": "*func(float, double) int", - "t_ptr_func_int_of_float_complex": "*func(complex float) int", - "t_ptr_func_int_of_double_complex": "*func(complex double) int", - "t_ptr_func_int_of_long_double_complex": "*func(complex long double) int", - "t_func_ptr_int_of_char_schar_uchar": "func(char, signed char, unsigned char) *int", - "t_func_void_of_char": "func(char) void", - "t_func_void_of_void": "func() void", - "t_func_void_of_ptr_char_dots": "func(*char, ...) void", - "t_my_struct": "struct my_struct {vi volatile int@0; x char@4 : 1@7; y int@4 : 4@27; z [0]int@8; array [40]long long int@8; zz [0]int@328}", - "t_my_struct1": "struct my_struct1 {zz [1]int@0}", - "t_my_union": "union my_union {vi volatile int@0; x char@0 : 1@7; y int@0 : 4@28; array [40]long long int@0}", - "t_my_enum": "enum my_enum {e1=1; e2=2; e3=-5; e4=1000000000000000}", - "t_my_list": "struct list {val short int@0; next *t_my_list@8}", - "t_my_tree": "struct tree {left *struct tree@0; right *struct tree@8; val long long unsigned int@16}", -} - -// As Apple converts gcc to a clang-based front end -// they keep breaking the DWARF output. This map lists the -// conversion from real answer to Apple answer. -var machoBug = map[string]string{ - "func(*char, ...) void": "func(*char) void", - "enum my_enum {e1=1; e2=2; e3=-5; e4=1000000000000000}": "enum my_enum {e1=1; e2=2; e3=-5; e4=-1530494976}", -} - -func elfData(t *testing.T, name string) *Data { - f, err := elf.Open(name) - if err != nil { - t.Fatal(err) - } - - d, err := f.DWARF() - if err != nil { - t.Fatal(err) - } - return d -} - -func machoData(t *testing.T, name string) *Data { - f, err := macho.Open(name) - if err != nil { - t.Fatal(err) - } - - d, err := f.DWARF() - if err != nil { - t.Fatal(err) - } - return d -} - -func TestTypedefsELF(t *testing.T) { testTypedefs(t, elfData(t, "testdata/typedef.elf"), "elf") } - -func TestTypedefsMachO(t *testing.T) { - testTypedefs(t, machoData(t, "testdata/typedef.macho"), "macho") -} - -func TestTypedefsELFDwarf4(t *testing.T) { testTypedefs(t, elfData(t, "testdata/typedef.elf4"), "elf") } - -func testTypedefs(t *testing.T, d *Data, kind string) { - r := d.Reader() - seen := make(map[string]bool) - for { - e, err := r.Next() - if err != nil { - t.Fatal("r.Next:", err) - } - if e == nil { - break - } - if e.Tag == TagTypedef { - typ, err := d.Type(e.Offset) - if err != nil { - t.Fatal("d.Type:", err) - } - t1 := typ.(*TypedefType) - var typstr string - if ts, ok := t1.Type.(*StructType); ok { - typstr = ts.Defn() - } else { - typstr = t1.Type.String() - } - - if want, ok := typedefTests[t1.Name]; ok { - if seen[t1.Name] { - t.Errorf("multiple definitions for %s", t1.Name) - } - seen[t1.Name] = true - if typstr != want && (kind != "macho" || typstr != machoBug[want]) { - t.Errorf("%s:\n\thave %s\n\twant %s", t1.Name, typstr, want) - } - } - } - if e.Tag != TagCompileUnit { - r.SkipChildren() - } - } - - for k := range typedefTests { - if !seen[k] { - t.Errorf("missing %s", k) - } - } -} diff --git a/src/pkg/debug/dwarf/typeunit.go b/src/pkg/debug/dwarf/typeunit.go deleted file mode 100644 index 3fd1c9973..000000000 --- a/src/pkg/debug/dwarf/typeunit.go +++ /dev/null @@ -1,166 +0,0 @@ -// Copyright 2012 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package dwarf - -import ( - "fmt" - "strconv" -) - -// Parse the type units stored in a DWARF4 .debug_types section. Each -// type unit defines a single primary type and an 8-byte signature. -// Other sections may then use formRefSig8 to refer to the type. - -// The typeUnit format is a single type with a signature. It holds -// the same data as a compilation unit. -type typeUnit struct { - unit - toff Offset // Offset to signature type within data. - name string // Name of .debug_type section. - cache Type // Cache the type, nil to start. -} - -// Parse a .debug_types section. -func (d *Data) parseTypes(name string, types []byte) error { - b := makeBuf(d, unknownFormat{}, name, 0, types) - for len(b.data) > 0 { - base := b.off - dwarf64 := false - n := b.uint32() - if n == 0xffffffff { - n64 := b.uint64() - if n64 != uint64(uint32(n64)) { - b.error("type unit length overflow") - return b.err - } - n = uint32(n64) - dwarf64 = true - } - hdroff := b.off - vers := b.uint16() - if vers != 4 { - b.error("unsupported DWARF version " + strconv.Itoa(int(vers))) - return b.err - } - var ao uint32 - if !dwarf64 { - ao = b.uint32() - } else { - ao64 := b.uint64() - if ao64 != uint64(uint32(ao64)) { - b.error("type unit abbrev offset overflow") - return b.err - } - ao = uint32(ao64) - } - atable, err := d.parseAbbrev(ao) - if err != nil { - return err - } - asize := b.uint8() - sig := b.uint64() - - var toff uint32 - if !dwarf64 { - toff = b.uint32() - } else { - to64 := b.uint64() - if to64 != uint64(uint32(to64)) { - b.error("type unit type offset overflow") - return b.err - } - toff = uint32(to64) - } - - boff := b.off - d.typeSigs[sig] = &typeUnit{ - unit: unit{ - base: base, - off: boff, - data: b.bytes(int(Offset(n) - (b.off - hdroff))), - atable: atable, - asize: int(asize), - vers: int(vers), - is64: dwarf64, - }, - toff: Offset(toff), - name: name, - } - if b.err != nil { - return b.err - } - } - return nil -} - -// Return the type for a type signature. -func (d *Data) sigToType(sig uint64) (Type, error) { - tu := d.typeSigs[sig] - if tu == nil { - return nil, fmt.Errorf("no type unit with signature %v", sig) - } - if tu.cache != nil { - return tu.cache, nil - } - - b := makeBuf(d, tu, tu.name, tu.off, tu.data) - r := &typeUnitReader{d: d, tu: tu, b: b} - t, err := d.readType(tu.name, r, Offset(tu.toff), make(map[Offset]Type)) - if err != nil { - return nil, err - } - - tu.cache = t - return t, nil -} - -// typeUnitReader is a typeReader for a tagTypeUnit. -type typeUnitReader struct { - d *Data - tu *typeUnit - b buf - err error -} - -// Seek to a new position in the type unit. -func (tur *typeUnitReader) Seek(off Offset) { - tur.err = nil - doff := off - tur.tu.off - if doff < 0 || doff >= Offset(len(tur.tu.data)) { - tur.err = fmt.Errorf("%s: offset %d out of range; max %d", tur.tu.name, doff, len(tur.tu.data)) - return - } - tur.b = makeBuf(tur.d, tur.tu, tur.tu.name, off, tur.tu.data[doff:]) -} - -// Next reads the next Entry from the type unit. -func (tur *typeUnitReader) Next() (*Entry, error) { - if tur.err != nil { - return nil, tur.err - } - if len(tur.tu.data) == 0 { - return nil, nil - } - e := tur.b.entry(tur.tu.atable, tur.tu.base) - if tur.b.err != nil { - tur.err = tur.b.err - return nil, tur.err - } - return e, nil -} - -// clone returns a new reader for the type unit. -func (tur *typeUnitReader) clone() typeReader { - return &typeUnitReader{ - d: tur.d, - tu: tur.tu, - b: makeBuf(tur.d, tur.tu, tur.tu.name, tur.tu.off, tur.tu.data), - } -} - -// offset returns the current offset. -func (tur *typeUnitReader) offset() Offset { - return tur.b.off -} diff --git a/src/pkg/debug/dwarf/unit.go b/src/pkg/debug/dwarf/unit.go deleted file mode 100644 index 0fbc8e082..000000000 --- a/src/pkg/debug/dwarf/unit.go +++ /dev/null @@ -1,90 +0,0 @@ -// Copyright 2009 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package dwarf - -import "strconv" - -// DWARF debug info is split into a sequence of compilation units. -// Each unit has its own abbreviation table and address size. - -type unit struct { - base Offset // byte offset of header within the aggregate info - off Offset // byte offset of data within the aggregate info - data []byte - atable abbrevTable - asize int - vers int - is64 bool // True for 64-bit DWARF format -} - -// Implement the dataFormat interface. - -func (u *unit) version() int { - return u.vers -} - -func (u *unit) dwarf64() (bool, bool) { - return u.is64, true -} - -func (u *unit) addrsize() int { - return u.asize -} - -func (d *Data) parseUnits() ([]unit, error) { - // Count units. - nunit := 0 - b := makeBuf(d, unknownFormat{}, "info", 0, d.info) - for len(b.data) > 0 { - len := b.uint32() - if len == 0xffffffff { - len64 := b.uint64() - if len64 != uint64(uint32(len64)) { - b.error("unit length overflow") - break - } - len = uint32(len64) - } - b.skip(int(len)) - nunit++ - } - if b.err != nil { - return nil, b.err - } - - // Again, this time writing them down. - b = makeBuf(d, unknownFormat{}, "info", 0, d.info) - units := make([]unit, nunit) - for i := range units { - u := &units[i] - u.base = b.off - n := b.uint32() - if n == 0xffffffff { - u.is64 = true - n = uint32(b.uint64()) - } - vers := b.uint16() - if vers != 2 && vers != 3 && vers != 4 { - b.error("unsupported DWARF version " + strconv.Itoa(int(vers))) - break - } - u.vers = int(vers) - atable, err := d.parseAbbrev(b.uint32()) - if err != nil { - if b.err == nil { - b.err = err - } - break - } - u.atable = atable - u.asize = int(b.uint8()) - u.off = b.off - u.data = b.bytes(int(n - (2 + 4 + 1))) - } - if b.err != nil { - return nil, b.err - } - return units, nil -} |