OpenCores
URL https://opencores.org/ocsvn/or1k/or1k/trunk

Subversion Repositories or1k

[/] [or1k/] [tags/] [before_ORP/] [uclinux/] [uClinux-2.0.x/] [scripts/] [ksymoops.cc] - Blame information for rev 1765

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 199 simons
// ksymoops.cc v1.7 -- A simple filter to resolve symbols in Linux Oops-logs
2
// Copyright (C) 1995 Greg McGary <gkm@magilla.cichlid.com>
3
// compile like so: g++ -o ksymoops ksymoops.cc -liostream
4
 
5
//////////////////////////////////////////////////////////////////////////////
6
 
7
// This program is free software; you can redistribute it and/or modify
8
// it under the terms of the GNU General Public License as published by
9
// the Free Software Foundation; either version 2, or (at your option)
10
// any later version.
11
 
12
// This program is distributed in the hope that it will be useful,
13
// but WITHOUT ANY WARRANTY; without even the implied warranty of
14
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15
// GNU General Public License for more details.
16
 
17
// You should have received a copy of the GNU General Public License
18
// along with this program; see the file COPYING.  If not, write to the
19
// Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20
 
21
// This is a simple filter to resolve EIP and call-trace symbols from
22
// a Linux kernel "Oops" log.  Supply the symbol-map file name as a
23
// command-line argument, and redirect the oops-log into stdin.  Out
24
// will come the EIP and call-trace in symbolic form.
25
 
26
//////////////////////////////////////////////////////////////////////////////
27
 
28
// BUGS:
29
// * Doesn't deal with line-prefixes prepended by syslog--strip
30
//   these off first, before submitting to ksymoops.
31
// * Only resolves operands of jump and call instructions.
32
 
33
#include <fstream.h>
34
#include <strstream.h>
35
#include <iomanip.h>
36
#include <stdio.h>
37
#include <string.h>
38
#include <stdlib.h>
39
#include <unistd.h>
40
#include <ctype.h>
41
 
42
inline int strequ(char const* x, char const* y) { return (::strcmp(x, y) == 0); }
43
inline int strnequ(char const* x, char const* y, size_t n) { return (::strncmp(x, y, n) == 0); }
44
 
45
const int code_size = 20;
46
 
47
//////////////////////////////////////////////////////////////////////////////
48
 
49
class KSym
50
{
51
    friend class NameList;
52
 
53
  private:
54
    long address_;
55
    char* name_;
56
    long offset_;
57
    long extent_;
58
 
59
  private:
60
    istream& scan(istream&);
61
    ostream& print(ostream&) const;
62
    void set_extent(KSym const& next_ksym) { extent_ = next_ksym.address_ - address_; }
63
 
64
  public:
65
    friend istream& operator >> (istream& is, KSym& k) { return k.scan(is); }
66
    friend ostream& operator << (ostream& os, const KSym& k) { return k.print(os); }
67
};
68
 
69
istream&
70
KSym::scan(istream& is)
71
{
72
    is >> ::hex >> address_;
73
    char type;
74
    is >> type;
75
    char name[128];
76
    is >> name;
77
    name_ = new char [strlen(name)+1];
78
    strcpy(name_, name);
79
    offset_ = 0;
80
    return is;
81
}
82
 
83
ostream&
84
KSym::print(ostream& os) const
85
{
86
    os << ::hex << address_ + offset_ << ' ' << '<' << name_;
87
    if (offset_)
88
        os << '+' << ::hex << offset_ << '/' << ::hex << extent_;
89
    return os << '>';
90
}
91
 
92
//////////////////////////////////////////////////////////////////////////////
93
 
94
class NameList
95
{
96
  private:
97
    // Caution: Fixed Allocation!
98
    // This should suffice for awhile since 1.1.86 has only 2482 symbols.
99
    KSym ksyms_0_[8000];
100
    int cardinality_;
101
 
102
  public:
103
    NameList() : cardinality_(0) { }
104
 
105
  private:
106
    istream& scan(istream&);
107
 
108
  public:
109
    int valid() { return (cardinality_ > 0); }
110
 
111
    KSym* find(long address);
112
    void decode(unsigned char* code, long eip_addr);
113
 
114
  public:
115
    friend istream& operator >> (istream& is, NameList& n) { return n.scan(is); }
116
};
117
 
