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 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 54Error::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//---------------------------------------------------------------------- 65const Error& 66Error::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//---------------------------------------------------------------------- 81const Error& 82Error::operator = (uint32_t err) 83{ 84 m_code = err; 85 m_type = eErrorTypeMachKernel; 86 m_string.clear(); 87 return *this; 88} 89 90Error::~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//---------------------------------------------------------------------- 99const char * 100Error::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//---------------------------------------------------------------------- 140void 141Error::Clear () 142{ 143 m_code = 0; 144 m_type = eErrorTypeGeneric; 145 m_string.clear(); 146} 147 148//---------------------------------------------------------------------- 149// Access the error value. 150//---------------------------------------------------------------------- 151Error::ValueType 152Error::GetError () const 153{ 154 return m_code; 155} 156 157//---------------------------------------------------------------------- 158// Access the error type. 159//---------------------------------------------------------------------- 160ErrorType 161Error::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//---------------------------------------------------------------------- 170bool 171Error::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//---------------------------------------------------------------------- 185void 186Error::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//---------------------------------------------------------------------- 224void 225Error::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//---------------------------------------------------------------------- 254void 255Error::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//---------------------------------------------------------------------- 265void 266Error::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//---------------------------------------------------------------------- 277void 278Error::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//---------------------------------------------------------------------- 289void 290Error::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//---------------------------------------------------------------------- 303void 304Error::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//------------------------------------------------------------------ 324int 325Error::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 342int 343Error::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//---------------------------------------------------------------------- 385bool 386Error::Success() const 387{ 388 return m_code == 0; 389} 390 391bool 392Error::WasInterrupted() const 393{ 394 if (m_type == eErrorTypePOSIX && m_code == EINTR) 395 return true; 396 else 397 return false; 398} 399 400