00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040 #include <errno.h>
00041 #include <stdio.h>
00042 #include <fcntl.h>
00043 #include <libgen.h>
00044 #include <sys/stat.h>
00045 #include "ir_prof.h"
00046 static char *thisfile = __FILE__;
00047
00048
00049 static int fd_counts;
00050
00051 #define FALSE 0
00052 #define TRUE 1
00053 #define NUM_COUNTS_ENTRY 4097
00054 #define SAMPLE_SIZE 15
00055
00056 static counts_entry *counts_array;
00057 static long num_counts;
00058 static long sizeof_counts_array = NUM_COUNTS_ENTRY;
00059
00060 typedef struct {
00061 unsigned *phash;
00062 unsigned *chain;
00063 char *strtab;
00064 unsigned nchain;
00065 unsigned size;
00066 unsigned nsym;
00067 unsigned strsize;
00068 unsigned nchars;
00069 } HASH_STRUCT;
00070
00071 #define DEF_STRSIZE 3
00072 #define DEF_NBUCKETS (NUM_COUNTS_ENTRY-1)
00073 #define DEF_NSYM (NUM_COUNTS_ENTRY-1)
00074 #define UNDEF -1
00075 static HASH_STRUCT h_tab;
00076
00077 extern void hashinit(void);
00078
00079
00080
00081 extern void *atexit();
00082
00083 extern int
00084 file_exists (char *path)
00085 {
00086 int st;
00087 struct stat sbuf;
00088 st = stat(path, &sbuf);
00089 if (st == -1 && (errno == ENOENT || errno == ENOTDIR))
00090 return FALSE;
00091 else
00092 return TRUE;
00093 }
00094
00095
00096 static void
00097 usage (char *progname)
00098 {
00099 fprintf (stderr, "Usage: %s [-v] <Binary IR>\n", progname);
00100 fprintf (stderr, "\t-v option will print out verbose info\n");
00101 fprintf (stderr, "\tall sizes are in bytes\n");
00102 exit (1);
00103 }
00104
00105
00106 #define PR_ASSERT(EX, p) if (!(EX)) ir_prof_error(ER_FATAL, p, "Ir_pr")
00107 #define MALLOC(nbytes) malloc((size_t)(nbytes))
00108 #define REALLOC(ptr, size) realloc((void *)(ptr), (size_t)(size))
00109
00110 void
00111 ir_prof_dump(void)
00112 {
00113 int i;
00114
00115 printf("Edge Counts Dump: (%d), total = %d\n", num_counts, SAMPLE_SIZE);
00116 for (i=0; i < num_counts; i++) {
00117 printf("\t0x%x : 0x%x\t%d\t%s(%d):\t%s(%d)\n",
00118 counts_array[i].caller, counts_array[i].callee, counts_array[i].count,
00119 (h_tab.strtab + counts_array[i].caller_name_idx),counts_array[i].caller_name_idx,
00120 (h_tab.strtab + counts_array[i].callee_name_idx),counts_array[i].callee_name_idx);
00121 }
00122 }
00123
00124
00125 void
00126 ir_prof_error(int type, char *fmt, char *fname)
00127 {
00128 fprintf (stderr, "%s: ", "Ir_prof");
00129 fprintf(stderr, fmt, fname);
00130 fputc('\n', stderr);
00131 fflush(stderr);
00132 switch (type) {
00133 ER_FATAL:
00134 exit(1);
00135 ER_WARNING:
00136 ER_INFO:
00137 ER_ERROR:
00138 ER_VERBOSE:
00139 ER_MSG:
00140 return;
00141 }
00142 }
00143
00144
00145 void
00146 ir_prof_start(void)
00147 {
00148 char *errmsg;
00149
00150 counts_array = (counts_entry *)(MALLOC(NUM_COUNTS_ENTRY * sizeof(counts_entry)));
00151 PR_ASSERT(counts_array, "ir_prof_start: malloc of counts_entry returns null");
00152 num_counts = 0;
00153 hashinit();
00154 return;
00155 }
00156
00157
00158 void
00159 ir_prof_dump_counts(int fd_counts)
00160 {
00161 Counts_hdr hdr;
00162
00163 PR_ASSERT(fd_counts, "ir_prof_dump_counts: fd_counts is null");
00164
00165 hdr.c_ident[0] = COUNTSMAG0;
00166 hdr.c_ident[1] = COUNTSMAG1;
00167 hdr.c_ident[2] = COUNTSMAG2;
00168 hdr.c_ident[3] = COUNTSMAG3;
00169 hdr.c_ident[4] = COUNTSMAG4;
00170 hdr.c_ident[5] = COUNTSMAG5;
00171 hdr.c_ident[6] = COUNTSMAG6;
00172 hdr.c_ident[7] = COUNTSMAG7;
00173 hdr.c_entry = num_counts;
00174 hdr.c_version = C_VERSION;
00175 hdr.c_dummy1 = 0;
00176 #ifdef _64BIT
00177 hdr.c_dummy2 = 0;
00178 hdr.c_dummy3 = 0;
00179 #endif
00180 write(fd_counts, (char *)&hdr, sizeof(hdr));
00181 write(fd_counts, (char *)counts_array, sizeof(counts_entry)*num_counts);
00182 write(fd_counts, h_tab.strtab, h_tab.nchars);
00183 }
00184
00185
00186 void
00187 cgt_fini(void)
00188 {
00189 char *errmsg;
00190 char *name = "junk.prof";
00191 int file_exists = 0;
00192 struct stat statbuf;
00193 int res, fd_counts;
00194
00195 if (num_counts == 0)
00196 return;
00197
00198 res = stat(name,&statbuf);
00199 if (res < 0) {
00200 if(errno == ENOENT) {
00201
00202 if ((fd_counts = open(name, O_RDWR|O_CREAT, 0555)) < 0) {
00203 errmsg = strerror(errno);
00204 ir_prof_error(ER_FATAL, "Unable to open addr_counts file: %s", name);
00205 }
00206 } else {
00207 errmsg = strerror(errno);
00208 ir_prof_error(ER_FATAL, "Unable to open addr_counts file: %s", name);
00209 }
00210 }
00211 else {
00212 file_exists = 1;
00213 if ((fd_counts = open(name, O_RDWR|O_TRUNC, 0555)) == 0) {
00214 errmsg = strerror(errno);
00215 ir_prof_error(ER_FATAL, "Existing addr_counts file open error: %s", name);
00216 }
00217 }
00218
00219
00220 (void)ir_prof_dump();
00221 ir_prof_dump_counts(fd_counts);
00222
00223 close (fd_counts);
00224 }
00225
00226
00227 void
00228 ir_prof_init(void)
00229 {
00230 void (*pf)() = cgt_fini;
00231 num_counts = 0;
00232 atexit(pf);
00233 }
00234
00235
00236 void hashinit()
00237 {
00238 unsigned *p;
00239
00240 h_tab.nchain = 0;
00241 h_tab.strsize = DEF_STRSIZE;
00242
00243 if ((p = (unsigned *)malloc(h_tab.strsize)) == (unsigned *)0)
00244 ir_prof_error(ER_FATAL, "Malloc error in %s\n", "malloc strtab");
00245 h_tab.strtab = (char *)p;
00246 p[0] = '\0';
00247 h_tab.nchars = 1;
00248
00249 if ((p = (unsigned *)malloc(DEF_NBUCKETS * sizeof(unsigned))) == (unsigned *)0)
00250 ir_prof_error(ER_FATAL, "Malloc error in %s\n", "malloc hash");
00251 memset((char *)p, -1, DEF_NBUCKETS * sizeof(unsigned));
00252 h_tab.phash = p;
00253 h_tab.size = DEF_NBUCKETS;
00254
00255 if ((p = (unsigned *)malloc(DEF_NSYM *sizeof(unsigned))) == (unsigned *)0)
00256 ir_prof_error(ER_FATAL, "Malloc error in %s\n", "hashtab");
00257 bzero (p, DEF_NSYM * sizeof(unsigned));
00258 h_tab.chain = p;
00259 h_tab.nsym = DEF_NSYM;
00260 return ;
00261 }
00262
00263
00264 void
00265 expand_htab()
00266 {
00267 unsigned *pnew;
00268 int nsym = h_tab.nsym * 2;
00269
00270 if ((pnew = (unsigned *)realloc(h_tab.chain, nsym*sizeof(unsigned))) == 0)
00271 ir_prof_error(ER_FATAL, "Realloc error when %s", "expanding hash");
00272 h_tab.chain = pnew;
00273 bzero (&pnew[h_tab.nsym], h_tab.nsym * sizeof(unsigned));
00274 h_tab.nsym = nsym;
00275 }
00276
00277
00278 void
00279 expand_strtab(int i)
00280 {
00281 char *pnew;
00282
00283 h_tab.strsize = 2 * (h_tab.strsize + i);
00284 if ((pnew = (char *)realloc(h_tab.strtab, h_tab.strsize)) == 0)
00285 ir_prof_error(ER_FATAL, "Realloc error when %s", "expanding strtab");
00286 h_tab.strtab = pnew;
00287 }
00288
00289
00290 int
00291 enter_str(char *name)
00292 {
00293 int i, ret;
00294 char *p = h_tab.strtab;
00295
00296 if (name == 0 || name[0] == '\0')
00297 return 0;
00298
00299 i = strlen(name) + 1;
00300 if ((i + h_tab.nchars) > h_tab.strsize)
00301 expand_strtab(i);
00302
00303 memcpy(h_tab.strtab + h_tab.nchars, name, i);
00304 ret = h_tab.nchars;
00305 h_tab.nchars += i;
00306 return ret;
00307 }
00308
00309
00310 static void
00311 hash_entry(ADDR caller, ADDR callee, char *caller_name, char *callee_name)
00312 {
00313 unsigned *pchain = h_tab.chain;
00314 int y;
00315 int i = h_tab.nchain;
00316
00317
00318
00319
00320 int hash = ((caller + callee) & 0x0FFFFFFFF) % h_tab.size;
00321
00322
00323 if ((y = h_tab.phash[hash]) == UNDEF) {
00324 if (h_tab.nchain == h_tab.nsym) {
00325 expand_htab();
00326 pchain = h_tab.chain;
00327 }
00328 pchain[i] = UNDEF;
00329
00330 counts_array[i].count = 1;
00331 counts_array[i].caller = caller;
00332 counts_array[i].callee = callee;
00333 counts_array[i].caller_name_idx = enter_str(caller_name);
00334 counts_array[i].callee_name_idx = enter_str(callee_name);
00335
00336 h_tab.phash[hash] = h_tab.nchain++;
00337 num_counts++;
00338
00339 return;
00340 }
00341
00342 while (y != UNDEF) {
00343 if (counts_array[y].caller == caller &&
00344 counts_array[y].callee == callee) {
00345 counts_array[y].count++;
00346
00347 return;
00348 }
00349 hash = y;
00350 y = pchain[y];
00351 }
00352
00353
00354 pchain[hash] = h_tab.nchain;
00355 if (i == h_tab.nsym) {
00356 expand_htab();
00357 pchain = h_tab.chain;
00358 }
00359
00360 pchain[i] = UNDEF;
00361
00362 counts_array[i].caller = caller;
00363 counts_array[i].callee = callee;
00364 counts_array[i].caller_name_idx = enter_str(caller_name);
00365 counts_array[i].callee_name_idx = enter_str(callee_name);
00366 counts_array[i].count = 1;
00367
00368 h_tab.nchain++;
00369 num_counts++;
00370 return;
00371 }
00372
00373
00374 void
00375 __profile_call(ADDR caller, ADDR callee, char *caller_name, char *callee_name)
00376 {
00377 #ifdef _DEBUG
00378 return;
00379 #else
00380 if (num_counts == 0)
00381 ir_prof_start();
00382
00383 if (num_counts == sizeof_counts_array) {
00384 sizeof_counts_array *= 2;
00385 counts_array = (counts_entry *)REALLOC(
00386 counts_array, sizeof_counts_array);
00387 PR_ASSERT(counts_array, "realloc of counts_array failed");
00388 }
00389
00390 hash_entry(caller, callee, caller_name, callee_name);
00391 #endif
00392 }
00393
00394
00395
00396 #ifdef _MAIN_DEBUG
00397
00398
00399 struct counts_desc_char {
00400 char caller[9];
00401 char callee[9];
00402 int caller_idx;
00403 int callee_idx;
00404 };
00405
00406 static char *str[6] = {
00407 "", "scan", "foo", "a", "longgggggggggggg", "new"};
00408 static struct counts_desc_char debugi[SAMPLE_SIZE] = {
00409 {"1000129c","1000129c",1, 1},
00410 {"1000133c","1000129c",2, 1},
00411 {"100012bc","1000129c",3, 1},
00412 {"1000127c","1000127c",4, 4},
00413 {"100012bc","100012ac",3, 0},
00414 {"1000127c","1000129c",4, 1},
00415 {"1000133c","1000129c",2, 1},
00416 {"1000129c","1000127c",1, 4},
00417 {"100012bc","1000129c",3, 1},
00418 {"10002340","1000129c",5, 1},
00419 {"1000127c","1000127c",4, 4},
00420 {"1000127c","1000127c",4, 4},
00421 {"100012bc","1000133c",3, 2},
00422 {"1000133c","10002340",2, 5},
00423 {"1000133c","1000127c",2, 4},
00424 };
00425 static counts_entry debug[SAMPLE_SIZE];
00426
00427
00428 long h2d(char *p)
00429 {
00430 int i;
00431 long val = 0;
00432 long ret = 0;
00433
00434 for (i=0; i < 8; i++) {
00435 if (p[i] < '0' || p[i] > '9') {
00436 val = p[i] - 'a' + 10;
00437 }
00438 else
00439 val = p[i] - '0';
00440
00441 ret = ret * 16 + val;
00442 }
00443 return ret;
00444 }
00445
00446
00447 int
00448 debug_init(void)
00449 {
00450 int i;
00451 for (i=0; i < SAMPLE_SIZE; i++) {
00452 debug[i].caller = h2d(debugi[i].caller);
00453 debug[i].callee = h2d(debugi[i].callee);
00454 debug[i].caller_name_idx = debugi[i].caller_idx;
00455 debug[i].callee_name_idx = debugi[i].callee_idx;
00456 }
00457 return SAMPLE_SIZE;
00458 }
00459
00460
00461 void
00462 main (int argc, char *argv[])
00463 {
00464 register char *progname = "ir_prof";
00465 int binarg = 1;
00466 int verbose = FALSE;
00467 int j, i;
00468
00469 progname = (argv[0]);
00470
00471 if (argc == 2) {
00472 if (strcmp(argv[1], "-h") == 0)
00473 usage(progname);
00474 exit(0);
00475 }
00476 j = debug_init();
00477 for (i = 0; i < j; i++) {
00478 __profile_call(debug[i].caller, debug[i].callee, str[debug[i].caller_name_idx],
00479 str[debug[i].callee_name_idx]);
00480 }
00481 ir_prof_dump();
00482 cgt_fini();
00483
00484 exit (0);
00485 }
00486 #endif
00487