From: Paul Fertser Date: Wed, 11 Feb 2015 08:02:34 +0000 (+0300) Subject: target/cortex_m: do not leak memory on reexamination X-Git-Tag: v0.9.0-rc1~87 X-Git-Url: https://review.openocd.org/gitweb?p=openocd.git;a=commitdiff_plain;h=11b6ab90fb59bb2f794bbf7ca4cb89964ead6280 target/cortex_m: do not leak memory on reexamination This bug was exposed by Valgrind. Change-Id: If50878664d928c0a44e309ca1452089c1ac71466 Signed-off-by: Paul Fertser Reviewed-on: http://openocd.zylin.com/2542 Tested-by: jenkins Reviewed-by: Stian Skjelstad Reviewed-by: Spencer Oliver --- diff --git a/src/target/cortex_m.c b/src/target/cortex_m.c index 38ed4c3a1f..028bfd8085 100644 --- a/src/target/cortex_m.c +++ b/src/target/cortex_m.c @@ -61,6 +61,7 @@ /* forward declarations */ static int cortex_m_store_core_reg_u32(struct target *target, uint32_t num, uint32_t value); +static void cortex_m_dwt_free(struct target *target); static int cortexm_dap_read_coreregister_u32(struct target *target, uint32_t *value, int regnum) @@ -1833,6 +1834,27 @@ fail1: */ } +static void cortex_m_dwt_free(struct target *target) +{ + struct cortex_m_common *cm = target_to_cm(target); + struct reg_cache *cache = cm->dwt_cache; + + free(cm->dwt_comparator_list); + cm->dwt_comparator_list = NULL; + + if (cache) { + register_unlink_cache(&target->reg_cache, cache); + + if (cache->reg_list) { + for (size_t i = 0; i < cache->num_regs; i++) + free(cache->reg_list[i].arch_info); + free(cache->reg_list); + } + free(cache); + } + cm->dwt_cache = NULL; +} + #define MVFR0 0xe000ef40 #define MVFR1 0xe000ef44 @@ -1910,6 +1932,7 @@ int cortex_m_examine(struct target *target) cortex_m->fp_num_code = ((fpcr >> 8) & 0x70) | ((fpcr >> 4) & 0xF); cortex_m->fp_num_lit = (fpcr >> 8) & 0xF; cortex_m->fp_code_available = cortex_m->fp_num_code; + free(cortex_m->fp_comparator_list); cortex_m->fp_comparator_list = calloc( cortex_m->fp_num_code + cortex_m->fp_num_lit, sizeof(struct cortex_m_fp_comparator)); @@ -1928,6 +1951,7 @@ int cortex_m_examine(struct target *target) cortex_m->fp_num_lit); /* Setup DWT */ + cortex_m_dwt_free(target); cortex_m_dwt_setup(cortex_m, target); /* These hardware breakpoints only work for code in flash! */ diff --git a/src/target/register.c b/src/target/register.c index 42b3b8b64e..1c1717c8ff 100644 --- a/src/target/register.c +++ b/src/target/register.c @@ -72,6 +72,14 @@ struct reg_cache **register_get_last_cache_p(struct reg_cache **first) return cache_p; } +void register_unlink_cache(struct reg_cache **cache_p, const struct reg_cache *cache) +{ + while (*cache_p && *cache_p != cache) + cache_p = &((*cache_p)->next); + if (*cache_p) + *cache_p = cache->next; +} + /** Marks the contents of the register cache as invalid (and clean). */ void register_cache_invalidate(struct reg_cache *cache) { diff --git a/src/target/register.h b/src/target/register.h index 354a17973c..7bac69b5a7 100644 --- a/src/target/register.h +++ b/src/target/register.h @@ -146,6 +146,7 @@ struct reg_arch_type { struct reg *register_get_by_name(struct reg_cache *first, const char *name, bool search_all); struct reg_cache **register_get_last_cache_p(struct reg_cache **first); +void register_unlink_cache(struct reg_cache **cache_p, const struct reg_cache *cache); void register_cache_invalidate(struct reg_cache *cache); void register_init_dummy(struct reg *reg);