public inbox for gcc-prs@sourceware.org
help / color / mirror / Atom feed
* c/5290: Miscompilation of GDB on i386
@ 2002-01-06 7:16 Mark Kettenis
0 siblings, 0 replies; 2+ messages in thread
From: Mark Kettenis @ 2002-01-06 7:16 UTC (permalink / raw)
To: gcc-gnats
>Number: 5290
>Category: c
>Synopsis: Miscompilation of GDB on i386
>Confidential: no
>Severity: serious
>Priority: medium
>Responsible: unassigned
>State: open
>Class: wrong-code
>Submitter-Id: net
>Arrival-Date: Sun Jan 06 07:16:00 PST 2002
>Closed-Date:
>Last-Modified:
>Originator: Mark Kettenis
>Release: 3.1 20020105 (experimental)
>Organization:
>Environment:
System: FreeBSD elgar.kettenis.dyndns.org 4.4-RELEASE FreeBSD 4.4-RELEASE #3: Thu Jan 3 09:44:07 CET 2002 kettenis@elgar.local:/usr/obj/usr/src/sys/ELGAR i386
host: i386-unknown-freebsd4.4
build: i386-unknown-freebsd4.4
target: i386-unknown-freebsd4.4
configured with: ../../src/gcc/configure --prefix=/home/kettenis/opt/gcc
>Description:
Running "gcc -g -O2 -S" on the code below produces wrong-code. The
function partial_memory_read() is called with a bogus value for its
second argument. Apparently the variable bufptr, which according to
the debug info lives in %ebx, isn't initialized correctly. The
following fragment shows that indeed %ebx is passed as the second
argument:
.loc 1 123 0
leal -16(%ebp), %eax
pushl %eax
imull %edi, %esi
pushl %esi
pushl %ebx
pushl 8(%ebp)
call partial_memory_read
I also recognize the addition of "bufsize * width" from line 119:
bufptr = buffer + bufsize * width;
in the generated assembly (a few lines up from the previous fragment).
.loc 1 119 0
movl -40(%ebp), %eax
imull %edi, %eax
addl %eax, %ebx
However, the code that initializes %ebx (presumably with the contents
of buffer which is allocated by xrealloc(), which lives at -32(%ebp))
is missing.
The problem disappears when compiling with -O1. I first noted this
bug around december 28, but it may have been present a long time
before, since it's been a while since I last tried to compile GDB with
mainline GCC.
>How-To-Repeat:
Run "gcc -g -O2 -S" on the following preprocessor output (generated
from a trimmed down GDB source file, so it's GPL'ed):
# 1 "valprint.c"
# 1 "<built-in>"
# 1 "<command line>"
# 1 "valprint.c"
typedef unsigned int size_t;
typedef long CORE_ADDR;
typedef unsigned long long ULONGEST;
typedef void (make_cleanup_ftype) (void *);
struct cleanup;
struct ui_file;
extern void discard_cleanups (struct cleanup *);
extern ULONGEST extract_unsigned_integer (void *, int);
extern void do_cleanups (struct cleanup *);
extern void fprintf_filtered (struct ui_file *, const char *, ...);
extern void fputs_filtered (const char *, struct ui_file *);
extern void gdb_flush (struct ui_file *);
extern struct cleanup *make_cleanup (make_cleanup_ftype *, void *);
extern void null_cleanup (void *);
extern void print_address_numeric (CORE_ADDR, int, struct ui_file *);
extern void quit (void);
extern char *safe_strerror (int);
extern int target_read_memory (CORE_ADDR memaddr, char *myaddr, int len);
extern void xfree (void *);
extern void *xmalloc (size_t);
extern void *xrealloc (void *, size_t);
extern int addressprint;
extern void (*interactive_hook) (void);
unsigned int print_max;
extern int quit_flag;
static int
partial_memory_read (CORE_ADDR memaddr, char *myaddr, int len, int *errnoptr)
{
return 0;
}
int
val_print_string (CORE_ADDR addr, int len, int width, struct ui_file *stream)
{
int force_ellipsis = 0;
int errcode;
unsigned int fetchlimit;
unsigned int nfetch;
unsigned int chunksize;
char *buffer = 0;
char *bufptr;
char *limit;
struct cleanup *old_chain = 0;
int found_nul;
# 70 "valprint.c"
fetchlimit = (len == -1 ? print_max : ((len) < (print_max) ? (len) : (print_max)));
# 81 "valprint.c"
chunksize = (len == -1 ? ((8) < (fetchlimit) ? (8) : (fetchlimit)) : fetchlimit);
found_nul = 0;
old_chain = make_cleanup (null_cleanup, 0);
# 103 "valprint.c"
if (len == -1)
{
unsigned long bufsize = 0;
do
{
nfetch = ((chunksize) < (fetchlimit - bufsize) ? (chunksize) : (fetchlimit - bufsize));
if (buffer == 0)
buffer = (char *) xmalloc (nfetch * width);
else
{
discard_cleanups (old_chain);
buffer = (char *) xrealloc (buffer, (nfetch + bufsize) * width);
}
old_chain = make_cleanup (xfree, buffer);
bufptr = buffer + bufsize * width;
bufsize += nfetch;
nfetch = partial_memory_read (addr, bufptr, nfetch * width, &errcode)
/ width;
limit = bufptr + nfetch * width;
while (bufptr < limit)
{
unsigned long c;
c = extract_unsigned_integer (bufptr, width);
addr += width;
bufptr += width;
if (c == 0)
{
errcode = 0;
found_nul = 1;
break;
}
}
}
while (errcode == 0
&& bufptr - buffer < fetchlimit * width
&& !found_nul);
}
else
{
buffer = bufptr = 0;
errcode = 0;
}
# 219 "valprint.c"
return ((bufptr - buffer) / width);
}
>Fix:
>Release-Note:
>Audit-Trail:
>Unformatted:
^ permalink raw reply [flat|nested] 2+ messages in thread
* Re: c/5290: Miscompilation of GDB on i386
@ 2002-01-09 21:16 DJ Delorie
0 siblings, 0 replies; 2+ messages in thread
From: DJ Delorie @ 2002-01-09 21:16 UTC (permalink / raw)
To: nobody; +Cc: gcc-prs
The following reply was made to PR c/5290; it has been noted by GNATS.
From: DJ Delorie <dj@redhat.com>
To: kettenis@gnu.org
Cc: gcc-gnats@gcc.gnu.org, gcc-prs@gcc.gnu.org, gcc-bugs@gcc.gnu.org
Subject: Re: c/5290: Miscompilation of GDB on i386
Date: Thu, 10 Jan 2002 00:06:35 -0500
Here's a shorter testcase, also derived from gdb:
int print_max;
int null_cleanup;
int addressprint;
void xfree();
int
val_print_string (int addr, int len, int width, char *stream)
{
int errcode;
unsigned int fetchlimit = max();
unsigned int nfetch;
char *buffer = 0;
char *bufptr;
int found_nul;
unsigned long bufsize = 0;
do
{
nfetch = min ();
if (buffer == 0)
buffer = (char *) xmalloc (nfetch * width);
else
buffer = (char *) xrealloc (buffer, (nfetch + bufsize) * width);
bufptr = buffer + bufsize * width;
bufsize += nfetch;
nfetch = partial_memory_read (addr, bufptr, nfetch * width, &errcode);
}
while (bufptr - buffer < fetchlimit * width
&& !found_nul);
}
The bug is in global alloc and reload. In valprint.c.21.lreg we see:
(call_insn 96 95 98 (set (reg:SI 0 eax)
(call (mem:QI (symbol_ref:SI ("xrealloc")) [0])
(const_int 8 [0x8]))) 649 {*call_value_0} (nil)
(nil)
(nil))
(insn 98 96 100 (set (reg/v/f:SI 67)
(reg:SI 0 eax)) 45 {*movsi_1} (insn_list 96 (nil))
(expr_list:REG_DEAD (reg:SI 0 eax)
(nil)))
;; End of basic block 3, registers live:
6 [bp] 7 [sp] 16 [] 20 [frame] 59 61 65 66 67 69 70 83 84
;; Start of basic block 4, registers live: 6 [bp] 7 [sp] 16 [] 20 [frame] 59 61 65 66 67 69 70 83 84
(code_label 100 98 172 6 "" "" [1 uses])
(note 172 100 102 [bb 4] NOTE_INSN_BASIC_BLOCK)
(insn 102 172 104 (parallel[
(set (reg/v:SI 70)
(mult:SI (reg/v:SI 70)
(reg/v:SI 61)))
(clobber (reg:CC 17 flags))
] ) 250 {*mulsi3_1} (nil)
(expr_list:REG_UNUSED (reg:CC 17 flags)
(nil)))
(insn 104 102 107 (parallel[
(set (reg/v/f:SI 68)
(plus:SI (reg/v/f:SI 67)
(reg/v:SI 70)))
(clobber (reg:CC 17 flags))
] ) 207 {*addsi_1} (insn_list 102 (nil))
(expr_list:REG_DEAD (reg/v:SI 70)
(expr_list:REG_UNUSED (reg:CC 17 flags)
(nil))))
But in valprint.c.22.greg we see:
Reloads for insn # 98
Reload 0: reload_out (SI) = (reg/v/f:SI 67)
NO_REGS, RELOAD_FOR_OUTPUT (opnum = 0), optional
reload_out_reg: (reg/v/f:SI 67)
Reloads for insn # 102
Reload 0: reload_in (SI) = (reg/v:SI 70)
reload_out (SI) = (reg/v:SI 70)
INDEX_REGS, RELOAD_OTHER (opnum = 0)
reload_in_reg: (reg/v:SI 70)
reload_out_reg: (reg/v:SI 70)
reload_reg_rtx: (reg:SI 0 eax)
Reload 1: reload_in (SI) = (reg/v:SI 61)
GENERAL_REGS, RELOAD_FOR_INPUT (opnum = 2), optional
reload_in_reg: (reg/v:SI 61)
Reloads for insn # 104
Reload 0: reload_in (SI) = (reg/v/f:SI 67)
reload_out (SI) = (reg/v/f:SI 3 ebx [68])
GENERAL_REGS, RELOAD_OTHER (opnum = 0)
reload_in_reg: (reg/v/f:SI 67)
reload_out_reg: (reg/v/f:SI 3 ebx [68])
reload_reg_rtx: (reg/v/f:SI 3 ebx [68])
Reload 1: reload_in (SI) = (reg/v:SI 70)
GENERAL_REGS, RELOAD_FOR_INPUT (opnum = 2), optional
reload_in_reg: (reg/v:SI 70)
reload_reg_rtx: (reg:SI 0 eax)
(call_insn 96 95 98 (set (reg:SI 0 eax)
(call (mem:QI (symbol_ref:SI ("xrealloc")) [0])
(const_int 8 [0x8]))) 649 {*call_value_0} (nil)
(nil)
(nil))
(insn 98 96 100 (set (mem:SI (plus:SI (reg/f:SI 6 ebp)
(const_int -24 [0xffffffffffffffe8])) [6])
(reg:SI 0 eax)) 45 {*movsi_1} (insn_list 96 (nil))
(nil))
;; End of basic block 3, registers live:
6 [bp] 7 [sp] 16 [] 20 [frame] 59 61 65 66 67 69 70 83 84
;; Start of basic block 4, registers live: 6 [bp] 7 [sp] 59 61 65 66 67 69 70 83 84
(code_label 100 98 172 6 "" "" [1 uses])
(note 172 100 219 [bb 4] NOTE_INSN_BASIC_BLOCK)
(insn 219 172 102 (set (reg:SI 0 eax)
(mem:SI (plus:SI (reg/f:SI 6 ebp)
(const_int -32 [0xffffffffffffffe0])) [8])) 45 {*movsi_1} (nil)
(nil))
(insn 102 219 104 (parallel[
(set (reg:SI 0 eax)
(mult:SI (reg:SI 0 eax)
(mem/f:SI (plus:SI (reg/f:SI 6 ebp)
(const_int 16 [0x10])) [1 width+0 S4 A32])))
(clobber (reg:CC 17 flags))
] ) 250 {*mulsi3_1} (nil)
(nil))
(insn 104 102 107 (parallel[
(set (reg/v/f:SI 3 ebx [68])
(plus:SI (reg/v/f:SI 3 ebx [68])
(reg:SI 0 eax)))
(clobber (reg:CC 17 flags))
] ) 207 {*addsi_1} (insn_list 102 (nil))
(nil))
^ permalink raw reply [flat|nested] 2+ messages in thread
end of thread, other threads:[~2002-01-10 5:16 UTC | newest]
Thread overview: 2+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2002-01-06 7:16 c/5290: Miscompilation of GDB on i386 Mark Kettenis
2002-01-09 21:16 DJ Delorie
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).