[comp.unix.xenix] XENIX 386 Compiler Bug: arrays/structs larger than 64k

skip@pwcmrd.com (Skip Gilbrech) (12/13/88)

I ran into the following Xenix 386 compiler bug while testing code originally
written for a Sun 386i (which worked fine there) on my home system.

The original code was an implementation of a circular buffer (size: about
174K) running in shared memory.  Under Xenix, the variables used to hold
the buffer pointers ended up in the middle of the main buffer, and of course
were overwritten during buffering, resulting in a core dump.

The original data structure was as follows:

#define DATASIZE		0x100
#define MAX_TO_ENQUEUE		500

typedef struct DATA {		/* structure for actual data buffers */
    unsigned char buf[DATASIZE];
} DATA;

typedef struct SHMEM {		/* structure for all of shared memory */
    DATA Bufs[MAX_TO_ENQUEUE+1];	/* buffers for data */
    DATA * PutPtr;		/* ptr to next buf for enqueing */
    DATA * GetPtr;		/* ptr to next buf for dequeing */
    DATA * Top;			/* ptr above last data buffer */
    int Count;				/* count of enqueued buffers */
    key_t InitSig;			/* Initialization signature */
    unsigned char AccessFlag;		/* flag to control access */
} SHMEM;

SHMEM * ShMP = (SHMEM *)0;		/* will point to shared memory */

It turned out that the compiler was sticking ShMP->PutPtr and all following
variables right in the middle of ShMP->Bufs, exactly 64K beneath where they
belonged.  I tried various ways of simplifying the problem (not using
shared mem, using an explicitly allocated SHMEM struct rather than a pointer,
etc.), but the bug was consistant & persistant:  it went away when sizes got
below 64K & came back as they were increased (another 286 legacy??).

Is this a known bug?  If not, I'll certainly report it to SCO as it could
be pretty hard to work around under certain circumstances.

I'm running XENIX 2.2.6 (thanks to VP/ix) but the 386 compiler is the one
that came with the original 386 upgrade.  The code below is a fairly minimal
illustration of the problem.  On my system it produces the following output:

sizeof(Data1): 00010000, sizeof(Data2): 00010004

Data1.buf: 01880784, sizeof(Data1.buf): 0000FFFC, Data1.Top: 01890780
&Data1.Top: 01890780, (char *)&Data1.Top - Data1.buf: 0000FFFC
Data2.buf: 01890784, sizeof(Data2.buf): 00010000, Data2.Top: 018A0784
&Data2.Top: 01890784, (char *)&Data2.Top - Data2.buf: 00000000

Note that the address of Data2.Top is the same as Data2.buf when it should
be 64K higher...

/* Test Xenix 386 compiler bug concerning arrays/structures larger than 64k */

/* #pragma pack(1)		/* try varying alignment */

#define NBYTES1	(65536 - 4)	/* try different values around 64k */
#define NBYTES2	(65536)

struct DATA1 {
    char buf[NBYTES1];
    char * Top;
} Data1;

struct DATA2 {
    char buf[NBYTES2];
    char * Top;
} Data2;

main()
{
    Data1.Top = Data1.buf + sizeof(Data1.buf);	/* these come out ok */
    Data2.Top = Data2.buf + sizeof(Data2.buf);

    printf("sizeof(Data1): %08X, sizeof(Data2): %08X\n\n",
	   sizeof(Data1), sizeof(Data2));

    printf("Data1.buf: %08X, sizeof(Data1.buf): %08X, Data1.Top: %08X\n",
	   Data1.buf, sizeof(Data1.buf), Data1.Top);
    printf("&Data1.Top: %08X, (char *)&Data1.Top - Data1.buf: %08X\n",
	   &Data1.Top, (char *)&Data1.Top - Data1.buf);
    printf("Data2.buf: %08X, sizeof(Data2.buf): %08X, Data2.Top: %08X\n",
	   Data2.buf, sizeof(Data2.buf), Data2.Top);
    printf("&Data2.Top: %08X, (char *)&Data2.Top - Data2.buf: %08X\n",
	   &Data2.Top, (char *)&Data2.Top - Data2.buf);
}
-- 
Skip Gilbrech                           UUCP: uunet!pwcmrd!skip
PaineWebber, NYC                              attmail!skipnyc!skip