Stack aligment in a callback function

I am working on an embedded system where the data layout provided by rust's toolchains just "almost" work for me. The issue is that when I register a rust function as an extern c function callback then the callback function stack alignment is invalid and it just crashes "randomly" depending on a specific complication version.

It seems like when I provide the data layout just like is documented, the variable I use for the stack alignment is just verified to be a power of 2 or something similar but does not actually affect the result binary in any other way.

Is there a way I can force a stack alignment to function?

You can know if it actually worked or not if you compile an "extern c function" and see the "and esp, MASK" or something similar.

The embedded platform is x86 based (32 bits) if that matters.

Thanks in advance

1 Like

Could you give more details on the problem: Is it that your extern "C" fn, defined in Rust, is compiled so that it assumes a certain alignment for the stack pointer, but the calling code, some API you do not control, does not guarantee that alignment? Which target are you compiling for?

I am using i686-unknown-linux-gnu, but with no_std because it is the closest one I have to what I need. And yes, rust assumes there is some alignment present. I wish I could force mask it to the extern "C" fn i have, (threads entry point and callbacks).

So apparently in C with clang or gcc, adding __attribute__((force_align_arg_pointer)) does what you seem to be asking for. In the LLVM-IR that clang generates, that corresponds to the additional attribute "stackrealign". I don't think there's currently a way to get that from rustc.

2 Likes

Could naked functions help here?

Probably possible, however I don't really want to create a naked function for each of the "entry point"(ie the callbacks or thread entry point).

Hmmmm, seems interesting.

How can one like request to add that as an attribute to a function in rustc? Could probably just solve my problem all together in the best way.

As it'd be a user-facing change to the language, I think it'd need an RFC. Introduction - The Rust RFC Book

1 Like

You could perhaps create a procedural macro that creates such a naked function automatically for each annotated function.

1 Like

I'm not that good with macros. Are you perhaps any better and could help me out?

I will check it out

Never done a procedural macro myself and I don't believe a macro_rules macro would be very ergonomic here (you could do it, but it would have to wrap the entire function definition, instead of just act as an attribute).

Isn't part of the problem that you are actually using the wrong target (i686-unknown-linux-gnu when it really isn't)? Rust doesn't seem to have a i686-unknown-none, but I believe there is an unstable feature to let you provide your own target definition file (used by rust in the Linux kernel for example). I have only read about this in the passing, so I don't know how it works, but presumably that file would contain the expected stack alignment.

I was able to locate a couple of pages about this feature though:

2 Likes

Actually, I have tried providing a different target spec json with a different value for the stack alignment.

However, in the assembly I have seen no difference. Practically I only saw that it verifies that it is a power of 2 or something similar.

I have tried stuff like they explain here but it did not work for me.

Maybe the solution could be something of this nature but I have failed doing it this way.

Created an RFC as suggested above.