Sign Up
Log In
Log In
or
Sign Up
Places
All Projects
Status Monitor
Collapse sidebar
home:mwilck:branches:Kernel:kdump
crash
eppic-switch-to-system-lib.patch
Overview
Repositories
Revisions
Requests
Users
Attributes
Meta
File eppic-switch-to-system-lib.patch of Package crash
--- 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; +} +
Locations
Projects
Search
Status Monitor
Help
OpenBuildService.org
Documentation
API Documentation
Code of Conduct
Contact
Support
@OBShq
Terms
openSUSE Build Service is sponsored by
The Open Build Service is an
openSUSE project
.
Sign Up
Log In
Places
Places
All Projects
Status Monitor