1 : /*
2 : * Copyright (c) 2011 The Native Client Authors. All rights reserved.
3 : * Use of this source code is governed by a BSD-style license that can be
4 : * found in the LICENSE file.
5 : */
6 :
7 : #include <assert.h>
8 :
9 : #include <map>
10 : #include <string>
11 :
12 : #include "native_client/src/trusted/gdb_rsp/abi.h"
13 : #include "native_client/src/trusted/port/platform.h"
14 :
15 : using port::IPlatform;
16 :
17 : namespace gdb_rsp {
18 :
19 : #define MINIDEF(x, name, purpose) { #name, sizeof(x), Abi::purpose, 0, 0 }
20 : #define BPDEF(x) { sizeof(x), x }
21 :
22 : static Abi::RegDef RegsX86_64[] = {
23 : MINIDEF(uint64_t, rax, GENERAL),
24 : MINIDEF(uint64_t, rbx, GENERAL),
25 : MINIDEF(uint64_t, rcx, GENERAL),
26 : MINIDEF(uint64_t, rdx, GENERAL),
27 : MINIDEF(uint64_t, rsi, GENERAL),
28 : MINIDEF(uint64_t, rdi, GENERAL),
29 : MINIDEF(uint64_t, rbp, GENERAL),
30 : MINIDEF(uint64_t, rsp, GENERAL),
31 : MINIDEF(uint64_t, r8, GENERAL),
32 : MINIDEF(uint64_t, r9, GENERAL),
33 : MINIDEF(uint64_t, r10, GENERAL),
34 : MINIDEF(uint64_t, r11, GENERAL),
35 : MINIDEF(uint64_t, r12, GENERAL),
36 : MINIDEF(uint64_t, r13, GENERAL),
37 : MINIDEF(uint64_t, r14, GENERAL),
38 : MINIDEF(uint64_t, r15, GENERAL),
39 : MINIDEF(uint64_t, rip, INST_PTR),
40 : MINIDEF(uint32_t, eflags, FLAGS),
41 : MINIDEF(uint32_t, cs, SEGMENT),
42 : MINIDEF(uint32_t, ss, SEGMENT),
43 : MINIDEF(uint32_t, ds, SEGMENT),
44 : MINIDEF(uint32_t, es, SEGMENT),
45 : MINIDEF(uint32_t, fs, SEGMENT),
46 : MINIDEF(uint32_t, gs, SEGMENT),
47 : };
48 :
49 : static Abi::RegDef RegsX86_32[] = {
50 : MINIDEF(uint32_t, eax, GENERAL),
51 : MINIDEF(uint32_t, ecx, GENERAL),
52 : MINIDEF(uint32_t, edx, GENERAL),
53 : MINIDEF(uint32_t, ebx, GENERAL),
54 : MINIDEF(uint32_t, esp, GENERAL),
55 : MINIDEF(uint32_t, ebp, GENERAL),
56 : MINIDEF(uint32_t, esi, GENERAL),
57 : MINIDEF(uint32_t, edi, GENERAL),
58 : MINIDEF(uint32_t, eip, INST_PTR),
59 : MINIDEF(uint32_t, eflags, FLAGS),
60 : MINIDEF(uint32_t, cs, SEGMENT),
61 : MINIDEF(uint32_t, ss, SEGMENT),
62 : MINIDEF(uint32_t, ds, SEGMENT),
63 : MINIDEF(uint32_t, es, SEGMENT),
64 : MINIDEF(uint32_t, fs, SEGMENT),
65 : MINIDEF(uint32_t, gs, SEGMENT),
66 : };
67 :
68 : static Abi::RegDef RegsArm[] = {
69 : MINIDEF(uint32_t, r0, GENERAL),
70 : MINIDEF(uint32_t, r1, GENERAL),
71 : MINIDEF(uint32_t, r2, GENERAL),
72 : MINIDEF(uint32_t, r3, GENERAL),
73 : MINIDEF(uint32_t, r4, GENERAL),
74 : MINIDEF(uint32_t, r5, GENERAL),
75 : MINIDEF(uint32_t, r6, GENERAL),
76 : MINIDEF(uint32_t, r7, GENERAL),
77 : MINIDEF(uint32_t, r8, GENERAL),
78 : MINIDEF(uint32_t, r9, GENERAL),
79 : MINIDEF(uint32_t, r10, GENERAL),
80 : MINIDEF(uint32_t, r11, GENERAL),
81 : MINIDEF(uint32_t, r12, GENERAL),
82 : MINIDEF(uint32_t, sp, STACK_PTR),
83 : MINIDEF(uint32_t, lr, LINK_PTR),
84 : MINIDEF(uint32_t, pc, INST_PTR),
85 : };
86 :
87 : /*
88 : * TODO(mcgrathr): This is hlt rather than the canonical int3. This is a
89 : * workaround for http://code.google.com/p/nativeclient/issues/detail?id=1730.
90 : * The only actual use of this is in the temporary breakpoint inserted
91 : * implicitly at the entry point to catch startup. The stub code doesn't
92 : * really keep track of the fact that the trap is its own expected
93 : * breakpoint hit, so it has no place that knows to adjust for it having
94 : * it. When the int3 trap hits, the PC is left after the int3 instruction,
95 : * i.e. one byte past the place where the breakpoint was inserted. (This
96 : * is the hardware behavior, and at least Linux is known not to fiddle the
97 : * register state left by the hardware.) If we remove the breakpoint and
98 : * resume without adjusting the PC back by one byte, then we are executing
99 : * one byte ahead of where we should be. That's either in the middle of an
100 : * instruction, making it an invalid instruction, or skipping a one-byte
101 : * instruction, breaking the computation by omitting the first instruction
102 : * of the program. Since hlt generates a fault-type exception rather than
103 : * a trap-type, it will leave the PC at the beginning of the instruction.
104 : * Since nobody cares what exception we actually got, this works around the
105 : * problem.
106 : */
107 : static uint8_t BPCodeX86[] = { 0xf4 };
108 :
109 : static Abi::BPDef BPX86 = BPDEF(BPCodeX86);
110 :
111 15 : static AbiMap_t *GetAbis() {
112 15 : static AbiMap_t *_abis = new AbiMap_t();
113 15 : return _abis;
114 : }
115 :
116 : // AbiInit & AbiIsAvailable
117 : // This pair of functions work together as singleton to
118 : // ensure the module has been correctly initialized. All
119 : // dependant functions should call AbiIsAvailable to ensure
120 : // the module is ready.
121 1 : static bool AbiInit() {
122 1 : Abi::Register("i386", RegsX86_32, sizeof(RegsX86_32), &BPX86);
123 1 : Abi::Register("i386:x86-64", RegsX86_64, sizeof(RegsX86_64), &BPX86);
124 :
125 : // TODO(cbiffle) Figure out how to REALLY detect ARM, and define Breakpoint
126 1 : Abi::Register("iwmmxt", RegsArm, sizeof(RegsArm), NULL);
127 :
128 1 : return true;
129 : }
130 :
131 7 : static bool AbiIsAvailable() {
132 7 : static bool initialized_ = AbiInit();
133 7 : return initialized_;
134 : }
135 :
136 :
137 :
138 3 : Abi::Abi() {}
139 0 : Abi::~Abi() {}
140 :
141 : void Abi::Register(const char *name, RegDef *regs,
142 3 : uint32_t bytes, const BPDef *bp) {
143 3 : uint32_t offs = 0;
144 3 : const uint32_t cnt = bytes / sizeof(RegDef);
145 :
146 : // Build indexes and offsets
147 59 : for (uint32_t loop = 0; loop < cnt; loop++) {
148 56 : regs[loop].index_ = loop;
149 56 : regs[loop].offset_ = offs;
150 56 : offs += regs[loop].bytes_;
151 : }
152 :
153 3 : Abi *abi = new Abi;
154 :
155 3 : abi->name_ = name;
156 3 : abi->regCnt_ = cnt;
157 3 : abi->regDefs_= regs;
158 3 : abi->ctxSize_ = offs;
159 3 : abi->bpDef_ = bp;
160 :
161 3 : AbiMap_t *abis = GetAbis();
162 3 : (*abis)[name] = abi;
163 3 : }
164 :
165 6 : const Abi* Abi::Find(const char *name) {
166 6 : if (!AbiIsAvailable()) {
167 0 : IPlatform::LogError("Failed to initalize ABIs.");
168 0 : return NULL;
169 : }
170 :
171 6 : AbiMap_t::const_iterator itr = GetAbis()->find(name);
172 7 : if (itr == GetAbis()->end()) return NULL;
173 :
174 5 : return itr->second;
175 : }
176 :
177 93 : const Abi* Abi::Get() {
178 : static const Abi* abi = NULL;
179 :
180 93 : if ((NULL == abi) && AbiIsAvailable()) {
181 : #ifdef GDB_RSP_ABI_ARM
182 : abi = Abi::Find("iwmmxt");
183 : #elif GDB_RSP_ABI_X86_64
184 : abi = Abi::Find("i386:x86-64");
185 : #elif GDB_RSP_ABI_X86
186 1 : abi = Abi::Find("i386");
187 : #else
188 : #error "Unknown CPU architecture."
189 : #endif
190 : }
191 :
192 93 : return abi;
193 : }
194 :
195 6 : const char* Abi::GetName() const {
196 6 : return name_;
197 : }
198 :
199 1 : const Abi::BPDef *Abi::GetBreakpointDef() const {
200 1 : return bpDef_;
201 : }
202 :
203 12 : uint32_t Abi::GetContextSize() const {
204 12 : return ctxSize_;
205 : }
206 :
207 121 : uint32_t Abi::GetRegisterCount() const {
208 121 : return regCnt_;
209 : }
210 :
211 251 : const Abi::RegDef *Abi::GetRegisterDef(uint32_t index) const {
212 251 : if (index >= regCnt_) return NULL;
213 :
214 248 : return ®Defs_[index];
215 : }
216 :
217 7 : const Abi::RegDef *Abi::GetRegisterType(RegType rtype, uint32_t nth) const {
218 7 : uint32_t typeNum = 0;
219 :
220 : // Scan for the "nth" register of rtype;
221 46 : for (uint32_t regNum = 0; regNum < regCnt_; regNum++) {
222 46 : if (rtype == regDefs_[regNum].type_) {
223 7 : if (typeNum == nth) return ®Defs_[regNum];
224 0 : typeNum++;
225 : }
226 : }
227 :
228 : // Otherwise we failed to find it
229 0 : return NULL;
230 : }
231 :
232 : } // namespace gdb_rsp
|