OpenCores
URL https://opencores.org/ocsvn/scarts/scarts/trunk

Subversion Repositories scarts

[/] [scarts/] [trunk/] [toolchain/] [scarts-gcc/] [gcc-4.1.1/] [libstdc++-v3/] [testsuite/] [testsuite_abi.cc] - Blame information for rev 19

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 19 jlechner
// -*- C++ -*-
2
 
3
// Copyright (C) 2004, 2005, 2006 Free Software Foundation, Inc.
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
7
// published by the Free Software Foundation; either version 2, or (at
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
16
// along with this library; see the file COPYING.  If not, write to
17
// the Free Software Foundation, 51 Franklin Street, Fifth Floor, Boston,
18
// MA 02110-1301, USA.
19
 
20
// As a special exception, you may use this file as part of a free
21
// software library without restriction.  Specifically, if other files
22
// instantiate templates or use macros or inline functions from this
23
// file, or you compile this file and link it with other files to
24
// produce an executable, this file does not by itself cause the
25
// resulting executable to be covered by the GNU General Public
26
// License.  This exception does not however invalidate any other
27
// reasons why the executable file might be covered by the GNU General
28
// Public License.
29
 
30
// Benjamin Kosnik  <bkoz@redhat.com>
31
 
32
#include "testsuite_abi.h"
33
#include <sstream>
34
#include <fstream>
35
#include <iostream>
36
 
37
using namespace std;
38
 
39
void
40
symbol::init(string& data)
41
{
42
  const char delim = ':';
43
  const char version_delim = '@';
44
  const string::size_type npos = string::npos;
45
  string::size_type n = 0;
46
 
47
  // Set the type.
48
  if (data.find("FUNC") == 0)
49
    type = symbol::function;
50
  else if (data.find("OBJECT") == 0)
51
    type = symbol::object;
52
 
53
  n = data.find_first_of(delim);
54
  if (n != npos)
55
    data.erase(data.begin(), data.begin() + n + 1);
56
 
57
  // Iff object, get size info.
58
  if (type == symbol::object)
59
    {
60
      n = data.find_first_of(delim);
61
      if (n != npos)
62
        {
63
          string size(data.begin(), data.begin() + n);
64
          istringstream iss(size);
65
          int x;
66
          iss >> x;
67
          if (!iss.fail())
68
            size = x;
69
          data.erase(data.begin(), data.begin() + n + 1);
70
        }
71
    }
72
 
73
  // Set the name and raw_name.
74
  raw_name = string(data.begin(), data.end());
75
  n = data.find_first_of(version_delim);
76
  if (n != npos)
77
    {
78
      // Found version string.
79
      name = string(data.begin(), data.begin() + n);
80
      n = data.find_last_of(version_delim);
81
      data.erase(data.begin(), data.begin() + n + 1);
82
 
83
      // Set version name.
84
      version_name = data;
85
    }
86
  else
87
    {
88
      // No versioning info.
89
      name = string(data.begin(), data.end());
90
      version_status = symbol::none;
91
    }
92
 
93
  // Set the demangled name.
94
  demangled_name = demangle(name);
95
}
96
 
97
void
98
symbol::print() const
99
{
100
  const char tab = '\t';
101
  cout << name << endl;
102
 
103
  if (demangled_name != name)
104
    cout << demangled_name << endl;
105
 
106
  string vers;
107
  switch (version_status)
108
    {
109
    case none:
110
      vers = "none";
111
      break;
112
    case compatible:
113
      vers = "compatible";
114
      break;
115
    case incompatible:
116
      vers = "incompatible";
117
      break;
118
     case unversioned:
119
      vers = "unversioned";
120
      break;
121
   default:
122
      vers = "<default>";
123
    }
124
  cout << "version status: " << vers << endl;
125
 
126
  if (version_name.size()
127
      && (version_status == compatible || version_status == incompatible))
128
    cout << version_name << endl;
129
 
130
  string type_string;
131
  switch (type)
132
    {
133
    case function:
134
      type_string = "function";
135
      break;
136
    case object:
137
      type_string = "object";
138
      break;
139
    case uncategorized:
140
      type_string = "uncategorized";
141
      break;
142
    default:
143
      type_string = "<default>";
144
    }
145
  cout << "type: " << type_string << endl;
146
 
147
  if (type == object)
148
    cout << "type size: " << size << endl;
149
 
150
  string status_string;
151
  switch (status)
152
    {
153
    case added:
154
      status_string = "added";
155
      break;
156
    case subtracted:
157
      status_string = "subtracted";
158
      break;
159
    case undesignated:
160
      status_string = "undesignated";
161
      break;
162
    default:
163
      status_string = "<default>";
164
    }
165
  cout << "status: " << status_string << endl;
166
 
167
  cout << endl;
168
}
169
 
