OSDN Git Service

2004-05-13 Benjamin Kosnik <bkoz@redhat.com>
authorbkoz <bkoz@138bc75d-0d04-0410-961f-82ee72b054a4>
Thu, 13 May 2004 12:50:53 +0000 (12:50 +0000)
committerbkoz <bkoz@138bc75d-0d04-0410-961f-82ee72b054a4>
Thu, 13 May 2004 12:50:53 +0000 (12:50 +0000)
* docs/html/abi.html: New.
* docs/html/abi.txt: Remove.
* docs/html/documentation.html: Add link.
* testsuite/Makefile.am: Add files.
* testsuite/Makefile.in: Regenerated.
* testsuite/abi_check.cc: Move and modify code into...
* testsuite/testsuite_abi.cc: Add.
* testsuite/testsuite_abi.h: Add.

* docs/html/17_intro/TODO: Update.
* include/bits/stl_pair.h: Format.

git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@81781 138bc75d-0d04-0410-961f-82ee72b054a4

libstdc++-v3/ChangeLog
libstdc++-v3/docs/html/17_intro/TODO
libstdc++-v3/docs/html/abi.html [new file with mode: 0644]
libstdc++-v3/docs/html/abi.txt [deleted file]
libstdc++-v3/docs/html/documentation.html
libstdc++-v3/include/bits/stl_pair.h
libstdc++-v3/testsuite/Makefile.am
libstdc++-v3/testsuite/Makefile.in
libstdc++-v3/testsuite/abi_check.cc
libstdc++-v3/testsuite/testsuite_abi.cc [new file with mode: 0644]
libstdc++-v3/testsuite/testsuite_abi.h [new file with mode: 0644]

index 6d723b4..428c559 100644 (file)
@@ -1,3 +1,17 @@
+2004-05-13  Benjamin Kosnik  <bkoz@redhat.com>
+       
+       * docs/html/abi.html: New.
+       * docs/html/abi.txt: Remove.
+       * docs/html/documentation.html: Add link.
+       * testsuite/Makefile.am: Add files.
+       * testsuite/Makefile.in: Regenerated.
+       * testsuite/abi_check.cc: Move and modify code into...
+       * testsuite/testsuite_abi.cc: Add.
+       * testsuite/testsuite_abi.h: Add.
+
+       * docs/html/17_intro/TODO: Update.
+       * include/bits/stl_pair.h: Format.
+       
 2004-05-06  Matthias Klose  <doko@debian.org>
 
        * include/backward/iterator.h:  Add GPL copyright info,
index 1670f04..93685fa 100644 (file)
@@ -2,16 +2,13 @@ std::allocator
 
   - switch to mt_allocator with --enable-threads=posix. 
 
-  - Try to figure out a way to switch allocators in a more elegant
-    manner, and make the default allocator configurable.
-
   - persistent allocator
 
   - global/extern allocator
 
 std::string 
 
-  - re-design for multi-paradigm, meta string class solution incorporating COW
+  - Policy-based design incorporating COW
     vs. deep copy issues, MT scalability
     See Andrei Alexandrescu, June 2001, C/C++ Users Journal
     "Generic<Programming>: A Policy-Based basic_string Implementation"
@@ -53,8 +50,6 @@ std::locale
 
   - minimize ctype convertion in data facets, see numpunct/num_put/num_get
 
-  - finish caching data facets and using the caches
-
 std::basic_filebuf, 27_io
 
   - wfilebuf, get variable-encoding working and tested, including
@@ -86,11 +81,11 @@ testsuite
 
   - diffing generated output files
 
+  - provide testsuites for numerics.
+
   - make check-abi needs to have full symbol checking. Scope the LSB
     testsuite, see what's going on with the typeinfo etc. bits.
 
-  - provide testsuites for numerics.
-
   - try to do a better job of ABI testing, with instantiations of all
     standard-specified types checked, not just exported symbols.
 
@@ -140,9 +135,6 @@ Nathan's commentary on cantrip, http://www.cantrip.org/cheaders.html
 - auto_ptr: seems to be some disagreement on what is
 standards-conformant behavior, specially on conversion operators.
 
-- looks like deque::get_allocator not standards conformant or deque
-allocator non-standard.
-
 - list::assignment operator needs const_cast
 
 - a cleaner division between pointers-to-value_type and true iterators
