From: Hsiangkai Wang Date: Wed, 14 Aug 2013 06:46:58 +0000 (+0800) Subject: target: enhance target profiling X-Git-Tag: v0.8.0-rc1~279 X-Git-Url: https://review.openocd.org/gitweb?p=openocd.git;a=commitdiff_plain;h=6d86ded4dbc7fb44cc659c6c39d6507752133c6b target: enhance target profiling 1. gprof uses 2-bytes as minimum bucket size. 2. As user wants to use gprof --sum to summarize multiple profiling data files, the range MUST be the same. Add new arguments to specify profiling range. Change-Id: Ie7e6afa6a4d82250e2d194a0eed2b428c1479ea1 Signed-off-by: Hsiangkai Wang Reviewed-on: http://openocd.zylin.com/1572 Tested-by: jenkins Reviewed-by: Spencer Oliver --- diff --git a/src/target/target.c b/src/target/target.c index b038519732..9cc94f3a09 100644 --- a/src/target/target.c +++ b/src/target/target.c @@ -3426,8 +3426,11 @@ static void writeString(FILE *f, char *s) writeData(f, s, strlen(s)); } +typedef unsigned char UNIT[2]; /* unit of profiling */ + /* Dump a gmon.out histogram file. */ -static void write_gmon(uint32_t *samples, uint32_t sampleNum, const char *filename) +static void write_gmon(uint32_t *samples, uint32_t sampleNum, const char *filename, + bool with_range, uint32_t start_address, uint32_t end_address) { uint32_t i; FILE *f = fopen(filename, "w"); @@ -3443,18 +3446,25 @@ static void write_gmon(uint32_t *samples, uint32_t sampleNum, const char *filena writeData(f, &zero, 1); /* figure out bucket size */ - uint32_t min = samples[0]; - uint32_t max = samples[0]; - for (i = 0; i < sampleNum; i++) { - if (min > samples[i]) - min = samples[i]; - if (max < samples[i]) - max = samples[i]; - } + uint32_t min; + uint32_t max; + if (with_range) { + min = start_address; + max = end_address; + } else { + min = samples[0]; + max = samples[0]; + for (i = 0; i < sampleNum; i++) { + if (min > samples[i]) + min = samples[i]; + if (max < samples[i]) + max = samples[i]; + } - /* max should be (largest sample + 1) - * Refer to binutils/gprof/hist.c (find_histogram_for_pc) */ - max++; + /* max should be (largest sample + 1) + * Refer to binutils/gprof/hist.c (find_histogram_for_pc) */ + max++; + } int addressSpace = max - min; assert(addressSpace >= 2); @@ -3462,7 +3472,7 @@ static void write_gmon(uint32_t *samples, uint32_t sampleNum, const char *filena /* FIXME: What is the reasonable number of buckets? * The profiling result will be more accurate if there are enough buckets. */ static const uint32_t maxBuckets = 128 * 1024; /* maximum buckets. */ - uint32_t numBuckets = addressSpace; + uint32_t numBuckets = addressSpace / sizeof(UNIT); if (numBuckets > maxBuckets) numBuckets = maxBuckets; int *buckets = malloc(sizeof(int) * numBuckets); @@ -3473,6 +3483,10 @@ static void write_gmon(uint32_t *samples, uint32_t sampleNum, const char *filena memset(buckets, 0, sizeof(int) * numBuckets); for (i = 0; i < sampleNum; i++) { uint32_t address = samples[i]; + + if ((address < min) || (max <= address)) + continue; + long long a = address - min; long long b = numBuckets; long long c = addressSpace; @@ -3517,7 +3531,7 @@ COMMAND_HANDLER(handle_profile_command) { struct target *target = get_current_target(CMD_CTX); - if (CMD_ARGC != 2) + if ((CMD_ARGC != 2) && (CMD_ARGC != 4)) return ERROR_COMMAND_SYNTAX_ERROR; const uint32_t MAX_PROFILE_SAMPLE_NUM = 10000; @@ -3565,7 +3579,17 @@ COMMAND_HANDLER(handle_profile_command) return retval; } - write_gmon(samples, num_of_sampels, CMD_ARGV[1]); + uint32_t start_address = 0; + uint32_t end_address = 0; + bool with_range = false; + if (CMD_ARGC == 4) { + with_range = true; + COMMAND_PARSE_NUMBER(uint, CMD_ARGV[2], start_address); + COMMAND_PARSE_NUMBER(uint, CMD_ARGV[3], end_address); + } + + write_gmon(samples, num_of_sampels, CMD_ARGV[1], + with_range, start_address, end_address); command_print(CMD_CTX, "Wrote %s", CMD_ARGV[1]); free(samples); @@ -5563,7 +5587,7 @@ static const struct command_registration target_exec_command_handlers[] = { .name = "profile", .handler = handle_profile_command, .mode = COMMAND_EXEC, - .usage = "seconds filename", + .usage = "seconds filename [start end]", .help = "profiling samples the CPU PC", }, /** @todo don't register virt2phys() unless target supports it */