Bus errors due to structure padding 32 -> 64-bit porting

Bus errors due to structure padding 32 -> 64-bit porting

Post by Sarat Kum » Sun, 06 Jan 2002 21:09:52



Hai

The structure padding implemented in Solaris8(sparcv9) has been giving
problems for us while migrating from 32-bit Solaris6 to 64-bit
solaris8 . The code has been working fine when compiled in 32-bit
mode.

we had a structure

struct XXX
{
  struct XXX_hdr;   4 bytes
  int i;            4 bytes
  void * addr;      8 bytes in solaris 8

Quote:}

struct XXX_hdr {
   enum type {  ......}   4 bytes

Quote:}

This structure was giving a bus error because of  structure padding
and it was required to move the void * addr  to the top in the
structure XXX. But this was again giving us a problem because our code
type casts the pointer to the struct XXX to a pointer to the struct
XXX_hdr as follows.

struct XXX * x;
struct XXX_hdr * x_hdr;

x_hdr = (XXX_hdr *) x;  which causes the first four bytes of the XXX
structure(ie first 4 bytes of addr ) to get passed thus resulting in
wrong values.

Is there any way of preventing this padding to occur or any
alternative to the problem. Hope I was Clear.

Thanks and Regards
Sarat

 
 
 

Bus errors due to structure padding 32 -> 64-bit porting

Post by Steve Bellen » Sun, 06 Jan 2002 23:46:09




>Hai

>The structure padding implemented in Solaris8(sparcv9) has been giving
>problems for us while migrating from 32-bit Solaris6 to 64-bit
>solaris8 . The code has been working fine when compiled in 32-bit
>mode.

>we had a structure

>struct XXX
>{
>  struct XXX_hdr;   4 bytes
>  int i;            4 bytes
>  void * addr;      8 bytes in solaris 8
>}

>struct XXX_hdr {
>   enum type {  ......}   4 bytes
>}

>This structure was giving a bus error because of  structure padding

