[Bug middle-end/84184] gcc generates wrong relocations with negative offsets in struct arrays

2018-08-20 Thread ebotcazou at gcc dot gnu.org
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=84184

Eric Botcazou  changed:

   What|Removed |Added

 Status|NEW |RESOLVED
 Resolution|--- |DUPLICATE

--- Comment #13 from Eric Botcazou  ---
.

*** This bug has been marked as a duplicate of bug 86984 ***

[Bug middle-end/84184] gcc generates wrong relocations with negative offsets in struct arrays

2018-08-04 Thread skvadrik at gmail dot com
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=84184

Ulya  changed:

   What|Removed |Added

 CC||skvadrik at gmail dot com

--- Comment #12 from Ulya  ---
(In reply to Eric Botcazou from comment #11)
> > Why those are handled differently? First looks like it works, second does
> > not. It was my main signal to file a bug against gcc as asymmetry looked
> > fishy.
> 
> Because the problematic bitfield path is only used for fields in structures,
> i.e. misaligned integers are handled by another, simpler path.

More details on the problematic path for this simple example:

extern char __some_table[] __attribute__((visibility("hidden")));   
struct s { long v; };   
long end(void) { return ((struct s *)__some_table)[-1].v; } 

1. The problematic path makes an illegal signed-to-unsigned integer conversion
in expand_expr_real_1 (expr.c) when passing the signed 'bitnum' variable, with
value -64, as the 3rd param of extract_bit_field (expmed.c), with value
18446744073709551552.

2. The conversion itself doesn't spoil the value (meaning that the bits of
'bitnum' are not changed), and the value is passed on to extract_bit_field_1,
extract_integral_bit_field and extract_fixed_bit_field unharmed.

3. Finally, 'bitnum' is passed as the 5th param 'bitpos' to
extract_split_bit_field, where it gets involved in unsigned integer arithmetics
and bad things start to happen:


static rtx  
extract_split_bit_field (rtx op0, opt_scalar_int_mode op0_mode, 
 unsigned HOST_WIDE_INT bitsize,
 unsigned HOST_WIDE_INT bitpos, int unsignedp,  
 bool reverse)  
{   
  unsigned int unit;
  unsigned int bitsdone = 0;
  // ...
  while (bitsdone < bitsize)
{   
  unsigned HOST_WIDE_INT thissize;  
  rtx part; 
  unsigned HOST_WIDE_INT thispos;   
  unsigned HOST_WIDE_INT offset;

  offset = (bitpos + bitsdone) / unit;  // <=== BAD THING 1 
  thispos = (bitpos + bitsdone) % unit; // <=== BAD THING 2 
  // ...


Regardless of whether GCC wants to handle this example or not, implicit
signed-to-unsigned conversion looks wrong to me. Even an assertion failure from
the compiler is better than this silent code corruption. Furthermore, can we
even guess all the possible cases when the problematic path is taken?


Full backtrace:

Breakpoint 15, extract_split_bit_field (op0=0x76cb7c60, op0_mode=...,
bitsize=64, bitpos=18446744073709551552, unsignedp=0, reverse=false)
at ../../gcc/gcc/expmed.c:2266
2266  thispos = (bitpos + bitsdone) % unit;
(gdb) bt
#0  extract_split_bit_field (op0=0x76cb7c60, op0_mode=..., bitsize=64,
bitpos=18446744073709551552, unsignedp=0, reverse=false) at
../../gcc/gcc/expmed.c:2266   
#1  0x00aafff7 in extract_fixed_bit_field (tmode=E_DImode,
op0=0x76cb7c60, op0_mode=..., bitsize=64, bitnum=18446744073709551552,
target=0x76cb7bb8, 
unsignedp=0, reverse=false) at ../../gcc/gcc/expmed.c:2125
#2  0x00aaf793 in extract_integral_bit_field (op0=0x76cb7c60,
op0_mode=..., bitsize=64, bitnum=18446744073709551552, unsignedp=0,
target=0x76cb7bb8, 
mode=E_DImode, tmode=E_DImode, reverse=false, fallback_p=true) at
../../gcc/gcc/expmed.c:2016 
#3  0x00aaeb74 in extract_bit_field_1 (str_rtx=0x76cb7c60,
bitsize=..., bitnum=..., unsignedp=0, target=0x76cb7bb8, mode=E_DImode,
tmode=E_DImode,   
reverse=false, fallback_p=true, alt_rtl=0x0) at ../../gcc/gcc/expmed.c:1827
#4  0x00aafe8c in extract_bit_field (str_rtx=0x76cb7c60,
bitsize=..., bitnum=..., unsignedp=0, target=0x76cb7bb8, mode=E_DImode,
tmode=E_DImode, 
reverse=false, alt_rtl=0x0) at ../../gcc/gcc/expmed.c:2096
#5  0x00aecaff in expand_expr_real_1 (exp=0x76ca6840,
target=0x76cb7bb8, tmode=E_DImode, modifier=EXPAND_NORMAL, alt_rtl=0x0,
inner_reference_p=false)   
at ../../gcc/gcc/expr.c:10777
#6  

[Bug middle-end/84184] gcc generates wrong relocations with negative offsets in struct arrays

2018-06-13 Thread ebotcazou at gcc dot gnu.org
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=84184

Eric Botcazou  changed:

   What|Removed |Added

 Status|ASSIGNED|NEW
   Assignee|ebotcazou at gcc dot gnu.org   |unassigned at gcc dot 
gnu.org

[Bug middle-end/84184] gcc generates wrong relocations with negative offsets in struct arrays

2018-02-03 Thread ebotcazou at gcc dot gnu.org
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=84184

--- Comment #11 from Eric Botcazou  ---
> Why those are handled differently? First looks like it works, second does
> not. It was my main signal to file a bug against gcc as asymmetry looked
> fishy.

Because the problematic bitfield path is only used for fields in structures,
i.e. misaligned integers are handled by another, simpler path.

[Bug middle-end/84184] gcc generates wrong relocations with negative offsets in struct arrays

2018-02-02 Thread slyfox at inbox dot ru
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=84184

--- Comment #10 from Sergei Trofimovich  ---
Oh, I have forgot to ask another question:

In attached reloc-bug.c there is seemingly two functionally identical samples:

  extern char glo_u64_middle_hidden[] __attribute__((visibility("hidden")));
  static u64 __attribute__((noinline)) val_u64_hidden(void) {
const u64 * m = (const u64 *)glo_u64_middle_hidden;
return m[-1];
  }

and

  extern char glo_s_middle_hidden[] __attribute__((visibility("hidden")));
  struct s { u64 a; };
  static u64 __attribute__((noinline)) val_s_hidden(void) {
const struct s * m = (const struct s *)glo_s_middle_hidden;
return m[-1].a;
  }

Why those are handled differently? First looks like it works, second does not.
It was my main signal to file a bug against gcc as asymmetry looked fishy.

$ ./reloc-bug
val/global = 100
val/hidden = 100
Segmentation fault

[Bug middle-end/84184] gcc generates wrong relocations with negative offsets in struct arrays

2018-02-02 Thread slyfox at inbox dot ru
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=84184

--- Comment #9 from Sergei Trofimovich  ---
Aha, makes sense! Proposed kernel tweak upstream as:
https://lkml.org/lkml/2018/2/2/914

[Bug middle-end/84184] gcc generates wrong relocations with negative offsets in struct arrays

2018-02-02 Thread ebotcazou at gcc dot gnu.org
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=84184

Eric Botcazou  changed:

   What|Removed |Added

  Component|c   |middle-end

--- Comment #8 from Eric Botcazou  ---
Recategorizing.