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