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