github.com/google/syzkaller@v0.0.0-20240517125934-c0f1611a36d6/docs/headerparser_usage.md (about)

     1  ## Headerparser
     2  
     3  headerparser is a tool that assists in writing device system call descriptions for syzkaller.
     4  
     5  In order to make syzkaller smarter when it comes to fuzzing a device node, you can provide it with
     6  information about the ioctl argument struct types it expects.
     7  
     8  However, in certain cases the number of argument struct types might be high, increasing the amount of manual
     9  effort that goes into writing the description files for the struct types.
    10  
    11  In order to ease the effort of writing ioctl argument type description files, headerlib does a best-effort job at
    12  generating them for you. You will still need to manually select the appropriate syzkaller data type from the list
    13  of types [here](/docs/syscall_descriptions_syntax.md).
    14  
    15  ## Dependencies
    16  Headerlib uses pycparser. You can install pycparser using pip.
    17  
    18  ```shell
    19  $ pip install pycparser
    20  ```
    21  
    22  ## Using headerparser
    23  ```shell
    24  $ python headerparser.py --filenames=./test_headers/th_b.h
    25  B {
    26            B1     len|fileoff|flags|intN     #(unsigned long)
    27            B2     len|fileoff|flags|intN     #(unsigned long)
    28  }
    29  struct_containing_union {
    30            something          len|fileoff|flags|int32                   #(int)
    31            a_union.a_char     ptr[in|out, string]|ptr[in, filename]     #(char*)
    32            a_union.B_ptr      ptr|buffer|array                          #(struct B*)
    33  }
    34  ```
    35  
    36  You can copy paste the content underneath the `Structure Metadata` over to your syzkaller device description.
    37  
    38  ## Something breaks
    39  Let us try parsing `test_headers/th_a.h` header file to generate argument structs.
    40  
    41  ```shell
    42  $ python headerparser.py --filenames=./test_headers/th_a.h
    43  ERROR:root:HeaderFilePreprocessorException: /tmp/tmpW8xzty/source.o:36:2: before: some_type
    44  
    45  $ python headerparser.py --filenames=./test_headers/th_a.h --debug
    46  DEBUG:GlobalHierarchy:load_header_files : ['./test_headers/th_a.h']
    47  DEBUG:HeaderFilePreprocessor:HeaderFilePreprocessor._mktempfiles: sourcefile=/tmp/tmpbBQYhR/source.cobjectfile=/tmp/tmpbBQYhR/source.o
    48  DEBUG:HeaderFilePreprocessor:HeaderFilePreprocessor.execute: cp ./test_headers/th_a.h /tmp/tmpbBQYhR
    49  DEBUG:HeaderFilePreprocessor:HeaderFilePreprocessor.execute: gcc -I. -E -P -c /tmp/tmpbBQYhR/source.c > /tmp/tmpbBQYhR/source.o
    50  ERROR:root:HeaderFilePreprocessorException: /tmp/tmpbBQYhR/source.o:36:2: before: some_type
    51  ```
    52  
    53  From the error message, we can see that the error occurs as pycparser is not aware of the type `some_type`. We can resolve this by making pycparser aware of the unknown type. In order to do this, we supply headerparser with a include file that contains C declarations and includes that can fix the parse error.
    54  
    55  ```shell
    56  $ cat > include_file
    57  typedef int some_type;
    58  $ python headerparser.py --filenames=./test_headers/th_a.h --include=./include_file
    59  A {
    60            B_item              ptr|buffer|array                          #(struct B*)
    61            char_ptr            ptr[in|out, string]|ptr[in, filename]     #(char*)
    62            an_unsigned_int     len|fileoff|int32                         #(unsigned int)
    63            a_bool              _Bool                                     #(_Bool)
    64            another_bool        _Bool                                     #(_Bool)
    65            var                 some_type                                 #(some_type)
    66  }
    67  ```