diff options
author | Antonio Borneo <borneo.antonio@gmail.com> | 2022-12-14 15:21:43 +0100 |
---|---|---|
committer | Antonio Borneo <borneo.antonio@gmail.com> | 2022-12-17 09:32:34 +0000 |
commit | 2b6fe8f1ab739798309b47f7b3a664894ba43a19 (patch) | |
tree | b3582be76108f615b578d0d821e8e3d45696f86a /src | |
parent | a51ac964c6160646f2c28db854aa8faf096eb314 (diff) | |
download | riscv-openocd-2b6fe8f1ab739798309b47f7b3a664894ba43a19.zip riscv-openocd-2b6fe8f1ab739798309b47f7b3a664894ba43a19.tar.gz riscv-openocd-2b6fe8f1ab739798309b47f7b3a664894ba43a19.tar.bz2 |
target: fix assert in 'monitor profile' on constant PC
When target is stopped in WFI/WFE or is in an infinite loop, the
sampled PC will always return the same value.
Command 'profile' requires that distance between min and max PC
should be at least 2, which is not the case for constant PC, and
incorrectly enforces the check through as assert().
Move the code that reads the optional parameters 'start' and 'end'
and check the gap 'end - start' before running the profile.
For self-computed min and max, increase max (or decrease min) to
match the required constraint.
Drop the assert().
Change-Id: I2be8df8568ce8c889923888c492e4f7ce354b16b
Signed-off-by: Antonio Borneo <borneo.antonio@gmail.com>
Fixes: https://sourceforge.net/p/openocd/tickets/370/
Reviewed-on: https://review.openocd.org/c/openocd/+/7400
Tested-by: jenkins
Diffstat (limited to 'src')
-rw-r--r-- | src/target/target.c | 31 |
1 files changed, 21 insertions, 10 deletions
diff --git a/src/target/target.c b/src/target/target.c index 755a8e2..e3a6f95 100644 --- a/src/target/target.c +++ b/src/target/target.c @@ -4253,10 +4253,17 @@ static void write_gmon(uint32_t *samples, uint32_t sample_num, const char *filen * Refer to binutils/gprof/hist.c (find_histogram_for_pc) */ if (max < UINT32_MAX) max++; + + /* gprof requires (max - min) >= 2 */ + while ((max - min) < 2) { + if (max < UINT32_MAX) + max++; + else + min--; + } } uint32_t address_space = max - min; - assert(address_space >= 2); /* FIXME: What is the reasonable number of buckets? * The profiling result will be more accurate if there are enough buckets. */ @@ -4332,6 +4339,19 @@ COMMAND_HANDLER(handle_profile_command) COMMAND_PARSE_NUMBER(u32, CMD_ARGV[0], offset); + uint32_t start_address = 0; + uint32_t end_address = 0; + bool with_range = false; + if (CMD_ARGC == 4) { + with_range = true; + COMMAND_PARSE_NUMBER(u32, CMD_ARGV[2], start_address); + COMMAND_PARSE_NUMBER(u32, CMD_ARGV[3], end_address); + if (start_address > end_address || (end_address - start_address) < 2) { + command_print(CMD, "Error: end - start < 2"); + return ERROR_COMMAND_ARGUMENT_INVALID; + } + } + uint32_t *samples = malloc(sizeof(uint32_t) * MAX_PROFILE_SAMPLE_NUM); if (!samples) { LOG_ERROR("No memory to store samples."); @@ -4384,15 +4404,6 @@ COMMAND_HANDLER(handle_profile_command) return retval; } - uint32_t start_address = 0; - uint32_t end_address = 0; - bool with_range = false; - if (CMD_ARGC == 4) { - with_range = true; - COMMAND_PARSE_NUMBER(u32, CMD_ARGV[2], start_address); - COMMAND_PARSE_NUMBER(u32, CMD_ARGV[3], end_address); - } - write_gmon(samples, num_of_samples, CMD_ARGV[1], with_range, start_address, end_address, target, duration_ms); command_print(CMD, "Wrote %s", CMD_ARGV[1]); |