qemu-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [PATCH v2 03/18] modules: add qemu-modinfo utility


From: Daniel P . Berrangé
Subject: Re: [PATCH v2 03/18] modules: add qemu-modinfo utility
Date: Tue, 15 Jun 2021 10:27:02 +0100
User-agent: Mutt/2.0.7 (2021-05-04)

On Tue, Jun 15, 2021 at 06:54:41AM +0200, Gerd Hoffmann wrote:
> > > Problem with that approach is that it doesn't work for module
> > > dependencies ...
> > > 
> > > Comments on the idea?  Suggestions for the module dependency problem?
> > > Could maybe libbfd be used to find module (symbol) dependencies
> > > automatically without writing a full dynamic linker?
> > 
> > Is there any value in exploring use of libclang ?  It gives us a real
> > C parser that we can use to extract information from the C source. In
> > libvirt we have experimental patches (not yet merged) using libclang to
> > auto-generate XML parser helpers from struct annotations. It is quite
> > nice compared to any other hacks for extracting information from C
> > source files without using a proper parser.  libclang can be accessed
> > from Python3 via its bindings and IIUC should be usable on all our
> > build platforms
> 
> Could you do something along the lines of ...
> 
>   (1) find constructors
>   (2) find type_register() calls in the constructor and the
>       TypeInfo structs passed to those calls.
>   (3) inspect the TypeInfo structs to figure the QOM type names.
> 
> ... with libclang?

In theory that should all be doable. I'm not very familiar myself with
libclang, but IIUC you basically get given the abstract syntax tree
and have to traverse it to find the info you want. This is kind of
low level but the info should all be there if you know how to find
it.

As an answer to (1) and part of (2), the following code I hacked up
quickly, finds all constructors that contain "type_register" calls.
Would need to find the arg to the calls and match that up to the
static structs too.


from clang.cindex import Index, CursorKind

def is_constructor(cursor):
    for bit in cursor.get_children():
        if bit.kind == CursorKind.UNEXPOSED_ATTR:
            for tok in bit.get_tokens():
                if tok.spelling == "constructor":
                    return True
    return False

def find_constructors(cursor):
    for cursor in cursor.get_children():
        if cursor.kind == CursorKind.FUNCTION_DECL:
            if is_constructor(cursor):
                yield cursor

def has_type_register(cursor):
    for cursor in constructor.get_children():
        if cursor.kind == CursorKind.COMPOUND_STMT:
            for c in cursor.get_children():
                if c.kind == CursorKind.CALL_EXPR:
                    if c.displayname == "type_register":
                        return True
    return False
                
index = Index.create()
tu = index.parse("demo.c")
for constructor in find_constructors(tu.cursor):
    has_reg = has_type_register(constructor)
    if has_reg:
        print("Constructor with type_register: " + constructor.displayname)


I tested with a short example

#include <stdio.h>

struct Foo {
  int bar;
};

static void type_register(struct Foo *foo) {
  printf("%d\n", foo->bar);
}
  
__attribute__((constructor)) static void startit(void) 
{
  static struct Foo foo = { 42 };
  type_register(&foo);
}

int main(int argc, char **argv) {
  printf("Running main\n");
}


$ python demo.py
Constructor with type register: startit()


Regards,
Daniel
-- 
|: https://berrange.com      -o-    https://www.flickr.com/photos/dberrange :|
|: https://libvirt.org         -o-            https://fstop138.berrange.com :|
|: https://entangle-photo.org    -o-    https://www.instagram.com/dberrange :|




reply via email to

[Prev in Thread] Current Thread [Next in Thread]