This source file includes following definitions.
- strequ
- strnequ
- set_extent
- scan
- print
- valid
- find
- decode
- scan
- usage
- main
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33 #include <fstream.h>
34 #include <iomanip.h>
35 #include <stdio.h>
36 #include <string.h>
37 #include <stdlib.h>
38 #include <unistd.h>
39 #include <ctype.h>
40
41 inline int strequ(char const* x, char const* y) { return (::strcmp(x, y) == 0); }
42 inline int strnequ(char const* x, char const* y, size_t n) { return (::strncmp(x, y, n) == 0); }
43
44 const int code_size = 20;
45
46
47
48 class KSym
49 {
50 friend class NameList;
51
52 private:
53 long address_;
54 char* name_;
55 long offset_;
56 long extent_;
57
58 private:
59 istream& scan(istream&);
60 ostream& print(ostream&) const;
61 void set_extent(KSym const& next_ksym) { extent_ = next_ksym.address_ - address_; }
62
63 public:
64 friend istream& operator >> (istream& is, KSym& k) { return k.scan(is); }
65 friend ostream& operator << (ostream& os, const KSym& k) { return k.print(os); }
66 };
67
68 istream&
69 KSym::scan(istream& is)
70 {
71 is >> ::hex >> address_;
72 char type;
73 is >> type;
74 char name[128];
75 is >> name;
76 name_ = new char [strlen(name)+1];
77 strcpy(name_, name);
78 offset_ = 0;
79 return is;
80 }
81
82 ostream&
83 KSym::print(ostream& os) const
84 {
85 os << ::hex << address_ + offset_ << ' ' << '<' << name_;
86 if (offset_)
87 os << '+' << ::hex << offset_ << '/' << ::hex << extent_;
88 return os << '>';
89 }
90
91
92
93 class NameList
94 {
95 private:
96
97
98 KSym ksyms_0_[4096];
99 int cardinality_;
100
101 public:
102 NameList() : cardinality_(0) { }
103
104 private:
105 istream& scan(istream&);
106
107 public:
108 int valid() { return (cardinality_ > 0); }
109
110 KSym* find(long address);
111 void decode(unsigned char* code, long eip_addr);
112
113 public:
114 friend istream& operator >> (istream& is, NameList& n) { return n.scan(is); }
115 };
116
117 KSym*
118 NameList::find(long address)
119 {
120 if (!valid())
121 return 0;
122 KSym* start = ksyms_0_;
123 KSym* end = &ksyms_0_[cardinality_ - 1];
124 if (address < start->address_ || address >= end->address_)
125 return 0;
126
127 KSym* mid;
128 while (start <= end) {
129 mid = &start[(end - start) / 2];
130 if (mid->address_ < address)
131 start = mid + 1;
132 else if (mid->address_ > address)
133 end = mid - 1;
134 else
135 return mid;
136 }
137 while (mid->address_ > address)
138 --mid;
139 mid->offset_ = address - mid->address_;
140 if (mid->offset_ > mid->extent_)
141 clog << "Oops! " << *mid << endl;
142 return mid;
143 }
144
145 void
146 NameList::decode(unsigned char* code, long eip_addr)
147 {
148
149
150
151 unsigned char objfile_head[] = {
152 0x07, 0x01, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00,
153 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
154 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
155 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
156 };
157 unsigned char objfile_tail[] = {
158 0x00, 0x90, 0x90, 0x90,
159 0x04, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
160 0x00, 0x00, 0x00, 0x00, 0x13, 0x00, 0x00, 0x00,
161 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
162 0x25, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00,
163 0x00, 0x00, 0x00, 0x00, 0x2a, 0x00, 0x00, 0x00,
164 'g', 'c', 'c', '2', '_', 'c', 'o', 'm',
165 'p', 'i', 'l', 'e', 'd', '.', '\0', '_',
166 'E', 'I', 'P', '\0', '\0', '\0', '\0', '\0',
167 '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0',
168 '\0', '\0', '\0', '\0', '\0', '\0'
169 };
170 char const* objdump_command = "objdump -d oops_decode.o";
171 char const* objfile_name = &objdump_command[11];
172 ofstream objfile_stream(objfile_name);
173
174 objfile_stream.write(objfile_head, sizeof(objfile_head));
175 objfile_stream.write(code, code_size);
176 objfile_stream.write(objfile_tail, sizeof(objfile_tail));
177 objfile_stream.close();
178
179 FILE* objdump_FILE = popen(objdump_command, "r");
180 if (objdump_FILE == 0) {
181 clog << "Sorry, without " << objdump_command << ", I can't disassemble the `Code' section." << endl;
182 return;
183 }
184
185 char buf[1024];
186 int lines = 0;
187 while (fgets(buf, sizeof(buf), objdump_FILE)) {
188 if (!strnequ(&buf[9], "<_EIP", 5))
189 continue;
190 if (strstr(buf, " is out of bounds"))
191 break;
192 lines++;
193 cout << "Code: ";
194 if (!valid()) {
195 cout << buf;
196 continue;
197 }
198 long offset = strtol(buf, 0, 16);
199 char* bp_0 = strchr(buf, '>') + 2;
200 KSym* ksym = find(eip_addr + offset);
201 if (ksym)
202 cout << *ksym << ' ';
203 char* bp = bp_0;
204 while (!isspace(*bp))
205 bp++;
206 while (isspace(*bp))
207 bp++;
208 if (*bp != '0') {
209 cout << bp_0;
210 } else if (*bp_0 == 'j' || strnequ(bp_0, "call", 4)) {
211 long rel_addr = strtol(bp, 0, 16);
212 ksym = find(eip_addr + rel_addr);
213 if (ksym) {
214 *bp++ = '\0';
215 cout << bp_0 << *ksym << endl;
216 } else
217 cout << bp_0;
218 } else {
219 cout << bp_0;
220 }
221 }
222 if (!lines)
223 clog << "Sorry, your " << objdump_command << " can't disassemble--you must upgrade your binutils." << endl;
224 pclose(objdump_FILE);
225 unlink(objfile_name);
226 }
227
228 istream&
229 NameList::scan(istream& is)
230 {
231 KSym* ksyms = ksyms_0_;
232 int cardinality = 0;
233 while (!is.eof()) {
234 is >> *ksyms;
235 if (cardinality++ > 0)
236 ksyms[-1].set_extent(*ksyms);
237 ksyms++;
238 }
239 cardinality_ = --cardinality;
240 return is;
241 }
242
243
244
245 char const* program_name;
246
247 void
248 usage()
249 {
250 clog << "Usage: " << program_name << " [ System.map ] < oops-log" << endl;
251 exit(1);
252 }
253
254 int
255 main(int argc, char** argv)
256 {
257 char c;
258 program_name = (argc--, *argv++);
259
260 NameList names;
261 if (argc > 1)
262 usage();
263 else if (argc == 1) {
264 char const* map_file_name = (argc--, *argv++);
265 ifstream map(map_file_name);
266 if (map.bad())
267 clog << program_name << ": Can't open `" << map_file_name << "'" << endl;
268 else {
269 map >> names;
270 cout << "Using `" << map_file_name << "' to map addresses to symbols." << endl;
271 }
272 }
273 if (!names.valid())
274 cout << "No symbol map. I'll only show you disassembled code." << endl;
275 cout << endl;
276
277 char buffer[1024];
278 while (!cin.eof())
279 {
280 long eip_addr;
281 cin >> buffer;
282 if (strequ(buffer, "EIP:") && names.valid()) {
283 cin >> ::hex >> eip_addr;
284 cin >> c >> c >> c;
285 cin >> ::hex >> eip_addr;
286 cin >> c >> c >> buffer;
287 if (!strequ(buffer, "EFLAGS:")) {
288 clog << "Please strip the line-prefixes and rerun " << program_name << endl;
289 exit(1);
290 }
291 KSym* ksym = names.find(eip_addr);
292 if (ksym)
293 cout << ">>EIP: " << *ksym << endl;
294 } else if (strequ(buffer, "Trace:") && names.valid()) {
295 long address;
296 while ((cin >> buffer) &&
297 (sscanf(buffer, " [<%x>]", &address) == 1) &&
298 address > 0xc) {
299 cout << "Trace: ";
300 KSym* ksym = names.find(address);
301 if (ksym)
302 cout << *ksym;
303 else
304 cout << ::hex << address;
305 cout << endl;
306 }
307 cout << endl;
308 }
309 if (strequ(buffer, "ode:") || strequ(buffer, "Code:")) {
310
311 unsigned char code[code_size];
312 unsigned char* cp = code;
313 unsigned char* end = &code[code_size];
314 while (cp < end) {
315 int c;
316 cin >> ::hex >> c;
317 *cp++ = c;
318 }
319 names.decode(code, eip_addr);
320 }
321 }
322 cout << flush;
323
324 return 0;
325 }