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
Error()30 Error::Error ():
31 m_code (0),
32 m_type (eErrorTypeInvalid),
33 m_string ()
34 {
35 }
36
37 //----------------------------------------------------------------------
38 // Default constructor
39 //----------------------------------------------------------------------
Error(ValueType err,ErrorType type)40 Error::Error(ValueType err, ErrorType type) :
41 m_code (err),
42 m_type (type),
43 m_string ()
44 {
45 }
46
Error(const Error & rhs)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
Error(const char * err_str)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&
operator =(const Error & rhs)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&
operator =(uint32_t err)82 Error::operator = (uint32_t err)
83 {
84 m_code = err;
85 m_type = eErrorTypeMachKernel;
86 m_string.clear();
87 return *this;
88 }
89
~Error()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 *
AsCString(const char * default_error_str) const100 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
Clear()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
GetError() const152 Error::GetError () const
153 {
154 return m_code;
155 }
156
157 //----------------------------------------------------------------------
158 // Access the error type.
159 //----------------------------------------------------------------------
160 ErrorType
GetType() const161 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
Fail() const171 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
PutToLog(Log * log,const char * format,...)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
LogIfError(Log * log,const char * format,...)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
SetMachError(uint32_t err)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
SetError(ValueType err,ErrorType type)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
SetErrorToErrno()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
SetErrorToGenericError()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
SetErrorString(const char * err_str)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
SetErrorStringWithFormat(const char * format,...)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
SetErrorStringWithVarArg(const char * format,va_list args)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
Success() const386 Error::Success() const
387 {
388 return m_code == 0;
389 }
390
391 bool
WasInterrupted() const392 Error::WasInterrupted() const
393 {
394 if (m_type == eErrorTypePOSIX && m_code == EINTR)
395 return true;
396 else
397 return false;
398 }
399
400