www.delorie.com/archives/browse.cgi   search  
Mail Archives: djgpp-workers/1999/03/23/17:36:07

Sender: nate AT cartsys DOT com
Message-ID: <36F8160F.3E388D52@cartsys.com>
Date: Tue, 23 Mar 1999 14:30:39 -0800
From: Nate Eldredge <nate AT cartsys DOT com>
X-Mailer: Mozilla 4.08 [en] (X11; I; Linux 2.2.3 i586)
MIME-Version: 1.0
To: djgpp-workers AT delorie DOT com
Subject: Patch: Child memory access in dbgcom checks page attributes
Reply-To: djgpp-workers AT delorie DOT com

This patch makes a debugger check the page attributes of the memory it's
about to access in the child, to make sure it's accessible.  This
prevents the debugger crashing if you try to (for instance) examine an
uncommitted page.  It should have no effect on DPMI servers other than
CWSDPMI (and maybe 386MAX) except to slow things down a little. :)

It's necessary for another project I'm working on, which uncommits pages
to prevent malloc overruns and such, but IMHO it's also a Good Thing in
general.  (Incidentally, those wanting to test my malloc debugger are
welcome also; just ask me.  The main thing it needs before release is
documentation, which I'm just too lazy to write at present.)

I'm not necessarily submitting this for 2.03; it should probably get
some more testing.  But I just wanted to throw it out there and see what
people think.

Off the subject: Why are the arrays at the top of dbgcom.c global?  I
made mine the same for no real reason.

Patch follows.
--- src/debug/common/dbgcom.c.orig	Mon Mar 22 20:25:17 1999
+++ src/debug/common/dbgcom.c	Tue Mar 23 14:18:17 1999
@@ -27,6 +27,7 @@
 #define DOS_DESCRIPTOR_COUNT	128
 
 long mem_handles[MEM_HANDLE_COUNT];
+unsigned long block_base_addresses[MEM_HANDLE_COUNT];
 unsigned short descriptors[DESCRIPTOR_COUNT];
 unsigned short dos_descriptors[DOS_DESCRIPTOR_COUNT];
 NPX npx;
@@ -211,8 +212,15 @@
 	.text								\n\
 	.align  2,0x90							\n\
 _change_handle:								\n\
+	pushl	%ebx							\n\
 	pushl	%ecx							\n\
+	pushw	%bx							\n\
+	pushw	%cx							\n\
+	popl	%ebx /* get address of block */				\n\
 	xorl	%ecx,%ecx						\n\
+	orl	%edx, %edx						\n\
+	jnz	CL1							\n\
+	xorl	%ebx, %ebx /* zero address if freeing */		\n\
 CL1:									\n\
 	.byte	0x2e 							\n\
 	cmpl	%eax,_mem_handles(,%ecx,4)				\n\
@@ -222,14 +230,17 @@
 	movw	_my_ds,%ax						\n\
 	movw	%ax,%ds							\n\
 	movl	%edx,_mem_handles(,%ecx,4)				\n\
+	movl	%ebx,_block_base_addresses(,%ecx,4)			\n\
 	pop	%ds							\n\
 	popl	%ecx							\n\
+	popl	%ebx							\n\
 	ret								\n\
 CL2:									\n\
 	incl	%ecx							\n\
 	cmpl	$256,%ecx	/* MEM_HANDLE_COUNT */			\n\
 	jl	CL1							\n\
 	popl	%ecx							\n\
+	popl	%ebx							\n\
 	ret								\n"
 );
 
@@ -600,28 +611,70 @@
   _clear_break_DPMI();
 }
 
-static int invalid_addr(unsigned a, unsigned len)
+static void setup_handle_and_address(unsigned a, __dpmi_meminfo *m)
+{
+  int i, best;
+  unsigned bestdiff;
+  unsigned long base;
+  unsigned linear;
+  __dpmi_get_segment_base_address(__djgpp_app_DS, &base);
+  linear = a + base;
+  best = -1;
+  bestdiff = 0xffffffff;
+  for (i = 0; i < MEM_HANDLE_COUNT; i++)
+    {
+      if (block_base_addresses[i]
+	  && linear > block_base_addresses[i]
+	  && (block_base_addresses[i] - linear) < bestdiff)
+	{	
+	  best = i;
+	  bestdiff = block_base_addresses[i] - linear;
+	}
+    }
+  m->handle = mem_handles[best];
+  m->address = linear - block_base_addresses[best];
+}
+
+static int invalid_addr(unsigned a, unsigned len, int wr)
 {
   /* Here we assume expand up writable code.  We could check the rights
to
      be sure, but that's a waste unless *_child routines fixed to know
about
      different selectors. */
 
   unsigned limit;
+  if (a <= 4096)
+    return 1; /* Null page */
   limit = __dpmi_get_segment_limit(__djgpp_app_DS);
-  if(4096 <= a             /* First page is used for NULL pointer
detection. */
-  && a <= limit            /* To guard against limit < len. */
-  && a - 1 <= limit - len  /* To guard against limit <= a + len - 1. */
-     )
-    return 0;
-/*  printf("Invalid access to child, address %#x length %#x  limit:
%#x\n", a, len, limit);
-  if (can_longjmp)
-    longjmp(debugger_jmpbuf, 1); */
-  return 1;
+  if (a > limit || (a - 1) > (limit - len))
+      return 1; /* Beyond limit */
+  {
+    unsigned short *attr;
+    __dpmi_meminfo m;
+    unsigned long startpg;
+    unsigned long npgs;
+
+    startpg = (unsigned long)a & ~4095;
+    npgs = (len + 4095) / 4096;
+    attr = alloca(npgs * sizeof(unsigned short));
+    setup_handle_and_address(startpg, &m);
+    m.size = npgs;
+    if (__dpmi_get_page_attributes(&m, attr) == 0)
+      {
+	int i;
+	for (i = 0; i < npgs; i++)
+	  {
+	    if (((attr[i] & 7) == 0) /* uncommitted */
+		|| (wr && !(attr[i] & 8))) /* read-only */
+		return 1;
+	  }
+      }
+  }
+  return 0;
 }
 
 int read_child(unsigned child_addr, void *buf, unsigned len)
 {
-  if (invalid_addr(child_addr, len))
+  if (invalid_addr(child_addr, len, 0))
     return 1;
   movedata(__djgpp_app_DS, child_addr, my_ds, (int)buf, len);
   return 0;
@@ -629,7 +682,7 @@
 
 int write_child(unsigned child_addr, void *buf, unsigned len)
 {
-  if (invalid_addr(child_addr, len))
+  if (invalid_addr(child_addr, len, 1))
     return 1;
   movedata(my_ds, (int)buf, __djgpp_app_DS, child_addr, len);
   return 0;
@@ -671,6 +724,13 @@
   movedata(a_tss.tss_fs,0,my_ds,(unsigned)&si,sizeof(si));
   memset(mem_handles,0,sizeof(mem_handles));
   mem_handles[0] = si.memory_handle;
+  /* Kludge: The base address of the first handle is also the base
+     address of the DS segment. */
+  {
+    unsigned long b;
+    __dpmi_get_segment_base_address(__djgpp_app_DS, &b);
+    block_base_addresses[0] = b;
+  }
   memset(descriptors,0,sizeof(descriptors));
   descriptors[0] = si.cs_selector;
   descriptors[1] = si.ds_selector;

-- 

Nate Eldredge
nate AT cartsys DOT com

- Raw text -


  webmaster     delorie software   privacy  
  Copyright © 2019   by DJ Delorie     Updated Jul 2019