170
 
171
bool
172
check_version(symbol& test, bool added)
173
{
174
  // Construct list of compatible versions.
175
  typedef std::vector<std::string> compat_list;
176
  static compat_list known_versions;
177
  if (known_versions.empty())
178
    {
179
      // NB: First version here must be the default version for this
180
      // version of DT_SONAME.
181
      known_versions.push_back("GLIBCXX_3.4");
182
      known_versions.push_back("GLIBCXX_3.4.1");
183
      known_versions.push_back("GLIBCXX_3.4.2");
184
      known_versions.push_back("GLIBCXX_3.4.3");
185
      known_versions.push_back("GLIBCXX_3.4.4");
186
      known_versions.push_back("GLIBCXX_3.4.5");
187
      known_versions.push_back("GLIBCXX_3.4.6");
188
      known_versions.push_back("GLIBCXX_3.4.7");
189
      known_versions.push_back("GLIBCXX_3.4.8");
190
      known_versions.push_back("CXXABI_1.3");
191
      known_versions.push_back("CXXABI_1.3.1");
192
    }
193
  compat_list::iterator begin = known_versions.begin();
194
  compat_list::iterator end = known_versions.end();
195
 
196
  // Check for compatible version.
197
  if (test.version_name.size())
198
    {
199
      compat_list::iterator it1 = find(begin, end, test.version_name);
200
      compat_list::iterator it2 = find(begin, end, test.name);
201
      if (it1 != end)
202
        test.version_status = symbol::compatible;
203
      else
204
        test.version_status = symbol::incompatible;
205
 
206
      // Check that added symbols aren't added in the base version.
207
      if (added && test.version_name == known_versions[0])
208
        test.version_status = symbol::incompatible;
209
 
210
      // Check for weak label.
211
      if (it1 == end && it2 == end)
212
        test.version_status = symbol::incompatible;
213
 
214
      // Check that 
215
      // GLIBCXX_3.4
216
      // GLIBCXX_3.4.5
217
      // version as compatible
218
      // XXX
219
    }
220
  else
221
    {
222
      if (added)
223
        {
224
          // New version labels are ok. The rest are not.
225
          compat_list::iterator it2 = find(begin, end, test.name);
226
          if (it2 != end)
227
            {
228
              test.version_status = symbol::compatible;
229
            }
230
          else
231
            test.version_status = symbol::incompatible;
232
        }
233
    }
234
  return test.version_status == symbol::compatible;
235
}
236
 
237
bool
238
check_compatible(symbol& lhs, symbol& rhs, bool verbose)
239
{
240
  bool ret = true;
241
  const char tab = '\t';
242
 
243
  // Check to see if symbol_objects are compatible.
244
  if (lhs.type != rhs.type)
245
    {
246
      ret = false;
247
      if (verbose)
248
        cout << tab << "incompatible types" << endl;
249
    }
250
 
251
  if (lhs.name != rhs.name)
252
    {
253
      ret = false;
254
      if (verbose)
255
        cout << tab << "incompatible names" << endl;
256
    }
257
 
258
  if (lhs.size != rhs.size)
259
    {
260
      ret = false;
261
      if (verbose)
262
        {
263
          cout << tab << "incompatible sizes" << endl;
264
          cout << tab << lhs.size << endl;
265
          cout << tab << rhs.size << endl;
266
        }
267
    }
268
 
269
  if (lhs.version_name != rhs.version_name
270
      && !check_version(lhs) && !check_version(rhs))
271
    {
272
      ret = false;
273
      if (verbose)
274
        {
275
          cout << tab << "incompatible versions" << endl;
276
          cout << tab << lhs.version_name << endl;
277
          cout << tab << rhs.version_name << endl;
278
        }
279
    }
280
 
281
  if (verbose)
282
    cout << endl;
283
 
284
  return ret;
285
}
286
 
