diff mbox

Fix remaining compiler warnings in sloffs.c

Message ID 1470256668-21374-1-git-send-email-thuth@redhat.com
State Superseded
Headers show

Commit Message

Thomas Huth Aug. 3, 2016, 8:37 p.m. UTC
With my version of GCC (v4.8.5 - Advance-Toolchain 7.0) there are
currently two warnings when compiling sloffs.c:

sloffs.c: In function ‘sloffs_dump’:
sloffs.c:437:6: warning: dereferencing type-punned pointer will break strict-aliasing rules [-Wstrict-aliasing]
      printf("%04x", be16_to_cpu(*(uint16_t *)(header->date + 2)));
      ^
sloffs.c:449:6: warning: dereferencing type-punned pointer will break strict-aliasing rules [-Wstrict-aliasing]
      printf("%04x", be16_to_cpu(*(uint16_t *)(header->mdate + 2)));
      ^

These can be easily fixed by accessing the memory byte by byte instead of
casting the pointer to (uint16_t *). And while we're at it, let's also
simplify the code a little bit by consolidating the date print code
into a separate function which can be used by the two spots that print
a date.

Signed-off-by: Thomas Huth <thuth@redhat.com>
---
 tools/sloffs.c | 36 +++++++++++++++---------------------
 1 file changed, 15 insertions(+), 21 deletions(-)

Comments

Adrian Reber Aug. 5, 2016, 8:48 a.m. UTC | #1
On Wed, Aug 03, 2016 at 10:37:48PM +0200, Thomas Huth wrote:
> With my version of GCC (v4.8.5 - Advance-Toolchain 7.0) there are
> currently two warnings when compiling sloffs.c:
> 
> sloffs.c: In function ‘sloffs_dump’:
> sloffs.c:437:6: warning: dereferencing type-punned pointer will break strict-aliasing rules [-Wstrict-aliasing]
>       printf("%04x", be16_to_cpu(*(uint16_t *)(header->date + 2)));
>       ^
> sloffs.c:449:6: warning: dereferencing type-punned pointer will break strict-aliasing rules [-Wstrict-aliasing]
>       printf("%04x", be16_to_cpu(*(uint16_t *)(header->mdate + 2)));
>       ^
> 
> These can be easily fixed by accessing the memory byte by byte instead of
> casting the pointer to (uint16_t *). And while we're at it, let's also
> simplify the code a little bit by consolidating the date print code
> into a separate function which can be used by the two spots that print
> a date.
> 
> Signed-off-by: Thomas Huth <thuth@redhat.com>
> ---

I do not see this warning with gcc 6.1.1 but I also see it with 4.8.5
and with this patch it is fixed.

Reviewed-by: Adrian Reber <areber@redhat.com>


