Skip to content

Commit

Permalink
Merged main:5099dc341f7f into amd-gfx:ab27814b3805
Browse files Browse the repository at this point in the history
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)
  • Loading branch information
SC llvm team authored and SC llvm team committed Oct 4, 2023
2 parents ab27814 + 5099dc3 commit ff56308
Show file tree
Hide file tree
Showing 62 changed files with 6,449 additions and 1,151 deletions.
2 changes: 1 addition & 1 deletion clang/include/clang/Driver/Options.td
Original file line number Diff line number Diff line change
Expand Up @@ -4287,7 +4287,7 @@ def mcmodel_EQ : Joined<["-"], "mcmodel=">, Group<m_Group>,
MarshallingInfoString<TargetOpts<"CodeModel">, [{"default"}]>;
def mlarge_data_threshold_EQ : Joined<["-"], "mlarge-data-threshold=">, Group<m_Group>,
Visibility<[ClangOption, CC1Option]>,
MarshallingInfoInt<TargetOpts<"LargeDataThreshold">>;
MarshallingInfoInt<TargetOpts<"LargeDataThreshold">, "65535">;
def mtls_size_EQ : Joined<["-"], "mtls-size=">, Group<m_Group>,
Flags<[NoXarchOption]>, Visibility<[ClangOption, CC1Option]>,
HelpText<"Specify bit size of immediate TLS offsets (AArch64 ELF only): "
Expand Down
7 changes: 3 additions & 4 deletions clang/lib/CodeGen/CGClass.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
#include "clang/CodeGen/CGFunctionInfo.h"
#include "llvm/IR/Intrinsics.h"
#include "llvm/IR/Metadata.h"
#include "llvm/Support/SaveAndRestore.h"
#include "llvm/Transforms/Utils/SanitizerStats.h"
#include <optional>

Expand Down Expand Up @@ -1291,10 +1292,10 @@ void CodeGenFunction::EmitCtorPrologue(const CXXConstructorDecl *CD,
assert(BaseCtorContinueBB);
}

