Re: [patch, ia64] Fix unaligned accesses on IA64 from dwarf2out.c

2011-08-10 Thread Richard Henderson
On 08/10/2011 09:52 AM, Steve Ellcey wrote:
> * md5.c (md5_read_ctx): Handle mis-aligned resbuf pointer.

Ok.


r~


Re: [patch, ia64] Fix unaligned accesses on IA64 from dwarf2out.c

2011-08-10 Thread Steve Ellcey
On Wed, 2011-08-10 at 11:19 +0200, Richard Guenther wrote:
> On Wed, Aug 10, 2011 at 10:48 AM, Pedro Alves  wrote:
> >
> > which makes me wonder if the right fix isn't to change
> > libiberty internally to not rely on the alignment.
> 
> I think that would be the best fix.  It hardly can be a performance
> critical part - libiberty could use a local aligned buffer for
> compute and do a copy on return.
> 
> Richard.

I like this idea.  How about this patch.  I am still testing it but it
should work.

Steve Ellcey
s...@cup.hp.com


2011-08-10  Steve Ellcey  

* md5.c (md5_read_ctx): Handle mis-aligned resbuf pointer.


Index: md5.c
===
--- md5.c   (revision 177411)
+++ md5.c   (working copy)
@@ -76,15 +76,19 @@ md5_init_ctx (struct md5_ctx *ctx)
 /* Put result from CTX in first 16 bytes following RESBUF.  The result
must be in little endian byte order.
 
-   IMPORTANT: On some systems it is required that RESBUF is correctly
-   aligned for a 32 bits value.  */
+   IMPORTANT: RESBUF may not be aligned as strongly as MD5_UNIT32 so we
+   put things in a local (aligned) buffer first, then memcpy into RESBUF.  */
 void *
 md5_read_ctx (const struct md5_ctx *ctx, void *resbuf)
 {
-  ((md5_uint32 *) resbuf)[0] = SWAP (ctx->A);
-  ((md5_uint32 *) resbuf)[1] = SWAP (ctx->B);
-  ((md5_uint32 *) resbuf)[2] = SWAP (ctx->C);
-  ((md5_uint32 *) resbuf)[3] = SWAP (ctx->D);
+  md5_unit32 buffer[4];
+
+  buffer[0] = SWAP (ctx->A);
+  buffer[1] = SWAP (ctx->B);
+  buffer[2] = SWAP (ctx->C);
+  buffer[3] = SWAP (ctx->D);
+
+  memcpy (resbuf, buffer, 16);
 
   return resbuf;
 }




Re: [patch, ia64] Fix unaligned accesses on IA64 from dwarf2out.c