diff --git a/libstdc++-v3/docs/html/abi.html b/libstdc++-v3/docs/html/abi.html
new file mode 100644 (file)
index 0000000..fcb84e9
--- /dev/null
@@ -0,0 +1,857 @@
+<?xml version="1.0" encoding="ISO-8859-1"?>
+<!DOCTYPE html
+          PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
+          "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
+<head>
+   <meta name="AUTHOR" content="bkoz@gcc.gnu.org (Benjamin Kosnik)" />
+   <meta name="KEYWORDS" content="C++, libstdc++, dynamic, shared, library, ABI, version" />
+   <meta name="DESCRIPTION" content="C++ Standard Library ABI" />
+   <meta name="GENERATOR" content="emacs and ten fingers" />
+   <title>Standard C++ Library ABI</title>
+<link rel="StyleSheet" href="lib3styles.css" type="text/css" />
+<link rel="Start" href="documentation.html" type="text/html"
+  title="GNU C++ Standard Library" />
+<link rel="Copyright" href="17_intro/license.html" type="text/html" />
+</head>
+<body>
+
+<h1 class="centered"><a name="top">C++ Standard Library ABI</a></h1>
+
+<p class="fineprint"><em>
+   The latest version of this document is always available at
+   <a href="http://gcc.gnu.org/onlinedocs/libstdc++/abi.html">
+   http://gcc.gnu.org/onlinedocs/libstdc++/abi.html</a>.
+</em></p>
+
+<p><em>
+   To the <a href="http://gcc.gnu.org/libstdc++/">libstdc++-v3 homepage</a>.
+</em></p>
+
+<!-- ####################################################### -->
+<hr />
+<h3 class="left">
+  <a name="C++interface">The C++ interface</a>
+</h3>
+
+<p> C++ applications often dependent on specific language support
+routines, say for throwing exceptions, or catching exceptions, and
+perhaps also dependent on features in the C++ Standard Library.
+</p>
+
+<p> The C++ Standard Library has many include files, types defined in
+those include files, specific named functions, and other behavior. The
+text of these behaviors, as written in source include files, is called
+the Application Programing Interface, or API.
+</p>
+
+<p> Furthermore, C++ source that is compiled into object files is
+ transformed by the compiler: it arranges objects with specific
+ alignment and in a particular layout, mangling names according to a
+ well-defined algorithm, has specific arrangements for the support of
+ virtual functions, etc. These details are defined as the compiler
+ Application Binary Interface, or ABI. The GNU C++ compiler uses an
+ industry-standard C++ ABI starting with version 3. Details can be
+ found in the <a href="http://www.codesourcery.com/cxx-abi/abi.html">
+ ABI specification</a>.
+</p>
+
+<p>
+ The GNU C++ compiler, g++, has a compiler command line option to
+  switch between various different C++ ABIs. This explicit version
+  switch is the flag <code> -fabi-version</code>. In addition, some
+  g++ command line options may change the ABI as a side-effect of
+  use. Such flags include <code>-fpack-struct</code> and
+  <code>-fno-exceptions</code>, but include others: see the complete
+  list in the GCC manual under the heading <a
+  href="http://gcc.gnu.org/onlinedocs/gcc/Code-Gen-Options.html#Code%20Gen%20Options">Options
+  for Code Generation Conventions</a>.
+</p>
+
+<p> The configure options used when building a specific libstdc++
+version may also impact the resulting library ABI. The available
+configure options, and their impact on the library ABI, are documented
+<a href="http://gcc.gnu.org/onlinedocs/libstdc++/configopts.html">
+here</a>.
+</p>
+
+<p> Putting all of these ideas together results in the C++ Standard
+library ABI, which is the compilation of a given library API by a
+given compiler ABI. In a nutshell:
+</p>
+
+<code> library API + compiler ABI = library ABI</code>
+
+<p>
+ The library ABI is mostly of interest for end-users who have
+ unresolved symbols and are linking dynamically to the C++ Standard
+ library, and who thus must be careful to compile their application
+ with a compiler that is compatible with the available C++ Standard
+ library binary. In this case, compatible is defined with the equation
+ above: given an application compiled with a given compiler ABI and
+ library API, it will work correctly with a Standard C++ Library
+ created with the same constraints.
+</p>
+
+<p>
+  To use a specific version of the C++ ABI, one must use a
+  corresponding GNU C++ toolchain (Ie, g++ and libstdc++) that
+  implements the C++ ABI in question.
+</p>
+
+<h3 class="left">
+  <a name="ABI versioning">Versioning</a>
+</h3>
+
+<p> The C++ interface has evolved throughout the history of the GNU
+C++ toolchain. With each release, various details have been changed so
+as to give distinct versions to the C++ interface.
+</p>
+
+<h5 class="left">
+  <a name="goals">Goals of versioning</a>
+</h5>
+
+<p>Extending existing, stable ABIs. Versioning gives subsequent stable
+releases series libraries the ability to add new symbols and add
+functionality, all the while retaining backwards compatibility with
+the previous releases in the series. Note: the reverse is not true. It
+is not possible to take binaries linked with the latest version of a
+release series (if symbols have been added) and expect the initial
+release of the series to remain link compatible.
+</p>
+
+<p>Allows multiple, incompatible ABIs to coexist at the same time.
+</p>
+
+<p>
+</p>
+
+<h5 class="left">
+  <a name="details"> Version History </a>
+</h5>
+<p>
+ How can this complexity be managed? What does C++ versioning mean?
+  Because library and compiler changes often make binaries compiled
+  with one version of the GNU tools incompatible with binaries
+  compiled with other (either newer or older) versions of the same GNU
+  tools, specific techniques are used to make managing this complexity
+  easier.
+</p>
+
+<p>
+  The following techniques are used:
+</p>
+
+  <ul>
+
+    <li> <p>Release versioning on the libgcc_s.so binary. This is
+implemented via file names and the ELF DT_SONAME mechanism (at least
+on ELF systems).</p>
+
+    <p>It is versioned as follows: 
+    </p>
+    <ul>
+    <li>gcc-3.0.0: libgcc_s.so.1</li>
+    <li>gcc-3.0.1: libgcc_s.so.1</li>
+    <li>gcc-3.0.2: libgcc_s.so.1</li>
+    <li>gcc-3.0.3: libgcc_s.so.1</li>
+    <li>gcc-3.0.4: libgcc_s.so.1</li>
+    <li>gcc-3.1.0: libgcc_s.so.1</li>
+    <li>gcc-3.1.1: libgcc_s.so.1</li>
+    <li>gcc-3.2.0: libgcc_s.so.1</li>
+    <li>gcc-3.2.1: libgcc_s.so.1</li>
+    <li>gcc-3.2.2: libgcc_s.so.1</li>
+    <li>gcc-3.2.3: libgcc_s.so.1</li>
+    <li>gcc-3.3.0: libgcc_s.so.1</li>
+    <li>gcc-3.3.1: libgcc_s.so.1</li>
+    <li>gcc-3.3.2: libgcc_s.so.1</li>
+    <li>gcc-3.3.3: libgcc_s.so.1</li>
+    <li>gcc-3.4.0: libgcc_s.so.1</li>
+    </ul>
+    </li>
+    <p></p>
+
+    <li>Release versioning on the libstdc++.so binary, implemented in the same was as the libgcc_s.so binary, above.
+
+    <p>It is versioned as follows:
+    </p>
+    <ul>
+    <li>gcc-3.0.0: libstdc++.so.3.0.0</li>
+    <li>gcc-3.0.1: libstdc++.so.3.0.1</li>
+    <li>gcc-3.0.2: libstdc++.so.3.0.2</li>
+    <li>gcc-3.0.3: libstdc++.so.3.0.2 (Error should be libstdc++.so.3.0.3)</li>
+    <li>gcc-3.0.4: libstdc++.so.3.0.4</li>
+    <li>gcc-3.1.0: libstdc++.so.4.0.0</li>
+    <li>gcc-3.1.1: libstdc++.so.4.0.1</li>
+    <li>gcc-3.2.0: libstdc++.so.5.0.0</li>
+    <li>gcc-3.2.1: libstdc++.so.5.0.1</li>
+    <li>gcc-3.2.2: libstdc++.so.5.0.2</li>
+    <li>gcc-3.2.3: libstdc++.so.5.0.3 (Not strictly required)</li>
+    <li>gcc-3.3.0: libstdc++.so.5.0.4</li>
+    <li>gcc-3.3.1: libstdc++.so.5.0.5</li>
+    <li>gcc-3.3.2: libstdc++.so.5.0.5</li>
+    <li>gcc-3.3.3: libstdc++.so.5.0.5</li>
+    <li>gcc-3.4.0: libstdc++.so.6.0.0</li>
+    </ul>
+    </li>
+    <p></p>
+
+    <li>Symbol versioning on the libgcc_s.so binary.
+    <p>mapfile: gcc/libgcc-std.ver</p>
+
+    <p>It is versioned with the following labels and version definitions:</p>
+    <ul>
+    <li>gcc-3.0.0: GCC_3.0</li>
+    <li>gcc-3.0.1: GCC_3.0</li>
+    <li>gcc-3.0.2: GCC_3.0</li>
+    <li>gcc-3.0.3: GCC_3.0</li>
+    <li>gcc-3.0.4: GCC_3.0</li>
+    <li>gcc-3.1.0: GCC_3.0</li>
+    <li>gcc-3.1.1: GCC_3.0</li>
+    <li>gcc-3.2.0: GCC_3.0</li>
+    <li>gcc-3.2.1: GCC_3.0</li>
+    <li>gcc-3.2.2: GCC_3.0</li>
+    <li>gcc-3.2.3: GCC_3.0</li>
+    <li>gcc-3.3.0: GCC_3.0</li>
+    <li>gcc-3.3.1: GCC_3.0</li>
+    <li>gcc-3.3.2: GCC_3.0</li>
+    <li>gcc-3.3.3: GCC_3.0</li>
+    <li>gcc-3.4.0: GCC_3.0</li>
+    </ul>
+    </li>
+    <p></p>
+
+    <li>Symbol versioning on the libstdc++.so binary.
+
+    <p>mapfile: libstdc++-v3/config/linker-map.gnu</p>
+    <p>It is versioned with the following labels and version
+   definitions, where the version definition is the maximum for a
+   particular release. Note, only symbol which are newly introduced
+   will use the maximum version definition. Thus, for release series
+   with the same label, but incremented version definitions, the later
+   release has both versions. (An example of this would be the
+   gcc-3.2.1 release, which has GLIBCPP_3.2.1 for new symbols and
+   GLIBCPP_3.2 for symbols that were introduced in the gcc-3.2.0
+   release.)
+   </p>
+    <ul>
+    <li>gcc-3.0.0: (Error, not versioned)</li>
+    <li>gcc-3.0.1: (Error, not versioned)</li>
+    <li>gcc-3.0.2: (Error, not versioned)</li>
+    <li>gcc-3.0.3: (Error, not versioned)</li>
+    <li>gcc-3.0.4: (Error, not versioned)</li>
+    <li>gcc-3.1.0: GLIBCPP_3.1, CXXABI_1</li>
+    <li>gcc-3.1.1: GLIBCPP_3.1, CXXABI_1</li>
+    <li>gcc-3.2.0: GLIBCPP_3.2, CXXABI_1.2</li>
+    <li>gcc-3.2.1: GLIBCPP_3.2.1, CXXABI_1.2</li>
+    <li>gcc-3.2.2: GLIBCPP_3.2.2, CXXABI_1.2</li>
+    <li>gcc-3.2.3: GLIBCPP_3.2.2, CXXABI_1.2</li>
+    <li>gcc-3.3.0: GLIBCPP_3.2.2, CXXABI_1.2.1</li>
+    <li>gcc-3.3.1: GLIBCPP_3.2.3, CXXABI_1.2.1</li>
+    <li>gcc-3.3.2: GLIBCPP_3.2.3, CXXABI_1.2.1</li>
+    <li>gcc-3.3.3: GLIBCPP_3.2.3, CXXABI_1.2.1</li>
+    <li>gcc-3.4.0: GLIBCXX_3.4, CXXABI_1.3</li>
+    </ul>
+    </li>
+    <p></p>
+  
+    <li>
+    <p>Incremental bumping of a compiler pre-defined macro,
+    __GXX_ABI_VERSION. This macro is defined as the version of the
+    compiler v3 ABI, with g++ 3.0.x being version 100. This macro will
+    be automatically defined whenever g++ is used (the curious can
+    test this by invoking g++ with the '-v' flag.)
+    </p>
+    
+    <p>
+    This macro is defined in the file "lang-specs.h" in the gcc/cp directory.
+    Later versions define it in "c-common.c" in the gcc directory.
+    </p>
+
+    <p>
+    It is versioned as follows:
+    </p>
+    <ul>
+    <li>gcc-3.0.x: 100</li>
+    <li>gcc-3.1.x: 100 (Error, should be 101)</li>
+    <li>gcc-3.2.x: 102</li>
+    <li>gcc-3.3.x: 102</li>
+    <li>gcc-3.4.x: 1002</li>
+    </ul>
+    </li>
+    <p></p>
+
+    <li>
+    <p>Changes to the default compiler option for
+    <code>-fabi-version</code>.
+    </p>
+   <p>
+    It is versioned as follows:
+    </p>
+    <ul>
+    <li>gcc-3.0.x: (Error, not versioned) </li>
+    <li>gcc-3.1.x: (Error, not versioned) </li>
+    <li>gcc-3.2.x: <code>-fabi-version=1</code></li>
+    <li>gcc-3.3.x: <code>-fabi-version=1</code></li>
+    <li>gcc-3.4.x: <code>-fabi-version=2</code></li>
+    </ul>
+    </li>
+    <p></p>
+
+   <li>
+    <p>Incremental bumping of a library pre-defined macro. For releases
+    before 3.4.0, the macro is __GLIBCPP__. For later releases, it's
+    __GLIBCXX__. (The libstdc++ project generously changed from CPP to
+    CXX throughout its source to allow the "C" pre-processor the CPP
+    macro namespace.) These macros are defined as the date the library
+    was released, in compressed ISO date format, as an unsigned long.
+    </p>
+
+    <p>
+    In addition, the pre-defined macro is defined in the file
+    "c++config" in the "libstdc++-v3/include/bits" directory and is
+    changed every night by an automated script.
+    </p>
+    <p>
+    It is versioned as follows:
+    </p>
+    <ul>
+    <li>gcc-3.0.0: 20010615</li>
+    <li>gcc-3.0.1: 20010819</li>
+    <li>gcc-3.0.2: 20011023</li>
+    <li>gcc-3.0.3: 20011220</li>
+    <li>gcc-3.0.4: 20020220</li>
+    <li>gcc-3.1.0: 20020514</li>
+    <li>gcc-3.1.1: 20020725</li>
+    <li>gcc-3.2.0: 20020814</li>
+    <li>gcc-3.2.1: 20021119</li>
+    <li>gcc-3.2.2: 20030205</li>
+    <li>gcc-3.2.3: 20030422</li>
+    <li>gcc-3.3.0: 20030513</li>
+    <li>gcc-3.3.1: 20030804</li>
+    <li>gcc-3.3.2: 20031016</li>
+    <li>gcc-3.3.3: 20040214</li>
+    <li>gcc-3.4.0: 20040419</li>
+    </ul>
+    </li>
+    <p></p>
+
+
+    <li>
+    <p>
+    Incremental bumping of a library pre-defined macro,
+    _GLIBCPP_VERSION. This macro is defined as the released version of
+    the library, as a string literal. This is only implemented in
+    gcc-3.1.0 releases and higher, and is deprecated in 3.4.
+    </p>
+
+    <p>
+    This macro is defined in the file "c++config" in the
+    "libstdc++-v3/include/bits" directory and is generated
+    automatically by autoconf as part of the configure-time generation
+    of config.h.
+    </p>
+
+    <p>
+    It is versioned as follows:
+    </p>
+    <ul>
+    <li>gcc-3.0.0: "3.0.0"</li>
+    <li>gcc-3.0.1: "3.0.0" (Error, should be "3.0.1")</li>
+    <li>gcc-3.0.2: "3.0.0" (Error, should be "3.0.2")</li>
+    <li>gcc-3.0.3: "3.0.0" (Error, should be "3.0.3")</li>
+    <li>gcc-3.0.4: "3.0.0" (Error, should be "3.0.4")</li>
+    <li>gcc-3.1.0: "3.1.0"</li>
+    <li>gcc-3.1.1: "3.1.1"</li>
+    <li>gcc-3.2.0: "3.2"</li>
+    <li>gcc-3.2.1: "3.2.1"</li>
+    <li>gcc-3.2.2: "3.2.2"</li>
+    <li>gcc-3.2.3: "3.2.3"</li>
+    <li>gcc-3.3.0: "3.3"</li>
+    <li>gcc-3.3.1: "3.3.1"</li>
+    <li>gcc-3.3.2: "3.3.2"</li>
+    <li>gcc-3.3.3: "3.3.3"</li>
+    <li>gcc-3.4.0: "version-unused"</li>
+    </ul>
+    </li>
+    <p></p>
+
+    <li>
+    <p>
+    Matching each specific C++ compiler release to a specific set of
+    C++ include files. This is only implemented in gcc-3.1.1 releases
+    and higher.
+    </p>
+    <p>
+    All C++ includes are installed in include/c++, then nest in a
+    directory hierarchy corresponding to the C++ compiler's released
+    version. This version corresponds to the variable "gcc_version" in
+    "libstdc++-v3/acinclude.m4," and more details can be found in that
+    file's macro GLIBCPP_CONFIGURE.
+    </p>
+    <p>
+    C++ includes are versioned as follows:
+    </p>
+    <ul>
+    <li>gcc-3.0.0: include/g++-v3</li>
+    <li>gcc-3.0.1: include/g++-v3</li>
+    <li>gcc-3.0.2: include/g++-v3</li>
+    <li>gcc-3.0.3: include/g++-v3</li>
+    <li>gcc-3.0.4: include/g++-v3</li>
+    <li>gcc-3.1.0: include/g++-v3</li>
+    <li>gcc-3.1.1: include/c++/3.1.1</li>
+    <li>gcc-3.2.0: include/c++/3.2</li>
+    <li>gcc-3.2.1: include/c++/3.2.1</li>
+    <li>gcc-3.2.2: include/c++/3.2.2</li>
+    <li>gcc-3.2.3: include/c++/3.2.3</li>
+    <li>gcc-3.3.0: include/c++/3.3</li>
+    <li>gcc-3.3.1: include/c++/3.3.1</li>
+    <li>gcc-3.3.2: include/c++/3.3.2</li>
+    <li>gcc-3.3.3: include/c++/3.3.3</li>
+    <li>gcc-3.4.0: include/c++/3.4.0</li>
+    </ul>
+    </li>
+    <p></p>
+  </ul>
+<p>
+  Taken together, these techniques can accurately specify interface
+  and implementation changes in the GNU C++ tools themselves. Used
+  properly, they allow both the GNU C++ tools implementation, and
+  programs using them, an evolving yet controlled development that
+  maintains backward compatibility.
+</p>
+
+
+
+<h5 class="left">
+  <a name="requirements"> Minimum requirements for a versioned ABI </a>
+</h5>
+<p>
+  Minimum environment that supports a versioned ABI: A supported
+  dynamic linker, a GNU linker of sufficient vintage to understand
+  demangled C++ name globbing (ld), a shared executable compiled with
+  g++, and shared libraries (libgcc_s, libstdc++-v3) compiled by a
+  compiler (g++) with a compatible ABI. Phew.
+</p>
+
+<p>
+  On top of all that, an additional constraint: libstdc++ did not
+  attempt to version symbols (or age gracefully, really) until version
+  3.1.0. 
+</p>
+
+<p>
+  Most modern Linux and BSD versions, particularly ones using
+  gcc-3.1.x tools and more recent vintages, will meet the requirements above.
+</p>
+
+
+<h5 class="left">
+  <a name="config"> What configure options impact symbol versioning? </a>
+</h5>
+<p>
+  It turns out that most of the configure options that change default
+  behavior will impact the mangled names of exported symbols, and thus
+  impact versioning and compatibility.
+</p>
+
+</p>
+  For more information on configure options, including ABI impacts, see:
+  http://gcc.gnu.org/onlinedocs/libstdc++/configopts.html
+</p>
+
+<p>
+  There is one flag that explicitly deals with symbol versioning:
+  --enable-symvers. 
+</p>
+
+<p>
+  In particular, libstdc++-v3/acinclude.m4 has a macro called
+  GLIBCXX_ENABLE_SYMVERS that defaults to yes (or the argument passed
+  in via --enable-symvers=foo). At that point, the macro attempts to
+  make sure that all the requirement for symbol versioning are in
+  place. For more information, please consult acinclude.m4. 
+</p>
+
+
+<h5 class="left">
+  <a name="active"> How to tell if symbol versioning is, indeed, active? </a>
+</h5>
+<p>
+  When the GNU C++ library is being built with symbol versioning on,
+  you should see the following at configure time for libstdc++-v3:
+</p>
+
+
+<code>  checking versioning on shared library symbols... gnu</code>
+
+<p>
+  If you don't see this line in the configure output, or if this line
+  appears but the last word is 'no', then you are out of luck.
+</p>
+
+<p>
+  If the compiler is pre-installed, a quick way to test is to compile
+  the following (or any) simple C++ file and link it to the shared
+  libstdc++ library:
+</p>
+
+<pre>
+#include &lt;iostream&gt;
+
+int main()
+{ std::cout &lt;&lt; "hello" &lt;&lt; std::endl; return 0; }
+
+%g++ hello.cc -o hello.out
+
+%ldd hello.out
+        libstdc++.so.5 => /usr/lib/libstdc++.so.5 (0x00764000)
+        libm.so.6 => /lib/tls/libm.so.6 (0x004a8000)
+        libgcc_s.so.1 => /mnt/hd/bld/gcc/gcc/libgcc_s.so.1 (0x40016000)
+        libc.so.6 => /lib/tls/libc.so.6 (0x0036d000)
+        /lib/ld-linux.so.2 => /lib/ld-linux.so.2 (0x00355000)
+
+%nm hello.out
+</pre>
+
+<p>
+If you see symbols in the resulting output with "GLIBCXX_3" as part
+of the name, then the executable is versioned. Here's an example:
+</p>
+
+   <code>      U _ZNSt8ios_base4InitC1Ev@@GLIBCXX_3.4 </code>
+
+<h3 class="left">
+  <a name="ABI allowed">Library allowed ABI changes</a>
+</h3>
+<p>
+The following will cause the library minor version number to
+increase, say from "libstdc++.so.3.0.4" to "libstdc++.so.3.0.5".
+</p>
+<ul>
+ <li>adding an exported global or static data member</li>
+ <li>adding an exported function, static or non-virtual member function</li>
+ <li>adding an exported symbol or symbols by additional instantiations</li>
+</ul>
+<p>
+</p>
+<p>
+Other allowed changes are possible.
+</p>
+
+
+<h3 class="left">
+  <a name="ABI disallowed">Library disallowed ABI changes</a>
+</h3>
+
+<p>
+The following non-exhaustive list will cause the library major version
+number to increase, say from "libstdc++.so.3.0.4" to
+"libstdc++.so.4.0.0".
+</p>
+<ul>
+ <li>changes in the gcc/g++ compiler ABI</li>
+<li>changing size of an exported symbol</li>
+<li>changing alignment of an exported symbol</li>
+<li>changing the layout of an exported symbol</li>
+<li>changing mangling on an exported symbol</li>
+<li>deleting an exported symbol</li>
+<li>changing the inheritance properties of a type by adding or removing
+    base classes</li>
+<li>
+  changing the size, alignment, or layout of types
+  specified in the C++ standard. These may not necessarily be
+  instantiated or otherwise exported in the library binary, and
+  include all the required locale facets, as well as things like
+  std::basic_streambuf, et al.
+</li>
+</ul>
+
+<h3 class="left">
+  <a name="implementation">Library implementation strategy</a>
+</h3>
+
+<ul>
+ <li>Separation of interface and implementation</li>
+<p>This is accomplished by two techniques that separate the API from
+the ABI: forcing undefined references to link against a library binary
+for definitions.
+</p>
+
+ <ul>
+ <li>Include files have declarations, source files have defines</li>
+
+<p> For non-templatized types, such as much of <code>class
+locale</code>, the appropriate standard C++ include, say
+<code>locale</code>, can contain full declarations, while various
+source files (say <code> locale.cc, locale_init.cc,
+localename.cc</code>) contain definitions.</p>
+
+  <li>Extern template on required types</li>
+
+   <p>For parts of the standard that have an explicit list of required
+   instantiations, the GNU extension syntax <code> extern template
+   </code> can be used to control where template definitions
+   reside. By marking required instantiations as <code> extern
+   template </code> in include files, and providing explicit
+   instantiations in the appropriate instantiation files, non-inlined
+   template functions can be versioned. This technique is mostly used
+   on parts of the standard that require <code> char</code> and <code>
+   wchar_t</code> instantiations, and includes <code>
+   basic_string</code>, the locale facets, and the types in <code>
+   iostreams</code>.</p>
+
+ </ul>
+ <p> In addition, these techniques have the additional benefit that
+ they reduce binary size, which can increase runtime performance.
+ </p>
+
+ <li>Namespaces linking symbol definitions to export mapfiles</li>
+
+<p>All symbols in the shared library binary are processed by a linker
+script at build time that either allows or disallows external
+linkage. Because of this, some symbols, regardless of normal C/C++
+linkage, are not visible. Symbols that are internal have several
+appealing characteristics: by not exporting the symbols, there are no
+relocations when the shared library is started and thus this makes for
+faster runtime loading performance by the underlying dynamic loading
+mechanism. In addition, they have the possibility of changing without
+impacting ABI compatibility.
+</p>
+
+<p>The following namespaces are transformed by the mapfile:</p>
+
+<ul>
+<li><code>namespace std</code></li>
+<p> Defaults to exporting all symbols in label
+<code>GLIBCXX</code> that do not begin with an underscore, ie
+<code>__test_func</code> would not be exported by default. Select
+exceptional symbols are allowed to be visible.</p>
+
+<li><code>namespace __gnu_cxx</code></li>
+<p> Defaults to not exporting any symbols in label
+<code>GLIBCXX</code>, select items are allowed to be visible.</p>
+
+<li><code>namespace __gnu_internal</code></li>
+<p> Defaults to not exported, no items are allowed to be visible.</p>
+
+<li><code>namespace __cxxabiv1</code>, aliased to <code> namespace abi</code></li>
+<p> Defaults to not exporting any symbols in label
+<code>CXXABI</code>, select items are allowed to be visible.</p>
+</ul>
+<p>
+</p>
+
+ <li>Freezing the API</li>
+ <p>Disallowed changes, as above, are not made on a stable release
+branch. Enforcement tends to be less strict with GNU extensions that
+standard includes.</p> </ul>
+
+<h3 class="left">
+  <a name="ABI testing">Testing ABI changes</a>
+</h3>
+
+<p>
+Testing for GNU C++ ABI changes is composed of two distinct areas:
+testing the C++ compiler (g++) for compiler changes, and testing the
+C++ library (libstdc++) for library changes.
+</p>
+
+<p>
+Testing the C++ compiler ABI can be done various ways.
+</p>
+
+<p>
+One. 
+Intel ABI checker. More information can be obtained
+<a href="http://developer.intel.com/software/products/opensource/">here.</a>
+</p>
+
+<p>
+Two.
+The second is yet unreleased, but has been announced on the gcc
+mailing list. It is yet unspecified if these tools will be freely
+available, and able to be included in a GNU project. Please contact
+Mark Mitchell (mark@codesourcery.com) for more details, and current
+status.
+</p>
+
+<p>
+Three.
+Involves using the vlad.consistency test framework. This has also been
+discussed on the gcc mailing lists.
+</p>
+
+<p>
+Testing the C++ library ABI can also be done various ways.
+</p>
+
+<p>
+One. 
+(Brendan Kehoe, Jeff Law suggestion to run 'make check-c++' two ways, 
+one with a new compiler and an old library, and the other with an old
+compiler and a new library, and look for testsuite regressions)
+</p>
+
+<p>
+Details on how to set this kind of test up can be found here:
+http://gcc.gnu.org/ml/gcc/2002-08/msg00142.html
+</p>
+
+<p>
+Two.  
+Use the 'make check-abi' rule in the libstdc++-v3 Makefile. 
+</p>
+
+<p>
+This is a proactive check the library ABI. Currently, exported symbol
+names that are either weak or defined are checked against a last known
+good baseline. Currently, this baseline is keyed off of 3.2.0
+binaries, as this was the last time the .so number was incremented. In
+addition, all exported names are demangled, and the exported objects
+are checked to make sure they are the same size as the same object in
+the baseline.
+</p>
+
+<p>
+This dataset is insufficient, yet a start. Also needed is a
+comprehensive check for all user-visible types part of the standard
+library for sizeof() and alignof() changes. 
+</p>
+
+<p>
+Verifying compatible layouts of objects is not even attempted.  It
+should be possible to use sizeof, alignof, and offsetof to compute
+offsets for each structure and type in the standard library, saving to
+another datafile. Then, compute this in a similar way for new
+binaries, and look for differences.
+</p>
+
+<p>
+Another approach might be to use the -fdump-class-hierarchy flag to
+get information. However, currently this approach gives insufficient
+data for use in library testing, as class data members, their offsets,
+and other detailed data is not displayed with this flag.
+(See g++/7470 on how this was used to find bugs.)
+</p>
+
+<p>
+Perhaps there are other C++ ABI checkers. If so, please notify
+us. We'd like to know about them!
+</p>
+
+<h3 class="left">
+  <a name="ABI multi testing">Testing Multi-ABI binaries</a>
+</h3>
+
+<p>
+A "C" application, dynamically linked to two shared libraries, liba,
+libb. The dependent library liba is C++ shared library compiled with
+gcc-3.3.x, and uses io, exceptions, locale, etc. The dependent library
+libb is a C++ shared library compiled with gcc-3.4.x, and also uses io,
+exceptions, locale, etc.
+</p>
+
+<p> As above, libone is constructed as follows: </p>
+<pre>
+%$bld/H-x86-gcc-3.4.0/bin/g++ -fPIC -DPIC -c a.cc
+
+%$bld/H-x86-gcc-3.4.0/bin/g++ -shared -Wl,-soname -Wl,libone.so.1 -Wl,-O1 -Wl,-z,defs a.o -o libone.so.1.0.0
+
+%ln -s libone.so.1.0.0 libone.so
+
+%$bld/H-x86-gcc-3.4.0/bin/g++ -c a.cc
+
+%ar cru libone.a a.o 
+</pre>
+
+<p> And, libtwo is constructed as follows: </p>
+
+<pre>
+%$bld/H-x86-gcc-3.3.3/bin/g++ -fPIC -DPIC -c b.cc
+
+%$bld/H-x86-gcc-3.3.3/bin/g++ -shared -Wl,-soname -Wl,libtwo.so.1 -Wl,-O1 -Wl,-z,defs b.o -o libtwo.so.1.0.0
+
+%ln -s libtwo.so.1.0.0 libtwo.so
+
+%$bld/H-x86-gcc-3.3.3/bin/g++ -c b.cc
+
+%ar cru libtwo.a b.o 
+</pre>
+
+<p> ...with the resulting libraries looking like </p>
+<pre>
+%ldd libone.so.1.0.0
+        libstdc++.so.6 => /usr/lib/libstdc++.so.6 (0x40016000)
+        libm.so.6 => /lib/tls/libm.so.6 (0x400fa000)
+        libgcc_s.so.1 => /mnt/hd/bld/gcc/gcc/libgcc_s.so.1 (0x4011c000)
+        libc.so.6 => /lib/tls/libc.so.6 (0x40125000)
+        /lib/ld-linux.so.2 => /lib/ld-linux.so.2 (0x00355000)
+
+%ldd libtwo.so.1.0.0
+        libstdc++.so.5 => /usr/lib/libstdc++.so.5 (0x40027000)
+        libm.so.6 => /lib/tls/libm.so.6 (0x400e1000)
+        libgcc_s.so.1 => /mnt/hd/bld/gcc/gcc/libgcc_s.so.1 (0x40103000)
+        libc.so.6 => /lib/tls/libc.so.6 (0x4010c000)
+        /lib/ld-linux.so.2 => /lib/ld-linux.so.2 (0x00355000)
+
+</pre>
+
+<p> Then, the "C" compiler is used to compile a source file that uses
+functions from each library.</p>
+<pre>
+gcc test.c -g -O2 -L. -lone -ltwo /usr/lib/libstdc++.so.5 /usr/lib/libstdc++.so.6
+</pre>
+
+<p>
+Which gives the expected:
+</p>
+<pre>
+%ldd a.out
+        libstdc++.so.5 => /usr/lib/libstdc++.so.5 (0x00764000)
+        libstdc++.so.6 => /usr/lib/libstdc++.so.6 (0x40015000)
+        libc.so.6 => /lib/tls/libc.so.6 (0x0036d000)
+        libm.so.6 => /lib/tls/libm.so.6 (0x004a8000)
+        libgcc_s.so.1 => /mnt/hd/bld/gcc/gcc/libgcc_s.so.1 (0x400e5000)
+        /lib/ld-linux.so.2 => /lib/ld-linux.so.2 (0x00355000)
+</pre>
+
+<p>
+This resulting binary, when executed, will be able to safely use code
+from both liba, and the dependent libstdc++.so.6, and libb, with the
+dependent libstdc++.so.5.
+</p>
+
+<h3 class="left">
+  <a name="references">Bibliography / Further Reading</a>
+</h3>
+
+<p>
+ABIcheck, a vague idea of checking ABI compatibility
+http://abicheck.sourceforge.net/
+
+<p>
+C++ ABI reference
+http://www.codesourcery.com/cxx-abi/
+</p>
+
+<p>
+Intel ABI documentation
+"Intel® Compilers for Linux* -Compatibility with the GNU Compilers"
+(included in icc 6.0)
+</p>
+
+<p>
+Sun Solaris 2.9 docs
+Linker and Libraries Guide (document 816-1386)
+C++ Migration Guide (document 816-2459)
+http://docs.sun.com/db/prod/solaris.9
+http://docs.sun.com/?p=/doc/816-1386&a=load
+</p>
+
+<p>
+Ulrich Drepper, "ELF Symbol Versioning"
+http://people.redhat.com/drepper/symbol-versioning
+</p>
diff --git a/libstdc++-v3/docs/html/abi.txt b/libstdc++-v3/docs/html/abi.txt
deleted file mode 100644 (file)
index 4301088..0000000
+++ /dev/null
@@ -1,389 +0,0 @@
-
-2002-10-14 Benjamin Kosnik
-
-Description of the libstdc++ ABI.
-
-I. What is an ABI? What's covered? What's not?
-
-- scope of document, of use to system integrators.
-
-- What's the deal with C++? Why can't different compiler's object
-  files link with each other? Bug? Feature?
-
-- compilation includes and linked library binary must match up..
-
-- shared library only, static is immutable.
-
-- What's an ABI?
-
-- library ABI, compiler ABI different issues, (but related)
-
-- GNU C++ does not have a compiler command line option to switch
-  between various different C++ ABIs. For instance, there is no way to
-  switch between the gcc-3.0.x ABI, gcc-3.1.x ABI, and the gcc-3.2.x
-  ABI during compilation. Other C++ compilers do allow this, and some
-  g++ command line options may change the ABI (-fno-exceptions, see
-  the complete list), but there is no version switch. Sorry. 
-
-  To use a specific C++ABI, one must use the corresponding GNU C++
-  toolchain. 
-
-- How can this complexity be managed? What does C++ versioning mean?
-  Because library and compiler changes often make binaries compiled
-  with one version of the GNU tools incompatible with binaries
-  compiled with other (either newer or older) versions of the same GNU
-  tools, specific techniques are used to make managing this complexity
-  easier.
-
-  The following techniques are used:
-
-  - Release versioning on the libgcc_s.so binary.
-
-    It is versioned as follows:
-    gcc-3.0.0: libgcc_s.so.1
-    gcc-3.0.1: libgcc_s.so.1
-    gcc-3.0.2: libgcc_s.so.1
-    gcc-3.0.3: libgcc_s.so.1
-    gcc-3.0.4: libgcc_s.so.1
-    gcc-3.1.0: libgcc_s.so.1
-    gcc-3.1.1: libgcc_s.so.1
-    gcc-3.2.0: libgcc_s.so.1
-
-
-  - Release versioning on the libstdc++.so binary.
-
-    It is versioned as follows:
-    gcc-3.0.0: libstdc++.so.3.0.0
-    gcc-3.0.1: libstdc++.so.3.0.1
-    gcc-3.0.2: libstdc++.so.3.0.2
-    gcc-3.0.3: libstdc++.so.3.0.2 (Error, should be libstdc++.so.3.0.3)
-    gcc-3.0.4: libstdc++.so.3.0.4
-    gcc-3.1.0: libstdc++.so.4.0.0
-    gcc-3.1.1: libstdc++.so.4.0.1
-    gcc-3.2.0: libstdc++.so.5.0.0
-
-
-  - Symbol versioning on the libgcc_s.so binary.
-  
-    file: gcc/libgcc-std.ver
-
-    It is versioned as follows:
-    gcc-3.0.0: GCC_3.0
-    gcc-3.0.1: GCC_3.0
-    gcc-3.0.2: GCC_3.0
-    gcc-3.0.3: GCC_3.0
-    gcc-3.0.4: GCC_3.0
-    gcc-3.1.0: GCC_3.0
-    gcc-3.1.1: GCC_3.0
-    gcc-3.2.0: GCC_3.0
-
-
-  - Symbol versioning on the libstdc++.so binary.
-  
-    It is versioned as follows:
-    gcc-3.0.0: (Error, unversioned)
-    gcc-3.0.1: (Error, unversioned)
-    gcc-3.0.2: (Error, unversioned)
-    gcc-3.0.3: (Error, unversioned)
-    gcc-3.0.4: (Error, unversioned)
-    gcc-3.1.0: GLIBCPP_3.1, CXXABI_1
-    gcc-3.1.1: GLIBCPP_3.1, CXXABI_1
-    gcc-3.2.0: GLIBCPP_3.2, CXXABI_1.2
-    
-    file: libstdc++-v3/config/linker-map.gnu
-  
-
-  - Incremental bumping of a compiler pre-defined macro,
-    __GXX_ABI_VERSION. This macro is defined as the version of the
-    compiler v3 ABI, with g++ 3.0.x being version 100. This macro will
-    be automatically defined whenever g++ is used (the curious can
-    test this by invoking g++ with the '-v' flag.)
-    
-    This macro is defined in the file "lang-specs.h" in the gcc/cp directory.
-    Later versions define it in "c-common.c" in the gcc directory.
-
-    It is versioned as follows:
-    gcc-3.0.x: 100
-    gcc-3.1.x: 100 (Error, should be 101)
-    gcc-3.2.x: 102
-
-
-  - Incremental bumping of a library pre-defined macro, __GLIBCPP__ or
-    __GLIBCXX__.  This macro is defined as the date the library was
-    released, in compressed ISO date format, as an unsigned long.
-
-    This macro is defined in the file "c++config" in the
-    "libstdc++-v3/include/bits" directory and is changed every night
-    by an automated script.
-
-    It is versioned as follows:
-    gcc-3.0.0: 20010615
-    gcc-3.0.1: 20010819
-    gcc-3.0.2: 20011023
-    gcc-3.0.3: 20011220
-    gcc-3.0.4: 20020220
-    gcc-3.1.0: 20020514
-    gcc-3.1.1: 20020725
-    gcc-3.2.0: 20020814
-
-
-  - Incremental bumping of a library pre-defined macro,
-    _GLIBCPP_VERSION. This macro is defined as the released version of
-    the library, as a string literal. This is only implemented in
-    gcc-3.1.0 releases and higher, and changed to _GLIBCXX_VERSION in 3.4.
-
-    This macro is defined in the file "c++config" in the
-    "libstdc++-v3/include/bits" directory and is generated
-    automatically by autoconf as part of the configure-time generation
-    of config.h.
-
-    It is versioned as follows:
-    gcc-3.0.0: "3.0.0"
-    gcc-3.0.1: "3.0.0" (Error, should be "3.0.1")
-    gcc-3.0.2: "3.0.0" (Error, should be "3.0.2")
-    gcc-3.0.3: "3.0.0" (Error, should be "3.0.3")
-    gcc-3.0.4: "3.0.0" (Error, should be "3.0.4")
-    gcc-3.1.0: "3.1.0"
-    gcc-3.1.1: "3.1.1"
-    gcc-3.2.0: "3.2"
-
-
-  - Matching each specific C++ compiler release to a specific set of
-    C++ include files. This is only implemented in gcc-3.1.1 releases
-    and higher.
-
-    All C++ includes are installed in include/c++, then nest in a
-    directory hierarchy corresponding to the C++ compiler's released
-    version. This version corresponds to the variable "gcc_version" in
-    "libstdc++-v3/acinclude.m4," and more details can be found in that
-    file's macro GLIBCPP_CONFIGURE.
-
-    C++ includes are versioned as follows:
-    gcc-3.0.0: include/g++-v3
-    gcc-3.0.1: include/g++-v3
-    gcc-3.0.2: include/g++-v3
-    gcc-3.0.3: include/g++-v3
-    gcc-3.0.4: include/g++-v3
-    gcc-3.1.0: include/g++-v3
-    gcc-3.1.1: include/c++/3.1.1
-    gcc-3.2.0: include/c++/3.2
-
-  Taken together, these techniques can accurately specify interface
-  and implementation changes in the GNU C++ tools themselves. Used
-  properly, they allow both the GNU C++ tools implementation, and
-  programs using them, an evolving yet controlled development that
-  maintains backward compatibility.
-
-- Minimum environment that supports a versioned ABI: what's needed?  A
-  supported dynamic linker, a GNU linker of sufficient vintage to
-  understand demangled C++ name globbing (ld), a shared executable
-  compiled with g++, and shared libraries (libgcc_s, libstdc++-v3)
-  compiled by a compiler (g++) with a compatible ABI. Phew.
-
-  On top of all that, an additional constraint: libstdc++ did not
-  attempt to version symbols (or age gracefully, really) until version
-  3.1.0. 
-
-  Most modern Linux and BSD versions, particularly ones using
-  gcc-3.1.x tools, will meet the requirements above.
-
-- What configure options impact symbol versioning?
-
-  It turns out that most of the configure options that change default
-  behavior will impact the mangled names of exported symbols, and thus
-  impact versioning and compatibility.
-
-  For more information on configure options, including ABI impacts, see:
-  http://gcc.gnu.org/onlinedocs/libstdc++/configopts.html
-
-  There is one flag that explicitly deals with symbol versioning:
-  --enable-symvers. 
-
-  In particular, libstdc++-v3/acinclude.m4 has a macro called
-  GLIBCXX_ENABLE_SYMVERS that defaults to yes (or the argument passed
-  in via --enable-symvers=foo). At that point, the macro attempts to
-  make sure that all the requirement for symbol versioning are in
-  place. For more information, please consult acinclude.m4. 
-
-- How can I tell if symbol versioning is, indeed, active? 
-
-  When the GNU C++ library is being built with symbol versioning on,
-  you should see the following at configure time for libstdc++-v3:
-
-  checking versioning on shared library symbols... gnu
-
-  If you don't see this line in the configure output, or if this line
-  appears but the last word is 'no', then you are out of luck.
-
-  If the compiler is pre-installed, a quick way to test is to compile
-  the following (or any) simple C++ file:
-
-#include <iostream>
-
-int main()
-{ std::cout << "hello" << std::endl; return 0; }
-
-%g++ hello.cc -o hello.out
-%nm hello.out
-
-If you see symbols in the resulting output with "GLIBCPP_3.x" as part
-of the name, then the executable is versioned. Here's an example:
-
-         U _ZNSt8ios_base4InitC1Ev@@GLIBCPP_3.1
-
-
-II. Library ABI changes
-
-The following will cause the library major version number to
-increase, say from "libstdc++.so.3.0.4" to "libstdc++.so.4.0.0".
-
-- (anything) changing in the gcc/g++ compiler ABI
-
-- (anything) changing size of an exported symbol
-
-- (anything) changing alignment of an exported symbol
-
-- (anything) changing the layout of an exported symbol
-
-- (anything) changing mangling on an exported symbol
-
-- (anything) deleting an exported symbol
-
-- (anything) changing the size, alignment, or layout of types
-  specified in the C++ standard. These may not necessarily be
-  instantiated or otherwise exported in the library binary, and
-  include all the required locale facets, as well as things like
-  std::basic_streambuf, et al.
-
-Note: adding an exported symbol, if it's in a new and dependent
-interface name, is ok.
-
-The following will cause the library revision version number to
-increase, say from "libstdc++.so.5.0.0" to "libstdc++.so.5.0.1".
-
-- any release of the gcc toolchain.
-
-
-III. Versioning
-
-- include files
-
-  - versioning headers with version, why necessary
-    (need to control member/non-member functions, add delete files)
-
-- shared library binaries
-
-  - release versions
-
-  - libtool versions
-
-  - when does so version get a bump? what are the options?
-
-  - how is the link map used?  
-
-  - in an non-abi breaking minor release, how are symbols added?
-    removed?
-
-  - in an abi-breaking major release, what happens? symbol fall back
-
-
-IV. Testing ABI changes
-
-Testing for GNU C++ ABI changes is composed of two distinct areas:
-testing the C++ compiler (g++) for compiler changes, and testing the
-C++ library (libstdc++) for library changes.
-
-Testing the C++ compiler ABI can be done various ways.
-
-One. 
-Intel ABI checker. More information can be obtained
-<a href="http://developer.intel.com/software/products/opensource/">here.</a>
-
-Two.
-The second is yet unreleased, but has been announced on the gcc
-mailing list. It is yet unspecified if these tools will be freely
-available, and able to be included in a GNU project. Please contact
-Mark Mitchell (mark@codesourcery.com) for more details, and current
-status.
-
-Three.
-Involves using the vlad.consistency test framework. This has also been
-discussed on the gcc mailing lists.
-
-Testing the C++ library ABI can also be done various ways.
-
-One. 
-(Brendan Kehoe, Jeff Law suggestion to run 'make check-c++' two ways, 
-one with a new compiler and an old library, and the other with an old
-compiler and a new library, and look for testsuite regressions)
-
-Details on how to set this kind of test up can be found here:
-http://gcc.gnu.org/ml/gcc/2002-08/msg00142.html
-
-Two.  
-Use the 'make check-abi' rule in the libstdc++-v3 Makefile. 
-
-This is a proactive check the library ABI. Currently, exported symbol
-names that are either weak or defined are checked against a last known
-good baseline. Currently, this baseline is keyed off of 3.2.0
-binaries, as this was the last time the .so number was incremented. In
-addition, all exported names are demangled, and the exported objects
-are checked to make sure they are the same size as the same object in
-the baseline.
-
-This dataset is insufficient, yet a start. Also needed is a
-comprehensive check for all user-visible types part of the standard
-library for sizeof() and alignof() changes. 
-
-Verifying compatible layouts of objects is not even attempted.  It
-should be possible to use sizeof, alignof, and offsetof to compute
-offsets for each structure and type in the standard library, saving to
-another datafile. Then, compute this in a similar way for new
-binaries, and look for differences.
-
-Another approach might be to use the -fdump-class-hierarchy flag to
-get information. However, currently this approach gives insufficient
-data for use in library testing, as class data members, their offsets,
-and other detailed data is not displayed with this flag.
-(See g++/7470 on how this was used to find bugs.)
-
-Perhaps there are other C++ ABI checkers. If so, please notify
-us. We'd like to know about them!
-
-
-V. Issues not directly addressed, and possible suggestions
-
-- what to do about multi-ABI systems (nathan scenario)?
-
-  - compatibility libs
-
-  --enable-version-specific-runtime-libs
-
-  - Alexandre Oliva proposal to have extended name attributes, modify ld
-  - directory-level versioning
-
-- wrapping C++ API's in "C" to use the C ABI.
-
-
-V. References
-
-ABIcheck, a vague idea of checking ABI compatibility
-http://abicheck.sourceforge.net/
-
-C++ ABI reference
-http://www.codesourcery.com/cxx-abi/
-
-Intel ABI documentation
-"Intel® Compilers for Linux* -Compatibility with the GNU Compilers"
-(included in icc 6.0)
-
-Sun Solaris 2.9 docs
-Linker and Libraries Guide (document 816-1386)
-C++ Migration Guide (document 816-2459)
-http://docs.sun.com/db/prod/solaris.9
-http://docs.sun.com/?p=/doc/816-1386&a=load
-
-Ulrich Drepper, "ELF Symbol Versioning"
-http://people.redhat.com/drepper/symbol-versioning
-
index 7819955..d1aea5a 100644 (file)
@@ -30,7 +30,7 @@
       <ul>
          <li><a href="17_intro/COPYING">License</a>
          - GPL v2 license terms</li>
