| // 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 ogle | |
| import ( | |
| "debug/proc" | |
| "math" | |
| ) | |
| type Arch interface { | |
| // ToWord converts an array of up to 8 bytes in memory order | |
| // to a word. | |
| ToWord(data []byte) proc.Word | |
| // FromWord converts a word to an array of up to 8 bytes in | |
| // memory order. | |
| FromWord(v proc.Word, out []byte) | |
| // ToFloat32 converts a word to a float. The order of this | |
| // word will be the order returned by ToWord on the memory | |
| // representation of a float, and thus may require reversing. | |
| ToFloat32(bits uint32) float32 | |
| // FromFloat32 converts a float to a word. This should return | |
| // a word that can be passed to FromWord to get the memory | |
| // representation of a float on this architecture. | |
| FromFloat32(f float32) uint32 | |
| // ToFloat64 is to float64 as ToFloat32 is to float32. | |
| ToFloat64(bits uint64) float64 | |
| // FromFloat64 is to float64 as FromFloat32 is to float32. | |
| FromFloat64(f float64) uint64 | |
| // IntSize returns the number of bytes in an 'int'. | |
| IntSize() int | |
| // PtrSize returns the number of bytes in a 'uintptr'. | |
| PtrSize() int | |
| // FloatSize returns the number of bytes in a 'float'. | |
| FloatSize() int | |
| // Align rounds offset up to the appropriate offset for a | |
| // basic type with the given width. | |
| Align(offset, width int) int | |
| // G returns the current G pointer. | |
| G(regs proc.Regs) proc.Word | |
| // ClosureSize returns the number of bytes expected by | |
| // ParseClosure. | |
| ClosureSize() int | |
| // ParseClosure takes ClosureSize bytes read from a return PC | |
| // in a remote process, determines if the code is a closure, | |
| // and returns the frame size of the closure if it is. | |
| ParseClosure(data []byte) (frame int, ok bool) | |
| } | |
| type ArchLSB struct{} | |
| func (ArchLSB) ToWord(data []byte) proc.Word { | |
| var v proc.Word | |
| for i, b := range data { | |
| v |= proc.Word(b) << (uint(i) * 8) | |
| } | |
| return v | |
| } | |
| func (ArchLSB) FromWord(v proc.Word, out []byte) { | |
| for i := range out { | |
| out[i] = byte(v) | |
| v >>= 8 | |
| } | |
| } | |
| func (ArchLSB) ToFloat32(bits uint32) float32 { | |
| // TODO(austin) Do these definitions depend on my current | |
| // architecture? | |
| return math.Float32frombits(bits) | |
| } | |
| func (ArchLSB) FromFloat32(f float32) uint32 { return math.Float32bits(f) } | |
| func (ArchLSB) ToFloat64(bits uint64) float64 { return math.Float64frombits(bits) } | |
| func (ArchLSB) FromFloat64(f float64) uint64 { return math.Float64bits(f) } | |
| type ArchAlignedMultiple struct{} | |
| func (ArchAlignedMultiple) Align(offset, width int) int { | |
| return ((offset - 1) | (width - 1)) + 1 | |
| } | |
| type amd64 struct { | |
| ArchLSB | |
| ArchAlignedMultiple | |
| gReg int | |
| } | |
| func (a *amd64) IntSize() int { return 4 } | |
| func (a *amd64) PtrSize() int { return 8 } | |
| func (a *amd64) FloatSize() int { return 4 } | |
| func (a *amd64) G(regs proc.Regs) proc.Word { | |
| // See src/pkg/runtime/mkasmh | |
| if a.gReg == -1 { | |
| ns := regs.Names() | |
| for i, n := range ns { | |
| if n == "r15" { | |
| a.gReg = i | |
| break | |
| } | |
| } | |
| } | |
| return regs.Get(a.gReg) | |
| } | |
| func (a *amd64) ClosureSize() int { return 8 } | |
| func (a *amd64) ParseClosure(data []byte) (int, bool) { | |
| if data[0] == 0x48 && data[1] == 0x81 && data[2] == 0xc4 && data[7] == 0xc3 { | |
| return int(a.ToWord(data[3:7]) + 8), true | |
| } | |
| return 0, false | |
| } | |
| var Amd64 = &amd64{gReg: -1} |