[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



This has some cleanups for the perf_event_open call
+ Makes the switch statements all have explicit case statements
  for all the cases we care about (instead of sometimes relying
  on default)
+ Uses rand32() or rand64() over rand() when appropriate
+ Adds a lot more coverage to the create_random_event() function
+ Some other fine tuning

In the end I didn't run lindent on it.  I agree the file could use it,
but I didn't want to mix indentation changes in with functionality 
changes.

Signed-off-by: Vince Weaver <vincent.weaver@xxxxxxxxx>

diff --git a/syscalls/perf_event_open.c b/syscalls/perf_event_open.c
index 32c11cf..aebf5e4 100644
--- a/syscalls/perf_event_open.c
+++ b/syscalls/perf_event_open.c
@@ -479,8 +479,11 @@ static long long random_cache_config(void)
 	case 6:
 		cache_id = PERF_COUNT_HW_CACHE_NODE;
 		break;
+	case 7:
+		cache_id = rand() % 256;
+		break;
 	default:
-		cache_id = rand();
+		cache_id = 0;
 		break;
 	}
 
@@ -494,8 +497,11 @@ static long long random_cache_config(void)
 	case 2:
 		hw_cache_op_id = PERF_COUNT_HW_CACHE_OP_PREFETCH;
 		break;
+	case 3:
+		hw_cache_op_id = rand() % 256;
+		break;
 	default:
-		hw_cache_op_id = rand();
+		hw_cache_op_id = 0;
 		break;
 	}
 
@@ -506,8 +512,11 @@ static long long random_cache_config(void)
 	case 1:
 		hw_cache_op_result_id = PERF_COUNT_HW_CACHE_RESULT_MISS;
 		break;
+	case 2:
+		hw_cache_op_result_id = rand() % 256;
+		break;
 	default:
-		hw_cache_op_result_id = rand();
+		hw_cache_op_result_id = 0;
 		break;
 	}
 
@@ -517,7 +526,7 @@ static long long random_cache_config(void)
 static int random_event_type(void)
 {
 
-	int type;
+	int type=0;
 
 	switch (rand() % 8) {
 	case 0:
@@ -541,8 +550,10 @@ static int random_event_type(void)
 	case 6:
 		type = PERF_TYPE_READ_FROM_SYSFS;
 		break;
+	case 7:
+		type = rand32();
+		break;
 	default:
-		type = rand();
 		break;
 	}
 	return type;
@@ -550,7 +561,7 @@ static int random_event_type(void)
 
 static long long random_event_config(__u32 *event_type, __u64 *config1)
 {
-	unsigned long long config;
+	unsigned long long config=0;
 
 	switch (*event_type) {
 	case PERF_TYPE_HARDWARE:
@@ -585,9 +596,11 @@ static long long random_event_config(__u32 *event_type, __u64 *config1)
 		case 9:
 			config = PERF_COUNT_HW_REF_CPU_CYCLES;
 			break;
-		default:
+		case 10:
 			config = rand64();
 			break;
+		default:
+			break;
 		}
 		break;
 	case PERF_TYPE_SOFTWARE:
@@ -619,14 +632,17 @@ static long long random_event_config(__u32 *event_type, __u64 *config1)
 		case 8:
 			config = PERF_COUNT_SW_EMULATION_FAULTS;
 			break;
-		default:
+		case 9:
 			config = rand64();
 			break;
+		default:
+			break;
 		}
 		break;
 	case PERF_TYPE_TRACEPOINT:
 		/* Actual values to use can be found under */
-		/* debugfs tracing/events// *//*/id         */
+		/* debugfs tracing/events// *//*/id        */
+		/* usually a small < 1024 number           */
 		config = rand64();
 		break;
 	case PERF_TYPE_HW_CACHE:
@@ -654,6 +670,7 @@ static long long random_event_config(__u32 *event_type, __u64 *config1)
 
 	default:
 		config = rand64();
+		*config1 = rand64();
 		break;
 	}
 	return config;
