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