Example #1
0
// 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, fmt.Errorf("no type entry found")
}
Example #2
0
func (d *DWARFHelper) toContentMethod(e *dwarf.Entry) (m content.Method, err error) {
	if v, ok := e.Val(dwarf.AttrName).(string); ok {
		m.Name.Relative = v
	}
	if v, ok := e.Val(dwarf.AttrType).(dwarf.Offset); ok {
		if t, err := d.GetType(v); err != nil {
			return m, err
		} else {
			m.Returns = append(m.Returns, content.Variable{Type: t})
		}
	} else {
		m.Returns = append(m.Returns, content.Variable{Type: content.Type{Name: content.FullyQualifiedName{Relative: "void"}}})
	}
	m.Flags = d.Flags(e)
	if !e.Children {
		return
	}
	r := d.df.Reader()
	r.Seek(e.Offset)
	for {
		e, err := r.Next()
		if err != nil {
			return m, err
		} else if e == nil || e.Tag == 0 {
			break
		}
		if e.Tag != dwarf.TagFormalParameter {
			continue
		}
		var p content.Variable
		if v, ok := e.Val(dwarf.AttrType).(dwarf.Offset); ok {
			if t, err := d.GetType(v); err != nil {
				return m, err
			} else {
				p.Type = t
			}
		}
		if v, ok := e.Val(dwarf.AttrName).(string); ok {
			p.Name.Relative = v
		}
		if v, ok := e.Val(dwarf.AttrArtificial).(bool); ok && v {
			if p.Type.Flags&content.FLAG_TYPE_MASK != content.FLAG_TYPE_POINTER {
				m.Parameters = append(m.Parameters, p)
				continue
			}
			// C++ "this" pointer
			t := p.Type.Specialization[0]
			if t.Flags&content.FLAG_CONST != 0 {
				m.Flags |= content.FLAG_CONST
			}
			//m.Name.Absolute = t.Name.Relative + "::" + m.Name.Relative
		} else {
			m.Parameters = append(m.Parameters, p)
		}
	}
	return
}
Example #3
0
//============================================================================
//		processCompileUnit : Process a compile unit.
//----------------------------------------------------------------------------
func processCompileUnit(theReader *dwarf.Reader, depth int, theEntry *dwarf.Entry) {

	// Process the entry
	gCurrentFile = theEntry.Val(dwarf.AttrName).(string)

	if theEntry.Children {
		processChildren(theReader, depth+1, false)
	}

	gCurrentFile = ""

}
Example #4
0
func (d *DWARFHelper) Flags(e *dwarf.Entry) (ret content.Flags) {
	if v, ok := e.Val(dwarf.AttrAccessibility).(int64); ok {
		switch v {
		case 1:
			ret |= content.FLAG_ACC_PUBLIC
		case 2:
			ret |= content.FLAG_ACC_PROTECTED
		case 3:
			ret |= content.FLAG_ACC_PRIVATE
		}
	}
	return
}
Example #5
0
//============================================================================
//		processSubprogram : Process a subprogram.
//----------------------------------------------------------------------------
func processSubprogram(theReader *dwarf.Reader, depth int, theEntry *dwarf.Entry) {

	var lowAddr uint64
	var highAddr uint64

	// Get the state we need
	lowVal := theEntry.Val(dwarf.AttrLowpc)
	highVal := theEntry.Val(dwarf.AttrHighpc)

	if lowVal != nil && highVal != nil {
		lowAddr = lowVal.(uint64)
		highAddr = highVal.(uint64)
	}

	// Check for a match
	if gTargetAddress >= lowAddr && gTargetAddress < highAddr {
		name := theEntry.Val(dwarf.AttrName)
		line := theEntry.Val(dwarf.AttrDeclLine)

		fmt.Printf("%v (%v:%v)\n", name, path.Base(gCurrentFile), line)
	}

	// Process the entry
	if theEntry.Children {
		processChildren(theReader, depth+1, false)
	}
}
Example #6
0
func (d *DWARFHelper) toContentField(e *dwarf.Entry) (content.Field, error) {
	var f content.Field
	if v, ok := e.Val(dwarf.AttrName).(string); ok {
		f.Name.Relative = v
	}
	if v, ok := e.Val(dwarf.AttrType).(dwarf.Offset); ok {
		if t, err := d.GetType(v); err != nil {
			return f, err
		} else {
			f.Type = t
		}
	}
	f.Flags = d.Flags(e)
	return f, nil
}
Example #7
0
// dwarfSourceLineEntry tries to get file/line information from a
// DWARF compilation unit. Returns nil if it doesn't find anything.
func (f *file) dwarfSourceLineEntry(r *dwarf.Reader, entry *dwarf.Entry, addr uint64) []plugin.Frame {
	lines, err := f.dwarf.LineReader(entry)
	if err != nil {
		return nil
	}
	var lentry dwarf.LineEntry
	if err := lines.SeekPC(addr, &lentry); err != nil {
		return nil
	}

	// Try to find the function name.
	name := ""
FindName:
	for entry, err := r.Next(); entry != nil && err == nil; entry, err = r.Next() {
		if entry.Tag == dwarf.TagSubprogram {
			ranges, err := f.dwarf.Ranges(entry)
			if err != nil {
				return nil
			}
			for _, pcs := range ranges {
				if pcs[0] <= addr && addr < pcs[1] {
					var ok bool
					// TODO: AT_linkage_name, AT_MIPS_linkage_name.
					name, ok = entry.Val(dwarf.AttrName).(string)
					if ok {
						break FindName
					}
				}
			}
		}
	}

	// TODO: Report inlined functions.

	frames := []plugin.Frame{
		{
			Func: name,
			File: lentry.File.Name,
			Line: lentry.Line,
		},
	}

	return frames
}
Example #8
0
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
}
Example #9
0
// Extracts the name, type, and value of a variable from a dwarf entry
func (thread *Thread) extractVariableFromEntry(entry *dwarf.Entry) (*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")
	}

	data := thread.dbp.dwarf
	t, err := data.Type(offset)
	if err != nil {
		return nil, err
	}

	instructions, ok := entry.Val(dwarf.AttrLocation).([]byte)
	if !ok {
		return nil, fmt.Errorf("type assertion failed")
	}

	val, err := thread.extractValue(instructions, 0, t, true)
	if err != nil {
		return nil, err
	}

	return &Variable{Name: n, Type: t.String(), Value: val}, nil
}
Example #10
0
// 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
}
Example #11
0
func (thread *Thread) evaluateStructMember(parentEntry *dwarf.Entry, rdr *reader.Reader, memberName string) (*Variable, error) {
	parentAddr, err := thread.extractVariableDataAddress(parentEntry, rdr)
	if err != nil {
		return nil, err
	}

	// Get parent variable name
	parentName, ok := parentEntry.Val(dwarf.AttrName).(string)
	if !ok {
		return nil, fmt.Errorf("unable to retrive variable name")
	}

	// Seek reader to the type information so members can be iterated
	_, err = rdr.SeekToType(parentEntry, true, true)
	if err != nil {
		return nil, err
	}

	// Iterate to find member by name
	for memberEntry, err := rdr.NextMemberVariable(); memberEntry != nil; memberEntry, err = rdr.NextMemberVariable() {
		if err != nil {
			return nil, err
		}

		name, ok := memberEntry.Val(dwarf.AttrName).(string)
		if !ok {
			continue
		}

		if name == memberName {
			// Nil ptr, wait until here to throw a nil pointer error to prioritize no such member error
			if parentAddr == 0 {
				return nil, fmt.Errorf("%s is nil", parentName)
			}

			memberInstr, err := rdr.InstructionsForEntry(memberEntry)
			if err != nil {
				return nil, err
			}

			offset, ok := memberEntry.Val(dwarf.AttrType).(dwarf.Offset)
			if !ok {
				return nil, fmt.Errorf("type assertion failed")
			}

			data := thread.dbp.dwarf
			t, err := data.Type(offset)
			if err != nil {
				return nil, err
			}

			baseAddr := make([]byte, 8)
			binary.LittleEndian.PutUint64(baseAddr, uint64(parentAddr))

			parentInstructions := append([]byte{op.DW_OP_addr}, baseAddr...)
			val, err := thread.extractValue(append(parentInstructions, memberInstr...), 0, t, true)
			if err != nil {
				return nil, err
			}
			return &Variable{Name: strings.Join([]string{parentName, memberName}, "."), Type: t.String(), Value: val}, nil
		}
	}

	return nil, fmt.Errorf("%s has no member %s", parentName, memberName)
}