@@ -678,15 +695,17 @@ static void setup_breakpoints(struct perf_event_attr *attr)
 	case 4:
 		attr->bp_type = HW_BREAKPOINT_X;
 		break;
+	case 5:
+		attr->bp_type = rand32();
+		break;
 	default:
-		attr->bp_type = rand();
 		break;
 	}
 
 	/* This might be more interesting if this were    */
 	/* a valid executable address for HW_BREAKPOINT_X */
 	/* or a valid mem location for R/W/RW             */
-	attr->bp_addr = rand();
+	attr->bp_addr = (long)get_address();
 
 	switch (rand() % 5) {
 	case 0:
@@ -701,8 +720,10 @@ static void setup_breakpoints(struct perf_event_attr *attr)
 	case 3:
 		attr->bp_len = HW_BREAKPOINT_LEN_8;
 		break;
+	case 4:
+		attr->bp_len = rand64();
+		break;
 	default:
-		attr->bp_len = rand();
 		break;
 	}
 }
@@ -713,7 +734,7 @@ static long long random_sample_type(void)
 	long long sample_type = 0;
 
 	if (rand() % 2)
-		return rand();
+		return rand64();
 
 	if (rand_bool())
 		sample_type |= PERF_SAMPLE_IP;
@@ -752,8 +773,8 @@ static long long random_read_format(void)
 
 	long long read_format = 0;
 
-	if (rand_bool())
-		return rand();
+	if (rand() % 2)
+		return rand64();
 
 	if (rand_bool())
 		read_format |= PERF_FORMAT_GROUP;
@@ -767,25 +788,53 @@ static long long random_read_format(void)
 	return read_format;
 }
 
-static void create_mostly_valid_counting_event(struct perf_event_attr *attr)
+static int random_attr_size(void) {
+
+	int size=0;
+
+	switch(rand() % 8) {
+	case 0:	size = PERF_ATTR_SIZE_VER0;
+		break;
+	case 1: size = PERF_ATTR_SIZE_VER1;
+		break;
+	case 2: size = PERF_ATTR_SIZE_VER2;
+		break;
+	case 3: size = PERF_ATTR_SIZE_VER3;
+		break;
+	case 4: size = sizeof(struct perf_event_attr);
+		break;
+	case 5: size = rand32();
+		break;
+	case 6:	size = get_len();
+		break;
+	case 7: size = 0;
+		break;
+	default:
+		break;
+	}
+
+	return size;
+}
+
+static void create_mostly_valid_counting_event(struct perf_event_attr *attr,
+						int group_leader)
 {
 
 	attr->type = random_event_type();
+	attr->size = random_attr_size();
+	attr->config = random_event_config(&attr->type,&attr->config1);
 
-	attr->size = sizeof(struct perf_event_attr);
-	/* FIXME: can typically be 64,72,80,or 96 depending on kernel */
-	/* Other values will likely not create a valid event       */
+	/* no freq for counting event */
+	/* no sample type for counting event */
 
-	attr->config = random_event_config(&attr->type,&attr->config1);
-	if (attr->type == PERF_TYPE_BREAKPOINT) {
-		setup_breakpoints(attr);
-	}
 	attr->read_format = random_read_format();
 
-	/* Boolean parameters */
+	/* Bitfield parameters, mostly boolean */
 	attr->disabled = rand_bool();
 	attr->inherit = rand_bool();
-	attr->pinned = rand_bool();
+	if (group_leader) {
+		attr->pinned = rand_bool();
+	}
 	attr->exclusive = rand_bool();
 	attr->exclude_user = rand_bool();
 	attr->exclude_kernel = rand_bool();
@@ -793,7 +842,7 @@ static void create_mostly_valid_counting_event(struct perf_event_attr *attr)
 	attr->exclude_idle = rand_bool();
 	attr->mmap = rand_bool();
 	attr->comm = rand_bool();
-	// freq not relevant
+	attr->freq = rand_bool();
 	attr->inherit_stat = rand_bool();
 	attr->enable_on_exec = rand_bool();
 	attr->task = rand_bool();
@@ -806,35 +855,40 @@ static void create_mostly_valid_counting_event(struct perf_event_attr *attr)
 	attr->exclude_callchain_kernel = rand_bool();
 	attr->exclude_callchain_user = rand_bool();
 
-	attr->wakeup_events = rand();	// also wakeup_watermark
-
-	//attr->config1 = rand64();
-	//attr->config2 = rand64();
-	// only valid with certain event combinations
+	/* wakeup events not relevant */
 
-	//attr->branch_sample_type = rand64();
-	//attr->sample_regs_user = rand64();
-	//attr->saple_stack_user = rand();
+	/* breakpoint events unioned with config */
+	if (attr->type == PERF_TYPE_BREAKPOINT) {
+		setup_breakpoints(attr);
+	} else {
+		/* config1 set earlier */
+		/* leave config2 alone for now */
+	}
 
 }
 
