Esempio n. 1
0
// map from global address to Field at that address
func globalsMap(d *Dump, w *dwarf.Data, t map[dwarf.Offset]dwarfType) *heap {
	h := new(heap)
	r := w.Reader()
	for {
		e, err := r.Next()
		if err != nil {
			log.Fatal(err)
		}
		if e == nil {
			break
		}
		if e.Tag != dwarf.TagVariable {
			continue
		}
		name := e.Val(dwarf.AttrName).(string)
		typ := t[e.Val(dwarf.AttrType).(dwarf.Offset)]
		locexpr := e.Val(dwarf.AttrLocation).([]uint8)
		if len(locexpr) == 0 || locexpr[0] != dw_op_addr {
			continue
		}
		loc := readPtr(d, locexpr[1:])
		if typ == nil {
			// lots of non-Go global symbols hit here (rodata, reflect.cvtFloat·f, ...)
			h.Insert(loc, Field{FieldKindPtr, 0, "~" + name, ""})
			continue
		}
		for _, f := range typ.Fields() {
			h.Insert(loc+f.Offset, Field{f.Kind, 0, joinNames(name, f.Name), f.BaseType})
		}
	}
	return h
}
Esempio n. 2
0
//============================================================================
//		main : Entry point.
//----------------------------------------------------------------------------
func main() {

	var dwarfData *dwarf.Data
	var theFile *macho.File
	var theErr os.Error
	var relativeAddress uint64
	var runtimeAddress uint64
	var loadAddress uint64
	var segmentAddress uint64
	var pathMacho string
	var pathDsym string

	// Parse our arguments
	flag.Uint64Var(&runtimeAddress, "raddr", 0, "")
	flag.Uint64Var(&loadAddress, "laddr", 0, "")
	flag.StringVar(&pathMacho, "macho", "", "")
	flag.StringVar(&pathDsym, "dsym", "", "")
	flag.Parse()

	if runtimeAddress == 0 || loadAddress == 0 || pathMacho == "" || pathDsym == "" {
		printHelp()
	}

	// Find the text segment address
	theFile, theErr = macho.Open(pathMacho)
	if theErr != nil {
		fatalError("Can't open Mach-O file: " + theErr.String())
	}

	segmentAddress = theFile.Segment("__TEXT").Addr

	theFile.Close()

	// Calculate the target address
	relativeAddress = runtimeAddress - loadAddress
	gTargetAddress = segmentAddress + relativeAddress

	// Find the target
	theFile, theErr = macho.Open(pathDsym)
	if theErr != nil {
		fatalError("Can't open .dsym file: " + theErr.String())
	}

	dwarfData, theErr = theFile.DWARF()
	if theErr != nil {
		fatalError("Can't find DWARF info: " + theErr.String())
	}

	processChildren(dwarfData.Reader(), 0, false)

	theFile.Close()
}
Esempio n. 3
0
File: main.go Progetto: ebfe/gover
func findVariable(d *dwarf.Data, name string) (*variable, error) {
	dr := d.Reader()
	for {
		e, err := dr.Next()
		if e == nil || err != nil {
			return nil, err
		}

		if e.Tag != dwarf.TagVariable {
			continue
		}

		aname, ok := e.Val(dwarf.AttrName).(string)
		if !ok || aname != name {
			continue
		}
		loc, ok := e.Val(dwarf.AttrLocation).([]uint8)
		if !ok {
			continue
		}
		if loc[0] != 3 {
			return nil, fmt.Errorf("can't determine variable addr")
		}
		addr := uint64(0)
		switch len(loc) {
		case 5:
			addr = uint64(binary.LittleEndian.Uint32(loc[1:]))
		case 9:
			addr = uint64(binary.LittleEndian.Uint64(loc[1:]))
		default:
			return nil, fmt.Errorf("unknown addr size")
		}

		off, ok := e.Val(dwarf.AttrType).(dwarf.Offset)
		if !ok {
			continue
		}
		typ, err := d.Type(off)
		if err != nil {
			return nil, err
		}

		return &variable{Addr: addr, Type: typ}, nil
	}
	return nil, nil
}
Esempio n. 4
0
// Makes a map from <function name, offset in arg area> to name of field.
func argsMap(d *Dump, w *dwarf.Data, t map[dwarf.Offset]dwarfType) map[localKey]string {
	m := make(map[localKey]string, 0)
	r := w.Reader()
	var funcname string
	for {
		e, err := r.Next()
		if err != nil {
			log.Fatal(err)
		}
		if e == nil {
			break
		}
		switch e.Tag {
		case dwarf.TagSubprogram:
			funcname = e.Val(dwarf.AttrName).(string)
		case dwarf.TagFormalParameter:
			if e.Val(dwarf.AttrName) == nil {
				continue
			}
			name := e.Val(dwarf.AttrName).(string)
			typ := t[e.Val(dwarf.AttrType).(dwarf.Offset)]
			loc := e.Val(dwarf.AttrLocation).([]uint8)
			if len(loc) == 0 || loc[0] != dw_op_call_frame_cfa {
				break
			}
			var offset int64
			if len(loc) == 1 {
				offset = 0
			} else if len(loc) >= 3 && loc[1] == dw_op_consts && loc[len(loc)-1] == dw_op_plus {
				loc, offset = readSleb(loc[2 : len(loc)-1])
				if len(loc) != 0 {
					break
				}
			}
			for _, f := range typ.Fields() {
				m[localKey{funcname, uint64(offset)}] = joinNames(name, f.Name)
			}
		}
	}
	return m
}
Esempio n. 5
0
// New returns a reader for the specified dwarf data.
func New(data *dwarf.Data) *Reader {
	return &Reader{data.Reader(), 0}
}
Esempio n. 6
0
// load a map of all of the dwarf types
func typeMap(d *Dump, w *dwarf.Data) map[dwarf.Offset]dwarfType {
	t := make(map[dwarf.Offset]dwarfType)

	// pass 1: make a dwarfType for all of the types in the file
	r := w.Reader()
	for {
		e, err := r.Next()
		if err != nil {
			log.Fatal(err)
		}
		if e == nil {
			break
		}
		if e.Val(dwarf.AttrName) == nil {
			// Dwarf info from non-go sources might be missing a name
			continue
		}
		switch e.Tag {
		case dwarf.TagBaseType:
			x := new(dwarfBaseType)
			x.name = e.Val(dwarf.AttrName).(string)
			x.size = uint64(e.Val(dwarf.AttrByteSize).(int64))
			x.encoding = e.Val(dwarf.AttrEncoding).(int64)
			t[e.Offset] = x
		case dwarf.TagPointerType:
			x := new(dwarfPtrType)
			x.name = e.Val(dwarf.AttrName).(string)
			x.size = d.PtrSize
			t[e.Offset] = x
		case dwarf.TagStructType:
			x := new(dwarfStructType)
			x.name = e.Val(dwarf.AttrName).(string)
			x.size = uint64(e.Val(dwarf.AttrByteSize).(int64))
			for _, a := range adjTypeNames {
				if k := a.matcher.FindStringSubmatch(x.name); k != nil {
					var i []interface{}
					for _, j := range k[1:] {
						i = append(i, j)
					}
					x.name = fmt.Sprintf(a.formatter, i...)
				}
			}
			t[e.Offset] = x
		case dwarf.TagArrayType:
			x := new(dwarfArrayType)
			x.name = e.Val(dwarf.AttrName).(string)
			x.size = uint64(e.Val(dwarf.AttrByteSize).(int64))
			t[e.Offset] = x
		case dwarf.TagTypedef:
			x := new(dwarfTypedef)
			x.name = e.Val(dwarf.AttrName).(string)
			t[e.Offset] = x
		case dwarf.TagSubroutineType:
			x := new(dwarfFuncType)
			x.name = e.Val(dwarf.AttrName).(string)
			x.size = d.PtrSize
			t[e.Offset] = x
		}
	}

	// pass 2: fill in / link up the types
	r = w.Reader()
	var currentStruct *dwarfStructType
	for {
		e, err := r.Next()
		if err != nil {
			log.Fatal(err)
		}
		if e == nil {
			break
		}
		switch e.Tag {
		case dwarf.TagTypedef:
			t[e.Offset].(*dwarfTypedef).type_ = t[e.Val(dwarf.AttrType).(dwarf.Offset)]
			if t[e.Offset].(*dwarfTypedef).type_ == nil {
				log.Fatalf("can't find referent for %s %d\n", t[e.Offset].(*dwarfTypedef).name, e.Val(dwarf.AttrType).(dwarf.Offset))
			}
		case dwarf.TagPointerType:
			i := e.Val(dwarf.AttrType)
			if i != nil {
				t[e.Offset].(*dwarfPtrType).elem = t[i.(dwarf.Offset)]
			}
			// The only nil cases are unsafe.Pointer and reflect.iword
		case dwarf.TagArrayType:
			t[e.Offset].(*dwarfArrayType).elem = t[e.Val(dwarf.AttrType).(dwarf.Offset)]
		case dwarf.TagStructType:
			currentStruct = t[e.Offset].(*dwarfStructType)
		case dwarf.TagMember:
			name := e.Val(dwarf.AttrName).(string)
			type_ := t[e.Val(dwarf.AttrType).(dwarf.Offset)]
			loc := e.Val(dwarf.AttrDataMemberLoc).([]uint8)
			var offset uint64
			if len(loc) == 0 {
				offset = 0
			} else if len(loc) >= 2 && loc[0] == dw_op_consts && loc[len(loc)-1] == dw_op_plus {
				loc, offset = readUleb(loc[1 : len(loc)-1])
				if len(loc) != 0 {
					break
				}
			}
			currentStruct.members = append(currentStruct.members, dwarfTypeMember{name, offset, type_})
		}
	}
	return t
}