brucee@runx.ips.oz (Bruce Evans) (11/26/88)
#! /bin/sh # This is a shell archive. Remove anything before this line, then unpack # it by saving it into a file and typing "sh file". To overwrite existing # files, type "sh file -c". You can also feed this as standard input via # unshar, or by typing "sh <file", e.g.. If this archive is complete, you # will see the following message at the end: # "End of archive 6 (of 7)." # Contents: kernel/db/db.c # Wrapped by sys@besplex on Sat Nov 26 06:00:29 1988 PATH=/bin:/usr/bin:/usr/ucb ; export PATH if test -f 'kernel/db/db.c' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'kernel/db/db.c'\" else echo shar: Extracting \"'kernel/db/db.c'\" \(17761 characters\) sed "s/^X//" >'kernel/db/db.c' <<'END_OF_FILE' X/* db.c */ X X#include "const.h" X#include "type.h" X#include "chars.h" X#include "/usr/include/a.out.h" /* full pathname to get right one! */ X#undef EXTERN X#define EXTERN X#include "var.h" X X#define NBREAKPOINTS 16 X#define VECTOR_SEGMENT 0 X#define makevectoff( intnum ) (4 * (intnum)) X X/* command keys for db */ X X#define BREAK1 'b' X#define BREAK2 ETOA( F9 ) X#define CASEFLIP1 'c' X#define DUMP1 'd' X#define ENTER1 'e' X#define FORK1 'f' X#define GO1 'g' X#define GO2 ETOA( F5 ) X#define FLIP1 'x' X#define FLIP2 ETOA( F4 ) X#define HELP 'h' X#define INPORT1 'i' X#define ITRACEFLIP1 'j' X#define MAPDUMP1 'm' X#define MAPDUMP2 ETOA( F2 ) X#define OUTPORT1 'o' X#define PROCDUMP1 'p' X#define PROCDUMP2 ETOA( F1 ) X#define QUIT1 'q' X#define QUIT2 ESCAPE X#define REG1 'r' X#define REG2 ETOA( F3 ) X#define SLEVEL1 's' X#define SYMBOL1 'n' X#define TRACE1 't' X#define TRACE2 ETOA( F8 ) X#define UNASM1 'u' X#define VERBOSE_ENTRY_FLIP 'v' XPRIVATE struct X{ X bool_t armed; X struct breakentry *end; X struct breakentry X { X struct adr eadr; X opcode_pt oldval; X } X entry[NBREAKPOINTS]; X} X breaktable = { 0, breaktable.entry }; X XFORWARD struct breakentry *findbreakentry(); X#define getbigcount_t( x ) getoffset_t( (x) ) XFORWARD void getch(); X#define getcount_t( x ) getopcode_pt( (x) ) X#define getport_t( x ) getopcode_pt( (x) ) XFORWARD void getsym(); XFORWARD physoff_t linearadr(); XFORWARD offset_t pop(); X XPRIVATE unsigned base = 16; XPRIVATE char_pt ch; XPRIVATE count_t dlength = 8; XPRIVATE struct adr dptr; XPRIVATE count_t dwidth = 16; XPRIVATE bool_t gotrace = FALSE; XPRIVATE port_t inportnum = 0; XPRIVATE bool_t ints_while_tracing = FALSE; XPRIVATE char *lineptr; XPRIVATE char_pt lowch; XPRIVATE struct adr mptr = { 0, 0 }; XPRIVATE flags_t pretrace_f; XPRIVATE bigcount_t tracecount = 0; XPRIVATE bool_t traceprint = FALSE; XPRIVATE struct adr tracestack = { 0, 0 }; XPRIVATE bigcount_t traceremainder; XPRIVATE count_t ulength = 16; XPRIVATE bool_t verbose_entry = TRUE; X XPUBLIC void db_main( is_sstep, regs ) Xbool_pt is_sstep; Xstruct regs regs; X{ X char_pt key; X X if ( is_sstep ) X { X if ( traceremainder == 0 ) X { X /* false alarm */ X regs.f &= ~TF; X return; X } X regs.f = regs.f & ~(IF | TF) | pretrace_f & (IF | TF); Xtrace_entry: X ++tracecount; X /* X count-down only if stack is above current level X print the trace only if finished or printing enabled as well X */ X if ( regs.sp >= tracestack.off && X (tracestack.off == 0 || regs.ss == tracestack.seg) && X ((--traceremainder == 0 || traceprint)) && !gotrace ) X { X if ( !showentry( ®s ) ) X traceremainder = 0; X if ( traceremainder != 0 ) X closeio(); X } X if ( traceremainder != 0 ) X { X if ( trace1( ®s ) ) X /* trace was faked */ X goto trace_entry; X /* continue tracing */ X return; X } X if ( gotrace ) X { X gotrace = FALSE; X armbreakpoints(); X return; X } X if ( tracecount > 1 ) X { X outh32( tracecount ); X outnstr( " instructions traced" ); X } X } X else X { X /* breakpoint interrupt */ X --regs.ip; X if ( !breaktable.armed || X findbreakentry( (struct adr *) ®s.ip ) == NULL ) X ++regs.ip; X disarmbreakpoints(); X showentry( ®s ); X } X traceprint = FALSE; X dptr.seg = regs.ds; X while ( TRUE ) X { X nextline(); X key = lowch; X getsym(); X if ( ch == ':' || ch == ';' ) X { X setproc( key, &dptr, &mptr ); X continue; X } X switch( key ) X { X case BREAK1: X if ( ch == '-' ) X { X getsym(); X clearbreakpoint(); X } X else X setbreakpoint(); X case BREAK2: X showbreakpoints(); X break; X case CASEFLIP1: /* case CLOSE: overloaded */ X switch( lowch ) X { X case 'k': can_keyboard(); break; X case 's': can_screen(); break; X case 't': X getch(); X if ( lowch == 'i' ) X can_itty(); X else if ( lowch == 'i' ) X can_otty(); X else X { X can_itty(); X can_otty(); X } X break; X default: flipcase(); break; X } X break; X case DUMP1: X if ( lowch == 'l' ) X { X getsym(); X getcount_t( &dlength ); X break; X } X if ( lowch == 'w' ) X { X getsym(); X getcount_t( &dwidth ); X break; X } X getadr( &dptr ); X/* case DUMP2: */ X showmem(); X break; X case ENTER1: X getadr( &mptr ); X setmem(); X break; X case FLIP1: X case FLIP2: X show_user_screen(); X while ( testchar() == EOF ) /* inchar() messes cursor */ X ; X show_db_screen(); X break; X case FORK1: X --regs.ip; X if ( peek8 ( (struct adr *) ®s.ip ) != INT_BREAKPOINT ) X ++regs.ip; X else X { X mptr.off = regs.ip; X mptr.seg = regs.cs; X setmem(); X } X break; X case GO1: X setbreakpoint(); X case GO2: X if ( findbreakentry( (struct adr *) ®s.ip ) != NULL ) X { X tracestack.off = 0; X ints_while_tracing = FALSE; X gotrace = TRUE; X goto trace; X } X armbreakpoints(); X /* fall into QUIT1 */ X case QUIT1: X case QUIT2: X tracestack.off = 0; X ints_while_tracing = FALSE; X closeio(); X return; X case HELP: X info(); X break; X case INPORT1: X showport(); X break; X case ITRACEFLIP1: X if ( (ints_while_tracing = !ints_while_tracing) == FALSE ) X outnstr( "Interrupts disabled while tracing" ); X else X outnstr( "Interrupts enabled while tracing" ); X break; X#ifndef DOS X case MAPDUMP1: X case MAPDUMP2: X map_dmp(); X break; X#endif X case OUTPORT1: /* case OPEN: overloaded */ X switch( lowch ) X { X case 'k': enab_keyboard(); break; X case 's': enab_screen(); break; X case 't': X getch(); X if ( lowch == 'i' ) X enab_itty(); X else if ( lowch == 'i' ) X enab_otty(); X else X { X enab_itty(); X enab_otty(); X } X break; X } X setport(); X break; X#ifndef DOS X case PROCDUMP1: X case PROCDUMP2: X p_dmp(); X break; X#endif X case REG1: X case REG2: X showregs( ®s ); X break; X case SLEVEL1: /* case STTY: is overloaded */ X if ( lowch == 't' ) X { X set_tty(); X break; X } X if ( !getoffset_t( &tracestack.off ) ) X { X if ( tracestack.off == 0 ) X tracestack.off = regs.sp; X else X tracestack.off = 0; X } X outh32( tracestack.off ); X outnl(); X break; X case SYMBOL1: X if ( ch != 0 ) X --lineptr; X findsname( lineptr, CSEG, TRUE ); X break; X case TRACE1: X if ( lowch == 'p' ) X { X traceprint = TRUE; X getsym(); X } X if ( getbigcount_t( &traceremainder ) && traceremainder == 0 ) X { X traceprint = FALSE; X break; X } X case TRACE2: Xtrace: X if ( traceremainder == 0 ) X ++traceremainder; X tracestack.seg = regs.ss; X closeio(); X tracecount = 0; X if ( trace1( ®s ) ) X goto trace_entry; X return; X case UNASM1: X if ( lowch == 'l' ) X { X getsym(); X getcount_t( &ulength ); X break; X } X getadr( &uptr ); X/* case UNASM2: */ X showinstructions(); X break; X case VERBOSE_ENTRY_FLIP: X verbose_entry = !verbose_entry; X break; X } X } X} X XPRIVATE void armbreakpoints() X{ X struct breakentry *entry; X X for ( entry = breaktable.entry; entry < breaktable.end; ++entry ) X { X entry->oldval = peek8( &entry->eadr ); X poke8( &entry->eadr, INT_BREAKPOINT ); X } X breaktable.armed = TRUE; X} X XPRIVATE void clearbreakpoint() X{ X struct breakentry *entry; X struct adr adr; X X if ( lowch == '-' ) X breaktable.end = breaktable.entry; X else if ( adr.seg = uptr.seg, getadr( &adr ) ) X { X if ( (entry = findbreakentry( &adr )) == NULL ) X error( "No Breakpoint Set" ); X else X { X memcpy( (char *) entry, (char *) (entry + 1), X (unsigned) ((char *) breaktable.end - (char *) entry) ); X --breaktable.end; X } X } X} X XPRIVATE void disarmbreakpoints() X{ X struct breakentry *entry; X X if ( breaktable.armed ) X { X for ( entry = breaktable.entry; entry < breaktable.end; ++entry ) X poke8( &entry->eadr, entry->oldval ); X breaktable.armed = FALSE; X } X} X XPRIVATE void error( s ) Xchar *s; X{ X outnstr( s ); X} X XPRIVATE void fakeint( intnum, regs ) Xunsigned intnum; Xstruct regs *regs; X{ X push( regs->f, regs ); X regs->f &= ~(IF | TF); X push( (offset_t) regs->cs, regs ); X regs->cs = peekw( VECTOR_SEGMENT, makevectoff( intnum ) + 2 ); X push( regs->ip, regs ); X regs->ip = peekw( VECTOR_SEGMENT, makevectoff( intnum ) ); X} X XPRIVATE struct breakentry *findbreakentry( adr ) Xstruct adr *adr; X{ X struct breakentry *entry; X X for ( entry = breaktable.entry; entry < breaktable.end; ++entry ) X if ( linearadr( &entry->eadr ) == linearadr( adr ) ) X return entry; X return NULL; X} X XPRIVATE void get1char() X{ X static char line[2] = { 0, 0 }; X X line[0] = ch = inchar(); X lineptr = line; X getch(); X} X X XPUBLIC void info() X{ X outstr( "MINIX db v1.0" ); X outnl(); X outstr( "Processor type is " ); X switch( db_processor ) X { X case 86: outstr( "8088 or 8086" ); break; X case 186: outstr( "80188 or 80186" ); break; X case 286: outstr( "80286" ); break; X case 386: outstr( "80386" ); break; X } X outnl(); X} X XPRIVATE physoff_t linearadr( adr ) Xstruct adr *adr; X{ X return CLICK_SIZE * (physoff_t) adr->seg + adr->off; X} X XPRIVATE offset_t pop( regs ) Xstruct regs *regs; X{ X offset_t value; X X /* need mods here for 32 bits and protected mode */ X value = peek16( (struct adr *) ®s->sp ); X regs->sp += 2; X return value; X} X XPRIVATE void push( value, regs ) Xoffset_t value; Xstruct regs *regs; X{ X regs->sp -= 2; X /* need mods here for 32 bits and protected mode */ X poke16( (struct adr *) ®s->sp, (u16_t) value ); X} X XPRIVATE void setbreakpoint() X{ X struct breakentry *entry; X X if ( (entry = breaktable.end) >= (breaktable.entry + NBREAKPOINTS) ) X { X error( "Breakpoint Table Full" ); X } X else if ( entry->eadr.seg = uptr.seg, getadr( &entry->eadr ) ) X { X if ( findbreakentry( entry ) != NULL ) X error( "Breakpoint Already Set" ); X else X { X entry->oldval = peek8( &entry->eadr ); X if ( (poke8( &entry->eadr, 0x55 ), peek8( &entry->eadr ) != 0x55) || X (poke8( &entry->eadr, 0xAA ), peek8( &entry->eadr ) != 0xAA) ) X error( "Breakpoint in ROM?" ); X else X ++breaktable.end; X poke8( &entry->eadr, entry->oldval ); X } X } X} X XPRIVATE void setmem() X{ X opcode_pt byte; X char_pt digit; X X outssegadr( &mptr ); X while ( TRUE ) X { X outh8( peek8( &mptr ) ); X outbyte( '-' ); X get1char(); X if ( getdigit( &digit ) ) X { X outbyte( lineptr[-1] ); X byte = digit; X while ( get1char(), getdigit( &digit ) ) X { X outbyte( lineptr[-1] ); X byte = byte * base + digit; X } X poke8( &mptr, byte ); X } X if ( ch == ' ' ) X ++mptr.off; X else if ( ch == '-' ) X { X --mptr.off; X outnl(); X outsegadr( &mptr ); X } X else X break; X out2space(); X } X outnl(); X} X XPRIVATE void setport() X{ X opcode_pt byte; X port_t outportnum; X X if ( getport_t( &outportnum ) && getopcode_pt( &byte ) ) X /* don't display port, may be side affect */ X oportb( outportnum, byte ); X} X XPRIVATE bool_pt show1instruction() X{ X bool_pt idone; X static char line[81]; X struct adr newuptr; X struct adr olduptr; X bool_pt outnlstatus; X struct nlist *sp; X X outbyte( '\r' ); X do X { X if ( (sp = findsval( uptr.off, CSEG )) != NULL && sp->n_value == uptr.off ) X { X outsym( sp, uptr.off ); X outcolon(); X outnl(); X } X olduptr = uptr; X openstring( line ); X idone = puti(); X line[stringpos()] = 0; X closestring(); X newuptr = uptr; X uptr = olduptr; X outssegadr( &uptr ); X while ( uptr.off != newuptr.off ) X outget8(); X if ( newuptr.off - olduptr.off < ((db_processor == 386) ? 5 : 3) ) X outtab(); /* to column 16 (24 for 386) */ X outtab(); /* to column 24 (32 for 386) */ X outnlstatus = outnstr( line ); X } X while ( !idone ); /* eat all prefixes */ X return outnlstatus; X} X XPRIVATE void showbreakpoints() X{ X struct breakentry *entry; X unsigned n; X X for ( entry = breaktable.entry, n = 0; entry < breaktable.end; ++entry, ++n ) X { X outssegadr( &entry->eadr ); X if ( n == 6 ) X { X outnl(); X n = -1; X } X } X if ( n != 0 ) X outnl(); X} X XPRIVATE bool_pt showentry( regs ) Xstruct regs *regs; X{ X openio(); X syminit(); X if ( verbose_entry ) X return showregs( regs ); X else X { X uptr.off = regs->ip; X uptr.seg = regs->cs; X return show1instruction(); X } X} X XPRIVATE void showinstructions() X{ X count_t row; X X for ( row = 0; row < ulength; ++row ) X if ( !show1instruction() ) X break; X} X XPRIVATE void showmem() X{ X u8_pt byte; X count_t column; X offset_t oldoffset; X count_t row; X X for ( column = (db_processor == 386 ? 16 : 12); column != 0; --column ) X /* spaces on title line above address */ X outspace(); X for ( column = 0; column < dwidth; ++column ) X { X outh4( (u4_pt) (dptr.off + column) ); X out2space(); X } X for ( row = 0; row < dlength; ++row ) X { X if ( !outnl() ) X break; X outssegadr( &dptr ); X for ( column = 0, oldoffset = dptr.off; column < dwidth; ++column ) X { X outh8s( peek8( &dptr ) ); X ++dptr.off; X } X for ( column = 0, dptr.off = oldoffset; column < dwidth; ++column ) X { X byte = peek8( &dptr ); X ++dptr.off; X if ( byte >= 0x7F || byte < ' ' ) X byte = '.'; X outbyte( (int) byte ); X } X } X outnl(); X} X XPRIVATE void showport() X{ X if ( !getport_t( &inportnum ) ) X { X outh16( inportnum ); X outcolon(); X outspace(); X } X outh8( inportb( inportnum ) ); X outnl(); X} X XPRIVATE bool_pt showregs( regs ) Xstruct regs *regs; X{ X char *nameptr; X static char *regnames = X "ax\0bx\0cx\0dx\0\nsi\0di\0bp\0\nds\0es\0sp\0ss\0\nip\0cs\0 f\0\n"; X offset_t *regptr; X X outbyte( '\r' ); X for ( nameptr = regnames, regptr = (offset_t *) regs; *nameptr != 0; ) X { X outustr( nameptr ); X outstr( " = " ); X if ( nameptr[1] == 's' ) X { X if ( db_processor == 386 ) X { X out2space(); X out2space(); X } X outh16( *(u16_t *) regptr ); X regptr = (offset_t *) ((u16_t *) regptr + 1); X } X else if ( db_processor == 386 ) X outh32( *regptr++ ); X else X outh16( (u16_t) *regptr++ ); X nameptr += 3; X if ( *nameptr == '\n' ) X { X ++nameptr; X outnl(); X } X else X outstr( " " ); X } X uptr.off = regs->ip; X uptr.seg = regs->cs; X return show1instruction(); X} X X/* set up for trace of 1 instruction, maybe fake the instruction */ X XPRIVATE bool_pt trace1( regs ) Xstruct regs *regs; X{ X unsigned intnum; X X /* X The 386 clears the trap flag for software interrupts. X This is undesirable since we want to trace them, both to debug and to X get proper instruction counts. X So fake these instructions (real mode only). X Division by zero and other 386 exceptions require another method. X Also fake all instructions which change the interrupt flag: X CLI, IRET, POPF, PUSHF, STI. X These fakes are not quite right yet, since prefixed instructions are X not caught. X INT and IRET are extremely complicated in protected mode and it will X be a big job to emulate them. X */ X#define BREAKPOINT_VECTOR 3 X#define CLI 0xFA X#define INT_GENERAL 0xCD X#define INT_OVERFLOW 0xCE X#define INTO_VECTOR 4 X#define IRET 0xCF X#define POPF 0x9D X#define PUSHF 0x9C X#define STI 0xFB X X switch( peek8( (struct adr *) ®s->ip ) ) X { X case CLI: X regs->f &= ~IF; X break; X case INT_GENERAL: X if ( protected ) X goto toohard; X ++regs->ip; X intnum = peek8( (struct adr *) ®s->ip ); X ++regs->ip; X fakeint( intnum, regs ); X return TRUE; X case INT_BREAKPOINT: X if ( protected ) X goto toohard; X fakeint( BREAKPOINT_VECTOR, regs ); X return TRUE; X case INT_OVERFLOW: X if ( protected ) X goto toohard; X fakeint( INTO_VECTOR, regs ); X return TRUE; X case IRET: X if ( protected ) X goto toohard; X regs->ip = pop( regs ); X regs->cs = pop( regs ); X regs->f = pop( regs ); X return TRUE; X case POPF: X if ( protected ) X goto toohard; X regs->f = pop( regs ); X break; X case PUSHF: X if ( protected ) X goto toohard; X push( regs->f, regs ); X break; X case STI: X regs->f |= IF; X break; X default: Xtoohard: X pretrace_f = regs->f; X if ( !ints_while_tracing ) X regs->f &= ~IF; X regs->f |= TF; X return FALSE; X } X ++regs->ip; X return TRUE; X} X X#ifdef DOS X X/* various dummy routines */ X XPUBLIC struct nlist *findsname() X{ X return NULL; X} X XPUBLIC struct nlist *findsval() X{ X return NULL; X} X XPUBLIC void get_con_state() X{ X} X XPUBLIC void outsym() X{ X} X XPUBLIC void reboot() X{ X} X XPUBLIC void reset_con_state() X{ X} X XPUBLIC void setproc() X{ X} X XPUBLIC void syminit() X{ X prompt = '?'; X} X X#endif X X/* parsing routines */ X X/* test input for being an address expression of the form [segment:;]offset */ X/* where segment and offset are numbers in the current base, fetch if so */ X XPRIVATE bool_pt getadr( adr ) Xstruct adr *adr; X{ X struct adr tempadr; X X if ( !getoffset_t( &tempadr.off ) ) X return FALSE; X if ( ch == ':' || ch == ';' ) X { X getsym(); X tempadr.seg = tempadr.off; X if ( !getoffset_t( &tempadr.off ) ) X return FALSE; X adr->seg = tempadr.seg; X } X adr->off = tempadr.off; X return TRUE; X} X XPRIVATE char_pt getch() X{ X /* convert to unsigned char so ETOA macro works */ X if ( (ch = UCHAR( *lineptr )) != 0 ) X ++lineptr; X lowch = mytolower( ch ); X return ch; X} X X/* test input for being an opcode_pt in the current base, fetch if so */ X XPRIVATE bool_pt getopcode_pt( num ) Xopcode_pt *num; X{ X offset_t tempnum; X X if ( !getoffset_t( &tempnum ) ) X return FALSE; X *num = tempnum; X return TRUE; X} X X/* test current char for being a digit in the current base, fetch if so */ X XPRIVATE bool_pt getdigit( digit ) Xchar_pt *digit; X{ X char_pt tempdigit; X X if ( (tempdigit = lowch) >= '0' && tempdigit <= '9' ) X tempdigit = tempdigit - '0'; X else if ( tempdigit >= 'a' && tempdigit <= 'f' ) X tempdigit = tempdigit + (10 - 'a'); X else X return FALSE; X if ( tempdigit >= base ) X return FALSE; X *digit = tempdigit; X getch(); X return TRUE; X} X X/* test input for being an offset_t in the current base, fetch if so */ X XPRIVATE bool_pt getoffset_t( num ) Xoffset_t *num; X{ X char_pt digit; X offset_t tempnum; X X if ( !getdigit( &digit ) ) X return FALSE; X tempnum = digit; X while ( getdigit( &digit ) ) X tempnum = tempnum * base + digit; X *num = tempnum; X if ( ch == ' ' ) X getsym(); X return TRUE; X} X XPRIVATE void getsym() X{ X while( getch() == ' ' ) X ; X} X XPRIVATE void nextline() X{ X lineptr = getline(); X if ( UCHAR( *lineptr ) <= '~' ) X outnl(); X getsym(); X} END_OF_FILE if test 17761 -ne `wc -c <'kernel/db/db.c'`; then echo shar: \"'kernel/db/db.c'\" unpacked with wrong size! fi # end of 'kernel/db/db.c' fi echo shar: End of archive 6 \(of 7\). cp /dev/null ark6isdone MISSING="" for I in 1 2 3 4 5 6 7 ; do if test ! -f ark${I}isdone ; then MISSING="${MISSING} ${I}" fi done if test "${MISSING}" = "" ; then echo You have unpacked all 7 archives. rm -f ark[1-9]isdone else echo You still need to unpack the following archives: echo " " ${MISSING} fi ## End of shell archive. exit 0 Bruce Evans Internet: brucee@runx.ips.oz.au UUCP: uunet!runx.ips.oz.au!brucee