diff -r 000000000000 -r 83f4b4db085c toolsandutils/e32tools/checklib/main.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/toolsandutils/e32tools/checklib/main.cpp Tue Feb 02 01:39:43 2010 +0200 @@ -0,0 +1,173 @@ +// Copyright (c) 2008-2009 Nokia Corporation and/or its subsidiary(-ies). +// All rights reserved. +// This component and the accompanying materials are made available +// under the terms of "Eclipse Public License v1.0" +// which accompanies this distribution, and is available +// at the URL "http://www.eclipse.org/legal/epl-v10.html". +// +// Initial Contributors: +// Nokia Corporation - initial contribution. +// +// Contributors: +// +// Description: +// Entry point for the checklib utility. +// +// + +#include "library/library.h" // For handling libraries of Unix "ar" format. +#include "object/object.h" // For handling (parts of) ELF and COFF object files. + +#include +#include +#include +#include + + +const char SELF_NAME[] = "checklib"; + +// Describes what kind of library it is. +enum libkind_t +{ + STDCPP, // Library should be compatible with Symbian C++. + SYMCPP // Library should be compatible with standard C++ (Open Environment). +}; + +// Describes what kind of objects are in the library: ELF or COFF. +typedef Object_factory::objkind_t objkind_t; + +void _usage_and_exit(int exit_code=EXIT_FAILURE); +void _error_and_exit(const std::string&, int exit_code=EXIT_FAILURE); + +// These are the ::operator new symbols we are worried about. +const char* NEW_NAMES[2][4] = { + {"_Znwj", "_Znaj", "_ZnwjRKSt9nothrow_t", "_ZnajRKSt9nothrow_t"}, // ELF + {"??2@YAPAXI@Z", "??_U@YAPAXI@Z", "??2@YAPAXIABUnothrow_t@std@@@Z", "??_U@YAPAXIABUnothrow_t@std@@@Z"} // COFF +}; + +// Checks whether the object files in the given library references any of the +// ::operator new functions. +bool _lib_ref_new(const Library&, objkind_t); + + +int main(int argc, const char* argv[]) +{ + // Do we have any standard module for handling the command-line interface? If + // not, see if we can start using getopt or Boost. + + if (argc < 4) + { + _usage_and_exit(); + } + + // Command-line options. + libkind_t opt_libkind; + objkind_t opt_objkind; + + if ( std::strcmp(argv[1], "stdc++") == 0 ) + { + opt_libkind = STDCPP; + } + else if ( std::strcmp(argv[1], "symc++") == 0 ) + { + opt_libkind = SYMCPP; + } + else + { + _usage_and_exit(); + } + + if ( std::strcmp(argv[2], "--elf") == 0 ) + { + opt_objkind = Object_factory::ELF; + } + else if ( std::strcmp(argv[2], "--coff") == 0 ) + { + opt_objkind = Object_factory::COFF; + } + else + { + _usage_and_exit(); + } + + try + { + // Check each library that was given on the command-line. + for (int i = 3; i < argc; i++) + { + Library lib( argv[i] ); // May throw std::runtime_error. + + // If the library has the tag, we know that it was built to be OE + // compatible, and vice versa. + bool lib_is_tagged = lib.contains_symbol("____symbian_stdcpp_mmviii"); + + // Handle the two only possible error cases: + + if ( opt_libkind == STDCPP && !lib_is_tagged && _lib_ref_new(lib, opt_objkind) ) + { + std::ostringstream err_msg; + err_msg << "library " << argv[i] << " is incompatible with standard C++"; + + _error_and_exit(err_msg.str()); + } + else if ( opt_libkind == SYMCPP && lib_is_tagged && _lib_ref_new(lib, opt_objkind) ) + { + std::ostringstream err_msg; + err_msg << "library " << argv[i] << " is incompatible with Symbian C++"; + + _error_and_exit(err_msg.str()); + } + } + } + catch (std::runtime_error& e) + { + _error_and_exit( e.what() ); + } + + return 0; +} + +void _error_and_exit(const std::string& a_msg, int a_exit_code) +{ + std::cerr << SELF_NAME << ": error: " << a_msg << "." << std::endl; + std::exit(a_exit_code); +} + +void _usage_and_exit(int a_exit_code) +{ + using std::cout; + using std::endl; + + cout << "usage: " << SELF_NAME << " stdc++ --elf|--coff \n" + << " " << SELF_NAME << " symc++ --elf|--coff " << endl; + + std::exit(a_exit_code); +} + +bool _lib_ref_new(const Library& a_lib, objkind_t a_objkind) +{ + typedef std::vector< std::pair > T; + + const T* objects_p = a_lib.get_objects(); + + T::const_iterator p = objects_p->begin(); + T::const_iterator end_p = objects_p->end(); + + // Iterate over all the objects ... + for (; p != end_p; ++p) + { + std::auto_ptr obj_p = Object_factory::create(a_objkind, p->first, p->second); + + // ... And check for references to any ::operator new function. + for (unsigned i = 0; i < sizeof(NEW_NAMES[a_objkind]) / sizeof(NEW_NAMES[a_objkind][0]); i++) + { + if ( obj_p->is_undef(NEW_NAMES[a_objkind][i]) ) + { + return 1; + } + } + } + + return 0; +} +