> diff --git a/tools/sloffs.c b/tools/sloffs.c
> index 91a23c3..764c956 100644
> --- a/tools/sloffs.c
> +++ b/tools/sloffs.c
> @@ -405,6 +405,19 @@ sloffs_append(const int file, const char *name, const char *dest)
>  	close(out);
>  }
>  
> +static void print_header_date(void *dptr)
> +{
> +	uint8_t *date = dptr;
> +
> +	if (*(uint64_t *)dptr != 0) {
> +		printf("%02x%02x-%02x-%02x %02x:%02x", date[2], date[3],
> +		       date[4], date[5], date[6], date[7]);
> +	} else {
> +		printf("N/A");
> +	}
> +
> +}
> +
>  static void
>  sloffs_dump(const int fd)
>  {
> @@ -413,7 +426,6 @@ sloffs_dump(const int fd)
>  	struct sloffs file;
>  	int i;
>  	uint64_t crc;
> -	uint64_t *datetmp;
>  	uint64_t header_len;
>  
>  	header = sloffs_header(fd);
> @@ -432,28 +444,10 @@ sloffs_dump(const int fd)
>  	/* there is a bug in the date position;
>  	 * it should be at header->date, but it is at (header->date + 2) */
>  	printf("  Build Date  : ");
> -	datetmp = (void *)header->date;
> -	if (be64_to_cpu(*datetmp)) {
> -	    printf("%04x", be16_to_cpu(*(uint16_t *)(header->date + 2)));
> -	    printf("-%02x", *(uint8_t *)(header->date + 4));
> -	    printf("-%02x", *(uint8_t *)(header->date + 5));
> -	    printf(" %02x:", *(uint8_t *)(header->date + 6));
> -	    printf("%02x", *(uint8_t *)(header->date + 7));
> -	} else {
> -	    printf("N/A");
> -	}
> +	print_header_date(header->date);
>  	printf("\n");
>  	printf("  Modify Date : ");
> -	datetmp = (void *)header->mdate;
> -	if (be64_to_cpu(*datetmp)) {
> -	    printf("%04x", be16_to_cpu(*(uint16_t *)(header->mdate + 2)));
> -	    printf("-%02x", *(uint8_t *)(header->mdate + 4));
> -	    printf("-%02x", *(uint8_t *)(header->mdate + 5));
> -	    printf(" %02x:", *(uint8_t *)(header->mdate + 6));
> -	    printf("%02x", *(uint8_t *)(header->mdate + 7));
> -	} else {
> -	    printf("N/A");
> -	}
> +	print_header_date(header->mdate);
>  	printf("\n");
>  	printf("  Image Length: %ld", be64_to_cpu(header->flashlen));
>  	printf(" (0x%lx) bytes\n", be64_to_cpu(header->flashlen));
> -- 
> 1.8.3.1
>
Segher Boessenkool Aug. 8, 2016, 1:30 a.m. UTC | #2
On Fri, Aug 05, 2016 at 10:48:18AM +0200, Adrian Reber wrote:
> > +static void print_header_date(void *dptr)
> > +{
> > +	uint8_t *date = dptr;
> > +
> > +	if (*(uint64_t *)dptr != 0) {

This is the exact same problem though.  Should be something like

	if (date[0] || date[1] || date[2] || date[3]
	    || date[4] || date[5] || date[6] || date[7])

> > +		printf("%02x%02x-%02x-%02x %02x:%02x", date[2], date[3],
> > +		       date[4], date[5], date[6], date[7]);
> > +	} else {
> > +		printf("N/A");
> > +	}
> > +
> > +}


Segher
Thomas Huth Aug. 8, 2016, 6:38 a.m. UTC | #3
On 08.08.2016 03:30, Segher Boessenkool wrote:
> On Fri, Aug 05, 2016 at 10:48:18AM +0200, Adrian Reber wrote:
>>> +static void print_header_date(void *dptr)
>>> +{
>>> +	uint8_t *date = dptr;
>>> +
>>> +	if (*(uint64_t *)dptr != 0) {
> 
> This is the exact same problem though.  Should be something like
> 
> 	if (date[0] || date[1] || date[2] || date[3]
> 	    || date[4] || date[5] || date[6] || date[7])

I'm now type-punning dptr here, not date, so this time it's a void
pointer instead of a char array ... and I thought type-punning a void
pointer would be OK since they are considered to alias any other kind of
data? I might be wrong here, though, these aliasing problems always
cause a headache for me.

In the end, we just might want to add -fno-strict-aliasing to the
HOSTCFLAGS, just like we already did it in make.rules for the normal
CFLAGS, and call it a day.
(But IMHO it makes sense to include this patch here anyway since it
consolidates the date printing a little bit)

 Thomas
Segher Boessenkool Aug. 8, 2016, 8:31 a.m. UTC | #4
On Mon, Aug 08, 2016 at 08:38:33AM +0200, Thomas Huth wrote:
> On 08.08.2016 03:30, Segher Boessenkool wrote:
> > On Fri, Aug 05, 2016 at 10:48:18AM +0200, Adrian Reber wrote:
> >>> +static void print_header_date(void *dptr)
> >>> +{
> >>> +	uint8_t *date = dptr;
> >>> +
> >>> +	if (*(uint64_t *)dptr != 0) {
> > 
> > This is the exact same problem though.  Should be something like
> > 
> > 	if (date[0] || date[1] || date[2] || date[3]
> > 	    || date[4] || date[5] || date[6] || date[7])
> 
> I'm now type-punning dptr here, not date, so this time it's a void
> pointer instead of a char array ... and I thought type-punning a void
> pointer would be OK since they are considered to alias any other kind of
> data? I might be wrong here, though, these aliasing problems always
> cause a headache for me.

That is not how it works.  The pointer type does not matter; it is
perfectly legal to cast a pointer.  What is not okay is accessing
something with a type not compatible with its effective type (ignoring
signedness), unless the access is character type.  "Effective type"
usually is just the declared type of the datum.

> In the end, we just might want to add -fno-strict-aliasing to the
> HOSTCFLAGS, just like we already did it in make.rules for the normal
> CFLAGS, and call it a day.

Or you could fix the problems.  SLOF used to work with -fstrict-aliasing,
and it was a nice performance win.


Segher
Thomas Huth Aug. 8, 2016, 9:09 a.m. UTC | #5
On 08.08.2016 10:31, Segher Boessenkool wrote:
> On Mon, Aug 08, 2016 at 08:38:33AM +0200, Thomas Huth wrote:
>> On 08.08.2016 03:30, Segher Boessenkool wrote:
>>> On Fri, Aug 05, 2016 at 10:48:18AM +0200, Adrian Reber wrote:
>>>>> +static void print_header_date(void *dptr)
>>>>> +{
>>>>> +	uint8_t *date = dptr;
>>>>> +
>>>>> +	if (*(uint64_t *)dptr != 0) {
>>>
>>> This is the exact same problem though.  Should be something like
>>>
>>> 	if (date[0] || date[1] || date[2] || date[3]
>>> 	    || date[4] || date[5] || date[6] || date[7])
>>
>> I'm now type-punning dptr here, not date, so this time it's a void
>> pointer instead of a char array ... and I thought type-punning a void
>> pointer would be OK since they are considered to alias any other kind of
>> data? I might be wrong here, though, these aliasing problems always
>> cause a headache for me.
> 
> That is not how it works.  The pointer type does not matter; it is
> perfectly legal to cast a pointer.  What is not okay is accessing
> something with a type not compatible with its effective type (ignoring
> signedness), unless the access is character type.  "Effective type"
> usually is just the declared type of the datum.

Ouch, OK, I got it now. I'll send a new version of my patch...

>> In the end, we just might want to add -fno-strict-aliasing to the
>> HOSTCFLAGS, just like we already did it in make.rules for the normal
>> CFLAGS, and call it a day.
> 
> Or you could fix the problems.  SLOF used to work with -fstrict-aliasing,
> and it was a nice performance win.

That's a question for Nikunj who committed that change a couple of years
ago ...
(see http://git.qemu.org/?p=SLOF.git;a=commitdiff;h=7eca6a5e56f468)

 Thomas
Nikunj A Dadhania Aug. 8, 2016, 9:15 a.m. UTC | #6
Thomas Huth <thuth@redhat.com> writes:

> On 08.08.2016 10:31, Segher Boessenkool wrote:
>> On Mon, Aug 08, 2016 at 08:38:33AM +0200, Thomas Huth wrote:
>>> On 08.08.2016 03:30, Segher Boessenkool wrote:
>>>> On Fri, Aug 05, 2016 at 10:48:18AM +0200, Adrian Reber wrote:
>>>>>> +static void print_header_date(void *dptr)
>>>>>> +{
>>>>>> +	uint8_t *date = dptr;
>>>>>> +
>>>>>> +	if (*(uint64_t *)dptr != 0) {
>>>>
>>>> This is the exact same problem though.  Should be something like
>>>>
>>>> 	if (date[0] || date[1] || date[2] || date[3]
>>>> 	    || date[4] || date[5] || date[6] || date[7])
>>>
>>> I'm now type-punning dptr here, not date, so this time it's a void
>>> pointer instead of a char array ... and I thought type-punning a void
>>> pointer would be OK since they are considered to alias any other kind of
>>> data? I might be wrong here, though, these aliasing problems always
>>> cause a headache for me.
>> 
>> That is not how it works.  The pointer type does not matter; it is
>> perfectly legal to cast a pointer.  What is not okay is accessing
>> something with a type not compatible with its effective type (ignoring
>> signedness), unless the access is character type.  "Effective type"
>> usually is just the declared type of the datum.
>
> Ouch, OK, I got it now. I'll send a new version of my patch...
>
>>> In the end, we just might want to add -fno-strict-aliasing to the
>>> HOSTCFLAGS, just like we already did it in make.rules for the normal
>>> CFLAGS, and call it a day.
>> 
>> Or you could fix the problems.  SLOF used to work with -fstrict-aliasing,
>> and it was a nice performance win.
>
> That's a question for Nikunj who committed that change a couple of years
> ago ...
> (see http://git.qemu.org/?p=SLOF.git;a=commitdiff;h=7eca6a5e56f468)

I remember that we had a discussion on this and BenH had suggested that
we cannot re-audit all the code for correctness with strict-aliasing. So
disable it.

Regards,
Nikunj
Segher Boessenkool Aug. 8, 2016, 9:22 a.m. UTC | #7
On Mon, Aug 08, 2016 at 02:45:35PM +0530, Nikunj A Dadhania wrote:
> >>> In the end, we just might want to add -fno-strict-aliasing to the
> >>> HOSTCFLAGS, just like we already did it in make.rules for the normal
> >>> CFLAGS, and call it a day.
> >> 
> >> Or you could fix the problems.  SLOF used to work with -fstrict-aliasing,
> >> and it was a nice performance win.
> >
> > That's a question for Nikunj who committed that change a couple of years
> > ago ...
> > (see http://git.qemu.org/?p=SLOF.git;a=commitdiff;h=7eca6a5e56f468)
> 
> I remember that we had a discussion on this and BenH had suggested that
> we cannot re-audit all the code for correctness with strict-aliasing. So
> disable it.

That's what -Wstrict-aliasing is for (needs -fstrict-aliasing active as
well, to work).

Rewriting the code to make it better can be quite a bit of work, of
course.  But you could e.g. only use -fno-strict-aliasing on those files
where -Wstrict-aliasing warns.


Segher
Nikunj A Dadhania Aug. 8, 2016, 10:32 a.m. UTC | #8
Segher Boessenkool <segher@kernel.crashing.org> writes:

> On Mon, Aug 08, 2016 at 02:45:35PM +0530, Nikunj A Dadhania wrote:
>> >>> In the end, we just might want to add -fno-strict-aliasing to the
>> >>> HOSTCFLAGS, just like we already did it in make.rules for the normal
>> >>> CFLAGS, and call it a day.
>> >> 
>> >> Or you could fix the problems.  SLOF used to work with -fstrict-aliasing,
>> >> and it was a nice performance win.
>> >
>> > That's a question for Nikunj who committed that change a couple of years
>> > ago ...
>> > (see http://git.qemu.org/?p=SLOF.git;a=commitdiff;h=7eca6a5e56f468)
>> 
>> I remember that we had a discussion on this and BenH had suggested that
>> we cannot re-audit all the code for correctness with strict-aliasing. So
>> disable it.
>
> That's what -Wstrict-aliasing is for (needs -fstrict-aliasing active as
> well, to work).
>
> Rewriting the code to make it better can be quite a bit of work, of
> course.  But you could e.g. only use -fno-strict-aliasing on those files
> where -Wstrict-aliasing warns.

fill_udp_checksum() was the offending routine. And don't remember
there was any warning, we found the hard way. Computed checksum was
incorrect in certain cases.

Regards
Nikunj
diff mbox

Patch

diff --git a/tools/sloffs.c b/tools/sloffs.c
index 91a23c3..764c956 100644
--- a/tools/sloffs.c
+++ b/tools/sloffs.c
@@ -405,6 +405,19 @@  sloffs_append(const int file, const char *name, const char *dest)
 	close(out);
 }
 
+static void print_header_date(void *dptr)
+{
+	uint8_t *date = dptr;
+
+	if (*(uint64_t *)dptr != 0) {
+		printf("%02x%02x-%02x-%02x %02x:%02x", date[2], date[3],
+		       date[4], date[5], date[6], date[7]);
+	} else {
+		printf("N/A");
+	}
+
+}
+
 static void
 sloffs_dump(const int fd)
 {
@@ -413,7 +426,6 @@  sloffs_dump(const int fd)
 	struct sloffs file;
 	int i;
 	uint64_t crc;
-	uint64_t *datetmp;
 	uint64_t header_len;
 
 	header = sloffs_header(fd);
@@ -432,28 +444,10 @@  sloffs_dump(const int fd)
 	/* there is a bug in the date position;
 	 * it should be at header->date, but it is at (header->date + 2) */
 	printf("  Build Date  : ");
-	datetmp = (void *)header->date;
-	if (be64_to_cpu(*datetmp)) {
-	    printf("%04x", be16_to_cpu(*(uint16_t *)(header->date + 2)));
-	    printf("-%02x", *(uint8_t *)(header->date + 4));
-	    printf("-%02x", *(uint8_t *)(header->date + 5));
-	    printf(" %02x:", *(uint8_t *)(header->date + 6));
-	    printf("%02x", *(uint8_t *)(header->date + 7));
-	} else {
-	    printf("N/A");
-	}
+	print_header_date(header->date);
 	printf("\n");
 	printf("  Modify Date : ");
-	datetmp = (void *)header->mdate;
-	if (be64_to_cpu(*datetmp)) {
-	    printf("%04x", be16_to_cpu(*(uint16_t *)(header->mdate + 2)));
-	    printf("-%02x", *(uint8_t *)(header->mdate + 4));
-	    printf("-%02x", *(uint8_t *)(header->mdate + 5));
-	    printf(" %02x:", *(uint8_t *)(header->mdate + 6));
-	    printf("%02x", *(uint8_t *)(header->mdate + 7));
-	} else {
-	    printf("N/A");
-	}
+	print_header_date(header->mdate);
 	printf("\n");
 	printf("  Image Length: %ld", be64_to_cpu(header->flashlen));
 	printf(" (0x%lx) bytes\n", be64_to_cpu(header->flashlen));