delorie.com/archives/browse.cgi   search  
Mail Archives: djgpp-workers/2009/11/07/08:26:45

X-Authentication-Warning: delorie.com: mail set sender to djgpp-workers-bounces using -f
X-Recipient: djgpp-workers AT delorie DOT com
Date: Sat, 07 Nov 2009 15:06:43 +0200
From: Eli Zaretskii <eliz AT gnu DOT org>
Subject: Re: Patch for windows watchpoint bug
In-reply-to: <003301ca5a70$7be8c5d0$73ba5170$@u-strasbg.fr>
X-012-Sender: halo1 AT inter DOT net DOT il
To: Pierre Muller <muller AT ics DOT u-strasbg DOT fr>
Cc: djgpp-workers AT delorie DOT com
Message-id: <83tyx6a3h8.fsf@gnu.org>
References: <001501c9e913$d9751830$8c5f4890$@u-strasbg.fr> <E1MEHx1-00069H-OM AT fencepost DOT gnu DOT org> <002501c9eadd$8433d070$8c9b7150$@u-strasbg.fr> <000f01ca517c$7a85e3f0$6f91abd0$@u-strasbg.fr> <83k4ykga4m DOT fsf AT gnu DOT org> <000c01ca5a3a$c09c4430$41d4cc90$@u-strasbg.fr> <83y6mrd0vv DOT fsf AT gnu DOT org> <003301ca5a70$7be8c5d0$73ba5170$@u-strasbg.fr>
Reply-To: djgpp-workers AT delorie DOT com
Errors-To: nobody AT delorie DOT com
X-Mailing-List: djgpp-workers AT delorie DOT com
X-Unsubscribes-To: listserv AT delorie DOT com

> From: "Pierre Muller" <muller AT ics DOT u-strasbg DOT fr>
> Date: Sat, 31 Oct 2009 22:24:07 +0100
> 
> What I found was
> gcc -s @../../gcc-l.opt -I. -I- -I../../../include -c dbgcom.c
> 
> gcc-l.opt contains only 
> -g 
> in my setup,
> but the default is probably
> -g -O2

No, it contains much more than that.

> Anyhow, using just this command line did
> recreate the correct object.

Do you still get these warnings (I do):

    dbgcom.c:25: warning: 'id' defined but not used
    D:/usr/tmp/cccwRkzy.s: Assembler messages:
    D:/usr/tmp/cccwRkzy.s:71: Warning: indirect lcall without `*'
    D:/usr/tmp/cccwRkzy.s:100: Warning: indirect ljmp without `*'
    D:/usr/tmp/cccwRkzy.s:167: Warning: indirect lcall without `*'
    D:/usr/tmp/cccwRkzy.s:251: Warning: indirect ljmp without `*'
    D:/usr/tmp/cccwRkzy.s:292: Warning: indirect lcall without `*'
    D:/usr/tmp/cccwRkzy.s:313: Warning: indirect lcall without `*'
    D:/usr/tmp/cccwRkzy.s:331: Warning: indirect lcall without `*'
    D:/usr/tmp/cccwRkzy.s:345: Warning: indirect lcall without `*'
    D:/usr/tmp/cccwRkzy.s:363: Warning: indirect lcall without `*'
    D:/usr/tmp/cccwRkzy.s:373: Warning: indirect lcall without `*'
    D:/usr/tmp/cccwRkzy.s:385: Warning: indirect lcall without `*'
    D:/usr/tmp/cccwRkzy.s:399: Warning: indirect lcall without `*'
    D:/usr/tmp/cccwRkzy.s:411: Warning: indirect lcall without `*'
    D:/usr/tmp/cccwRkzy.s:425: Warning: indirect lcall without `*'
    D:/usr/tmp/cccwRkzy.s:434: Warning: indirect lcall without `*'
    D:/usr/tmp/cccwRkzy.s:444: Warning: indirect ljmp without `*'
    D:/usr/tmp/cccwRkzy.s:548: Warning: indirect ljmp without `*'

This needed real changes in the lcall/ljmp directives (add a `*'
before the argument of lcall/ljmp).  V2.04 already has a solution for
that.

