dyld-732.8.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 //FIXME: this should be assertNoError(), but we currently overwrite some errors
89 //assertNoError();
90 _buffer = _simple_salloc();
91 _simple_vsprintf(_buffer, format, list);
92
93 #if BUILDING_CACHE_BUILDER
94 if ( !_verbose )
95 return;
96
97 if (_prefix.empty()) {
98 fprintf(stderr, "%s", _simple_string(_buffer));
99 } else {
100 fprintf(stderr, "[%s] %s", _prefix.c_str(), _simple_string(_buffer));
101 }
102 #endif
103 }
104
105 bool Diagnostics::hasError() const
106 {
107 return _buffer != nullptr;
108 }
109
110 bool Diagnostics::noError() const
111 {
112 return _buffer == nullptr;
113 }
114
115 void Diagnostics::clearError()
116 {
117 if ( _buffer )
118 _simple_sfree(_buffer);
119 _buffer = nullptr;
120 }
121
122 void Diagnostics::assertNoError() const
123 {
124 if ( _buffer != nullptr )
125 abort_report_np("%s", _simple_string(_buffer));
126 }
127
128 #if !BUILDING_CACHE_BUILDER
129 const char* Diagnostics::errorMessage() const
130 {
131 return _simple_string(_buffer);
132 }
133
134 #else
135 void Diagnostics::warning(const char* format, ...)
136 {
137 _SIMPLE_STRING tmp = _simple_salloc();
138 va_list list;
139 va_start(list, format);
140 _simple_vsprintf(tmp, format, list);
141 va_end(list);
142 #if BUILDING_CACHE_BUILDER
143 dispatch_sync(sWarningQueue, ^{
144 _warnings.insert(_simple_string(tmp));
145 });
146 #else
147 _warnings.insert(_simple_string(tmp));
148 #endif
149 _simple_sfree(tmp);
150 }
151
152 void Diagnostics::verbose(const char* format, ...)
153 {
154 if ( !_verbose )
155 return;
156
157 char* output_string;
158 va_list list;
159 va_start(list, format);
160 vasprintf(&output_string, format, list);
161 va_end(list);
162
163 if (_prefix.empty()) {
164 fprintf(stderr, "%s", output_string);
165 } else {
166 fprintf(stderr, "[%s] %s", _prefix.c_str(), output_string);
167 }
168 free(output_string);
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 "";
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