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