Home | History | Annotate | Download | only in Core
      1 //===-- Error.cpp -----------------------------------------------*- C++ -*-===//
      2 //
      3 //                     The LLVM Compiler Infrastructure
      4 //
      5 // This file is distributed under the University of Illinois Open Source
      6 // License. See LICENSE.TXT for details.
      7 //
      8 //===----------------------------------------------------------------------===//
      9 
     10 // C Includes
     11 #include <errno.h>
     12 
     13 // C++ Includes
     14 // Other libraries and framework includes
     15 // Project includes
     16 #include "lldb/Core/Error.h"
     17 #include "lldb/Core/Log.h"
     18 #include "llvm/ADT/SmallVector.h"
     19 #include <cstdarg>
     20 #include <cstdlib>
     21 #include <cstring>
     22 
     23 #if defined (__arm__) && defined (__APPLE__)
     24 #include <SpringBoardServices/SpringBoardServer.h>
     25 #endif
     26 
     27 using namespace lldb;
     28 using namespace lldb_private;
     29 
     30 Error::Error ():
     31     m_code (0),
     32     m_type (eErrorTypeInvalid),
     33     m_string ()
     34 {
     35 }
     36 
     37 //----------------------------------------------------------------------
     38 // Default constructor
     39 //----------------------------------------------------------------------
     40 Error::Error(ValueType err, ErrorType type) :
     41     m_code (err),
     42     m_type (type),
     43     m_string ()
     44 {
     45 }
     46 
     47 Error::Error (const Error &rhs) :
     48     m_code (rhs.m_code),
     49     m_type (rhs.m_type),
     50     m_string (rhs.m_string)
     51 {
     52 }
     53 
     54 Error::Error (const char* err_str):
     55     m_code (0),
     56     m_type (eErrorTypeInvalid),
     57     m_string ()
     58 {
     59     SetErrorString(err_str);
     60 }
     61 
     62 //----------------------------------------------------------------------
     63 // Assignment operator
     64 //----------------------------------------------------------------------
     65 const Error&
     66 Error::operator = (const Error& rhs)
     67 {
     68     if (this != &rhs)
     69     {
     70         m_code = rhs.m_code;
     71         m_type = rhs.m_type;
     72         m_string = rhs.m_string;
     73     }
     74     return *this;
     75 }
     76 
     77 
     78 //----------------------------------------------------------------------
     79 // Assignment operator
     80 //----------------------------------------------------------------------
     81 const Error&
     82 Error::operator = (uint32_t err)
     83 {
     84     m_code = err;
     85     m_type = eErrorTypeMachKernel;
     86     m_string.clear();
     87     return *this;
     88 }
     89 
     90 Error::~Error()
     91 {
     92 }
     93 
     94 //----------------------------------------------------------------------
     95 // Get the error value as a NULL C string. The error string will be
     96 // fetched and cached on demand. The cached error string value will
     97 // remain until the error value is changed or cleared.
     98 //----------------------------------------------------------------------
     99 const char *
    100 Error::AsCString(const char *default_error_str) const
    101 {
    102     if (Success())
    103         return NULL;
    104 
    105     if (m_string.empty())
    106     {
    107         const char *s = NULL;
    108         switch (m_type)
    109         {
    110         case eErrorTypeMachKernel:
    111 #if defined (__APPLE__)
    112             s = ::mach_error_string (m_code);
    113 #endif
    114             break;
    115 
    116         case eErrorTypePOSIX:
    117             s = ::strerror (m_code);
    118             break;
    119 
    120         default:
    121             break;
    122         }
    123         if (s)
    124             m_string.assign(s);
    125     }
    126     if (m_string.empty())
    127     {
    128         if (default_error_str)
    129             m_string.assign(default_error_str);
    130         else
    131             return NULL;    // User wanted a NULL string back...
    132     }
    133     return m_string.c_str();
    134 }
    135 
    136 
    137 //----------------------------------------------------------------------
    138 // Clear the error and any cached error string that it might contain.
    139 //----------------------------------------------------------------------
    140 void
    141 Error::Clear ()
    142 {
    143     m_code = 0;
    144     m_type = eErrorTypeGeneric;
    145     m_string.clear();
    146 }
    147 
    148 //----------------------------------------------------------------------
    149 // Access the error value.
    150 //----------------------------------------------------------------------
    151 Error::ValueType
    152 Error::GetError () const
    153 {
    154     return m_code;
    155 }
    156 
    157 //----------------------------------------------------------------------
    158 // Access the error type.
    159 //----------------------------------------------------------------------
    160 ErrorType
    161 Error::GetType () const
    162 {
    163     return m_type;
    164 }
    165 
    166 //----------------------------------------------------------------------
    167 // Retuns true if this object contains an value that describes an
    168 // error or otherwise non-success result.
    169 //----------------------------------------------------------------------
    170 bool
    171 Error::Fail () const
    172 {
    173     return m_code != 0;
    174 }
    175 
    176 //----------------------------------------------------------------------
    177 // Log the error given a string with format. If the this object
    178 // contains an error code, update the error string to contain the
    179 // "error: " followed by the formatted string, followed by the error
    180 // value and any string that describes the current error. This
    181 // allows more context to be given to an error string that remains
    182 // cached in this object. Logging always occurs even when the error
    183 // code contains a non-error value.
    184 //----------------------------------------------------------------------
    185 void
    186 Error::PutToLog (Log *log, const char *format, ...)
    187 {
    188     char *arg_msg = NULL;
    189     va_list args;
    190     va_start (args, format);
    191     ::vasprintf (&arg_msg, format, args);
    192     va_end (args);
    193 
    194     if (arg_msg != NULL)
    195     {
    196         if (Fail())
    197         {
    198             const char *err_str = AsCString();
    199             if (err_str == NULL)
    200                 err_str = "???";
    201 
    202             SetErrorStringWithFormat("error: %s err = %s (0x%8.8x)", arg_msg, err_str, m_code);
    203             if (log)
    204                 log->Error("%s", m_string.c_str());
    205         }
    206         else
    207         {
    208             if (log)
    209                 log->Printf("%s err = 0x%8.8x", arg_msg, m_code);
    210         }
    211         ::free (arg_msg);
    212     }
    213 }
    214 
    215 //----------------------------------------------------------------------
    216 // Log the error given a string with format. If the this object
    217 // contains an error code, update the error string to contain the
    218 // "error: " followed by the formatted string, followed by the error
    219 // value and any string that describes the current error. This
    220 // allows more context to be given to an error string that remains
    221 // cached in this object. Logging only occurs even when the error
    222 // code contains a error value.
    223 //----------------------------------------------------------------------
    224 void
    225 Error::LogIfError (Log *log, const char *format, ...)
    226 {
    227     if (Fail())
    228     {
    229         char *arg_msg = NULL;
    230         va_list args;
    231         va_start (args, format);
    232         ::vasprintf (&arg_msg, format, args);
    233         va_end (args);
    234 
    235         if (arg_msg != NULL)
    236         {
    237             const char *err_str = AsCString();
    238             if (err_str == NULL)
    239                 err_str = "???";
    240 
    241             SetErrorStringWithFormat("error: %s err = %s (0x%8.8x)", arg_msg, err_str, m_code);
    242             if (log)
    243                 log->Error("%s", m_string.c_str());
    244 
    245             ::free (arg_msg);
    246         }
    247     }
    248 }
    249 
    250 //----------------------------------------------------------------------
    251 // Set accesssor for the error value to "err" and the type to
    252 // "eErrorTypeMachKernel"
    253 //----------------------------------------------------------------------
    254 void
    255 Error::SetMachError (uint32_t err)
    256 {
    257     m_code = err;
    258     m_type = eErrorTypeMachKernel;
    259     m_string.clear();
    260 }
    261 
    262 //----------------------------------------------------------------------
    263 // Set accesssor for the error value and type.
    264 //----------------------------------------------------------------------
    265 void
    266 Error::SetError (ValueType err, ErrorType type)
    267 {
    268     m_code = err;
    269     m_type = type;
    270     m_string.clear();
    271 }
    272 
    273 //----------------------------------------------------------------------
    274 // Update the error value to be "errno" and update the type to
    275 // be "POSIX".
    276 //----------------------------------------------------------------------
    277 void
    278 Error::SetErrorToErrno()
    279 {
    280     m_code = errno;
    281     m_type = eErrorTypePOSIX;
    282     m_string.clear();
    283 }
    284 
    285 //----------------------------------------------------------------------
    286 // Update the error value to be LLDB_GENERIC_ERROR and update the type
    287 // to be "Generic".
    288 //----------------------------------------------------------------------
    289 void
    290 Error::SetErrorToGenericError ()
    291 {
    292     m_code = LLDB_GENERIC_ERROR;
    293     m_type = eErrorTypeGeneric;
    294     m_string.clear();
    295 }
    296 
    297 //----------------------------------------------------------------------
    298 // Set accessor for the error string value for a specific error.
    299 // This allows any string to be supplied as an error explanation.
    300 // The error string value will remain until the error value is
    301 // cleared or a new error value/type is assigned.
    302 //----------------------------------------------------------------------
    303 void
    304 Error::SetErrorString (const char *err_str)
    305 {
    306     if (err_str && err_str[0])
    307     {
    308         // If we have an error string, we should always at least have
    309         // an error set to a generic value.
    310         if (Success())
    311             SetErrorToGenericError();
    312         m_string = err_str;
    313     }
    314     else
    315         m_string.clear();
    316 }
    317 
    318 //------------------------------------------------------------------
    319 /// Set the current error string to a formatted error string.
    320 ///
    321 /// @param format
    322 ///     A printf style format string
    323 //------------------------------------------------------------------
    324 int
    325 Error::SetErrorStringWithFormat (const char *format, ...)
    326 {
    327     if (format && format[0])
    328     {
    329         va_list args;
    330         va_start (args, format);
    331         int length = SetErrorStringWithVarArg (format, args);
    332         va_end (args);
    333         return length;
    334     }
    335     else
    336     {
    337         m_string.clear();
    338     }
    339     return 0;
    340 }
    341 
    342 int
    343 Error::SetErrorStringWithVarArg (const char *format, va_list args)
    344 {
    345     if (format && format[0])
    346     {
    347         // If we have an error string, we should always at least have
    348         // an error set to a generic value.
    349         if (Success())
    350             SetErrorToGenericError();
    351 
    352         // Try and fit our error into a 1024 byte buffer first...
    353         llvm::SmallVector<char, 1024> buf;
    354         buf.resize(1024);
    355         // Copy in case our first call to vsnprintf doesn't fit into our
    356         // allocated buffer above
    357         va_list copy_args;
    358         va_copy (copy_args, args);
    359         unsigned length = ::vsnprintf (buf.data(), buf.size(), format, args);
    360         if (length >= buf.size())
    361         {
    362             // The error formatted string didn't fit into our buffer, resize it
    363             // to the exact needed size, and retry
    364             buf.resize(length + 1);
    365             length = ::vsnprintf (buf.data(), buf.size(), format, copy_args);
    366             va_end (copy_args);
    367             assert (length < buf.size());
    368         }
    369         m_string.assign(buf.data(), length);
    370         va_end (args);
    371         return length;
    372     }
    373     else
    374     {
    375         m_string.clear();
    376     }
    377     return 0;
    378 }
    379 
    380 
    381 //----------------------------------------------------------------------
    382 // Returns true if the error code in this object is considered a
    383 // successful return value.
    384 //----------------------------------------------------------------------
    385 bool
    386 Error::Success() const
    387 {
    388     return m_code == 0;
    389 }
    390 
    391 bool
    392 Error::WasInterrupted() const
    393 {
    394     if (m_type == eErrorTypePOSIX && m_code == EINTR)
    395         return true;
    396     else
    397         return false;
    398 }
    399 
    400