diff options
author | kcc <kcc@138bc75d-0d04-0410-961f-82ee72b054a4> | 2013-12-05 09:18:38 +0000 |
---|---|---|
committer | kcc <kcc@138bc75d-0d04-0410-961f-82ee72b054a4> | 2013-12-05 09:18:38 +0000 |
commit | 4fc7b5acfc1d42a0701c8fff726a3ebe7f563dd9 (patch) | |
tree | 20d85354103063e38b162a6a90b7ae51fb4b6104 /libsanitizer/ubsan | |
parent | 50e6c257ee5ad435e3a736a1375ccc7639fd9244 (diff) | |
download | gcc-4fc7b5acfc1d42a0701c8fff726a3ebe7f563dd9.tar.gz |
libsanitizer merge from upstream r196090
git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@205695 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'libsanitizer/ubsan')
-rw-r--r-- | libsanitizer/ubsan/ubsan_diag.cc | 33 | ||||
-rw-r--r-- | libsanitizer/ubsan/ubsan_diag.h | 6 | ||||
-rw-r--r-- | libsanitizer/ubsan/ubsan_handlers.cc | 31 | ||||
-rw-r--r-- | libsanitizer/ubsan/ubsan_handlers.h | 11 | ||||
-rw-r--r-- | libsanitizer/ubsan/ubsan_type_hash.cc | 16 | ||||
-rw-r--r-- | libsanitizer/ubsan/ubsan_value.h | 4 |
6 files changed, 74 insertions, 27 deletions
diff --git a/libsanitizer/ubsan/ubsan_diag.cc b/libsanitizer/ubsan/ubsan_diag.cc index c7378fdbda2..786ffa7254f 100644 --- a/libsanitizer/ubsan/ubsan_diag.cc +++ b/libsanitizer/ubsan/ubsan_diag.cc @@ -24,12 +24,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) || + if (!Symbolizer::GetOrInit()->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); @@ -66,29 +75,29 @@ static void PrintHex(UIntMax Val) { } static void renderLocation(Location Loc) { + InternalScopedString LocBuffer(1024); switch (Loc.getKind()) { case Location::LK_Source: { SourceLocation SLoc = Loc.getSourceLocation(); if (SLoc.isInvalid()) - Printf("<unknown>:"); - else { - Printf("%s:%d:", SLoc.getFilename(), SLoc.getLine()); - if (SLoc.getColumn()) - Printf("%d:", SLoc.getColumn()); - } + LocBuffer.append("<unknown>"); + else + PrintSourceLocation(&LocBuffer, SLoc.getFilename(), SLoc.getLine(), + SLoc.getColumn()); break; } case Location::LK_Module: - Printf("%s:0x%zx:", Loc.getModuleLocation().getModuleName(), - Loc.getModuleLocation().getOffset()); + PrintModuleAndOffset(&LocBuffer, Loc.getModuleLocation().getModuleName(), + Loc.getModuleLocation().getOffset()); break; case Location::LK_Memory: - Printf("%p:", Loc.getMemoryLocation()); + LocBuffer.append("%p", Loc.getMemoryLocation()); break; case Location::LK_Null: - Printf("<unknown>:"); + LocBuffer.append("<unknown>"); break; } + Printf("%s:", LocBuffer.data()); } static void renderText(const char *Message, const Diag::Arg *Args) { @@ -108,7 +117,7 @@ static void renderText(const char *Message, const Diag::Arg *Args) { Printf("%s", A.String); break; case Diag::AK_Mangled: { - Printf("'%s'", getSymbolizer()->Demangle(A.String)); + Printf("'%s'", Symbolizer::GetOrInit()->Demangle(A.String)); break; } case Diag::AK_SInt: diff --git a/libsanitizer/ubsan/ubsan_diag.h b/libsanitizer/ubsan/ubsan_diag.h index 969d51cb677..04503687568 100644 --- a/libsanitizer/ubsan/ubsan_diag.h +++ b/libsanitizer/ubsan/ubsan_diag.h @@ -78,6 +78,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. diff --git a/libsanitizer/ubsan/ubsan_handlers.cc b/libsanitizer/ubsan/ubsan_handlers.cc index 5947c2a5101..dd2e7bbf3e5 100644 --- a/libsanitizer/ubsan/ubsan_handlers.cc +++ b/libsanitizer/ubsan/ubsan_handlers.cc @@ -244,15 +244,36 @@ void __ubsan::__ubsan_handle_float_cast_overflow_abort( void __ubsan::__ubsan_handle_load_invalid_value(InvalidValueData *Data, ValueHandle Val) { - // TODO: Add deduplication once a SourceLocation is generated for this check. - Diag(getCallerLocation(), DL_Error, + SourceLocation Loc = Data->Loc.acquire(); + if (Loc.isDisabled()) + return; + + Diag(Loc, DL_Error, "load of value %0, which is not a valid value for type %1") << Value(Data->Type, Val) << Data->Type; } void __ubsan::__ubsan_handle_load_invalid_value_abort(InvalidValueData *Data, ValueHandle Val) { - Diag(getCallerLocation(), DL_Error, - "load of value %0, which is not a valid value for type %1") - << Value(Data->Type, Val) << Data->Type; + __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(); } diff --git a/libsanitizer/ubsan/ubsan_handlers.h b/libsanitizer/ubsan/ubsan_handlers.h index 034edf59021..226faadc287 100644 --- a/libsanitizer/ubsan/ubsan_handlers.h +++ b/libsanitizer/ubsan/ubsan_handlers.h @@ -103,13 +103,22 @@ struct FloatCastOverflowData { RECOVERABLE(float_cast_overflow, FloatCastOverflowData *Data, ValueHandle From) struct InvalidValueData { - // FIXME: SourceLocation Loc; + SourceLocation Loc; const TypeDescriptor &Type; }; /// \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 diff --git a/libsanitizer/ubsan/ubsan_type_hash.cc b/libsanitizer/ubsan/ubsan_type_hash.cc index 440d3ad89c6..d01009426db 100644 --- a/libsanitizer/ubsan/ubsan_type_hash.cc +++ b/libsanitizer/ubsan/ubsan_type_hash.cc @@ -83,16 +83,18 @@ namespace abi = __cxxabiv1; // reused as needed. The second caching layer is a large hash table with open // chaining. We can freely evict from either layer since this is just a cache. // -// FIXME: Make these hash table accesses thread-safe. The races here are benign -// (worst-case, we could miss a bug or see a slowdown) but we should -// avoid upsetting race detectors. +// FIXME: Make these hash table accesses thread-safe. The races here are benign: +// assuming the unsequenced loads and stores don't misbehave too badly, +// the worst case is false negatives or poor cache behavior, not false +// positives or crashes. /// Find a bucket to store the given hash value in. static __ubsan::HashValue *getTypeCacheHashTableBucket(__ubsan::HashValue V) { static const unsigned HashTableSize = 65537; - static __ubsan::HashValue __ubsan_vptr_hash_set[HashTableSize] = { 1 }; + static __ubsan::HashValue __ubsan_vptr_hash_set[HashTableSize]; - unsigned Probe = V & 65535; + unsigned First = (V & 65535) ^ 1; + unsigned Probe = First; for (int Tries = 5; Tries; --Tries) { if (!__ubsan_vptr_hash_set[Probe] || __ubsan_vptr_hash_set[Probe] == V) return &__ubsan_vptr_hash_set[Probe]; @@ -102,12 +104,12 @@ static __ubsan::HashValue *getTypeCacheHashTableBucket(__ubsan::HashValue V) { } // FIXME: Pick a random entry from the probe sequence to evict rather than // just taking the first. - return &__ubsan_vptr_hash_set[V]; + return &__ubsan_vptr_hash_set[First]; } /// A cache of recently-checked hashes. Mini hash table with "random" evictions. __ubsan::HashValue -__ubsan::__ubsan_vptr_type_cache[__ubsan::VptrTypeCacheSize] = { 1 }; +__ubsan::__ubsan_vptr_type_cache[__ubsan::VptrTypeCacheSize]; /// \brief Determine whether \p Derived has a \p Base base class subobject at /// offset \p Offset. diff --git a/libsanitizer/ubsan/ubsan_value.h b/libsanitizer/ubsan/ubsan_value.h index 9b31eb7defb..6ca0f56c99d 100644 --- a/libsanitizer/ubsan/ubsan_value.h +++ b/libsanitizer/ubsan/ubsan_value.h @@ -23,8 +23,8 @@ // FIXME: Move this out to a config header. #if __SIZEOF_INT128__ -typedef __int128 s128; -typedef unsigned __int128 u128; +__extension__ typedef __int128 s128; +__extension__ typedef unsigned __int128 u128; #define HAVE_INT128_T 1 #else #define HAVE_INT128_T 0 |