How to catch data-alignment faults on x86 (aka SIG

2019-01-17 07:59发布

Is it somehow possible to catch data-alignment faults even on i386? Maybe by setting a i386 specific machine register or something like that.

On Solaris-Sparc I am receiving a SIGBUS in this case, but on i386 everything is fine.

Environment:

  • 32-bit application
  • Ubuntu Karmic
  • gcc/g++ v4.4.1

EDIT: Here is why I am asking this:

  • our application crashes on Sol-Sparc with SIGBUS. For the purpose of debugging I would try to get a similar behavior on our i386 platform.
  • our Sol-sparc machine is very slow, so compiling and debugging takes a lot of time there. And our i386 machine is unbelievable fast (8 cores, 32G memory).
  • Even on i386 platforms there is a cost of performance on data-alignment faults. And therefore I would like to fix data-alignment faults wherever possible.

标签: c++ c gcc g++
6条回答
混吃等死
2楼-- · 2019-01-17 08:24

Meanwhile I found an Intel CPU document addressing this topic.

See Intel® 64 and IA-32 Architectures Software Developer’s Manual.

It seems to be difficult to put all this stuff together. However it doesn't sound like it is completely impossible. The interesting chapter is 4.10.5 Checking Alignment

EDIT (some condensed material from the mentioned document):

page 5-60

Interrupt 17 Alignment Check Exception (#AC)

to enable alignment checking, the following conditions must be true:

AM flag is set(bit 18 of control regisster CR0)
AC flag is set (bit 18 of the EFLAGS)
The CPL is 3 (protected mode or virtual-8086 mode).

additionally - in 14.8.2.6 - Memory Controller Errors are mentioned. I don't know if it is the same only in other words:

table 14-11, Encoding of MMM and CCCC Sub-Fields
Address/Command Error  AC  011
查看更多
时光不老,我们不散
3楼-- · 2019-01-17 08:25

I have found a very simple solution on SOF! See: Mis-aligned pointers on x86.

int main(int argc, char **argv)
{
# if defined i386
    /* EDIT: enable AC check */
    asm("pushf; "
    "orl $(1<<18), (%esp); "
    "popf;");
# endif

    char d[] = "12345678";  /* yep! - causes SIGBUS even on Linux-i386 */
    return 0;
}

But I must confess that I do not understand why the assignment

char d[] = "12345678";

is assumed to be mis-aligned?

EDIT:

on the SPARC machine there is no SIGBUS on the line of assignment to char d[].

查看更多
爷、活的狠高调
4楼-- · 2019-01-17 08:33

Intel built in unaligned transfers from the start - it was one of the selling points when x86 was brand new. I understand your reasons for wanting to trap unaligned access, but I don't think it's possible.

Edit: very glad to be proven wrong.

查看更多
▲ chillily
5楼-- · 2019-01-17 08:39

To expand on Vokuhila-Oliba's answer looking at the "SOF Mis-aligned pointers on x86." thread it seems that gcc can generate code with mis-aligned memory access. AFAIK you don't have any control over this.

Enabling alignment checks on gcc compiled code would be a bad idea. You risk getting SIGBUS errors for good C code.

ReEdited: Sorry about that

查看更多
唯我独甜
6楼-- · 2019-01-17 08:39

Intel are very big on supporting unaligned loads. If I had to detect such loads on an Intel platform, I think I would have to modify valgrind to treat unaligned loads as errors. Such a modification is not trivial, but valgrind was designed with the idea in mind that users could create new 'tools'. I think a simple modification to the memcheck tool would detect your unaligned references. And the error reporting is really very nice.

查看更多
闹够了就滚
7楼-- · 2019-01-17 08:47

Many years later: if your gcc/clang is new enough (GCC 4.9, clang 3.3?) you may be able to build your code with the undefined behaviour sanitizer (-fsanitize=undefined) to get warnings about misaligned accesses on a given platform (but bear in mind different platforms have different alignment requirements, different compilers will choose different layouts etc). See https://clang.llvm.org/docs/UndefinedBehaviorSanitizer.html and https://developers.redhat.com/blog/2014/10/16/gcc-undefined-behavior-sanitizer-ubsan/ for details.

查看更多
登录 后发表回答