00001
00017 #include "opjitconv.h"
00018 #include "opd_printf.h"
00019 #include "op_file.h"
00020 #include "op_libiberty.h"
00021
00022 #include <dirent.h>
00023 #include <fnmatch.h>
00024 #include <errno.h>
00025 #include <fcntl.h>
00026 #include <limits.h>
00027 #include <pwd.h>
00028 #include <stdint.h>
00029 #include <stdio.h>
00030 #include <stdlib.h>
00031 #include <string.h>
00032 #include <sys/mman.h>
00033 #include <sys/types.h>
00034 #include <unistd.h>
00035 #include <wait.h>
00036
00037
00038
00039
00040
00041
00042
00043 struct jitentry * jitentry_list = NULL;
00044 struct jitentry_debug_line * jitentry_debug_line_list = NULL;
00045
00046
00047 asymbol ** syms;
00048
00049
00050 enum bfd_architecture dump_bfd_arch;
00051 int dump_bfd_mach;
00052 char const * dump_bfd_target_name;
00053
00054
00055 struct passwd * pw_oprofile;
00056
00057 char sys_cmd_buffer[PATH_MAX + 1];
00058
00059
00060 bfd * cur_bfd;
00061
00062
00063 u32 entry_count;
00064
00065 u32 max_entry_count;
00066
00067 struct jitentry ** entries_symbols_ascending;
00068
00069 struct jitentry ** entries_address_ascending;
00070
00071
00072 int debug;
00073
00074 int non_root;
00075
00076 int delete_jitdumps;
00077 LIST_HEAD(jitdump_deletion_candidates);
00078
00079
00080
00081
00082
00083
00084
00085
00086
00087
00088
00089
00090
00091
00092
00093 static void get_pathname(char const * pathname, void * name_list)
00094 {
00095 struct list_head * names = (struct list_head *) name_list;
00096 struct pathname * pn = xmalloc(sizeof(struct pathname));
00097 pn->name = xstrdup(pathname);
00098 list_add(&pn->neighbor, names);
00099 }
00100
00101 static void delete_pathname(struct pathname * pname)
00102 {
00103 free(pname->name);
00104 list_del(&pname->neighbor);
00105 free(pname);
00106 }
00107
00108
00109 static void delete_path_names_list(struct list_head * list)
00110 {
00111 struct list_head * pos1, * pos2;
00112 list_for_each_safe(pos1, pos2, list) {
00113 struct pathname * pname = list_entry(pos1, struct pathname,
00114 neighbor);
00115 delete_pathname(pname);
00116 }
00117 }
00118
00119 static int mmap_jitdump(char const * dumpfile,
00120 struct op_jitdump_info * file_info)
00121 {
00122 int rc = OP_JIT_CONV_OK;
00123 int dumpfd;
00124
00125 dumpfd = open(dumpfile, O_RDONLY);
00126 if (dumpfd < 0) {
00127 if (errno == ENOENT)
00128 rc = OP_JIT_CONV_NO_DUMPFILE;
00129 else
00130 rc = OP_JIT_CONV_FAIL;
00131 goto out;
00132 }
00133 rc = fstat(dumpfd, &file_info->dmp_file_stat);
00134 if (rc < 0) {
00135 perror("opjitconv:fstat on dumpfile");
00136 rc = OP_JIT_CONV_FAIL;
00137 goto out;
00138 }
00139 file_info->dmp_file = mmap(0, file_info->dmp_file_stat.st_size,
00140 PROT_READ, MAP_PRIVATE, dumpfd, 0);
00141 if (file_info->dmp_file == MAP_FAILED) {
00142 perror("opjitconv:mmap\n");
00143 rc = OP_JIT_CONV_FAIL;
00144 }
00145 out:
00146 return rc;
00147 }
00148
00149 static char const * find_anon_dir_match(struct list_head * anon_dirs,
00150 char const * proc_id)
00151 {
00152 struct list_head * pos;
00153 char match_filter[10];
00154 snprintf(match_filter, 10, "*/%s.*", proc_id);
00155 list_for_each(pos, anon_dirs) {
00156 struct pathname * anon_dir =
00157 list_entry(pos, struct pathname, neighbor);
00158 if (!fnmatch(match_filter, anon_dir->name, 0))
00159 return anon_dir->name;
00160 }
00161 return NULL;
00162 }
00163
00164 int change_owner(char * path)
00165 {
00166 int rc = OP_JIT_CONV_OK;
00167 int fd;
00168
00169 if (non_root)
00170 return rc;
00171 fd = open(path, 0);
00172 if (fd < 0) {
00173 printf("opjitconv: File cannot be opened for changing ownership.\n");
00174 rc = OP_JIT_CONV_FAIL;
00175 goto out;
00176 }
00177 if (fchown(fd, pw_oprofile->pw_uid, pw_oprofile->pw_gid) != 0) {
00178 printf("opjitconv: Changing ownership failed (%s).\n", strerror(errno));
00179 close(fd);
00180 rc = OP_JIT_CONV_FAIL;
00181 goto out;
00182 }
00183 close(fd);
00184
00185 out:
00186 return rc;
00187 }
00188
00189
00190
00191
00192 int copy_dumpfile(char const * dumpfile, char * tmp_dumpfile)
00193 {
00194 int rc = OP_JIT_CONV_OK;
00195
00196 sprintf(sys_cmd_buffer, "/bin/cp -p %s %s", dumpfile, tmp_dumpfile);
00197
00198 if (system(sys_cmd_buffer) != 0) {
00199 printf("opjitconv: Calling system() to copy files failed.\n");
00200 rc = OP_JIT_CONV_FAIL;
00201 goto out;
00202 }
00203
00204 if (change_owner(tmp_dumpfile) != 0) {
00205 printf("opjitconv: Changing ownership of temporary dump file failed.\n");
00206 rc = OP_JIT_CONV_FAIL;
00207 goto out;
00208 }
00209
00210 out:
00211 return rc;
00212 }
00213
00214
00215
00216
00217
00218 int copy_elffile(char * elf_file, char * tmp_elffile)
00219 {
00220 int rc = OP_JIT_CONV_OK;
00221 int fd;
00222
00223 sprintf(sys_cmd_buffer, "/bin/cp -p %s %s", tmp_elffile, elf_file);
00224 if (system(sys_cmd_buffer) != 0) {
00225 printf("opjitconv: Calling system() to copy files failed.\n");
00226 rc = OP_JIT_CONV_FAIL;
00227 goto out;
00228 }
00229
00230 fd = open(elf_file, 0);
00231 if (fd < 0) {
00232 printf("opjitconv: File cannot be opened for changing ownership.\n");
00233 rc = OP_JIT_CONV_FAIL;
00234 goto out;
00235 }
00236 if (fchown(fd, getuid(), getgid()) != 0) {
00237 printf("opjitconv: Changing ownership failed (%s).\n", strerror(errno));
00238 close(fd);
00239 rc = OP_JIT_CONV_FAIL;
00240 goto out;
00241 }
00242 close(fd);
00243
00244 out:
00245 return rc;
00246 }
00247
00248
00249
00250
00251
00252
00253
00254 static int process_jit_dumpfile(char const * dmp_pathname,
00255 struct list_head * anon_sample_dirs,
00256 unsigned long long start_time,
00257 unsigned long long end_time,
00258 char * tmp_conv_dir)
00259 {
00260 int result_dir_length, proc_id_length;
00261 int rc = OP_JIT_CONV_OK;
00262 int jofd;
00263 struct stat file_stat;
00264 time_t dumpfile_modtime;
00265 struct op_jitdump_info dmp_info;
00266 char * elf_file = NULL;
00267 char * proc_id = NULL;
00268 char const * anon_dir;
00269 char const * dumpfilename = rindex(dmp_pathname, '/');
00270
00271 char * tmp_dumpfile;
00272
00273 char * tmp_elffile;
00274
00275 verbprintf(debug, "Processing dumpfile %s\n", dmp_pathname);
00276
00277
00278
00279
00280
00281 if (lstat(dmp_pathname, &file_stat) == -1) {
00282 printf("opjitconv: lstat for dumpfile failed (%s).\n", strerror(errno));
00283 rc = OP_JIT_CONV_FAIL;
00284 goto out;
00285 }
00286 if (S_ISLNK(file_stat.st_mode)) {
00287 printf("opjitconv: dumpfile path is corrupt (symbolic links not allowed).\n");
00288 rc = OP_JIT_CONV_FAIL;
00289 goto out;
00290 }
00291
00292 if (dumpfilename) {
00293 size_t tmp_conv_dir_length = strlen(tmp_conv_dir);
00294 char const * dot_dump = rindex(++dumpfilename, '.');
00295 if (!dot_dump)
00296 goto chk_proc_id;
00297 proc_id_length = dot_dump - dumpfilename;
00298 proc_id = xmalloc(proc_id_length + 1);
00299 memcpy(proc_id, dumpfilename, proc_id_length);
00300 proc_id[proc_id_length] = '\0';
00301 verbprintf(debug, "Found JIT dumpfile for process %s\n",
00302 proc_id);
00303
00304 tmp_dumpfile = xmalloc(tmp_conv_dir_length + 1 + strlen(dumpfilename) + 1);
00305 strncpy(tmp_dumpfile, tmp_conv_dir, tmp_conv_dir_length);
00306 tmp_dumpfile[tmp_conv_dir_length] = '\0';
00307 strcat(tmp_dumpfile, "/");
00308 strcat(tmp_dumpfile, dumpfilename);
00309 }
00310 chk_proc_id:
00311 if (!proc_id) {
00312 printf("opjitconv: dumpfile path is corrupt.\n");
00313 rc = OP_JIT_CONV_FAIL;
00314 goto out;
00315 }
00316 if (!(anon_dir = find_anon_dir_match(anon_sample_dirs, proc_id))) {
00317
00318
00319
00320
00321
00322
00323
00324
00325
00326 verbprintf(debug, "Informational message: No matching anon samples for %s\n",
00327 dmp_pathname);
00328 rc = OP_JIT_CONV_NO_MATCHING_ANON_SAMPLES;
00329 goto free_res1;
00330 }
00331
00332 if (copy_dumpfile(dmp_pathname, tmp_dumpfile) != OP_JIT_CONV_OK)
00333 goto free_res1;
00334
00335 if ((rc = mmap_jitdump(tmp_dumpfile, &dmp_info)) == OP_JIT_CONV_OK) {
00336 char * anon_path_seg = rindex(anon_dir, '/');
00337 if (!anon_path_seg) {
00338 printf("opjitconv: Bad path for anon sample: %s\n",
00339 anon_dir);
00340 rc = OP_JIT_CONV_FAIL;
00341 goto free_res2;
00342 }
00343 result_dir_length = ++anon_path_seg - anon_dir;
00344
00345 elf_file = xmalloc(result_dir_length +
00346 strlen(proc_id) + strlen(".jo") + 1);
00347 strncpy(elf_file, anon_dir, result_dir_length);
00348 elf_file[result_dir_length] = '\0';
00349 strcat(elf_file, proc_id);
00350 strcat(elf_file, ".jo");
00351
00352 tmp_elffile = xmalloc(strlen(tmp_conv_dir) + 1 +
00353 strlen(proc_id) + strlen(".jo") + 1);
00354 strncpy(tmp_elffile, tmp_conv_dir, strlen(tmp_conv_dir));
00355 tmp_elffile[strlen(tmp_conv_dir)] = '\0';
00356 strcat(tmp_elffile, "/");
00357 strcat(tmp_elffile, proc_id);
00358 strcat(tmp_elffile, ".jo");
00359
00360
00361 jofd = open(elf_file, O_RDONLY);
00362 if (jofd < 0)
00363 goto create_elf;
00364 rc = fstat(jofd, &file_stat);
00365 if (rc < 0) {
00366 perror("opjitconv:fstat on .jo file");
00367 rc = OP_JIT_CONV_FAIL;
00368 goto free_res3;
00369 }
00370 if (dmp_info.dmp_file_stat.st_mtime >
00371 dmp_info.dmp_file_stat.st_ctime)
00372 dumpfile_modtime = dmp_info.dmp_file_stat.st_mtime;
00373 else
00374 dumpfile_modtime = dmp_info.dmp_file_stat.st_ctime;
00375
00376
00377
00378
00379
00380 if (!(file_stat.st_ctime < dumpfile_modtime ||
00381 file_stat.st_mtime < dumpfile_modtime)) {
00382 rc = OP_JIT_CONV_ALREADY_DONE;
00383 goto free_res3;
00384 }
00385
00386 create_elf:
00387 verbprintf(debug, "Converting %s to %s\n", dmp_pathname,
00388 elf_file);
00389
00390 if (!non_root && setegid(pw_oprofile->pw_gid) != 0) {
00391 perror("opjitconv: setegid to special user failed");
00392 rc = OP_JIT_CONV_FAIL;
00393 goto free_res3;
00394 }
00395
00396 if (!non_root && seteuid(pw_oprofile->pw_uid) != 0) {
00397 perror("opjitconv: seteuid to special user failed");
00398 rc = OP_JIT_CONV_FAIL;
00399 goto free_res3;
00400 }
00401
00402 rc = op_jit_convert(dmp_info, tmp_elffile, start_time, end_time);
00403
00404 if (!non_root && seteuid(getuid()) != 0) {
00405 perror("opjitconv: seteuid to original user failed");
00406 rc = OP_JIT_CONV_FAIL;
00407 goto free_res3;
00408 }
00409
00410 if (!non_root && setegid(getgid()) != 0) {
00411 perror("opjitconv: setegid to original user failed");
00412 rc = OP_JIT_CONV_FAIL;
00413 goto free_res3;
00414 }
00415 rc = copy_elffile(elf_file, tmp_elffile);
00416 free_res3:
00417 free(elf_file);
00418 free(tmp_elffile);
00419 free_res2:
00420 munmap(dmp_info.dmp_file, dmp_info.dmp_file_stat.st_size);
00421 }
00422 free_res1:
00423 free(proc_id);
00424 free(tmp_dumpfile);
00425 out:
00426 return rc;
00427 }
00428
00429
00430 static char * get_procid_from_dirname(char * dirname)
00431 {
00432 char * ret = NULL;
00433 if (dirname) {
00434 char * proc_id;
00435 int proc_id_length;
00436 char * fname = rindex(dirname, '/');
00437 char const * dot = index(++fname, '.');
00438 if (!dot)
00439 goto out;
00440 proc_id_length = dot - fname;
00441 proc_id = xmalloc(proc_id_length + 1);
00442 memcpy(proc_id, fname, proc_id_length);
00443 proc_id[proc_id_length] = '\0';
00444 ret = proc_id;
00445 }
00446 out:
00447 return ret;
00448 }
00449 static void filter_anon_samples_list(struct list_head * anon_dirs)
00450 {
00451 struct procid {
00452 struct procid * next;
00453 char * pid;
00454 };
00455 struct procid * pid_list = NULL;
00456 struct procid * id, * nxt;
00457 struct list_head * pos1, * pos2;
00458 list_for_each_safe(pos1, pos2, anon_dirs) {
00459 struct pathname * pname = list_entry(pos1, struct pathname,
00460 neighbor);
00461 char * proc_id = get_procid_from_dirname(pname->name);
00462 if (proc_id) {
00463 int found = 0;
00464 for (id = pid_list; id != NULL; id = id->next) {
00465 if (!strcmp(id->pid, proc_id)) {
00466
00467
00468
00469
00470 free(pname->name);
00471 list_del(&pname->neighbor);
00472 free(pname);
00473 found = 1;
00474 }
00475 }
00476 if (!found) {
00477 struct procid * this_proc =
00478 xmalloc(sizeof(struct procid));
00479 this_proc->pid = proc_id;
00480 this_proc->next = pid_list;
00481 pid_list = this_proc;
00482 }
00483 } else {
00484 printf("Unexpected result in processing anon sample"
00485 " directory\n");
00486 }
00487 }
00488 for (id = pid_list; id; id = nxt) {
00489 free(id->pid);
00490 nxt = id->next;
00491 free(id);
00492 }
00493 }
00494
00495
00496 static void _add_jitdumps_to_deletion_list(void * all_jitdumps, char const * jitdump_dir )
00497 {
00498 struct list_head * jd_fnames = (struct list_head *) all_jitdumps;
00499 struct list_head * pos1, *pos2;
00500 size_t dir_len = strlen(jitdump_dir);
00501
00502 list_for_each_safe(pos1, pos2, jd_fnames) {
00503 struct pathname * dmpfile =
00504 list_entry(pos1, struct pathname, neighbor);
00505 struct stat mystat;
00506 char dmpfile_pathname[dir_len + 20];
00507 int fd;
00508 memset(dmpfile_pathname, '\0', dir_len + 20);
00509 strcpy(dmpfile_pathname, jitdump_dir);
00510 strcat(dmpfile_pathname,dmpfile->name);
00511 fd = open(dmpfile_pathname, O_RDONLY);
00512 if (fd < 0) {
00513
00514 verbprintf(debug, "opjitconv: cannot open jitdump file %s\n",
00515 dmpfile_pathname);
00516 continue;
00517 }
00518 if (fstat(fd, &mystat) < 0) {
00519
00520 verbprintf(debug, "opjitconv: cannot fstat jitdump file");
00521 continue;
00522 }
00523 if (geteuid() == mystat.st_uid) {
00524 struct jitdump_deletion_candidate * jdc =
00525 xmalloc(sizeof(struct jitdump_deletion_candidate));
00526 jdc->name = xstrdup(dmpfile->name);
00527 list_add(&jdc->neighbor, &jitdump_deletion_candidates);
00528 }
00529 }
00530 }
00531
00532 static int op_process_jit_dumpfiles(char const * session_dir,
00533 unsigned long long start_time, unsigned long long end_time)
00534 {
00535 struct list_head * pos1, * pos2;
00536 int rc = OP_JIT_CONV_OK;
00537 char jitdumpfile[PATH_MAX + 1];
00538 char oprofile_tmp_template[PATH_MAX + 1];
00539 char const * jitdump_dir = "/var/lib/oprofile/jitdump/";
00540
00541 LIST_HEAD(jd_fnames);
00542 char const * anon_dir_filter = "*/{dep}/{anon:anon}/[0-9]*.*";
00543 LIST_HEAD(anon_dnames);
00544 char const * samples_subdir = "/samples/current";
00545 int samples_dir_len = strlen(session_dir) + strlen(samples_subdir);
00546 char * samples_dir;
00547
00548 char * tmp_conv_dir = NULL;
00549
00550 if (non_root)
00551 sprintf(oprofile_tmp_template, "%s/tmp", session_dir);
00552 else
00553 strcpy(oprofile_tmp_template, "/tmp/oprofile.XXXXXX");
00554
00555
00556
00557 if (non_root) {
00558 sprintf(sys_cmd_buffer, "/bin/rm -rf %s", oprofile_tmp_template);
00559 if (system(sys_cmd_buffer) != 0) {
00560 printf("opjitconv: Removing temporary working directory %s failed.\n",
00561 oprofile_tmp_template);
00562 rc = OP_JIT_CONV_TMPDIR_NOT_REMOVED;
00563 } else {
00564 if (!mkdir(oprofile_tmp_template, S_IRWXU | S_IRWXG ))
00565 tmp_conv_dir = oprofile_tmp_template;
00566 }
00567 } else {
00568 tmp_conv_dir = mkdtemp(oprofile_tmp_template);
00569 }
00570
00571 if (tmp_conv_dir == NULL) {
00572 printf("opjitconv: Temporary working directory %s cannot be created.\n",
00573 oprofile_tmp_template);
00574 perror("Exiting due to error");
00575 rc = OP_JIT_CONV_FAIL;
00576 goto out;
00577 }
00578
00579
00580 errno = 0;
00581 if ((rc = get_matching_pathnames(&jd_fnames, get_pathname,
00582 jitdump_dir, "*.dump", NO_RECURSION)) < 0
00583 || list_empty(&jd_fnames)) {
00584 if (errno) {
00585 if (errno != ENOENT) {
00586 char msg[PATH_MAX];
00587 strcpy(msg, "opjitconv: fatal error trying to find JIT dump files in ");
00588 strcat(msg, jitdump_dir);
00589 perror(msg);
00590 rc = OP_JIT_CONV_FAIL;
00591 } else {
00592 verbprintf(debug, "opjitconv: Non-fatal error trying to find JIT dump files in %s: %s\n",
00593 jitdump_dir, strerror(errno));
00594 rc = OP_JIT_CONV_NO_DUMPFILE;
00595 }
00596 }
00597 goto rm_tmp;
00598 }
00599
00600 if (delete_jitdumps)
00601 _add_jitdumps_to_deletion_list(&jd_fnames, jitdump_dir);
00602
00603
00604
00605 if (non_root) {
00606 pw_oprofile = NULL;
00607 } else {
00608 pw_oprofile = getpwnam("oprofile");
00609 if (pw_oprofile == NULL) {
00610 printf("opjitconv: User information for special user oprofile cannot be found.\n");
00611 rc = OP_JIT_CONV_FAIL;
00612 goto rm_tmp;
00613 }
00614 }
00615
00616
00617
00618
00619 if (change_owner(tmp_conv_dir) != 0) {
00620 printf("opjitconv: Changing ownership of temporary directory failed.\n");
00621 rc = OP_JIT_CONV_FAIL;
00622 goto rm_tmp;
00623 }
00624
00625 samples_dir = xmalloc(samples_dir_len + 1);
00626 sprintf(samples_dir, "%s%s", session_dir, samples_subdir);
00627 if (get_matching_pathnames(&anon_dnames, get_pathname,
00628 samples_dir, anon_dir_filter,
00629 MATCH_DIR_ONLY_RECURSION) < 0
00630 || list_empty(&anon_dnames)) {
00631 rc = OP_JIT_CONV_NO_ANON_SAMPLES;
00632 goto rm_tmp;
00633 }
00634
00635
00636
00637
00638
00639
00640
00641
00642
00643
00644
00645 filter_anon_samples_list(&anon_dnames);
00646
00647
00648
00649
00650
00651 list_for_each_safe(pos1, pos2, &jd_fnames) {
00652 struct pathname * dmpfile =
00653 list_entry(pos1, struct pathname, neighbor);
00654 strncpy(jitdumpfile, jitdump_dir, PATH_MAX);
00655 strncat(jitdumpfile, dmpfile->name, PATH_MAX);
00656 rc = process_jit_dumpfile(jitdumpfile, &anon_dnames,
00657 start_time, end_time, tmp_conv_dir);
00658 if (rc == OP_JIT_CONV_FAIL) {
00659 verbprintf(debug, "JIT convert error %d\n", rc);
00660 goto rm_tmp;
00661 }
00662 delete_pathname(dmpfile);
00663 }
00664 delete_path_names_list(&anon_dnames);
00665
00666 rm_tmp:
00667
00668
00669
00670 sprintf(sys_cmd_buffer, "/bin/rm -rf %s", tmp_conv_dir);
00671 if (system(sys_cmd_buffer) != 0) {
00672 printf("opjitconv: Removing temporary working directory failed.\n");
00673 rc = OP_JIT_CONV_TMPDIR_NOT_REMOVED;
00674 }
00675
00676 out:
00677 return rc;
00678 }
00679
00680 static void _cleanup_jitdumps(void)
00681 {
00682 struct list_head * pos1, *pos2;
00683 char const * jitdump_dir = "/var/lib/oprofile/jitdump/";
00684 size_t dir_len = strlen(jitdump_dir);
00685 char dmpfile_pathname[dir_len + 20];
00686 char proc_fd_dir[PATH_MAX];
00687
00688 if (!delete_jitdumps)
00689 return;
00690
00691
00692
00693
00694
00695
00696
00697
00698
00699 list_for_each_safe(pos1, pos2, &jitdump_deletion_candidates) {
00700 DIR * dir;
00701 struct dirent * dirent;
00702 int pid;
00703 size_t dmpfile_name_len;
00704 int do_not_delete = 0;
00705 struct jitdump_deletion_candidate * cand = list_entry(pos1,
00706 struct jitdump_deletion_candidate,
00707 neighbor);
00708 memset(dmpfile_pathname, '\0', dir_len + 20);
00709 memset(proc_fd_dir, '\0', PATH_MAX);
00710
00711 if ((sscanf(cand->name, "%d", &pid)) != 1) {
00712 verbprintf(debug, "Cannot get process id from jitdump file %s\n",
00713 cand->name);
00714 continue;
00715 }
00716
00717 strcpy(dmpfile_pathname, jitdump_dir);
00718 strcat(dmpfile_pathname, cand->name);
00719 dmpfile_name_len = strlen(dmpfile_pathname);
00720
00721 sprintf(proc_fd_dir, "/proc/%d/fd/", pid);
00722 if ((dir = opendir(proc_fd_dir))) {
00723 size_t proc_fd_dir_len = strlen(proc_fd_dir);
00724 while ((dirent = readdir(dir))) {
00725 if (dirent->d_type == DT_LNK) {
00726 char buf[1024];
00727 char fname[1024];
00728 memset(fname, '\0', 1024);
00729 strcpy(fname, proc_fd_dir);
00730 strncat(fname, dirent->d_name, 1023 - proc_fd_dir_len);
00731 if (readlink(fname, buf, 1023) > 0) {
00732 verbprintf(debug, "readlink found for %s\n", buf);
00733 if (strncmp(buf, dmpfile_pathname,
00734 dmpfile_name_len) == 0) {
00735 do_not_delete = 1;
00736 break;
00737 }
00738 }
00739 }
00740 }
00741 }
00742 if (!do_not_delete)
00743 remove(dmpfile_pathname);
00744 }
00745 list_for_each_safe(pos1, pos2, &jitdump_deletion_candidates) {
00746 struct jitdump_deletion_candidate * pname = list_entry(pos1,
00747 struct jitdump_deletion_candidate,
00748 neighbor);
00749 free(pname->name);
00750 list_del(&pname->neighbor);
00751 free(pname);
00752 }
00753
00754 }
00755
00756 int main(int argc, char ** argv)
00757 {
00758 unsigned long long start_time, end_time;
00759 char const * session_dir;
00760 int rc = 0;
00761
00762 debug = 0;
00763 if (argc > 1 && strcmp(argv[1], "-d") == 0) {
00764 debug = 1;
00765 argc--;
00766 argv++;
00767 }
00768 non_root = 0;
00769 if (argc > 1 && strcmp(argv[1], "--non-root") == 0) {
00770 non_root = 1;
00771 argc--;
00772 argv++;
00773 }
00774
00775 delete_jitdumps = 0;
00776 if (argc > 1 && strcmp(argv[1], "--delete-jitdumps") == 0) {
00777 delete_jitdumps = 1;
00778 argc--;
00779 argv++;
00780 }
00781
00782 if (argc != 4) {
00783 printf("Usage: opjitconv [-d] <session_dir> <starttime>"
00784 " <endtime>\n");
00785 fflush(stdout);
00786 rc = EXIT_FAILURE;
00787 goto out;
00788 }
00789
00790 session_dir = argv[1];
00791
00792
00793
00794
00795
00796
00797 if (strlen(session_dir) > PATH_MAX - 16) {
00798 printf("opjitconv: Path name length limit exceeded for session directory: %s\n", session_dir);
00799 rc = EXIT_FAILURE;
00800 goto out;
00801 }
00802
00803 start_time = atol(argv[2]);
00804 end_time = atol(argv[3]);
00805
00806 if (start_time > end_time) {
00807 rc = EXIT_FAILURE;
00808 goto out;
00809 }
00810 verbprintf(debug, "start time/end time is %llu/%llu\n",
00811 start_time, end_time);
00812 rc = op_process_jit_dumpfiles(session_dir, start_time, end_time);
00813 if (delete_jitdumps)
00814 _cleanup_jitdumps();
00815
00816 if (rc > OP_JIT_CONV_OK) {
00817 verbprintf(debug, "opjitconv: Ending with rc = %d. This code"
00818 " is usually OK, but can be useful for debugging"
00819 " purposes.\n", rc);
00820 rc = OP_JIT_CONV_OK;
00821 }
00822 fflush(stdout);
00823 if (rc == OP_JIT_CONV_OK)
00824 rc = EXIT_SUCCESS;
00825 else
00826 rc = EXIT_FAILURE;
00827 out:
00828 _exit(rc);
00829 }