Index: lib/ubsan/ubsan_handlers.cc =================================================================== --- lib/ubsan/ubsan_handlers.cc +++ lib/ubsan/ubsan_handlers.cc @@ -660,6 +660,20 @@ if (!FName) FName = "(unknown)"; Diag(FLoc, DL_Note, ET, "%0 defined here") << FName; + + // If the failure occurred due to a cross-DSO icall, report the DSO names. + const char *DstModule = FLoc.get()->info.module; + if (!DstModule) + DstModule = "(unknown)"; + + const char *SrcModule = Symbolizer::GetOrInit()->GetModuleNameForPc(Opts.pc); + if (!SrcModule) + SrcModule = "(unknown)"; + + if (internal_strcmp(SrcModule, DstModule)) + Diag(Loc, DL_Note, ET, + "check failed in %0, destination function located in %1") + << SrcModule << DstModule; } namespace __ubsan { Index: lib/ubsan/ubsan_handlers_cxx.cc =================================================================== --- lib/ubsan/ubsan_handlers_cxx.cc +++ lib/ubsan/ubsan_handlers_cxx.cc @@ -137,16 +137,25 @@ << Data->Type << CheckKindStr << (void *)Vtable; // If possible, say what type it actually points to. - if (!DTI.isValid()) { - const char *module = Symbolizer::GetOrInit()->GetModuleNameForPc(Vtable); - if (module) - Diag(Vtable, DL_Note, ET, "invalid vtable in module %0") << module; - else - Diag(Vtable, DL_Note, ET, "invalid vtable"); - } else { + if (!DTI.isValid()) + Diag(Vtable, DL_Note, ET, "invalid vtable"); + else Diag(Vtable, DL_Note, ET, "vtable is of type %0") << TypeName(DTI.getMostDerivedTypeName()); - } + + // If the failure involved different DSOs for the check location and vtable, + // report the DSO names. + const char *DstModule = Symbolizer::GetOrInit()->GetModuleNameForPc(Vtable); + if (!DstModule) + DstModule = "(unknown)"; + + const char *SrcModule = Symbolizer::GetOrInit()->GetModuleNameForPc(Opts.pc); + if (!SrcModule) + SrcModule = "(unknown)"; + + if (internal_strcmp(SrcModule, DstModule)) + Diag(Loc, DL_Note, ET, "check failed in %0, vtable located in %1") + << SrcModule << DstModule; } } // namespace __ubsan Index: test/cfi/cross-dso-diagnostic.cpp =================================================================== --- /dev/null +++ test/cfi/cross-dso-diagnostic.cpp @@ -0,0 +1,29 @@ +// Check that cross-DSO diagnostics print the names of both modules + +// RUN: %clangxx_cfi_diag -g -o %t %s -ldl +// RUN: %t 2>&1 | FileCheck %s + +// REQUIRES: cxxabi + +#include +#include + +struct S1 { + virtual void f1(); +}; + +void S1::f1() {} + +int main() { + // CHECK: runtime error: control flow integrity check for type 'void (int)' failed during indirect function call + // CHECK: getpid defined here + // CHECK: check failed in {{.*}}, destination function located in {{.*}} + void (*fp)(int) = + reinterpret_cast(dlsym(RTLD_DEFAULT, "getpid")); + fp(1); // trigger cfi-icall failure + + // CHECK: runtime error: control flow integrity check for type 'S1' failed during cast to unrelated type + // CHECK: invalid vtable + // CHECK: check failed in {{.*}}, vtable located in {{.*}} + S1 *S = reinterpret_cast(fp); // trigger cfi-unrelated-cast failure +}