-         <li><a href="abi.txt">ABI Policy and Guidelines</a></li>
+         <li><a href="abi.html">ABI Policy and Guidelines</a></li>
          <li><a href="17_intro/BUGS">BUGS</a></li>
          <li><a href="17_intro/PROBLEMS">PROBLEMS</a>
          - target-specific known issues</li>
index 0bbaa24..d5146bb 100644 (file)
@@ -63,9 +63,8 @@
 
 namespace std
 {
-
   /// pair holds two objects of arbitrary type.
-  template <class _T1, class _T2>
+  template<class _T1, class _T2>
     struct pair
     {
       typedef _T1 first_type;    ///<  @c first_type is the first bound type
@@ -79,51 +78,51 @@ namespace std
       /** The default constructor creates @c first and @c second using their
        *  respective default constructors.  */
       pair()
-      : first(), second() {}
+      : first(), second() { }
 
       /** Two objects may be passed to a @c pair constructor to be copied.  */
       pair(const _T1& __a, const _T2& __b)
-      : first(__a), second(__b) {}
+      : first(__a), second(__b) { }
 
       /** There is also a templated copy ctor for the @c pair class itself.  */
-      template <class _U1, class _U2>
+      template<class _U1, class _U2>
         pair(const pair<_U1, _U2>& __p)
-       : first(__p.first), second(__p.second) {}
+       : first(__p.first), second(__p.second) { }
     };
 
   /// Two pairs of the same type are equal iff their members are equal.
-  template <class _T1, class _T2>
+  template<class _T1, class _T2>
     inline bool
     operator==(const pair<_T1, _T2>& __x, const pair<_T1, _T2>& __y)
     { return __x.first == __y.first && __x.second == __y.second; }
 
   /// <http://gcc.gnu.org/onlinedocs/libstdc++/20_util/howto.html#pairlt>
-  template <class _T1, class _T2>
+  template<class _T1, class _T2>
     inline bool
     operator<(const pair<_T1, _T2>& __x, const pair<_T1, _T2>& __y)
     { return __x.first < __y.first
             || (!(__y.first < __x.first) && __x.second < __y.second); }
 
   /// Uses @c operator== to find the result.
-  template <class _T1, class _T2>
+  template<class _T1, class _T2>
     inline bool
     operator!=(const pair<_T1, _T2>& __x, const pair<_T1, _T2>& __y)
     { return !(__x == __y); }
 
   /// Uses @c operator< to find the result.
-  template <class _T1, class _T2>
+  template<class _T1, class _T2>
     inline bool
     operator>(const pair<_T1, _T2>& __x, const pair<_T1, _T2>& __y)
     { return __y < __x; }
 
   /// Uses @c operator< to find the result.
-  template <class _T1, class _T2>
+  template<class _T1, class _T2>
     inline bool
     operator<=(const pair<_T1, _T2>& __x, const pair<_T1, _T2>& __y)
     { return !(__y < __x); }
 
   /// Uses @c operator< to find the result.
-  template <class _T1, class _T2>
+  template<class _T1, class _T2>
     inline bool
     operator>=(const pair<_T1, _T2>& __x, const pair<_T1, _T2>& __y)
     { return !(__x < __y); }
@@ -138,18 +137,11 @@ namespace std
    *  but LWG issue #181 says they should be passed by const value.  We follow
    *  the LWG by default.
    */
-  template <class _T1, class _T2>
-
   // _GLIBCXX_RESOLVE_LIB_DEFECTS
   // 181.  make_pair() unintended behavior
-  inline pair<_T1, _T2>
-  make_pair(_T1 __x, _T2 __y)
-  { return pair<_T1, _T2>(__x, __y); }
-
+  template<class _T1, class _T2>
+    inline pair<_T1, _T2>
+    make_pair(_T1 __x, _T2 __y) { return pair<_T1, _T2>(__x, __y); }
 } // namespace std
 
 #endif /* _PAIR_H */