It is not clear to me how this struct could give a bus error? You
must be doing something `bad' with the structure for this to cause
you problems.

Quote:>and it was required to move the void * addr  to the top in the
>structure XXX. But this was again giving us a problem because our code
>type casts the pointer to the struct XXX to a pointer to the struct
>XXX_hdr as follows.

>struct XXX * x;
>struct XXX_hdr * x_hdr;

>x_hdr = (XXX_hdr *) x;  which causes the first four bytes of the XXX
>structure(ie first 4 bytes of addr ) to get passed thus resulting in
>wrong values.

Well you could change the cast to
x_hdr = (XXX_hdr*) &(x.XXX_hdr); // or whatever you call this field.

Quote:

>Is there any way of preventing this padding to occur or any
>alternative to the problem. Hope I was Clear.

>Thanks and Regards
>Sarat

--
http://www.math.fsu.edu/~bellenot
bellenot <At/> math.fsu.edu
+1.850.644.7189 (4053fax)

 
 
 

Bus errors due to structure padding 32 -> 64-bit porting

Post by Casper H.S. Dik - Network Security Engine » Sun, 06 Jan 2002 21:44:24


[[ PLEASE DON'T SEND ME EMAIL COPIES OF POSTINGS ]]


>struct XXX
>{
>  struct XXX_hdr;   4 bytes
>  int i;            4 bytes
>  void * addr;      8 bytes in solaris 8
>}
>struct XXX_hdr {
>   enum type {  ......}   4 bytes
>}
>This structure was giving a bus error because of  structure padding
>and it was required to move the void * addr  to the top in the
>structure XXX. But this was again giving us a problem because our code
>type casts the pointer to the struct XXX to a pointer to the struct
>XXX_hdr as follows.

That shouldn't generally be a problem.

But now that you've moved the pointer (why?) you can no longer do the
cast.  (If XXX_hdr is 4 bytes, the pointer causes no padding)
Struct XXX requires 8 byte alignment, struct XXX_hdr requires only 4
bytes, so casting the other way and dereferencing the "void *addr" will
give problems but the void * wouldn't exist; memory returned from malloc()
will not give problems in that way;

Quote:>struct XXX * x;
>struct XXX_hdr * x_hdr;
>x_hdr = (XXX_hdr *) x;  which causes the first four bytes of the XXX
>structure(ie first 4 bytes of addr ) to get passed thus resulting in
>wrong values.

So keep the header at start of the structure.

Quote:>Is there any way of preventing this padding to occur or any
>alternative to the problem. Hope I was Clear.

Your cut-down example has no padding.

In otehr cases padding can not be avoided other than by carefully
rearraging the members; but obviously your code depends on the header
to be first.

Why is padding bad?

Casper
--
Expressed in this posting are my opinions.  They are in no way related
to opinions held by my employer, Sun Microsystems.
Statements on Sun products included here are not gospel and may
be fiction rather than truth.

 
 
 

Bus errors due to structure padding 32 -> 64-bit porting

Post by Stefaan A Eeckel » Mon, 07 Jan 2002 02:18:37


On 5 Jan 2002 04:09:52 -0800


> The structure padding implemented in Solaris8(sparcv9) has been giving
> problems for us while migrating from 32-bit Solaris6 to 64-bit
> solaris8 . The code has been working fine when compiled in 32-bit
> mode.

> we had a structure

> struct XXX
> {
>   struct XXX_hdr;   4 bytes
>   int i;            4 bytes
>   void * addr;      8 bytes in solaris 8
> }

> struct XXX_hdr {
>    enum type {  ......}   4 bytes
> }

> This structure was giving a bus error because of  structure padding
> and it was required to move the void * addr  to the top in the
> structure XXX. But this was again giving us a problem because our code
> type casts the pointer to the struct XXX to a pointer to the struct
> XXX_hdr as follows.

> struct XXX * x;
> struct XXX_hdr * x_hdr;

> x_hdr = (XXX_hdr *) x;  which causes the first four bytes of the XXX
> structure(ie first 4 bytes of addr ) to get passed thus resulting in
> wrong values.

When was it giving you a bus error? The struct XXX you mention
doesn't require any padding when compiled for 64 bits. In the
absence of the exact code that caused the bus error, it's hard
to see how moving the "void *addr" to the top of the structure
could have made any difference.
I tried the following piece of code with Sun C 5.2(*):

#include <stdlib.h>
#include <unistd.h>
#include <stdio.h>

enum hdr_type {BIRD,INSECT,MAMMAL,REPTILE};
struct XXX_hdr {
        int type;

Quote:} hdr;

struct XXX {
        struct XXX_hdr hdr;
        int i;
        void *addr;

Quote:} xxx;

int main() {
        struct XXX_hdr *hdrp = (struct XXX_hdr *)&xxx;

        printf("The size of hdr is %d\n", sizeof(hdr));
        printf("The size of xxx is %d\n", sizeof(xxx));
        printf("The size of xxx.addr is %d\n", sizeof(xxx.addr));
        xxx.addr = &xxx;
        printf("Sizeof long is %d\n", sizeof(long));
        printf("Just set xxx.addr to 0x%p\n", (long)xxx.addr);
        xxx.i = 12;
        printf("Just set xxx.i to %d\n", xxx.i);
        xxx.hdr.type = MAMMAL;
        printf("Just set xxx.hdr.type to %d\n", xxx.hdr.type);
        printf("First member of struct is %d\n", hdrp->type);

Quote:}

Compiling this as a 32-bit executable gives:

ultra~/Stuff[324] cc str3264.c -o str3264
ultra~/Stuff[325] ./str3264
The size of hdr is 4
The size of xxx is 12
The size of xxx.addr is 4
Sizeof long is 4
Just set xxx.addr to 0x20c2c
Just set xxx.i to 12
Just set xxx.hdr.type to 2
First member of struct is 2

And as a 64-bit executable gives:

ultra~/Stuff[326] cc -xtarget=ultra -xarch=v9 str3264.c -o str3264
ultra~/Stuff[327] ./str3264
The size of hdr is 4
The size of xxx is 16
The size of xxx.addr is 8
Sizeof long is 8
Just set xxx.addr to 0x1001010b0
Just set xxx.i to 12
Just set xxx.hdr.type to 2
First member of struct is 2

Quote:> Is there any way of preventing this padding to occur or any
> alternative to the problem.

Without the original code, I can't tell where you'd get any
padding in the 64-bit version. Certainly none that would cause
"address of the structure == address of the first member" to
become invalid. Obviously, if struct XXX_hdr is more complex
than a simple int, padding will occur:

....
struct XXX_hdr {
        int type;
        char foo;

Quote:} hdr;

....

ultra~/Stuff[342] cc -xtarget=ultra -xarch=v9 str3264.c -o str3264
ultra~/Stuff[343] ./str3264
The size of hdr is 8
The size of xxx is 24
The size of xxx.addr is 8
Sizeof long is 8
Just set xxx.addr to 0x1001010f0
Just set xxx.i to 12
Just set xxx.hdr.type to 2
First member of struct is 2
ultra~/Stuff[344]

but not in struct XXX. The address of the structure is still
the address of the first member. BTW, the 32-bit version also
pads XXX_hdr to 8 bytes.

Quote:> Hope I was Clear.

Please post the code that causes grief, and details about the build
environment.

(*) Your use of "enum" in a struct is a syntax error in 'C'. It's
OK in C++, but I cannot see how it would serve any purpose because
"enum" is declarative only, and thus doesn't reserve any storage.

--
Stefaan (GPG Fingerprint 25D8 551B 4C0F BF73 3283 21F1 5978 D158 7539 76E4)
--
"Object-oriented programming is an exceptionally bad idea which
 could only have originated in California." --Edsger Dijkstra

  application_pgp-signature_part
< 1K Download
 
 
 

Bus errors due to structure padding 32 -> 64-bit porting

Post by Sarat Kum » Wed, 09 Jan 2002 16:00:06


Hai

I think the bus error is not due to structure padding but due to some
other reason. I have written some sample program and the bus error
occurs in the 64-bit mode on sparcv9 , solaris8 but not in the 32-bit
mode on the same machine.
The code involves shared memory segments and pipes . Exception
conditions havent been taken care of . Any pointers to solve this
problem would be helpful.

There are two files server.C and client.C . server is run first and
then the client.

server.C

#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <iostream.h>
#include <unistd.h>
#include <fcntl.h>
#include <stdio.h>
#include <errno.h>
#include <sys/stat.h>

enum ESS_Type {
   SR_USEENVREPLY

Quote:};

struct ESS_hdr
{
    ESS_Type type;

Quote:};

struct ESS_UseEnvMsg
{
  ESS_hdr hdr;
  key_t  segKey;
  void * segAddress;
Quote:};

const void * const SHMADDRESSBASE = (void*)0xEA000000;
static unsigned envSegmentSize = 2048 * 1024;
main()
{
int shmid,flag,fd1,fd;
char buf[20];
key_t key = 0x10;

if(mknod("myfifo",010666,0) < 0) cout << "failed creating myfifo";
if(mknod("hisfifo",010666,0) < 0) cout << "failed creating hisfifo";
if ((fd = open("myfifo",O_RDWR))<0) cout << "failed opening myfifo in
server";

read(fd,(void *) &buf,20);   // wait for request from the client
printf("%s\n",buf);

//Create Shared memory

void * shmAdd = (void *) ((char *) SHMADDRESSBASE);
 const int shmFlg = 0644 | IPC_CREAT | IPC_EXCL;
shmid=shmget(key,envSegmentSize,shmFlg);
void * seg = (char *) shmat(shmid,(char *) shmAdd,0);

// copy the shared memory details into the structure.
 ESS_UseEnvMsg replyMsg;
 memset((void*)&replyMsg, 0, sizeof(replyMsg));
 replyMsg.hdr.type = SR_USEENVREPLY;
 replyMsg.segKey = key;
 replyMsg.segAddress = shmAdd;
if ((fd1 = open("hisfifo",O_RDWR))<0) cout << "failed to open hisfifo
in server";
write(fd1,(char *) &replyMsg, sizeof(replyMsg));  // Send the
structure to client

Quote:}

client.C

#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <stdio.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <iostream.h>

enum ESS_Type {
   SR_USEENVREPLY};
struct ESS_hdr
{
    ESS_Type type;

Quote:};

struct ESS_UseEnvMsg
{
  ESS_hdr hdr;
  key_t  segKey;
  void * segAddress;

Quote:};

main()
{
int shmid,flag,fd,fd1;
char msgBuf[80];
char buf[20];
key_t envSegKey;
void * envSegAddress;

strcpy(buf,"sent struct");
if ((fd = open("myfifo",O_WRONLY))<0) cout << "failed to open myfifo
in client";
write(fd,(void *)&buf,20);

if ((fd1 = open("hisfifo",O_RDONLY))<0) cout << "failed to open
hisfifo in client";
read(fd1,(void *) msgBuf,16); // read the structure sent by server
//     ESS_hdr *  replyHdr = (ESS_hdr*)msgBuf;
       ESS_UseEnvMsg *msg = (ESS_UseEnvMsg*)msgBuf;
       envSegKey = msg->segKey;
       envSegAddress = msg->segAddress; //Bus error occurs here

//attach to the client the shared memory

shmid=shmget(envSegKey,100,IPC_CREAT|0666);
char * ptr = (char *) shmat(shmid,(char *)envSegAddress,0);
//printf("%p \n",ptr);

Quote:}

The files were compiled with
 CC -xarch=v9 -xarch=v9a -g -o server server.C and
 CC -xarch=v9 -xarch=v9a -g -o client client.C and with      
LD_LIBRARY_PATH_64=/opt/SUNWspro/WS6U2/lib/v9

Thanks and Regards
Sarat

 
 
 

Bus errors due to structure padding 32 -> 64-bit porting

Post by Casper H.S. Dik - Network Security Engine » Wed, 09 Jan 2002 16:52:33


[[ PLEASE DON'T SEND ME EMAIL COPIES OF POSTINGS ]]


>char msgBuf[80];
>//     ESS_hdr *  replyHdr = (ESS_hdr*)msgBuf;
>       ESS_UseEnvMsg *msg = (ESS_UseEnvMsg*)msgBuf;
>       envSegKey = msg->segKey;
>       envSegAddress = msg->segAddress; //Bus error occurs here

You're assuming that msgBuf is properly aligned to contain
a "msg".

That is not the case.

Casper
--
Expressed in this posting are my opinions.  They are in no way related
to opinions held by my employer, Sun Microsystems.
Statements on Sun products included here are not gospel and may
be fiction rather than truth.

 
 
 

Bus errors due to structure padding 32 -> 64-bit porting

Post by Stefaan A Eeckel » Wed, 09 Jan 2002 22:54:20


On 7 Jan 2002 23:00:06 -0800


> I think the bus error is not due to structure padding but due to some
> other reason.

The alignment problem stems from the fact that you don't
given enough clues to the compiler to achieve the 8-byte
alignment required for longs and pointers.

Quote:> I have written some sample program and the bus error
> occurs in the 64-bit mode on sparcv9 , solaris8 but not in the 32-bit
> mode on the same machine.
> The code involves shared memory segments and pipes . Exception
> conditions havent been taken care of . Any pointers to solve this
> problem would be helpful.

> client.C

< snippage>

Quote:

> main()
> {
> int shmid,flag,fd,fd1;

char msgBuf[80]; // aligns at *4
struct ESS_UseEnvMsg msgBuf1;   // aligns at *8

Quote:> char buf[20];
> key_t envSegKey;
> void * envSegAddress;

> strcpy(buf,"sent struct");
> if ((fd = open("myfifo",O_WRONLY))<0) cout << "failed to open myfifo
> in client";
> write(fd,(void *)&buf,20);

> if ((fd1 = open("hisfifo",O_RDONLY))<0) cout << "failed to open
> hisfifo in client";
> read(fd1,(void *) msgBuf,16); // read the structure sent by server
> //     ESS_hdr *  replyHdr = (ESS_hdr*)msgBuf;
>        ESS_UseEnvMsg *msg = (ESS_UseEnvMsg*)msgBuf;
>        envSegKey = msg->segKey;

        fprintf(stderr, "Address of msgBuf1.segAddress: 0x%p (align8: %d)\n",
                        &msgBuf1.segAddress,
                        (unsigned long)&msgBuf1.segAddress % 8);
        envSegAddress = msgBuf1.segAddress;
        fprintf(stderr, "Address of msg->segAddress: 0x%p (align8: %d)\n",
                        &(msg->segAddress),
                        (unsigned long)&(msg->segAddress) % 8);

Quote:>        envSegAddress = msg->segAddress; //Bus error occurs here

> //attach to the client the shared memory

> shmid=shmget(envSegKey,100,IPC_CREAT|0666);
> char * ptr = (char *) shmat(shmid,(char *)envSegAddress,0);
> //printf("%p \n",ptr);
> }

$ ./client
sent struct
Address of msgBuf1.segAddress: 0xffffffff7fffec30 (align8: 0)
Address of msg->segAddress: 0xffffffff7fffec64 (align8: 4)
Bus error (core dumped)
$

When you create an array of characters on the stack, it
will not be properly aligned for an access to a long, as
shown above. You need to ensure 8-byte alignment not 4-byte
alignment as on 32-bit SPARCs.
Either use the structure, or use malloc (it returns
addresses that are aligned for use with the most restrictive
data type).

--
Stefaan (GPG Fingerprint 25D8 551B 4C0F BF73 3283 21F1 5978 D158 7539
76E4)--
"Object-oriented programming is an exceptionally bad idea which
 could only have originated in California." --Edsger Dijkstra

  application_pgp-signature_part
< 1K Download
 
 
 

Bus errors due to structure padding 32 -> 64-bit porting

Post by Sarat Kum » Wed, 09 Jan 2002 23:53:10


Hai casper
Thanks for your reply.What could I  do to rectify this. This was not
giving any error while running the 32-bit version of the same program.

Thanks and Regards
Sarat


> [[ PLEASE DON'T SEND ME EMAIL COPIES OF POSTINGS ]]


> >char msgBuf[80];

> >//     ESS_hdr *  replyHdr = (ESS_hdr*)msgBuf;
> >       ESS_UseEnvMsg *msg = (ESS_UseEnvMsg*)msgBuf;
> >       envSegKey = msg->segKey;
> >       envSegAddress = msg->segAddress; //Bus error occurs here

> You're assuming that msgBuf is properly aligned to contain
> a "msg".

> That is not the case.

> Casper

 
 
 

Bus errors due to structure padding 32 -> 64-bit porting

Post by ultraspa.. » Thu, 10 Jan 2002 02:22:12



Quote:>Any pointers to solve this problem would be helpful.

see below.

Quote:>main()
>{
>char msgBuf[80];
...
>read(fd1,(void *) msgBuf,16); // read the structure sent by server
>//     ESS_hdr *  replyHdr = (ESS_hdr*)msgBuf;
>       ESS_UseEnvMsg *msg = (ESS_UseEnvMsg*)msgBuf;

casts are evil, if you had used the "-v" compiler option it may have even
complained about these.  i would guess that "msgBuf", a simple char array,
isn't suitably aligned for a ESS_UseEnvMsg structure and that...

Quote:>       envSegKey = msg->segKey;
>       envSegAddress = msg->segAddress; //Bus error occurs here

...one of these is where you are getting the bus error due to the
alignment problem.

you should have provided the location of the bus error, any
de* shows you the instructions or lines of code where
it happens.

 
 
 

Bus errors due to structure padding 32 -> 64-bit porting

Post by Casper H.S. Dik - Network Security Engine » Thu, 10 Jan 2002 00:22:17


[[ PLEASE DON'T SEND ME EMAIL COPIES OF POSTINGS ]]


>Thanks for your reply.What could I  do to rectify this. This was not
>giving any error while running the 32-bit version of the same program.

You were lucky.

If you use casts, you can have problems.

Quote:>> >char msgBuf[80];

(Please don't top-post)

Instead of char msgBuf[] use something like:

        union {
                ESS_hdr         replyHdr;
                ESS_UseEnvMsg   msg;
                char            msgBuf[80];
        } myMsg;

No casts needed, proper size and alignment.

Casper
--
Expressed in this posting are my opinions.  They are in no way related
to opinions held by my employer, Sun Microsystems.
Statements on Sun products included here are not gospel and may
be fiction rather than truth.

 
 
 

1. Solaris 9 installed with 32 & 64 bit supports but boots in 32 bit mode

Hi every one,

I have installed Solaris 9 on a Sun Sparc E220R. When I installed, it asked
me whether you want 32 bit or 64/32 bit support. I select 32/64 bit support
and I was assuming that it will boot in 64 bit, but when system booted after
the installation, it was in 32 bit mode.

Can I force the system to boot in 64 bit mode or there is any other way ...

Please advise.

Regards and thanks in advance for the advise.

Abdul Majid

2. need help with ncpmount?

3. 32 bit -> 64 bit Move

4. Flash4 for Linux (RedHat 6.0/Netscape Communicator 4.6.1)

5. How 32 bit driver can be ported to 64 bit driver?

6. Telnet Firewall

7. performance of runing 32/64 bit program in 64 bit kernel.

8. Redat 4.1 Upgrade

9. Porting 32 bit app to 64 bits ?

10. 32 bit to 64 bit porting ...

11. 32-bit Core files on 64-bit Sysetm

12. 64-bit Solaris 7: wasn't Solaris 2.6 also 32-bit?

13. 64-bit to 32-bit OS change