bintools/checklib/main.cpp
changeset 2 39c28ec933dd
child 11 d610106f78c9
equal deleted inserted replaced
1:820b22e13ff1 2:39c28ec933dd
       
     1 // Copyright (c) 2008-2009 Nokia Corporation and/or its subsidiary(-ies).
       
     2 // All rights reserved.
       
     3 // This component and the accompanying materials are made available
       
     4 // under the terms of "Eclipse Public License v1.0"
       
     5 // which accompanies this distribution, and is available
       
     6 // at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     7 //
       
     8 // Initial Contributors:
       
     9 // Nokia Corporation - initial contribution.
       
    10 //
       
    11 // Contributors:
       
    12 //
       
    13 // Description:
       
    14 // Entry point for the checklib utility.
       
    15 // 
       
    16 //
       
    17 
       
    18 #include "library/library.h" // For handling libraries of Unix "ar" format.
       
    19 #include "object/object.h"   // For handling (parts of) ELF and COFF object files.
       
    20 
       
    21 #include <string>
       
    22 #include <sstream>
       
    23 #include <iostream>
       
    24 #include <stdexcept>
       
    25 #include <cstring>
       
    26 
       
    27 
       
    28 const char SELF_NAME[] = "checklib";
       
    29 
       
    30 // Describes what kind of library it is.
       
    31 enum libkind_t
       
    32 {
       
    33     STDCPP, // Library should be compatible with Symbian C++.
       
    34     SYMCPP  // Library should be compatible with standard C++ (Open Environment).
       
    35 };
       
    36 
       
    37 // Describes what kind of objects are in the library: ELF or COFF.
       
    38 typedef Object_factory::objkind_t objkind_t;
       
    39 
       
    40 void _usage_and_exit(int exit_code=EXIT_FAILURE);
       
    41 void _error_and_exit(const std::string&, int exit_code=EXIT_FAILURE);
       
    42 
       
    43 // These are the ::operator new symbols we are worried about.
       
    44 const char* NEW_NAMES[2][4] = {
       
    45     {"_Znwj", "_Znaj", "_ZnwjRKSt9nothrow_t", "_ZnajRKSt9nothrow_t"}, // ELF
       
    46     {"??2@YAPAXI@Z", "??_U@YAPAXI@Z", "??2@YAPAXIABUnothrow_t@std@@@Z", "??_U@YAPAXIABUnothrow_t@std@@@Z"} // COFF
       
    47 };
       
    48 
       
    49 // Checks whether the object files in the given library references any of the
       
    50 // ::operator new functions.
       
    51 bool _lib_ref_new(const Library&, objkind_t);
       
    52 
       
    53 
       
    54 int main(int argc, const char* argv[])
       
    55 {
       
    56     // Do we have any standard module for handling the command-line interface? If
       
    57     // not, see if we can start using getopt or Boost. 
       
    58 
       
    59     if (argc < 4)
       
    60     {
       
    61         _usage_and_exit();
       
    62     }
       
    63 
       
    64     // Command-line options.
       
    65     libkind_t opt_libkind;
       
    66     objkind_t opt_objkind;
       
    67 
       
    68     if ( std::strcmp(argv[1], "stdc++") == 0 )
       
    69     {
       
    70         opt_libkind = STDCPP;
       
    71     }
       
    72     else if ( std::strcmp(argv[1], "symc++") == 0 )
       
    73     {
       
    74         opt_libkind = SYMCPP;
       
    75     }
       
    76     else
       
    77     {
       
    78         _usage_and_exit();
       
    79     }
       
    80 
       
    81     if ( std::strcmp(argv[2], "--elf") == 0 )
       
    82     {
       
    83         opt_objkind = Object_factory::ELF;
       
    84     }
       
    85     else if ( std::strcmp(argv[2], "--coff") == 0 )
       
    86     {
       
    87         opt_objkind = Object_factory::COFF;
       
    88     }
       
    89     else
       
    90     {
       
    91         _usage_and_exit();
       
    92     }
       
    93 
       
    94     try
       
    95     {
       
    96         // Check each library that was given on the command-line.
       
    97         for (int i = 3; i < argc; i++)
       
    98         {
       
    99             Library lib( argv[i] ); // May throw std::runtime_error.
       
   100 
       
   101             // If the library has the tag, we know that it was built to be OE
       
   102             // compatible, and vice versa.
       
   103             bool lib_is_tagged = lib.contains_symbol("____symbian_stdcpp_mmviii");
       
   104 
       
   105             // Handle the two only possible error cases:
       
   106 
       
   107             if ( opt_libkind == STDCPP && !lib_is_tagged && _lib_ref_new(lib, opt_objkind) )
       
   108             {
       
   109                 std::ostringstream err_msg;
       
   110                 err_msg << "library " << argv[i] <<  " is incompatible with standard C++";
       
   111 
       
   112                 _error_and_exit(err_msg.str());
       
   113             }
       
   114             else if ( opt_libkind == SYMCPP && lib_is_tagged && _lib_ref_new(lib, opt_objkind) )
       
   115             {
       
   116                 std::ostringstream err_msg;
       
   117                 err_msg << "library " << argv[i] <<  " is incompatible with Symbian C++";
       
   118 
       
   119                 _error_and_exit(err_msg.str());
       
   120             }
       
   121         }
       
   122     }
       
   123     catch (std::runtime_error& e)
       
   124     {
       
   125         _error_and_exit( e.what() );
       
   126     }
       
   127 
       
   128     return 0;
       
   129 }
       
   130 
       
   131 void _error_and_exit(const std::string& a_msg, int a_exit_code)
       
   132 {
       
   133     std::cerr << SELF_NAME << ": error: " << a_msg << "." << std::endl;
       
   134     std::exit(a_exit_code);
       
   135 }
       
   136 
       
   137 void _usage_and_exit(int a_exit_code)
       
   138 {
       
   139     using std::cout;
       
   140     using std::endl;
       
   141 
       
   142     cout << "usage: " << SELF_NAME << " stdc++ --elf|--coff <lib_list>\n"
       
   143          << "       " << SELF_NAME << " symc++ --elf|--coff <lib_list>" << endl;
       
   144 
       
   145     std::exit(a_exit_code);
       
   146 }
       
   147 
       
   148 bool _lib_ref_new(const Library& a_lib, objkind_t a_objkind)
       
   149 {
       
   150     typedef std::vector< std::pair<const char*, const char*> > T;
       
   151 
       
   152     const T* objects_p = a_lib.get_objects();
       
   153 
       
   154     T::const_iterator p = objects_p->begin();
       
   155     T::const_iterator end_p = objects_p->end();
       
   156 
       
   157     // Iterate over all the objects ...
       
   158     for (; p != end_p; ++p)
       
   159     {
       
   160         std::auto_ptr<Object> obj_p = Object_factory::create(a_objkind, p->first, p->second);
       
   161 
       
   162         // ... And check for references to any ::operator new function.
       
   163         for (unsigned i = 0; i < sizeof(NEW_NAMES[a_objkind]) / sizeof(NEW_NAMES[a_objkind][0]); i++)
       
   164         {
       
   165             if ( obj_p->is_undef(NEW_NAMES[a_objkind][i]) )
       
   166             {
       
   167                 return 1;
       
   168             }
       
   169         }
       
   170     }
       
   171 
       
   172     return 0;
       
   173 }
       
   174