Statetrace: Print the correct address of auxiliary vectors.
[gem5.git] / util / statetrace / arch / tracechild_amd64.cc
1 /*
2 * Copyright (c) 2007 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: Gabe Black
29 */
30
31 #include <iostream>
32 #include <errno.h>
33 #include <sys/ptrace.h>
34 #include <stdint.h>
35
36 #include "tracechild_amd64.hh"
37
38 using namespace std;
39
40 char * AMD64TraceChild::regNames[numregs] = {
41 //GPRs
42 "rax", "rbx", "rcx", "rdx",
43 //Index registers
44 "rsi", "rdi",
45 //Base pointer and stack pointer
46 "rbp", "rsp",
47 //New 64 bit mode registers
48 "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15",
49 //Segmentation registers
50 "cs", "ds", "es", "fs", "gs", "ss", "fs_base", "gs_base",
51 //PC
52 "rip",
53 //Flags
54 "eflags"};
55
56 bool AMD64TraceChild::sendState(int socket)
57 {
58 uint64_t regVal = 0;
59 for(int x = 0; x <= R15; x++)
60 {
61 regVal = getRegVal(x);
62 if(write(socket, &regVal, sizeof(regVal)) == -1)
63 {
64 cerr << "Write failed! " << strerror(errno) << endl;
65 tracing = false;
66 return false;
67 }
68 }
69 regVal = getRegVal(RIP);
70 if(write(socket, &regVal, sizeof(regVal)) == -1)
71 {
72 cerr << "Write failed! " << strerror(errno) << endl;
73 tracing = false;
74 return false;
75 }
76 return true;
77 }
78
79 int64_t AMD64TraceChild::getRegs(user_regs_struct & myregs, int num)
80 {
81 assert(num < numregs && num >= 0);
82 switch(num)
83 {
84 //GPRs
85 case RAX: return myregs.rax;
86 case RBX: return myregs.rbx;
87 case RCX: return myregs.rcx;
88 case RDX: return myregs.rdx;
89 //Index registers
90 case RSI: return myregs.rsi;
91 case RDI: return myregs.rdi;
92 //Base pointer and stack pointer
93 case RBP: return myregs.rbp;
94 case RSP: return myregs.rsp;
95 //New 64 bit mode registers
96 case R8: return myregs.r8;
97 case R9: return myregs.r9;
98 case R10: return myregs.r10;
99 case R11: return myregs.r11;
100 case R12: return myregs.r12;
101 case R13: return myregs.r13;
102 case R14: return myregs.r14;
103 case R15: return myregs.r15;
104 //Segmentation registers
105 case CS: return myregs.cs;
106 case DS: return myregs.ds;
107 case ES: return myregs.es;
108 case FS: return myregs.fs;
109 case GS: return myregs.gs;
110 case SS: return myregs.ss;
111 case FS_BASE: return myregs.fs_base;
112 case GS_BASE: return myregs.gs_base;
113 //PC
114 case RIP: return myregs.rip;
115 //Flags
116 case EFLAGS: return myregs.eflags;
117 default:
118 assert(0);
119 return 0;
120 }
121 }
122
123 bool AMD64TraceChild::update(int pid)
124 {
125 oldregs = regs;
126 if(ptrace(PTRACE_GETREGS, pid, 0, &regs) != 0)
127 {
128 cerr << "update: " << strerror(errno) << endl;
129 return false;
130 }
131 for(unsigned int x = 0; x < numregs; x++)
132 regDiffSinceUpdate[x] = (getRegVal(x) != getOldRegVal(x));
133 return true;
134 }
135
136 AMD64TraceChild::AMD64TraceChild()
137 {
138 for(unsigned int x = 0; x < numregs; x++)
139 regDiffSinceUpdate[x] = false;
140 }
141
142 int64_t AMD64TraceChild::getRegVal(int num)
143 {
144 return getRegs(regs, num);
145 }
146
147 int64_t AMD64TraceChild::getOldRegVal(int num)
148 {
149 return getRegs(oldregs, num);
150 }
151
152 char * AMD64TraceChild::printReg(int num)
153 {
154 sprintf(printBuffer, "0x%08X", getRegVal(num));
155 return printBuffer;
156 }
157
158 ostream & AMD64TraceChild::outputStartState(ostream & os)
159 {
160 uint64_t sp = getSP();
161 uint64_t pc = getPC();
162 char obuf[1024];
163 sprintf(obuf, "Initial stack pointer = 0x%016llx\n", sp);
164 os << obuf;
165 sprintf(obuf, "Initial program counter = 0x%016llx\n", pc);
166 os << obuf;
167
168 //Output the argument count
169 uint64_t cargc = ptrace(PTRACE_PEEKDATA, pid, sp, 0);
170 sprintf(obuf, "0x%016llx: Argc = 0x%016llx\n", sp, cargc);
171 os << obuf;
172 sp += 8;
173
174 //Output argv pointers
175 int argCount = 0;
176 uint64_t cargv;
177 do
178 {
179 cargv = ptrace(PTRACE_PEEKDATA, pid, sp, 0);
180 sprintf(obuf, "0x%016llx: argv[%d] = 0x%016llx\n",
181 sp, argCount++, cargv);
182 os << obuf;
183 sp += 8;
184 } while(cargv);
185
186 //Output the envp pointers
187 int envCount = 0;
188 uint64_t cenvp;
189 do
190 {
191 cenvp = ptrace(PTRACE_PEEKDATA, pid, sp, 0);
192 sprintf(obuf, "0x%016llx: envp[%d] = 0x%016llx\n",
193 sp, envCount++, cenvp);
194 os << obuf;
195 sp += 8;
196 } while(cenvp);
197 uint64_t auxType, auxVal;
198 do
199 {
200 auxType = ptrace(PTRACE_PEEKDATA, pid, sp, 0);
201 sp += 8;
202 auxVal = ptrace(PTRACE_PEEKDATA, pid, sp, 0);
203 sp += 8;
204 sprintf(obuf, "0x%016llx: Auxiliary vector = {0x%016llx, 0x%016llx}\n",
205 sp - 16, auxType, auxVal);
206 os << obuf;
207 } while(auxType != 0 || auxVal != 0);
208 //Print out the argument strings, environment strings, and file name.
209 string current;
210 uint64_t buf;
211 uint64_t currentStart = sp;
212 bool clearedInitialPadding = false;
213 do
214 {
215 buf = ptrace(PTRACE_PEEKDATA, pid, sp, 0);
216 char * cbuf = (char *)&buf;
217 for(int x = 0; x < sizeof(uint64_t); x++)
218 {
219 if(cbuf[x])
220 current += cbuf[x];
221 else
222 {
223 sprintf(obuf, "0x%016llx: \"%s\"\n",
224 currentStart, current.c_str());
225 os << obuf;
226 current = "";
227 currentStart = sp + x + 1;
228 }
229 }
230 sp += 8;
231 clearedInitialPadding = clearedInitialPadding || buf != 0;
232 } while(!clearedInitialPadding || buf != 0);
233 return os;
234 }
235
236 TraceChild * genTraceChild()
237 {
238 return new AMD64TraceChild;
239 }