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