dyld-625.13.tar.gz
[apple/dyld.git] / dyld3 / Diagnostics.cpp
1 /*
2 * Copyright (c) 2017 Apple Inc. All rights reserved.
3 *
4 * @APPLE_LICENSE_HEADER_START@
5 *
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. Please obtain a copy of the License at
10 * http://www.opensource.apple.com/apsl/ and read it before using this
11 * file.
12 *
13 * The Original Code and all software distributed under the License are
14 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
15 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
16 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
18 * Please see the License for the specific language governing rights and
19 * limitations under the License.
20 *
21 * @APPLE_LICENSE_HEADER_END@
22 */
23
24
25 #include <stdint.h>
26 #include <stdio.h>
27 #include <string.h>
28 #include <assert.h>
29 #include <uuid/uuid.h>
30 #include <fcntl.h>
31 #include <errno.h>
32 #include <_simple.h>
33 #include <unistd.h>
34 #include <sys/uio.h>
35 #include <sys/param.h>
36 #include <sys/sysctl.h>
37 #include <sys/resource.h>
38 #include <sys/types.h>
39 #include <sys/stat.h>
40 #include <sys/mman.h>
41 #include <dirent.h>
42 #include <mach/mach.h>
43 #include <mach/machine.h>
44 #include <mach-o/loader.h>
45 #include <mach-o/nlist.h>
46 #include <mach-o/fat.h>
47 #include <pthread.h>
48 #include <libc_private.h>
49
50 #include "Diagnostics.h"
51
52 #if BUILDING_CACHE_BUILDER
53 #include <dispatch/dispatch.h>
54 dispatch_queue_t sWarningQueue = dispatch_queue_create("com.apple.dyld.cache-builder.warnings", NULL);
55 #endif
56
57 Diagnostics::Diagnostics(bool verbose)
58 #if BUILDING_CACHE_BUILDER
59 : _verbose(verbose)
60 , _prefix("")
61 #endif
62 {
63 }
64
65 #if BUILDING_CACHE_BUILDER
66 Diagnostics::Diagnostics(const std::string& prefix, bool verbose)
67 : _verbose(verbose)
68 , _prefix(prefix)
69 {
70 }
71 #endif
72
73 Diagnostics::~Diagnostics()
74 {
75 clearError();
76 }
77
78 void Diagnostics::error(const char* format, ...)
79 {
80 va_list list;
81 va_start(list, format);
82 error(format, list);
83 va_end(list);
84 }
85
86 void Diagnostics::error(const char* format, va_list list)
87 {
88 _buffer = _simple_salloc();
89 _simple_vsprintf(_buffer, format, list);
90
91 #if BUILDING_CACHE_BUILDER
92 if ( !_verbose )
93 return;
94
95 char *output_string;
96 vasprintf(&output_string, format, list);
97
98 if (_prefix.empty()) {
99 fprintf(stderr, "%s", output_string);
100 } else {
101 fprintf(stderr, "[%s] %s", _prefix.c_str(), output_string);
102 }
103 #endif
104 }
105
106 bool Diagnostics::hasError() const
107 {
108 return _buffer != nullptr;
109 }
110
111 bool Diagnostics::noError() const
112 {
113 return _buffer == nullptr;
114 }
115
116 void Diagnostics::clearError()
117 {
118 if ( _buffer )
119 _simple_sfree(_buffer);
120 _buffer = nullptr;
121 }
122
123 void Diagnostics::assertNoError() const
124 {
125 if ( _buffer != nullptr )
126 abort_report_np("%s", _simple_string(_buffer));
127 }
128
129 #if !BUILDING_CACHE_BUILDER
130 const char* Diagnostics::errorMessage() const
131 {
132 return _simple_string(_buffer);
133 }
134
135 #else
136 void Diagnostics::warning(const char* format, ...)
137 {
138 _SIMPLE_STRING tmp = _simple_salloc();
139 va_list list;
140 va_start(list, format);
141 _simple_vsprintf(tmp, format, list);
142 va_end(list);
143 #if BUILDING_CACHE_BUILDER
144 dispatch_sync(sWarningQueue, ^{
145 _warnings.insert(_simple_string(tmp));
146 });
147 #else
148 _warnings.insert(_simple_string(tmp));
149 #endif
150 _simple_sfree(tmp);
151 }
152
153 void Diagnostics::verbose(const char* format, ...)
154 {
155 if ( !_verbose )
156 return;
157
158 char* output_string;
159 va_list list;
160 va_start(list, format);
161 vasprintf(&output_string, format, list);
162 va_end(list);
163
164 if (_prefix.empty()) {
165 fprintf(stderr, "%s", output_string);
166 } else {
167 fprintf(stderr, "[%s] %s", _prefix.c_str(), output_string);
168 }
169 }
170
171 const std::string Diagnostics::prefix() const
172 {
173 return _prefix;
174 }
175
176 void Diagnostics::copy(const Diagnostics& other)
177 {
178 if ( other.hasError() )
179 error("%s", other.errorMessage().c_str());
180 for (const std::string& warn : other.warnings())
181 warning("%s", warn.c_str());
182 }
183
184 std::string Diagnostics::errorMessage() const
185 {
186 if ( _buffer != nullptr )
187 return _simple_string(_buffer);
188 else
189 return std::string();
190 }
191
192 const std::set<std::string> Diagnostics::warnings() const
193 {
194 #if BUILDING_CACHE_BUILDER
195 __block std::set<std::string> retval;
196 dispatch_sync(sWarningQueue, ^{
197 retval = _warnings;
198 });
199 return retval;
200 #else
201 return _warnings;
202 #endif
203 }
204
205 void Diagnostics::clearWarnings()
206 {
207 #if BUILDING_CACHE_BUILDER
208 dispatch_sync(sWarningQueue, ^{
209 _warnings.clear();
210 });
211 #else
212 _warnings.clear();
213 #endif
214 }
215
216 #endif
217