Anyway, it was still no cigar after these changes: the linker still
complained about undefined reference to `_forced_test'.  I needed to
rename forced_test into __dj_forced_test and make it non-static (like
v2.04 did) to overcome this weird problem.  After that, GDB indeed
started working correctly with watchpoints on my Windows XP SP2
machine, whereas previously it would get SIGTRAP for the second
watchpoint, as you described.

So I guess your patch is good and should be committed to the DJGPP
CVS, thanks.  I CC djgpp-workers for the record.  Here for the
reference is the full patch I needed for the v2.03 sources to get
dbgcom.c to compile and fix the watchpoints on Windows:

--- dbgcom.c~	2009-10-24 15:58:17.281250000 +0200
+++ dbgcom.c	2009-11-07 14:56:44.696375000 +0200
@@ -99,18 +99,18 @@
   int i;
   if ((__dpmi_get_coprocessor_status() & FPU_PRESENT) == 0)
     return;
-  asm ("movb	$0x0b, %%al
-	outb	%%al, $0xa0
-	inb	$0xa0, %%al
-	testb	$0x20, %%al
-	jz	1f
-	xorb	%%al, %%al
-	outb	%%al, $0xf0
-	movb	$0x20, %%al
-	outb	%%al, $0xa0
-	outb	%%al, $0x20
-1:
-	fnsave	%0
+  asm ("movb	$0x0b, %%al\n\
+	outb	%%al, $0xa0\n\
+	inb	$0xa0, %%al\n\
+	testb	$0x20, %%al\n\
+	jz	1f\n\
+	xorb	%%al, %%al\n\
+	outb	%%al, $0xf0\n\
+	movb	$0x20, %%al\n\
+	outb	%%al, $0xa0\n\
+	outb	%%al, $0x20\n\
+1:\n\
+	fnsave	%0\n\
 	fwait"
        : "=m" (npx)
        : /* No input */
@@ -226,15 +226,11 @@
 
 	asm volatile(						       "\n\
 	    movl   %1,%%ebx						\n\
-	    movw   $0x0b02,%%ax						\n\
-	    int    $0x31						\n\
-	    jnc    2f							\n\
-	    xorl   %%eax,%%eax                                          \n\
-2:	    andl   $1,%%eax						\n\
-	    pushl  %%eax						\n\
 	    movw   $0x0b01,%%ax						\n\
 	    int    $0x31						\n\
-	    popl   %0							\n\
+	    jc    1f							\n\
+	    xorl   %%eax,%%eax                                          \n\
+1:	    movl   %%eax,%0						\n\
 	    "
 	    : "=g" (state)			/* outputs */
 	    : "g"  (handle)			/* inputs */
@@ -243,6 +239,26 @@
 	return state;
 }
 
+static int _DPMIhitBreak(int handle)
+{
+	unsigned state;
+
+	asm volatile(						       "\n\
+	    movl   %1,%%ebx						\n\
+ 	    movw   $0x0b02,%%ax						\n\
+ 	    int    $0x31						\n\
+ 	    jnc    2f							\n\
+	    movl   $0xffffffff,%%eax					\n\
+ 2:	    andl   $1,%%eax						\n\
+	    movl   %%eax,%0						\n\
+ 	    "
+ 	    : "=g" (state)			/* outputs */
+ 	    : "g"  (handle)			/* inputs */
+	    : "ax", "bx"			/* regs used */
+	);
+	return state;
+}
+
 /* Can't be static because called in asm below; -O3 inlines if static */
 void _set_break_DPMI(void);
 void _set_break_DPMI(void)
@@ -280,7 +296,7 @@
 void _clear_break_DPMI(void);
 void _clear_break_DPMI(void)
 {
-  int i,bt;
+  int i,bt,res;
 
   if(!nset) {
     edi.dr[6] = 0;
@@ -291,10 +307,25 @@
   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 */
+      {
+        res = _DPMIhitBreak(breakhandle[i]);  /* Set low bit if active */
+	if (res == 1)
+	  bt |= 1;
+	else if (res == -1)
+	  printf("Error checking DPMI hit status\n");
+      }
   }
 
   edi.dr[6] = bt;
+  for(i=3;i>=0;i--) {
+    bt = bt << 1;                             /* Shift for next bit */
+    if(breakhandle[i] != -1)
+      {
+        res = _DPMIcancelBreak(breakhandle[i]);  
+	if (res) 
+	  printf("Error resetting DPMI Debug Watchpoint\n");
+      }
+  }
 }
 
 static __dpmi_paddr old_i31,old_i21,user_i31,user_i21;
@@ -351,7 +382,7 @@
   __djgpp_app_DS = app_ds;
 }
 
-/* The instructions in forced_test[] MUST MATCH the expansion of:
+/* The instructions in __dj_forced_test[] MUST MATCH the expansion of:
 
    EXCEPTION_ENTRY($13)
    EXCEPTION_ENTRY($14)
@@ -373,7 +404,7 @@
    the time.  So most DPMI servers don't support it, and our code will
    never be called if we tie it to exception 17.  In contrast, exception
    13 is GPF, and *any* DPMI server will support that!  */
-static unsigned char forced_test[] = {
+unsigned char __dj_forced_test[] = {
   0x6a,0x0d,			/* pushl $0x0d */
   0xeb,0x10,			/* jmp relative +0x10 */
   0x6a,0x0e,			/* pushl $0x0e */
@@ -389,7 +420,7 @@
   0x2e,0x80,0x3d		/* (beginning of) %cs:cmpb $0,forced */
 }; /* four next bytes contain the address of the `forced' variable */
 
