File eppic-switch-to-system-lib.patch of Package crash.21946
---
extensions/eppic.mk | 26
extensions/eppic/applications/crash/eppic.c | 1110 ++++++++++++++++++++++++++++
2 files changed, 1112 insertions(+), 24 deletions(-)
--- a/extensions/eppic.mk
+++ b/extensions/eppic.mk
@@ -31,29 +31,7 @@ all:
@if [ -f /usr/bin/flex ] && [ -f /usr/bin/bison ]; then \
if [ -f ../$(GDB)/crash.target ]; \
then \
- if [ ! -f $(APPFILE) ]; \
- then \
- if [ -f "$(GIT)" ]; \
- then \
- if [ -n "$(EPPIC_GIT_URL)" ]; then \
- git clone "$(EPPIC_GIT_URL)" eppic; \
- else \
- if [ -n "$(GITHUB)" ] ; then \
- git clone https://github.com/lucchouina/eppic.git eppic; \
- fi; \
- fi; \
- else \
- if [ ! -f "$(GIT)" ]; then \
- echo "eppic.so: git command is needed for pulling eppic extension code"; \
- fi; \
- fi; \
- fi; \
- if [ -f $(APPFILE) ]; \
- then \
make -f eppic.mk eppic.so; \
- else \
- echo "eppic.so: failed to pull eppic code from git repo"; \
- fi; \
else \
echo "eppic.so: build failed: requires the crash $(GDB) module"; \
fi ;\
@@ -64,8 +42,8 @@ all:
lib-eppic:
cd eppic/libeppic && make
-eppic.so: ../defs.h $(APPFILE) lib-eppic
- gcc -g -Ieppic/libeppic -I../$(GDB)/gdb -I../$(GDB)/bfd -I../$(GDB)/include -I../$(GDB)/gdb/config -I../$(GDB)/gdb/common -I../$(GDB) -nostartfiles -shared -rdynamic -o eppic.so $(APPFILE) -fPIC $(TARGET_FLAGS) $(GDB_FLAGS) -Leppic/libeppic -leppic
+eppic.so: ../defs.h $(APPFILE)
+ gcc -g -I../$(GDB)/gdb -I../$(GDB)/bfd -I../$(GDB)/include -I../$(GDB)/gdb/config -I../$(GDB)/gdb/common -I../$(GDB) -nostartfiles -shared -rdynamic -o eppic.so $(APPFILE) -fPIC $(TARGET_FLAGS) $(GDB_FLAGS) -leppic
clean:
if [ -d eppic/libeppic ]; \
--- /dev/null
+++ b/extensions/eppic/applications/crash/eppic.c
@@ -0,0 +1,1110 @@
+/*
+ * $Id: eppic.c,v 1.15 2012/01/04 14:46:57 anderson Exp $
+ *
+ * This file is part of lcrash, an analysis tool for Linux memory dumps.
+ *
+ * Created by Silicon Graphics, Inc.
+ * Contributions by IBM, and others
+ *
+ * Copyright (C) 1999 - 2005 Silicon Graphics, Inc. All rights reserved.
+ * Copyright (C) 2001, 2002 IBM Deutschland Entwicklung GmbH, IBM Corporation
+ *
+ * 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 of the License, or
+ * (at your option) any later version. See the file COPYING for more
+ * information.
+ */
+
+#include "gdb/defs.h"
+#include "target.h"
+#include "symtab.h"
+#include "gdbtypes.h"
+#include "gdbcore.h"
+#include "frame.h"
+#include "value.h"
+#include "symfile.h"
+#include "objfiles.h"
+#include "gdbcmd.h"
+/*#include "call-cmds.h"*/
+#include "gdb_regex.h"
+#include "expression.h"
+#include "language.h"
+#include "demangle.h"
+#include "inferior.h"
+#include "linespec.h"
+#include "source.h"
+#include "filenames.h" /* for FILENAME_CMP */
+#include "objc-lang.h"
+
+#include "hashtab.h"
+
+#include "gdb_obstack.h"
+#include "block.h"
+#include "dictionary.h"
+
+#include <sys/types.h>
+#include <fcntl.h>
+#include "gdb_string.h"
+#include "gdb_stat.h"
+#include <ctype.h>
+#include "cp-abi.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <sys/types.h>
+#include <eppic_api.h>
+
+/////////////////////////////////////////////////////////////////////////
+// some stuff from crash's defs.h, file which cannot be included here.
+// Hate to do this but this is a quick port.
+// If anyone cares to work on the include and defs structure to make
+// this work cleanly...
+//
+/*
+ * Global data (global_data.c)
+ */
+extern char *args[];
+extern int argcnt;
+extern int argerrs;
+#define SYNOPSIS (0x1)
+#define COMPLETE_HELP (0x2)
+#define PIPE_TO_LESS (0x4)
+#define KVADDR (0x1)
+#define QUIET (0x4)
+
+typedef void (*cmd_func_t)(void);
+
+struct command_table_entry { /* one for each command in menu */
+ char *name;
+ cmd_func_t func;
+ char **help_data;
+ ulong flags;
+};
+extern FILE *fp;
+extern char *crash_global_cmd();
+
+typedef unsigned long long int ulonglong;
+extern int readmem(ulonglong, int, void *, long, char *, ulong);
+extern int symbol_exists(char *);
+extern ulong symbol_value(char *);
+extern void cmd_usage(char *, int);
+extern void register_extension(struct command_table_entry *);
+
+
+//
+/////////////////////////////////////////////////////////////////////////
+/*
+ This is the glue between the eppic interpreter and crash.
+*/
+
+static int
+apigetmem(ull iaddr, void *p, int nbytes)
+{
+ return readmem(iaddr, KVADDR, p, nbytes, NULL, QUIET);
+}
+
+// Since crash is target dependant (build for the
+static uint8_t apigetuint8(void* ptr)
+{
+uint8_t val;
+ if(!readmem((unsigned long)ptr, KVADDR, (char*)&val, sizeof val, NULL, QUIET)) return (uint8_t)-1;
+ return val;
+}
+
+static uint16_t apigetuint16(void* ptr)
+{
+uint16_t val;
+ if(!readmem((unsigned long)ptr, KVADDR, (char*)&val, sizeof val, NULL, QUIET)) return (uint16_t)-1;
+ return val;
+}
+
+static uint32_t apigetuint32(void* ptr)
+{
+uint32_t val;
+ if(!readmem((unsigned long)ptr, KVADDR, (char*)&val, sizeof val, NULL, QUIET)) return (uint32_t)-1;
+ return val;
+}
+
+static uint64_t apigetuint64(void* ptr)
+{
+uint64_t val;
+ if(!readmem((unsigned long)ptr, KVADDR, (char*)&val, sizeof val, NULL, QUIET)) return (uint64_t)-1;
+ return val;
+}
+
+static int
+apiputmem(ull iaddr, void *p, int nbytes)
+{
+ return 1;
+}
+
+/* extract a complex type (struct, union and enum) */
+static int
+apigetctype(int ctype, char *name, TYPE_S *tout)
+{
+ struct symbol *sym;
+ struct type *type;
+ int v=0;
+
+ eppic_dbg_named(DBG_TYPE, name, 2, "Looking for type %d name [%s] in struct domain...", ctype, name);
+#ifdef GDB_6_1
+ sym = lookup_symbol(name, 0, STRUCT_DOMAIN, 0, (struct symtab **) NULL);
+#else
+ sym = lookup_symbol(name, 0, STRUCT_DOMAIN, 0);
+#endif
+ if(!sym) {
+ eppic_dbg_named(DBG_TYPE, name, 2, "Not found.\nLooking for type %d name [%s] in var domain...", ctype, name);
+#ifdef GDB_6_1
+ sym = lookup_symbol(name, 0, VAR_DOMAIN, 0, (struct symtab **) NULL);
+#else
+ sym = lookup_symbol(name, 0, VAR_DOMAIN, 0);
+#endif
+ if(sym) {
+ eppic_dbg_named(DBG_TYPE, name, 2, "found class=%d\n", sym->aclass);
+ if(sym->aclass == LOC_TYPEDEF) v=1;
+ }
+ }
+
+ if (sym) {
+ type=sym->type;
+ if(eppic_is_typedef(ctype) && v) goto match;
+ eppic_dbg_named(DBG_TYPE, name, 2, "TYPE_CODE is %d ctype %d\n", TYPE_CODE(type), ctype);
+ switch(TYPE_CODE(type)) {
+ case TYPE_CODE_INT:
+ eppic_dbg_named(DBG_TYPE, name, 2, "Variable is integer\n");
+ if (eppic_is_typedef(ctype)) {
+ eppic_dbg_named(DBG_TYPE, name, 2,
+ "integer is not a typedef\n");
+ break;
+
+ }
+
+ case TYPE_CODE_TYPEDEF:
+ if(eppic_is_typedef(ctype)) goto match; break;
+ case TYPE_CODE_ENUM: if(eppic_is_enum(ctype)) goto match; break;
+ case TYPE_CODE_STRUCT: if(eppic_is_struct(ctype)) goto match; break;
+ case TYPE_CODE_UNION: if(eppic_is_union(ctype)) goto match; break;
+ }
+ eppic_dbg_named(DBG_TYPE, name, 2, "Found but no match.\n");
+ }
+ else eppic_dbg_named(DBG_TYPE, name, 2, "Not Found.\n");
+
+ return 0;
+
+match:
+ eppic_dbg_named(DBG_TYPE, name, 2, "Found.\n");
+ /* populate */
+ eppic_type_settype(tout, ctype);
+ eppic_type_setsize(tout, TYPE_LENGTH(type));
+ eppic_type_setidx(tout, (ull)(unsigned long)type);
+ eppic_pushref(tout, 0);
+ return 1;
+}
+
+/* set idx value to actual array indexes from specified size */
+static void
+eppic_setupidx(TYPE_S*t, int ref, int nidx, int *idxlst)
+{
+ /* put the idxlst in index size format */
+ if(nidx) {
+
+ int i;
+
+ for(i=0;i<nidx-1;i++) {
+ /* kludge for array dimensions of [1] */
+ if (idxlst[i+1] == 0) {
+ idxlst[i+1] = 1;
+ }
+ idxlst[i]=idxlst[i]/idxlst[i+1];
+ }
+
+ /* divide by element size for last element bound */
+ if(ref) idxlst[i] /= eppic_defbsize();
+ else idxlst[i] /= eppic_type_getsize(t);
+ eppic_type_setidxlst(t, idxlst);
+ }
+}
+/*
+ This function needs to drill down a typedef and
+ return the corresponding type.
+ If the typedef is from a basetype eppic_parsetype() will be
+ called back to build the type
+*/
+static char *
+drilldowntype(struct type *type, TYPE_S *t)
+{
+char *tstr=0;
+int fctflg=0, ref=0;
+int *idxlst=0;
+int nidx=0;
+
+ while(type)
+ {
+ check_typedef(type);
+
+ // check out for stub types and pull in the definition instead
+ if(TYPE_STUB(type) && TYPE_TAG_NAME(type)) {
+#ifdef GDB_6_1
+ struct symbol *sym=lookup_symbol(TYPE_TAG_NAME(type), 0, STRUCT_DOMAIN, 0, (struct symtab **) NULL);
+#else
+ struct symbol *sym=lookup_symbol(TYPE_TAG_NAME(type), 0, STRUCT_DOMAIN, 0);
+#endif
+ if(sym) {
+ type=sym->type;
+ }
+ }
+ switch(TYPE_CODE(type)) {
+
+ /* typedef inserts a level of reference to the 1'dactual type */
+ case TYPE_CODE_PTR:
+
+ ref++;
+ type=TYPE_TARGET_TYPE(type);
+ /* this could be a void*, in which case the drill down stops here */
+ if(!type) {
+
+ /* make it a char* */
+ eppic_parsetype("char", t, ref);
+ return 0;
+
+ }
+ break;
+
+ /* handle pointer to functions */
+ case TYPE_CODE_FUNC:
+
+ fctflg=1;
+ type=TYPE_TARGET_TYPE(type);
+ break;
+
+ /* Is this an array ? if so then just skip this type info and
+ we only need information on the elements themselves */
+ case TYPE_CODE_ARRAY:
+ if(!idxlst) idxlst=eppic_calloc(sizeof(int)*(MAXIDX+1));
+ if(nidx >= MAXIDX) eppic_error("Too many indexes! max=%d\n", MAXIDX);
+ if (TYPE_LENGTH (type) > 0 && TYPE_LENGTH (TYPE_TARGET_TYPE (type)) > 0)
+ {
+ idxlst[nidx++]=TYPE_LENGTH (type) / TYPE_LENGTH (check_typedef(TYPE_TARGET_TYPE (type)));
+ }
+ type=TYPE_TARGET_TYPE(type);
+ break;
+
+ /* typedef points to a typedef itself */
+ case TYPE_CODE_TYPEDEF:
+ type=TYPE_TARGET_TYPE(type);
+ break;
+
+ case TYPE_CODE_INT:
+
+ eppic_parsetype(tstr=TYPE_NAME(type), t, 0);
+ type=0;
+ break;
+
+ case TYPE_CODE_BOOL:
+ eppic_parsetype("char", t, ref);
+ type=0;
+ break;
+
+ case TYPE_CODE_UNION:
+ eppic_type_mkunion(t);
+ goto label;
+
+ case TYPE_CODE_ENUM:
+ eppic_type_mkenum(t);
+ goto label;
+
+ case TYPE_CODE_STRUCT:
+ {
+ eppic_type_mkstruct(t);
+
+label:
+ eppic_type_setsize(t, TYPE_LENGTH(type));
+ eppic_type_setidx(t, (ull)(unsigned long)type);
+ tstr=TYPE_TAG_NAME(type);
+ if(tstr) apigetctype(V_STRUCT, tstr, t);
+ type=0;
+ }
+ break;
+
+ /* we don;t have all the info about it */
+ case TYPE_CODE_VOID:
+ eppic_parsetype("int", t, 0);
+ type=0;
+ break;
+
+
+ default:
+ eppic_error("Oops drilldowntype");
+ break;
+ }
+
+
+ }
+ eppic_setupidx(t, ref, nidx, idxlst);
+ if(fctflg) eppic_type_setfct(t, 1);
+ eppic_pushref(t, ref+(nidx?1:0));
+ if(tstr) return eppic_strdup(tstr);
+ return eppic_strdup("");
+}
+
+static char *
+apigetrtype(ull idx, TYPE_S *t)
+{
+ return drilldowntype((struct type*)(unsigned long)(idx), t);
+}
+
+/*
+ Return the name of a symbol at an address (if any)
+*/
+static char*
+apifindsym(char *p)
+{
+ return NULL;
+}
+
+
+/*
+ Get the type, size and position information for a member of a structure.
+*/
+static char*
+apimember(char *mname, ull tnum, TYPE_S *tm, MEMBER_S *m, ull *lnum)
+{
+struct type *type=(struct type*)(unsigned long)tnum;
+int midx;
+#define LASTNUM (*lnum)
+
+ /* if we're being asked the next member in a getfirst/getnext sequence */
+ if(mname && !mname[0] && LASTNUM) {
+
+ midx = LASTNUM;
+
+ } else {
+
+ if (TYPE_CODE(type) == TYPE_CODE_TYPEDEF) {
+ return 0;
+ }
+ if ((TYPE_CODE(type) != TYPE_CODE_STRUCT) && (TYPE_CODE(type) != TYPE_CODE_UNION)) {
+ return 0;
+ }
+ midx=0;
+ }
+ while(midx < TYPE_NFIELDS(type)) {
+
+ if (!mname || !mname[0] || !strcmp(mname, TYPE_FIELD_NAME(type, midx))) {
+
+ check_typedef(TYPE_FIELD_TYPE(type, midx));
+ eppic_member_soffset(m, TYPE_FIELD_BITPOS(type, midx)/8);
+ eppic_member_ssize(m, TYPE_FIELD_TYPE(type, midx)->length);
+ eppic_member_snbits(m, TYPE_FIELD_BITSIZE(type, midx));
+ eppic_member_sfbit(m, TYPE_FIELD_BITPOS(type, midx)%8);
+ eppic_member_sname(m, TYPE_FIELD_NAME(type, midx));
+ LASTNUM=midx+1;
+ return drilldowntype(TYPE_FIELD_TYPE(type, midx), tm);
+ }
+ midx++;
+ }
+ return 0;
+}
+
+/*
+ This function gets the proper allignment value for a type.
+*/
+static int
+apialignment(ull idx)
+{
+struct type *type=(struct type *)(unsigned long)idx;
+
+ while(1)
+ {
+ switch(TYPE_CODE(type)) {
+
+ case TYPE_CODE_ARRAY: case TYPE_CODE_TYPEDEF:
+ type=TYPE_TARGET_TYPE(type);
+ break;
+
+ case TYPE_CODE_STRUCT:
+ case TYPE_CODE_UNION:
+ {
+ int max=0, cur;
+ int midx=0;
+
+ while(midx < TYPE_NFIELDS(type)) {
+ cur=apialignment((ull)(unsigned long)TYPE_FIELD_TYPE(type, midx));
+ if(cur > max) max=cur;
+ midx++;
+ }
+ return max;
+ }
+
+
+ case TYPE_CODE_PTR:
+ case TYPE_CODE_ENUM:
+ case TYPE_CODE_INT:
+
+ return TYPE_LENGTH (type);
+
+ default:
+
+ eppic_error("Oops apialignment");
+ }
+ }
+}
+
+/* get the value of a symbol */
+static int
+apigetval(char *name, ull *val, VALUE_S *value)
+{
+ if (symbol_exists(name)) {
+
+ *val=symbol_value(name);
+
+ if(value) {
+ struct expression *expr;
+ struct value *sval;
+ struct cleanup *old_chain = NULL;
+ struct type *type;
+ VALUE_S *vref;
+ TYPE_S *stype;
+ expr = parse_expression (name);
+ old_chain = make_cleanup (free_current_contents, &expr);
+ sval = evaluate_type (expr);
+ type = value_type(sval);
+ stype=eppic_gettype(value);
+ apigetrtype((ull)type, stype);
+ eppic_pushref(stype, 1);
+ eppic_setmemaddr(value, *val);
+ eppic_do_deref(1, value, value);
+ *val=eppic_getval(value);
+ if(!eppic_typeislocal(stype) && eppic_type_getidx(stype) > 100) {
+ char *tname;
+ type=(struct type*)((long)eppic_type_getidx(stype));
+ if(type->main_type) tname=type->main_type->tag_name;
+ if(tname) eppic_chktype(stype, tname);
+ }
+ do_cleanups (old_chain);
+ }
+ return 1;
+ }
+ return 0;
+}
+
+/*
+ Get the list of enum symbols.
+*/
+ENUM_S*
+apigetenum(char *name)
+{
+ struct symbol *sym;
+
+#ifdef GDB_6_1
+ sym = lookup_symbol(name, 0, STRUCT_DOMAIN, 0, (struct symtab **) NULL);
+#else
+ sym = lookup_symbol(name, 0, STRUCT_DOMAIN, 0);
+#endif
+ if (sym && TYPE_CODE(sym->type)==TYPE_CODE_ENUM) {
+ ENUM_S *et=0;
+ struct type *type=sym->type;
+ int n=0;
+ while(n < TYPE_NFIELDS (type)) {
+ et=eppic_add_enum(et, eppic_strdup(TYPE_FIELD_NAME(type, n)), TYPE_FIELD_BITPOS(type, n));
+ n++;
+ }
+ return et;
+ }
+ return 0;
+}
+
+/*
+ Return the list of preprocessor defines.
+ For Irix we have to get the die for a startup.c file.
+ Of dwarf type DW_TAG_compile_unit.
+ the DW_AT_producer will contain the compile line.
+
+ We then need to parse that line to get all the -Dname[=value]
+*/
+DEF_S *
+apigetdefs(void)
+{
+DEF_S *dt=0;
+int i;
+static struct linuxdefs_s {
+
+ char *name;
+ char *value;
+
+} linuxdefs[] = {
+
+ {"crash", "1"},
+ {"linux", "1"},
+ {"__linux", "1"},
+ {"__linux__", "1"},
+ {"unix", "1"},
+ {"__unix", "1"},
+ {"__unix__", "1"},
+ // helper macros
+ {"LINUX_2_2_16", "(LINUX_RELEASE==0x020210)"},
+ {"LINUX_2_2_17", "(LINUX_RELEASE==0x020211)"},
+ {"LINUX_2_4_0", "(LINUX_RELEASE==0x020400)"},
+ {"LINUX_2_2_X", "(((LINUX_RELEASE) & 0xffff00) == 0x020200)"},
+ {"LINUX_2_4_X", "(((LINUX_RELEASE) & 0xffff00) == 0x020400)"},
+ {"LINUX_2_6_X", "(((LINUX_RELEASE) & 0xffff00) == 0x020600)"},
+ {"LINUX_3_X_X", "(((LINUX_RELEASE) & 0xff0000) == 0x030000)"},
+ {"NULL", "0"},
+#ifdef i386
+ {"i386", "1"},
+ {"__i386", "1"},
+ {"__i386__", "1"},
+ {"BITS_PER_LONG","32"},
+#endif
+#ifdef s390
+ {"s390", "1"},
+ {"__s390", "1"},
+ {"__s390__", "1"},
+ {"BITS_PER_LONG","32"},
+#endif
+#ifdef s390x
+ {"s390x", "1"},
+ {"__s390x", "1"},
+ {"__s390x__", "1"},
+ {"BITS_PER_LONG","32"},
+#endif
+#ifdef __ia64__
+ {"ia64", "1"},
+ {"__ia64", "1"},
+ {"__ia64__", "1"},
+ {"__LP64__", "1"},
+ {"_LONGLONG", "1"},
+ {"__LONG_MAX__", "9223372036854775807L"},
+ {"BITS_PER_LONG","64"},
+#endif
+#ifdef __x86_64__
+ {"x86_64", "1"},
+ {"_x86_64_", "1"},
+ {"__x86_64__", "1"},
+ {"__LP64__", "1"},
+ {"_LONGLONG", "1"},
+ {"__LONG_MAX__", "9223372036854775807L"},
+ {"BITS_PER_LONG","64"},
+#endif
+#ifdef ppc64
+ {"ppc64", "1"},
+ {"__ppc64", "1"},
+ {"__ppc64__", "1"},
+ {"BITS_PER_LONG","64"},
+#endif
+ };
+
+static char *untdef[] = {
+ "clock",
+ "mode",
+ "pid",
+ "uid",
+ "xtime",
+ "init_task",
+ "size",
+ "type",
+ "level",
+ 0
+};
+
+#if 0
+How to extract basic set of -D flags from the kernel image
+
+ prod=eppic_strdup(kl_getproducer());
+ for(p=prod; *p; p++) {
+
+ if(*p=='-' && *(p+1)=='D') {
+
+ char *def=p+2;
+
+ while(*p && *p != '=' && *p != ' ') p++;
+
+ if(!*p || *p == ' ') {
+
+ *p='\0';
+ dt=eppic_add_def(dt, eppic_strdup(def), eppic_strdup("1"));
+
+ } else {
+
+ char *val=p+1;
+
+ *p++='\0';
+ while(*p && *p != ' ') p++;
+ *p='\0';
+
+ dt=eppic_add_def(dt, eppic_strdup(def), eppic_strdup(val));
+ }
+ }
+ }
+#endif
+
+ /* remove some tdef with very usual identifier.
+ could also be cases where the kernel defined a type and variable with same name e.g. xtime.
+ the same can be accomplished in source using #undef <tdefname> or forcing the evaluation of
+ a indentifier as a variable name ex: __var(xtime).
+
+ I tried to make the grammar as unambiqguous as I could.
+
+ If this becomes to much of a problem I might diable usage of all image typedefs usage in eppic!
+ */
+ {
+ char **tdefname=untdef;
+ while(*tdefname) eppic_addneg(*tdefname++);;
+
+ }
+
+ /* insert constant defines from list above */
+ for(i=0;i<sizeof(linuxdefs)/sizeof(linuxdefs[0]);i++) {
+
+ dt=eppic_add_def(dt, eppic_strdup(linuxdefs[i].name),
+ eppic_strdup(linuxdefs[i].value));
+ }
+
+#if 1
+ {
+ ull addr;
+ char banner[200];
+ if(apigetval("linux_banner", &addr, NULL)) {
+ if(apigetmem(addr, banner, sizeof banner-1)) {
+
+ // parse the banner string and set up release macros
+ banner[sizeof banner -1]='\0';
+ char *tok=strtok(banner, " \t");
+ if(tok) tok=strtok(NULL, " \t");
+ if(tok) tok=strtok(NULL, " \t");
+ if(tok) {
+ int version, patchlevel, sublevel, ret;
+ ret = sscanf(tok, "%d.%d.%d-", &version, &patchlevel, &sublevel);
+ switch (ret) {
+ case 2:
+ sublevel = 0;
+ case 3:
+ sprintf(banner, "0x%02x%02x%02x", version, patchlevel, sublevel);
+ dt=eppic_add_def(dt, eppic_strdup("LINUX_RELEASE"), eppic_strdup(banner));
+ eppic_msg("Core LINUX_RELEASE == '%s'\n", tok);
+ default:
+ break;
+ }
+ }
+ }
+ else eppic_msg("Eppic init: could not read symbol 'linux_banner' from corefile.\n");
+ }
+ else eppic_msg("Eppic init: could not find symbol 'linux_banner' in corefile.\n");
+ }
+#endif
+ return dt;
+}
+
+apiops icops= {
+ apigetmem,
+ apiputmem,
+ apimember,
+ apigetctype,
+ apigetrtype,
+ apialignment,
+ apigetval,
+ apigetenum,
+ apigetdefs,
+ apigetuint8,
+ apigetuint16,
+ apigetuint32,
+ apigetuint64,
+ apifindsym
+};
+
+void
+eppic_version(void)
+{
+ eppic_msg("< Eppic interpreter version %d.%d >\n"
+ , S_MAJOR, S_MINOR);
+}
+
+static void
+run_callback(void)
+{
+extern char *crash_global_cmd();
+FILE *ofp = NULL;
+
+ if (fp) {
+ ofp = eppic_getofile();
+ eppic_setofile(fp);
+ }
+
+ eppic_cmd(crash_global_cmd(), args, argcnt);
+
+ if (ofp)
+ eppic_setofile(ofp);
+}
+
+
+void
+edit_cmd(void)
+{
+int c, file=0;
+ while ((c = getopt(argcnt, args, "lf")) != EOF) {
+ switch(c)
+ {
+ case 'l':
+ eppic_vilast();
+ return;
+ break;
+ case 'f':
+ file++;
+ break;
+ default:
+ argerrs++;
+ break;
+ }
+ }
+
+ if (argerrs)
+ cmd_usage(crash_global_cmd(), SYNOPSIS);
+
+ else if(args[optind]) {
+ while(args[optind]) {
+ eppic_vi(args[optind++], file);
+ }
+ }
+ else cmd_usage(crash_global_cmd(), SYNOPSIS);
+}
+
+char *edit_help[]={
+ "edit",
+ "Start a $EDITOR session of a eppic function or file",
+ "<-f fileName>|<function name>",
+ "This command can be use during a tight development cycle",
+ "where frequent editing->run->editing sequences are executed.",
+ "To edit a known eppic macro file use the -f option. To edit the file",
+ "at the location of a known function's declaration omit the -f option.",
+ "Use a single -l option to be brought to the last compile error location.",
+ "",
+ "EXAMPLES:",
+ " %s> edit -f ps",
+ " %s> edit ps",
+ " %s> edit ps_opt",
+ " %s> edit -l",
+ NULL
+};
+
+
+// these control debug mode when parsing (pre-processor and compile)
+int eppicdebug, eppicppdebug;
+
+void
+load_cmd(void)
+{
+ if(argcnt< 2) cmd_usage(crash_global_cmd(), SYNOPSIS);
+ else {
+ eppic_setofile(fp);
+ eppic_loadunload(1, args[1], 0);
+ }
+}
+
+char *load_help[]={
+ "load",
+ "Load a eppic file",
+ "<fileName>|<Directory>",
+ " Load a file or a directory. In the case of a directory",
+ " all files in that directory will be loaded.",
+ NULL
+
+};
+
+void
+unload_cmd(void)
+{
+ if(argcnt < 2) cmd_usage(crash_global_cmd(), SYNOPSIS);
+ else eppic_loadunload(0, args[1], 0);
+}
+
+char *unload_help[]={
+ "unload",
+ "Unload a eppic file",
+ "<fileName>|<Directory>",
+ " Unload a file or a directory. In the case of a directory",
+ " all files in that directory will be unloaded.",
+ NULL
+};
+
+void
+sdebug_cmd(void)
+{
+ if(argcnt < 2) eppic_msg("Current eppic debug level is %d\n", eppic_getdbg());
+ else eppic_setdbg(atoi(args[1]));
+}
+
+char *sdebug_help[]={
+ "sdebug",
+ "Print or set eppic debug level",
+ "<Debug level 0..9>",
+ " Set the debug of eppic. Without any parameter, shows the current debug level.",
+ NULL
+};
+
+void
+sname_cmd(void)
+{
+ if(argcnt < 2) {
+ if(eppic_getname()) eppic_msg("Current eppic name match is '%s'\n", eppic_getname());
+ else eppic_msg("No name match specified yet.\n");
+ } else eppic_setname(args[1]);
+}
+
+char *sname_help[]={
+ "sname",
+ "Print or set eppic name match.",
+ "<name>",
+ " Set eppic name string for matches. Debug messages that are object oriented",
+ " will only be displayed if the object name (struct, type, ...) matches this",
+ " value.",
+ NULL
+};
+
+void
+sclass_cmd(void)
+{
+ if(argcnt < 2) {
+ char **classes=eppic_getclass();
+ eppic_msg("Current eppic classes are :");
+ while(*classes) eppic_msg("'%s' ", *classes++);
+ eppic_msg("\n");
+
+ }
+ else {
+ int i;
+ for(i=1; i<argcnt; i++) eppic_setclass(args[i]);
+ }
+}
+
+char *sclass_help[]={
+ "sclass",
+ "Print or set eppic debug message class(es).",
+ "<className>[, <className>]",
+ " Set eppic debug classes. Only debug messages that are in the specified classes",
+ " will be displayed.",
+ NULL
+};
+
+#define NCMDS 200
+static struct command_table_entry command_table[NCMDS] = {
+
+ {"edit", edit_cmd, edit_help},
+ {"load", load_cmd, load_help},
+ {"unload", unload_cmd, unload_help},
+ {"sdebug", sdebug_cmd, sdebug_help},
+ {"sname", sname_cmd, sname_help},
+ {"sclass", sclass_cmd, sclass_help},
+ {(char *)0 }
+};
+
+static void
+add_eppic_cmd(char *name, void (*cmd)(void), char **help, int flags)
+{
+struct command_table_entry *cp;
+struct command_table_entry *crash_cmd_table();
+
+ // check for a clash with native commands
+ for (cp = crash_cmd_table(); cp->name; cp++) {
+ if (!strcmp(cp->name, name)) {
+ eppic_msg("Eppic command name '%s' conflicts with native crash command.\n", name);
+ return;
+ }
+ }
+
+ // make sure we have enough space for the new command
+ if(!command_table[NCMDS-2].name) {
+ for (cp = command_table; cp->name; cp++);
+ cp->name=eppic_strdup(name);
+ cp->func=cmd;
+ cp->help_data=help;
+ cp->flags=flags;
+ }
+}
+
+static void
+rm_eppic_cmd(char *name)
+{
+struct command_table_entry *cp, *end;
+
+ for (cp = command_table; cp->name; cp++) {
+ if (!strcmp(cp->name, name)) {
+ eppic_free(cp->name);
+ memmove(cp, cp+1, sizeof *cp *(NCMDS-(cp-command_table)-1));
+ break;
+ }
+ }
+}
+
+/*
+ This function is called for every new function
+ generated by a load command. This enables us to
+ register new commands.
+
+ We check here is the functions:
+
+ fname_help()
+ fname_opt()
+ and
+ fname_usage()
+
+ exist, and if so then we have a new command.
+ Then we associated (register) a function with
+ the standard eppic callbacks.
+*/
+void
+reg_callback(char *name, int load)
+{
+char fname[MAX_SYMNAMELEN+sizeof("_usage")+1];
+char *help_str, *opt_str;
+char **help=malloc(sizeof *help * 5);
+
+ if(!help) return;
+ snprintf(fname, sizeof(fname), "%s_help", name);
+ if(eppic_chkfname(fname, 0)) {
+ snprintf(fname, sizeof(fname), "%s_usage", name);
+ if(eppic_chkfname(fname, 0)) {
+ if(load) {
+ opt_str=eppic_strdup((char*)(unsigned long)eppic_exefunc(fname, 0));
+ snprintf(fname, sizeof(fname), "%s_help", name);
+ help_str=eppic_strdup((char*)(unsigned long)eppic_exefunc(fname, 0));
+ help[0]=eppic_strdup(name);
+ help[1]="";
+ help[2]=eppic_strdup(opt_str);
+ help[3]=eppic_strdup(help_str);
+ help[4]=0;
+ add_eppic_cmd(name, run_callback, help, 0);
+ eppic_free(help_str);
+ eppic_free(opt_str);
+ return;
+ }
+ else rm_eppic_cmd(name);
+ }
+ }
+ free(help);
+ return;
+}
+
+/*
+ * The _fini() function is called if the shared object is unloaded.
+ * If desired, perform any cleanups here.
+ */
+void _fini()
+{
+ // need to unload any files we have loaded
+
+}
+
+VALUE_S *curtask(VALUE_S *v, ...)
+{
+unsigned long get_curtask();
+ return eppic_makebtype((ull)get_curtask());
+}
+
+_init() /* Register the command set. */
+{
+#define LCDIR "/usr/share/eppic/crash"
+#define LCIDIR "include"
+#define LCUDIR ".eppic"
+
+
+ if(eppic_open() >= 0) {
+
+ char *path, *ipath;
+ char *homepath=0;
+ char *home=getenv("HOME");
+
+ /* set api, default size, and default sign for types */
+#ifdef i386
+#define EPPIC_ABI ABI_INTEL_X86
+#else
+#ifdef __ia64__
+#define EPPIC_ABI ABI_INTEL_IA
+#else
+#ifdef __x86_64__
+#define EPPIC_ABI ABI_INTEL_IA
+#else
+#ifdef __s390__
+#define EPPIC_ABI ABI_S390
+#else
+#ifdef __s390x__
+#define EPPIC_ABI ABI_S390X
+#else
+#ifdef PPC64
+#define EPPIC_ABI ABI_PPC64
+#else
+#error eppic: Unkown ABI
+#endif
+#endif
+#endif
+#endif
+#endif
+#endif
+ eppic_apiset(&icops, EPPIC_ABI, sizeof(long), 0);
+
+ eppic_version();
+
+ /* set the macro search path */
+ if(!(path=getenv("EPPIC_MPATH"))) {
+
+ if(home) {
+
+ path=eppic_alloc(strlen(home)+sizeof(LCUDIR)+sizeof(LCDIR)+4);
+ homepath=eppic_alloc(strlen(home)+sizeof(LCUDIR)+2);
+
+ /* build a path for call to eppic_load() */
+ strcpy(homepath, home);
+ strcat(homepath, "/");
+ strcat(homepath, LCUDIR);
+
+ /* built the official path */
+ strcpy(path, LCDIR);
+ strcat(path, ":");
+ strcat(path, home);
+ strcat(path, "/");
+ strcat(path, LCUDIR);
+ }
+ else path=LCDIR;
+ }
+ eppic_setmpath(path);
+
+ fprintf(fp, "\tLoading eppic commands from %s .... ",
+ path);
+
+ /* include path */
+ if(!(ipath=getenv("EPPIC_IPATH"))) {
+
+ if(home) {
+
+ ipath=eppic_alloc(strlen(home)+sizeof(LCDIR)+sizeof(LCUDIR)+(sizeof(LCIDIR)*2)+(sizeof("/usr/include")+2)+6);
+
+ /* built the official path */
+ strcpy(ipath, LCDIR);
+ strcat(ipath, "/"LCIDIR":");
+ strcat(ipath, home);
+ strcat(ipath, "/");
+ strcat(ipath, LCUDIR);
+ strcat(ipath, "/"LCIDIR);
+ strcat(ipath, ":/usr/include");
+ }
+ else ipath=LCDIR"/"LCIDIR;
+ }
+ eppic_setipath(ipath);
+
+ /* set the new function callback */
+ eppic_setcallback(reg_callback);
+
+ /* load the default macros */
+ eppic_loadall();
+
+ /* load some eppic specific commands */
+ register_extension(command_table);
+
+ /* some builtins */
+ eppic_builtin("int curtask()", curtask);
+
+ fprintf(fp, "Done.\n");
+ }
+ return 1;
+}
+