]>
Commit | Line | Data |
---|---|---|
4b260c20 BK |
1 | // -*- C++ -*- |
2 | ||
8d9254fc | 3 | // Copyright (C) 2004-2020 Free Software Foundation, Inc. |
4b260c20 BK |
4 | |
5 | // This library is free software; you can redistribute it and/or | |
6 | // modify it under the terms of the GNU General Public License as | |
748086b7 | 7 | // published by the Free Software Foundation; either version 3, or (at |
4b260c20 BK |
8 | // your option) any later version. |
9 | ||
10 | // This library is distributed in the hope that it will be useful, but | |
11 | // WITHOUT ANY WARRANTY; without even the implied warranty of | |
12 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
13 | // General Public License for more details. | |
14 | ||
15 | // You should have received a copy of the GNU General Public License | |
748086b7 JJ |
16 | // along with this library; see the file COPYING3. If not see |
17 | // <http://www.gnu.org/licenses/>. | |
4b260c20 | 18 | |
4b260c20 BK |
19 | |
20 | // Benjamin Kosnik <bkoz@redhat.com> | |
21 | ||
22 | #include "testsuite_abi.h" | |
0c3de900 | 23 | #include <cstdlib> |
4b260c20 BK |
24 | #include <sstream> |
25 | #include <fstream> | |
26 | #include <iostream> | |
0c3de900 | 27 | #include <vector> |
4f39bf5c | 28 | #include <algorithm> |
4b260c20 BK |
29 | |
30 | using namespace std; | |
31 | ||
c9fd7c7b | 32 | void |
4b260c20 BK |
33 | symbol::init(string& data) |
34 | { | |
35 | const char delim = ':'; | |
36 | const char version_delim = '@'; | |
37 | const string::size_type npos = string::npos; | |
38 | string::size_type n = 0; | |
39 | ||
40 | // Set the type. | |
41 | if (data.find("FUNC") == 0) | |
42 | type = symbol::function; | |
43 | else if (data.find("OBJECT") == 0) | |
44 | type = symbol::object; | |
bf718682 BK |
45 | else if (data.find("TLS") == 0) |
46 | type = symbol::tls; | |
bb2b2a24 | 47 | |
4b260c20 BK |
48 | n = data.find_first_of(delim); |
49 | if (n != npos) | |
50 | data.erase(data.begin(), data.begin() + n + 1); | |
51 | ||
bf718682 BK |
52 | // Iff object or TLS, get size info. |
53 | if (type == symbol::object || type == symbol::tls) | |
4b260c20 BK |
54 | { |
55 | n = data.find_first_of(delim); | |
56 | if (n != npos) | |
57 | { | |
69240fc2 SW |
58 | string objectsize(data.begin(), data.begin() + n); |
59 | istringstream iss(objectsize); | |
4b260c20 BK |
60 | int x; |
61 | iss >> x; | |
62 | if (!iss.fail()) | |
63 | size = x; | |
64 | data.erase(data.begin(), data.begin() + n + 1); | |
65 | } | |
66 | } | |
67 | ||
bb2b2a24 BK |
68 | // Set the name and raw_name. |
69 | raw_name = string(data.begin(), data.end()); | |
4b260c20 BK |
70 | n = data.find_first_of(version_delim); |
71 | if (n != npos) | |
72 | { | |
73 | // Found version string. | |
74 | name = string(data.begin(), data.begin() + n); | |
75 | n = data.find_last_of(version_delim); | |
76 | data.erase(data.begin(), data.begin() + n + 1); | |
77 | ||
78 | // Set version name. | |
79 | version_name = data; | |
80 | } | |
81 | else | |
82 | { | |
83 | // No versioning info. | |
84 | name = string(data.begin(), data.end()); | |
bb2b2a24 | 85 | version_status = symbol::none; |
4b260c20 BK |
86 | } |
87 | ||
88 | // Set the demangled name. | |
89 | demangled_name = demangle(name); | |
90 | } | |
91 | ||
92 | void | |
93 | symbol::print() const | |
94 | { | |
95 | const char tab = '\t'; | |
bb2b2a24 | 96 | cout << name << endl; |
4b260c20 | 97 | |
bb2b2a24 BK |
98 | if (demangled_name != name) |
99 | cout << demangled_name << endl; | |
100 | ||
101 | string vers; | |
102 | switch (version_status) | |
4b260c20 BK |
103 | { |
104 | case none: | |
bb2b2a24 BK |
105 | vers = "none"; |
106 | break; | |
107 | case compatible: | |
108 | vers = "compatible"; | |
109 | break; | |
110 | case incompatible: | |
111 | vers = "incompatible"; | |
112 | break; | |
113 | case unversioned: | |
114 | vers = "unversioned"; | |
4b260c20 | 115 | break; |
bb2b2a24 BK |
116 | default: |
117 | vers = "<default>"; | |
118 | } | |
119 | cout << "version status: " << vers << endl; | |
120 | ||
c9fd7c7b | 121 | if (version_name.size() |
bb2b2a24 | 122 | && (version_status == compatible || version_status == incompatible)) |
c9fd7c7b | 123 | cout << version_name << endl; |
bb2b2a24 BK |
124 | |
125 | string type_string; | |
126 | switch (type) | |
127 | { | |
4b260c20 BK |
128 | case function: |
129 | type_string = "function"; | |
130 | break; | |
131 | case object: | |
132 | type_string = "object"; | |
133 | break; | |
bf718682 BK |
134 | case tls: |
135 | type_string = "tls"; | |
136 | break; | |
bb2b2a24 BK |
137 | case uncategorized: |
138 | type_string = "uncategorized"; | |
4b260c20 BK |
139 | break; |
140 | default: | |
141 | type_string = "<default>"; | |
142 | } | |
bb2b2a24 | 143 | cout << "type: " << type_string << endl; |
c9fd7c7b | 144 | |
bf718682 | 145 | if (type == object || type == tls) |
bb2b2a24 | 146 | cout << "type size: " << size << endl; |
4b260c20 BK |
147 | |
148 | string status_string; | |
149 | switch (status) | |
150 | { | |
4b260c20 BK |
151 | case added: |
152 | status_string = "added"; | |
153 | break; | |
154 | case subtracted: | |
155 | status_string = "subtracted"; | |
156 | break; | |
bb2b2a24 BK |
157 | case undesignated: |
158 | status_string = "undesignated"; | |
4b260c20 BK |
159 | break; |
160 | default: | |
161 | status_string = "<default>"; | |
162 | } | |
bb2b2a24 BK |
163 | cout << "status: " << status_string << endl; |
164 | ||
165 | cout << endl; | |
4b260c20 BK |
166 | } |
167 | ||
168 | ||
169 | bool | |
bb2b2a24 | 170 | check_version(symbol& test, bool added) |
4b260c20 | 171 | { |
bb2b2a24 | 172 | // Construct list of compatible versions. |
4b260c20 BK |
173 | typedef std::vector<std::string> compat_list; |
174 | static compat_list known_versions; | |
175 | if (known_versions.empty()) | |
176 | { | |
bb2b2a24 BK |
177 | // NB: First version here must be the default version for this |
178 | // version of DT_SONAME. | |
4b260c20 | 179 | known_versions.push_back("GLIBCXX_3.4"); |
fb7f649d | 180 | known_versions.push_back("GLIBCXX_LDBL_3.4"); |
7c9fee34 | 181 | known_versions.push_back("GLIBCXX_3.4.1"); |
9e802114 | 182 | known_versions.push_back("GLIBCXX_3.4.2"); |
0e98ac62 | 183 | known_versions.push_back("GLIBCXX_3.4.3"); |
c9fd7c7b | 184 | known_versions.push_back("GLIBCXX_3.4.4"); |
36b72d8d | 185 | known_versions.push_back("GLIBCXX_3.4.5"); |
bb2b2a24 | 186 | known_versions.push_back("GLIBCXX_3.4.6"); |
18c75543 | 187 | known_versions.push_back("GLIBCXX_3.4.7"); |
fb7f649d | 188 | known_versions.push_back("GLIBCXX_LDBL_3.4.7"); |
45f388bb | 189 | known_versions.push_back("GLIBCXX_3.4.8"); |
0efaed01 | 190 | known_versions.push_back("GLIBCXX_3.4.9"); |
5dddb7e5 | 191 | known_versions.push_back("GLIBCXX_3.4.10"); |
fb7f649d | 192 | known_versions.push_back("GLIBCXX_LDBL_3.4.10"); |
31908b79 | 193 | known_versions.push_back("GLIBCXX_3.4.11"); |
efdb7347 | 194 | known_versions.push_back("GLIBCXX_3.4.12"); |
95bfca5e | 195 | known_versions.push_back("GLIBCXX_3.4.13"); |
41bc3c4a | 196 | known_versions.push_back("GLIBCXX_3.4.14"); |
1e2c0906 | 197 | known_versions.push_back("GLIBCXX_3.4.15"); |
07703a37 | 198 | known_versions.push_back("GLIBCXX_3.4.16"); |
43653c33 | 199 | known_versions.push_back("GLIBCXX_3.4.17"); |
90a75549 | 200 | known_versions.push_back("GLIBCXX_3.4.18"); |
2d500828 | 201 | known_versions.push_back("GLIBCXX_3.4.19"); |
2e8a9734 | 202 | known_versions.push_back("GLIBCXX_3.4.20"); |
a8218d79 | 203 | known_versions.push_back("GLIBCXX_3.4.21"); |
34a2b755 | 204 | known_versions.push_back("GLIBCXX_LDBL_3.4.21"); |
62589e99 JW |
205 | known_versions.push_back("GLIBCXX_3.4.22"); |
206 | known_versions.push_back("GLIBCXX_3.4.23"); | |
78aa76df | 207 | known_versions.push_back("GLIBCXX_3.4.24"); |
4317778a | 208 | known_versions.push_back("GLIBCXX_3.4.25"); |
cda121ac | 209 | known_versions.push_back("GLIBCXX_3.4.26"); |
67699bf6 | 210 | known_versions.push_back("GLIBCXX_3.4.27"); |
d02a0412 | 211 | known_versions.push_back("GLIBCXX_3.4.28"); |
4b260c20 | 212 | known_versions.push_back("CXXABI_1.3"); |
fb7f649d | 213 | known_versions.push_back("CXXABI_LDBL_1.3"); |
44dd2da2 | 214 | known_versions.push_back("CXXABI_1.3.1"); |
9b4fc32c | 215 | known_versions.push_back("CXXABI_1.3.2"); |
c466b2cd | 216 | known_versions.push_back("CXXABI_1.3.3"); |
fae927d3 | 217 | known_versions.push_back("CXXABI_1.3.4"); |
67275575 | 218 | known_versions.push_back("CXXABI_1.3.5"); |
50da34bb | 219 | known_versions.push_back("CXXABI_1.3.6"); |
f5220359 | 220 | known_versions.push_back("CXXABI_1.3.7"); |
fb7f649d | 221 | known_versions.push_back("CXXABI_1.3.8"); |
e4012a04 | 222 | known_versions.push_back("CXXABI_1.3.9"); |
7573116b | 223 | known_versions.push_back("CXXABI_1.3.10"); |
27abac26 | 224 | known_versions.push_back("CXXABI_1.3.11"); |
c124af93 | 225 | known_versions.push_back("CXXABI_1.3.12"); |
c9fd7c7b | 226 | known_versions.push_back("CXXABI_TM_1"); |
bb59f396 | 227 | known_versions.push_back("CXXABI_FLOAT128"); |
4b260c20 BK |
228 | } |
229 | compat_list::iterator begin = known_versions.begin(); | |
230 | compat_list::iterator end = known_versions.end(); | |
231 | ||
bb2b2a24 BK |
232 | // Check for compatible version. |
233 | if (test.version_name.size()) | |
234 | { | |
235 | compat_list::iterator it1 = find(begin, end, test.version_name); | |
236 | compat_list::iterator it2 = find(begin, end, test.name); | |
237 | if (it1 != end) | |
238 | test.version_status = symbol::compatible; | |
239 | else | |
240 | test.version_status = symbol::incompatible; | |
c9fd7c7b BK |
241 | |
242 | // Check that added symbols are added in the latest pre-release version. | |
d02a0412 | 243 | bool latestp = (test.version_name == "GLIBCXX_3.4.28" |
c124af93 | 244 | || test.version_name == "CXXABI_1.3.12" |
bb59f396 | 245 | || test.version_name == "CXXABI_FLOAT128" |
c9fd7c7b BK |
246 | || test.version_name == "CXXABI_TM_1"); |
247 | if (added && !latestp) | |
bb2b2a24 | 248 | test.version_status = symbol::incompatible; |
c75bd36b | 249 | |
0c312c2d | 250 | // Check that long double compatibility symbols demangled as |
bb59f396 MG |
251 | // __float128 and regular __float128 symbols are put into some _LDBL_ |
252 | // or _FLOAT128 version name. | |
34a2b755 JW |
253 | if (added && test.demangled_name.find("__float128") != std::string::npos |
254 | && test.demangled_name.find("std::__cxx11::") != 0) | |
0c312c2d | 255 | { |
bb59f396 MG |
256 | if (test.version_name.find("_LDBL_") == std::string::npos |
257 | && test.version_name.find("_FLOAT128") == std::string::npos) | |
0c312c2d BK |
258 | test.version_status = symbol::incompatible; |
259 | } | |
260 | ||
bb2b2a24 BK |
261 | // Check for weak label. |
262 | if (it1 == end && it2 == end) | |
263 | test.version_status = symbol::incompatible; | |
c9fd7c7b BK |
264 | |
265 | // Check that | |
bb2b2a24 BK |
266 | // GLIBCXX_3.4 |
267 | // GLIBCXX_3.4.5 | |
268 | // version as compatible | |
269 | // XXX | |
270 | } | |
271 | else | |
272 | { | |
273 | if (added) | |
274 | { | |
275 | // New version labels are ok. The rest are not. | |
276 | compat_list::iterator it2 = find(begin, end, test.name); | |
277 | if (it2 != end) | |
6defecc2 | 278 | test.version_status = symbol::compatible; |
bb2b2a24 BK |
279 | else |
280 | test.version_status = symbol::incompatible; | |
281 | } | |
282 | } | |
283 | return test.version_status == symbol::compatible; | |
4b260c20 BK |
284 | } |
285 | ||
c9fd7c7b | 286 | bool |
bb2b2a24 | 287 | check_compatible(symbol& lhs, symbol& rhs, bool verbose) |
4b260c20 BK |
288 | { |
289 | bool ret = true; | |
290 | const char tab = '\t'; | |
291 | ||
292 | // Check to see if symbol_objects are compatible. | |
293 | if (lhs.type != rhs.type) | |
294 | { | |
295 | ret = false; | |
296 | if (verbose) | |
297 | cout << tab << "incompatible types" << endl; | |
298 | } | |
c9fd7c7b | 299 | |
4b260c20 BK |
300 | if (lhs.name != rhs.name) |
301 | { | |
302 | ret = false; | |
303 | if (verbose) | |
304 | cout << tab << "incompatible names" << endl; | |
305 | } | |
306 | ||
307 | if (lhs.size != rhs.size) | |
308 | { | |
309 | ret = false; | |
310 | if (verbose) | |
311 | { | |
312 | cout << tab << "incompatible sizes" << endl; | |
313 | cout << tab << lhs.size << endl; | |
314 | cout << tab << rhs.size << endl; | |
315 | } | |
316 | } | |
317 | ||
c9fd7c7b | 318 | if (lhs.version_name != rhs.version_name |
4b260c20 BK |
319 | && !check_version(lhs) && !check_version(rhs)) |
320 | { | |
321 | ret = false; | |
322 | if (verbose) | |
323 | { | |
324 | cout << tab << "incompatible versions" << endl; | |
325 | cout << tab << lhs.version_name << endl; | |
326 | cout << tab << rhs.version_name << endl; | |
327 | } | |
328 | } | |
329 | ||
330 | if (verbose) | |
331 | cout << endl; | |
332 | ||
333 | return ret; | |
334 | } | |
335 | ||
336 | ||
0c312c2d BK |
337 | inline bool |
338 | has_symbol(const string& name, const symbols& s) throw() | |
339 | { return s.find(name) != s.end(); } | |
4b260c20 | 340 | |
0c312c2d BK |
341 | const symbol& |
342 | get_symbol(const string& name, const symbols& s) | |
4b260c20 | 343 | { |
0c312c2d BK |
344 | symbols::const_iterator i = s.find(name); |
345 | if (i != s.end()) | |
4b260c20 | 346 | { |
0c312c2d | 347 | return i->second; |
4b260c20 BK |
348 | } |
349 | else | |
350 | { | |
351 | ostringstream os; | |
0c312c2d | 352 | os << "get_symbol failed for symbol " << name; |
56ffd9b3 | 353 | __throw_logic_error(os.str().c_str()); |
4b260c20 BK |
354 | } |
355 | } | |
356 | ||
c9fd7c7b | 357 | void |
4b260c20 BK |
358 | examine_symbol(const char* name, const char* file) |
359 | { | |
360 | try | |
361 | { | |
362 | symbols s = create_symbols(file); | |
0c312c2d | 363 | const symbol& sym = get_symbol(name, s); |
4b260c20 BK |
364 | sym.print(); |
365 | } | |
366 | catch(...) | |
d98fd134 | 367 | { __throw_exception_again; } |
4b260c20 BK |
368 | } |
369 | ||
fdbba6bc | 370 | int |
c9fd7c7b | 371 | compare_symbols(const char* baseline_file, const char* test_file, |
4b260c20 BK |
372 | bool verbose) |
373 | { | |
374 | // Input both lists of symbols into container. | |
375 | symbols baseline = create_symbols(baseline_file); | |
376 | symbols test = create_symbols(test_file); | |
4b260c20 BK |
377 | |
378 | // Sanity check results. | |
0c312c2d | 379 | if (!baseline.size() || !test.size()) |
4b260c20 BK |
380 | { |
381 | cerr << "Problems parsing the list of exported symbols." << endl; | |
382 | exit(2); | |
383 | } | |
384 | ||
4a49c70b BK |
385 | // Check to see if any long double compatibility symbols are produced. |
386 | bool ld_version_found(false); | |
0c312c2d BK |
387 | symbols::iterator li(test.begin()); |
388 | while (!ld_version_found && li != test.end()) | |
4a49c70b | 389 | { |
0c312c2d | 390 | if (li->second.version_name.find("_LDBL_") != std::string::npos) |
4a49c70b BK |
391 | ld_version_found = true; |
392 | ++li; | |
393 | } | |
394 | ||
4b260c20 | 395 | // Sort out names. |
0c312c2d BK |
396 | // Assuming all baseline names and test names are both unique w/ no |
397 | // duplicates. | |
4b260c20 | 398 | // |
0c312c2d | 399 | // The names added to missing_names are baseline names not found in |
c9fd7c7b | 400 | // test names |
4b260c20 BK |
401 | // -> symbols that have been deleted. |
402 | // | |
0c312c2d BK |
403 | // The names added to added_names are test names not in |
404 | // baseline names | |
4b260c20 | 405 | // -> symbols that have been added. |
0c312c2d | 406 | typedef std::vector<std::string> symbol_names; |
4b260c20 BK |
407 | symbol_names shared_names; |
408 | symbol_names missing_names; | |
0c312c2d BK |
409 | symbol_names added_names; |
410 | for (li = test.begin(); li != test.end(); ++li) | |
411 | added_names.push_back(li->first); | |
412 | ||
413 | for (symbols::iterator i = baseline.begin(); i != baseline.end(); ++i) | |
4b260c20 | 414 | { |
0c312c2d | 415 | string name(i->first); |
4b260c20 | 416 | symbol_names::iterator end = added_names.end(); |
0c312c2d | 417 | symbol_names::iterator it = find(added_names.begin(), end, name); |
4b260c20 BK |
418 | if (it != end) |
419 | { | |
420 | // Found. | |
0c312c2d | 421 | shared_names.push_back(name); |
4b260c20 BK |
422 | added_names.erase(it); |
423 | } | |
0c312c2d BK |
424 | else |
425 | { | |
426 | // Iff no test long double compatibility symbols at all and the symbol | |
427 | // missing is a baseline long double compatibility symbol, skip. | |
428 | string version_name(i->second.version_name); | |
429 | bool base_ld(version_name.find("_LDBL_") != std::string::npos); | |
430 | if (!base_ld || base_ld && ld_version_found) | |
431 | missing_names.push_back(name); | |
432 | } | |
4b260c20 BK |
433 | } |
434 | ||
0c312c2d | 435 | // Fill out list of incompatible symbols. |
4b260c20 BK |
436 | typedef pair<symbol, symbol> symbol_pair; |
437 | vector<symbol_pair> incompatible; | |
0c312c2d | 438 | |
c9fd7c7b BK |
439 | // Fill out list of undesignated symbols. |
440 | vector<symbol> undesignated; | |
441 | ||
0c312c2d BK |
442 | // Check missing names for compatibility. |
443 | for (size_t j = 0; j < missing_names.size(); ++j) | |
4b260c20 | 444 | { |
0c312c2d BK |
445 | symbol& sbase = baseline[missing_names[j]]; |
446 | sbase.status = symbol::subtracted; | |
447 | incompatible.push_back(symbol_pair(sbase, sbase)); | |
4b260c20 BK |
448 | } |
449 | ||
450 | // Check shared names for compatibility. | |
6defecc2 JJ |
451 | const symbol_names::size_type shared_size = shared_names.size(); |
452 | for (size_t k = 0; k < shared_size; ++k) | |
4b260c20 | 453 | { |
0c312c2d BK |
454 | symbol& sbase = baseline[shared_names[k]]; |
455 | symbol& stest = test[shared_names[k]]; | |
456 | stest.status = symbol::existing; | |
457 | if (!check_compatible(sbase, stest)) | |
458 | incompatible.push_back(symbol_pair(sbase, stest)); | |
4b260c20 BK |
459 | } |
460 | ||
461 | // Check added names for compatibility. | |
6defecc2 JJ |
462 | const symbol_names::size_type added_size = added_names.size(); |
463 | for (size_t l = 0; l < added_size; ++l) | |
4b260c20 | 464 | { |
0c312c2d | 465 | symbol& stest = test[added_names[l]]; |
c9fd7c7b BK |
466 | |
467 | // Mark TLS as undesignated, remove from added. | |
468 | if (stest.type == symbol::tls) | |
469 | { | |
470 | stest.status = symbol::undesignated; | |
471 | if (!check_version(stest, false)) | |
472 | incompatible.push_back(symbol_pair(stest, stest)); | |
473 | else | |
474 | undesignated.push_back(stest); | |
475 | } | |
476 | else | |
477 | { | |
478 | stest.status = symbol::added; | |
479 | if (!check_version(stest, true)) | |
480 | incompatible.push_back(symbol_pair(stest, stest)); | |
481 | } | |
4b260c20 BK |
482 | } |
483 | ||
c9fd7c7b BK |
484 | // Normalize added names and undesignated names. |
485 | const size_t undesignated_size = undesignated.size(); | |
486 | for (size_t l = 0; l < undesignated_size; ++l) | |
487 | { | |
488 | symbol& sundes = undesignated[l]; | |
489 | symbol_names::iterator end = added_names.end(); | |
490 | symbol_names::iterator it = find(added_names.begin(), end, sundes.name); | |
491 | if (it != end) | |
492 | { | |
493 | // Found. | |
494 | added_names.erase(it); | |
495 | } | |
496 | else | |
497 | __throw_runtime_error(sundes.name.c_str()); | |
498 | } | |
499 | ||
500 | ||
4b260c20 BK |
501 | // Report results. |
502 | if (verbose && added_names.size()) | |
503 | { | |
bb2b2a24 | 504 | cout << endl << added_names.size() << " added symbols " << endl; |
4b260c20 | 505 | for (size_t j = 0; j < added_names.size() ; ++j) |
bb2b2a24 BK |
506 | { |
507 | cout << j << endl; | |
0c312c2d | 508 | test[added_names[j]].print(); |
bb2b2a24 | 509 | } |
4b260c20 | 510 | } |
c9fd7c7b | 511 | |
4b260c20 BK |
512 | if (verbose && missing_names.size()) |
513 | { | |
bb2b2a24 | 514 | cout << endl << missing_names.size() << " missing symbols " << endl; |
4b260c20 | 515 | for (size_t j = 0; j < missing_names.size() ; ++j) |
bb2b2a24 BK |
516 | { |
517 | cout << j << endl; | |
0c312c2d | 518 | baseline[missing_names[j]].print(); |
bb2b2a24 | 519 | } |
4b260c20 | 520 | } |
c9fd7c7b BK |
521 | |
522 | if (verbose && undesignated.size()) | |
523 | { | |
524 | cout << endl << undesignated.size() << " undesignated symbols " << endl; | |
525 | for (size_t j = 0; j < undesignated.size() ; ++j) | |
526 | { | |
527 | // First, print index. | |
528 | cout << j << endl; | |
529 | ||
530 | // Second, report name. | |
531 | symbol& s = undesignated[j]; | |
532 | s.print(); | |
533 | } | |
534 | } | |
535 | ||
4b260c20 BK |
536 | if (verbose && incompatible.size()) |
537 | { | |
bb2b2a24 | 538 | cout << endl << incompatible.size() << " incompatible symbols " << endl; |
4b260c20 BK |
539 | for (size_t j = 0; j < incompatible.size() ; ++j) |
540 | { | |
bb2b2a24 BK |
541 | // First, print index. |
542 | cout << j << endl; | |
543 | ||
544 | // Second, report name. | |
0c312c2d BK |
545 | symbol& sbase = incompatible[j].first; |
546 | symbol& stest = incompatible[j].second; | |
547 | stest.print(); | |
c9fd7c7b BK |
548 | |
549 | // Third, report reason or reasons incompatible. | |
0c312c2d | 550 | check_compatible(sbase, stest, true); |
4b260c20 BK |
551 | } |
552 | } | |
c9fd7c7b | 553 | |
332781bb | 554 | cout << "\n\t\t==== libstdc++-v3 check-abi Summary ====" << endl; |
4b260c20 BK |
555 | cout << endl; |
556 | cout << "# of added symbols:\t\t " << added_names.size() << endl; | |
557 | cout << "# of missing symbols:\t\t " << missing_names.size() << endl; | |
c9fd7c7b | 558 | cout << "# of undesignated symbols:\t " << undesignated.size() << endl; |
4b260c20 BK |
559 | cout << "# of incompatible symbols:\t " << incompatible.size() << endl; |
560 | cout << endl; | |
561 | cout << "using: " << baseline_file << endl; | |
fdbba6bc MM |
562 | |
563 | return !(missing_names.size() || incompatible.size()); | |
4b260c20 BK |
564 | } |
565 | ||
566 | ||
567 | symbols | |
568 | create_symbols(const char* file) | |
569 | { | |
570 | symbols s; | |
571 | ifstream ifs(file); | |
572 | if (ifs.is_open()) | |
573 | { | |
0c312c2d BK |
574 | // Organize file data into an associated container (symbols) of symbol |
575 | // objects mapped to mangled names without versioning | |
576 | // information. | |
4b260c20 BK |
577 | const string empty; |
578 | string line = empty; | |
579 | while (getline(ifs, line).good()) | |
580 | { | |
581 | symbol tmp; | |
582 | tmp.init(line); | |
0c312c2d | 583 | s[tmp.name] = tmp; |
4b260c20 BK |
584 | line = empty; |
585 | } | |
586 | } | |
587 | else | |
588 | { | |
589 | ostringstream os; | |
590 | os << "create_symbols failed for file " << file; | |
56ffd9b3 | 591 | __throw_runtime_error(os.str().c_str()); |
4b260c20 BK |
592 | } |
593 | return s; | |
594 | } | |
595 | ||
596 | ||
4f7c2c7f | 597 | std::string |
4b260c20 BK |
598 | demangle(const std::string& mangled) |
599 | { | |
4f7c2c7f | 600 | std::string name; |
4b260c20 BK |
601 | if (mangled[0] != '_' || mangled[1] != 'Z') |
602 | { | |
603 | // This is not a mangled symbol, thus has "C" linkage. | |
4f7c2c7f | 604 | name = mangled; |
4b260c20 BK |
605 | } |
606 | else | |
607 | { | |
608 | // Use __cxa_demangle to demangle. | |
609 | int status = 0; | |
4f7c2c7f JW |
610 | char* ptr = abi::__cxa_demangle(mangled.c_str(), 0, 0, &status); |
611 | if (ptr) | |
612 | { | |
613 | name = ptr; | |
614 | free(ptr); | |
615 | } | |
616 | else | |
4b260c20 BK |
617 | { |
618 | switch (status) | |
619 | { | |
620 | case 0: | |
621 | name = "error code = 0: success"; | |
622 | break; | |
623 | case -1: | |
624 | name = "error code = -1: memory allocation failure"; | |
625 | break; | |
626 | case -2: | |
627 | name = "error code = -2: invalid mangled name"; | |
628 | break; | |
629 | case -3: | |
630 | name = "error code = -3: invalid arguments"; | |
631 | break; | |
632 | default: | |
633 | name = "error code unknown - who knows what happened"; | |
634 | } | |
635 | } | |
636 | } | |
637 | return name; | |
638 | } |