-static int forced_test_size = sizeof (forced_test);
+static int __dj_forced_test_size = sizeof (__dj_forced_test);
 
 static int forced_address_known = 0;
 static unsigned int forced_address = 0;
@@ -426,8 +457,8 @@
         cld                                                             \n\
         movw  %cx,%es                                                   \n\
         movl  %edx,%edi                                                 \n\
-        movl  $_forced_test,%esi                                        \n\
-        movl  _forced_test_size,%ecx                                    \n\
+        movl  $___dj_forced_test,%esi                                   \n\
+        movl  ___dj_forced_test_size,%ecx                               \n\
         repe                                                            \n\
         cmpsb                                                           \n\
         jne   _forced_not_found                                         \n\
@@ -462,7 +493,7 @@
         pushl   %eax                                                    \n\
 	pushf								\n\
 	.byte	0x2e							\n\
-	lcall	_old_i31						\n\
+	lcall	*_old_i31						\n\
         popl   %eax                                                     \n\
 	jc	Lc31_set_flags_and_iret					\n\
         pushl   %eax                                                    \n\
@@ -491,7 +522,7 @@
         pop   %es                                                       \n\
         popl  %eax                                                      \n\
         .byte 0x2e                                                      \n\
-        ljmp _old_i31                                                   \n\
+        ljmp *_old_i31                                                   \n\
         ret                                                             \n"
 ); 
 
@@ -566,7 +597,7 @@
 	movw	$0x0003,%ax						\n\
 	pushf								\n\
 	.byte	0x2e							\n\
-	lcall	_old_i31						\n\
+	lcall	*_old_i31						\n\
 	movw	%ax,%bx							\n\
 	popl	%eax							\n\
 	pushl	%eax							\n\
@@ -695,7 +726,7 @@
 	je	Lc31_resize_mem						\n\
 L_jmp_to_old_i31:                                                       \n\
         .byte	0x2e							\n\
-	ljmp	_old_i31						\n\
+	ljmp	*_old_i31						\n\
 Lc31_set_flags_and_iret:                                                \n\
         pushl	%eax				                        \n\
 	pushf								\n\
@@ -736,7 +767,7 @@
 	jne	L_jmp_to_old_i31					\n\
 	pushf								\n\
 	.byte	0x2e							\n\
-	lcall	_old_i31						\n\
+	lcall	*_old_i31						\n\
 	call	___djgpp_save_interrupt_regs				\n\
 	call	__clear_break_DPMI					\n\
 	call	__set_break_DPMI					\n\
@@ -757,7 +788,7 @@
 Lc31_alloc_mem:								\n\
 	pushf								\n\
 	.byte	0x2e							\n\
-	lcall	_old_i31						\n\
+	lcall	*_old_i31						\n\
 	jc	Lc31_set_flags_and_iret					\n\
 	pushf								\n\
 	pushl	%edx							\n\
@@ -775,7 +806,7 @@
 	pushw	%di							\n\
 	pushf								\n\
 	.byte	0x2e							\n\
-	lcall	_old_i31						\n\
+	lcall	*_old_i31						\n\
 	jc	Lc31_resize_mem_error					\n\
 	popl	%eax							\n\
 	push	%edx							\n\
@@ -789,7 +820,7 @@
 	pushw	%di							\n\
 	pushf								\n\
 	.byte	0x2e							\n\
