summaryrefslogtreecommitdiff
path: root/lib/ubsan/ubsan_diag.h
diff options
context:
space:
mode:
authorRichard Smith <richard-llvm@metafoo.co.uk>2012-12-18 04:23:18 +0000
committerRichard Smith <richard-llvm@metafoo.co.uk>2012-12-18 04:23:18 +0000
commit5f1164955fb28a9bcb826abc195aa2119feb0f97 (patch)
tree8c48a8795cb47b12e4756a31049b14bd1c31ac18 /lib/ubsan/ubsan_diag.h
parentfe0b77be4057ba90a0321107cc5d0f603f297bfa (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.h69
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();