1// Copyright 2018 Google Inc. All Rights Reserved. 2// 3// Licensed under the Apache License, Version 2.0 (the "License"); 4// you may not use this file except in compliance with the License. 5// You may obtain a copy of the License at 6// 7// http://www.apache.org/licenses/LICENSE-2.0 8// 9// Unless required by applicable law or agreed to in writing, software 10// distributed under the License is distributed on an "AS IS" BASIS, 11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12// See the License for the specific language governing permissions and 13// limitations under the License. 14 15// Package arch contains architecture-specific definitions. 16package arch 17 18import ( 19 "encoding/binary" 20 "math" 21) 22 23const MaxBreakpointSize = 4 // TODO 24 25// Architecture defines the architecture-specific details for a given machine. 26type Architecture struct { 27 // BreakpointSize is the size of a breakpoint instruction, in bytes. 28 BreakpointSize int 29 // IntSize is the size of the int type, in bytes. 30 IntSize int 31 // PointerSize is the size of a pointer, in bytes. 32 PointerSize int 33 // ByteOrder is the byte order for ints and pointers. 34 ByteOrder binary.ByteOrder 35 // FloatByteOrder is the byte order for floats. 36 FloatByteOrder binary.ByteOrder 37 BreakpointInstr [MaxBreakpointSize]byte 38} 39 40func (a *Architecture) Int(buf []byte) int64 { 41 return int64(a.Uint(buf)) 42} 43 44func (a *Architecture) Uint(buf []byte) uint64 { 45 if len(buf) != a.IntSize { 46 panic("bad IntSize") 47 } 48 switch a.IntSize { 49 case 4: 50 return uint64(a.ByteOrder.Uint32(buf[:4])) 51 case 8: 52 return a.ByteOrder.Uint64(buf[:8]) 53 } 54 panic("no IntSize") 55} 56 57func (a *Architecture) Int16(buf []byte) int16 { 58 return int16(a.Uint16(buf)) 59} 60 61func (a *Architecture) Int32(buf []byte) int32 { 62 return int32(a.Uint32(buf)) 63} 64 65func (a *Architecture) Int64(buf []byte) int64 { 66 return int64(a.Uint64(buf)) 67} 68 69func (a *Architecture) Uint16(buf []byte) uint16 { 70 return a.ByteOrder.Uint16(buf) 71} 72 73func (a *Architecture) Uint32(buf []byte) uint32 { 74 return a.ByteOrder.Uint32(buf) 75} 76 77func (a *Architecture) Uint64(buf []byte) uint64 { 78 return a.ByteOrder.Uint64(buf) 79} 80 81func (a *Architecture) IntN(buf []byte) int64 { 82 if len(buf) == 0 { 83 return 0 84 } 85 x := int64(0) 86 if a.ByteOrder == binary.LittleEndian { 87 i := len(buf) - 1 88 x = int64(int8(buf[i])) // sign-extended 89 for i--; i >= 0; i-- { 90 x <<= 8 91 x |= int64(buf[i]) // not sign-extended 92 } 93 } else { 94 x = int64(int8(buf[0])) // sign-extended 95 for i := 1; i < len(buf); i++ { 96 x <<= 8 97 x |= int64(buf[i]) // not sign-extended 98 } 99 } 100 return x 101} 102 103func (a *Architecture) UintN(buf []byte) uint64 { 104 u := uint64(0) 105 if a.ByteOrder == binary.LittleEndian { 106 shift := uint(0) 107 for _, c := range buf { 108 u |= uint64(c) << shift 109 shift += 8 110 } 111 } else { 112 for _, c := range buf { 113 u <<= 8 114 u |= uint64(c) 115 } 116 } 117 return u 118} 119 120func (a *Architecture) Uintptr(buf []byte) uint64 { 121 if len(buf) != a.PointerSize { 122 panic("bad PointerSize") 123 } 124 switch a.PointerSize { 125 case 4: 126 return uint64(a.ByteOrder.Uint32(buf[:4])) 127 case 8: 128 return a.ByteOrder.Uint64(buf[:8]) 129 } 130 panic("no PointerSize") 131} 132 133func (a *Architecture) Float32(buf []byte) float32 { 134 if len(buf) != 4 { 135 panic("bad float32 size") 136 } 137 return math.Float32frombits(a.FloatByteOrder.Uint32(buf)) 138} 139 140func (a *Architecture) Float64(buf []byte) float64 { 141 if len(buf) != 8 { 142 panic("bad float64 size") 143 } 144 return math.Float64frombits(a.FloatByteOrder.Uint64(buf)) 145} 146 147func (a *Architecture) Complex64(buf []byte) complex64 { 148 if len(buf) != 8 { 149 panic("bad complex64 size") 150 } 151 return complex(a.Float32(buf[0:4]), a.Float32(buf[4:8])) 152} 153 154func (a *Architecture) Complex128(buf []byte) complex128 { 155 if len(buf) != 16 { 156 panic("bad complex128 size") 157 } 158 return complex(a.Float64(buf[0:8]), a.Float64(buf[8:16])) 159} 160 161var AMD64 = Architecture{ 162 BreakpointSize: 1, 163 IntSize: 8, 164 PointerSize: 8, 165 ByteOrder: binary.LittleEndian, 166 FloatByteOrder: binary.LittleEndian, 167 BreakpointInstr: [MaxBreakpointSize]byte{0xCC}, // INT 3 168} 169 170var X86 = Architecture{ 171 BreakpointSize: 1, 172 IntSize: 4, 173 PointerSize: 4, 174 ByteOrder: binary.LittleEndian, 175 FloatByteOrder: binary.LittleEndian, 176 BreakpointInstr: [MaxBreakpointSize]byte{0xCC}, // INT 3 177} 178 179var ARM = Architecture{ 180 BreakpointSize: 4, // TODO 181 IntSize: 4, 182 PointerSize: 4, 183 ByteOrder: binary.LittleEndian, 184 FloatByteOrder: binary.LittleEndian, // TODO 185 BreakpointInstr: [MaxBreakpointSize]byte{0x00, 0x00, 0x00, 0x00}, // TODO 186} 187