2011-08-10 Thread Richard Guenther
On Wed, Aug 10, 2011 at 10:48 AM, Pedro Alves  wrote:
> On Wednesday 10 August 2011 01:02:50, Steve Ellcey wrote:
>> On Tue, 2011-08-09 at 16:50 -0700, Richard Henderson wrote:
>> > >
>> > > I think I like using a union to ensure the alignment of checksum better.
>> > > In dwarf2out.c we are always using one md5_ctx structure and one
>> > > checksum buffer but in fold-const.c there are routines where we use one
>> > > md5_ctx structure with 4 (fold_build2_stat_loc) or 6
>> > > (fold_build3_stat_loc) different checksum buffers.
>> >
>> > I'm not keen on this.
>> >
>> > Yes, it does happen to work, but only accidentally.  The CTX
>> > object and the CHECKSUM object have overlapping lifetimes
>> > within md5_read_ctx.
>> >
>> >
>> > r~
>>
>> I am not proposing we put the CTX object and the CHECKSUM object into
>> one union.  I am proposing we leave the CTX object alone and put the
>> CHECKSUM object in a union with a dummy variable of type md5_uint32 in
>> order to ensure that the CHECKSUM object has the correct alignment.
>>
>> So the usage would be:
>>
>> union md5_resbuf
>> {
>>   md5_uint32 dummy;                     /* Unused variable used to ensure 
>> alignment */
>>   unsigned char resbuf[16];             /* The buffer we are using in 
>> md5_finish_ctx */
>> };
>
> Or even
>
> union md5_resbuf
> {
>  md5_uint32 ui32[4];
>  unsigned char ui8[16];
> };
>
> and put it in include/md5.h instead, so that all clients
> can use it instead of cooking up the same themselves.
> liberty's md5.c itself internaly could be make to use the
> union instead of the casts?
>
> *looks for users of md5*
>
> but then, gold does:
>
>  unsigned char* ov = of->get_output_view(this->build_id_note_->offset(),
>                                          this->build_id_note_->data_size());
>
>  const char* style = parameters->options().build_id();
>  if (strcmp(style, "sha1") == 0)
>    {
>      sha1_ctx ctx;
>      sha1_init_ctx(&ctx);
>      sha1_process_bytes(iv, this->output_file_size_, &ctx);
>      sha1_finish_ctx(&ctx, ov);
>    }
>  else if (strcmp(style, "md5") == 0)
>    {
>      md5_ctx ctx;
>      md5_init_ctx(&ctx);
>      md5_process_bytes(iv, this->output_file_size_, &ctx);
>      md5_finish_ctx(&ctx, ov);
>
> which makes me wonder if the right fix isn't to change
> libiberty internally to not rely on the alignment.

I think that would be the best fix.  It hardly can be a performance
critical part - libiberty could use a local aligned buffer for
compute and do a copy on return.

Richard.

> libiberty's sha1 routines seem to have the same issue
> (though they don't appear used in gcc.  gold uses them, as
> seen above).
>
> --
> Pedro Alves
>


Re: [patch, ia64] Fix unaligned accesses on IA64 from dwarf2out.c

2011-08-10 Thread Pedro Alves
On Wednesday 10 August 2011 01:02:50, Steve Ellcey wrote:
> On Tue, 2011-08-09 at 16:50 -0700, Richard Henderson wrote:
> > > 
> > > I think I like using a union to ensure the alignment of checksum better.
> > > In dwarf2out.c we are always using one md5_ctx structure and one
> > > checksum buffer but in fold-const.c there are routines where we use one
> > > md5_ctx structure with 4 (fold_build2_stat_loc) or 6
> > > (fold_build3_stat_loc) different checksum buffers.
> > 
> > I'm not keen on this.
> > 
> > Yes, it does happen to work, but only accidentally.  The CTX
> > object and the CHECKSUM object have overlapping lifetimes
> > within md5_read_ctx.
> > 
> > 
> > r~
> 
> I am not proposing we put the CTX object and the CHECKSUM object into
> one union.  I am proposing we leave the CTX object alone and put the
> CHECKSUM object in a union with a dummy variable of type md5_uint32 in
> order to ensure that the CHECKSUM object has the correct alignment.
> 
> So the usage would be:
> 
> union md5_resbuf
> {
>   md5_uint32 dummy; /* Unused variable used to ensure 
> alignment */
>   unsigned char resbuf[16]; /* The buffer we are using in 
> md5_finish_ctx */
> };

Or even

union md5_resbuf
{
  md5_uint32 ui32[4];
  unsigned char ui8[16];
};

and put it in include/md5.h instead, so that all clients
can use it instead of cooking up the same themselves.
liberty's md5.c itself internaly could be make to use the
union instead of the casts?

*looks for users of md5*

but then, gold does:

  unsigned char* ov = of->get_output_view(this->build_id_note_->offset(),
  this->build_id_note_->data_size());

  const char* style = parameters->options().build_id();
  if (strcmp(style, "sha1") == 0)
{
  sha1_ctx ctx;
  sha1_init_ctx(&ctx);
  sha1_process_bytes(iv, this->output_file_size_, &ctx);
  sha1_finish_ctx(&ctx, ov);
}
  else if (strcmp(style, "md5") == 0)
{
  md5_ctx ctx;
  md5_init_ctx(&ctx);
  md5_process_bytes(iv, this->output_file_size_, &ctx);
  md5_finish_ctx(&ctx, ov);

which makes me wonder if the right fix isn't to change
libiberty internally to not rely on the alignment.

libiberty's sha1 routines seem to have the same issue
(though they don't appear used in gcc.  gold uses them, as
seen above).

-- 
Pedro Alves


Re: [patch, ia64] Fix unaligned accesses on IA64 from dwarf2out.c

2011-08-09 Thread Steve Ellcey
On Tue, 2011-08-09 at 16:50 -0700, Richard Henderson wrote:
> > 
> > I think I like using a union to ensure the alignment of checksum better.
> > In dwarf2out.c we are always using one md5_ctx structure and one
> > checksum buffer but in fold-const.c there are routines where we use one
> > md5_ctx structure with 4 (fold_build2_stat_loc) or 6
> > (fold_build3_stat_loc) different checksum buffers.
> 
> I'm not keen on this.
> 
> Yes, it does happen to work, but only accidentally.  The CTX
> object and the CHECKSUM object have overlapping lifetimes
> within md5_read_ctx.
> 
> 
> r~

I am not proposing we put the CTX object and the CHECKSUM object into
one union.  I am proposing we leave the CTX object alone and put the
CHECKSUM object in a union with a dummy variable of type md5_uint32 in
order to ensure that the CHECKSUM object has the correct alignment.

So the usage would be:

union md5_resbuf
{
  md5_uint32 dummy; /* Unused variable used to ensure 
alignment */
  unsigned char resbuf[16]; /* The buffer we are using in 
md5_finish_ctx */
};

struct md5_ctx ctx; /* Same as before */
union md5_resbuf checksum;  /* Instead of unsigned char 
checksum[16]; */
md5_finish_ctx (&ctx, checksum.resbuf); /* instead of md5_finish_ctx (&ctx, 
checksum); */

Steve Ellcey
s...@cup.hp.com



Re: [patch, ia64] Fix unaligned accesses on IA64 from dwarf2out.c

2011-08-09 Thread Richard Henderson
On 08/09/2011 02:32 PM, Steve Ellcey wrote:
> On Tue, 2011-08-09 at 08:25 -0700, Richard Henderson wrote:
>> On 08/08/2011 03:22 PM, Steve Ellcey wrote:
>>> Oh, so after I declare md5, I call md5_finish_ctx like: 
>>>
>>> md5_finish_ctx (&md5.ctx, md5.checksum);
>>>
>>> Is that what you are proposing?  It seems a bit odd to put checksum in a
>>> a structure with ctx just to guarantee its alignment and not to pass
>>> them around as one entity, but I guess it's no worse then using a union.
>>
>> Yes, that's what I'm proposing.
>>
>>
>> r~
> 
> I think I like using a union to ensure the alignment of checksum better.
> In dwarf2out.c we are always using one md5_ctx structure and one
> checksum buffer but in fold-const.c there are routines where we use one
> md5_ctx structure with 4 (fold_build2_stat_loc) or 6
> (fold_build3_stat_loc) different checksum buffers.

I'm not keen on this.

Yes, it does happen to work, but only accidentally.  The CTX
object and the CHECKSUM object have overlapping lifetimes
within md5_read_ctx.


r~


Re: [patch, ia64] Fix unaligned accesses on IA64 from dwarf2out.c

2011-08-09 Thread Steve Ellcey
On Tue, 2011-08-09 at 08:25 -0700, Richard Henderson wrote:
> On 08/08/2011 03:22 PM, Steve Ellcey wrote:
> > Oh, so after I declare md5, I call md5_finish_ctx like: 
> > 
> > md5_finish_ctx (&md5.ctx, md5.checksum);
> > 
> > Is that what you are proposing?  It seems a bit odd to put checksum in a
> > a structure with ctx just to guarantee its alignment and not to pass
> > them around as one entity, but I guess it's no worse then using a union.
> 
> Yes, that's what I'm proposing.
> 
> 
> r~

I think I like using a union to ensure the alignment of checksum better.
In dwarf2out.c we are always using one md5_ctx structure and one
checksum buffer but in fold-const.c there are routines where we use one
md5_ctx structure with 4 (fold_build2_stat_loc) or 6
(fold_build3_stat_loc) different checksum buffers.

If I use a structure containing one md5_ctx struct and one checksum
array then I need to create a lot of extra md5_ctx structures in
fold-const.c.  If I use the md5_ctx as it currently is and just change
checksum from a structure to a union in order to guarantee its alignment
then I don't need to increase the space the fold-const routines are
using.

Steve Ellcey
s...@cup.hp.com



Re: [patch, ia64] Fix unaligned accesses on IA64 from dwarf2out.c

2011-08-09 Thread Richard Henderson
On 08/08/2011 03:22 PM, Steve Ellcey wrote:
> Oh, so after I declare md5, I call md5_finish_ctx like: 
> 
>   md5_finish_ctx (&md5.ctx, md5.checksum);
> 
> Is that what you are proposing?  It seems a bit odd to put checksum in a
> a structure with ctx just to guarantee its alignment and not to pass
> them around as one entity, but I guess it's no worse then using a union.

Yes, that's what I'm proposing.


r~


Re: [patch, ia64] Fix unaligned accesses on IA64 from dwarf2out.c

2011-08-08 Thread Steve Ellcey
On Fri, 2011-08-05 at 11:45 -0700, Richard Henderson wrote:
> On 08/05/2011 10:54 AM, Steve Ellcey wrote:
> > -  unsigned char checksum[16];
> >struct md5_ctx ctx;
> > +  unsigned char checksum[16];
> 
> How about
> 
>   struct md5_data
>   {
> struct md5_ctx ctx;
> unsigned char checksum[16];
>   };
> 
>   struct md5_data md5;
> 
> with the structure definition somewhere interesting?
> If no where else, just dwarf2out.c file scope.
> 
> 
> r~

Oh, so after I declare md5, I call md5_finish_ctx like: 

md5_finish_ctx (&md5.ctx, md5.checksum);

Is that what you are proposing?  It seems a bit odd to put checksum in a
a structure with ctx just to guarantee its alignment and not to pass
them around as one entity, but I guess it's no worse then using a union.

Steve Ellcey
s...@cup.hp.com



Re: [patch, ia64] Fix unaligned accesses on IA64 from dwarf2out.c

2011-08-08 Thread Richard Henderson
On 08/08/2011 02:24 PM, Steve Ellcey wrote:
> Do you mean a union, as Andreas suggested?

No, I mean struct.  The union is wrong, because both data elements
are live at the same time.


r~


Re: [patch, ia64] Fix unaligned accesses on IA64 from dwarf2out.c

2011-08-08 Thread Steve Ellcey
On Fri, 2011-08-05 at 11:45 -0700, Richard Henderson wrote:
> On 08/05/2011 10:54 AM, Steve Ellcey wrote:
> > -  unsigned char checksum[16];
> >struct md5_ctx ctx;
> > +  unsigned char checksum[16];
> 
> How about
> 
>   struct md5_data
>   {
> struct md5_ctx ctx;
> unsigned char checksum[16];
>   };
> 
>   struct md5_data md5;
> 
> with the structure definition somewhere interesting?
> If no where else, just dwarf2out.c file scope.
> 
> 
> r~

Do you mean a union, as Andreas suggested?  What do you think of this
patch?  I used a union of the unsigned char array that we need and a
dummy variable of type md5_uint32 since md5_read_ctx is treating the
pointer as a pointer to an array of type md5_uint32 and so that is the
alignment that we need.

If this is considered the right approach, we can make a similar change
to fold-const.c which is why I put the definition of md5_resbuf in md5.h
instead of in dwarf2out.c.

Steve Ellcey
s...@cup.hp.com


2011-08-08  Steve Ellcey  

* md5.h (md5_resbuf): New union type.


gcc/ChangeLog


2011-08-08  Steve Ellcey  

* dwarf2out.c (generate_type_signature): Change type of checksum to
union and change usages to access resbuf field.
(compute_section_prefix): Ditto.
(optimize_macinfo_range): Ditto.



Index: include/md5.h
===
--- include/md5.h   (revision 177411)
+++ include/md5.h   (working copy)
@@ -89,6 +89,15 @@ struct md5_ctx
   char buffer[128] ATTRIBUTE_ALIGNED_ALIGNOF(md5_uint32);
 };
 
+/* Union for buffer data that must be aligned when accessed by
+   md5_read_ctx (usually called from md5_finish_ctx).  */
+
+union md5_resbuf
+{
+  md5_uint32 dummy;
+  unsigned char resbuf[16];
+};
+
 /*
  * The following three functions are build up the low level used in
  * the functions `md5_stream' and `md5_buffer'.
Index: gcc/dwarf2out.c
===
--- gcc/dwarf2out.c (revision 177411)
+++ gcc/dwarf2out.c (working copy)
@@ -6369,8 +6369,8 @@ generate_type_signature (dw_die_ref die,
 {
   int mark;
   const char *name;
-  unsigned char checksum[16];
   struct md5_ctx ctx;
+  union md5_resbuf checksum;
   dw_die_ref decl;
 
   name = get_AT_string (die, DW_AT_name);
@@ -6390,9 +6390,9 @@ generate_type_signature (dw_die_ref die,
 
   md5_process_bytes (&die->die_tag, sizeof (die->die_tag), &ctx);
   md5_process_bytes (name, strlen (name) + 1, &ctx);
-  md5_finish_ctx (&ctx, checksum);
+  md5_finish_ctx (&ctx, checksum.resbuf);
 
-  add_AT_data8 (type_node->root_die, DW_AT_GNU_odr_signature, 
&checksum[8]);
+  add_AT_data8 (type_node->root_die, DW_AT_GNU_odr_signature, 
&checksum.resbuf[8]);
 }
 
   /* Next, compute the complete type signature.  */
@@ -6408,11 +6408,11 @@ generate_type_signature (dw_die_ref die,
   /* Checksum the DIE and its children.  */
   die_checksum_ordered (die, &ctx, &mark);
   unmark_all_dies (die);
-  md5_finish_ctx (&ctx, checksum);
+  md5_finish_ctx (&ctx, checksum.resbuf);
 
   /* Store the signature in the type node and link the type DIE and the
  type node together.  */
-  memcpy (type_node->signature, &checksum[16 - DWARF_TYPE_SIGNATURE_SIZE],
+  memcpy (type_node->signature, &checksum.resbuf[16 - 
DWARF_TYPE_SIGNATURE_SIZE],
   DWARF_TYPE_SIGNATURE_SIZE);
   die->die_id.die_type_node = type_node;
   type_node->type_die = die;
@@ -6602,8 +6602,8 @@ compute_section_prefix (dw_die_ref unit_
   char *name = XALLOCAVEC (char, strlen (base) + 64);
   char *p;
   int i, mark;
-  unsigned char checksum[16];
   struct md5_ctx ctx;
+  union md5_resbuf checksum;
 
   /* Compute the checksum of the DIE, then append part of it as hex digits to
  the name filename of the unit.  */
@@ -6612,7 +6612,7 @@ compute_section_prefix (dw_die_ref unit_
   mark = 0;
   die_checksum (unit_die, &ctx, &mark);
   unmark_all_dies (unit_die);
-  md5_finish_ctx (&ctx, checksum);
+  md5_finish_ctx (&ctx, checksum.resbuf);
 
   sprintf (name, "%s.", base);
   clean_symbol_name (name);
@@ -6620,7 +6620,7 @@ compute_section_prefix (dw_die_ref unit_
   p = name + strlen (name);
   for (i = 0; i < 4; i++)
 {
-  sprintf (p, "%.2x", checksum[i]);
+  sprintf (p, "%.2x", checksum.resbuf[i]);
   p += 2;
 }
 
@@ -20662,8 +20662,8 @@ optimize_macinfo_range (unsigned int idx
 {
   macinfo_entry *first, *second, *cur, *inc;
   char linebuf[sizeof (HOST_WIDE_INT) * 3 + 1];
-  unsigned char checksum[16];
   struct md5_ctx ctx;
+  union md5_resbuf checksum;
   char *grp_name, *tail;
   const char *base;
   unsigned int i, count, encoded_filename_len, linebuf_len;
@@ -20702,7 +20702,7 @@ optimize_macinfo_range (unsigned int idx
checksum_uleb128 (cur->lineno, &ctx);
md5_process_bytes (cur->info, strlen (cur->info) + 1, &ctx);
   }
-  md5_finish_ctx (&ctx, checksum);
+  md5_finish_ctx (&ctx, checksum.resbuf);
   count = i - idx;
 
 

Re: [patch, ia64] Fix unaligned accesses on IA64 from dwarf2out.c

2011-08-05 Thread Richard Henderson
On 08/05/2011 10:54 AM, Steve Ellcey wrote:
> -  unsigned char checksum[16];
>struct md5_ctx ctx;
> +  unsigned char checksum[16];

How about

  struct md5_data
  {
struct md5_ctx ctx;
unsigned char checksum[16];
  };

  struct md5_data md5;

with the structure definition somewhere interesting?
If no where else, just dwarf2out.c file scope.


r~


Re: [patch, ia64] Fix unaligned accesses on IA64 from dwarf2out.c

2011-08-05 Thread Andreas Schwab
Steve Ellcey  writes:

> Obviously this isn't a perfect fix, it is relying on how GCC is laying
> out local variables which isn't gauranteed, but it fixes the problem and
> I thought I would see if I could get approval for this simple fix or if
> people think we need a more complete fix.

Why not making it a union?

Andreas.

-- 
Andreas Schwab, sch...@linux-m68k.org
GPG Key fingerprint = 58CA 54C7 6D53 942B 1756  01D3 44D5 214B 8276 4ED5
"And now for something completely different."


[patch, ia64] Fix unaligned accesses on IA64 from dwarf2out.c

2011-08-05 Thread Steve Ellcey
Some recent changes in dwarf2out.c have caused GCC to generate unaligned
data traps on IA64 Linux.  In looking a this I tracked it down to
md5_read_ctx in libiberty, which is called by md5_finish_ctx, which in
turn is called by various routines in dwarf2out.c.

md5_read_ctx has a comment that the buffer must be 32 bit aligned but
there is nothing in dwarf2out.c to enforce this alignment to the
checksum buffer passed in to md5_finish_ctx.  I looked at calls to
md5_finish_ctx in fold-const.c to see why these didn't seem to have a
problem and noticed that the buffers used were always declared after the
md5_ctx structure and I think that 'accidentaly' got everything aligned
correctly.  If I do the same thing on the three buffer declarations in
dwarf2out.c the misaligned messages go away and things work fine.

Obviously this isn't a perfect fix, it is relying on how GCC is laying
out local variables which isn't gauranteed, but it fixes the problem and
I thought I would see if I could get approval for this simple fix or if
people think we need a more complete fix.  If we need a better fix, what
should I do?  It doesn't look like we use the alignment attribute in the
GCC code anywhere.  I could change the type of the checksum buffer from an
array of unsigned char to something that has a stronger alignment
requirement, but that would probably require a number of casts be added
where the checksum variable is used.

So, can I get someone to approve this simple, if imperfect, patch?
Tested on IA64 Linux.

Steve Ellcey
s...@cup.hp.com


2011-08-05  Steve Ellcey  

* dwarf2out.c (generate_type_signature): Change decl order to force
alignment.
(compute_section_prefix): 
(optimize_macinfo_range): Ditto.


Index: dwarf2out.c
===
--- dwarf2out.c (revision 177422)
+++ dwarf2out.c (working copy)
@@ -6369,8 +6369,8 @@ generate_type_signature (dw_die_ref die,
 {
   int mark;
   const char *name;
-  unsigned char checksum[16];
   struct md5_ctx ctx;
+  unsigned char checksum[16];
   dw_die_ref decl;
 
   name = get_AT_string (die, DW_AT_name);
@@ -6602,8 +6602,8 @@ compute_section_prefix (dw_die_ref unit_
   char *name = XALLOCAVEC (char, strlen (base) + 64);
   char *p;
   int i, mark;
-  unsigned char checksum[16];
   struct md5_ctx ctx;
+  unsigned char checksum[16];
 
   /* Compute the checksum of the DIE, then append part of it as hex digits to
  the name filename of the unit.  */
@@ -20662,8 +20662,8 @@ optimize_macinfo_range (unsigned int idx
 {
   macinfo_entry *first, *second, *cur, *inc;
   char linebuf[sizeof (HOST_WIDE_INT) * 3 + 1];
-  unsigned char checksum[16];
   struct md5_ctx ctx;
+  unsigned char checksum[16];
   char *grp_name, *tail;
   const char *base;
   unsigned int i, count, encoded_filename_len, linebuf_len;