// SeekToType moves the reader to the type specified by the entry, // optionally resolving typedefs and pointer types. If the reader is set // to a struct type the NextMemberVariable call can be used to walk all member data. func (reader *Reader) SeekToType(entry *dwarf.Entry, resolveTypedefs bool, resolvePointerTypes bool) (*dwarf.Entry, error) { offset, ok := entry.Val(dwarf.AttrType).(dwarf.Offset) if !ok { return nil, fmt.Errorf("entry does not have a type attribute") } // Seek to the first type offset reader.Seek(offset) // Walk the types to the base for typeEntry, err := reader.Next(); typeEntry != nil; typeEntry, err = reader.Next() { if err != nil { return nil, err } if typeEntry.Tag == dwarf.TagTypedef && !resolveTypedefs { return typeEntry, nil } if typeEntry.Tag == dwarf.TagPointerType && !resolvePointerTypes { return typeEntry, nil } offset, ok = typeEntry.Val(dwarf.AttrType).(dwarf.Offset) if !ok { return typeEntry, nil } reader.Seek(offset) } return nil, TypeNotFoundErr }
func (reader *Reader) InstructionsForEntry(entry *dwarf.Entry) ([]byte, error) { if entry.Tag == dwarf.TagMember { instructions, ok := entry.Val(dwarf.AttrDataMemberLoc).([]byte) if !ok { return nil, fmt.Errorf("member data has no data member location attribute") } // clone slice to prevent stomping on the dwarf data return append([]byte{}, instructions...), nil } // non-member instructions, ok := entry.Val(dwarf.AttrLocation).([]byte) if !ok { return nil, fmt.Errorf("entry has no location attribute") } // clone slice to prevent stomping on the dwarf data return append([]byte{}, instructions...), nil }
// parseParameterOrLocal parses the entry for a function parameter or local // variable, which are both specified the same way. fp contains the frame // pointer, which is used to calculate the variable location. func (s *Server) parseParameterOrLocal(entry *dwarf.Entry, fp uint64) (program.LocalVar, error) { var v program.LocalVar v.Name, _ = entry.Val(dwarf.AttrName).(string) if off, err := s.dwarfData.EntryTypeOffset(entry); err != nil { return v, err } else { v.Var.TypeID = uint64(off) } if i := entry.Val(dwarf.AttrLocation); i == nil { return v, fmt.Errorf("missing location description") } else if locationDescription, ok := i.([]uint8); !ok { return v, fmt.Errorf("unsupported location description") } else if offset, err := evalLocation(locationDescription); err != nil { return v, err } else { v.Var.Address = fp + uint64(offset) } return v, nil }
// printEntryValueAt pretty-prints the data at the specified address. // using the type information in the Entry. func (p *Printer) printEntryValueAt(entry *dwarf.Entry, a uint64) { if a == 0 { p.printf("<nil>") return } switch entry.Tag { case dwarf.TagVariable, dwarf.TagFormalParameter: // OK default: p.errorf("unrecognized entry type %s", entry.Tag) return } iface := entry.Val(dwarf.AttrType) if iface == nil { p.errorf("no type") return } typ, err := p.dwarf.Type(iface.(dwarf.Offset)) if err != nil { p.errorf("type lookup: %v", err) return } p.printValueAt(typ, a) }
// Extracts the name and type of a variable from a dwarf entry // then executes the instructions given in the DW_AT_location attribute to grab the variable's address func (scope *EvalScope) extractVarInfoFromEntry(entry *dwarf.Entry, rdr *reader.Reader) (*Variable, error) { if entry == nil { return nil, fmt.Errorf("invalid entry") } if entry.Tag != dwarf.TagFormalParameter && entry.Tag != dwarf.TagVariable { return nil, fmt.Errorf("invalid entry tag, only supports FormalParameter and Variable, got %s", entry.Tag.String()) } n, ok := entry.Val(dwarf.AttrName).(string) if !ok { return nil, fmt.Errorf("type assertion failed") } offset, ok := entry.Val(dwarf.AttrType).(dwarf.Offset) if !ok { return nil, fmt.Errorf("type assertion failed") } t, err := scope.Type(offset) if err != nil { return nil, err } instructions, ok := entry.Val(dwarf.AttrLocation).([]byte) if !ok { return nil, fmt.Errorf("type assertion failed") } addr, err := op.ExecuteStackProgram(scope.CFA, instructions) if err != nil { return nil, err } return scope.newVariable(n, uintptr(addr), t), nil }