[Date Prev][Date Next] [Thread Prev][Thread Next] [Date Index] [Thread Index]

Re: A question about stack alignment in C language



On Sat, Apr 06, 2019 at 02:08:17AM +0000, Mo Zhou wrote:
> Hi mentors,

Unlike Matthew, I don't consider code questions to be completely off topic. 
And I hate Stack Overflow.  So let's continue to the fun. :)

> 	float sasum64(size_t N, const float *X, size_t incX)
> 	float sasum32(int N, const float *X, int incX)

> compiled as libfoo.so: gcc -shared -fPIC libfoo.c -o libfoo.so

> 	float sasum64(int N, const float *X, int incX);
> 	float sasum32(size_t N, const float *X, size_t incX);

> 		printf("%f, %f\n", sasum32(3, a, 1), sasum64(3, a, 1));

> My questions are:
> 
> 	1. Why doesn't the application segfault, since it has already
> 	misused the index (N and incX) type?

On 32-bit archs, all these types have same widths.

On 64-bit, you have undefined behaviour portability-wise as registers that
are being used to pass these values might or might not have their upper bits
cleared.

On arm64, this is explicitly the case for a store to lower half (w0 of x0):

# w0 through w30 - for 32-bit-wide access (same registers - upper 32 bits
# are either cleared on load or sign-extended (set to the value of the most
# significant bit of the loaded value)).

On amd64, this is also the case for stores to lower 32-bits of a 64-bit
register (eax of rax).  That's very surprising for those of us who did most
of their asm programming in 16-bit days: a store to al does _not_ clear the
upper half of ax.

I have no idea about other archs -- they very well could behave like 8086. 
But the problem is, everyone among us has an amd64 box and a bunch of
arm64/armhf boards, but a trip to a porterbox for fringe archs tends to be
something you do only upon suspecting a bug.

Someone more knowledgeable may fill us in.

> 	2. Did we avoid SIGSEGV because the arguments used to call
> 	sasum32 or sasum64 are aligned in 64-bits? But that's still
> 	strange due to little-endianess...

Registers don't care about endianness nor alignment.  Any modern ABI passes
such arguments in the registers rather than stack, at most spilling once you
have too many.

On the stack, all 64-bit archs I'm aware of require 64-bit values to be
aligned; whether passing two 32-bit values side-to-side requires one or two
words depends on the ABI (stack is different from structs).  In no case you
mention there's two 32-bit args.

> 	3. How can I make the app.c segfault?

Possibly use a musty old arch (not sure about that)?  Have more args that
include two 32-bit ones?  Use negative values (size_t vs int, sign
extension)?

(And thanks for the question: TIL that eax -> rax zero/sign extends while
al -> ax did not.)


Meow!
-- 
⢀⣴⠾⠻⢶⣦⠀ It's all millenials' fault.  I've discussed this with a cow
⣾⠁⢠⠒⠀⣿⡁ orker, we just couldn't agree on a definition -- I say
⢿⡄⠘⠷⠚⠋⠀ millenials start at 1979, he claims it's 1985+.  But it's
⠈⠳⣄⠀⠀⠀⠀ certain: smelly millenials are the cause of all problems.


Reply to: