f



Diffs between OpenBSD 3.9 gcc 3.3.5 <-> Linux 2.6 gcc 4.0 ?

I'm hoping some of you experienced OpenBSD users may be able to provide
some insight for a noviate like myself about what should be a simple C
problem (but it's not simple until it's fixed :-).

Here's the situation: I have a medium-sized program in C that I wrote
on Linux 2.6 using gcc 3.3.6, now ported to gcc 4.0.  It intentionally
has no malloc/free calls; instead, it uses arrays to pass data between
routines (yes I know the reasons why this shouldn't be done).

The calling routine passes the array addresses to the called
subroutine.

But the callee doesn't get the correct address; instead it gets some
different number, so the program crashes immediately upon entering the
called routine.  A typical call is like so:

typedef unsigned char UINT8;
typedef int SINT32;

-------------------------------------------- caller

SINT32 sendreqexe(SINT32 reqexelen, UINT8 *exefile, SINT32 exefileLen,
                  SINT32 csockfd) {

    UINT8       packed[REQEXEMSG_LEN];   // about 1 Mb

    UINT8       sessEKey[LTKEY_LEN];     // 16 bytes
    UINT8       sessHKey[LTKEY_LEN];     // 16 bytes
    UINT8       padKey[MAXEXESIZE];      // about 1 Mb

    SINT32      err, packedLen = -1;
    <other vars elided>

    // ..... call to fractious routine:

    err = buildReqExeMsg(packed, sizeof(packed),
                         sessEKey, sessHKey, padKey,
                         reqexelen, exefile, exefileLen,
                         &packedLen);

-------------------------------------------- called

SINT32 buildReqExeMsg(UINT8 *packed, SINT32 packedbuflen,
                      UINT8 *sessEKey, UINT8 *sessHKey,
                      UINT8 *padKey, SINT32 padKeyLen,
                      UINT8 *exefile, SINT32 exefileLen,
                      SINT32 *packedLen) {
		      ....

Here are the values of the passed vars inside the caller:

(gdb) p &packed
$6 = (UINT8 (*)[1000488]) 0xcf8f4cf0
p sizeof (packed)
$3 = 1000488
(gdb) p &sessEKey
$7 = (UINT8 (*)[16]) 0xcf9e9130
(gdb) p &sessHKey
$8 = (UINT8 (*)[16]) 0xcf9e9120
(gdb) p &padKey
$10 = (UINT8 (*)[1000000]) 0xcf9e9140
(gdb) p reqexelen
$4 = 25107
(gdb) p exefile
$9 = (UINT8 *) 0xcfbd1854 "/tmp/rc/adm/daz2"
(gdb) p exefileLen
$5 = 16

And here's what the callee gets, all the pointers are changed:

(gdb) p packed
Cannot access memory at address 0xcf617a3c  (should be 0xcf8f4cf0)
(gdb) p packedbuflen
$11 = 1000488                               (correct)
(gdb) p sessEKey
Cannot access memory at address 0xcf617a38  (should be 0xcf9e9130)
(gdb) p sessHKey
Cannot access memory at address 0xcf617a34  (should be 0xcf9e9120)
(gdb) p padKey
Cannot access memory at address 0xcf617a30  (should be 0xcf9e9140)
(gdb) p padKeyLen
$12 = 25107                                 (correct)
(gdb) p exefile
Cannot access memory at address 0xcf617a2c  (should be 0xcfbd1854)
(gdb) p exefileLen
$13 = 16                                    (correct)

--> Synopsis: All the pointer addresses are incorrectly transferred,
but all the integers come through OK.  What's happening here?

Typically, when mysterious things like this happen, it's because of
some memory problem.  But this code works fine in Linux, and passes
valgrind's memcheck with no problems.

Is there something special about the stack size in OpenBSD?  Some of
the arrays I use are large 1Mb, but reducing their size didn't help.
The total size of the arrays is < 4 Mb.

So if anyone has ANY ideas, please let me know !  Thanks !

Jim

0
n33ed
9/22/2006 11:03:54 PM
comp.unix.bsd.openbsd.misc 3191 articles. 1 followers. Post Follow

3 Replies
667 Views

Similar Articles

[PageSpeed] 50

n33ed wrote:
>     UINT8       packed[REQEXEMSG_LEN];   // about 1 Mb
> 
>     UINT8       sessEKey[LTKEY_LEN];     // 16 bytes
>     UINT8       sessHKey[LTKEY_LEN];     // 16 bytes
>     UINT8       padKey[MAXEXESIZE];      // about 1 Mb
> 
>     SINT32      err, packedLen = -1;
>     <other vars elided>
> 
>     // ..... call to fractious routine:
> 
>     err = buildReqExeMsg(packed, sizeof(packed),
>                          sessEKey, sessHKey, padKey,
>                          reqexelen, exefile, exefileLen,
>                          &packedLen);
> 
> -------------------------------------------- called
> 
> SINT32 buildReqExeMsg(UINT8 *packed, SINT32 packedbuflen,
>                       UINT8 *sessEKey, UINT8 *sessHKey,
>                       UINT8 *padKey, SINT32 padKeyLen,
>                       UINT8 *exefile, SINT32 exefileLen,
>                       SINT32 *packedLen) {
> 		      ....
> 


Hi,
I have had mixed luck assuming that function calls passing arrays 
actually pass as a pointer. I think that is a compiler dependent 
feature, but it may have been codified by one of the later ansii revisions.

I would try:
      err = buildReqExeMsg(&packed[0], sizeof(packed),
                           &sessEKey[0], &sessHKey[0],
                           &padKey[0], reqexelen,
                           &exefile[0], exefileLen,
                           &packedLen);

Another idea would be to make sure the large arrays are declared in 
global space, so that they don't wind up on the stack.

Good Luck,
Bob
0
BobH
9/23/2006 3:55:38 AM
BobH, thanks for your advice but I regret to say that I've already
tried both of those with much the same results.  :-(

Your advice on not counting on the compiler passing a pointer for
arrays is well-taken, but for gcc it should be consistent.  Besides, it
works fine in other places in the same program, plus it works on little
test programs such as the one below, which seems to work fine and
identically in OpenBSD and Linux.

This seems to be a fundamental problem, but I'm stumped.

Jim

/*
% cc -g -O0 -o mem mem.c
*/

/*
 * Test passing of addr to a big array.
 */

#include <stdio.h>

/* Convenience typedefs */
typedef unsigned char UINT8;
typedef char SINT8;
typedef unsigned short UINT16;
typedef short SINT16;
typedef unsigned int UINT32;
typedef int SINT32;
typedef unsigned long UINT64;
typedef long SINT64;

typedef float FLOAT32;
typedef double FLOAT64;

#define SZ	1000488
#define ZERO	0
#define ONE	1

int main(SINT32 argc, UINT8 **argv) {
    UINT8	bigarr[SZ];
    SINT32	ij;

    printf("main: &bigarr %x size %d\n",
	   &bigarr[0], sizeof(bigarr));

    ij = ONE;
    for (ij = 0; ij < sizeof(bigarr); ij++) {
	bigarr[ij] = ij & 0xFF;
    }

    sub(bigarr, sizeof(bigarr));

    printf("Done\n");

}

sub(UINT8 *mybig, SINT32 mybigsiz) {
    SINT32	kk = ZERO;
    UINT8	*myname = "sub";

    printf("%s: addr mybig %x size %d\n",
	   myname, mybig, mybigsiz);

    kk = ONE;
    printf("%s: mybig from 0 to %d:\n", myname, 8 * 16);
    for (kk = 0; kk < 8 * 16; kk++) {
	printf("%2x ", mybig[kk] & 0xff);
	if(kk > 0 && (kk % 16 == 0)) {
	    printf("\n");
	}
    }
    printf("\n");

    printf("%s: mybig from %d to %d:\n",
	   myname, mybigsiz - 8 * 16 - 1, mybigsiz - 1);
    for (kk = mybigsiz - 8 * 16 - 1; kk < mybigsiz; kk++) {
	printf("%2x ", mybig[kk] & 0xff);
	if(kk > 0 && (kk % 16 == 0)) {
	    printf("\n");
	}
    }
    printf("\n");
}

BobH wrote:

> Hi,
> I have had mixed luck assuming that function calls passing arrays
> actually pass as a pointer. I think that is a compiler dependent
> feature, but it may have been codified by one of the later ansii revisions.
>
> I would try:
>       err = buildReqExeMsg(&packed[0], sizeof(packed),
>                            &sessEKey[0], &sessHKey[0],
>                            &padKey[0], reqexelen,
>                            &exefile[0], exefileLen,
>                            &packedLen);
>
> Another idea would be to make sure the large arrays are declared in
> global space, so that they don't wind up on the stack.
> 
> Good Luck,
> Bob

0
n33ed
9/23/2006 5:13:22 PM
According to n33ed <n33ed@hotmail.com>:
> BobH, thanks for your advice but I regret to say that I've already
> tried both of those with much the same results.  :-(
> 
> Your advice on not counting on the compiler passing a pointer for
> arrays is well-taken, but for gcc it should be consistent.  Besides, it
> works fine in other places in the same program, plus it works on little
> test programs such as the one below, which seems to work fine and
> identically in OpenBSD and Linux.
> 
> This seems to be a fundamental problem, but I'm stumped.

	Without digging through all of your code, is there a possibility
that something is implemented as a macro in one version, and as a
function in the other?

	If you have other flavors of unix, you might consider compiling
both versions of gcc on the other machines, and see whether you get the
same behavioral difference.  If so -- perhaps it is time to send in a bug
report to the FSF on that version of gcc.

	I know that on one program which I have been helping a friend
test portability on, I find that on the various OpenBSD versions (up
through 3.9), and *only* there (several Solaris versions are the other
ones which I am testing on), the only noticed bug (so far) is that when
I *exit* the program, it also logs me out of that system (connected via a
slogin from a Solaris system), consistently.  Everything else seems to
work properly.  I haven't tried running it from the console on those
systems, yet, so I don't know whether it behaves similarly under those
conditions.

	Good Luck,
		DoN.
-- 
 Email:   <dnichols@d-and-d.com>   | Voice (all times): (703) 938-4564
	(too) near Washington D.C. | http://www.d-and-d.com/dnichols/DoN.html
           --- Black Holes are where God is dividing by zero ---
0
dnichols
9/23/2006 7:13:36 PM
Reply: