Don't mess around with EPOCROOT until actually entering raptor so we know what the original was
Put the original epocroot back on the front of the whatcomp output. This allows what output to be
either relative or absolute depending on what your epocroot is.
// 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 <string>
#include <sstream>
#include <iostream>
#include <stdexcept>
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 <lib_list>\n"
<< " " << SELF_NAME << " symc++ --elf|--coff <lib_list>" << endl;
std::exit(a_exit_code);
}
bool _lib_ref_new(const Library& a_lib, objkind_t a_objkind)
{
typedef std::vector< std::pair<const char*, const char*> > 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<Object> 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;
}