You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
When calling a vararg function (like printf), the IR generator allocates a memory block on the stack and fills it with the variable arguments.
In doing so, padding is inserted when needed to cover the alignement constraints.
The callee receives the memory block and uses a pointer to read the expected type, then increments the pointer with the size of the expected type, so it does not handle padding.
This does not work in all cases where padding is inserted by the caller since it is ignored by the callee.
Typical case that does not work (and crashes most of the time):
int i;
char *pc;
printf("%d %s", i, pc);
For x86_64, this creates a 16byte block filled as follows;
the 4byte i is stored at offset 0
a 4byte padding at offset 4
the 8byte pc is stored at offset 8
Printf uses va_arg(int) then va_arg(char *) and will not skip any padding:
read the 4byte i at offset 0 (OK)
read the 8byte pc at offset 4 (wrong)
Two solutions:
Either the caller never uses any padding
Or arguments are all aligned on the strongest alignement contraint (8byte on x86_64)
Solution 2) is the only that is compliant with the alignment constraints.
x86 is tolerant towards misaligned data but other architectures are much more sensitive.
The strongest alignment constraint could be computed once (and put in the context) by taking the strongest alignment among int, long, and pointer types. The information would then be used in varrag callee and caller IR generation.
The text was updated successfully, but these errors were encountered:
Seems like the va_list type is a specific thing per architecture.
One way to handle this properly would be to add additional IR-code instructions I assume, and have a sort of polyfill method which falls back to this old method.
When calling a vararg function (like printf), the IR generator allocates a memory block on the stack and fills it with the variable arguments.
In doing so, padding is inserted when needed to cover the alignement constraints.
The callee receives the memory block and uses a pointer to read the expected type, then increments the pointer with the size of the expected type, so it does not handle padding.
This does not work in all cases where padding is inserted by the caller since it is ignored by the callee.
Typical case that does not work (and crashes most of the time):
For x86_64, this creates a 16byte block filled as follows;
Printf uses va_arg(int) then va_arg(char *) and will not skip any padding:
Two solutions:
Solution 2) is the only that is compliant with the alignment constraints.
x86 is tolerant towards misaligned data but other architectures are much more sensitive.
The strongest alignment constraint could be computed once (and put in the context) by taking the strongest alignment among int, long, and pointer types. The information would then be used in varrag callee and caller IR generation.
The text was updated successfully, but these errors were encountered: