| // 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} |