-	lcall	_old_i31						\n\
+	lcall	*_old_i31						\n\
 	jnc	Lc31_resize_mem_ok					\n\
 Lc31_resize_mem_error:							\n\
 	addl	$4,%esp							\n\
@@ -807,7 +838,7 @@
 	pushl	%ecx							\n\
 	pushf								\n\
 	.byte	0x2e							\n\
-	lcall	_old_i31						\n\
+	lcall	*_old_i31						\n\
 	popl	%ecx							\n\
 	jc	Lc31_set_flags_and_iret					\n\
 	call	_add_descriptors					\n\
@@ -817,7 +848,7 @@
 	pushl	%ebx							\n\
 	pushf								\n\
 	.byte	0x2e							\n\
-	lcall	_old_i31						\n\
+	lcall	*_old_i31						\n\
 	popl	%eax							\n\
 	jc	Lc31_set_flags_and_iret					\n\
 	push	%edx							\n\
@@ -829,7 +860,7 @@
 Lc31_create_alias_descriptor:						\n\
 	pushf								\n\
 	.byte	0x2e							\n\
-	lcall	_old_i31						\n\
+	lcall	*_old_i31						\n\
 	jc	Lc31_set_flags_and_iret					\n\
 	pushl	%eax							\n\
 	push	%edx							\n\
@@ -843,7 +874,7 @@
 Lc31_allocate_dos_memory:						\n\
 	pushf								\n\
 	.byte	0x2e							\n\
-	lcall	_old_i31						\n\
+	lcall	*_old_i31						\n\
 	jc	Lc31_set_flags_and_iret					\n\
 	pushl	%eax							\n\
 	xorl	%eax,%eax						\n\
@@ -855,7 +886,7 @@
 	pushl	%edx							\n\
 	pushf								\n\
 	.byte	0x2e							\n\
-	lcall	_old_i31						\n\
+	lcall	*_old_i31						\n\
 	popl	%eax							\n\
 	jc	Lc31_set_flags_and_iret					\n\
 	xorw	%dx,%dx							\n\
@@ -869,7 +900,7 @@
         pushl  %edx                                                     \n\
         pushf                                                           \n\
         .byte  0x2e                                                     \n\
-        lcall   _old_i31                                                \n\
+        lcall   *_old_i31                                                \n\
         popl   %edx                                                     \n\
         popl   %ecx                                                     \n\
         popl   %ebx                                                     \n\
@@ -878,7 +909,7 @@
         call   _change_exception_handler                                \n\
         pushf                                                           \n\
         .byte  0x2e                                                     \n\
-        lcall   _old_i31                                                \n\
+        lcall   *_old_i31                                                \n\
         jmp Lc31_set_flags_and_iret                                     \n\
 	.balign  16,,7							\n\
         .globl  _dbgcom_hook_i21                                        \n\
@@ -888,7 +919,7 @@
 	je	Lc21							\n\
 Lc21_jmp_to_old:                                                        \n\
         .byte	0x2e							\n\
-	ljmp	_old_i21						\n\
+	ljmp	*_old_i21						\n\
 Lc21:	push	%eax							\n\
 	movl	8(%esp),%eax						\n\
 	cs								\n\
@@ -915,79 +946,79 @@
 	);
 
 /* complete code to return from an exception */