118
KSym*
119
NameList::find(long address)
120
{
121
    if (!valid())
122
        return 0;
123
    KSym* start = ksyms_0_;
124
    KSym* end = &ksyms_0_[cardinality_ - 1];
125
    if (address < start->address_ || address >= end->address_)
126
        return 0;
127
 
128
    KSym* mid;
129
    while (start <= end) {
130
        mid = &start[(end - start) / 2];
131
        if (mid->address_ < address)
132
            start = mid + 1;
133
        else if (mid->address_ > address)
134
            end = mid - 1;
135
        else
136
            return mid;
137
    }
138
    while (mid->address_ > address)
139
        --mid;
140
    mid->offset_ = address - mid->address_;
141
    if (mid->offset_ > mid->extent_)
142
        clog << "Oops! " << *mid << endl;
143
    return mid;
144
}
145
 
146
void
147
NameList::decode(unsigned char* code, long eip_addr)
148
{
149
    /* This is a hack to avoid using gcc.  We create an object file by
150
       concatenating objfile_head, the twenty bytes of code, and
151
       objfile_tail.  */
152
    unsigned char objfile_head[] = {
153
        0x07, 0x01, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00,
154
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
155
        0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
156
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
157
    };
158
    unsigned char objfile_tail[] = {
159
        0x00, 0x90, 0x90, 0x90,
160
        0x04, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
161
        0x00, 0x00, 0x00, 0x00, 0x13, 0x00, 0x00, 0x00,
162
        0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
163
        0x25, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00,
164
        0x00, 0x00, 0x00, 0x00, 0x2a, 0x00, 0x00, 0x00,
165
        'g',  'c',  'c',  '2',  '_',  'c',  'o',  'm',
166
        'p',  'i',  'l',  'e',  'd',  '.',  '\0', '_',
167
        'E',  'I',  'P',  '\0', '\0', '\0', '\0', '\0',
168
        '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0',
169
        '\0', '\0', '\0', '\0', '\0', '\0'
170
    };
171
    char const* objdump_command = "objdump -d oops_decode.o";
172
    char const* objfile_name = &objdump_command[11];
173
    ofstream objfile_stream(objfile_name);
174
 
175
    objfile_stream.write(objfile_head, sizeof(objfile_head));
176
    objfile_stream.write(code, code_size);
177
    objfile_stream.write(objfile_tail, sizeof(objfile_tail));
178
    objfile_stream.close();
179
 
180
    FILE* objdump_FILE = popen(objdump_command, "r");
181
    if (objdump_FILE == 0) {
182
        clog << "Sorry, without " << objdump_command << ", I can't disassemble the `Code' section." << endl;
183
        return;
184
    }
185
 
186
    char buf[1024];
187
    int lines = 0;
188
    int eip_seen = 0;
189
    long offset;
190
    while (fgets(buf, sizeof(buf), objdump_FILE)) {
191
        if (eip_seen && buf[4] == ':') {
192
            // assume objdump from binutils 2.8..., reformat to old style
193
            offset = strtol(buf, 0, 16);
194
            char newbuf[sizeof(buf)];
195
            memset(newbuf, '\0', sizeof(newbuf));
196
            ostrstream ost(newbuf, sizeof(newbuf));
197
            ost.width(8);
198
            ost << offset;
199
            ost << " <_EIP+" << offset << ">: " << &buf[6] << ends;
200
            strcpy(buf, newbuf);
201
        }
202
        if (!strnequ(&buf[9], "<_EIP", 5))
203
            continue;
204
        eip_seen = 1;
205
        if (strstr(buf, " is out of bounds"))
206
            break;
207
        lines++;
208
        cout << "Code: ";
209
        if (!valid()) {
210
            cout << buf;
211
            continue;
212
        }
213
        offset = strtol(buf, 0, 16);
214
        char* bp_0 = strchr(buf, '>');
215
        KSym* ksym = find(eip_addr + offset);
216
        if (bp_0)
217
            bp_0 += 2;
218
        else
219
            bp_0 = strchr(buf, ':');
220
        if (ksym)
221
            cout << *ksym << ' ';
222
        char *bp_1 = strstr(bp_0, "\t");        // objdump from binutils 2.8...
223
        if (bp_1)
224
            ++bp_1;
225
        else
226
            bp_1 = bp_0;
227
        char *bp = bp_1;
228
        while (!isspace(*bp))
229
            bp++;
230
        while (isspace(*bp))
231
            bp++;
232
        if (!isxdigit(*bp)) {
233
            cout << bp_0;
234
        } else if (*bp_1 == 'j' || strnequ(bp_1, "call", 4)) { // a jump or call insn
235
            long rel_addr = strtol(bp, 0, 16);
236
            ksym = find(eip_addr + rel_addr);
237
            if (ksym) {
238
                *bp++ = '\0';
239
                cout << bp_0 << *ksym << endl;
240
            } else
241
                cout << bp_0;
242
        } else {
243
            cout << bp_0;
244
        }
245
    }
246
    if (!lines)
247
        clog << "Sorry, your " << objdump_command << " can't disassemble--you must upgrade your binutils." << endl;
248
    pclose(objdump_FILE);
249
    unlink(objfile_name);
250
}
251
 
