Skip to content

Commit 0254de3

Browse files
committed
Add test file for context functions
For now, this just tests stack alignment in a context's entry point This test shows a problem when building on i386 with `-msse2`, where the compiler is allowed use some instructions that move data in and out of the xmm0-7 registers, requiring them to be aligned on 16-byte boundaries. Because the compiler will generally assume the stack is correctly aligned on entering a function, the misalignment will propagate through the stack until something uses an instruction that requires 16-byte alignment, and we get a segmentation fault. The misalignment happens because the stack is heap-allocated (and the heap allocator provides a properly aligned pointer), but we push the argument for the async task onto the stack as we call it, leaving the stack 4 bytes below proper alignment. The test is equally valid on x86_64, but the stack alignment is correct there - nothing is pushed onto the stack prior to calling the task function, as it's passed in a register.
1 parent 5af90f0 commit 0254de3

File tree

2 files changed

+45
-1
lines changed

2 files changed

+45
-1
lines changed

unittest/libmariadb/CMakeLists.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ INCLUDE_DIRECTORIES(${CC_SOURCE_DIR}/include
2626
${CC_SOURCE_DIR}/unittest/libmariadb)
2727
ADD_DEFINITIONS(-DLIBMARIADB)
2828

29-
SET(API_TESTS "conc336" "bulk1" "performance" "basic-t" "fetch" "charset" "logs" "cursor" "errors" "view" "ps" "ps_bugs" "sp" "result" "connection" "misc" "ps_new" "thread" "features-10_2")
29+
SET(API_TESTS "conc336" "bulk1" "performance" "basic-t" "fetch" "charset" "logs" "cursor" "errors" "view" "ps" "ps_bugs" "sp" "result" "connection" "misc" "ps_new" "thread" "features-10_2" "context")
3030
IF(WITH_DYNCOL)
3131
SET(API_TESTS ${API_TESTS} "dyncol")
3232
ENDIF()

unittest/libmariadb/context.c

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
/*
2+
* Tests for ma_context functions.
3+
*/
4+
5+
#include "my_test.h"
6+
#include "mysql.h"
7+
#include "ma_context.h"
8+
#include <stdio.h>
9+
#include <stdint.h>
10+
#include <stddef.h>
11+
12+
/*
13+
* Ensures the context system aligns the stack correctly for i386 and x86_64
14+
*/
15+
void async_task(__attribute__((unused)) void *v) {
16+
#if defined( __GNUC__ ) && ( defined( __i386__ ) || defined( __x86_64__ ) )
17+
/*
18+
* The compiler assumes the stack is correctly aligned on a 16-byte
19+
* boundary on entry to the function (actually, with a return address
20+
* popped on top of the aligned address). Creating an object with a
21+
* max_align_t type should also be aligned at that boundary, so we should
22+
* be able to use movaps to move the first 128 bits into xmm0.
23+
*/
24+
union {
25+
max_align_t aligned;
26+
uint64_t data[2];
27+
} aligned;
28+
__asm__("movaps %0, %%xmm0" : : "m" (aligned.data) : "xmm0" );
29+
#endif
30+
}
31+
32+
static int test_stack_align() {
33+
struct my_context ctx;
34+
my_context_init(&ctx, 65536);
35+
my_context_spawn(&ctx, async_task, &ctx);
36+
my_context_destroy(&ctx);
37+
return 0;
38+
}
39+
40+
int main()
41+
{
42+
plan(1);
43+
ok( test_stack_align() == 0, "stack alignment check" );
44+
}

0 commit comments

Comments
 (0)