287
 
288
bool
289
has_symbol(const string& mangled, const symbols& s) throw()
290
{
291
  const symbol_names& names = s.first;
292
  symbol_names::const_iterator i = find(names.begin(), names.end(), mangled);
293
  return i != names.end();
294
}
295
 
296
symbol&
297
get_symbol(const string& mangled, const symbols& s)
298
{
299
  const symbol_names& names = s.first;
300
  symbol_names::const_iterator i = find(names.begin(), names.end(), mangled);
301
  if (i != names.end())
302
    {
303
      symbol_objects objects = s.second;
304
      return objects[mangled];
305
    }
306
  else
307
    {
308
      ostringstream os;
309
      os << "get_symbol failed for symbol " << mangled;
310
      __throw_logic_error(os.str().c_str());
311
    }
312
}
313
 
314
void
315
examine_symbol(const char* name, const char* file)
316
{
317
  try
318
    {
319
      symbols s = create_symbols(file);
320
      symbol& sym = get_symbol(name, s);
321
      sym.print();
322
    }
323
  catch(...)
324
    { __throw_exception_again; }
325
}
326
 
327
int
328
compare_symbols(const char* baseline_file, const char* test_file,
329
                bool verbose)
330
{
331
  // Input both lists of symbols into container.
332
  symbols baseline = create_symbols(baseline_file);
333
  symbols test = create_symbols(test_file);
334
  symbol_names& baseline_names = baseline.first;
335
  symbol_objects& baseline_objects = baseline.second;
336
  symbol_names& test_names = test.first;
337
  symbol_objects& test_objects = test.second;
338
 
339
  //  Sanity check results.
340
  const symbol_names::size_type baseline_size = baseline_names.size();
341
  const symbol_names::size_type test_size = test_names.size();
342
  if (!baseline_size || !test_size)
343
    {
344
      cerr << "Problems parsing the list of exported symbols." << endl;
345
      exit(2);
346
    }
347
 
348
  // Sort out names.
349
  // Assuming baseline_names, test_names are both unique w/ no duplicates.
350
  //
351
  // The names added to missing_names are baseline_names not found in
352
  // test_names 
353
  // -> symbols that have been deleted.
354
  //
355
  // The names added to added_names are test_names not in
356
  // baseline_names
357
  // -> symbols that have been added.
358
  symbol_names shared_names;
359
  symbol_names missing_names;
360
  symbol_names added_names = test_names;
361
  for (size_t i = 0; i < baseline_size; ++i)
362
    {
363
      string what(baseline_names[i]);
364
      symbol_names::iterator end = added_names.end();
365
      symbol_names::iterator it = find(added_names.begin(), end, what);
366
      if (it != end)
367
        {
368
          // Found.
369
          shared_names.push_back(what);
370
          added_names.erase(it);
371
        }
372
      else
373
          missing_names.push_back(what);
374
    }
375
 
376
  // Check missing names for compatibility.
377
  typedef pair<symbol, symbol> symbol_pair;
378
  vector<symbol_pair> incompatible;
379
  for (size_t j = 0; j < missing_names.size(); ++j)
380
    {
381
      symbol& base = baseline_objects[missing_names[j]];
382
      base.status = symbol::subtracted;
383
      incompatible.push_back(symbol_pair(base, base));
384
    }
385
 
386
  // Check shared names for compatibility.
387
  for (size_t k = 0; k < shared_names.size(); ++k)
388
    {
389
      symbol& base = baseline_objects[shared_names[k]];
390
      symbol& test = test_objects[shared_names[k]];
391
      test.status = symbol::existing;
392
      if (!check_compatible(base, test))
393
        incompatible.push_back(symbol_pair(base, test));
394
    }
395
 
396
  // Check added names for compatibility.
397
  for (size_t l = 0; l < added_names.size(); ++l)
398
    {
399
      symbol& test = test_objects[added_names[l]];
400
      test.status = symbol::added;
401
      if (!check_version(test, true))
402
        incompatible.push_back(symbol_pair(test, test));
403
    }
404
 
405
  // Report results.
406
  if (verbose && added_names.size())
407
    {
408
      cout << endl << added_names.size() << " added symbols " << endl;
409
      for (size_t j = 0; j < added_names.size() ; ++j)
410
        {
411
          cout << j << endl;
412
          test_objects[added_names[j]].print();
413
        }
414
    }
415
 
416
  if (verbose && missing_names.size())
417
    {
418
      cout << endl << missing_names.size() << " missing symbols " << endl;
419
      for (size_t j = 0; j < missing_names.size() ; ++j)
420
        {
421
          cout << j << endl;
422
          baseline_objects[missing_names[j]].print();
423
        }
424
    }
425
 
426
  if (verbose && incompatible.size())
427
    {
428
      cout << endl << incompatible.size() << " incompatible symbols " << endl;
429
      for (size_t j = 0; j < incompatible.size() ; ++j)
430
        {
431
          // First, print index.
432
          cout << j << endl;
433
 
434
          // Second, report name.
435
          symbol& base = incompatible[j].first;
436
          symbol& test = incompatible[j].second;
437
          test.print();
438
 
439
          // Second, report reason or reasons incompatible.
440
          check_compatible(base, test, true);
441
        }
442
    }
443
 
444
  cout << "\n\t\t=== libstdc++-v3 check-abi Summary ===" << endl;
445
  cout << endl;
446
  cout << "# of added symbols:\t\t " << added_names.size() << endl;
447
  cout << "# of missing symbols:\t\t " << missing_names.size() << endl;
448
  cout << "# of incompatible symbols:\t " << incompatible.size() << endl;
449
  cout << endl;
450
  cout << "using: " << baseline_file << endl;
451
 
452
  return !(missing_names.size() || incompatible.size());
453
}
454
 
