Hi Vincent,
Le 14/05/2016 19:08, Vincent Bernat a écrit :
❦ 14 mai 2016 15:20 +0200, Cyril Bonté <cyril.bo...@free.fr> :
What is the most important is to report this to the gcc maintainers so that
they can fix the bug. The fix will naturally flow into the distros.
I understand this and of course I could try to fill a bug on their side but
the gcc stuff is a bit out of my league.
After spending some time on this, I'm now able to produce a minimal
test case.
$ gcc-6 -O2 -o debug debug.c && ./debug
0
=> here we have an issue, as it shouldn't be 0
$ gcc-6 -O2 -DDEBUG -o debug debug.c && ./debug
7f000001
7f000001
=> Suddenly, everything works
And now, what happens with this debug code when -fno-tree-sra is used ?
$ gcc-6 -O2 -fno-tree-sra -DDEBUG -o debug debug.c && ./debug
7f000001
0
=> It still doesn't work :-( So, disabling "tree-sra" doesn't
guarantee the right behaviour.
I also attach a debug2.c example, which is also disturbing. It is the
same code, but adds a local variable. Depending on the code order,
strange things happen (looks like a memory alignment issue).
For example :
$ gcc-6 -O2 -o debug2 debug2.c && ./debug2
0
fd7f0000
Note : my tests were made on a Debian SID with the gcc-6 package.
I think this is an aliasing problem. You cannot have two incompatible
variables pointing at the same memory spot. It seems that now
sockaddr_storage and sockaddr_in are not compatible anymore.
#v+
struct sockaddr_storage
{
__SOCKADDR_COMMON (ss_); /* Address family, etc. */
__ss_aligntype __ss_align; /* Force desired alignment. */
char __ss_padding[_SS_PADSIZE];
};
struct sockaddr_in
{
__SOCKADDR_COMMON (sin_);
in_port_t sin_port; /* Port number. */
struct in_addr sin_addr; /* Internet address. */
/* Pad to size of `struct sockaddr'. */
unsigned char sin_zero[sizeof (struct sockaddr) -
__SOCKADDR_COMMON_SIZE -
sizeof (in_port_t) -
sizeof (struct in_addr)];
};
#v-
If I introduce this type:
#v+
struct sockaddr_storage_universal {
union {
struct sockaddr_storage sas;
struct sockaddr_in sai;
struct sockaddr_in6 sai6;
};
};
#v-
This works when used in place of "struct sockaddr_storage". I see the
glibc is using an union too instead of struct sockaddr or struct
sockaddr_storage. man 7 socket still says to use struct
sockaddr_storage.
Searching a bit, there is this old question on StackOverflow:
http://stackoverflow.com/questions/1429645/how-to-cast-sockaddr-storage-and-avoid-breaking-strict-aliasing-rules
Yes, that's where I stopped too after extracting the test case from the
whole code.
--
Cyril Bonté