00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019 #include <dtoolbase.h>
00020
00021 #include <interrogate_interface.h>
00022 #include <interrogate_request.h>
00023 #include <load_dso.h>
00024 #include <filename.h>
00025 #include <pystub.h>
00026
00027 #include <stdlib.h>
00028
00029 #ifndef HAVE_GETOPT
00030 #include <gnu_getopt.h>
00031 #else
00032 #include <getopt.h>
00033 #endif
00034
00035
00036
00037 static ostream &
00038 indent(ostream &out, int indent_level) {
00039 for (int i = 0; i < indent_level; i++) {
00040 out << ' ';
00041 }
00042 return out;
00043 }
00044
00045 void
00046 show_type(int type, bool verbose = false) {
00047 cout << interrogate_type_name(type) << " ";
00048 if (verbose) {
00049 if (strcmp(interrogate_type_name(type),
00050 interrogate_type_true_name(type)) != 0) {
00051 cout << "(" << interrogate_type_true_name(type) << ") ";
00052 }
00053 }
00054 cout << "(" << type << ")";
00055 }
00056
00057 void
00058 show_function(int function) {
00059 cout << interrogate_function_scoped_name(function) << " (" << function << ")";
00060 }
00061
00062 void
00063 describe_wrapper(int wrapper, int indent_level) {
00064 indent(cout, indent_level)
00065 << "Wrapper (" << wrapper << ")";
00066
00067 if (interrogate_wrapper_has_return_value(wrapper)) {
00068 cout << " returns ";
00069 show_type(interrogate_wrapper_return_type(wrapper));
00070 } else {
00071 cout << " no return value";
00072 }
00073
00074 int num_params = interrogate_wrapper_number_of_parameters(wrapper);
00075 cout << ", ";
00076 if (num_params == 0) {
00077 cout << "no parameters.\n";
00078 } else if (num_params == 1) {
00079 cout << "1 parameter:\n";
00080 } else {
00081 cout << num_params << " parameters:\n";
00082 }
00083
00084 for (int i = 0; i < num_params; i++) {
00085 indent(cout, indent_level + 4);
00086 if (interrogate_wrapper_parameter_is_this(wrapper, i)) {
00087 cout << "*";
00088 } else {
00089 cout << i;
00090 }
00091 cout << ": ";
00092 show_type(interrogate_wrapper_parameter_type(wrapper, i));
00093 if (interrogate_wrapper_parameter_has_name(wrapper, i)) {
00094 cout << " '" << interrogate_wrapper_parameter_name(wrapper, i) << "'";
00095 } else {
00096 cout << " (no name)";
00097 }
00098 cout << "\n";
00099 }
00100
00101
00102 if (interrogate_wrapper_caller_manages_return_value(wrapper)) {
00103 indent(cout, indent_level + 2)
00104 << "Caller manages return value using ";
00105 show_function(interrogate_wrapper_return_value_destructor(wrapper));
00106 cout << "\n";
00107 }
00108
00109 indent(cout, indent_level + 2)
00110 << "Wrapper name: " << interrogate_wrapper_name(wrapper);
00111 if (interrogate_wrapper_is_callable_by_name(wrapper)) {
00112 cout << " (callable)";
00113 }
00114 cout << "\n";
00115 if (interrogate_wrapper_has_pointer(wrapper)) {
00116 indent(cout, indent_level + 2)
00117 << "Has pointer: " << interrogate_wrapper_pointer(wrapper) << "\n";
00118 }
00119 string unique_name = interrogate_wrapper_unique_name(wrapper);
00120 indent(cout, indent_level + 2)
00121 << "Unique name is " << unique_name;
00122 int reverse_lookup = interrogate_get_wrapper_by_unique_name(unique_name.c_str());
00123 if (reverse_lookup == 0) {
00124 cout << " (no reverse lookup)";
00125 } else if (reverse_lookup != wrapper) {
00126 cout << " (*** reverse lookup returns " << reverse_lookup << "! ***)";
00127 }
00128 cout << "\n";
00129 }
00130
00131 void
00132 describe_function(int function, int indent_level) {
00133 indent(cout, indent_level)
00134 << "Function " << interrogate_function_scoped_name(function)
00135 << " (" << function << ")\n";
00136
00137 indent(cout, indent_level + 2)
00138 << "In C: " << interrogate_function_prototype(function) << "\n";
00139
00140 if (interrogate_function_is_method(function)) {
00141 indent(cout, indent_level + 2)
00142 << "Method of ";
00143 show_type(interrogate_function_class(function));
00144 cout << "\n";
00145 }
00146
00147 if (interrogate_function_is_virtual(function)) {
00148 indent(cout, indent_level + 2) << "is virtual.\n";
00149 }
00150
00151 int w;
00152
00153 int num_c_wrappers = interrogate_function_number_of_c_wrappers(function);
00154 if (num_c_wrappers == 0) {
00155 } else if (num_c_wrappers == 1) {
00156 indent(cout, indent_level + 2)
00157 << "1 C-style wrapper:\n";
00158 } else {
00159 indent(cout, indent_level + 2)
00160 << num_c_wrappers << " C-style wrappers:\n";
00161 }
00162 for (w = 0; w < num_c_wrappers; w++) {
00163 describe_wrapper(interrogate_function_c_wrapper(function, w),
00164 indent_level + 4);
00165 }
00166
00167 int num_python_wrappers =
00168 interrogate_function_number_of_python_wrappers(function);
00169 if (num_python_wrappers == 0) {
00170 } else if (num_python_wrappers == 1) {
00171 indent(cout, indent_level + 2)
00172 << "1 Python-style wrapper:\n";
00173 } else {
00174 indent(cout, indent_level + 2)
00175 << num_python_wrappers << " Python-style wrappers:\n";
00176 }
00177 for (w = 0; w < num_python_wrappers; w++) {
00178 describe_wrapper(interrogate_function_python_wrapper(function, w),
00179 indent_level + 4);
00180 }
00181
00182 }
00183
00184 void
00185 report_manifests() {
00186 int num_manifests = interrogate_number_of_manifests();
00187 cout << "\n" << num_manifests << " manifests:\n";
00188 for (int i = 0; i < num_manifests; i++) {
00189 int manifest = interrogate_get_manifest(i);
00190
00191 cout << " Manifest " << interrogate_manifest_name(manifest);
00192 if (interrogate_manifest_has_type(manifest)) {
00193 cout << " of type ";
00194 show_type(interrogate_manifest_get_type(manifest));
00195 cout << "\n";
00196 } else {
00197 cout << " of unknown type\n";
00198 }
00199 cout << " definition is \""
00200 << interrogate_manifest_definition(manifest) << "\"\n";
00201
00202 if (interrogate_manifest_has_getter(manifest)) {
00203 cout << " value getter: ";
00204 show_function(interrogate_manifest_getter(manifest));
00205 cout << "\n";
00206 }
00207
00208 if (interrogate_manifest_has_int_value(manifest)) {
00209 cout << " int value = "
00210 << interrogate_manifest_get_int_value(manifest)
00211 << "\n";
00212 }
00213 }
00214 }
00215
00216 void
00217 describe_element(int element, int indent_level) {
00218 indent(cout, indent_level)
00219 << "Element " << interrogate_element_scoped_name(element)
00220 << " of type ";
00221 show_type(interrogate_element_type(element));
00222 cout << "\n";
00223
00224 if (interrogate_element_has_getter(element)) {
00225 indent(cout, indent_level + 2)
00226 << "Getter is ";
00227 show_function(interrogate_element_getter(element));
00228 cout << "\n";
00229 }
00230
00231 if (interrogate_element_has_setter(element)) {
00232 indent(cout, indent_level + 2)
00233 << "Setter is ";
00234 show_function(interrogate_element_setter(element));
00235 cout << "\n";
00236 }
00237 }
00238
00239 void
00240 report_globals() {
00241 int num_globals = interrogate_number_of_globals();
00242 cout << "\n" << num_globals << " globals:\n";
00243 for (int i = 0; i < num_globals; i++) {
00244 describe_element(interrogate_get_global(i), 2);
00245 }
00246 }
00247
00248 void
00249 describe_type(int type, int indent_level) {
00250 indent(cout, indent_level) << "Type ";
00251 show_type(type, true);
00252 cout << "\n";
00253 if (interrogate_type_is_nested(type)) {
00254 indent(cout, indent_level + 2)
00255 << "Nested within ";
00256 show_type(interrogate_type_outer_class(type));
00257 cout << "\n";
00258 }
00259 if (interrogate_type_is_atomic(type)) {
00260 indent(cout, indent_level + 2)
00261 << "atomic " << (int)interrogate_type_atomic_token(type) << "\n";
00262 }
00263 if (interrogate_type_is_unsigned(type)) {
00264 indent(cout, indent_level + 2)
00265 << "unsigned\n";
00266 }
00267 if (interrogate_type_is_signed(type)) {
00268 indent(cout, indent_level + 2)
00269 << "signed\n";
00270 }
00271 if (interrogate_type_is_long(type)) {
00272 indent(cout, indent_level + 2)
00273 << "long\n";
00274 }
00275 if (interrogate_type_is_longlong(type)) {
00276 indent(cout, indent_level + 2)
00277 << "long long\n";
00278 }
00279 if (interrogate_type_is_short(type)) {
00280 indent(cout, indent_level + 2)
00281 << "short\n";
00282 }
00283 if (interrogate_type_is_wrapped(type)) {
00284 indent(cout, indent_level + 2)
00285 << "wrapped ";
00286 show_type(interrogate_type_wrapped_type(type));
00287 cout << "\n";
00288 }
00289 if (interrogate_type_is_pointer(type)) {
00290 indent(cout, indent_level + 2)
00291 << "pointer\n";
00292 }
00293 if (interrogate_type_is_const(type)) {
00294 indent(cout, indent_level + 2)
00295 << "const\n";
00296 }
00297 if (interrogate_type_is_fully_defined(type)) {
00298 indent(cout, indent_level + 2)
00299 << "fully defined\n";
00300 }
00301 if (interrogate_type_is_unpublished(type)) {
00302 indent(cout, indent_level + 2)
00303 << "undefined because unpublished\n";
00304 }
00305 if (interrogate_type_is_enum(type)) {
00306 indent(cout, indent_level + 2)
00307 << "is enum type\n";
00308 }
00309 if (interrogate_type_is_struct(type)) {
00310 indent(cout, indent_level + 2)
00311 << "is struct type\n";
00312 }
00313 if (interrogate_type_is_class(type)) {
00314 indent(cout, indent_level + 2)
00315 << "is class type\n";
00316 }
00317 if (interrogate_type_is_union(type)) {
00318 indent(cout, indent_level + 2)
00319 << "is union type\n";
00320 }
00321 int num_enum_values = interrogate_type_number_of_enum_values(type);
00322 if (num_enum_values > 0) {
00323 for (int i = 0; i < num_enum_values; i++) {
00324 indent(cout, indent_level + 4)
00325 << interrogate_type_enum_value_name(type, i)
00326 << " = " << interrogate_type_enum_value(type, i) << "\n";
00327 }
00328 }
00329 int num_constructors = interrogate_type_number_of_constructors(type);
00330 if (num_constructors > 0) {
00331 indent(cout, indent_level + 2)
00332 << num_constructors << " constructors:\n";
00333 for (int i = 0; i < num_constructors; i++) {
00334 describe_function(interrogate_type_get_constructor(type, i), 6);
00335 }
00336 }
00337 if (interrogate_type_has_destructor(type)) {
00338 indent(cout, indent_level + 2)
00339 << "destructor:\n";
00340 describe_function(interrogate_type_get_destructor(type), 6);
00341 }
00342 int num_casts = interrogate_type_number_of_casts(type);
00343 if (num_casts > 0) {
00344 indent(cout, indent_level + 2)
00345 << num_casts << " casts:\n";
00346 for (int i = 0; i < num_casts; i++) {
00347 describe_function(interrogate_type_get_cast(type, i), 6);
00348 }
00349 }
00350 int num_methods = interrogate_type_number_of_methods(type);
00351 if (num_methods > 0) {
00352 indent(cout, indent_level + 2)
00353 << num_methods << " methods:\n";
00354 for (int i = 0; i < num_methods; i++) {
00355 describe_function(interrogate_type_get_method(type, i), 6);
00356 }
00357 }
00358 int num_elements = interrogate_type_number_of_elements(type);
00359 if (num_elements > 0) {
00360 indent(cout, indent_level + 2)
00361 << num_elements << " elements:\n";
00362 for (int i = 0; i < num_elements; i++) {
00363 describe_element(interrogate_type_get_element(type, i), indent_level + 2);
00364 }
00365 }
00366 int num_derivations = interrogate_type_number_of_derivations(type);
00367 if (num_derivations > 0) {
00368 indent(cout, indent_level + 2)
00369 << num_derivations << " derivations:\n";
00370 for (int i = 0; i < num_derivations; i++) {
00371 int derivation = interrogate_type_get_derivation(type, i);
00372 indent(cout, indent_level + 4);
00373 show_type(derivation);
00374 if (interrogate_type_derivation_has_upcast(type, i)) {
00375 cout << " (has upcast)";
00376 }
00377 if (interrogate_type_derivation_downcast_is_impossible(type, i)) {
00378 cout << " (downcast is impossible)";
00379 }
00380 if (interrogate_type_derivation_has_downcast(type, i)) {
00381 cout << " (has downcast)";
00382 }
00383 cout << "\n";
00384
00385
00386
00387
00388
00389
00390
00391
00392 }
00393 }
00394 int num_nested_types = interrogate_type_number_of_nested_types(type);
00395 if (num_nested_types > 0) {
00396 indent(cout, indent_level + 2)
00397 << num_nested_types << " nested types:\n";
00398 for (int i = 0; i < num_nested_types; i++) {
00399 indent(cout, indent_level + 4);
00400 show_type(interrogate_type_get_nested_type(type, i));
00401 cout << "\n";
00402 }
00403 }
00404 }
00405
00406 void
00407 report_global_types() {
00408 int num_types = interrogate_number_of_global_types();
00409 cout << "\n" << num_types << " global types:\n";
00410
00411 for (int i = 0; i < num_types; i++) {
00412 int type = interrogate_get_global_type(i);
00413 describe_type(type, 2);
00414 }
00415 }
00416
00417 void
00418 report_global_functions() {
00419 int num_functions = interrogate_number_of_global_functions();
00420 cout << "\n" << num_functions << " global functions:\n";
00421 for (int i = 0; i < num_functions; i++) {
00422 int function = interrogate_get_global_function(i);
00423 describe_function(function, 2);
00424 }
00425 }
00426
00427 void
00428 report_all_types() {
00429 int num_types = interrogate_number_of_types();
00430 cout << "\n" << num_types << " total types:\n";
00431
00432 for (int i = 0; i < num_types; i++) {
00433 int type = interrogate_get_type(i);
00434 describe_type(type, 2);
00435 }
00436 }
00437
00438 void
00439 report_all_functions() {
00440 int num_functions = interrogate_number_of_functions();
00441 cout << "\n" << num_functions << " total functions:\n";
00442 for (int i = 0; i < num_functions; i++) {
00443 int function = interrogate_get_function(i);
00444 describe_function(function, 2);
00445 }
00446 }
00447
00448 void
00449 usage() {
00450 cerr <<
00451 "\n"
00452 "test_interrogate [opts] libfile.so [libfile.so ...]\n\n"
00453
00454 "Loads the given shared library or libraries, if possible, and reports the\n"
00455 "symbols, types, and functions available within those libraries as reported\n"
00456 "by interrogate.\n\n"
00457
00458 "In lieu of loading a shared library, you may also read the interrogate\n"
00459 "database file directly by specifying a filename like libfile.in. This will\n"
00460 "report the symbols defined in that file only (without pulling in dependent\n"
00461 "files), and will not have any function pointers available.\n\n"
00462
00463 "Options:\n\n"
00464 " -f Give a detailed report of each function in the database, including\n"
00465 " synthesized functions like upcasts and downcasts.\n"
00466 " -t Give a detailed report of every type in the database, including types\n"
00467 " like pointers and const pointers.\n"
00468 " -q Quickly load up each shared library, if possible, and then immediately\n"
00469 " exit. Useful for quickly determining whether a library can even load.\n\n";
00470 }
00471
00472 int
00473 main(int argc, char *argv[]) {
00474
00475 extern int optind;
00476 const char *optstr = "ftqh";
00477
00478 bool all_functions = false;
00479 bool all_types = false;
00480 bool quick_load = false;
00481 int flag = getopt(argc, argv, optstr);
00482
00483 while (flag != EOF) {
00484 switch (flag) {
00485 case 'f':
00486 all_functions = true;
00487 break;
00488
00489 case 't':
00490 all_types = true;
00491 break;
00492
00493 case 'q':
00494 quick_load = true;
00495 break;
00496
00497 case 'h':
00498 usage();
00499 exit(0);
00500
00501 default:
00502 exit(1);
00503 }
00504 flag = getopt(argc, argv, optstr);
00505 }
00506
00507 argc -= (optind-1);
00508 argv += (optind-1);
00509
00510 if (argc < 2) {
00511 cerr << "No libraries specified.\n";
00512 exit(1);
00513 }
00514
00515 int return_status = 0;
00516
00517 for (int i = 1; i < argc; i++) {
00518 string param = argv[i];
00519
00520 if (param.length() > 3 && param.substr(param.length() - 3) == ".in") {
00521
00522
00523 interrogate_request_database(param.c_str());
00524
00525 } else {
00526
00527 Filename pathname = Filename::dso_filename(argv[i]);
00528 cerr << "Loading " << pathname << "\n";
00529 void *dl = load_dso(pathname);
00530 if (dl == NULL) {
00531 cerr << "Unable to load: " << load_dso_error() << "\n";
00532 return_status++;
00533 }
00534 }
00535 }
00536
00537 if (!quick_load) {
00538 if (all_types) {
00539 report_all_types();
00540 }
00541 if (all_functions) {
00542 report_all_functions();
00543 }
00544
00545 if (!all_types && !all_functions) {
00546 report_manifests();
00547 report_globals();
00548 report_global_types();
00549 report_global_functions();
00550 }
00551 }
00552
00553 return (return_status);
00554 }