ftp.nice.ch/pub/next/developer/languages/c/djgpp-NS.s.tar.gz#/djgpp/go32/extdebug.c

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.