-
-// Local Variables:
-// mode:C++
-// End:
index c58d008..9e11ac3 100644 (file)
@@ -39,18 +39,14 @@ GLIBCXX_DIR=${glibcxx_builddir}/src/.libs
 CXXLINK = \
        $(LIBTOOL) --tag=CXX --mode=link $(CXX) \
        -R $(GLIBGCC_DIR) -R $(GLIBCXX_DIR) \
-       $(AM_CXXFLAGS) $(CXXFLAGS) $(LDFLAGS) -o $@
-
-# Generated lists of files to run.  All of these names are valid make
-# targets, if you wish to generate a list manually.
-lists_of_files = \
-   testsuite_files \
-   testsuite_files_interactive \
-   testsuite_files_performance
+       $(AM_CXXFLAGS) $(CXXFLAGS) $(LDFLAGS) -lv3test -L. -o $@
 
 ## Build support library.
 noinst_LIBRARIES = libv3test.a
-libv3test_a_SOURCES = testsuite_hooks.cc testsuite_allocator.cc
+libv3test_a_SOURCES = \
+       testsuite_abi.cc \
+       testsuite_allocator.cc \
+       testsuite_hooks.cc 
 
 ## Build support utilities.
 if GLIBCXX_TEST_ABI
@@ -59,6 +55,7 @@ else
 noinst_PROGRAMS =
 endif
 abi_check_SOURCES = abi_check.cc