-asm (  ".text
-       .balign 16,,7
-       .globl    _dbgcom_exception_return_to_debuggee
-_dbgcom_exception_return_to_debuggee:       /* remove errorcode from stack */
-       /* we must also switch stack back !! */
-       /* relative to ebp */
-       /* 0 previous ebp */
-       /* 4 exception number */
-       /* 8 return eip */
-       /* 12 return cs */
-       /* 16 return eflags */
-       /* 20 return esp  */
-       /* 24 return ss  */
-       /* -4 stored ds */
-       /* -8 stored eax */
-       /* -12 stored esi */
-       pushl  %ebp
-       movl   %esp,%ebp
-       pushl  %ds
-       pushl  %eax
-       pushl  %esi
-       movl   %cs:___djgpp_our_DS,%eax
-       movw   %ax,%ds
-       addl   $32,_cur_pos
-       decl    _child_exception_level
-       movl   24(%ebp),%eax
-       movw   %ax,%ds
-       movl   20(%ebp),%esi
-       /* ds:esi points now to app stack */
-       subl  $28,%esi
-       movl  %esi,20(%ebp)
-       /* eflags on app stack */
-       movl  16(%ebp),%eax
-       movl  %eax,%ds:24(%esi)
-       /* cs on app stack */
-       movl  12(%ebp),%eax
-       movl  %eax,%ds:20(%esi)
-       /* eip on app stack */
-       movl  8(%ebp),%eax
-       movl  %eax,%ds:16(%esi)
-       /* esi on app stack */
-       movl  -12(%ebp),%eax
-       movl  %eax,%ds:12(%esi)
-       /* eax on app stack */
-       movl  -8(%ebp),%eax
-       movl  %eax,%ds:8(%esi)
-       /* ds on app_stack */
-       movl  -4(%ebp),%eax
-       movl  %eax,%ds:4(%esi)
-       /* ebp on app_stack */
-       movl  (%ebp),%eax
-       movl  %eax,%ds:(%esi)
-       /* switch stack */
-       movl  24(%ebp),%eax
-       movw  %ax,%ss
-       movl  %esi,%esp
-       /* now on app stack */
-       popl  %ebp
-       popl  %eax
-       movw  %ax,%ds
-       popl  %eax
-       popl  %esi
-       iret
+asm (  ".text\n\
+       .balign 16,,7\n\
+       .globl    _dbgcom_exception_return_to_debuggee\n\
+_dbgcom_exception_return_to_debuggee:       /* remove errorcode from stack */\n\
+       /* we must also switch stack back !! */\n\
+       /* relative to ebp */\n\
+       /* 0 previous ebp */\n\
+       /* 4 exception number */\n\
+       /* 8 return eip */\n\
+       /* 12 return cs */\n\
+       /* 16 return eflags */\n\
+       /* 20 return esp  */\n\
+       /* 24 return ss  */\n\
+       /* -4 stored ds */\n\
+       /* -8 stored eax */\n\
+       /* -12 stored esi */\n\
+       pushl  %ebp\n\
+       movl   %esp,%ebp\n\
+       pushl  %ds\n\
+       pushl  %eax\n\
+       pushl  %esi\n\
+       movl   %cs:___djgpp_our_DS,%eax\n\
+       movw   %ax,%ds\n\
+       addl   $32,_cur_pos\n\
+       decl    _child_exception_level\n\
+       movl   24(%ebp),%eax\n\
+       movw   %ax,%ds\n\
+       movl   20(%ebp),%esi\n\
+       /* ds:esi points now to app stack */\n\
+       subl  $28,%esi\n\
+       movl  %esi,20(%ebp)\n\
+       /* eflags on app stack */\n\
+       movl  16(%ebp),%eax\n\
+       movl  %eax,%ds:24(%esi)\n\
+       /* cs on app stack */\n\
+       movl  12(%ebp),%eax\n\
+       movl  %eax,%ds:20(%esi)\n\
+       /* eip on app stack */\n\
+       movl  8(%ebp),%eax\n\
+       movl  %eax,%ds:16(%esi)\n\
+       /* esi on app stack */\n\
+       movl  -12(%ebp),%eax\n\
+       movl  %eax,%ds:12(%esi)\n\
+       /* eax on app stack */\n\
+       movl  -8(%ebp),%eax\n\
+       movl  %eax,%ds:8(%esi)\n\
+       /* ds on app_stack */\n\
+       movl  -4(%ebp),%eax\n\
+       movl  %eax,%ds:4(%esi)\n\
+       /* ebp on app_stack */\n\
+       movl  (%ebp),%eax\n\
+       movl  %eax,%ds:(%esi)\n\
+       /* switch stack */\n\
+       movl  24(%ebp),%eax\n\
+       movw  %ax,%ss\n\
+       movl  %esi,%esp\n\
+       /* now on app stack */\n\
+       popl  %ebp\n\
+       popl  %eax\n\
+       movw  %ax,%ds\n\
+       popl  %eax\n\
+       popl  %esi\n\
+       iret\n\
     ");
 
 static jmp_buf here;
 
 /* simple code to return from an exception */
 /* don't forget to increment cur_pos       */
-asm (  ".text
-       .balign 16,,7
-       .globl    _dbgcom_exception_return_to_here
-_dbgcom_exception_return_to_here:       /* remove errorcode from stack */
+asm (  ".text\n\
+       .balign 16,,7\n\
+       .globl    _dbgcom_exception_return_to_here\n\
+_dbgcom_exception_return_to_here:       /* remove errorcode from stack */\n\
         movl    %cs:___djgpp_our_DS,%eax                                \n\
         movw    %ax,%ds                                                 \n\
         movw    %ax,%es                                                 \n\
@@ -1003,10 +1034,10 @@
 	movw	$0x7021,0xb0f00						\n\ */
 
 /* do not set limit of ds selector two times */
-asm (".text
-        .global ___dbgcom_kbd_hdlr
-___dbgcom_kbd_hdlr:
-        ljmp    %cs:___djgpp_old_kbd");
+asm (".text\n\
+        .global ___dbgcom_kbd_hdlr\n\
+___dbgcom_kbd_hdlr:\n\
+        ljmp    *%cs:___djgpp_old_kbd");
         
     
     
@@ -1100,8 +1131,8 @@
 {
   unsigned int ds_size;
   int signum =  __djgpp_exception_state->__signum;
-  asm ("movl _app_ds,%%eax
-        lsl  %%eax,%%eax
+  asm ("movl _app_ds,%%eax\n\
+        lsl  %%eax,%%eax\n\
         movl %%eax,%0"
         : "=g" (ds_size) );
 
@@ -1317,15 +1348,15 @@
   char read_allowed = 0;
   char write_allowed = 0;
   
-  asm("
-      movw  %2,%%ax
-      verr  %%ax
-      jnz   .Ldoes_not_has_read_right
-      movb  $1,%0
-.Ldoes_not_has_read_right:
-      verw  %%ax
-      jnz   .Ldoes_not_has_write_right
-      movb  $1,%1
+  asm("\n\
+      movw  %2,%%ax\n\
+      verr  %%ax\n\
+      jnz   .Ldoes_not_has_read_right\n\
+      movb  $1,%0\n\
+.Ldoes_not_has_read_right:\n\
+      verw  %%ax\n\
+      jnz   .Ldoes_not_has_write_right\n\
+      movb  $1,%1\n\
 .Ldoes_not_has_write_right: "
      : "=g" (read_allowed), "=g" (write_allowed)
      : "g" (sel)
@@ -1353,7 +1384,7 @@
 int read_sel_addr(unsigned child_addr, void *buf, unsigned len, unsigned sel)
 {
   /* first clear memory */
-  memcpy(buf,0,len);
+  memset(buf,0,len);
   if (invalid_sel_addr(sel, child_addr, len, 0))
     return 1;
   movedata(sel, child_addr, my_ds, (int)buf, len);
@@ -1494,7 +1525,7 @@
   /* Invalidate the info about the `forced' variable.  */
   forced_address_known = 0;
   forced_address = 0;
-  forced_test_size = sizeof (forced_test); /* pacify the compiler */
+  __dj_forced_test_size = sizeof (__dj_forced_test); /* pacify the compiler */
   /* Set the flag, that the user interrupt vectors are no longer valid */
   user_int_set = 0;
 
@@ -1617,7 +1648,7 @@
 static int dbg_fsext(__FSEXT_Fnumber _function_number,
                       int *_rv, va_list _args)
 {
-  int attrib,oflag,retval = 0,handle;
+  int attrib,oflag,retval = 0,handle,old_handle;
   const char *filename;
   /* We are called from this function */
   if (in_dbg_fsext) return 0;
@@ -1669,6 +1700,29 @@
         __FSEXT_set_function(handle,NULL);
       }
       break;
+    case __FSEXT_dup:
+      old_handle = va_arg(_args,int);
+      handle = va_arg(_args,int);
+#ifdef DEBUG_DBGCOM_FILES
+      fprintf(stderr,"dup(%d) => %d\n",old_handle,handle);
+#endif
+      if (handle >= 0)
+      {
+        handles[handle] = old_handle;
+      }
+      return 0;
+    case __FSEXT_dup2:
+      old_handle = va_arg(_args,int);
+      handle = va_arg(_args,int);
+      retval = va_arg(_args,int);
+#ifdef DEBUG_DBGCOM_FILES
+      fprintf(stderr,"dup2(%d,%d) => %d\n",old_handle,handle,retval);
+#endif
+      if (retval >= 0)
+      {
+        handles[retval] = old_handle;
+      }
+      return 0;
   }
   *_rv = retval;
   return 1;

- Raw text -


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