-static void create_mostly_valid_sampling_event(struct perf_event_attr *attr)
+static void create_mostly_valid_sampling_event(struct perf_event_attr *attr,
+						int group_leader)
 {
 
 	attr->type = random_event_type();
-	attr->size = sizeof(struct perf_event_attr);
+	attr->size = random_attr_size();
 	attr->config = random_event_config(&attr->type,&attr->config1);
-	if (attr->type == PERF_TYPE_BREAKPOINT) {
-		setup_breakpoints(attr);
-	}
-	attr->sample_period = rand();	/* low values more likely to have "interesting" results */
+
+	/* low values more likely to have "interesting" results */
+	attr->sample_period = rand64();
 	attr->sample_type = random_sample_type();
 	attr->read_format = random_read_format();
 
-	/* Boolean parameters */
+	/* Bitfield parameters, mostly boolean */
 	attr->disabled = rand_bool();
 	attr->inherit = rand_bool();
-	attr->pinned = rand_bool();
+	/* only group leaders can be pinned */
+	if (group_leader) {
+		attr->pinned = rand_bool();
+	} else {
+		attr->pinned = 0;
+	}
 	attr->exclusive = rand_bool();
 	attr->exclude_user = rand_bool();
 	attr->exclude_kernel = rand_bool();
@@ -842,7 +896,7 @@ static void create_mostly_valid_sampling_event(struct perf_event_attr *attr)
 	attr->exclude_idle = rand_bool();
 	attr->mmap = rand_bool();
 	attr->comm = rand_bool();
-
+	attr->freq = rand_bool();
 	attr->inherit_stat = rand_bool();
 	attr->enable_on_exec = rand_bool();
 	attr->task = rand_bool();
@@ -855,42 +909,71 @@ static void create_mostly_valid_sampling_event(struct perf_event_attr *attr)
 	attr->exclude_callchain_kernel = rand_bool();
 	attr->exclude_callchain_user = rand_bool();
 
-	attr->wakeup_events = rand();	// also wakeup_watermark
+	attr->wakeup_events = rand32();
 
-	//attr->config1 = rand64();
-	//attr->config2 = rand64();
-	// only valid with certain event combinations
-
-	//attr->branch_sample_type = rand64();
-	//attr->sample_regs_user = rand64();
-	//attr->saple_stack_user = rand();
+	if (attr->type == PERF_TYPE_BREAKPOINT) {
+		setup_breakpoints(attr);
+	}
+	else {
+		/* breakpoint fields unioned with config fields */
+		/* config1 set earlier */
+	}
 
 }
 
