• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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