+abi_check_DEPENDENCIES = libv3test.a
 
 all-local: stamp_wchar testsuite_files
 
@@ -70,6 +67,14 @@ else
 stamp_wchar:
 endif
 
+# Generated lists of files to run.  All of these names are valid make
+# targets, if you wish to generate a list manually.
+lists_of_files = \
+   testsuite_files \
+   testsuite_files_interactive \
+   testsuite_files_performance
+
+
 # We need more things in site.exp, but automake completely controls the
 # creation of that file; there's no way to append to it without messing up
 # the dependancy chains.  So we overrule automake.  This rule is exactly
index bd00606..b74f2b3 100644 (file)
@@ -58,8 +58,8 @@ ARFLAGS = cru
 LIBRARIES = $(noinst_LIBRARIES)
 libv3test_a_AR = $(AR) $(ARFLAGS)
 libv3test_a_LIBADD =
-am_libv3test_a_OBJECTS = testsuite_hooks.$(OBJEXT) \
-       testsuite_allocator.$(OBJEXT)
+am_libv3test_a_OBJECTS = testsuite_abi.$(OBJEXT) \
+       testsuite_allocator.$(OBJEXT) testsuite_hooks.$(OBJEXT)
 libv3test_a_OBJECTS = $(am_libv3test_a_OBJECTS)
 PROGRAMS = $(noinst_PROGRAMS)
 am_abi_check_OBJECTS = abi_check.$(OBJEXT)
