aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/test-dissect.c
AgeCommit message (Collapse)AuthorFilesLines
2017-06-21dissect: use built_in_ident() instead of MK_IDENT()Luc Van Oostenryck1-3/+3
The motivation for this patch was to allow sparse to be compiled with clang which doesn't like static initialization of flexible array members which is used in MK_IDENT(). But also, there is no enough good justifications here for not creating the identifiers the normal way with built_in_ident(). Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com> Acked-by: Oleg Nesterov <oleg@redhat.com>
2006-12-04cleanup write to argument array hackChristopher Li1-4/+6
The sparse interface is a kind of snaky that it change the input argument array. The function sparse() does the same hack just to skip the files. This patch add the ptr list for string. So sparse_initialize will return list of file to compile. The string pointer is not aligned at word boundary. This patch introduce non taged version of the ptr list iteration function. Signed-off-by: Christopher Li <sparse@chrisli.org>
2005-12-20[PATCH] dissect.cOleg Nesterov1-0/+95
This patch adds dissect.{h,c} files to the sparse distribution. From dissect.h: struct reporter { void (*r_symdef)(struct symbol*); void (*r_symbol)(unsigned mode, struct position*, struct symbol*); void (*r_member)(unsigned mode, struct position*, struct symbol*, struct symbol*); }; extern void dissect(struct symbol_list*, struct reporter*); dissect() walks the output of the sparse_file() and calls reporter's callbacks. ->r_symdef() is called when the symbol (variable or function) is defined. ->r_symbol() - when the symbol is used in any way. The 'mode' parameter denotes how this symbol was used. It is a bitmask of possible flags: FLAG: Code example: U_R_VAL return VAR; U_W_VAL VAR = 0; U_R_PTR return *VAR; U_W_PTR *VAR = 0; U_R_AOF const void *... = &VAR; U_W_AOF memset(&VAR, ...); ->r_member() tracks the use of members of structures in the same way. This patch also adds test-dissect.c, a simple and stupid example. It prints the 'mode' parameter in a human readable format along with the storage info, variable's name (or struct_name.member_name), and it's type. The 'mode' is dumped as a 3-letter string. The first letter denotes AOF part, 2-nd - VAL, 3-rd - PTR. 0 -> '-' U_R_xxx -> 'r' U_W_xxx -> 'w' U_R_xxx | U_W_xxx -> 'm' Example: $ cat -n T.c 1 int var; 2 3 static void func(void) 4 { 5 int *ptr; 6 7 ptr = &var; 8 *ptr = var; 9 10 var = *++ptr; 11 } $ ./test-dissect T.c FILE: T.c 1:5 g def var int 3:13 s def func void ( )( ... ) 5:6 l def ptr int * 7:2 l -w- ptr int * 7:9 g m-- var int 8:3 l --w ptr int * 8:9 g -r- var int 10:2 g -w- var int 10:11 l -mr ptr int * Note that '*ptr' does not add U_R_VAL flag, this is a feature, not a bug, even if technically wrong. dissect() does not check the code for correctness, for example: 0 = X = Y; gives this output: 5:6 g -w- X bad type 5:10 g -r- Y bad type Again, X has no U_R_VAL, notabug. Members of structures usage: task_t *tsk; tsk->parent->real_parent->pid++; output: 7:2 l --r tsk struct task_struct [usertype] * 7:5 g --r task_struct.parent struct task_struct * 7:13 g --m task_struct.real_parent struct task_struct * 7:26 g -m- task_struct.pid int dissect() tries to de-anonymize unnamed structures/unions: 1 struct T { 2 struct { 3 int x, y; 4 } m; 5 } t = { 6 { undeclared } 7 }; output: 5:3 g def t struct T 5:3 g -w- t struct T 6:2 s -w- T.m struct T:m 6:4 s -w- T:m.x int 6:4 g -r- undeclared bad type When entire struct is overwritten, ->r_member() is called with mem == NULL, this reported as struct_name.*, example: *new_vma = *vma; output: 2028:5 l --w new_vma struct vm_area_struct * 2028:13 g -w- vm_area_struct.* struct vm_area_struct 2028:13 g -w- pgprot_t.* struct pgprot_t 2028:13 g -w- rb_node.* struct rb_node 2028:13 g -w- vm_area_struct:shared.* union vm_area_struct:shared 2028:13 g -w- vm_area_struct:shared:vm_set.* struct vm_area_struct:shared:vm_set 2028:13 g -w- list_head.* struct list_head 2028:13 g -w- raw_prio_tree_node.* struct raw_prio_tree_node 2028:13 g -w- list_head.* struct list_head 2028:16 l --r vma struct vm_area_struct * Function calls use U_R_PTR bit: 5 func(); 6 pf = func; 7 pf(); 5:2 g --r func void ( )( ... ) 6:2 l -w- pf void ( * )( ... ) 6:7 g r-- func void ( )( ... ) 7:2 l --r pf void ( * )( ... ) BUGS: 1. dissect() confuses array-in-container with a pointer: 3 struct T { int ary[]; } t; 4 5 t.ary[0] = 0; output: 5:2 l -r- t /* BUG, should be -w- */ struct T 5:3 s -w- T.ary int [0] 2. It can't detect the case when the address is taken only for writing, eg: *(&i + 1) = 0, so U_W_AOF always implies U_R_AOF. 3. It does not support "flat" initializers without braces: 3 struct O { 4 struct I { 5 int x, y; 6 } a, b; 7 }; 8 9 struct O o1 = { 1, 2, 3 }; buggy output: 9:11 l -w- o1 struct O 9:18 s -w- O.a struct I 9:21 s -w- O.b struct I 9:24 s -w- O.? bad type This is ok: 11 struct O o2 = { { 1 }, .b = { .y = 0 } }; 11:11 l -w- o2 struct O 11:18 s -w- O.a struct I 11:20 s -w- I.x int 11:30 s -w- O.b struct I 11:37 s -w- I.y int 4. The implementation is far from perfect. It was really done in "add some code + printf and see what happens" manner, without studying the sources first. However I beleive it may be useful for others, that is why I am posting it. Signed-off-by: Oleg Nesterov <oleg@tv-sign.ru> Signed-off-by: Linus Torvalds <torvalds@osdl.org>