+/* Creates a completely random event, unlikely to be valid */
 static void create_random_event(struct perf_event_attr *attr)
 {
 
 	attr->type = random_event_type();
-	attr->config = random_event_config(&attr->type,&attr->config1);
-	setup_breakpoints(attr);
 
-	switch (rand_bool()) {
-	case 0:
-		attr->size = sizeof(struct perf_event_attr);
-		break;
-	case 1:
-		attr->size = get_len();
-	default:
-		break;
-	}
+	attr->size = random_attr_size();
+
+	attr->config = random_event_config(&attr->type,&attr->config1);
 
+	attr->sample_period = rand64();
 	attr->sample_type = random_sample_type();
 	attr->read_format = random_read_format();
 
-	/* booleans */
+	/* bitfields */
+	attr->disabled = rand_bool();
+	attr->inherit = rand_bool();
+	attr->pinned = rand_bool();
+	attr->exclusive = rand_bool();
 	attr->exclude_user = rand_bool();
-	attr->exclude_kernel = rand_bool();	/* doesn't require root unless paranoid set to 2 */
+	attr->exclude_kernel = rand_bool();
 	attr->exclude_hv = rand_bool();
+	attr->exclude_idle = rand_bool();
+	attr->mmap = rand_bool();
+	attr->comm = rand_bool();
+	attr->freq = rand_bool();
+	attr->inherit_stat = rand_bool();
+	attr->enable_on_exec = rand_bool();
+	attr->task = rand_bool();
+	attr->watermark = rand_bool();
+	attr->precise_ip = rand() % 4;
+	attr->mmap_data = rand_bool();
+	attr->sample_id_all = rand_bool();
+	attr->exclude_host = rand_bool();
+	attr->exclude_guest = rand_bool();
+	attr->exclude_callchain_kernel = rand_bool();
+	attr->exclude_callchain_user = rand_bool();
+
+	attr->wakeup_events=rand32();
+
+	/* Breakpoints are unioned with the config values */
+	if (rand() % 2) {
+		setup_breakpoints(attr);
+	}
+	else {
+		/* config1 set earlier */
+		attr->config2 = rand64();
+	}
+
+	attr->branch_sample_type = rand64();
+	attr->sample_regs_user = rand64();
+	attr->sample_stack_user = rand32();
+
 }
 
 static void sanitise_perf_event_open(int childno)
@@ -898,7 +981,7 @@ static void sanitise_perf_event_open(int childno)
 	struct perf_event_attr *attr;
 	unsigned long flags;
 	pid_t pid;
-	int group_fd;
+	int group_leader=0;
 
 	shm->a1[childno] = (unsigned long)page_rand;
 	attr = (struct perf_event_attr *)shm->a1[childno];
@@ -916,12 +999,22 @@ static void sanitise_perf_event_open(int childno)
 	/* should usually be -1 or another perf_event fd         */
 	/* Anything but -1 unlikely to work unless the other pid */
 	/* was properly set up to be a group master              */
-	if (rand() % 2) {
-		group_fd = -1;
-	} else {
-		group_fd = get_pid();
+	switch (rand() % 3) {
+	case 0:
+		shm->a4[childno] = -1;
+		group_leader = 1;
+		break;
+	case 1:
+		/* Try to get a previous random perf_event_open() fd  */
+		/* It's unclear whether get_random_fd() would do this */
+		shm->a4[childno] = rand() % 1024;
+		break;
+	case 2:
+		/* Rely on ARG_FD */
+		break;
+	default:
+		break;
 	}
-	shm->a4[childno] = group_fd;
 
 	/* flags */
 	/* You almost never set these unless you're playing with cgroups */
@@ -957,14 +1050,16 @@ static void sanitise_perf_event_open(int childno)
 	/* set up attr structure */
 	switch (rand() % 3) {
 	case 0:
-		create_mostly_valid_counting_event(attr);
+		create_mostly_valid_counting_event(attr,group_leader);
 		break;
 	case 1:
-		create_mostly_valid_sampling_event(attr);
+		create_mostly_valid_sampling_event(attr,group_leader);
 		break;
-	default:
+	case 2:
 		create_random_event(attr);
 		break;
+	default:
+		break;
 	}
 }
 
--
To unsubscribe from this list: send the line "unsubscribe trinity" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html




[Index of Archives]     [Linux SCSI]     [Linux USB Devel]     [Video for Linux]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]

  Powered by Linux