@@ -272,8 +272,16 @@ GLIBCXX_DIR = ${glibcxx_builddir}/src/.libs
 CXXLINK = \
        $(LIBTOOL) --tag=CXX --mode=link $(CXX) \
        -R $(GLIBGCC_DIR) -R $(GLIBCXX_DIR) \
-       $(AM_CXXFLAGS) $(CXXFLAGS) $(LDFLAGS) -o $@
+       $(AM_CXXFLAGS) $(CXXFLAGS) $(LDFLAGS) -lv3test -L. -o $@
 
+noinst_LIBRARIES = libv3test.a
+libv3test_a_SOURCES = \
+       testsuite_abi.cc \
+       testsuite_allocator.cc \
+       testsuite_hooks.cc 
+
+abi_check_SOURCES = abi_check.cc
+abi_check_DEPENDENCIES = libv3test.a
 
 # Generated lists of files to run.  All of these names are valid make
 # targets, if you wish to generate a list manually.
@@ -282,9 +290,6 @@ lists_of_files = \
    testsuite_files_interactive \
    testsuite_files_performance
 
-noinst_LIBRARIES = libv3test.a
-libv3test_a_SOURCES = testsuite_hooks.cc testsuite_allocator.cc
-abi_check_SOURCES = abi_check.cc
 baseline_file = ${baseline_dir}/baseline_symbols.txt
 extract_symvers = $(glibcxx_srcdir)/scripts/extract_symvers
 
index 2116f7a..18c8b7b 100644 (file)
-// Utility for libstdc++ ABI analysis -*- C++ -*-
-
-// Copyright (C) 2002, 2003 Free Software Foundation, Inc.
-//
-// This file is part of the GNU ISO C++ Library.  This library is free
-// software; you can redistribute it and/or modify it under the
-// terms of the GNU General Public License as published by the
-// Free Software Foundation; either version 2, or (at your option)
-// any later version.
-
-// This library is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-// GNU General Public License for more details.
-
-// You should have received a copy of the GNU General Public License along
-// with this library; see the file COPYING.  If not, write to the Free
-// Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307,
-// USA.
-
-// As a special exception, you may use this file as part of a free software
-// library without restriction.  Specifically, if other files instantiate
-// templates or use macros or inline functions from this file, or you compile
-// this file and link it with other files to produce an executable, this
-// file does not by itself cause the resulting executable to be covered by
-// the GNU General Public License.  This exception does not however
-// invalidate any other reasons why the executable file might be covered by
-// the GNU General Public License.
+// -*- C++ -*-
+
+// Copyright (C) 2004 Free Software Foundation, Inc.
+
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License as
+// published by the Free Software Foundation; either version 2, or (at
+// your option) any later version.
+
+// This library is distributed in the hope that it will be useful, but
+// WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+// General Public License for more details.
+
+// You should have received a copy of the GNU General Public License
+// along with this library; see the file COPYING.  If not, write to
+// the Free Software Foundation, 59 Temple Place - Suite 330, Boston,
+// MA 02111-1307, USA.
+
+// As a special exception, you may use this file as part of a free
+// software library without restriction.  Specifically, if other files
+// instantiate templates or use macros or inline functions from this
+// file, or you compile this file and link it with other files to
+// produce an executable, this file does not by itself cause the
+// resulting executable to be covered by the GNU General Public
+// License.  This exception does not however invalidate any other
+// reasons why the executable file might be covered by the GNU General
+// Public License.
 
 // Benjamin Kosnik  <bkoz@redhat.com>
 // Blame subsequent hacks on Loren J. Rittle <ljrittle@acm.org>, Phil
 // Edwards <pme@gcc.gnu.org>, and a cast of dozens at libstdc++@gcc.gnu.org.
-
-#include <string>
-#include <ext/hash_map>
-#include <deque>
-#include <sstream>
-#include <fstream>
+#include "testsuite_abi.h"
 #include <iostream>
-#include <cxxabi.h>
-#include <stdlib.h>    // for system(3)
-#include <unistd.h>    // for access(2)
-
-struct symbol_info
-{
-  enum category { none, function, object, error };
-  category     type;  
-  std::string  name;
-  std::string  demangled_name;
-  int          size;
-  std::string  version_name;
-
-  symbol_info() : type(none), size(0) { }
-
-  symbol_info(const symbol_info& other) 
-  : type(other.type), name(other.name), demangled_name(other.demangled_name), 
-   size(other.size), version_name(other.version_name) { }
-};
-
-namespace __gnu_cxx
-{
-  using namespace std;
-
-  template<> 
-    struct hash<string>
-    {
-      size_t operator()(const string& s) const 
-      { 
-       const collate<char>& c = use_facet<collate<char> >(locale::classic());
-       return c.hash(s.c_str(), s.c_str() + s.size());
-      }
-    }; 
-}
-
-typedef std::deque<std::string>                                symbol_names;
-typedef __gnu_cxx::hash_map<std::string, symbol_info>  symbol_infos;
-
-
-bool
-check_version(const symbol_info& test, bool added = false)
-{
-  typedef std::vector<std::string> compat_list;
-  static compat_list known_versions;
-  if (known_versions.empty())
-    {
-      known_versions.push_back("GLIBCPP_3.2"); // base version
-      known_versions.push_back("GLIBCPP_3.2.1");
-      known_versions.push_back("GLIBCPP_3.2.2");
-      known_versions.push_back("GLIBCPP_3.2.3"); // gcc-3.3.0
-      known_versions.push_back("GLIBCXX_3.4");
-      known_versions.push_back("CXXABI_1.2");
-      known_versions.push_back("CXXABI_1.2.1");
-      known_versions.push_back("CXXABI_1.3");
-    }
-  compat_list::iterator begin = known_versions.begin();
-  compat_list::iterator end = known_versions.end();
-
-  // Check version names for compatibility...
-  compat_list::iterator it1 = find(begin, end, test.version_name);
-  
-  // Check for weak label.
-  compat_list::iterator it2 = find(begin, end, test.name);
-
-  // Check that added symbols aren't added in the base version.
-  bool compat = true;
-  if (added && test.version_name == known_versions[0])
-    compat = false;
-
-  if (it1 == end && it2 == end)
-    compat = false;
-
-  return compat;
-}
-
-bool 
-check_compatible(const symbol_info& lhs, const symbol_info& rhs, 
-                bool verbose = false)
-{
-  using namespace std;
-  bool ret = true;
-  const char tab = '\t';
-
-  // Check to see if symbol_infos are compatible.
-  if (lhs.type != rhs.type)
-    {
-      ret = false;
-      if (verbose)
-       {
-         cout << tab << "incompatible types" << endl;
-       }
-    }
-  
-  if (lhs.name != rhs.name)
-    {
-      ret = false;
-      if (verbose)
-       {
-         cout << tab << "incompatible names" << endl;
-       }
-    }
-
-  if (lhs.size != rhs.size)
-    {
-      ret = false;
-      if (verbose)
-       {
-         cout << tab << "incompatible sizes" << endl;
-         cout << tab << lhs.size << endl;
-         cout << tab << rhs.size << endl;
-       }
-    }
-
-  if (lhs.version_name != rhs.version_name 
-      && !check_version(lhs) && !check_version(rhs))
-    {
-      ret = false;
-      if (verbose)
-       {
-         cout << tab << "incompatible versions" << endl;
-         cout << tab << lhs.version_name << endl;
-         cout << tab << rhs.version_name << endl;
-       }
-    }
-
-  if (verbose)
-    cout << endl;
-
-  return ret;
-}
-
-const char*
-demangle(const std::string& mangled)
-{
-  const char* name;
-  if (mangled[0] != '_' || mangled[1] != 'Z')
-    {
-      // This is not a mangled symbol, thus has "C" linkage.
-      name = mangled.c_str();
-    }
-  else
-    {
-      // Use __cxa_demangle to demangle.
-      int status = 0;
-      name = abi::__cxa_demangle(mangled.c_str(), 0, 0, &status);
-      if (!name)
-       {
-         switch (status)
-           {
-           case 0:
-             name = "error code = 0: success";
-             break;
-           case -1:
-             name = "error code = -1: memory allocation failure";
-             break;
-           case -2:
-             name = "error code = -2: invalid mangled name";
-             break;
-           case -3:
-             name = "error code = -3: invalid arguments";
-             break;
-           default:
-             name = "error code unknown - who knows what happened";
-           }
-       }
-    }
-  return name;
-}
-
-void 
-line_to_symbol_info(std::string& input, symbol_info& output)
-{
-  using namespace std;
-  const char delim = ':';
-  const char version_delim = '@';
-  const string::size_type npos = string::npos;
-  string::size_type n = 0;
-
-  // Set the type.
-  if (input.find("FUNC") == 0)
-    output.type = symbol_info::function;
-  else if (input.find("OBJECT") == 0)
-    output.type = symbol_info::object;
-  else
-    output.type = symbol_info::error;
-  n = input.find_first_of(delim);
-  if (n != npos)
-    input.erase(input.begin(), input.begin() + n + 1);
-
-  // Iff object, get size info.
-  if (output.type == symbol_info::object)
-    {
-      n = input.find_first_of(delim);
-      if (n != npos)
-       {
-         string size(input.begin(), input.begin() + n);
-         istringstream iss(size);
-         int x;
-         iss >> x;
-         if (!iss.fail())
-           output.size = x;
-         input.erase(input.begin(), input.begin() + n + 1);
-       }
-    }
-
-  // Set the name.
-  n = input.find_first_of(version_delim);
-  if (n != npos)
-    {
-      // Found version string.
-      output.name = string(input.begin(), input.begin() + n);
-      n = input.find_last_of(version_delim);
-      input.erase(input.begin(), input.begin() + n + 1);
-
-      // Set version name.
-      output.version_name = input;
-    }
-  else
-    {
-      // No versioning info.
-      output.name = string(input.begin(), input.end());
-      input.erase(input.begin(), input.end());
-    }
-
-  // Set the demangled name.
-  output.demangled_name = demangle(output.name);
-}
-
-void
-create_symbol_data(const char* file, symbol_infos& symbols, 
-                  symbol_names& names)
-{
-  // Parse list of symbols in file into vectors of symbol_info.
-  // For 3.2.0 on x86/linux, this usually is
-  // 947 non-weak symbols
-  // 2084 weak symbols
-  using namespace std;
-  ifstream ifs(file); 
-  if (ifs.is_open())
-    {
-      // Organize input into container of symbol_info objects.
-      const string empty;
-      string line = empty;
-      while (getline(ifs, line).good())
-       {
-         symbol_info symbol;
-         line_to_symbol_info(line, symbol);
-         symbols[symbol.name] = symbol;
-         names.push_back(symbol.name);
-         line = empty;
-       }
-    }
-}
-
-void
-report_symbol_info(const symbol_info& symbol, std::size_t n, bool ret = true)
-{
-  using namespace std;
-  const char tab = '\t';
-
-  // Add any other information to display here.
-  cout << tab << symbol.demangled_name << endl;
-  cout << tab << symbol.name << endl;
-  cout << tab << symbol.version_name << endl;
-
-  if (ret)
-    cout << endl;
-}
-
 
 int
 main(int argc, char** argv)