252
istream&
253
NameList::scan(istream& is)
254
{
255
    KSym* ksyms = ksyms_0_;
256
    int cardinality = 0;
257
    while (!is.eof()) {
258
        is >> *ksyms;
259
        if (cardinality++ > 0)
260
            ksyms[-1].set_extent(*ksyms);
261
        ksyms++;
262
    }
263
    cardinality_ = --cardinality;
264
    return is;
265
}
266
 
267
//////////////////////////////////////////////////////////////////////////////
268
 
269
char const* program_name;
270
 
271
void
272
usage()
273
{
274
    clog << "Usage: " << program_name << " [ System.map ] < oops-log" << endl;
275
    exit(1);
276
}
277
 
278
int
279
main(int argc, char** argv)
280
{
281
    char c;
282
    program_name = (argc--, *argv++);
283
 
284
    NameList names;
285
    if (argc > 1)
286
        usage();
287
    else if (argc == 1) {
288
        char const* map_file_name = (argc--, *argv++);
289
        ifstream map(map_file_name);
290
        if (map.bad())
291
            clog << program_name << ": Can't open `" << map_file_name << "'" << endl;
292
        else {
293
            map >> names;
294
            cout << "Using `" << map_file_name << "' to map addresses to symbols." << endl;
295
        }
296
    }
297
    if (!names.valid())
298
        cout << "No symbol map.  I'll only show you disassembled code." << endl;
299
    cout << endl;
300
 
301
    char buffer[1024];
302
    while (!cin.eof())
303
    {
304
        long eip_addr;
305
        cin >> buffer;
306
        if (strequ(buffer, "EIP:") && names.valid()) {
307
            cin >> ::hex >> eip_addr;
308
            cin >> c >> c >> c;
309
            cin >> ::hex >> eip_addr;
310
            cin >> c >> c >> buffer;
311
            if (!strequ(buffer, "EFLAGS:")) {
312
                clog << "Please strip the line-prefixes and rerun " << program_name << endl;
313
                exit(1);
314
            }
315
            KSym* ksym = names.find(eip_addr);
316
            if (ksym)
317
                cout << ">>EIP: " << *ksym << endl;
318
        } else if (strequ(buffer, "Trace:") && names.valid()) {
319
            long address;
320
            while ((cin >> buffer) &&
321
                   (sscanf(buffer, " [<%x>]", &address) == 1) &&
322
                   address > 0xc) {
323
                cout << "Trace: ";
324
                KSym* ksym = names.find(address);
325
                if (ksym)
326
                    cout << *ksym;
327
                else
328
                    cout << ::hex << address;
329
                cout << endl;
330
            }
331
            cout << endl;
332
        }
333
        if (strequ(buffer, "ode:") || strequ(buffer, "Code:")) {
334
            // The 'C' might have been consumed as a hex number
335
            unsigned char code[code_size];
336
            unsigned char* cp = code;
337
            unsigned char* end = &code[code_size];
338
            while (cp < end) {
339
                int c;
340
                cin >> ::hex >> c;
341
                *cp++ = c;
342
            }
343
            names.decode(code, eip_addr);
344
        }
345
    }
346
    cout << flush;
347
 
348
    return 0;
349
}

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.