blob: 4d1b2723cb387680251d88a40f6d54bbee467052 [file] [log] [blame]
Zachary Turner97206d52017-05-12 04:51:55 +00001//===-- Status.cpp -----------------------------------------------*- C++
2//-*-===//
Chris Lattner30fdc8d2010-06-08 16:52:24 +00003//
Chandler Carruth2946cd72019-01-19 08:50:56 +00004// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
5// See https://llvm.org/LICENSE.txt for license information.
6// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
Chris Lattner30fdc8d2010-06-08 16:52:24 +00007//
8//===----------------------------------------------------------------------===//
9
Zachary Turner97206d52017-05-12 04:51:55 +000010#include "lldb/Utility/Status.h"
Zachary Turner4479ac12017-04-06 18:12:24 +000011
12#include "lldb/Utility/VASPrintf.h"
Jonas Devlieghere672d2c12018-11-11 23:16:43 +000013#include "lldb/lldb-defines.h"
14#include "lldb/lldb-enumerations.h"
15#include "llvm/ADT/SmallString.h"
16#include "llvm/ADT/StringRef.h"
Pavel Labath10c41f32017-06-06 14:06:17 +000017#include "llvm/Support/Errno.h"
Jonas Devlieghere672d2c12018-11-11 23:16:43 +000018#include "llvm/Support/FormatProviders.h"
Zachary Turner4479ac12017-04-06 18:12:24 +000019
20#include <cerrno>
21#include <cstdarg>
Jonas Devlieghere672d2c12018-11-11 23:16:43 +000022#include <string>
Zachary Turner4479ac12017-04-06 18:12:24 +000023#include <system_error>
24
Charles Davis322fc842013-08-27 06:13:56 +000025#ifdef __APPLE__
Charles Davis510938e2013-08-27 05:04:57 +000026#include <mach/mach.h>
Charles Davis322fc842013-08-27 06:13:56 +000027#endif
Chris Lattner30fdc8d2010-06-08 16:52:24 +000028
Aaron Smithc3d447f2018-10-19 18:58:24 +000029#ifdef _WIN32
30#include <windows.h>
31#endif
Jonas Devlieghere672d2c12018-11-11 23:16:43 +000032#include <stdint.h>
Eugene Zelenkoa74f37a2016-03-10 23:57:12 +000033
Zachary Turner4479ac12017-04-06 18:12:24 +000034namespace llvm {
35class raw_ostream;
36}
Chris Lattner30fdc8d2010-06-08 16:52:24 +000037
Chris Lattner30fdc8d2010-06-08 16:52:24 +000038using namespace lldb;
39using namespace lldb_private;
40
Zachary Turner97206d52017-05-12 04:51:55 +000041Status::Status() : m_code(0), m_type(eErrorTypeInvalid), m_string() {}
Greg Claytonca512b32011-01-14 04:54:56 +000042
Zachary Turner97206d52017-05-12 04:51:55 +000043Status::Status(ValueType err, ErrorType type)
Kate Stoneb9c1b512016-09-06 20:57:50 +000044 : m_code(err), m_type(type), m_string() {}
Greg Claytonca512b32011-01-14 04:54:56 +000045
Zachary Turner97206d52017-05-12 04:51:55 +000046Status::Status(std::error_code EC)
Zachary Turner7d86ee52017-03-08 17:56:08 +000047 : m_code(EC.value()), m_type(ErrorType::eErrorTypeGeneric),
48 m_string(EC.message()) {}
49
Zachary Turner97206d52017-05-12 04:51:55 +000050Status::Status(const Status &rhs) = default;
Greg Claytonca512b32011-01-14 04:54:56 +000051
Zachary Turner97206d52017-05-12 04:51:55 +000052Status::Status(const char *format, ...)
Kate Stoneb9c1b512016-09-06 20:57:50 +000053 : m_code(0), m_type(eErrorTypeInvalid), m_string() {
54 va_list args;
55 va_start(args, format);
56 SetErrorToGenericError();
57 SetErrorStringWithVarArg(format, args);
58 va_end(args);
Enrico Granataf2bbf712011-07-15 02:26:42 +000059}
60
Pavel Labath3adc4082017-06-15 11:23:26 +000061const Status &Status::operator=(llvm::Error error) {
62 if (!error) {
63 Clear();
64 return *this;
65 }
Pavel Labatha24a3a32017-05-18 12:46:50 +000066
67 // if the error happens to be a errno error, preserve the error code
68 error = llvm::handleErrors(
69 std::move(error), [&](std::unique_ptr<llvm::ECError> e) -> llvm::Error {
70 std::error_code ec = e->convertToErrorCode();
71 if (ec.category() == std::generic_category()) {
72 m_code = ec.value();
73 m_type = ErrorType::eErrorTypePOSIX;
74 return llvm::Error::success();
75 }
76 return llvm::Error(std::move(e));
77 });
78
79 // Otherwise, just preserve the message
Pavel Labath3adc4082017-06-15 11:23:26 +000080 if (error) {
81 SetErrorToGenericError();
Pavel Labatha24a3a32017-05-18 12:46:50 +000082 SetErrorString(llvm::toString(std::move(error)));
Pavel Labath3adc4082017-06-15 11:23:26 +000083 }
84
85 return *this;
Pavel Labatha24a3a32017-05-18 12:46:50 +000086}
87
88llvm::Error Status::ToError() const {
89 if (Success())
90 return llvm::Error::success();
91 if (m_type == ErrorType::eErrorTypePOSIX)
Aaron Smithc3d447f2018-10-19 18:58:24 +000092 return llvm::errorCodeToError(
93 std::error_code(m_code, std::generic_category()));
Pavel Labatha24a3a32017-05-18 12:46:50 +000094 return llvm::make_error<llvm::StringError>(AsCString(),
95 llvm::inconvertibleErrorCode());
96}
97
Chris Lattner30fdc8d2010-06-08 16:52:24 +000098//----------------------------------------------------------------------
99// Assignment operator
100//----------------------------------------------------------------------
Zachary Turner97206d52017-05-12 04:51:55 +0000101const Status &Status::operator=(const Status &rhs) {
Kate Stoneb9c1b512016-09-06 20:57:50 +0000102 if (this != &rhs) {
103 m_code = rhs.m_code;
104 m_type = rhs.m_type;
105 m_string = rhs.m_string;
106 }
107 return *this;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000108}
109
Zachary Turner97206d52017-05-12 04:51:55 +0000110Status::~Status() = default;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000111
Aaron Smithc3d447f2018-10-19 18:58:24 +0000112#ifdef _WIN32
113static std::string RetrieveWin32ErrorString(uint32_t error_code) {
114 char *buffer = nullptr;
115 std::string message;
116 // Retrieve win32 system error.
117 if (::FormatMessageA(
118 FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM |
119 FORMAT_MESSAGE_MAX_WIDTH_MASK,
120 NULL, error_code, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
121 (LPSTR)&buffer, 0, NULL)) {
122 message.assign(buffer);
123 ::LocalFree(buffer);
124 }
125 return message;
126}
127#endif
128
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000129//----------------------------------------------------------------------
Adrian Prantl05097242018-04-30 16:49:04 +0000130// Get the error value as a NULL C string. The error string will be fetched and
131// cached on demand. The cached error string value will remain until the error
132// value is changed or cleared.
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000133//----------------------------------------------------------------------
Zachary Turner97206d52017-05-12 04:51:55 +0000134const char *Status::AsCString(const char *default_error_str) const {
Kate Stoneb9c1b512016-09-06 20:57:50 +0000135 if (Success())
136 return nullptr;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000137
Kate Stoneb9c1b512016-09-06 20:57:50 +0000138 if (m_string.empty()) {
Kate Stoneb9c1b512016-09-06 20:57:50 +0000139 switch (m_type) {
140 case eErrorTypeMachKernel:
141#if defined(__APPLE__)
Pavel Labath10c41f32017-06-06 14:06:17 +0000142 if (const char *s = ::mach_error_string(m_code))
143 m_string.assign(s);
Eli Friedman6eb685c2010-06-10 23:45:58 +0000144#endif
Kate Stoneb9c1b512016-09-06 20:57:50 +0000145 break;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000146
Kate Stoneb9c1b512016-09-06 20:57:50 +0000147 case eErrorTypePOSIX:
Pavel Labath10c41f32017-06-06 14:06:17 +0000148 m_string = llvm::sys::StrError(m_code);
Kate Stoneb9c1b512016-09-06 20:57:50 +0000149 break;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000150
Aaron Smithc3d447f2018-10-19 18:58:24 +0000151 case eErrorTypeWin32:
152#if defined(_WIN32)
153 m_string = RetrieveWin32ErrorString(m_code);
154#endif
155 break;
156
Kate Stoneb9c1b512016-09-06 20:57:50 +0000157 default:
158 break;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000159 }
Kate Stoneb9c1b512016-09-06 20:57:50 +0000160 }
161 if (m_string.empty()) {
162 if (default_error_str)
163 m_string.assign(default_error_str);
164 else
165 return nullptr; // User wanted a nullptr string back...
166 }
167 return m_string.c_str();
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000168}
169
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000170//----------------------------------------------------------------------
171// Clear the error and any cached error string that it might contain.
172//----------------------------------------------------------------------
Zachary Turner97206d52017-05-12 04:51:55 +0000173void Status::Clear() {
Kate Stoneb9c1b512016-09-06 20:57:50 +0000174 m_code = 0;
175 m_type = eErrorTypeInvalid;
176 m_string.clear();
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000177}
178
179//----------------------------------------------------------------------
180// Access the error value.
181//----------------------------------------------------------------------
Zachary Turner97206d52017-05-12 04:51:55 +0000182Status::ValueType Status::GetError() const { return m_code; }
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000183
184//----------------------------------------------------------------------
185// Access the error type.
186//----------------------------------------------------------------------
Zachary Turner97206d52017-05-12 04:51:55 +0000187ErrorType Status::GetType() const { return m_type; }
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000188
189//----------------------------------------------------------------------
Adrian Prantl05097242018-04-30 16:49:04 +0000190// Returns true if this object contains a value that describes an error or
191// otherwise non-success result.
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000192//----------------------------------------------------------------------
Zachary Turner97206d52017-05-12 04:51:55 +0000193bool Status::Fail() const { return m_code != 0; }
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000194
195//----------------------------------------------------------------------
Bruce Mitchener4ebdee02018-05-29 09:10:46 +0000196// Set accessor for the error value to "err" and the type to
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000197// "eErrorTypeMachKernel"
198//----------------------------------------------------------------------
Zachary Turner97206d52017-05-12 04:51:55 +0000199void Status::SetMachError(uint32_t err) {
Kate Stoneb9c1b512016-09-06 20:57:50 +0000200 m_code = err;
201 m_type = eErrorTypeMachKernel;
202 m_string.clear();
203}
204
Zachary Turner97206d52017-05-12 04:51:55 +0000205void Status::SetExpressionError(lldb::ExpressionResults result,
206 const char *mssg) {
Kate Stoneb9c1b512016-09-06 20:57:50 +0000207 m_code = result;
208 m_type = eErrorTypeExpression;
209 m_string = mssg;
210}
211
Zachary Turner97206d52017-05-12 04:51:55 +0000212int Status::SetExpressionErrorWithFormat(lldb::ExpressionResults result,
213 const char *format, ...) {
Kate Stoneb9c1b512016-09-06 20:57:50 +0000214 int length = 0;
215
216 if (format != nullptr && format[0]) {
217 va_list args;
218 va_start(args, format);
219 length = SetErrorStringWithVarArg(format, args);
220 va_end(args);
221 } else {
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000222 m_string.clear();
Kate Stoneb9c1b512016-09-06 20:57:50 +0000223 }
224 m_code = result;
225 m_type = eErrorTypeExpression;
226 return length;
Jim Ingham1624a2d2014-05-05 02:26:40 +0000227}
228
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000229//----------------------------------------------------------------------
Bruce Mitchener4ebdee02018-05-29 09:10:46 +0000230// Set accessor for the error value and type.
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000231//----------------------------------------------------------------------
Zachary Turner97206d52017-05-12 04:51:55 +0000232void Status::SetError(ValueType err, ErrorType type) {
Kate Stoneb9c1b512016-09-06 20:57:50 +0000233 m_code = err;
234 m_type = type;
235 m_string.clear();
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000236}
237
238//----------------------------------------------------------------------
Adrian Prantl05097242018-04-30 16:49:04 +0000239// Update the error value to be "errno" and update the type to be "POSIX".
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000240//----------------------------------------------------------------------
Zachary Turner97206d52017-05-12 04:51:55 +0000241void Status::SetErrorToErrno() {
Kate Stoneb9c1b512016-09-06 20:57:50 +0000242 m_code = errno;
243 m_type = eErrorTypePOSIX;
244 m_string.clear();
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000245}
246
247//----------------------------------------------------------------------
Adrian Prantl05097242018-04-30 16:49:04 +0000248// Update the error value to be LLDB_GENERIC_ERROR and update the type to be
249// "Generic".
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000250//----------------------------------------------------------------------
Zachary Turner97206d52017-05-12 04:51:55 +0000251void Status::SetErrorToGenericError() {
Kate Stoneb9c1b512016-09-06 20:57:50 +0000252 m_code = LLDB_GENERIC_ERROR;
253 m_type = eErrorTypeGeneric;
254 m_string.clear();
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000255}
256
257//----------------------------------------------------------------------
Adrian Prantl05097242018-04-30 16:49:04 +0000258// Set accessor for the error string value for a specific error. This allows
259// any string to be supplied as an error explanation. The error string value
260// will remain until the error value is cleared or a new error value/type is
261// assigned.
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000262//----------------------------------------------------------------------
Zachary Turner97206d52017-05-12 04:51:55 +0000263void Status::SetErrorString(llvm::StringRef err_str) {
Zachary Turnerc1564272016-11-16 21:15:24 +0000264 if (!err_str.empty()) {
Adrian Prantl05097242018-04-30 16:49:04 +0000265 // If we have an error string, we should always at least have an error set
266 // to a generic value.
Kate Stoneb9c1b512016-09-06 20:57:50 +0000267 if (Success())
268 SetErrorToGenericError();
Zachary Turnerc1564272016-11-16 21:15:24 +0000269 }
270 m_string = err_str;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000271}
272
273//------------------------------------------------------------------
274/// Set the current error string to a formatted error string.
275///
276/// @param format
277/// A printf style format string
278//------------------------------------------------------------------
Zachary Turner97206d52017-05-12 04:51:55 +0000279int Status::SetErrorStringWithFormat(const char *format, ...) {
Kate Stoneb9c1b512016-09-06 20:57:50 +0000280 if (format != nullptr && format[0]) {
281 va_list args;
282 va_start(args, format);
283 int length = SetErrorStringWithVarArg(format, args);
284 va_end(args);
285 return length;
286 } else {
287 m_string.clear();
288 }
289 return 0;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000290}
291
Zachary Turner97206d52017-05-12 04:51:55 +0000292int Status::SetErrorStringWithVarArg(const char *format, va_list args) {
Kate Stoneb9c1b512016-09-06 20:57:50 +0000293 if (format != nullptr && format[0]) {
Adrian Prantl05097242018-04-30 16:49:04 +0000294 // If we have an error string, we should always at least have an error set
295 // to a generic value.
Kate Stoneb9c1b512016-09-06 20:57:50 +0000296 if (Success())
297 SetErrorToGenericError();
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000298
Zachary Turner24ae6292017-02-16 19:38:21 +0000299 llvm::SmallString<1024> buf;
300 VASprintf(buf, format, args);
Pavel Labatha272fa82017-02-17 10:19:46 +0000301 m_string = buf.str();
Zachary Turner24ae6292017-02-16 19:38:21 +0000302 return buf.size();
Kate Stoneb9c1b512016-09-06 20:57:50 +0000303 } else {
304 m_string.clear();
305 }
306 return 0;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000307}
308
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000309//----------------------------------------------------------------------
Adrian Prantl05097242018-04-30 16:49:04 +0000310// Returns true if the error code in this object is considered a successful
311// return value.
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000312//----------------------------------------------------------------------
Zachary Turner97206d52017-05-12 04:51:55 +0000313bool Status::Success() const { return m_code == 0; }
Jim Ingham4e5c8212013-06-07 22:09:53 +0000314
Zachary Turner97206d52017-05-12 04:51:55 +0000315bool Status::WasInterrupted() const {
Kate Stoneb9c1b512016-09-06 20:57:50 +0000316 return (m_type == eErrorTypePOSIX && m_code == EINTR);
Jim Ingham4e5c8212013-06-07 22:09:53 +0000317}
Zachary Turner33aba3c2017-02-06 18:31:44 +0000318
Zachary Turner97206d52017-05-12 04:51:55 +0000319void llvm::format_provider<lldb_private::Status>::format(
320 const lldb_private::Status &error, llvm::raw_ostream &OS,
Zachary Turner33aba3c2017-02-06 18:31:44 +0000321 llvm::StringRef Options) {
322 llvm::format_provider<llvm::StringRef>::format(error.AsCString(), OS,
323 Options);
324}