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