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 program_name = (argc--, *argv++);
258
259 NameList names;
260 if (argc > 1)
261 usage();
262 else if (argc == 1) {
263 char const* map_file_name = (argc--, *argv++);
264 ifstream map(map_file_name);
265 if (map.bad())
266 clog << program_name << ": Can't open `" << map_file_name << "'" << endl;
267 else {
268 map >> names;
269 cout << "Using `" << map_file_name << "' to map addresses to symbols." << endl;
270 }
271 }
272 if (!names.valid())
273 cout << "No symbol map. I'll only show you disassembled code." << endl;
274 cout << endl;
275
276 char buffer[1024];
277 while (!cin.eof())
278 {
279 long eip_addr;
280 cin >> buffer;
281 if (strequ(buffer, "EIP:") && names.valid()) {
282 cin >> ::hex >> eip_addr;
283 cin >> buffer[0];
284 cin >> ::hex >> eip_addr;
285 cin >> buffer;
286 if (!strequ(buffer, "EFLAGS:")) {
287 clog << "Please strip the line-prefixes and rerun " << program_name << endl;
288 exit(1);
289 }
290 KSym* ksym = names.find(eip_addr);
291 if (ksym)
292 cout << ">>EIP: " << *ksym << endl;
293 } else if (strequ(buffer, "Trace:") && names.valid()) {
294 long address;
295 while ((cin >> ::hex >> address) && address > 0xc) {
296 cout << "Trace: ";
297 KSym* ksym = names.find(address);
298 if (ksym)
299 cout << *ksym;
300 else
301 cout << ::hex << address;
302 cout << endl;
303 }
304 cout << endl;
305 } else if (strequ(buffer, "ode:") || strequ(buffer, "Code:")) {
306
307 unsigned char code[code_size];
308 unsigned char* cp = code;
309 unsigned char* end = &code[code_size];
310 while (cp < end) {
311 int c;
312 cin >> ::hex >> c;
313 *cp++ = c;
314 }
315 names.decode(code, eip_addr);
316 }
317 }
318 cout << flush;
319
320 return 0;
321 }