@@ -313,144 +40,54 @@ main(int argc, char** argv)
   using namespace std;
 
   // Get arguments.  (Heading towards getopt_long, I can feel it.)
-  bool verbose = false;
   string argv1 = argc > 1 ? argv[1] : "";
   if (argv1 == "--help" || argc < 4)
     {
       cerr << "usage: abi_check --check         current baseline\n"
               "                 --check-verbose current baseline\n"
-              "                 --help\n\n"
-              "Where CURRENT is a file containing the current results from\n"
-              "extract_symvers, and BASELINE is one from config/abi.\n"
+              "                 --examine       symbol current\n"
+              "                 --help\n"
+             "\n"
+              "All arguments are string literals.\n"
+             "CURRENT is a file generated byextract_symvers.\n"
+              "BASELINE is a file from config/abi.\n"
+              "SYMBOL is a mangled name.\n"
           << endl;
       exit(1);
     }
-  else if (argv1 == "--check-verbose")
-    verbose = true;
-
-  // Quick sanity/setup check for arguments.
-  const char* test_file = argv[2];
-  const char* baseline_file = argv[3];
-  if (access(test_file, R_OK) != 0)
-    {
-      cerr << "Cannot read symbols file " << test_file
-           << ", did you forget to build first?" << endl;
-      exit(1);
-    }
-  if (access(baseline_file, R_OK) != 0)
-    {
-      cerr << "Cannot read baseline file " << baseline_file << endl;
-      exit(1);
-    }
-
-  // Input both lists of symbols into container.
-  symbol_infos  baseline_symbols;
-  symbol_names  baseline_names;
-  symbol_infos  test_symbols;
-  symbol_names  test_names;
-  create_symbol_data(baseline_file, baseline_symbols, baseline_names);
-  create_symbol_data(test_file, test_symbols, test_names);
-
-  //  Sanity check results.
-  const symbol_names::size_type baseline_size = baseline_names.size();
-  const symbol_names::size_type test_size = test_names.size();
-  if (!baseline_size || !test_size)
-    {
-      cerr << "Problems parsing the list of exported symbols." << endl;
-      exit(2);
-    }
-
-  // Sort out names.
-  // Assuming baseline_names, test_names are both unique w/ no duplicates.
-  //
-  // The names added to missing_names are baseline_names not found in
-  // test_names 
-  // -> symbols that have been deleted.
-  //
-  // The names added to added_names are test_names are names not in
-  // baseline_names
-  // -> symbols that have been added.
-  symbol_names shared_names;
-  symbol_names missing_names;
-  symbol_names added_names = test_names;
-  for (size_t i = 0; i < baseline_size; ++i)
-    {
-      string what(baseline_names[i]);
-      symbol_names::iterator end = added_names.end();
-      symbol_names::iterator it = find(added_names.begin(), end, what);
-      if (it != end)
+  
+  if (argv1.find("--check") != string::npos)
+    {
+      bool verbose = false;
+      if (argv1 == "--check-verbose")
+       verbose = true;
+      
+      // Quick sanity/setup check for arguments.
+      const char* test_file = argv[2];
+      const char* baseline_file = argv[3];
+      if (access(test_file, R_OK) != 0)
        {
-         // Found.
-         shared_names.push_back(what);
-         added_names.erase(it);
+         cerr << "Cannot read symbols file " << test_file
+              << ", did you forget to build first?" << endl;
+         exit(1);
        }
-      else
-         missing_names.push_back(what);
-    }
-
-  // Check missing names for compatibility.
-  typedef pair<symbol_info, symbol_info> symbol_pair;
-  vector<symbol_pair> incompatible;
-  for (size_t i = 0; i < missing_names.size(); ++i)
-    {
-      symbol_info base = baseline_symbols[missing_names[i]];
-      incompatible.push_back(symbol_pair(base, base));
-    }
-
-  // Check shared names for compatibility.
-  for (size_t i = 0; i < shared_names.size(); ++i)
-    {
-      symbol_info base = baseline_symbols[shared_names[i]];
-      symbol_info test = test_symbols[shared_names[i]];
-      if (!check_compatible(base, test))
-       incompatible.push_back(symbol_pair(base, test));
-    }
-
-  // Check added names for compatibility.
-  for (size_t i = 0; i < added_names.size(); ++i)
-    {
-      symbol_info test = test_symbols[added_names[i]];
-      if (!check_version(test, true))
-       incompatible.push_back(symbol_pair(test, test));
-    }
-
-  // Report results.
-  if (verbose && added_names.size())
-    {
-      cout << added_names.size() << " added symbols " << endl;
-      for (size_t j = 0; j < added_names.size() ; ++j)
-       report_symbol_info(test_symbols[added_names[j]], j + 1);
-    }
-  
-  if (verbose && missing_names.size())
-    {
-      cout << missing_names.size() << " missing symbols " << endl;
-      for (size_t j = 0; j < missing_names.size() ; ++j)
-       report_symbol_info(baseline_symbols[missing_names[j]], j + 1);
+      if (access(baseline_file, R_OK) != 0)
+       {
+         cerr << "Cannot read baseline file " << baseline_file << endl;
+       exit(1);
+       }
+      compare_symbols(baseline_file, test_file, verbose);
     }
   
-  if (verbose && incompatible.size())
+  if (argv1 == "--examine")
     {
-      cout << incompatible.size() << " incompatible symbols " << endl;
-      for (size_t j = 0; j < incompatible.size() ; ++j)
+      const char* file = argv[3];
+      if (access(file, R_OK) != 0)
        {
-         // First, report name.
-         const symbol_info& base = incompatible[j].first;
-         const symbol_info& test = incompatible[j].second;
-         report_symbol_info(test, j + 1, false);
-         
-         // Second, report reason or reasons incompatible.
-         check_compatible(base, test, true);
+         cerr << "Cannot read symbol file " << file << endl;
+         exit(1);
        }
+      examine_symbol(argv[2], file);
     }
-  
-  cout << "\n\t\t=== libstdc++-v3 check-abi Summary ===" << endl;
-  cout << endl;
-  cout << "# of added symbols:\t\t " << added_names.size() << endl;
-  cout << "# of missing symbols:\t\t " << missing_names.size() << endl;
-  cout << "# of incompatible symbols:\t " << incompatible.size() << endl;
-  cout << endl;
-  cout << "using: " << baseline_file << endl;
-
   return 0;
 }
