ARM: Add ARM support to statetrace.
[gem5.git] / util / statetrace / arch / tracechild_arm.cc
1 /*
2 * Copyright (c) 2006-2009 The Regents of The University of Michigan
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are
7 * met: redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer;
9 * redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution;
12 * neither the name of the copyright holders nor the names of its
13 * contributors may be used to endorse or promote products derived from
14 * this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 *
28 * Authors: Ali Saidi
29 * Gabe Black
30 */
31
32 #include <iostream>
33 #include <errno.h>
34 #include <stdint.h>
35 #include <cstring>
36
37 #include "tracechild_arm.hh"
38
39 using namespace std;
40
41 const char* ARMTraceChild::regNames[numregs] = {
42 "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7",
43 "r8", "r9", "r10", "fp", "r12", "sp", "lr", "pc",
44 "cpsr" };
45
46
47 ARMTraceChild::ARMTraceChild()
48 {
49 for (int x = 0; x < numregs; x++)
50 regDiffSinceUpdate[x] = false;
51 }
52
53 bool ARMTraceChild::sendState(int socket)
54 {
55 uint32_t regVal = 0;
56 for(int x = 0; x < numregs; x++)
57 {
58 regVal = getRegVal(x);
59 if(write(socket, &regVal, sizeof(regVal)) == -1)
60 {
61 cerr << "Write failed! " << strerror(errno) << endl;
62 tracing = false;
63 return false;
64 }
65
66 }
67
68 return true;
69 }
70
71 uint32_t ARMTraceChild::getRegs(user_regs &myregs, int num)
72 {
73 assert(num < numregs && num >= 0);
74 return myregs.uregs[num];
75 }
76
77 bool ARMTraceChild::update(int pid)
78 {
79 oldregs = regs;
80 if(ptrace(PTRACE_GETREGS, pid, 0, &regs) != 0)
81 {
82 cerr << "update: " << strerror(errno) << endl;
83 return false;
84 }
85
86 for(unsigned int x = 0; x < numregs; x++)
87 regDiffSinceUpdate[x] = (getRegVal(x) != getOldRegVal(x));
88 return true;
89 }
90
91 int64_t ARMTraceChild::getRegVal(int num)
92 {
93 return getRegs(regs, num);
94 }
95
96 int64_t ARMTraceChild::getOldRegVal(int num)
97 {
98 return getRegs(oldregs, num);
99 }
100
101 char * ARMTraceChild::printReg(int num)
102 {
103 sprintf(printBuffer, "0x%08X", (uint32_t)getRegVal(num));
104 return printBuffer;
105 }
106
107 ostream & ARMTraceChild::outputStartState(ostream & os)
108 {
109 uint32_t sp = getSP();
110 uint32_t pc = getPC();
111 uint32_t highestInfo = 0;
112 char obuf[1024];
113 sprintf(obuf, "Initial stack pointer = 0x%08x\n", sp);
114 os << obuf;
115 sprintf(obuf, "Initial program counter = 0x%08x\n", pc);
116 os << obuf;
117
118 //Output the argument count
119 int32_t cargc = ptrace(PTRACE_PEEKDATA, pid, sp, 0);
120 sprintf(obuf, "0x%08x: Argc = 0x%08x\n", sp, cargc);
121 os << obuf;
122 sp += 4;
123
124 //Output argv pointers
125 int argCount = 0;
126 int32_t cargv;
127 do
128 {
129 cargv = ptrace(PTRACE_PEEKDATA, pid, sp, 0);
130 sprintf(obuf, "0x%08x: argv[%d] = 0x%08x\n",
131 sp, argCount++, cargv);
132 if(cargv)
133 if(highestInfo < cargv)
134 highestInfo = cargv;
135 os << obuf;
136 sp += 4;
137 } while(cargv);
138
139 //Output the envp pointers
140 int envCount = 0;
141 uint32_t cenvp;
142 do
143 {
144 cenvp = ptrace(PTRACE_PEEKDATA, pid, sp, 0);
145 sprintf(obuf, "0x%08x: envp[%d] = 0x%08x\n",
146 sp, envCount++, cenvp);
147 os << obuf;
148 sp += 4;
149 } while(cenvp);
150 uint32_t auxType, auxVal;
151 do
152 {
153 auxType = ptrace(PTRACE_PEEKDATA, pid, sp, 0);
154 sp += 4;
155 auxVal = ptrace(PTRACE_PEEKDATA, pid, sp, 0);
156 sp += 4;
157 sprintf(obuf, "0x%08x: Auxiliary vector = {0x%08x, 0x%08x}\n",
158 sp - 8, auxType, auxVal);
159 os << obuf;
160 } while(auxType != 0 || auxVal != 0);
161 //Print out the argument strings, environment strings, and file name.
162 string current;
163 uint32_t buf;
164 uint32_t currentStart = sp;
165 bool clearedInitialPadding = false;
166 do
167 {
168 buf = ptrace(PTRACE_PEEKDATA, pid, sp, 0);
169 char * cbuf = (char *)&buf;
170 for(int x = 0; x < sizeof(uint32_t); x++)
171 {
172 if(cbuf[x])
173 current += cbuf[x];
174 else
175 {
176 sprintf(obuf, "0x%08x: \"%s\"\n",
177 currentStart, current.c_str());
178 os << obuf;
179 current = "";
180 currentStart = sp + x + 1;
181 }
182 }
183 sp += 4;
184 clearedInitialPadding = clearedInitialPadding || buf != 0;
185 } while(!clearedInitialPadding || buf != 0 || sp <= highestInfo);
186 return os;
187 }
188
189 bool ARMTraceChild::step()
190 {
191
192 const uint32_t bkpt_inst = 0xE1200070;
193 const uint32_t bkpt_mask = 0xFFF000F0;
194
195 const uint32_t swi_inst = 0x0F0000000;
196 const uint32_t swi_mask = 0x0F0000000;
197
198 uint32_t next_op = ptrace(PTRACE_PEEKDATA, pid, getPC(), 0);
199 if ((next_op & swi_mask) == swi_inst) {
200 ptrace(PTRACE_POKEDATA, pid, next_op + sizeof(uint32_t), bkpt_inst);
201 ptraceSingleStep();
202 ptrace(PTRACE_POKEDATA, pid, next_op + sizeof(uint32_t), next_op);
203 }
204 else
205 {
206 ptraceSingleStep();
207 }
208 }
209
210
211 TraceChild * genTraceChild()
212 {
213 return new ARMTraceChild;
214 }
215