[elinks-users] crash on 64bit archs

Karel Zak kzak at redhat.com
Mon May 9 03:19:48 PDT 2005

On Sat, 2005-05-07 at 01:58 +0200, Jonas Fonseca wrote:
> Karel Zak <kzak at redhat.com> wrote Thu, May 05, 2005:
> > 
> > It looks that Elinks is useless on 64bit archs. I tested 0.10.3 and
> > 0.10.5 on ppc and ia64.
> It could be some code in the URI comparing or URI parsing which tries to
> be too smart and 32-bit friendly. I will try to find my way to a 64-bit
> system at school.
> In the meantime, maybe you could give us a real backtrace dump from gdb
> instead of the less readable crash backtrace?


(Note: there's gcc 4.0 in FC4)

Comment #7
>From Jakub
on 2005-05-09
05:56 EST:


Generally, if something works with -O0 and does not with -O2, it is more often
an application bug than GCC bug.  Only when you debug it and prove it is indeed
a GCC bug it should be reassigned to GCC.

Particularly in this case, the bug goes away with -O2 -fno-strict-aliasing,
and there are 94 places where GCC warns about aliasing problems:

grep warning.*type-punned elinks.log | sort -u | wc -l

Plus there are several places where the code violates those but GCC does not
warn. Say in find_in_cache, all the lists.h macros used there are buggy.

And error.h even shows that the authors see the problems, just for unknown
reason can't admit it is their bug and not a compiler bug:

/* This function does nothing, except making compiler not to optimize certains
 * spots of code --- this is useful when that particular optimization is buggy.
 * So we are just workarounding buggy compilers. */
/* This function should be always used only in context of compiler version
 * specific macros. */
void do_not_optimize_here(void *x);

#if defined(__GNUC__) && __GNUC__ == 2 && __GNUC_MINOR__ <= 7
#define do_not_optimize_here_gcc_2_7(x) do_not_optimize_here(x)
#define do_not_optimize_here_gcc_2_7(x)

#if defined(__GNUC__) && __GNUC__ == 3
#define do_not_optimize_here_gcc_3_x(x) do_not_optimize_here(x)
#define do_not_optimize_here_gcc_3_x(x)

#if defined(__GNUC__) && __GNUC__ == 3 && __GNUC_MINOR__ == 3
#define do_not_optimize_here_gcc_3_3(x) do_not_optimize_here(x)
#define do_not_optimize_here_gcc_3_3(x)

The lists implementation is broken by design, it just can't work that way.
You can't access the same object through aliasing incompatible types.
But lists.h is doing that a lot, it sometimes accesses next/prev as void *,
sometimes as struct cache_entry *, etc.

Cleanest fix IMHO would be to use a void *next; void *prev; structure and
put that structure as first field into the various structures that are chained
into lists, say:

struct cache_entry
  struct list_head_elinks head;

and then the macro use cached->head.prev, etc.  What will also work
is just make the prev/next pointers void *, but directly in the structure, say

struct cache_entry
  void *next; void *prev;

and have

struct list_head_elinks
  void *next; void *prev;

But writing/reading through void ** pointer and then writing/reading through
struct cache_entry ** pointer is violation of ISO C99 6.5 (6,7).

Karel Zak <kzak at redhat.com>

More information about the elinks-users mailing list