455
 
456
symbols
457
create_symbols(const char* file)
458
{
459
  symbols s;
460
  ifstream ifs(file);
461
  if (ifs.is_open())
462
    {
463
      // Organize file data into container of symbol objects.
464
      symbol_names& names = s.first;
465
      symbol_objects& objects = s.second;
466
      const string empty;
467
      string line = empty;
468
      while (getline(ifs, line).good())
469
        {
470
          symbol tmp;
471
          tmp.init(line);
472
          objects[tmp.raw_name] = tmp;
473
          names.push_back(tmp.raw_name);
474
          line = empty;
475
        }
476
    }
477
  else
478
    {
479
      ostringstream os;
480
      os << "create_symbols failed for file " << file;
481
      __throw_runtime_error(os.str().c_str());
482
    }
483
  return s;
484
}
485
 
486
 
487
const char*
488
demangle(const std::string& mangled)
489
{
490
  const char* name;
491
  if (mangled[0] != '_' || mangled[1] != 'Z')
492
    {
493
      // This is not a mangled symbol, thus has "C" linkage.
494
      name = mangled.c_str();
495
    }
496
  else
497
    {
498
      // Use __cxa_demangle to demangle.
499
      int status = 0;
500
      name = abi::__cxa_demangle(mangled.c_str(), 0, 0, &status);
501
      if (!name)
502
        {
503
          switch (status)
504
            {
505
            case 0:
506
              name = "error code = 0: success";
507
              break;
508
            case -1:
509
              name = "error code = -1: memory allocation failure";
510
              break;
511
            case -2:
512
              name = "error code = -2: invalid mangled name";
513
              break;
514
            case -3:
515
              name = "error code = -3: invalid arguments";
516
              break;
517
            default:
518
              name = "error code unknown - who knows what happened";
519
            }
520
        }
521
    }
522
  return name;
523
}
524
 

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.