1 #include <stdio.h> 2 #include <malloc.h> 3 #include <string.h> 4 #include <ctype.h> 5 6 #ifdef _WIN32 7 #define popen _popen 8 #define snprintf _snprintf 9 #endif 10 11 typedef struct _stub { 12 char *name; 13 char *origin; 14 struct _stub *next; 15 } stub; 16 17 void usage( char *name ) { 18 fprintf( stderr, 19 "Usage: %s [-n nm] [-m make] libs...\n" 20 "nm -- The command used to run nm on reactos objects\n" 21 "make -- The command used to build reactos\n\n" 22 "libs are import libraries (.a files) typically from\n" 23 "dk/lib/nkm and dk/lib/w32\n", 24 name ); 25 } 26 27 int main( int argc, char **argv ) { 28 char line[1024]; 29 char *make = "make"; 30 char *nm = "nm"; 31 char *origin = "unknown.a"; 32 stub *functions = NULL, *new_f, *imports = NULL, *search; 33 FILE *make_f, *nm_f; 34 int i, libstart = argc; 35 FILE *out = fopen("tests/stubs.tst","w"); 36 37 if( argc == 1 ) { 38 if( out ) fclose( out ); 39 usage(argv[0]); 40 return 1; 41 } 42 43 if( !out ) { 44 fprintf( stderr, "Could not write file tests/stubs.tst\n" ); 45 return 1; 46 } 47 48 fprintf( out, "# Automatically generated by stubgen\n" ); 49 50 for( i = 1; i < argc; i++ ) { 51 if( !strcmp( argv[i], "-m" ) ) { 52 make = argv[i+1]; 53 i++; 54 } else if( !strcmp( argv[i], "-n" ) ) { 55 nm = argv[i+1]; 56 i++; 57 } else { libstart = i; break; } 58 } 59 60 snprintf( line, sizeof(line), "%s test 2>&1", make ); 61 make_f = popen( line, "r" ); 62 63 if( !make_f ) { 64 fclose( out ); 65 fprintf( stderr, "Could not run %s test\n", make ); 66 return 1; 67 } 68 69 while( fgets( line, sizeof(line), make_f ) ) { 70 char *end_of_location; 71 char *begin_q, *end_q; 72 73 if( !strstr( line, "undefined reference to" ) ) continue; 74 75 end_of_location = strrchr( line, ':' ); 76 77 if( !end_of_location ) continue; 78 79 begin_q = strchr( end_of_location, '`' ); 80 end_q = strchr( end_of_location, '\'' ); 81 82 if( !begin_q || !end_q ) continue; 83 84 begin_q += 2; /* skip `_ */ 85 86 memmove( line, begin_q, end_q - begin_q ); 87 line[end_q - begin_q] = 0; 88 89 for( new_f = functions; new_f; new_f = new_f->next ) 90 if( !strcmp( new_f->name, line ) ) break; 91 92 if( new_f ) continue; 93 94 new_f = (stub *)malloc( sizeof(stub) ); 95 if( !new_f ) 96 { 97 fprintf( stderr, "Out of memory\n" ); 98 fclose( out ); 99 pclose( make_f ); 100 return 1; 101 } 102 103 new_f->name = strdup( line ); 104 new_f->next = functions; 105 functions = new_f; 106 } 107 108 /* Scan libraries and collect available import sections */ 109 for( i = libstart; i < argc; i++ ) { 110 snprintf( line, sizeof(line), "%s %s", nm, argv[i] ); 111 nm_f = popen( line, "r" ); 112 113 for( origin = argv[i]; *argv[i]; argv[i]++ ) 114 if( *argv[i] == '/' || *argv[i] == '\\' ) 115 origin = argv[i] + 1; 116 117 118 if( !nm_f ) { 119 fprintf( stderr, "Could not run %s\n", line ); 120 continue; 121 } 122 123 while( fgets( line, sizeof(line), nm_f ) ) { 124 char *import_sign, *eol; 125 126 if( !(import_sign = strstr( line, " I " )) ) continue; 127 128 import_sign += 3; 129 while( *import_sign && isspace(*import_sign) ) import_sign++; 130 131 /* Strip ws after name */ 132 for( eol = import_sign; *eol && !isspace(*eol); eol++ ); 133 134 *eol = 0; 135 136 for( new_f = imports; new_f; new_f = new_f->next ) 137 if( !strcmp( new_f->name, import_sign ) ) break; 138 139 if( new_f ) continue; 140 141 new_f = (stub *)malloc( sizeof(stub) ); 142 if( !new_f ) 143 { 144 fprintf( stderr, "Out of memory\n" ); 145 fclose( out ); 146 pclose( make_f ); 147 pclose( nm_f ); 148 return 1; 149 } 150 151 new_f->name = strdup( import_sign + 1 ); 152 new_f->origin = origin; 153 new_f->next = imports; 154 imports = new_f; 155 } 156 157 pclose( nm_f ); 158 } 159 160 /* Now we have a list of unique functions and a list of imports, 161 lookup each function and output the entry from the import list. */ 162 for( new_f = functions; new_f; new_f = new_f->next ) { 163 for( search = imports; search; search = search->next ) { 164 if( !strcmp( new_f->name, search->name ) ) { 165 fprintf( out, "%s %s\n", search->origin, search->name ); 166 continue; 167 } 168 } 169 } 170 171 fclose( out ); 172 pclose( make_f ); 173 return 0; 174 } 175