patch-2.2.0-pre4 linux/scripts/ksymoops.cc
Next file: linux/scripts/tkcond.c
Previous file: linux/scripts/ksymoops-0.6/symbol.c
Back to the patch index
Back to the overall index
- Lines: 412
- Date:
Wed Dec 31 16:00:00 1969
- Orig file:
v2.2.0-pre3/linux/scripts/ksymoops.cc
- Orig date:
Sun Jun 7 11:16:40 1998
diff -u --recursive --new-file v2.2.0-pre3/linux/scripts/ksymoops.cc linux/scripts/ksymoops.cc
@@ -1,411 +0,0 @@
-// ksymoops.cc v1.7 -- A simple filter to resolve symbols in Linux Oops-logs
-// Copyright (C) 1995 Greg McGary <gkm@magilla.cichlid.com>
-// compile like so: g++ -o ksymoops ksymoops.cc -liostream
-
-// Update to binutils 2.8 and handling of header text on oops lines by
-// Keith Owens <kaos@ocs.com.au>
-
-//////////////////////////////////////////////////////////////////////////////
-
-// This program is free software; you can redistribute it and/or modify
-// it under the terms of the GNU General Public License as published by
-// the Free Software Foundation; either version 2, or (at your option)
-// any later version.
-
-// This program is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// GNU General Public License for more details.
-
-// You should have received a copy of the GNU General Public License
-// along with this program; see the file COPYING. If not, write to the
-// Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
-
-// This is a simple filter to resolve EIP and call-trace symbols from
-// a Linux kernel "Oops" log. Supply the symbol-map file name as a
-// command-line argument, and redirect the oops-log into stdin. Out
-// will come the EIP and call-trace in symbolic form.
-
-// Changed by Andreas Schwab <schwab@issan.informatik.uni-dortmund.de>
-// adapted to Linux/m68k
-
-//////////////////////////////////////////////////////////////////////////////
-
-// BUGS:
-// * Only resolves operands of jump and call instructions.
-
-#include <fstream.h>
-#include <strstream.h>
-#include <iomanip.h>
-#include <stdio.h>
-#include <string.h>
-#include <stdlib.h>
-#include <unistd.h>
-#include <ctype.h>
-#include <a.out.h>
-
-inline int strnequ(char const* x, char const* y, size_t n) { return (strncmp(x, y, n) == 0); }
-
-const int code_size = 20;
-
-//////////////////////////////////////////////////////////////////////////////
-
-class KSym
-{
- friend class NameList;
-
- private:
- unsigned long address_;
- char* name_;
- long offset_;
- long extent_;
-
- private:
- istream& scan(istream&);
- ostream& print(ostream&) const;
- void set_extent(KSym const& next_ksym) { extent_ = next_ksym.address_ - address_; }
-
- public:
- friend istream& operator >> (istream& is, KSym& k) { return k.scan(is); }
- friend ostream& operator << (ostream& os, const KSym& k) { return k.print(os); }
-};
-
-istream&
-KSym::scan(istream& is)
-{
- is >> ::hex >> address_;
- char type;
- is >> type;
- char name[128];
- is >> name;
- name_ = new char [strlen(name)+1];
- strcpy(name_, name);
- offset_ = 0;
- return is;
-}
-
-ostream&
-KSym::print(ostream& os) const
-{
- os << ::hex << address_ + offset_ << ' ' << '<' << name_;
- if (offset_)
- os << '+' << ::hex << offset_ << '/' << ::hex << extent_;
- return os << '>';
-}
-
-//////////////////////////////////////////////////////////////////////////////
-
-class NameList
-{
- private:
- // Caution: Fixed Allocation!
- // This should suffice for awhile since 1.1.86 has only 2482 symbols.
- KSym ksyms_0_[8000];
- int cardinality_;
-
- public:
- NameList() : cardinality_(0) { }
-
- private:
- istream& scan(istream&);
-
- public:
- int valid() { return (cardinality_ > 0); }
-
- KSym* find(unsigned long address);
- void decode(unsigned char* code, long eip_addr);
-
- public:
- friend istream& operator >> (istream& is, NameList& n) { return n.scan(is); }
-};
-
-KSym*
-NameList::find(unsigned long address)
-{
- if (!valid())
- return 0;
- KSym* start = ksyms_0_;
- KSym* end = &ksyms_0_[cardinality_ - 1];
- if (address < start->address_ || address >= end->address_)
- return 0;
-
- KSym* mid;
- while (start <= end) {
- mid = &start[(end - start) / 2];
- if (mid->address_ < address)
- start = mid + 1;
- else if (mid->address_ > address)
- end = mid - 1;
- else
- return mid;
- }
- while (mid->address_ > address)
- --mid;
- mid->offset_ = address - mid->address_;
- if (mid->offset_ > mid->extent_)
- clog << "Oops! " << *mid << endl;
- return mid;
-}
-
-void
-NameList::decode(unsigned char* code, long eip_addr)
-{
- /* This is a hack to avoid using gcc. We create an object file by
- concatenating objfile_head, the twenty bytes of code, and
- objfile_tail. */
- static struct exec objfile_head = {
- OMAGIC, code_size + 4, 0, 0, sizeof (struct nlist) * 3, 0, 0, 0
- };
- static struct {
- unsigned char tail[4];
- struct nlist syms[3];
- unsigned long strsize;
- char strings[42];
- } objfile_tail = {
-#ifdef i386
- { 0x00, 0x90, 0x90, 0x90 },
-#endif
-#ifdef mc68000
- { 0x00, 0x00, 0x00, 0x00 },
-#endif
- { { (char *) 4, N_TEXT, 0, 0, 0 },
- { (char *) 19, N_TEXT, 0, 0, 0 },
- { (char *) 37, N_TEXT | N_EXT, 0, 0, 0 } },
- 42,
- "gcc2_compiled.\0___gnu_compiled_c\0_EIP\0"
- };
- char const* objdump_command = "objdump -d oops_decode.o";
- char const* objfile_name = &objdump_command[11];
- ofstream objfile_stream(objfile_name);
-
- objfile_stream.write((char *) &objfile_head, sizeof(objfile_head));
- objfile_stream.write(code, code_size);
- objfile_stream.write((char *) &objfile_tail, sizeof(objfile_tail));
- objfile_stream.close();
-
- FILE* objdump_FILE = popen(objdump_command, "r");
- if (objdump_FILE == 0) {
- clog << "Sorry, without " << objdump_command << ", I can't disassemble the `Code' section." << endl;
- return;
- }
-
- char buf[1024];
- int lines = 0;
- int eip_seen = 0;
- long offset;
- while (fgets(buf, sizeof(buf), objdump_FILE)) {
- if (strlen(buf) < 14)
- continue;
- if (eip_seen && buf[4] == ':') {
- // assume objdump from binutils 2.8..., reformat to old style
- offset = strtol(buf, 0, 16);
- char newbuf[sizeof(buf)];
- memset(newbuf, '\0', sizeof(newbuf));
- ostrstream ost(newbuf, sizeof(newbuf));
- ost.width(8);
- ost << hex << offset;
- ost << " <_EIP+" << hex << offset << ">: " << &buf[6] << ends;
- strcpy(buf, newbuf);
- }
- if (!strnequ(&buf[9], "<_EIP", 5))
- continue;
- eip_seen = 1;
- if (strstr(buf, " is out of bounds"))
- break;
- lines++;
- cout << "Code: ";
- if (!valid()) {
- cout << buf;
- continue;
- }
- offset = strtol(buf, 0, 16);
- char* bp_0 = strchr(buf, '>');
- KSym* ksym = find(eip_addr + offset);
- if (bp_0)
- bp_0 += 2;
- else
- bp_0 = strchr(buf, ':');
- if (ksym)
- cout << *ksym << ' ';
- char *bp_1 = strstr(bp_0, "\t"); // objdump from binutils 2.8...
- if (bp_1)
- ++bp_1;
- else
- bp_1 = bp_0;
- char *bp = bp_1;
- while (!isspace(*bp))
- bp++;
- while (isspace(*bp))
- bp++;
- if (!isxdigit(*bp)) {
- cout << bp_0;
-#ifdef i386
- } else if (*bp_1 == 'j' || strnequ(bp_1, "call", 4)) { // a jump or call insn
- long rel_addr = strtol(bp, 0, 16);
- ksym = find(eip_addr + rel_addr);
- if (ksym) {
- *bp++ = '\0';
- cout << bp_0 << *ksym << endl;
- } else
- cout << bp_0;
-#endif
-#ifdef mc68000
- } else if ((bp_1[0] == 'b' && bp_1[4] == ' ' && strchr("swl", bp_1[3]))
- || (bp_1[0] == 'd' && bp_1[1] == 'b')) {
- // a branch or decr-and-branch insn
- if (bp_1[0] == 'd') // skip register
- while (*bp && *bp++ != ',');
- long rel_addr = strtoul(bp, 0, 16);
- ksym = find(eip_addr + rel_addr);
- if (ksym) {
- *bp++ = '\0';
- cout << bp_0 << *ksym << endl;
- } else
- cout << bp_0;
-#endif
- } else {
- cout << bp_0;
- }
- }
- if (!lines)
- clog << "Sorry, your " << objdump_command << " can't disassemble--you must upgrade your binutils." << endl;
- pclose(objdump_FILE);
- unlink(objfile_name);
-}
-
-istream&
-NameList::scan(istream& is)
-{
- KSym* ksyms = ksyms_0_;
- int cardinality = 0;
- while (!is.eof()) {
- is >> *ksyms;
- if (cardinality++ > 0)
- ksyms[-1].set_extent(*ksyms);
- ksyms++;
- }
- cardinality_ = --cardinality;
- return is;
-}
-
-//////////////////////////////////////////////////////////////////////////////
-
-char const* program_name;
-
-void
-usage()
-{
- clog << "Usage: " << program_name << " [ System.map ] < oops-log" << endl;
- exit(1);
-}
-
-int
-main(int argc, char** argv)
-{
- char c;
- char *oops_column = NULL;
- program_name = (argc--, *argv++);
-
- NameList names;
- if (argc > 1)
- usage();
- else if (argc == 1) {
- char const* map_file_name = (argc--, *argv++);
- ifstream map(map_file_name);
- if (map.bad())
- clog << program_name << ": Can't open `" << map_file_name << "'" << endl;
- else {
- map >> names;
- cout << "Using `" << map_file_name << "' to map addresses to symbols." << endl;
- }
- }
- if (!names.valid())
- cout << "No symbol map. I'll only show you disassembled code." << endl;
- cout << endl;
-
- char buffer[1024];
- while (1) {
- long eip_addr;
- cin.get(buffer, sizeof(buffer));
- if (cin.eof())
- break;
- cin.get(c); /* swallow newline */
-#ifdef i386
- if (strstr(buffer, "EIP:") && names.valid()) {
- oops_column = strstr(buffer, "EIP:");
- if (sscanf(oops_column+13, "[<%x>]", &eip_addr) != 1) {
- cout << "Cannot read eip address from EIP: line. Is this a valid oops file?" << endl;
- exit(1);
- }
- cout << ">>EIP: ";
- KSym* ksym = names.find(eip_addr);
- if (ksym)
- cout << *ksym << endl;
- else
- cout << ::hex << eip_addr << " cannot be resolved" << endl;
- }
-#endif
-#ifdef mc68000
- if (strstr(buffer, "PC:") && names.valid()) {
- oops_column = strstr(buffer, "PC:");
- if (sscanf(oops_column+4, "[<%x>]", &eip_addr) != 1) {
- cout << "Cannot read pc address from PC: line. Is this a valid oops file?" << endl;
- exit(1);
- }
- cout << ">>PC: ";
- KSym* ksym = names.find(eip_addr);
- if (ksym)
- cout << *ksym << endl;
- else
- cout << ::hex << eip_addr << " cannot be resolved" << endl;
- }
-#endif
- else if (oops_column && strstr(oops_column, "[<") && names.valid()) {
- unsigned long address;
- while (strstr(oops_column, "[<")) {
- char *p = oops_column;
- while (1) {
- while (*p && *p++ != '[')
- ;
- if (sscanf(p, "<%x>]", &address) != 1)
- break;
- cout << "Trace: ";
- KSym* ksym = names.find(address);
- if (ksym)
- cout << *ksym;
- else
- cout << ::hex << address;
- cout << endl;
- }
- cin.get(buffer, sizeof(buffer));
- if (cin.eof())
- break;
- cin.get(c); /* swallow newline */
- }
- }
- if (oops_column && strnequ(oops_column, "Code:", 5)) {
- unsigned char code[code_size];
- unsigned char* cp = code;
- unsigned char* end = &code[code_size];
- char *p = oops_column + 5;
- int c;
- memset(code, '\0', sizeof(code));
- while (*p && cp < end) {
- while (*p == ' ')
- ++p;
- if (sscanf(p, "%x", &c) != 1)
- break;
-#ifdef mc68000
- *cp++ = c >> 8;
-#endif
- *cp++ = c;
- while (*p && *p++ != ' ')
- ;
- }
- names.decode(code, eip_addr);
- }
- }
- cout << flush;
-
- return 0;
-}
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen, slshen@lbl.gov