llvm / llvm-project

The LLVM Project is a collection of modular and reusable compiler and toolchain technologies.
http://llvm.org
Other
29.25k stars 12.08k forks source link

Function std::terminate can be created without type metadata resulting in assertion failure linking libc++ with ThinLTO + cfi-icall #33099

Open pcc opened 7 years ago

pcc commented 7 years ago
Bugzilla Link 33752
Version trunk
OS Linux
CC @eugenis

Extended Description

$ cat term.cpp namespace test0 { void foo() {}

struct A { A(); ~A(); };

void test() noexcept { A a; foo(); } } // namespace test0

namespace std { void terminate() {} }

void f(void (*p)()) { p(); }

void *g();

int main(int argc, char *argv) { f((void ()())g()); } $ cat term2.cpp namespace std {

void terminate();

}

void g() { return (void )&std::terminate; } $ ~/src2/llvm-project/ra/bin/clang -fsanitize=cfi-icall term.cpp term2.cpp -flto=thin -std=c++11 -fuse-ld=lld ld.lld: lib/Transforms/IPO/LowerTypeTests.cpp:860: void (anonymous namespace)::LowerTypeTestsModule::importFunction(llvm::Function *, bool): Assertion `isDefinition' failed.

pcc commented 7 years ago

r307744 fixes the assertion failure, but the type metadata is still missing.

pcc commented 7 years ago

There are actually two bugs:

The second issue can be encountered in a relatively common case (mixed CFI + non-CFI compilation). After discussion with Evgeniy I think the right thing to do about functions without type metadata in the pass is to skip them. Then they will basically be treated the same way as functions that are defined outside of the LTO unit (e.g. in a regular object file).

Separately, we need to fix clang so that it adds type metadata to the definition of std::terminate (and perhaps other builtin functions), but that seems less important than fixing the pass.