|
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 |