bintools/checklib/main.cpp
changeset 0 044383f39525
equal deleted inserted replaced
-1:000000000000 0:044383f39525
       
     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 
       
    26 
       
    27 const char SELF_NAME[] = "checklib";
       
    28 
       
    29 // Describes what kind of library it is.
       
    30 enum libkind_t
       
    31 {
       
    32     STDCPP, // Library should be compatible with Symbian C++.
       
    33     SYMCPP  // Library should be compatible with standard C++ (Open Environment).
       
    34 };
       
    35 
       
    36 // Describes what kind of objects are in the library: ELF or COFF.
       
    37 typedef Object_factory::objkind_t objkind_t;
       
    38 
       
    39 void _usage_and_exit(int exit_code=EXIT_FAILURE);
       
    40 void _error_and_exit(const std::string&, int exit_code=EXIT_FAILURE);
       
    41 
       
    42 // These are the ::operator new symbols we are worried about.
       
    43 const char* NEW_NAMES[2][4] = {
       
    44     {"_Znwj", "_Znaj", "_ZnwjRKSt9nothrow_t", "_ZnajRKSt9nothrow_t"}, // ELF
       
    45     {"??2@YAPAXI@Z", "??_U@YAPAXI@Z", "??2@YAPAXIABUnothrow_t@std@@@Z", "??_U@YAPAXIABUnothrow_t@std@@@Z"} // COFF
       
    46 };
       
    47 
       
    48 // Checks whether the object files in the given library references any of the
       
    49 // ::operator new functions.
       
    50 bool _lib_ref_new(const Library&, objkind_t);
       
    51 
       
    52 
       
    53 int main(int argc, const char* argv[])
       
    54 {
       
    55     // Do we have any standard module for handling the command-line interface? If
       
    56     // not, see if we can start using getopt or Boost. 
       
    57 
       
    58     if (argc < 4)
       
    59     {
       
    60         _usage_and_exit();
       
    61     }
       
    62 
       
    63     // Command-line options.
       
    64     libkind_t opt_libkind;
       
    65     objkind_t opt_objkind;
       
    66 
       
    67     if ( std::strcmp(argv[1], "stdc++") == 0 )
       
    68     {
       
    69         opt_libkind = STDCPP;
       
    70     }
       
    71     else if ( std::strcmp(argv[1], "symc++") == 0 )
       
    72     {
       
    73         opt_libkind = SYMCPP;
       
    74     }
       
    75     else
       
    76     {
       
    77         _usage_and_exit();
       
    78     }
       
    79 
       
    80     if ( std::strcmp(argv[2], "--elf") == 0 )
       
    81     {
       
    82         opt_objkind = Object_factory::ELF;
       
    83     }
       
    84     else if ( std::strcmp(argv[2], "--coff") == 0 )
       
    85     {
       
    86         opt_objkind = Object_factory::COFF;
       
    87     }
       
    88     else
       
    89     {
       
    90         _usage_and_exit();
       
    91     }
       
    92 
       
    93     try
       
    94     {
       
    95         // Check each library that was given on the command-line.
       
    96         for (int i = 3; i < argc; i++)
       
    97         {
       
    98             Library lib( argv[i] ); // May throw std::runtime_error.
       
    99 
       
   100             // If the library has the tag, we know that it was built to be OE
       
   101             // compatible, and vice versa.
       
   102             bool lib_is_tagged = lib.contains_symbol("____symbian_stdcpp_mmviii");
       
   103 
       
   104             // Handle the two only possible error cases:
       
   105 
       
   106             if ( opt_libkind == STDCPP && !lib_is_tagged && _lib_ref_new(lib, opt_objkind) )
       
   107             {
       
   108                 std::ostringstream err_msg;
       
   109                 err_msg << "library " << argv[i] <<  " is incompatible with standard C++";
       
   110 
       
   111                 _error_and_exit(err_msg.str());
       
   112             }
       
   113             else if ( opt_libkind == SYMCPP && lib_is_tagged && _lib_ref_new(lib, opt_objkind) )
       
   114             {
       
   115                 std::ostringstream err_msg;
       
   116                 err_msg << "library " << argv[i] <<  " is incompatible with Symbian C++";
       
   117 
       
   118                 _error_and_exit(err_msg.str());
       
   119             }
       
   120         }
       
   121     }
       
   122     catch (std::runtime_error& e)
       
   123     {
       
   124         _error_and_exit( e.what() );
       
   125     }
       
   126 
       
   127     return 0;
       
   128 }
       
   129 
       
   130 void _error_and_exit(const std::string& a_msg, int a_exit_code)
       
   131 {
       
   132     std::cerr << SELF_NAME << ": error: " << a_msg << "." << std::endl;
       
   133     std::exit(a_exit_code);
       
   134 }
       
   135 
       
   136 void _usage_and_exit(int a_exit_code)
       
   137 {
       
   138     using std::cout;
       
   139     using std::endl;
       
   140 
       
   141     cout << "usage: " << SELF_NAME << " stdc++ --elf|--coff <lib_list>\n"
       
   142          << "       " << SELF_NAME << " symc++ --elf|--coff <lib_list>" << endl;
       
   143 
       
   144     std::exit(a_exit_code);
       
   145 }
       
   146 
       
   147 bool _lib_ref_new(const Library& a_lib, objkind_t a_objkind)
       
   148 {
       
   149     typedef std::vector< std::pair<const char*, const char*> > T;
       
   150 
       
   151     const T* objects_p = a_lib.get_objects();
       
   152 
       
   153     T::const_iterator p = objects_p->begin();
       
   154     T::const_iterator end_p = objects_p->end();
       
   155 
       
   156     // Iterate over all the objects ...
       
   157     for (; p != end_p; ++p)
       
   158     {
       
   159         std::auto_ptr<Object> obj_p = Object_factory::create(a_objkind, p->first, p->second);
       
   160 
       
   161         // ... And check for references to any ::operator new function.
       
   162         for (unsigned i = 0; i < sizeof(NEW_NAMES[a_objkind]) / sizeof(NEW_NAMES[a_objkind][0]); i++)
       
   163         {
       
   164             if ( obj_p->is_undef(NEW_NAMES[a_objkind][i]) )
       
   165             {
       
   166                 return 1;
       
   167             }
       
   168         }
       
   169     }
       
   170 
       
   171     return 0;
       
   172 }
       
   173