Messages in this thread | | | From | Ammar Faizi <> | Subject | Re: [PATCH 2/2] tools/nolibc: x86-64: Fix startup code bug | Date | Fri, 15 Oct 2021 15:57:01 +0700 |
| |
Hi,
This is a code to test.
Compile with: gcc -O3 -ggdb3 -nostdlib -o test test.c
Technical explanation: The System V ABI mandates the %rsp must be 16-byte aligned before performing a function call, but the current nolibc.h violates it.
This %rsp alignment violation makes the callee can't align its stack properly. Note that the callee may have a situation where it requires vector aligned move. For example, `movaps` with memory operand w.r.t. xmm registers, it requires the src/dst address be 16-byte aligned.
Since the callee can't align its stack properly, it will segfault when executing `movaps`. The following C code is the reproducer and test to ensure the bug really exists and this patch fixes it.
``` /* SPDX-License-Identifier: LGPL-2.1 OR MIT */
/* * Bug reproducer and test for Willy's nolibc (x86-64) by Ammar. * * Compile with: * gcc -O3 -ggdb3 -nostdlib -o test test.c */
#include "tools/include/nolibc/nolibc.h"
static void dump_argv(int argc, char *argv[]) { int i; const char str[] = "\nDumping argv...\n";
write(1, str, strlen(str)); for (i = 0; i < argc; i++) { write(1, argv[i], strlen(argv[i])); write(1, "\n", 1); } }
static void dump_envp(char *envp[]) { int i = 0; const char str[] = "\nDumping envp...\n";
write(1, str, strlen(str)); while (envp[i] != NULL) { write(1, envp[i], strlen(envp[i])); write(1, "\n", 1); i++; } }
#define read_barrier(PTR) __asm__ volatile(""::"r"(PTR):"memory")
__attribute__((__target__("sse2"))) static void test_sse_move_aligned(void) { int i; int arr[32] __attribute__((__aligned__(16)));
/* * The assignment inside this loop is very likely * performed with aligned move, thus if we don't * align the %rsp properly, it will fault! * * If we fault due to misaligned here, then there * must be a caller below us that violates SysV * ABI w.r.t. to %rsp alignment before func call. */ for (i = 0; i < 32; i++) arr[i] = 1;
read_barrier(arr); }
int main(int argc, char *argv[], char *envp[]) { dump_argv(argc, argv); dump_envp(envp); test_sse_move_aligned(); return 0; } ```
-- Ammar Faizi
| |