Reputation: 22781
I'm working on porting some code to an environment with more strict alignment requirements than x86 has, but I'm changing/testing on an x86 Linux machine for the time being due to this being easier for hardware access reasons, among other things.
I've distilled the first problem that I've run into into the following concise example:
#include <stdio.h>
#include <string.h>
#define BUFFER_SIZE 1024
#define DMQUOTE_LOG "DMQUOTELOG"
void aFunction (const char *configPath)
{
char LogFilename[BUFFER_SIZE] __attribute ((aligned));
// printf ("A\n");
strcpy (LogFilename, configPath);
strcat (LogFilename, DMQUOTE_LOG);
printf ("Log: %s\n", LogFilename);
}
int main (int argc, char **argv)
{
__asm__("pushf\n"
"orl $0x40000, (%esp)\n"
"popf");
aFunction ("");
return 0;
}
Running this code as is provides the expected output. However, uncommenting the other printf causes a bus error to trigger on the strcat line.
It looks to me as if the reason for this is that by introducing a second string constant, the constant from the define is shifted so that it's not aligned. This is upheld by noticing that if the string constant is changed from "A\n" to "AAA\n", everything works again (and magically gcc replaces the call to printf with a call to puts and drops the \n from the constant).
Is there some nice way to make gcc insert extra padding between all of the string constants that it's inserting into the .rodata section so that things align properly?
[EDIT]
As mentioned by fucanchik below, here's what the .rodata section of the above is (with the extra printf enabled):
.file "sample.c"
.section .rodata
.LC0:
.string "A"
.LC1:
.string "DMQUOTELOG"
.LC2:
.string "Log: %s\n"
.text
.globl aFunction
...
There is no alignment forced, which makes sense because I'm compiling under x86, which doesn't strictly require it. Naturally, modifying the assembler to this has the desired effect. However, I can't see a way to get gcc to apply this on its own on the fly. This may of course be moot if glibc itself can't handle being run in this mode in the general case, though.
.file "sample.c"
.section .rodata
.LC0:
.string "A"
.align 4,0
.LC1:
.string "DMQUOTELOG"
.LC2:
.string "Log: %s\n"
.text
.globl aFunction
...
Upvotes: 1
Views: 1447
Reputation: 22781
There does not seem to be any way to accomplish this, at least with GCC. Testing seems to indicate that although the compiler will align integers, doubles and so on,because string constants are made of characters and alignment for character data is on byte boundaries, the compiler feels no need to align them.
The particulars of this bus error seem to indicate that glibc uses optimized routines that copy data words at a time without checking for alignment first (having not looked at the source, I don't know if this is true or not however).
This led me to investigating musl, an alternative libc implementation that is simple to install and use on a project by project basis.The C source code of the musl version of strcat takes care to copy unaligned bytes before copying words at a time, and thus this particular issue goes away, although naturally others remain.
Upvotes: 1