diff --git a/libstdc++-v3/testsuite/testsuite_abi.cc b/libstdc++-v3/testsuite/testsuite_abi.cc
new file mode 100644 (file)
index 0000000..552da1b
--- /dev/null
@@ -0,0 +1,462 @@
+// -*- C++ -*-
+
+// Copyright (C) 2004 Free Software Foundation, Inc.
+
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License as
+// published by the Free Software Foundation; either version 2, or (at
+// your option) any later version.
+
+// This library is distributed in the hope that it will be useful, but
+// WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+// General Public License for more details.
+
+// You should have received a copy of the GNU General Public License
+// along with this library; see the file COPYING.  If not, write to
+// the Free Software Foundation, 59 Temple Place - Suite 330, Boston,
+// MA 02111-1307, USA.
+
+// As a special exception, you may use this file as part of a free
+// software library without restriction.  Specifically, if other files
+// instantiate templates or use macros or inline functions from this
+// file, or you compile this file and link it with other files to
+// produce an executable, this file does not by itself cause the
+// resulting executable to be covered by the GNU General Public
+// License.  This exception does not however invalidate any other
+// reasons why the executable file might be covered by the GNU General
+// Public License.
+
+// Benjamin Kosnik  <bkoz@redhat.com>
+
+#include "testsuite_abi.h"
+#include <sstream>
+#include <fstream>
+#include <iostream>
+
+using namespace std;
+
+void 
+symbol::init(string& data)
+{
+  const char delim = ':';
+  const char version_delim = '@';
+  const string::size_type npos = string::npos;
+  string::size_type n = 0;
+
+  // Set the type.
+  if (data.find("FUNC") == 0)
+    type = symbol::function;
+  else if (data.find("OBJECT") == 0)
+    type = symbol::object;
+  else
+    type = symbol::error;
+  n = data.find_first_of(delim);
+  if (n != npos)
+    data.erase(data.begin(), data.begin() + n + 1);
+
+  // Iff object, get size info.
+  if (type == symbol::object)
+    {
+      n = data.find_first_of(delim);
+      if (n != npos)
+       {
+         string size(data.begin(), data.begin() + n);
+         istringstream iss(size);
+         int x;
+         iss >> x;
+         if (!iss.fail())
+           size = x;
+         data.erase(data.begin(), data.begin() + n + 1);
+       }
+    }
+
+  // Set the name.
+  n = data.find_first_of(version_delim);
+  if (n != npos)
+    {
+      // Found version string.
+      name = string(data.begin(), data.begin() + n);
+      n = data.find_last_of(version_delim);
+      data.erase(data.begin(), data.begin() + n + 1);
+
+      // Set version name.
+      version_name = data;
+    }
+  else
+    {
+      // No versioning info.
+      name = string(data.begin(), data.end());
+      data.erase(data.begin(), data.end());
+    }
+
+  // Set the demangled name.
+  demangled_name = demangle(name);
+}
+
+void
+symbol::print() const
+{
+  const char tab = '\t';
+  cout << tab << name << endl;
+  cout << tab << demangled_name << endl;
+  cout << tab << version_name << endl;
+
+  string type_string;
+  switch (type)
+    {
+    case none:
+      type_string = "none";
+      break;
+    case function:
+      type_string = "function";
+      break;
+    case object:
+      type_string = "object";
+      break;
+    case error:
+      type_string = "error";
+      break;
+    default:
+      type_string = "<default>";
+    }
+  cout << tab << type_string << endl;
+  
+  if (type == object)
+    cout << tab << size << endl;
+
+  string status_string;
+  switch (status)
+    {
+    case unknown:
+      status_string = "unknown";
+      break;
+    case added:
+      status_string = "added";
+      break;
+    case subtracted:
+      status_string = "subtracted";
+      break;
+    case compatible:
+      status_string = "compatible";
+      break;
+    case incompatible:
+      status_string = "incompatible";
+      break;
+    default:
+      status_string = "<default>";
+    }
+  cout << tab << status_string << endl;
+}
+
+
+bool
+check_version(const symbol& test, bool added)
+{
+  typedef std::vector<std::string> compat_list;
+  static compat_list known_versions;
+  if (known_versions.empty())
+    {
+      known_versions.push_back("GLIBCPP_3.2"); // base version
+      known_versions.push_back("GLIBCPP_3.2.1");
+      known_versions.push_back("GLIBCPP_3.2.2");
+      known_versions.push_back("GLIBCPP_3.2.3"); // gcc-3.3.0
+      known_versions.push_back("GLIBCXX_3.4");
+      known_versions.push_back("CXXABI_1.2");
+      known_versions.push_back("CXXABI_1.2.1");
+      known_versions.push_back("CXXABI_1.3");
+    }
+  compat_list::iterator begin = known_versions.begin();
+  compat_list::iterator end = known_versions.end();
+
+  // Check version names for compatibility...
+  compat_list::iterator it1 = find(begin, end, test.version_name);
+  
+  // Check for weak label.
+  compat_list::iterator it2 = find(begin, end, test.name);
+
+  // Check that added symbols aren't added in the base version.
+  bool compat = true;
+  if (added && test.version_name == known_versions[0])
+    compat = false;
+
+  if (it1 == end && it2 == end)
+    compat = false;
+
+  return compat;
+}
+
+bool 
+check_compatible(const symbol& lhs, const symbol& rhs, bool verbose)
+{
+  bool ret = true;
+  const char tab = '\t';
+
+  // Check to see if symbol_objects are compatible.
+  if (lhs.type != rhs.type)
+    {
+      ret = false;
+      if (verbose)
+       cout << tab << "incompatible types" << endl;
+    }
+  
+  if (lhs.name != rhs.name)
+    {
+      ret = false;
+      if (verbose)
+       cout << tab << "incompatible names" << endl;
+    }
+
+  if (lhs.size != rhs.size)
+    {
+      ret = false;
+      if (verbose)
+       {
+         cout << tab << "incompatible sizes" << endl;
+         cout << tab << lhs.size << endl;
+         cout << tab << rhs.size << endl;
+       }
+    }
+
+  if (lhs.version_name != rhs.version_name 
+      && !check_version(lhs) && !check_version(rhs))
+    {
+      ret = false;
+      if (verbose)
+       {
+         cout << tab << "incompatible versions" << endl;
+         cout << tab << lhs.version_name << endl;
+         cout << tab << rhs.version_name << endl;
+       }
+    }
+
+  if (verbose)
+    cout << endl;
+
+  return ret;
+}
+
+
+bool
+has_symbol(const string& mangled, const symbols& s) throw()
+{
+  const symbol_names& names = s.first;
+  symbol_names::const_iterator i = find(names.begin(), names.end(), mangled);
+  return i != names.end();
+}
+
+symbol&
+get_symbol(const string& mangled, const symbols& s)
+{
+  const symbol_names& names = s.first;
+  symbol_names::const_iterator i = find(names.begin(), names.end(), mangled);
+  if (i != names.end())
+    {
+      symbol_objects objects = s.second;
+      return objects[mangled];
+    }
+  else
+    {
+      ostringstream os;
+      os << "get_symbol failed for symbol " << mangled;
+      throw symbol_error(os.str());
+    }
+}
+
+void 
+examine_symbol(const char* name, const char* file)
+{
+  try
+    {
+      symbols s = create_symbols(file);
+      symbol& sym = get_symbol(name, s);
+      sym.print();
+    }
+  catch(...)
+    { throw; }
+}
+
+void 
+compare_symbols(const char* baseline_file, const char* test_file, 
+               bool verbose)
+{
+  // Input both lists of symbols into container.
+  symbols baseline = create_symbols(baseline_file);
+  symbols test = create_symbols(test_file);
+  symbol_names& baseline_names = baseline.first;
+  symbol_objects& baseline_objects = baseline.second;
+  symbol_names& test_names = test.first;
+  symbol_objects& test_objects = test.second;
+
+  //  Sanity check results.
+  const symbol_names::size_type baseline_size = baseline_names.size();
+  const symbol_names::size_type test_size = test_names.size();
+  if (!baseline_size || !test_size)
+    {
+      cerr << "Problems parsing the list of exported symbols." << endl;
+      exit(2);
+    }
+
+  // Sort out names.
+  // Assuming baseline_names, test_names are both unique w/ no duplicates.
+  //
+  // The names added to missing_names are baseline_names not found in
+  // test_names 
+  // -> symbols that have been deleted.
+  //
+  // The names added to added_names are test_names are names not in
+  // baseline_names
+  // -> symbols that have been added.
+  symbol_names shared_names;
+  symbol_names missing_names;
+  symbol_names added_names = test_names;
+  for (size_t i = 0; i < baseline_size; ++i)
+    {
+      string what(baseline_names[i]);
+      symbol_names::iterator end = added_names.end();
+      symbol_names::iterator it = find(added_names.begin(), end, what);
+      if (it != end)
+       {
+         // Found.
+         shared_names.push_back(what);
+         added_names.erase(it);
+       }
+      else
+         missing_names.push_back(what);
+    }
+
+  // Check missing names for compatibility.
+  typedef pair<symbol, symbol> symbol_pair;
+  vector<symbol_pair> incompatible;
+  for (size_t i = 0; i < missing_names.size(); ++i)
+    {
+      symbol base = baseline_objects[missing_names[i]];
+      incompatible.push_back(symbol_pair(base, base));
+    }
+
+  // Check shared names for compatibility.
+  for (size_t i = 0; i < shared_names.size(); ++i)
+    {
+      symbol base = baseline_objects[shared_names[i]];
+      symbol test = test_objects[shared_names[i]];
+      if (!check_compatible(base, test))
+       incompatible.push_back(symbol_pair(base, test));
+    }
+
+  // Check added names for compatibility.
+  for (size_t i = 0; i < added_names.size(); ++i)
+    {
+      symbol test = test_objects[added_names[i]];
+      if (!check_version(test, true))
+       incompatible.push_back(symbol_pair(test, test));
+    }
+
+  // Report results.
+  if (verbose && added_names.size())
+    {
+      cout << added_names.size() << " added symbols " << endl;
+      for (size_t j = 0; j < added_names.size() ; ++j)
+       test_objects[added_names[j]].print();
+    }
+  
+  if (verbose && missing_names.size())
+    {
+      cout << missing_names.size() << " missing symbols " << endl;
+      for (size_t j = 0; j < missing_names.size() ; ++j)
+       baseline_objects[missing_names[j]].print();
+    }
+  
+  if (verbose && incompatible.size())
+    {
+      cout << incompatible.size() << " incompatible symbols " << endl;
+      for (size_t j = 0; j < incompatible.size() ; ++j)
+       {
+         // First, report name.
+         const symbol& base = incompatible[j].first;
+         const symbol& test = incompatible[j].second;
+         test.print();
+         
+         // Second, report reason or reasons incompatible.
+         check_compatible(base, test, true);
+       }
+    }
+  
+  cout << "\n\t\t=== libstdc++-v3 check-abi Summary ===" << endl;
+  cout << endl;
+  cout << "# of added symbols:\t\t " << added_names.size() << endl;
+  cout << "# of missing symbols:\t\t " << missing_names.size() << endl;
+  cout << "# of incompatible symbols:\t " << incompatible.size() << endl;
+  cout << endl;
+  cout << "using: " << baseline_file << endl;
+}
+
+
+symbols
+create_symbols(const char* file)
+{
+  symbols s;
+  ifstream ifs(file);
+  if (ifs.is_open())
+    {
+      // Organize file data into container of symbol objects.
+      symbol_names& names = s.first;
+      symbol_objects& objects = s.second;
+      const string empty;
+      string line = empty;
+      while (getline(ifs, line).good())
+       {
+         symbol tmp;
+         tmp.init(line);
+         objects[tmp.name] = tmp;
+         names.push_back(tmp.name);
+         line = empty;
+       }
+    }
+  else
+    {
+      ostringstream os;
+      os << "create_symbols failed for file " << file;
+      throw runtime_error(os.str());
+    }
+  return s;
+}
+
+
+const char*
+demangle(const std::string& mangled)
+{
+  const char* name;
+  if (mangled[0] != '_' || mangled[1] != 'Z')
+    {
+      // This is not a mangled symbol, thus has "C" linkage.
+      name = mangled.c_str();
+    }
+  else
+    {
+      // Use __cxa_demangle to demangle.
+      int status = 0;
+      name = abi::__cxa_demangle(mangled.c_str(), 0, 0, &status);
+      if (!name)
+       {
+         switch (status)
+           {
+           case 0:
+             name = "error code = 0: success";
+             break;
+           case -1:
+             name = "error code = -1: memory allocation failure";
+             break;
+           case -2:
+             name = "error code = -2: invalid mangled name";
+             break;
+           case -3:
+             name = "error code = -3: invalid arguments";
+             break;
+           default:
+             name = "error code unknown - who knows what happened";
+           }
+       }
+    }
+  return name;
+}
+
diff --git a/libstdc++-v3/testsuite/testsuite_abi.h b/libstdc++-v3/testsuite/testsuite_abi.h
new file mode 100644 (file)
index 0000000..ebacb6a
--- /dev/null
@@ -0,0 +1,129 @@
+// -*- C++ -*-
+
+// Copyright (C) 2004 Free Software Foundation, Inc.
+
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License as
+// published by the Free Software Foundation; either version 2, or (at
+// your option) any later version.
+
+// This library is distributed in the hope that it will be useful, but
+// WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+// General Public License for more details.
+
+// You should have received a copy of the GNU General Public License
+// along with this library; see the file COPYING.  If not, write to
+// the Free Software Foundation, 59 Temple Place - Suite 330, Boston,
+// MA 02111-1307, USA.
+
+// As a special exception, you may use this file as part of a free
+// software library without restriction.  Specifically, if other files
+// instantiate templates or use macros or inline functions from this
+// file, or you compile this file and link it with other files to
+// produce an executable, this file does not by itself cause the
+// resulting executable to be covered by the GNU General Public
+// License.  This exception does not however invalidate any other
+// reasons why the executable file might be covered by the GNU General
+// Public License.
+
+// Benjamin Kosnik  <bkoz@redhat.com>
+
+#include <string>
+#include <stdexcept>
+#include <deque>
+#include <ext/hash_map>
+#include <cxxabi.h>
+
+// Encapsulates symbol characteristics.
+struct symbol
+{
+  enum category { none, function, object, error };
+  enum designation { unknown, added, subtracted, compatible, incompatible };
+  enum compatibility 
+    { 
+      compat_type = 1, 
+      compat_name = 2, 
+      compat_size = 4, 
+      compat_version = 8 
+    };
+
+  category     type;
+  std::string  name;
+  std::string  demangled_name;
+  int          size;
+  std::string  version_name;
+  designation  status;
+
+  symbol() : type(none), size(0), status(unknown) { }
+
+  symbol(const symbol& other) 
+  : type(other.type), name(other.name), demangled_name(other.demangled_name), 
+   size(other.size), version_name(other.version_name),
+   status(other.status) { }
+
+  void
+  print() const;
+
+  void
+  init(std::string& data);
+};
+
+struct symbol_error : public std::logic_error
+{
+  explicit symbol_error(const std::string& s) : std::logic_error(s) { }
+};
+
+
+typedef __gnu_cxx::hash_map<std::string, symbol>       symbol_objects;
+
+typedef std::deque<std::string>                                symbol_names;
+
+typedef std::pair<symbol_names, symbol_objects>                symbols;
+
+
+// Check.
+bool
+check_version(const symbol& test, bool added = false);
+
+bool 
+check_compatible(const symbol& lhs, const symbol& rhs, bool verbose = false);
+
+
+// Examine.
+bool
+has_symbol(const std::string& mangled, const symbols& list) throw();
+
+symbol&
+get_symbol(const std::string& mangled, const symbols& list);
+
+extern "C" void
+examine_symbol(const char* name, const char* file);
+
+extern "C" void
+compare_symbols(const char* baseline_file, const char* test_file, bool verb);
+
+
+// Util.
+symbols
+create_symbols(const char* file);
+
+const char*
+demangle(const std::string& mangled);
+
+
+// Specialization.
+namespace __gnu_cxx
+{
+  using namespace std;
+
+  template<> 
+    struct hash<string>
+    {
+      size_t operator()(const string& s) const 
+      { 
+       const collate<char>& c = use_facet<collate<char> >(locale::classic());
+       return c.hash(s.c_str(), s.c_str() + s.size());
+      }
+    }; 
+}