diff options
author | Richard Smith <richard-llvm@metafoo.co.uk> | 2012-12-18 04:23:18 +0000 |
---|---|---|
committer | Richard Smith <richard-llvm@metafoo.co.uk> | 2012-12-18 04:23:18 +0000 |
commit | 5f1164955fb28a9bcb826abc195aa2119feb0f97 (patch) | |
tree | 8c48a8795cb47b12e4756a31049b14bd1c31ac18 /lib/ubsan/ubsan_diag.h | |
parent | fe0b77be4057ba90a0321107cc5d0f603f297bfa (diff) |
ubsan: if the frontend didn't provide us with a source location, try to work
one out from the return address. Currently, we can only resolve this address to
a file and line number if we have an external symbolizer.
git-svn-id: https://llvm.org/svn/llvm-project/compiler-rt/trunk@170407 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/ubsan/ubsan_diag.h')
-rw-r--r-- | lib/ubsan/ubsan_diag.h | 69 |
1 files changed, 66 insertions, 3 deletions
diff --git a/lib/ubsan/ubsan_diag.h b/lib/ubsan/ubsan_diag.h index 6424ceef8..0cd9a7a3b 100644 --- a/lib/ubsan/ubsan_diag.h +++ b/lib/ubsan/ubsan_diag.h @@ -17,14 +17,77 @@ namespace __ubsan { +/// \brief A location within a loaded module in the program. These are used when +/// the location can't be resolved to a SourceLocation. +class ModuleLocation { + const char *ModuleName; + uptr Offset; + +public: + ModuleLocation() : ModuleName(0), Offset(0) {} + ModuleLocation(const char *ModuleName, uptr Offset) + : ModuleName(ModuleName), Offset(Offset) {} + const char *getModuleName() const { return ModuleName; } + uptr getOffset() const { return Offset; } +}; + +/// A location of some data within the program's address space. +typedef uptr MemoryLocation; + +/// \brief Location at which a diagnostic can be emitted. Either a +/// SourceLocation, a ModuleLocation, or a MemoryLocation. +class Location { +public: + enum LocationKind { LK_Null, LK_Source, LK_Module, LK_Memory }; + +private: + LocationKind Kind; + // FIXME: In C++11, wrap these in an anonymous union. + SourceLocation SourceLoc; + ModuleLocation ModuleLoc; + MemoryLocation MemoryLoc; + +public: + Location() : Kind(LK_Null) {} + Location(SourceLocation Loc) : + Kind(LK_Source), SourceLoc(Loc) {} + Location(ModuleLocation Loc) : + Kind(LK_Module), ModuleLoc(Loc) {} + Location(MemoryLocation Loc) : + Kind(LK_Memory), MemoryLoc(Loc) {} + + LocationKind getKind() const { return Kind; } + + bool isSourceLocation() const { return Kind == LK_Source; } + bool isModuleLocation() const { return Kind == LK_Module; } + bool isMemoryLocation() const { return Kind == LK_Memory; } + + SourceLocation getSourceLocation() const { + CHECK(isSourceLocation()); + return SourceLoc; + } + ModuleLocation getModuleLocation() const { + CHECK(isModuleLocation()); + return ModuleLoc; + } + MemoryLocation getMemoryLocation() const { + CHECK(isMemoryLocation()); + return MemoryLoc; + } +}; + +/// Try to obtain a location for the caller. This might fail, and produce either +/// an invalid location or a module location for the caller. +Location getCallerLocation(uptr CallerLoc = GET_CALLER_PC()); + /// \brief Representation of an in-flight diagnostic. /// /// Temporary \c Diag instances are created by the handler routines to /// accumulate arguments for a diagnostic. The destructor emits the diagnostic /// message. class Diag { - /// The source location at which the problem occurred. - const SourceLocation &Loc; + /// The location at which the problem occurred. + Location Loc; /// The message which will be emitted, with %0, %1, ... placeholders for /// arguments. @@ -75,7 +138,7 @@ class Diag { Diag &operator=(const Diag &); public: - Diag(const SourceLocation &Loc, const char *Message) + Diag(Location Loc, const char *Message) : Loc(Loc), Message(Message), NumArgs(0) {} ~Diag(); |