testsuite_abi.cc 19 KB

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