llvm::Value *const OldThis = CXXThisValue;
for (; B != E && (*B)->isBaseInitializer() && (*B)->isBaseVirtual(); B++) {
if (!ConstructVBases)
continue;
SaveAndRestore ThisRAII(CXXThisValue);
if (CGM.getCodeGenOpts().StrictVTablePointers &&
CGM.getCodeGenOpts().OptimizationLevel > 0 &&
isInitializerOfDynamicClass(*B))
Expand All @@ -1311,16 +1312,14 @@ void CodeGenFunction::EmitCtorPrologue(const CXXConstructorDecl *CD,
// Then, non-virtual base initializers.
for (; B != E && (*B)->isBaseInitializer(); B++) {
assert(!(*B)->isBaseVirtual());

SaveAndRestore ThisRAII(CXXThisValue);
if (CGM.getCodeGenOpts().StrictVTablePointers &&
CGM.getCodeGenOpts().OptimizationLevel > 0 &&
isInitializerOfDynamicClass(*B))
CXXThisValue = Builder.CreateLaunderInvariantGroup(LoadCXXThis());
EmitBaseInitializer(*this, ClassDecl, *B);
}

CXXThisValue = OldThis;

InitializeVTablePointers(ClassDecl);

// And finally, initialize class members.
Expand Down
5 changes: 4 additions & 1 deletion clang/lib/Format/WhitespaceManager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -354,6 +354,9 @@ AlignTokenSequence(const FormatStyle &Style, unsigned Start, unsigned End,
}
}

if (Shift == 0)
continue;

// This is for function parameters that are split across multiple lines,
// as mentioned in the ScopeStack comment.
if (InsideNestedScope && CurrentChange.NewlinesBefore > 0) {
Expand Down Expand Up @@ -447,7 +450,7 @@ AlignTokenSequence(const FormatStyle &Style, unsigned Start, unsigned End,
CurrentChange.Spaces += Shift;

// We should not remove required spaces unless we break the line before.
assert(Shift >= 0 || Changes[i].NewlinesBefore > 0 ||
assert(Shift > 0 || Changes[i].NewlinesBefore > 0 ||
CurrentChange.Spaces >=
static_cast<int>(Changes[i].Tok->SpacesRequiredBefore) ||
CurrentChange.Tok->is(tok::eof));
Expand Down
2 changes: 1 addition & 1 deletion clang/test/CodeGen/large-data-threshold.c
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
// RUN: %clang_cc1 -triple x86_64-unknown-unknown -S %s -o - -mcmodel=medium -mlarge-data-threshold=200 | FileCheck %s --check-prefix=ASM-SMALL
// RUN: %clang_cc1 -triple x86_64-unknown-unknown -S %s -o - -mcmodel=medium -mlarge-data-threshold=2 | FileCheck %s --check-prefix=ASM-LARGE

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

// ASM-SMALL-NOT: movabsq
Expand Down
22 changes: 22 additions & 0 deletions clang/test/CodeGenCXX/strict-vtable-pointers-GH67937.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
// RUN: %clang_cc1 %s -I%S -triple=x86_64-pc-windows-msvc -fstrict-vtable-pointers -disable-llvm-passes -O1 -emit-llvm -o %t.ll
// RUN: FileCheck %s < %t.ll

struct A {
virtual ~A();
};
struct B : virtual A {};
class C : B {};
C foo;

// CHECK-LABEL: define {{.*}} @"??0C@@QEAA@XZ"(ptr {{.*}} %this, i32 {{.*}} %is_most_derived)
// CHECK: ctor.init_vbases:
// CHECK-NEXT: %0 = getelementptr inbounds i8, ptr %this1, i64 0
// CHECK-NEXT: store ptr @"??_8C@@7B@", ptr %0
// CHECK-NEXT: %1 = call ptr @llvm.launder.invariant.group.p0(ptr %this1)
// CHECK-NEXT: %2 = getelementptr inbounds i8, ptr %1, i64 8
// CHECK-NEXT: %call = call noundef ptr @"??0A@@QEAA@XZ"(ptr {{.*}} %2) #2
// CHECK-NEXT: br label %ctor.skip_vbases
// CHECK-EMPTY:
// CHECK-NEXT: ctor.skip_vbases:
// CHECK-NEXT: %3 = call ptr @llvm.launder.invariant.group.p0(ptr %this1)
// CHECK-NEXT: %call3 = call noundef ptr @"??0B@@QEAA@XZ"(ptr {{.*}} %3, i32 noundef 0) #2
2 changes: 1 addition & 1 deletion libc/src/__support/float_to_string.h
Original file line number Diff line number Diff line change
Expand Up @@ -708,7 +708,7 @@ FloatToString<long double>::get_negative_block(int block_index) {
const int32_t SHIFT_CONST = TABLE_SHIFT_CONST;

// if the requested block is zero
if (block_index <= MIN_BLOCK_2[idx]) {
if (block_index < MIN_BLOCK_2[idx]) {
return 0;
}
const uint32_t p = POW10_OFFSET_2[idx] + block_index - MIN_BLOCK_2[idx];
Expand Down
1 change: 1 addition & 0 deletions libc/startup/linux/x86_64/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ add_startup_object(
libc.src.__support.threads.thread
libc.src.__support.OSUtil.osutil
libc.src.stdlib.exit
libc.src.stdlib.abort
libc.src.stdlib.atexit
libc.src.string.memory_utils.inline_memcpy
libc.src.unistd.environ
Expand Down
21 changes: 20 additions & 1 deletion libc/startup/linux/x86_64/start.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,10 @@
//===----------------------------------------------------------------------===//

#include "config/linux/app.h"
#include "src/__support/OSUtil/io.h"
#include "src/__support/OSUtil/syscall.h"
#include "src/__support/threads/thread.h"
#include "src/stdlib/abort.h"
#include "src/stdlib/atexit.h"
#include "src/stdlib/exit.h"
#include "src/string/memory_utils/inline_memcpy.h"
Expand All @@ -23,6 +25,11 @@

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
Expand Down Expand Up @@ -54,7 +61,9 @@ void init_tls(TLSDescriptor &tls_descriptor) {
// Per the x86_64 TLS ABI, the entry pointed to by the thread pointer is the
// address of the TLS block. So, we add more size to accomodate this address
// entry.
uintptr_t tlsSizeWithAddr = tlsSize + sizeof(uintptr_t);
// We also need to include space for the stack canary. The canary is at
// offset 0x28 (40) and is of size uintptr_t.
uintptr_t tlsSizeWithAddr = tlsSize + sizeof(uintptr_t) + 40;

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

tls_descriptor = {tlsSizeWithAddr, uintptr_t(tlsAddr), endPtr};
return;
Expand Down
23 changes: 23 additions & 0 deletions libc/test/integration/src/unistd/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,29 @@ add_integration_test(
libc.src.unistd.fork
)

if((${LIBC_TARGET_OS} STREQUAL "linux") AND (${LIBC_TARGET_ARCHITECTURE_IS_X86}))
add_integration_test(
stack_smashing_test
SUITE
unistd-integration-tests
SRCS
stack_smashing_test.cpp
DEPENDS
libc.include.errno
libc.include.signal
libc.include.sys_wait
libc.include.unistd
libc.src.pthread.pthread_atfork
libc.src.signal.raise
libc.src.sys.wait.wait
libc.src.sys.wait.wait4
libc.src.sys.wait.waitpid
libc.src.unistd.fork
COMPILE_OPTIONS
-fstack-protector-all
)
endif()

add_executable(
libc_execv_test_normal_exit
EXCLUDE_FROM_ALL
Expand Down
68 changes: 68 additions & 0 deletions libc/test/integration/src/unistd/stack_smashing_test.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
//===--- Stack smashing test to check stack canary set up ----------------===//
//
// 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/__support/CPP/string.h"
#include "src/__support/OSUtil/io.h"
#include "src/pthread/pthread_atfork.h"
#include "src/signal/raise.h"
#include "src/sys/wait/wait.h"
#include "src/sys/wait/wait4.h"
#include "src/sys/wait/waitpid.h"
#include "src/unistd/fork.h"

#include "test/IntegrationTest/test.h"

#include <errno.h>
#include <signal.h>
#include <sys/wait.h>
#include <unistd.h>

void no_stack_smashing_normal_exit() {
pid_t pid = LIBC_NAMESPACE::fork();
if (pid == 0) {
// Child process
char foo[30];
for (int i = 0; i < 30; i++)
foo[i] = (foo[i] != 42) ? 42 : 24;
return;
}
ASSERT_TRUE(pid > 0);
int status;
pid_t cpid = LIBC_NAMESPACE::wait(&status);
ASSERT_TRUE(cpid > 0);
ASSERT_EQ(cpid, pid);
ASSERT_TRUE(WIFEXITED(status));
}

void stack_smashing_abort() {
pid_t pid = LIBC_NAMESPACE::fork();
if (pid == 0) {
// Child process
char foo[30];
char *frame_ptr = static_cast<char *>(__builtin_frame_address(0));
char *cur_ptr = &foo[0];
// Corrupt the stack
while (cur_ptr != frame_ptr) {
*cur_ptr = (*cur_ptr != 42) ? 42 : 24;
cur_ptr++;
}
return;
}
ASSERT_TRUE(pid > 0);
int status;
pid_t cpid = LIBC_NAMESPACE::wait(&status);
ASSERT_TRUE(cpid > 0);
ASSERT_EQ(cpid, pid);
ASSERT_TRUE(WTERMSIG(status) == SIGABRT);
}

TEST_MAIN(int argc, char **argv, char **envp) {
no_stack_smashing_normal_exit();
stack_smashing_abort();
return 0;
}
19 changes: 19 additions & 0 deletions libc/test/src/stdio/sprintf_test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2433,6 +2433,9 @@ TEST_F(LlvmLibcSPrintfTest, FloatAutoConv) {
written = LIBC_NAMESPACE::sprintf(buff, "%g", 9999999000000.00);
ASSERT_STREQ_LEN(written, buff, "1e+13");

written = LIBC_NAMESPACE::sprintf(buff, "%g", 0xa.aaaaaaaaaaaaaabp-7);
ASSERT_STREQ_LEN(written, buff, "0.0833333");

// Simple Subnormal Tests.

written = LIBC_NAMESPACE::sprintf(buff, "%g", 0x1.0p-1027);
Expand All @@ -2457,9 +2460,16 @@ TEST_F(LlvmLibcSPrintfTest, FloatAutoConv) {

// Length Modifier Tests.

#if defined(SPECIAL_X86_LONG_DOUBLE)

written = LIBC_NAMESPACE::sprintf(buff, "%Lg", 0xf.fffffffffffffffp+16380L);
ASSERT_STREQ_LEN(written, buff, "1.18973e+4932");

written = LIBC_NAMESPACE::sprintf(buff, "%Lg", 0xa.aaaaaaaaaaaaaabp-7L);
ASSERT_STREQ_LEN(written, buff, "0.0833333");

#endif // SPECIAL_X86_LONG_DOUBLE

// TODO: Uncomment the below tests after long double support is added
/*
written = LIBC_NAMESPACE::sprintf(buff, "%Lf", 1e100L);
Expand Down Expand Up @@ -2757,6 +2767,15 @@ TEST_F(LlvmLibcSPrintfTest, FloatAutoConv) {
written = LIBC_NAMESPACE::sprintf(buff, "%.10g", 0x1.0p-1074);
ASSERT_STREQ_LEN(written, buff, "4.940656458e-324");

#if defined(SPECIAL_X86_LONG_DOUBLE)

written = LIBC_NAMESPACE::sprintf(buff, "%.60Lg", 0xa.aaaaaaaaaaaaaabp-7L);
ASSERT_STREQ_LEN(
written, buff,
"0.0833333333333333333355920878593448009041821933351457118988037");

#endif // SPECIAL_X86_LONG_DOUBLE

// Long double precision tests.
// These are currently commented out because they require long double support
// that isn't ready yet.
Expand Down
6 changes: 5 additions & 1 deletion libcxx/include/__algorithm/pstl_backend.h
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,11 @@ A PSTL parallel backend is a tag type to which the following functions are assoc
_Comp __comp);
template <class _ExecutionPolicy, class _InIterator, class _OutIterator, class _UnaryOperation>
_OutIterator __pstl_transform(_Backend, _InIterator __first, _InIterator __last, _OutIterator __result, _UnaryOperation __op);
_OutIterator __pstl_transform(_Backend,
_InIterator __first,
_InIterator __last,
_OutIterator __result,
_UnaryOperation __op);
template <class _ExecutionPolicy, class _InIterator1, class _InIterator2, class _OutIterator, class _BinaryOperation>
_OutIterator __pstl_transform(_Backend,
Expand Down
43 changes: 42 additions & 1 deletion lld/ELF/Arch/X86_64.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,14 @@
//===----------------------------------------------------------------------===//

#include "OutputSections.h"
#include "Relocations.h"
#include "Symbols.h"
#include "SyntheticSections.h"
#include "Target.h"
#include "lld/Common/ErrorHandler.h"
#include "llvm/BinaryFormat/ELF.h"
#include "llvm/Support/Endian.h"
#include "llvm/Support/MathExtras.h"

using namespace llvm;
using namespace llvm::object;
Expand Down Expand Up @@ -47,6 +49,7 @@ class X86_64 : public TargetInfo {
uint8_t stOther) const override;
bool deleteFallThruJmpInsn(InputSection &is, InputFile *file,
InputSection *nextIS) const override;
bool relaxOnce(int pass) const override;
};
} // namespace

Expand Down Expand Up @@ -305,6 +308,43 @@ bool X86_64::deleteFallThruJmpInsn(InputSection &is, InputFile *file,
return true;
}

bool X86_64::relaxOnce(int pass) const {
uint64_t minVA = UINT64_MAX, maxVA = 0;
for (OutputSection *osec : outputSections) {
minVA = std::min(minVA, osec->addr);
maxVA = std::max(maxVA, osec->addr + osec->size);
}
// If the max VA difference is under 2^31, GOT-generating relocations with a 32-bit range cannot overflow.
if (isUInt<31>(maxVA - minVA))
return false;

SmallVector<InputSection *, 0> storage;
bool changed = false;
for (OutputSection *osec : outputSections) {
if (!(osec->flags & SHF_EXECINSTR))
continue;
for (InputSection *sec : getInputSections(*osec, storage)) {
for (Relocation &rel : sec->relocs()) {
if (rel.expr != R_RELAX_GOT_PC)
continue;

uint64_t v = sec->getRelocTargetVA(
sec->file, rel.type, rel.addend,
sec->getOutputSection()->addr + rel.offset, *rel.sym, rel.expr);
if (isInt<32>(v))
continue;
if (rel.sym->auxIdx == 0) {
rel.sym->allocateAux();
addGotEntry(*rel.sym);
changed = true;
}
rel.expr = R_GOT_PC;
}
}
}
return changed;
}

RelExpr X86_64::getRelExpr(RelType type, const Symbol &s,
const uint8_t *loc) const {
switch (type) {
Expand Down Expand Up @@ -912,7 +952,8 @@ static void relaxGotNoPic(uint8_t *loc, uint64_t val, uint8_t op,
}

static void relaxGot(uint8_t *loc, const Relocation &rel, uint64_t val) {
checkInt(loc, val, 32, rel);
assert(isInt<32>(val) &&
"GOTPCRELX should not have been relaxed if it overflows");
const uint8_t op = loc[-2];
const uint8_t modRm = loc[-1];

Expand Down
Loading

0 comments on commit ff56308

Please sign in to comment.