Runtime support for the indirect function call checker.

Differential Revision: http://llvm-reviews.chandlerc.com/D1339

llvm-svn: 193060
This commit is contained in:
Peter Collingbourne 2013-10-20 21:29:46 +00:00
parent b714e7e12a
commit 90a0876ae7
9 changed files with 70 additions and 0 deletions

View File

@ -137,6 +137,8 @@ endif()
add_compiler_rt_resource_file(asan_blacklist asan_blacklist.txt)
add_custom_target(asan DEPENDS asan_blacklist ${ASAN_RUNTIME_LIBRARIES})
if(LLVM_INCLUDE_TESTS)
add_subdirectory(tests)
endif()

View File

@ -8,6 +8,7 @@ if(COMPILER_RT_CAN_EXECUTE_TESTS)
# working binaries.
set(UBSAN_TEST_DEPS
${SANITIZER_COMMON_LIT_TEST_DEPS}
asan
${UBSAN_RUNTIME_LIBRARIES})
set(UBSAN_TEST_PARAMS
ubsan_site_config=${CMAKE_CURRENT_BINARY_DIR}/lit.site.cfg

View File

@ -0,0 +1,17 @@
// RUN: %clangxx -fsanitize=address,function %s -O3 -g -o %t
// RUN: %t 2>&1 | FileCheck %s
#include <stdint.h>
void f() {}
void g(int x) {}
int main(void) {
// CHECK: runtime error: call to function f() through pointer to incorrect function type 'void (*)(int)'
// CHECK-NEXT: function.cpp:6: note: f() defined here
reinterpret_cast<void (*)(int)>(reinterpret_cast<uintptr_t>(f))(42);
// CHECK-NOT: runtime error: call to function g
reinterpret_cast<void (*)(int)>(reinterpret_cast<uintptr_t>(g))(42);
}

View File

@ -0,0 +1,3 @@
# The function type checker is only supported on x86 and x86_64 for now.
if config.root.host_arch not in ['x86', 'x86_64']:
config.unsupported = True

View File

@ -54,6 +54,9 @@ config.substitutions.append( ("%clang ", (" " + config.clang + " ")) )
config.substitutions.append( ("%clangxx ", (" " + config.clang +
" --driver-mode=g++ ")) )
# Setup path to external LLVM symbolizer.
config.environment['ASAN_SYMBOLIZER_PATH'] = config.llvm_symbolizer_path
# Default test suffixes.
config.suffixes = ['.c', '.cc', '.cpp']

View File

@ -26,12 +26,21 @@ Location __ubsan::getCallerLocation(uptr CallerLoc) {
return Location();
uptr Loc = StackTrace::GetPreviousInstructionPc(CallerLoc);
return getFunctionLocation(Loc, 0);
}
Location __ubsan::getFunctionLocation(uptr Loc, const char **FName) {
if (!Loc)
return Location();
AddressInfo Info;
if (!getSymbolizer()->SymbolizeCode(Loc, &Info, 1) ||
!Info.module || !*Info.module)
return Location(Loc);
if (FName && Info.function)
*FName = Info.function;
if (!Info.file)
return ModuleLocation(Info.module, Info.module_offset);

View File

@ -80,6 +80,12 @@ public:
/// an invalid location or a module location for the caller.
Location getCallerLocation(uptr CallerLoc = GET_CALLER_PC());
/// Try to obtain a location for the given function pointer. This might fail,
/// and produce either an invalid location or a module location for the caller.
/// If FName is non-null and the name of the function is known, set *FName to
/// the function name, otherwise *FName is unchanged.
Location getFunctionLocation(uptr Loc, const char **FName);
/// A diagnostic severity level.
enum DiagLevel {
DL_Error, ///< An error.

View File

@ -259,3 +259,23 @@ void __ubsan::__ubsan_handle_load_invalid_value_abort(InvalidValueData *Data,
__ubsan_handle_load_invalid_value(Data, Val);
Die();
}
void __ubsan::__ubsan_handle_function_type_mismatch(
FunctionTypeMismatchData *Data,
ValueHandle Function) {
const char *FName = "(unknown)";
Location Loc = getFunctionLocation(Function, &FName);
Diag(Data->Loc, DL_Error,
"call to function %0 through pointer to incorrect function type %1")
<< FName << Data->Type;
Diag(Loc, DL_Note, "%0 defined here") << FName;
}
void __ubsan::__ubsan_handle_function_type_mismatch_abort(
FunctionTypeMismatchData *Data,
ValueHandle Function) {
__ubsan_handle_function_type_mismatch(Data, Function);
Die();
}

View File

@ -112,6 +112,15 @@ struct InvalidValueData {
/// \brief Handle a load of an invalid value for the type.
RECOVERABLE(load_invalid_value, InvalidValueData *Data, ValueHandle Val)
struct FunctionTypeMismatchData {
SourceLocation Loc;
const TypeDescriptor &Type;
};
RECOVERABLE(function_type_mismatch,
FunctionTypeMismatchData *Data,
ValueHandle Val)
}
#endif // UBSAN_HANDLERS_H