This is extdebug.c in view mode; [Download] [Up]
#include <stdio.h> #include <stdlib.h> #include <fcntl.h> #include <io.h> #include <string.h> #include <dos.h> #include "gotypes.h" #include "aout.h" #include "extdebug.h" #include "dpmi.h" #include "paging.h" #include "tss.h" #include "exphdlr.h" #include "mswitch.h" #include "utils.h" #include "gdt.h" #include "utils.h" #include "eventque.h" extern EventQueue *event_queue; extern word32 dr[8]; extern word32 dr0, dr1, dr2, dr3, dr6, dr7; extern DPMImemory DPMImem; /* DPMI arena address from paging.c */ static ExternalDebuggerInfo ext_debug_info; int using_external_debugger = 0; static word16 ourDSsel; static int breakhandle[4],nset; /* for DPMI breakpoints */ #define VCPI_ED 1 void load_external_debugger(char *fn, char *running_fname, char *argv0) { FILEHDR eh; GNU_AOUT gah; #if VCPI_ED word32 edb_base; #endif int fd; char fn2[100], *fns; fd = _open(fn, O_RDONLY); if (fd < 0) { char *cp; strcpy(fn2, argv0); fns = 0; for (cp=fn2; *cp; cp++) if (strchr(":\\/", *cp)) fns = cp; if (fns) { strcpy(fns+1, fn); fd = _open(fn2, O_RDONLY); if (fd >= 0) fn = fn2; } } if (fd < 0) { char *path = getenv("PATH"); char *pathbeg=path, *pathsep; while (1) { pathsep = pathbeg; while (*pathsep && *pathsep != ';') pathsep++; strncpy(fn2, pathbeg, pathsep-pathbeg); fn2[pathsep-pathbeg] = '/'; strcpy(fn2+(pathsep-pathbeg)+1, fn); fd = _open(fn2, O_RDONLY); if (fd >= 0) { fn = fn2; break; } if (*pathsep == 0) break; pathbeg = pathsep+1; } } if (fd < 0) { fprintf(stderr, "Error: cannot open external debugger file %s\n", fn); perror("The error was"); exit(1); } read(fd, &eh, sizeof(eh)); if (eh.f_magic != 0x14c) { fprintf(stderr, "Invalid external debugger %s - not COFF binary\n", fn); exit(1); } read(fd, &gah, sizeof(gah)); #if VCPI_ED if (use_DPMI) edb_base = 0; else edb_base = 0x90000000L; if (gah.entry != edb_base+0x0a8L) { fprintf(stderr, "Invalid external debugger %s - entry point not 0x%lx (is 0x%lx)\n", fn, edb_base+0xa8L, gah.entry); if (gah.entry == 0x900000a8L) fprintf(stderr, "Try using the DPMI binary - ed32-dpmi - instead\n"); if (gah.entry == 0xa8) fprintf(stderr, "Try using the non-DPMI binary - edebug32 - instead\n"); exit(1); } #endif memcpy(&ed_tss, &a_tss, sizeof(TSS)); /* clone a_tss */ tss_ptr = &ed_tss; ed_tss.tss_eip = gah.entry; if (use_DPMI) { AREAS dbgarea; word32 newbytes; DPMImemory dbgmem; int dbgselect; dbgarea.first_addr = 0; dbgarea.last_addr = gah.tsize + gah.dsize + 0xa7; dbgarea.foffset = 0; dbgarea.fileno = fd; newbytes = (dbgarea.last_addr + 0x200fffL) & ~0xfff; /* 2Mb extra */ DPMIprotectedMode(); if (! DPMIalloc(&dbgmem, newbytes)) { DPMIrealMode(); fprintf(stderr,"DPMI: Not enough memory for debugger (0x%08lx bytes).\n", newbytes); exit(1); } ourDSsel = _DS; /* in protected mode, of course */ dbgselect = DPMIselector(2); /* one for CS, one for SS/DS */ DPMIassignSelector(dbgselect, 0xc0b3, dbgmem.address, dbgmem.bytes - 1 ); DPMIassignSelector(dbgselect+8, 0xc0bb, dbgmem.address, dbgmem.bytes - 1 ); DPMIrealMode(); ed_tss.tss_ds = ed_tss.tss_es = ed_tss.tss_fs = ed_tss.tss_ss = dbgselect; ed_tss.tss_cs = dbgselect + 8; ed_tss.tss_esp = dbgmem.bytes - 12; ed_tss.tss_eflags = 0x0202; loadAout(&dbgarea); Pmemset(dbgselect, dbgarea.last_addr+1, 0, dbgmem.bytes-dbgarea.last_addr-1); close(fd); } else { #if VCPI_ED areas[A_syms].first_addr = 0xa0000000L; areas[A_syms].last_addr = 0xa00000a7L + gah.tsize + gah.dsize; #else areas[A_syms].first_addr = 0xa0001000L; areas[A_syms].last_addr = 0xa00010a7L + gah.tsize + gah.dsize; #endif areas[A_syms].foffset = 0; areas[A_syms].fileno = fd; areas[A_syms2].first_addr = areas[A_syms].last_addr+1; areas[A_syms2].last_addr = 0xafffffffL; areas[A_syms2].foffset = -1; #if !VCPI_ED ed_tss.tss_esp = 0x0ffffff4l; ed_tss.tss_ds = g_edds * 8; ed_tss.tss_es = g_edds * 8; ed_tss.tss_ss = g_edds * 8; ed_tss.tss_cs = g_edcs * 8; ed_tss.tss_edi = 0; ed_tss.tss_ebx = 0; ed_tss.tss_ebp = 0; #else ed_tss.tss_esp = 0x9ffffff4l; #endif ourDSsel = g_rdata * 8; } ext_debug_info.version = EXTERNAL_DEBUGGER_VERSION; ext_debug_info.a_tss_ofs = FP_OFF(&a_tss); ext_debug_info.a_tss_seg = ourDSsel; ext_debug_info.filename_ofs = FP_OFF(running_fname); ext_debug_info.filename_seg = ourDSsel; ext_debug_info.filename_len = strlen(running_fname); ext_debug_info.areas_ofs = FP_OFF(&areas); ext_debug_info.areas_seg = ourDSsel; ext_debug_info.app_base = ARENA; ext_debug_info.ansi_mode = use_ansi; memset(ext_debug_info.dr, 32, 0); using_external_debugger = 1; } void set_break_DPMI(void) { int i,enabled,extract; word16 sizetype; word32 br_addr; enabled = (int)dr[7]; extract = (int)(dr[7] >> 16); nset = 0; for(i=0;i<4;i++) if( (enabled >> (i*2))&3 ) { sizetype = (extract >> (i*4)) & 3; /* extract the type */ if(sizetype == 3) sizetype = 2; /* convert for DPMI brain damage */ sizetype = (sizetype << 8) + ((extract >> (i*4+2)) & 3) + 1; /* & size */ br_addr = dr[i] + DPMImem.address; breakhandle[i] = DPMIsetBreak(sizetype, br_addr); if(breakhandle[i] == -1) fprintf(stderr,"Error allocating DPMI breakpoint at address 0x%08lx\n",dr[i]); else nset++; } else breakhandle[i] = -1; return; } void clear_break_DPMI(void) { int i,bt; if(!nset) { dr[6] = 0L; return; } bt = 0; for(i=3;i>=0;i--) { bt = bt << 1; /* Shift for next bit */ if(breakhandle[i] != -1) bt |= DPMIcancelBreak(breakhandle[i]); /* Set low bit if active */ } dr[6] = (word32)bt; } int external_debugger_handler(void) { static unsigned char old_enable; if (tss_ptr != &ed_tss) return 1; switch ((word8)(tss_ptr->tss_eax)) { case EXTERNAL_DEBUGGER_EXECUTE: if(event_queue != NULL) /* enable events */ event_queue->evq_enable = old_enable; tss_ptr = &a_tss; memcpy(dr, ext_debug_info.dr, 32); if (use_DPMI) set_break_DPMI(); go_til_stop(0); if (use_DPMI) clear_break_DPMI(); memcpy(ext_debug_info.dr, dr, 32); dr[7] = 0; if(event_queue != NULL) { /* disable events */ old_enable = event_queue->evq_enable; event_queue->evq_enable = 0; } if (a_tss.tss_irqn <= hard_master_hi && a_tss.tss_irqn >= hard_master_lo) a_tss.tss_irqn -= hard_master_lo - 8; if (a_tss.tss_irqn <= hard_slave_hi && a_tss.tss_irqn >= hard_slave_lo) a_tss.tss_irqn -= hard_slave_lo - 0x70; tss_ptr = &ed_tss; return 0; case EXTERNAL_DEBUGGER_GETINFOPTR: tss_ptr->tss_eax = FP_OFF(&ext_debug_info); tss_ptr->tss_edx = ourDSsel; return 0; default: return 1; } }
These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.