Skip to content
This repository was archived by the owner on Sep 15, 2025. It is now read-only.

Commit ff56308

Browse files
SC llvm teamSC llvm team
authored andcommitted
Merged main:5099dc341f7f into amd-gfx:ab27814b3805
Local branch amd-gfx ab27814 Merged main:7539bcf994ed into amd-gfx:0e8798f5c1bd Remote branch main 5099dc3 [Clang][CodeGen] Fix use of CXXThisValue with StrictVTablePointers (llvm#68169)
2 parents ab27814 + 5099dc3 commit ff56308

File tree

62 files changed

+6449
-1151
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

62 files changed

+6449
-1151
lines changed

clang/include/clang/Driver/Options.td

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4287,7 +4287,7 @@ def mcmodel_EQ : Joined<["-"], "mcmodel=">, Group<m_Group>,
42874287
MarshallingInfoString<TargetOpts<"CodeModel">, [{"default"}]>;
42884288
def mlarge_data_threshold_EQ : Joined<["-"], "mlarge-data-threshold=">, Group<m_Group>,
42894289
Visibility<[ClangOption, CC1Option]>,
4290-
MarshallingInfoInt<TargetOpts<"LargeDataThreshold">>;
4290+
MarshallingInfoInt<TargetOpts<"LargeDataThreshold">, "65535">;
42914291
def mtls_size_EQ : Joined<["-"], "mtls-size=">, Group<m_Group>,
42924292
Flags<[NoXarchOption]>, Visibility<[ClangOption, CC1Option]>,
42934293
HelpText<"Specify bit size of immediate TLS offsets (AArch64 ELF only): "

clang/lib/CodeGen/CGClass.cpp

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@
2828
#include "clang/CodeGen/CGFunctionInfo.h"
2929
#include "llvm/IR/Intrinsics.h"
3030
#include "llvm/IR/Metadata.h"
31+
#include "llvm/Support/SaveAndRestore.h"
3132
#include "llvm/Transforms/Utils/SanitizerStats.h"
3233
#include <optional>
3334

@@ -1291,10 +1292,10 @@ void CodeGenFunction::EmitCtorPrologue(const CXXConstructorDecl *CD,
12911292
assert(BaseCtorContinueBB);
12921293
}
12931294

1294-
llvm::Value *const OldThis = CXXThisValue;
12951295
for (; B != E && (*B)->isBaseInitializer() && (*B)->isBaseVirtual(); B++) {
12961296
if (!ConstructVBases)
12971297
continue;
1298+
SaveAndRestore ThisRAII(CXXThisValue);
12981299
if (CGM.getCodeGenOpts().StrictVTablePointers &&
12991300
CGM.getCodeGenOpts().OptimizationLevel > 0 &&
13001301
isInitializerOfDynamicClass(*B))
@@ -1311,16 +1312,14 @@ void CodeGenFunction::EmitCtorPrologue(const CXXConstructorDecl *CD,
13111312
// Then, non-virtual base initializers.
13121313
for (; B != E && (*B)->isBaseInitializer(); B++) {
13131314
assert(!(*B)->isBaseVirtual());
1314-
1315+
SaveAndRestore ThisRAII(CXXThisValue);
13151316
if (CGM.getCodeGenOpts().StrictVTablePointers &&
13161317
CGM.getCodeGenOpts().OptimizationLevel > 0 &&
13171318
isInitializerOfDynamicClass(*B))
13181319
CXXThisValue = Builder.CreateLaunderInvariantGroup(LoadCXXThis());
13191320
EmitBaseInitializer(*this, ClassDecl, *B);
13201321
}
13211322

1322-
CXXThisValue = OldThis;
1323-
13241323
InitializeVTablePointers(ClassDecl);
13251324

13261325
// And finally, initialize class members.

clang/lib/Format/WhitespaceManager.cpp

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -354,6 +354,9 @@ AlignTokenSequence(const FormatStyle &Style, unsigned Start, unsigned End,
354354
}
355355
}
356356

357+
if (Shift == 0)
358+
continue;
359+
357360
// This is for function parameters that are split across multiple lines,
358361
// as mentioned in the ScopeStack comment.
359362
if (InsideNestedScope && CurrentChange.NewlinesBefore > 0) {
@@ -447,7 +450,7 @@ AlignTokenSequence(const FormatStyle &Style, unsigned Start, unsigned End,
447450
CurrentChange.Spaces += Shift;
448451

449452
// We should not remove required spaces unless we break the line before.
450-
assert(Shift >= 0 || Changes[i].NewlinesBefore > 0 ||
453+
assert(Shift > 0 || Changes[i].NewlinesBefore > 0 ||
451454
CurrentChange.Spaces >=
452455
static_cast<int>(Changes[i].Tok->SpacesRequiredBefore) ||
453456
CurrentChange.Tok->is(tok::eof));

clang/test/CodeGen/large-data-threshold.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
// RUN: %clang_cc1 -triple x86_64-unknown-unknown -S %s -o - -mcmodel=medium -mlarge-data-threshold=200 | FileCheck %s --check-prefix=ASM-SMALL
66
// RUN: %clang_cc1 -triple x86_64-unknown-unknown -S %s -o - -mcmodel=medium -mlarge-data-threshold=2 | FileCheck %s --check-prefix=ASM-LARGE
77

8-
// IR-DEFAULT: !{i32 1, !"Large Data Threshold", i64 0}
8+
// IR-DEFAULT: !{i32 1, !"Large Data Threshold", i64 65535}
99
// IR-CUSTOM: !{i32 1, !"Large Data Threshold", i64 200}
1010

1111
// ASM-SMALL-NOT: movabsq
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
// RUN: %clang_cc1 %s -I%S -triple=x86_64-pc-windows-msvc -fstrict-vtable-pointers -disable-llvm-passes -O1 -emit-llvm -o %t.ll
2+
// RUN: FileCheck %s < %t.ll
3+
4+
struct A {
5+
virtual ~A();
6+
};
7+
struct B : virtual A {};
8+
class C : B {};
9+
C foo;
10+
11+
// CHECK-LABEL: define {{.*}} @"??0C@@QEAA@XZ"(ptr {{.*}} %this, i32 {{.*}} %is_most_derived)
12+
// CHECK: ctor.init_vbases:
13+
// CHECK-NEXT: %0 = getelementptr inbounds i8, ptr %this1, i64 0
14+
// CHECK-NEXT: store ptr @"??_8C@@7B@", ptr %0
15+
// CHECK-NEXT: %1 = call ptr @llvm.launder.invariant.group.p0(ptr %this1)
16+
// CHECK-NEXT: %2 = getelementptr inbounds i8, ptr %1, i64 8
17+
// CHECK-NEXT: %call = call noundef ptr @"??0A@@QEAA@XZ"(ptr {{.*}} %2) #2
18+
// CHECK-NEXT: br label %ctor.skip_vbases
19+
// CHECK-EMPTY:
20+
// CHECK-NEXT: ctor.skip_vbases:
21+
// CHECK-NEXT: %3 = call ptr @llvm.launder.invariant.group.p0(ptr %this1)
22+
// CHECK-NEXT: %call3 = call noundef ptr @"??0B@@QEAA@XZ"(ptr {{.*}} %3, i32 noundef 0) #2

libc/src/__support/float_to_string.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -708,7 +708,7 @@ FloatToString<long double>::get_negative_block(int block_index) {
708708
const int32_t SHIFT_CONST = TABLE_SHIFT_CONST;
709709

710710
// if the requested block is zero
711-
if (block_index <= MIN_BLOCK_2[idx]) {
711+
if (block_index < MIN_BLOCK_2[idx]) {
712712
return 0;
713713
}
714714
const uint32_t p = POW10_OFFSET_2[idx] + block_index - MIN_BLOCK_2[idx];

libc/startup/linux/x86_64/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ add_startup_object(
1010
libc.src.__support.threads.thread
1111
libc.src.__support.OSUtil.osutil
1212
libc.src.stdlib.exit
13+
libc.src.stdlib.abort
1314
libc.src.stdlib.atexit
1415
libc.src.string.memory_utils.inline_memcpy
1516
libc.src.unistd.environ

libc/startup/linux/x86_64/start.cpp

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,10 @@
77
//===----------------------------------------------------------------------===//
88

99
#include "config/linux/app.h"
10+
#include "src/__support/OSUtil/io.h"
1011
#include "src/__support/OSUtil/syscall.h"
1112
#include "src/__support/threads/thread.h"
13+
#include "src/stdlib/abort.h"
1214
#include "src/stdlib/atexit.h"
1315
#include "src/stdlib/exit.h"
1416
#include "src/string/memory_utils/inline_memcpy.h"
@@ -23,6 +25,11 @@
2325

2426
extern "C" int main(int, char **, char **);
2527

28+
extern "C" void __stack_chk_fail() {
29+
LIBC_NAMESPACE::write_to_stderr("stack smashing detected");
30+
LIBC_NAMESPACE::abort();
31+
}
32+
2633
namespace LIBC_NAMESPACE {
2734

2835
#ifdef SYS_mmap2
@@ -54,7 +61,9 @@ void init_tls(TLSDescriptor &tls_descriptor) {
5461
// Per the x86_64 TLS ABI, the entry pointed to by the thread pointer is the
5562
// address of the TLS block. So, we add more size to accomodate this address
5663
// entry.
57-
uintptr_t tlsSizeWithAddr = tlsSize + sizeof(uintptr_t);
64+
// We also need to include space for the stack canary. The canary is at
65+
// offset 0x28 (40) and is of size uintptr_t.
66+
uintptr_t tlsSizeWithAddr = tlsSize + sizeof(uintptr_t) + 40;
5867

5968
// We cannot call the mmap function here as the functions set errno on
6069
// failure. Since errno is implemented via a thread local variable, we cannot
@@ -76,6 +85,16 @@ void init_tls(TLSDescriptor &tls_descriptor) {
7685
LIBC_NAMESPACE::inline_memcpy(reinterpret_cast<char *>(tlsAddr),
7786
reinterpret_cast<const char *>(app.tls.address),
7887
app.tls.init_size);
88+
uintptr_t *stackGuardAddr = reinterpret_cast<uintptr_t *>(endPtr + 40);
89+
// Setting the stack guard to a random value.
90+
// We cannot call the get_random function here as the function sets errno on
91+
// failure. Since errno is implemented via a thread local variable, we cannot
92+
// use errno before TLS is setup.
93+
ssize_t stackGuardRetVal = LIBC_NAMESPACE::syscall_impl<ssize_t>(
94+
SYS_getrandom, reinterpret_cast<long>(stackGuardAddr), sizeof(uint64_t),
95+
0);
96+
if (stackGuardRetVal < 0)
97+
LIBC_NAMESPACE::syscall_impl(SYS_exit, 1);
7998

8099
tls_descriptor = {tlsSizeWithAddr, uintptr_t(tlsAddr), endPtr};
81100
return;

libc/test/integration/src/unistd/CMakeLists.txt

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,29 @@ add_integration_test(
3333
libc.src.unistd.fork
3434
)
3535

36+
if((${LIBC_TARGET_OS} STREQUAL "linux") AND (${LIBC_TARGET_ARCHITECTURE_IS_X86}))
37+
add_integration_test(
38+
stack_smashing_test
39+
SUITE
40+
unistd-integration-tests
41+
SRCS
42+
stack_smashing_test.cpp
43+
DEPENDS
44+
libc.include.errno
45+
libc.include.signal
46+
libc.include.sys_wait
47+
libc.include.unistd
48+
libc.src.pthread.pthread_atfork
49+
libc.src.signal.raise
50+
libc.src.sys.wait.wait
51+
libc.src.sys.wait.wait4
52+
libc.src.sys.wait.waitpid
53+
libc.src.unistd.fork
54+
COMPILE_OPTIONS
55+
-fstack-protector-all
56+
)
57+
endif()
58+
3659
add_executable(
3760
libc_execv_test_normal_exit
3861
EXCLUDE_FROM_ALL
Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
//===--- Stack smashing test to check stack canary set up ----------------===//
2+
//
3+
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4+
// See https://llvm.org/LICENSE.txt for license information.
5+
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6+
//
7+
//===----------------------------------------------------------------------===//
8+
9+
#include "src/__support/CPP/string.h"
10+
#include "src/__support/OSUtil/io.h"
11+
#include "src/pthread/pthread_atfork.h"
12+
#include "src/signal/raise.h"
13+
#include "src/sys/wait/wait.h"
14+
#include "src/sys/wait/wait4.h"
15+
#include "src/sys/wait/waitpid.h"
16+
#include "src/unistd/fork.h"
17+
18+
#include "test/IntegrationTest/test.h"
19+
20+
#include <errno.h>
21+
#include <signal.h>
22+
#include <sys/wait.h>
23+
#include <unistd.h>
24+
25+
void no_stack_smashing_normal_exit() {
26+
pid_t pid = LIBC_NAMESPACE::fork();
27+
if (pid == 0) {
28+
// Child process
29+
char foo[30];
30+
for (int i = 0; i < 30; i++)
31+
foo[i] = (foo[i] != 42) ? 42 : 24;
32+
return;
33+
}
34+
ASSERT_TRUE(pid > 0);
35+
int status;
36+
pid_t cpid = LIBC_NAMESPACE::wait(&status);
37+
ASSERT_TRUE(cpid > 0);
38+
ASSERT_EQ(cpid, pid);
39+
ASSERT_TRUE(WIFEXITED(status));
40+
}
41+
42+
void stack_smashing_abort() {
43+
pid_t pid = LIBC_NAMESPACE::fork();
44+
if (pid == 0) {
45+
// Child process
46+
char foo[30];
47+
char *frame_ptr = static_cast<char *>(__builtin_frame_address(0));
48+
char *cur_ptr = &foo[0];
49+
// Corrupt the stack
50+
while (cur_ptr != frame_ptr) {
51+
*cur_ptr = (*cur_ptr != 42) ? 42 : 24;
52+
cur_ptr++;
53+
}
54+
return;
55+
}
56+
ASSERT_TRUE(pid > 0);
57+
int status;
58+
pid_t cpid = LIBC_NAMESPACE::wait(&status);
59+
ASSERT_TRUE(cpid > 0);
60+
ASSERT_EQ(cpid, pid);
61+
ASSERT_TRUE(WTERMSIG(status) == SIGABRT);
62+
}
63+
64+
TEST_MAIN(int argc, char **argv, char **envp) {
65+
no_stack_smashing_normal_exit();
66+
stack_smashing_abort();
67+
return 0;
68+
}

0 commit comments

Comments
 (0)