Subject: gcc4 lossage on mips kernels with semi-packed struct
To: None <tech-toolchain@netbsd.org>
From: Simon Burge <simonb@wasabisystems.com>
List: tech-toolchain
Date: 05/16/2006 12:22:01
Hi folks,

In nfs/nfs_bootdhcp.c we have struct bootpcontext which is:

	struct bootpcontext {
		int xid;
		u_char *haddr; 
		u_char halen; 
		struct bootp *replybuf;
		int replylen;
	#ifdef NFS_BOOT_DHCP
		char expected_dhcpmsgtype, dhcp_ok;
		struct in_addr dhcp_serverip; 
	#endif
	};

where struct in_addr is effectively:

	struct in_addr {
		uint32_t s_addr;
	} __attribute__((__packed__));

Under both gcc3 and gcc4, dhcp_serverip is at offset 22 in struct
bootpcontext.

In bootpcheck() there is:

                        memcpy(&bpc->dhcp_serverip.s_addr, p,
                              sizeof(bpc->dhcp_serverip.s_addr));

On gcc3 this generates:

        lwl     $2,3($4)
        lwr     $2,0($4)
        swl     $2,25($18)
        swr     $2,22($18)

where swl and swr are unaligned stores.  Life is good.

On gcc4 this generates:

        lwl     $2,3($4)
        lwr     $2,0($4)
        sw      $2,22($17)

where sw is an aligned store, which promptly panics when it tries
to store at an unaligned address.

A workaround is to simply reverse the last two lines in struct
bootpcontext, so that dhcp_serverip is aligned nicely.

Is gcc4 doing something wrong here, or is it a problem with the
structure definitions?  I don't want to just swap the lines around
in the struct without understanding what's at fault here.

Simon.
--
Simon Burge                                   <simonb@wasabisystems.com>
NetBSD Development, Support and Service:   http://www.wasabisystems.com/