diff --git a/libc/config/baremetal/arm/entrypoints.txt b/libc/config/baremetal/arm/entrypoints.txt index a88b7aa749e5..a0779c41652a 100644 --- a/libc/config/baremetal/arm/entrypoints.txt +++ b/libc/config/baremetal/arm/entrypoints.txt @@ -17,6 +17,9 @@ set(TARGET_LIBC_ENTRYPOINTS libc.src.ctype.tolower libc.src.ctype.toupper + # compiler entrypoints (no corresponding header) + libc.src.compiler.__stack_chk_fail + # errno.h entrypoints libc.src.errno.errno @@ -69,7 +72,7 @@ set(TARGET_LIBC_ENTRYPOINTS libc.src.stdio.snprintf libc.src.stdio.vsprintf libc.src.stdio.vsnprintf - + # stdlib.h entrypoints libc.src.stdlib.abs libc.src.stdlib.atoi diff --git a/libc/config/baremetal/riscv/entrypoints.txt b/libc/config/baremetal/riscv/entrypoints.txt index 3b7ca513eb09..3e15cc8901bd 100644 --- a/libc/config/baremetal/riscv/entrypoints.txt +++ b/libc/config/baremetal/riscv/entrypoints.txt @@ -17,6 +17,9 @@ set(TARGET_LIBC_ENTRYPOINTS libc.src.ctype.tolower libc.src.ctype.toupper + # compiler entrypoints (no corresponding header) + libc.src.compiler.__stack_chk_fail + # errno.h entrypoints libc.src.errno.errno diff --git a/libc/config/linux/aarch64/entrypoints.txt b/libc/config/linux/aarch64/entrypoints.txt index 60e0e2b29aed..77c9a50b8b7e 100644 --- a/libc/config/linux/aarch64/entrypoints.txt +++ b/libc/config/linux/aarch64/entrypoints.txt @@ -16,7 +16,7 @@ set(TARGET_LIBC_ENTRYPOINTS libc.src.ctype.toascii libc.src.ctype.tolower libc.src.ctype.toupper - + # errno.h entrypoints libc.src.errno.errno @@ -239,7 +239,7 @@ set(TARGET_LIBM_ENTRYPOINTS libc.src.math.asinf libc.src.math.asinhf libc.src.math.atanf - libc.src.math.atanhf + libc.src.math.atanhf libc.src.math.copysign libc.src.math.copysignf libc.src.math.copysignl @@ -353,6 +353,9 @@ set(TARGET_LIBM_ENTRYPOINTS if(LLVM_LIBC_FULL_BUILD) list(APPEND TARGET_LIBC_ENTRYPOINTS + # compiler entrypoints (no corresponding header) + libc.src.compiler.__stack_chk_fail + # network.h entrypoints libc.src.network.htonl libc.src.network.htons diff --git a/libc/config/linux/arm/entrypoints.txt b/libc/config/linux/arm/entrypoints.txt index 123c7e33377a..274d5aa5a005 100644 --- a/libc/config/linux/arm/entrypoints.txt +++ b/libc/config/linux/arm/entrypoints.txt @@ -66,7 +66,7 @@ set(TARGET_LIBC_ENTRYPOINTS libc.src.inttypes.imaxdiv libc.src.inttypes.strtoimax libc.src.inttypes.strtoumax - + # stdlib.h entrypoints libc.src.stdlib.abs libc.src.stdlib.atoi @@ -88,7 +88,7 @@ set(TARGET_LIBC_ENTRYPOINTS libc.src.stdlib.strtoll libc.src.stdlib.strtoul libc.src.stdlib.strtoull - + # sys/mman.h entrypoints libc.src.sys.mman.mmap libc.src.sys.mman.munmap diff --git a/libc/config/linux/riscv/entrypoints.txt b/libc/config/linux/riscv/entrypoints.txt index 948708e35f45..e389936ffca1 100644 --- a/libc/config/linux/riscv/entrypoints.txt +++ b/libc/config/linux/riscv/entrypoints.txt @@ -362,6 +362,9 @@ set(TARGET_LIBM_ENTRYPOINTS if(LLVM_LIBC_FULL_BUILD) list(APPEND TARGET_LIBC_ENTRYPOINTS + # compiler entrypoints (no corresponding header) + libc.src.compiler.__stack_chk_fail + # assert.h entrypoints libc.src.assert.__assert_fail diff --git a/libc/config/linux/x86_64/entrypoints.txt b/libc/config/linux/x86_64/entrypoints.txt index 1c93063e25e9..3adcd57d0c08 100644 --- a/libc/config/linux/x86_64/entrypoints.txt +++ b/libc/config/linux/x86_64/entrypoints.txt @@ -375,6 +375,9 @@ if(LLVM_LIBC_FULL_BUILD) # assert.h entrypoints libc.src.assert.__assert_fail + # compiler entrypoints (no corresponding header) + libc.src.compiler.__stack_chk_fail + # dirent.h entrypoints libc.src.dirent.closedir libc.src.dirent.dirfd diff --git a/libc/src/CMakeLists.txt b/libc/src/CMakeLists.txt index 3ab62a4f667d..492f9c5bd50f 100644 --- a/libc/src/CMakeLists.txt +++ b/libc/src/CMakeLists.txt @@ -29,10 +29,11 @@ if(NOT LLVM_LIBC_FULL_BUILD) endif() add_subdirectory(assert) +add_subdirectory(compiler) add_subdirectory(network) +add_subdirectory(search) add_subdirectory(setjmp) add_subdirectory(signal) add_subdirectory(spawn) add_subdirectory(threads) add_subdirectory(time) -add_subdirectory(search) diff --git a/libc/src/compiler/CMakeLists.txt b/libc/src/compiler/CMakeLists.txt new file mode 100644 index 000000000000..aa59d84e08d1 --- /dev/null +++ b/libc/src/compiler/CMakeLists.txt @@ -0,0 +1,18 @@ +if(EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/${LIBC_TARGET_OS}) + add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/${LIBC_TARGET_OS}) +else() + add_subdirectory(generic) +endif() + +if(TARGET libc.src.compiler.${LIBC_TARGET_OS}.__stack_chk_fail) + set(stack_chk_fail_dep libc.src.compiler.${LIBC_TARGET_OS}.__stack_chk_fail) +else() + set(stack_chk_fail_dep libc.src.compiler.generic.__stack_chk_fail) +endif() + +add_entrypoint_object( + __stack_chk_fail + ALIAS + DEPENDS + ${stack_chk_fail_dep} +) diff --git a/libc/src/compiler/__stack_chk_fail.h b/libc/src/compiler/__stack_chk_fail.h new file mode 100644 index 000000000000..2e3d849ff8c6 --- /dev/null +++ b/libc/src/compiler/__stack_chk_fail.h @@ -0,0 +1,18 @@ +//===-- Internal header for __stack_chk_fail --------------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_LIBC_SRC_COMPILER___STACK_CHK_FAIL_H +#define LLVM_LIBC_SRC_COMPILER___STACK_CHK_FAIL_H + +namespace LIBC_NAMESPACE { + +[[noreturn]] void __stack_chk_fail(); + +} // namespace LIBC_NAMESPACE + +#endif // LLVM_LIBC_SRC_COMPILER___STACK_CHK_FAIL_H diff --git a/libc/src/compiler/generic/CMakeLists.txt b/libc/src/compiler/generic/CMakeLists.txt new file mode 100644 index 000000000000..0d869b72a12c --- /dev/null +++ b/libc/src/compiler/generic/CMakeLists.txt @@ -0,0 +1,11 @@ +add_entrypoint_object( + __stack_chk_fail + SRCS + __stack_chk_fail.cpp + HDRS + ../__stack_chk_fail.h + DEPENDS + libc.include.assert + libc.src.__support.OSUtil.osutil + libc.src.stdlib.abort +) diff --git a/libc/src/compiler/generic/__stack_chk_fail.cpp b/libc/src/compiler/generic/__stack_chk_fail.cpp new file mode 100644 index 000000000000..0ca02071f2a9 --- /dev/null +++ b/libc/src/compiler/generic/__stack_chk_fail.cpp @@ -0,0 +1,20 @@ +//===-- Implementation of __stack_chk_fail --------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#include "src/compiler/__stack_chk_fail.h" +#include "src/__support/OSUtil/io.h" +#include "src/stdlib/abort.h" + +namespace LIBC_NAMESPACE { + +LLVM_LIBC_FUNCTION(void, __stack_chk_fail, (void)) { + LIBC_NAMESPACE::write_to_stderr("stack smashing detected"); + LIBC_NAMESPACE::abort(); +} + +} // namespace LIBC_NAMESPACE diff --git a/libc/startup/linux/x86_64/start.cpp b/libc/startup/linux/x86_64/start.cpp index c98f58a4ac0a..bc03a3cb1de2 100644 --- a/libc/startup/linux/x86_64/start.cpp +++ b/libc/startup/linux/x86_64/start.cpp @@ -25,11 +25,6 @@ extern "C" int main(int, char **, char **); -extern "C" void __stack_chk_fail() { - LIBC_NAMESPACE::write_to_stderr("stack smashing detected"); - LIBC_NAMESPACE::abort(); -} - namespace LIBC_NAMESPACE { #ifdef SYS_mmap2 diff --git a/libc/test/src/CMakeLists.txt b/libc/test/src/CMakeLists.txt index c45b94f36439..6bd8ace9ea71 100644 --- a/libc/test/src/CMakeLists.txt +++ b/libc/test/src/CMakeLists.txt @@ -60,8 +60,9 @@ if(NOT LLVM_LIBC_FULL_BUILD) return() endif() -add_subdirectory(dirent) add_subdirectory(assert) +add_subdirectory(compiler) +add_subdirectory(dirent) add_subdirectory(network) add_subdirectory(setjmp) add_subdirectory(signal) diff --git a/libc/test/src/compiler/CMakeLists.txt b/libc/test/src/compiler/CMakeLists.txt new file mode 100644 index 000000000000..b8d682c1c519 --- /dev/null +++ b/libc/test/src/compiler/CMakeLists.txt @@ -0,0 +1,14 @@ +add_custom_target(libc_stack_chk_guard_unittests) + +add_libc_unittest( + stack_chk_guard_test + SUITE + libc_stack_chk_guard_unittests + SRCS + stack_chk_guard_test.cpp + DEPENDS + libc.src.compiler.__stack_chk_fail + libc.src.string.memset + COMPILE_OPTIONS + -fstack-protector-all + ) diff --git a/libc/test/src/compiler/stack_chk_guard_test.cpp b/libc/test/src/compiler/stack_chk_guard_test.cpp new file mode 100644 index 000000000000..1de2d1b7357f --- /dev/null +++ b/libc/test/src/compiler/stack_chk_guard_test.cpp @@ -0,0 +1,26 @@ +//===-- Unittests for __stack_chk_fail ------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#include "llvm-libc-macros/signal-macros.h" +#include "src/compiler/__stack_chk_fail.h" +#include "src/string/memset.h" +#include "test/UnitTest/Test.h" + +TEST(LlvmLibcStackChkFail, Death) { + EXPECT_DEATH([] { LIBC_NAMESPACE::__stack_chk_fail(); }, + WITH_SIGNAL(SIGABRT)); +} + +TEST(LlvmLibcStackChkFail, Smash) { + EXPECT_DEATH( + [] { + int arr[20]; + LIBC_NAMESPACE::memset(arr, 0xAA, 9001); + }, + WITH_SIGNAL(SIGABRT)); +}