Smatch hooks and modules

There are two kinds of Smatch files. smatch_*.c files are core files which provide functionality and check_*.c files are checks. The other files in the directory are Sparse files.

The most interesting smatch_*.c file is smatch_flow.c which describes how the code flows and how smatch hooks are called. Search for __pass_to_client(expr, WHATEVER_HOOK);

The smatch_function_hooks.c file is useful because of the comment at the top of the file which describes a bunch of function related hooks.

/*
 * There are several types of function hooks.
 *
 * The param_key hooks are probably the right things to use going forward.
 * They give you a name/sym pair so it means less code in the checks.
 *
 * The add_function_hook() functions are trigger for every call.  The
 * "return_implies" are triggered for specific return ranges.  The "exact"
 * variants will be triggered if it's *definitely* in the range where the
 * others will be triggered if it's *possibly* in the range.  The "late"
 * variants will be triggered after the others have run.
 *
 * There are a few miscellaneous things like add_function_assign_hook() and
 * add_macro_assign_hook() which are only triggered for assignments.  The
 * add_implied_return_hook() let's you manually adjust the return range.
 *
 * Every call:
 *     add_function_param_key_hook_early()
 *     add_function_param_key_hook()
 *     add_function_param_key_hook_late()
 *     add_function_hook_early()
 *     add_function_hook()
 *
 * Just for some return ranges:
 *     return_implies_param_key()
 *     return_implies_param_key_exact()
 *     return_implies_state()
 *     select_return_param_key()  (It's weird that this is not in smatch_db.c)
 *
 * For Assignments:
 *     add_function_assign_hook()
 *
 * For Macro Assignments:
 *     add_macro_assign_hook()
 *
 * Manipulate the return range.
 *     add_implied_return_hook()
 */

Smatch has hooks to say that if we pass foo to a given function that means it returns bar. Or if a function returns foo that means bar. We might want to specify if a range falls partially or totally within the return range. Etc.

In my First Smatch Check post I left out an important part of the check. If we kfree(p), then assign “p = new_ptr;” then it is no longer freed. The hook to reset the state is:

add_modification_hook(my_id, &reset_state);
	
static void reset_state(struct sm_state *sm, struct expression *mod_expr)
{
	set_state(my_id, sm->name, sm->sym, &undefined);
}

Some of the Smatch checks rely on data from other checks so sometimes the ordering is tricky. I used to rely on the ordering in the check_list.h file but that was hard to document and maintain so it’s better to use _early() and _late() hooks to set the ordering. Also it’s better to add your checks in the middle of the file with the other checks instead of with the register_* stuff at the start and end of the file.

Sometimes you will want to treat macros differently. Use the get_macro_name() for this. Smatch runs on the pre-processed code so handling macros is very awkward, but sometimes it is necessary.

Here are some functions to do with numbers and degree of certainty:

  • get_value(): Get constant value
  • get_implied_value(): Get “known” value
  • get_implied_rl(): Get “known” range list. (Might be the whole range).
  • get_absolute_rl(): Get the possible range list. (Always returns something)

The smatch_extra.c/smatch_math.c files handle numbers, but the smatch_comparison.c file handles how variables are related to each other.

I have mentioned in previous blogs that I prefer to create small checks these days. Often that means splitting a check into multiple parts. For example, the check for scheduling in atomic context is split into four parts.

  • check_preempt_info.c: Registers increments and decrements of the atomic count
  • check_preempt.c: Stores whether the count is currently incremented
  • check_sleep_info.c: Records every sleep
  • check_scheduling_in_atomic.c: Prints the warnings

Splitting it up like this results in much simpler code.

The smatch_ssa.c file is basically an implementation of Single Static Assignment. For example, imagine that you have code like this:

x = p;
kfree(x);

Freeing x is the same as freeing p. What Smatch does is that it says actually you’re not freeing x you’re freeing p:123. The SSA code is sort of new-ish and slightly complicated. I wish it were simpler and more modules were written to take advantage of it.

There is a lot of hooks and modules and this blog entry is just a brief guide to a few are they are and they might exist. Ask on the mailing list if you have any questions.

Leave a comment

Design a site like this with WordPress.com
Get started