thewrongchristian wrote:Your example is not optimized. As soon as you enable even minimal optimization (-O), the problem disappears:
Yeah, I know that, but I'd like
everything to work with -O0 (my debug build) too.
kzinti wrote:Are you just trying to get a warning-free code base or is there some other concern(s) here?
Yes, I do. Briefly, I build and test the project in a variety of configurations (more than 10) using almost all the warnings compilers have, with -Werror, of course. My goal is making a project as robust and portable as possible, even if today supports just x86. Also, it has to be absolutely UB-free too. [
UB is my biggest enemy. Coming from C++, I learned that in large-enough code bases there's always an UB lurking somewhere, ready to strike. I
hate so much when everything works and it's doing exactly what most people expect to, but in reality, that's just an illusion, that miserably breaks after upgrading the compiler.]
The longer story. I don't really care that the stack is unaligned in debug builds, on x86 with clang. That's fine, the performance of debug builds is not a problem. The problem is that I cannot turn on
-fsanitize=alignment because of that. I don't want to display UBSAN warnings or log them somewhere. My policy is: if there
might be a problem, just panic. I'll fix it and restart all the testing. Now, some time ago, I realized thanks to a discussion here with @Octocontrabass that we have no ad-hoc option to make unaligned access non-UB. I believed that -fno-strict-aliasing did that as a side effect, but that was simple false. No such thing as -fwrapv for unaligned access. So,
just for the moment in kernel where we disallow any kind of SIMD instructions, it looks safe it's to do unaligned access, but
in the future that won't be the case, anymore. In the last years, compiler developers are taking advantage of the undefined behavior where allowed by the standard as much as possible. I don't want end up with weird UB bugs when I switch to the newest compiler a few years from now. Warnings like -Wcast-align helped, but not in all the cases. In some cases, we have to check at runtime if unaligned access is performed by "regular" C code.
Here comes the
UBSAN: I started introducing it two days ago and it already helped me fixing a few places, not just about unaligned access, but other stuff too, discovering real bugs. For example, in one case I was performing unaligned access needlessly simply because I forgot to add a .align directive in the assembly where I declared two arrays. In another cases, with minor effort I could align a buffer. In other, the access was misaligned because of a wrong offset. Finally, in rare cases, I really needed to support unaligned access as well. For those cases, given that the only standard-compliant way to do read/write memory where the address might be unaligned is to use something like __builtin_memcpy(), that's what I did. I introduced macros like READ_LONG(), WRITE_U32() etc. and I used them in the very few places where the address might not be aligned. Anyway, UBSAN with GCC does the work, but it's sad that with clang I have to conditionally not enable -fsanitize=alignment, because of that weird behavior in leaf functions.
And yes, just to use -fsanitize=alignment for debug builds with clang on x86, I could do insane tricks in the kernel to align the stack pointer on interrupts, but it's not worth the effort. Not only that, it will make that assembly code forked with #ifdefs etc. It would be a mess that I wouldn't be happy to maintain. The compiler should just support an option to prevent that. It's sad that -mstack-alignment has no effect.