tcg: Add support for debugging leakage of temporaries
Add support (if CONFIG_DEBUG_TCG is defined) for debugging leakage of temporary variables. Generally any temporaries created by a target while it is translating an instruction should be freed by the end of that instruction; otherwise carefully crafted guest code could cause TCG to run out of temporaries and assert. By calling tcg_check_temp_count() after each instruction we can check that we are not leaking temporaries in this way. Signed-off-by: Peter Maydell <peter.maydell@linaro.org> Signed-off-by: Aurelien Jarno <aurelien@aurel32.net>
This commit is contained in:
parent
6ed221b637
commit
27bfd83c33
32
tcg/tcg.c
32
tcg/tcg.c
@ -450,6 +450,10 @@ static inline int tcg_temp_new_internal(TCGType type, int temp_local)
|
||||
s->nb_temps++;
|
||||
}
|
||||
}
|
||||
|
||||
#if defined(CONFIG_DEBUG_TCG)
|
||||
s->temps_in_use++;
|
||||
#endif
|
||||
return idx;
|
||||
}
|
||||
|
||||
@ -475,6 +479,13 @@ static inline void tcg_temp_free_internal(int idx)
|
||||
TCGTemp *ts;
|
||||
int k;
|
||||
|
||||
#if defined(CONFIG_DEBUG_TCG)
|
||||
s->temps_in_use--;
|
||||
if (s->temps_in_use < 0) {
|
||||
fprintf(stderr, "More temporaries freed than allocated!\n");
|
||||
}
|
||||
#endif
|
||||
|
||||
assert(idx >= s->nb_globals && idx < s->nb_temps);
|
||||
ts = &s->temps[idx];
|
||||
assert(ts->temp_allocated != 0);
|
||||
@ -528,6 +539,27 @@ TCGv_i64 tcg_const_local_i64(int64_t val)
|
||||
return t0;
|
||||
}
|
||||
|
||||
#if defined(CONFIG_DEBUG_TCG)
|
||||
void tcg_clear_temp_count(void)
|
||||
{
|
||||
TCGContext *s = &tcg_ctx;
|
||||
s->temps_in_use = 0;
|
||||
}
|
||||
|
||||
int tcg_check_temp_count(void)
|
||||
{
|
||||
TCGContext *s = &tcg_ctx;
|
||||
if (s->temps_in_use) {
|
||||
/* Clear the count so that we don't give another
|
||||
* warning immediately next time around.
|
||||
*/
|
||||
s->temps_in_use = 0;
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
void tcg_register_helper(void *func, const char *name)
|
||||
{
|
||||
TCGContext *s = &tcg_ctx;
|
||||
|
17
tcg/tcg.h
17
tcg/tcg.h
@ -323,6 +323,10 @@ struct TCGContext {
|
||||
int64_t restore_count;
|
||||
int64_t restore_time;
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_DEBUG_TCG
|
||||
int temps_in_use;
|
||||
#endif
|
||||
};
|
||||
|
||||
extern TCGContext tcg_ctx;
|
||||
@ -392,6 +396,19 @@ static inline TCGv_i64 tcg_temp_local_new_i64(void)
|
||||
void tcg_temp_free_i64(TCGv_i64 arg);
|
||||
char *tcg_get_arg_str_i64(TCGContext *s, char *buf, int buf_size, TCGv_i64 arg);
|
||||
|
||||
#if defined(CONFIG_DEBUG_TCG)
|
||||
/* If you call tcg_clear_temp_count() at the start of a section of
|
||||
* code which is not supposed to leak any TCG temporaries, then
|
||||
* calling tcg_check_temp_count() at the end of the section will
|
||||
* return 1 if the section did in fact leak a temporary.
|
||||
*/
|
||||
void tcg_clear_temp_count(void);
|
||||
int tcg_check_temp_count(void);
|
||||
#else
|
||||
#define tcg_clear_temp_count() do { } while (0)
|
||||
#define tcg_check_temp_count() 0
|
||||
#endif
|
||||
|
||||
void tcg_dump_info(FILE *f, fprintf_function cpu_fprintf);
|
||||
|
||||
#define TCG_CT_ALIAS 0x80
|
||||
|
Loading…
Reference in New Issue
Block a user