Operating System - HP-UX
1825002 Members
2673 Online
109678 Solutions
New Discussion юеВ

Re: 64 bit gcc 3.0.2 on HP-UX 11i...

 
Adam Morris
Occasional Advisor

64 bit gcc 3.0.2 on HP-UX 11i...

Greetings,
I'm using the HP depot for gcc 3.0.2 and have run into an interesting problem...

One line of code (the beta version of Conserver (http://www.conserver.org) console/console.c) is causing problems...

The original line

if ((in_addr_t)-1 == (pPort->sin_addr.s_addr = inet_addr(pcToHost))) { blah }

doesn't work.

If it's changed to
if (-1 == (int)(pPort->sin_addr.s_addr = inet_addr(pcToHost))) {blah}

it does...

if the assignment is moved to prior to the if statement...
pPort->sin_addr.s_addr = inet_addr(pcToHost);
if (-1 == inet_addr(pcToHost)) {blah}

it works, however if the check is done on pPort->sin.addr.s_addr it fails...

pPort->sin_addr.s_addr = inet_addr(pcToHost);
if (-1 == pPort->sin_addr.s_addr) {blah}


If the original code is compiled with debugging on, it works.

Does anyone know if this is a known fault in gcc, a strange bug, or something wrong with the code... (The fact that it works when compiled with debugging on makes me think that it's a bug, not a fault with the code.) There are no compilation errors at all, in any of the scenarios.

inet_addr(pcToHost) returns an in_addr_t. However on failure it returns -1. As in_addr_t is defined as either an unsigned int (64 bit) or an unsigned long (32bit)in /usr/include/netinet/in.h it seems odd that a negative value should be returned in it...

Anyone have any ideas, comments or suggestions?
11 REPLIES 11
Eric Ladner
Trusted Contributor

Re: 64 bit gcc 3.0.2 on HP-UX 11i...

Could be a bug. Might be a change in how expressions are evaluated. Do you have a HP
ANSI C compiler to test it aginst?

I'd run this through the gcc mailing lists and see what you get.

Returning -1 to an unsigned int isn't that uncommon and not really illegal (although, admitedly strange). What it ends up doing is putting all ones in the value (i.e. 11111111 is a one byte number representing -1 if it is signed, 255 if it is not).

If you turned around and printed it out using the spec for an unsigned number, you'd get the max-value for that data type (int, long int, etc.)
harry d brown jr
Honored Contributor

Re: 64 bit gcc 3.0.2 on HP-UX 11i...

Adam,

I'm going to poke a stick in my eye, but here it goes:


I'm not too sure about the casting of "-1" to type "in_addr_t)" (found in the original code):

if ((in_addr_t)-1 == (pPort->sin_addr.s_addr = inet_addr(pcToHost))) { blah }


You "FORCED" the return value of "(pPort->sin_addr.s_addr = inet_addr(pcToHost))" to be of type "INT", hence it can be equated to "-1".


if it's changed to
if (-1 == (int)(pPort->sin_addr.s_addr = inet_addr(pcToHost))) {blah}


Here "inet_addr(pcToHost)" must return an int or doesn't care:

if the assignment is moved to prior to the if statement...
pPort->sin_addr.s_addr = inet_addr(pcToHost);
if (-1 == inet_addr(pcToHost)) {blah}


Here, what happens if you cast "-1" to be of type "in_addr_t"??

pPort->sin_addr.s_addr = inet_addr(pcToHost);
if (-1 == pPort->sin_addr.s_addr) {blah}



Of course I have serious issues about how 3.0.2 was built. The documentation does not clearly define where every thing came from in the paths, like which "as", "ar", "ld", and C compiler was used, etc...


live free or die
harry
Live Free or Die
Adam Morris
Occasional Advisor

Re: 64 bit gcc 3.0.2 on HP-UX 11i...

Thanks for your input so far...

Originally there were no casts in the if statement, and it didn't work. I added a cast to int and it worked...

Reading the header files I had an in_addr_t being cast to int... but in_addr_t is defined as unsigned int. So, casting an int to an int makes it work... Hmmm...

I understand the binary representation of the positive and negative signed integers, and was merely making a side comment on this technically being an invalid return value. In fact, that is perfectly safe in this case as the maximum legal value of output from inet_addr is a 32bit number.

The thing that confuses me is that compiling with the debug flag on suddenly starts it working properly.

I do have access to AnsiC on an HP-UX 11.00 machine, but it gives me LOTS of errors. I was hoping to be able to bypass having to solve these errors... :-) The errors are in the server, and not the client which is giving me so much trouble with gcc. In fact the errors seem to be rather spurious to my reading... (sprintf(character array, format string, variable) gives the errors "warning 604: Pointers are not assignment-compatible.\nwarning 563: Argument #1 is not the correct type.")


Steven Gillard_2
Honored Contributor

Re: 64 bit gcc 3.0.2 on HP-UX 11i...

Another observation - these sorts of "spurious" crashes are very often caused by simple memory handling mistakes.

For example, is the pcToHost buffer large enough to hold whats inside? Has the pPort struct been allocated correctly?

I've run into this a number of times - the code will work fine in some cases because the incorrect memory read doesn't always cause the access violation. Changing the code around like you've been doing or compiling with debug on can mask the problem by changing the way the memory structures are arranged - ie what used to be on a page boundary is no longer and hence the crash doesn't occur.

My feeling is that this is a bug in the code you're compiling, not the compiler itself. And yes, its *very* annoying when the thing doesn't crash when compiled with debug!! :)

Regards,
Steve
H.Merijn Brand (procura
Honored Contributor

Re: 64 bit gcc 3.0.2 on HP-UX 11i...

related: inet_ntoa with gcc/64 is a bug in gcc which has been reported (and confirmed) by the perl5-porters to the GNU gcc maintainers.

Below is the code that works around that bug in the perl core. It might be a lead to a workaround for you:



void
inet_ntoa(ip_address_sv)
SV * ip_address_sv
CODE:
{
STRLEN addrlen;
struct in_addr addr;
char * addr_str;
char * ip_address;
if (DO_UTF8(ip_address_sv) && !sv_utf8_downgrade(ip_address_sv, 1))
croak("Wide character in Socket::inet_ntoa");
ip_address = SvPVbyte(ip_address_sv, addrlen);
if (addrlen == sizeof(addr) || addrlen == 4)
addr.s_addr =
(ip_address[0] & 0xFF) << 24 |
(ip_address[1] & 0xFF) << 16 |
(ip_address[2] & 0xFF) << 8 |
(ip_address[3] & 0xFF);
else
croak("Bad arg length for %s, length is %d, should be %d",
"Socket::inet_ntoa",
addrlen, sizeof(addr));
/* We could use inet_ntoa() but that is broken
* in HP-UX + GCC + 64bitint (returns "0.0.0.0"),
* so let's use this sprintf() workaround everywhere. */
New(1138, addr_str, 4 * 3 + 3 + 1, char);
sprintf(addr_str, "%d.%d.%d.%d",
((addr.s_addr >> 24) & 0xFF),
((addr.s_addr >> 16) & 0xFF),
((addr.s_addr >> 8) & 0xFF),
( addr.s_addr & 0xFF));
ST(0) = sv_2mortal(newSVpvn(addr_str, strlen(addr_str)));
Safefree(addr_str);
}
Enjoy, Have FUN! H.Merijn
Adam Morris
Occasional Advisor

Re: 64 bit gcc 3.0.2 on HP-UX 11i...

Thanks Steven,
But, there is nothing wrong with this segment of code...
The pcToHost buffer is large enough to hold what's inside. The pPort struct has been allocated correctly... When I ran it through the debugger the memory all showed exactly what I expected it to show. I originally didn't run it through wdb, but added in lots of debug statements to print out the values of key variables at various points in this routine... I had to modify this if statement to do that, but if the check was (-1 == pPort->sin_addr.s_addr) then it failed. pPort is a pointer to a sockaddr_in returned by inet_addr(pcToHost). in_addr_t is defined in /usr/include/netinet/in.h as...
typedef unsigned int in_addr_t
in_addr is defined as
struct in_addr {
in_addr_t s_addr;
};
and sockaddr_in is defined as
struct sockaddr_in {
sa_family_t sin_family;
in_port_t sin_port;
struct in_addr sin_addr;
unsigned char sin_zero[8];
};
or
struct sockaddr_in {
short sin_family;
u_short sin_port;
struct in_addr sin_addr;
char sin_zero[8];
};

either way pPort->sin_addr.s_addr is a valid construct. It should return an in_addr_t which in the 64 bit case is simply an unsigned int. So the comparison between -1 and an unsigned int should succeed. This is a fairly frequent construct in TCP/IP programming, and this code looks like a text book example to me (some of the other code in this package can look a bit hairy... but...)

After thinking about it for a bit, I've just compiled the client only under AnsiC on an HP-UX 11.00 machine (64bit, no debug code) and it works perfectly. This looks even more like a compiler error to me.

I'll try extracting the relevant code into a small sample program that does nothing useful and see whether that compiles...

Thanks for the info Procura, I already have several workarounds... and I heard from the maintainer of conserver that he is going to implement one of them (taking the assignment out of the if statement for the moment) so that it works...

I've also come across the inet_ntoa error but hadn't realised as it's only used in internal debugging of conserver... :-)

Thanks,
Adam



Adam Morris
Occasional Advisor

Re: 64 bit gcc 3.0.2 on HP-UX 11i...

I've written a very short program to test this, compiled it under 64bit gcc and it works only when optimisation is turned off.

# gcc -O -o bugtest -Wall bugtest.c
# ./bugtest
pPort check fails in main
pPort->sin_addr.s_addr: -1
sPort.sin_addr.s_addr: -1
inet_addr(pcToHost): -1
pcToHost: www.mutant.net
# gcc -o bugtest -Wall bugtest.c
# ./bugtest
pPort check works in main
pPort->sin_addr.s_addr: -1
sPort.sin_addr.s_addr: -1
inet_addr(pcToHost): -1
pcToHost: www.mutant.net
#

and here is bugtest.c

#include
#include
#include
#include

int
main()
{
char pcToHost[]="www.mutant.net";
struct sockaddr_in *pPort;
struct sockaddr_in sPort;
pPort = &sPort;
if (-1 == (pPort->sin_addr.s_addr = inet_addr(pcToHost))) {
printf("pPort check works in main\n");
} else {
printf("pPort check fails in main\n");
}
printf("pPort->sin_addr.s_addr: %i\n", pPort->sin_addr.s_addr);
printf("sPort.sin_addr.s_addr: %i\n", sPort.sin_addr.s_addr);
printf("inet_addr(pcToHost): %i\n", inet_addr(pcToHost));
printf("pcToHost: %s\n", pcToHost);
return(0);
}

I guess I'll report this to the GCC folks... Thanks for everyone's help and comments.

Adam
Jack Cummings
Occasional Contributor

Re: 64 bit gcc 3.0.2 on HP-UX 11i...

The good news is that this bug appears to be fixed in gcc-3.1..





[cummings@serapis]bt$ gcc -o test test.c
[cummings@serapis]bt$ ./test
pPort check works in main
pPort->sin_addr.s_addr: -1
sPort.sin_addr.s_addr: -1
inet_addr(pcToHost): -1
pcToHost: www.mutant.net
[cummings@serapis]bt$ gcc -O2 -o test test.c
[cummings@serapis]bt$ ./test
pPort check works in main
pPort->sin_addr.s_addr: -1
sPort.sin_addr.s_addr: -1
inet_addr(pcToHost): -1
pcToHost: www.mutant.net
[cummings@serapis]bt$ gcc -v
Reading specs from /home/cummings/hppa2.0w-hp-hpux11.00/bin/../lib/gcc-lib/hppa64-hp-hpux11.00/3.1/specs
Configured with: ../configure --prefix=/home/cummings/packages/gcc -exec-prefix=/home/cummings/packages/gcc/hppa2.0w-hp-hpux11.00 --enable-languages=c,c++,f77,objc --host=hppa64-hp-hpux11.00 --target=hppa64-hp-hpux11.00 --with-gnu-as --with-as=/pkg/binutils/binutils__v2.11.2.dist/binutils/bin/as --with-gnu-ld --with-ld=/pkg/binutils/binutils__v2.11.2.dist/binutils/bin/ld
Thread model: single
gcc version 3.1 20011119 (experimental)
[cummings@serapis]bt$ file test
test: ELF-64 executable object file - PA-RISC 2.0 (LP64)
Adam Morris
Occasional Advisor

Re: 64 bit gcc 3.0.2 on HP-UX 11i...

FYI:- The GCC guys responded..
"This is closely related to 5169, 5185 and 5264, though slightly different.

It works with the current development sources (and I expect the 3.1 branch),
but that's more by accident than by design as far as I can tell."

So there you have it.

Adam
H.Merijn Brand (procura
Honored Contributor

Re: 64 bit gcc 3.0.2 on HP-UX 11i...

HP-UX does not seem to be in the target area of GNU-gcc :(

I've managed to build binutils-2.12 in 64bit mode using that same gcc-3.02./64 and together with gcc-3.0.2/64 I rebuilt gcc-3.0.4/64 and I got stuck with an internal gcc error. I've posted a bug report with gcc, but got no reply - other than a receipt confirmation - yet.

3.1.x? Is there a snapshot (other than through cvs) downloadable yet?
Enjoy, Have FUN! H.Merijn
Jack Cummings
Occasional Contributor

Re: 64 bit gcc 3.0.2 on HP-UX 11i...


Building a 64 bit gcc for hpux is ... painful.

Mainly because you have to first build a cross toolchain from 32->64 bit, and then a cross compiler.

You can then use the cross compiler to build a native 64 bit compiler, but that is of questionable value, as it will run slower than the cross compiler.

If you want to cheat a bit, you can start with the 64 gcc-3.0.1 binaries I created at http://ice.mudshark.org/ ..

--Jack