18cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd/**
28cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd * @file opjitconv.c
38cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd * Convert a jit dump file to an ELF file
48cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd *
58cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd * @remark Copyright 2007 OProfile authors
68cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd * @remark Read the file COPYING
78cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd *
88cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd * @author Jens Wilke
98cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd * @Modifications Maynard Johnson
108cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd * @Modifications Daniel Hansel
118cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd * @Modifications Gisle Dankel
128cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd *
138cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd * Copyright IBM Corporation 2007
148cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd *
158cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd */
168cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd
178cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd#include "opjitconv.h"
188cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd#include "opd_printf.h"
198cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd#include "op_file.h"
208cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd#include "op_libiberty.h"
218cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd
228cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd#include <dirent.h>
238cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd#include <fnmatch.h>
248cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd#include <errno.h>
258cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd#include <fcntl.h>
268cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd#include <limits.h>
278cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd#include <pwd.h>
288cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd#include <stdint.h>
298cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd#include <stdio.h>
308cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd#include <stdlib.h>
318cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd#include <string.h>
328cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd#include <sys/mman.h>
338cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd#include <sys/types.h>
348cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd#include <unistd.h>
358cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd#include <wait.h>
368cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd
378cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd/*
388cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd * list head.  The linked list is used during parsing (parse_all) to
398cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd * hold all jitentry elements. After parsing, the program works on the
408cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd * array structures (entries_symbols_ascending, entries_address_ascending)
418cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd * and the linked list is not used any more.
428cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd */
438cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Doddstruct jitentry * jitentry_list = NULL;
448cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Doddstruct jitentry_debug_line * jitentry_debug_line_list = NULL;
458cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd
468cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd/* Global variable for asymbols so we can free the storage later. */
478cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Doddasymbol ** syms;
488cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd
498cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd/* jit dump header information */
508cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Doddenum bfd_architecture dump_bfd_arch;
518cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Doddint dump_bfd_mach;
528cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Doddchar const * dump_bfd_target_name;
538cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd
548cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd/* user information for special user 'oprofile' */
558cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Doddstruct passwd * pw_oprofile;
568cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd
578cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Doddchar sys_cmd_buffer[PATH_MAX + 1];
588cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd
598cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd/* the bfd handle of the ELF file we write */
608cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Doddbfd * cur_bfd;
618cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd
628cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd/* count of jitentries in the list */
638cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Doddu32 entry_count;
648cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd/* maximul space in the entry arrays, needed to add entries */
658cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Doddu32 max_entry_count;
668cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd/* array pointing to all jit entries, sorted by symbol names */
678cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Doddstruct jitentry ** entries_symbols_ascending;
688cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd/* array pointing to all jit entries sorted by address */
698cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Doddstruct jitentry ** entries_address_ascending;
708cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd
718cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd/* debug flag, print some information */
728cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Doddint debug;
738cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd
748cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd/*
758cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd *  Front-end processing from this point to end of the source.
768cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd *    From main(), the general flow is as follows:
778cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd *      1. Find all anonymous samples directories
788cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd *      2. Find all JIT dump files
798cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd *      3. For each JIT dump file:
808cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd *        3.1 Find matching anon samples dir (from list retrieved in step 1)
818cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd *        3.2 mmap the JIT dump file
828cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd *        3.3 Call op_jit_convert to create ELF file if necessary
838cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd */
848cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd
858cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd/* Callback function used for get_matching_pathnames() call to obtain
868cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd * matching path names.
878cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd */
888cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Doddstatic void get_pathname(char const * pathname, void * name_list)
898cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd{
908cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	struct list_head * names = (struct list_head *) name_list;
918cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	struct pathname * pn = xmalloc(sizeof(struct pathname));
928cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	pn->name = xstrdup(pathname);
938cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	list_add(&pn->neighbor, names);
948cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd}
958cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd
968cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Doddstatic void delete_pathname(struct pathname * pname)
978cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd{
988cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	free(pname->name);
998cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	list_del(&pname->neighbor);
1008cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	free(pname);
1018cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd}
1028cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd
1038cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd
1048cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Doddstatic void delete_path_names_list(struct list_head * list)
1058cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd{
1068cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	struct list_head * pos1, * pos2;
1078cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	list_for_each_safe(pos1, pos2, list) {
1088cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		struct pathname * pname = list_entry(pos1, struct pathname,
1098cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd						     neighbor);
1108cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		delete_pathname(pname);
1118cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	}
1128cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd}
1138cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd
1148cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Doddstatic int mmap_jitdump(char const * dumpfile,
1158cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	struct op_jitdump_info * file_info)
1168cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd{
1178cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	int rc = OP_JIT_CONV_OK;
1188cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	int dumpfd;
1198cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd
1208cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	dumpfd = open(dumpfile, O_RDONLY);
1218cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	if (dumpfd < 0) {
1228cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		if (errno == ENOENT)
1238cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd			rc = OP_JIT_CONV_NO_DUMPFILE;
1248cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		else
1258cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd			rc = OP_JIT_CONV_FAIL;
1268cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		goto out;
1278cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	}
1288cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	rc = fstat(dumpfd, &file_info->dmp_file_stat);
1298cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	if (rc < 0) {
1308cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		perror("opjitconv:fstat on dumpfile");
1318cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		rc = OP_JIT_CONV_FAIL;
1328cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		goto out;
1338cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	}
1348cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	file_info->dmp_file = mmap(0, file_info->dmp_file_stat.st_size,
1358cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd				   PROT_READ, MAP_PRIVATE, dumpfd, 0);
1368cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	if (file_info->dmp_file == MAP_FAILED) {
1378cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		perror("opjitconv:mmap\n");
1388cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		rc = OP_JIT_CONV_FAIL;
1398cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	}
1408cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Doddout:
1418cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	return rc;
1428cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd}
1438cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd
1448cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Doddstatic char const * find_anon_dir_match(struct list_head * anon_dirs,
1458cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd					char const * proc_id)
1468cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd{
1478cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	struct list_head * pos;
1488cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	char match_filter[10];
1498cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	snprintf(match_filter, 10, "*/%s.*", proc_id);
1508cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	list_for_each(pos, anon_dirs) {
1518cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		struct pathname * anon_dir =
1528cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd			list_entry(pos, struct pathname, neighbor);
1538cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		if (!fnmatch(match_filter, anon_dir->name, 0))
1548cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd			return anon_dir->name;
1558cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	}
1568cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	return NULL;
1578cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd}
1588cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd
1598cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Doddint change_owner(char * path)
1608cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd{
1618cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	int rc = OP_JIT_CONV_OK;
1628cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	int fd;
1638cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd
1648cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	fd = open(path, 0);
1658cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	if (fd < 0) {
1668cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		printf("opjitconv: File cannot be opened for changing ownership.\n");
1678cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		rc = OP_JIT_CONV_FAIL;
1688cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		goto out;
1698cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	}
1708cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	if (fchown(fd, pw_oprofile->pw_uid, pw_oprofile->pw_gid) != 0) {
1718cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		printf("opjitconv: Changing ownership failed (%s).\n", strerror(errno));
1728cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		close(fd);
1738cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		rc = OP_JIT_CONV_FAIL;
1748cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		goto out;
1758cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	}
1768cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	close(fd);
1778cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd
1788cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Doddout:
1798cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	return rc;
1808cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd}
1818cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd
1828cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd/* Copies the given file to the temporary working directory and sets ownership
1838cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd * to 'oprofile:oprofile'.
1848cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd */
1858cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Doddint copy_dumpfile(char const * dumpfile, char * tmp_dumpfile)
1868cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd{
1878cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	int rc = OP_JIT_CONV_OK;
1888cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd
1898cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	sprintf(sys_cmd_buffer, "/bin/cp -p %s %s", dumpfile, tmp_dumpfile);
1908cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd
1918cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	if (system(sys_cmd_buffer) != 0) {
1928cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		printf("opjitconv: Calling system() to copy files failed.\n");
1938cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		rc = OP_JIT_CONV_FAIL;
1948cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		goto out;
1958cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	}
1968cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd
1978cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	if (change_owner(tmp_dumpfile) != 0) {
1988cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		printf("opjitconv: Changing ownership of temporary dump file failed.\n");
1998cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		rc = OP_JIT_CONV_FAIL;
2008cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		goto out;
2018cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	}
2028cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd
2038cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Doddout:
2048cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	return rc;
2058cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd}
2068cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd
2078cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd/* Copies the created ELF file located in the temporary working directory to the
2088cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd * final destination (i.e. given ELF file name) and sets ownership to the
2098cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd * current user.
2108cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd */
2118cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Doddint copy_elffile(char * elf_file, char * tmp_elffile)
2128cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd{
2138cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	int rc = OP_JIT_CONV_OK;
2148cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	int fd;
2158cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd
2168cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	sprintf(sys_cmd_buffer, "/bin/cp -p %s %s", tmp_elffile, elf_file);
2178cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	if (system(sys_cmd_buffer) != 0) {
2188cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		printf("opjitconv: Calling system() to copy files failed.\n");
2198cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		rc = OP_JIT_CONV_FAIL;
2208cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		goto out;
2218cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	}
2228cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd
2238cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	fd = open(elf_file, 0);
2248cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	if (fd < 0) {
2258cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		printf("opjitconv: File cannot be opened for changing ownership.\n");
2268cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		rc = OP_JIT_CONV_FAIL;
2278cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		goto out;
2288cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	}
2298cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	if (fchown(fd, getuid(), getgid()) != 0) {
2308cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		printf("opjitconv: Changing ownership failed (%s).\n", strerror(errno));
2318cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		close(fd);
2328cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		rc = OP_JIT_CONV_FAIL;
2338cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		goto out;
2348cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	}
2358cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	close(fd);
2368cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd
2378cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Doddout:
2388cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	return rc;
2398cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd}
2408cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd
2418cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd/* Look for an anonymous samples directory that matches the process ID
2428cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd * given by the passed JIT dmp_pathname.  If none is found, it's an error
2438cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd * since by agreement, all JIT dump files should be removed every time
2448cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd * the user does --reset.  If we do find the matching samples directory,
2458cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd * we create an ELF file (<proc_id>.jo) and place it in that directory.
2468cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd */
2478cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Doddstatic int process_jit_dumpfile(char const * dmp_pathname,
2488cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd				struct list_head * anon_sample_dirs,
2498cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd				unsigned long long start_time,
2508cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd				unsigned long long end_time,
2518cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd				char * tmp_conv_dir)
2528cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd{
2538cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	int result_dir_length, proc_id_length;
2548cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	int rc = OP_JIT_CONV_OK;
2558cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	int jofd;
2568cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	struct stat file_stat;
2578cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	time_t dumpfile_modtime;
2588cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	struct op_jitdump_info dmp_info;
2598cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	char * elf_file = NULL;
2608cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	char * proc_id = NULL;
2618cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	char const * anon_dir;
2628cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	char const * dumpfilename = rindex(dmp_pathname, '/');
2638cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	/* temporary copy of dump file created for conversion step */
2648cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	char * tmp_dumpfile;
2658cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	/* temporary ELF file created during conversion step */
2668cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	char * tmp_elffile;
2678cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd
2688cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	verbprintf(debug, "Processing dumpfile %s\n", dmp_pathname);
2698cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd
2708cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	/* Check if the dump file is a symbolic link.
2718cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	 * We should not trust symbolic links because we only produce normal dump
2728cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	 * files (no links).
2738cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	 */
2748cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	if (lstat(dmp_pathname, &file_stat) == -1) {
2758cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		printf("opjitconv: lstat for dumpfile failed (%s).\n", strerror(errno));
2768cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		rc = OP_JIT_CONV_FAIL;
2778cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		goto out;
2788cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	}
2798cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	if (S_ISLNK(file_stat.st_mode)) {
2808cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		printf("opjitconv: dumpfile path is corrupt (symbolic links not allowed).\n");
2818cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		rc = OP_JIT_CONV_FAIL;
2828cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		goto out;
2838cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	}
2848cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd
2858cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	if (dumpfilename) {
2868cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		size_t tmp_conv_dir_length = strlen(tmp_conv_dir);
2878cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		char const * dot_dump = rindex(++dumpfilename, '.');
2888cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		if (!dot_dump)
2898cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd			goto chk_proc_id;
2908cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		proc_id_length = dot_dump - dumpfilename;
2918cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		proc_id = xmalloc(proc_id_length + 1);
2928cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		memcpy(proc_id, dumpfilename, proc_id_length);
2938cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		proc_id[proc_id_length] = '\0';
2948cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		verbprintf(debug, "Found JIT dumpfile for process %s\n",
2958cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd			   proc_id);
2968cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd
2978cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		tmp_dumpfile = xmalloc(tmp_conv_dir_length + 1 + strlen(dumpfilename) + 1);
2988cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		strncpy(tmp_dumpfile, tmp_conv_dir, tmp_conv_dir_length);
2998cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		tmp_dumpfile[tmp_conv_dir_length] = '\0';
3008cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		strcat(tmp_dumpfile, "/");
3018cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		strcat(tmp_dumpfile, dumpfilename);
3028cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	}
3038cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Doddchk_proc_id:
3048cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	if (!proc_id) {
3058cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		printf("opjitconv: dumpfile path is corrupt.\n");
3068cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		rc = OP_JIT_CONV_FAIL;
3078cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		goto out;
3088cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	}
3098cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	if (!(anon_dir = find_anon_dir_match(anon_sample_dirs, proc_id))) {
3108cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		printf("Possible error: No matching anon samples for %s\n",
3118cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		       dmp_pathname);
3128cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		rc = OP_JIT_CONV_NO_MATCHING_ANON_SAMPLES;
3138cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		goto free_res1;
3148cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	}
3158cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd
3168cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	if (copy_dumpfile(dmp_pathname, tmp_dumpfile) != OP_JIT_CONV_OK)
3178cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		goto free_res1;
3188cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd
3198cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	if ((rc = mmap_jitdump(tmp_dumpfile, &dmp_info)) == OP_JIT_CONV_OK) {
3208cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		char * anon_path_seg = rindex(anon_dir, '/');
3218cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		if (!anon_path_seg) {
3228cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd			printf("opjitconv: Bad path for anon sample: %s\n",
3238cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd			       anon_dir);
3248cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd			rc = OP_JIT_CONV_FAIL;
3258cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd			goto free_res2;
3268cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		}
3278cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		result_dir_length = ++anon_path_seg - anon_dir;
3288cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		/* create final ELF file name */
3298cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		elf_file = xmalloc(result_dir_length +
3308cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd				   strlen(proc_id) + strlen(".jo") + 1);
3318cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		strncpy(elf_file, anon_dir, result_dir_length);
3328cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		elf_file[result_dir_length] = '\0';
3338cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		strcat(elf_file, proc_id);
3348cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		strcat(elf_file, ".jo");
3358cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		/* create temporary ELF file name */
3368cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		tmp_elffile = xmalloc(strlen(tmp_conv_dir) + 1 +
3378cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd				   strlen(proc_id) + strlen(".jo") + 1);
3388cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		strncpy(tmp_elffile, tmp_conv_dir, strlen(tmp_conv_dir));
3398cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		tmp_elffile[strlen(tmp_conv_dir)] = '\0';
3408cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		strcat(tmp_elffile, "/");
3418cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		strcat(tmp_elffile, proc_id);
3428cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		strcat(tmp_elffile, ".jo");
3438cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd
3448cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		// Check if final ELF file exists already
3458cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		jofd = open(elf_file, O_RDONLY);
3468cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		if (jofd < 0)
3478cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd			goto create_elf;
3488cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		rc = fstat(jofd, &file_stat);
3498cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		if (rc < 0) {
3508cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd			perror("opjitconv:fstat on .jo file");
3518cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd			rc = OP_JIT_CONV_FAIL;
3528cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd			goto free_res3;
3538cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		}
3548cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		if (dmp_info.dmp_file_stat.st_mtime >
3558cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		    dmp_info.dmp_file_stat.st_ctime)
3568cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd			dumpfile_modtime = dmp_info.dmp_file_stat.st_mtime;
3578cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		else
3588cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd			dumpfile_modtime = dmp_info.dmp_file_stat.st_ctime;
3598cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd
3608cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		/* Final ELF file already exists, so if dumpfile has not been
3618cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		 * modified since the ELF file's mod time, we don't need to
3628cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		 * do ELF creation again.
3638cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		 */
3648cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		if (!(file_stat.st_ctime < dumpfile_modtime ||
3658cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		    file_stat.st_mtime < dumpfile_modtime)) {
3668cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd			rc = OP_JIT_CONV_ALREADY_DONE;
3678cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd			goto free_res3;
3688cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		}
3698cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd
3708cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	create_elf:
3718cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		verbprintf(debug, "Converting %s to %s\n", dmp_pathname,
3728cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd			   elf_file);
3738cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		/* Set eGID of the special user 'oprofile'. */
3748cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		if (setegid(pw_oprofile->pw_gid) != 0) {
3758cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd			perror("opjitconv: setegid to special user failed");
3768cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd			rc = OP_JIT_CONV_FAIL;
3778cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd			goto free_res3;
3788cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		}
3798cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		/* Set eUID of the special user 'oprofile'. */
3808cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		if (seteuid(pw_oprofile->pw_uid) != 0) {
3818cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd			perror("opjitconv: seteuid to special user failed");
3828cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd			rc = OP_JIT_CONV_FAIL;
3838cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd			goto free_res3;
3848cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		}
3858cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		/* Convert the dump file as the special user 'oprofile'. */
3868cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		rc = op_jit_convert(dmp_info, tmp_elffile, start_time, end_time);
3878cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		/* Set eUID back to the original user. */
3888cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		if (seteuid(getuid()) != 0) {
3898cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd			perror("opjitconv: seteuid to original user failed");
3908cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd			rc = OP_JIT_CONV_FAIL;
3918cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd			goto free_res3;
3928cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		}
3938cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		/* Set eGID back to the original user. */
3948cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		if (setegid(getgid()) != 0) {
3958cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd			perror("opjitconv: setegid to original user failed");
3968cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd			rc = OP_JIT_CONV_FAIL;
3978cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd			goto free_res3;
3988cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		}
3998cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		rc = copy_elffile(elf_file, tmp_elffile);
4008cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	free_res3:
4018cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		free(elf_file);
4028cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		free(tmp_elffile);
4038cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	free_res2:
4048cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		munmap(dmp_info.dmp_file, dmp_info.dmp_file_stat.st_size);
4058cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	}
4068cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Doddfree_res1:
4078cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	free(proc_id);
4088cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	free(tmp_dumpfile);
4098cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Doddout:
4108cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	return rc;
4118cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd}
4128cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd
4138cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd/* If non-NULL value is returned, caller is responsible for freeing memory.*/
4148cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Doddstatic char * get_procid_from_dirname(char * dirname)
4158cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd{
4168cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	char * ret = NULL;
4178cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	if (dirname) {
4188cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		char * proc_id;
4198cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		int proc_id_length;
4208cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		char * fname = rindex(dirname, '/');
4218cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		char const * dot = index(++fname, '.');
4228cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		if (!dot)
4238cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd			goto out;
4248cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		proc_id_length = dot - fname;
4258cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		proc_id = xmalloc(proc_id_length + 1);
4268cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		memcpy(proc_id, fname, proc_id_length);
4278cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		proc_id[proc_id_length] = '\0';
4288cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		ret = proc_id;
4298cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	}
4308cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Doddout:
4318cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	return ret;
4328cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd}
4338cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Doddstatic void filter_anon_samples_list(struct list_head * anon_dirs)
4348cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd{
4358cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	struct procid {
4368cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		struct procid * next;
4378cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		char * pid;
4388cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	};
4398cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	struct procid * pid_list = NULL;
4408cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	struct procid * id, * nxt;
4418cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	struct list_head * pos1, * pos2;
4428cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	list_for_each_safe(pos1, pos2, anon_dirs) {
4438cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		struct pathname * pname = list_entry(pos1, struct pathname,
4448cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd						     neighbor);
4458cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		char * proc_id = get_procid_from_dirname(pname->name);
4468cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		if (proc_id) {
4478cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd			int found = 0;
4488cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd			for (id = pid_list; id != NULL; id = id->next) {
4498cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd				if (!strcmp(id->pid, proc_id)) {
4508cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd					/* Already have an entry for this
4518cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd					 * process ID, so delete this entry
4528cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd					 * from anon_dirs.
4538cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd					 */
4548cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd					free(pname->name);
4558cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd					list_del(&pname->neighbor);
4568cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd					free(pname);
4578cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd					found = 1;
4588cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd				}
4598cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd			}
4608cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd			if (!found) {
4618cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd				struct procid * this_proc =
4628cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd					xmalloc(sizeof(struct procid));
4638cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd				this_proc->pid = proc_id;
4648cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd				this_proc->next = pid_list;
4658cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd				pid_list = this_proc;
4668cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd			}
4678cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		} else {
4688cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd			printf("Unexpected result in processing anon sample"
4698cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd			       " directory\n");
4708cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		}
4718cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	}
4728cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	for (id = pid_list; id; id = nxt) {
4738cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		free(id->pid);
4748cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		nxt = id->next;
4758cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		free(id);
4768cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	}
4778cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd}
4788cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd
4798cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd
4808cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Doddstatic int op_process_jit_dumpfiles(char const * session_dir,
4818cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	unsigned long long start_time, unsigned long long end_time)
4828cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd{
4838cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	struct list_head * pos1, * pos2;
4848cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	int rc = OP_JIT_CONV_OK;
4858cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	char jitdumpfile[PATH_MAX + 1];
4868cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	char oprofile_tmp_template[] = "/tmp/oprofile.XXXXXX";
4878cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	char const * jitdump_dir = "/var/lib/oprofile/jitdump/";
4888cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	LIST_HEAD(jd_fnames);
4898cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	char const * anon_dir_filter = "*/{dep}/{anon:anon}/[0-9]*.*";
4908cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	LIST_HEAD(anon_dnames);
4918cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	char const * samples_subdir = "/samples/current";
4928cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	int samples_dir_len = strlen(session_dir) + strlen(samples_subdir);
4938cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	char * samples_dir;
4948cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	/* temporary working directory for dump file conversion step */
4958cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	char * tmp_conv_dir;
4968cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd
4978cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	/* Create a temporary working directory used for the conversion step.
4988cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	 */
4998cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	tmp_conv_dir = mkdtemp(oprofile_tmp_template);
5008cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	if (tmp_conv_dir == NULL) {
5018cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		printf("opjitconv: Temporary working directory cannot be created.\n");
5028cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		rc = OP_JIT_CONV_FAIL;
5038cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		goto out;
5048cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	}
5058cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd
5068cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	if ((rc = get_matching_pathnames(&jd_fnames, get_pathname,
5078cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		jitdump_dir, "*.dump", NO_RECURSION)) < 0
5088cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd			|| list_empty(&jd_fnames))
5098cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		goto rm_tmp;
5108cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd
5118cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	/* Get user information (i.e. UID and GID) for special user 'oprofile'.
5128cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	 */
5138cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	pw_oprofile = getpwnam("oprofile");
5148cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	if (pw_oprofile == NULL) {
5158cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		printf("opjitconv: User information for special user oprofile cannot be found.\n");
5168cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		rc = OP_JIT_CONV_FAIL;
5178cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		goto rm_tmp;
5188cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	}
5198cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd
5208cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	/* Change ownership of the temporary working directory to prevent other users
5218cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	 * to attack conversion process.
5228cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	 */
5238cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	if (change_owner(tmp_conv_dir) != 0) {
5248cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		printf("opjitconv: Changing ownership of temporary directory failed.\n");
5258cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		rc = OP_JIT_CONV_FAIL;
5268cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		goto rm_tmp;
5278cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	}
5288cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd
5298cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	samples_dir = xmalloc(samples_dir_len + 1);
5308cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	sprintf(samples_dir, "%s%s", session_dir, samples_subdir);
5318cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	if (get_matching_pathnames(&anon_dnames, get_pathname,
5328cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd				    samples_dir, anon_dir_filter,
5338cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd				    MATCH_DIR_ONLY_RECURSION) < 0
5348cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	    || list_empty(&anon_dnames)) {
5358cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		rc = OP_JIT_CONV_NO_ANON_SAMPLES;
5368cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		goto rm_tmp;
5378cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	}
5388cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	/* When using get_matching_pathnames to find anon samples,
5398cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	 * the list that's returned may contain multiple entries for
5408cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	 * one or more processes; e.g.,
5418cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	 *    6868.0x100000.0x103000
5428cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	 *    6868.0xdfe77000.0xdec40000
5438cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	 *    7012.0x100000.0x103000
5448cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	 *    7012.0xdfe77000.0xdec40000
5458cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	 *
5468cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	 * So we must filter the list so there's only one entry per
5478cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	 * process.
5488cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	 */
5498cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	filter_anon_samples_list(&anon_dnames);
5508cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd
5518cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	/* get_matching_pathnames returns only filename segment when
5528cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	 * NO_RECURSION is passed, so below, we add back the JIT
5538cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	 * dump directory path to the name.
5548cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	 */
5558cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	list_for_each_safe(pos1, pos2, &jd_fnames) {
5568cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		struct pathname * dmpfile =
5578cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd			list_entry(pos1, struct pathname, neighbor);
5588cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		strncpy(jitdumpfile, jitdump_dir, PATH_MAX);
5598cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		strncat(jitdumpfile, dmpfile->name, PATH_MAX);
5608cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		rc = process_jit_dumpfile(jitdumpfile, &anon_dnames,
5618cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd					  start_time, end_time, tmp_conv_dir);
5628cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		if (rc == OP_JIT_CONV_FAIL) {
5638cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd			verbprintf(debug, "JIT convert error %d\n", rc);
5648cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd			goto rm_tmp;
5658cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		}
5668cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		delete_pathname(dmpfile);
5678cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	}
5688cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	delete_path_names_list(&anon_dnames);
5698cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd
5708cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Doddrm_tmp:
5718cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	/* Delete temporary working directory with all its files
5728cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	 * (i.e. dump and ELF file).
5738cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	 */
5748cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	sprintf(sys_cmd_buffer, "/bin/rm -rf %s", tmp_conv_dir);
5758cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	if (system(sys_cmd_buffer) != 0) {
5768cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		printf("opjitconv: Removing temporary working directory failed.\n");
5778cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		rc = OP_JIT_CONV_TMPDIR_NOT_REMOVED;
5788cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	}
5798cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd
5808cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Doddout:
5818cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	return rc;
5828cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd}
5838cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd
5848cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Doddint main(int argc, char ** argv)
5858cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd{
5868cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	unsigned long long start_time, end_time;
5878cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	char const * session_dir;
5888cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	int rc = 0;
5898cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd
5908cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	debug = 0;
5918cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	if (argc > 1 && strcmp(argv[1], "-d") == 0) {
5928cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		debug = 1;
5938cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		argc--;
5948cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		argv++;
5958cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	}
5968cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd
5978cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	if (argc != 4) {
5988cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		printf("Usage: opjitconv [-d] <session_dir> <starttime>"
5998cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		       " <endtime>\n");
6008cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		fflush(stdout);
6018cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		rc = EXIT_FAILURE;
6028cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		goto out;
6038cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	}
6048cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd
6058cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	session_dir = argv[1];
6068cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	/*
6078cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	 * Check for a maximum of 4096 bytes (Linux path name length limit) decremented
6088cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	 * by 16 bytes (will be used later for appending samples sub directory).
6098cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	 * Integer overflows according to the session dir parameter (user controlled)
6108cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	 * are not possible anymore.
6118cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	 */
6128cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	if (strlen(session_dir) > PATH_MAX - 16) {
6138cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		printf("opjitconv: Path name length limit exceeded for session directory: %s\n", session_dir);
6148cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		rc = EXIT_FAILURE;
6158cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		goto out;
6168cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	}
6178cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd
6188cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	start_time = atol(argv[2]);
6198cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	end_time = atol(argv[3]);
6208cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd
6218cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	if (start_time > end_time) {
6228cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		rc = EXIT_FAILURE;
6238cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		goto out;
6248cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	}
6258cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	verbprintf(debug, "start time/end time is %llu/%llu\n",
6268cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		   start_time, end_time);
6278cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	rc = op_process_jit_dumpfiles(session_dir, start_time, end_time);
6288cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	if (rc > OP_JIT_CONV_OK) {
6298cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		verbprintf(debug, "opjitconv: Ending with rc = %d. This code"
6308cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd			   " is usually OK, but can be useful for debugging"
6318cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd			   " purposes.\n", rc);
6328cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		rc = OP_JIT_CONV_OK;
6338cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	}
6348cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	fflush(stdout);
6358cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	if (rc == OP_JIT_CONV_OK)
6368cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		rc = EXIT_SUCCESS;
6378cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	else
6388cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		rc = EXIT_FAILURE;
6398cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Doddout:
6408cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	_exit(rc);
6418cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd}
642