3

I am trying to build a program that communicates with a 32-bit embedded system, that runs on a Linux based x86_64 machine (host). On the host program I have a structure containing a few pointers that reflects an identical structure on the embedded system.

The problem is that on the host, pointers are natively 64-bits, so the offset of the structure members is not the same as in the embedded system. Thus, when copying the structure (as memcpy), the contents end up at the wrong place in the host copy.

struct {
    float a;
    float b;
    float *p;
    float *q;
} mailbox;
// sizeof(mailbox) is 4*4=16 on the embedded, but 2*4+2*8=24 on the host

Luckily, I found out here that gcc has an option -mx32 for generating 32-bit pointers on x86_64 machines. But, when trying to use this, I get an error saying:

$ gcc -mx32 test.c -o test.e
cc1: error: unrecognized command line option "-mx32"

This is for gcc versions 4.4.3 and 4.7.0 20120120 (experimental).

Why doesn't this option work? Is there a way around this?

EDIT: Accrding to the v4.4.7 manual, there was no -mx32 option available, and this is true up to v4.6.3. OTOH, v4.7.0 does show that option, so it may be that the Jan-20 version I am using is not the final one?!

ysap
  • 7,723
  • 7
  • 59
  • 122
  • 1
    If you are communicating with a difference system, using a stucture with pointers seems like the wrong approach as the pointers will only be valid on one side of the communication link even if it were that case that pointers had the same size in both systems. Perhaps you could describe your "bigger picture" issue? – CB Bailey Jun 02 '12 at 06:46
  • @CharlesBailey - I am not using the pointers at the host side to reference any data. I just need the addresses of the referenced objects at the embedded system. I use (the value of) these addresses for some purpose at the host size. – ysap Jun 02 '12 at 06:59
  • @CharlesBailey - BTW, if the host will end up on an embedded host processor (which it will in my case), like an ARM cpu with an external math accelerator where they both share the same memory space, then using the addresses may be valid on both sides. – ysap Jun 02 '12 at 07:01
  • For what purpose do you use those values? Could you use something else like an index or handle value instead? – CB Bailey Jun 02 '12 at 07:03
  • @CharlesBailey - The actual purpose doesn't really matter, and yes, I ended up replacing the pointers with integers. The reason I want the pointers is that this structure is defined in a header file that is mutual to the host project and to the embedded project - as I don't want to keep track of changes in problem parameters (like matrix size) in two places. In the embedded system I want to actually use the pointers as pointers. It would be nice if the compiler flag would enable that. Until then, I'll use some less pretty code. – ysap Jun 02 '12 at 07:13

2 Answers2

6

Don't do this. First, x32 is a separate architecture. It's not merely a compiler switch. You need an x32 version of every library you link against to make this work. Linux distros aren't yet producing x32 versions, so that means you'll be either linking statically or rolling your own library environment.

More broadly: that's just asking for trouble. If your structure contains pointers they should be pointers. If it contains "32 bit addresses" they should be a 32 bit integer type.

Andy Ross
  • 11,699
  • 1
  • 34
  • 31
  • Thanks, Andy. As mentioned earlier, I did change the members to integer types. However, I do not agree that this is "asking for troubles", if the behaviour of the system is well defined and if one knows what he is doing. It is not really a matter of life and death in our particular situation, but it would be handy to have it working. The host application is really meant to be run on an ARM embedded system. However, at this time I have no such system available, so I develop that small app on a Linux based PC. Then it should be easy to rebuild it for the ARM. – ysap Jun 03 '12 at 17:01
  • The host app is really small and except for the runtime and newlib doesn't really need any additional libraries (like libm or so). What you are saying here is that the -mx32 option, although documented, is not really implemented in GCC, and this may be seen as a bug, doesn't it? Or, is it a problem specific to Linux? – ysap Jun 03 '12 at 17:03
  • 1
    The "-mx32 option" says to generate code for the "x32" machine target. It is a **different** ABI. It works fine, AFAIK. You don't have such a machine, however. Your linux distro is running x86_64. – Andy Ross Jun 04 '12 at 03:56
  • Of course it is a different ABI, and I agree that it requires different libraries. But the doc says: *"These `-m' switches are supported in addition to the above on **x86-64** processors in 64-bit environments."* and *"The -mx32 option sets int, long, and pointer types **to 32 bits**, and generates code for the **x86-64** architecture"* which is what I was looking for. It may be that I am missing a point here, but my understanding is that it is supposed to work on Linux targets as well (given supporting libraries). – ysap Jun 04 '12 at 07:33
  • Anyway, I don't see how it works fine, as you said, if it gives me that error message. Can you give an example for such a compatible machine? – ysap Jun 04 '12 at 07:34
  • It's a new-ish argument. It works fine (I just checked the generated assembly to verify use of 32 bit pointers) on gcc 4.7.0 as shipped in Fedora 17 x86_64. It probably doesn't work on 4.4.x, which is now over three years old. – Andy Ross Jun 04 '12 at 19:22
  • Thanks. As I wrote above, I tested on 4.7.0 (experimental). This, in fact was not the Linux compiler (I have 4.4.3 installed on the Linux machine) but rather our port for the gcc intended for our embedded architecture. I assumed that any feature in the mainline gcc will be available in our port. So, it is either that the experimental version is not yet updated with that option, or that it was intentionally not-included in this build. – ysap Jun 04 '12 at 20:23
  • `-m32` is merely a compiler switch that changes ABI too. Does that mean I should never use `-m32` either? gcc has "multilib" to handle it. – doug65536 May 01 '21 at 07:18
0

You might need a newer version of binutils

Though I think gcc 4.8 is recommended

But in general you need a kernel compiled multilib with it: https://unix.stackexchange.com/questions/121424/linux-and-x32-abi-how-to-use

rogerdpack
  • 62,887
  • 36
  • 269
  • 388