Re: GObject Introspection as part of the GNOME platform



On Wed, 2009-03-11 at 11:08 -0400, muppet wrote:
> Johan Dahlin wrote:
> > As far as I can see there aren't any easy solutions.
> > We're depending on libffi to calculate struct sizes for the typelib
> > which is very
> > much host and compiler dependent.  g-ir-compile really needs to run on the
> > target system the way things are setup right now. The same applies
> > for the small generated program which introspects signals & properties, but
> > that's probably easier to solve.
> >
> > In my opinion, supporting cross-compilation shouldn't be a blocker for
> > integration into glib proper. It's more of a 'nice feature' to support.
> 
> I'm sure people putting gnome on phones will disagree.
> 
> You could do tricks like using the cross compiler to generate assembly instead
> of machine code from specially-crafted, generated C code, and then parse the
> resulting assembly to extract the structure sizes and offsets.

Maybe it is really obvious but, why are you not using the output of
readelf -wi ? It's fairly trivial to parse and all of this could be done
on the host without any working target provided you have a
cross-compiler.

A sample output parser is attached to this email. Feel free to consider
it in the public domain and rip it out if you wish to. (at some point, I
had a working C-based dwarf2/3 debuginfo parser which did not rely on
readelf, and I could share that if there was really interest but,
really, I don't think it would be of much use).

regards,
Mathieu
#!/usr/bin/env python

import sys
import re
import getopt
import os


class Data:
    def __init__(self, data):
        self.data = data

class DebugData:
    class Item:
        def __init__(self):
            self.type = ''
            self.ref = 0
            self.level = 0
            self.attributes = {}
    def __init__(self, debug_filename):
        file = os.popen ('readelf -wi ' + debug_filename, 'r')
        self.__lines = file.readlines ()
        self.__current = 0
        self.__re1 = re.compile ('<([^>]+)><([^>]+)>:[^A]*Abbrev Number:.*\d+.*\((\w+)\)')
        self.__re2 = re.compile ('<[^>]+>[^D]*(DW_AT_\w+)([^:]*:)+ <?0?x?([^ \t><\)]+)[ >\t\)]*$')
        return
    def rewind (self):
        self.__current = 0
        return
    def read_line (self):
        if self.__current == len (self.__lines):
            return ''
        line = self.__lines[self.__current]
        self.__current = self.__current + 1
        return line
    def write_back_line (self):
        self.__current = self.__current - 1
        return
    def write_back_one (self, item):
        self.__current = self.__current - 1 - len (item.attributes.keys ())
        return
    def read_one (self):
        item = DebugData.Item ()
        while 1:
            line = self.read_line ()
            if line == '':
                if item.type == '':
                    return None
                else:
                    return item
            result = self.__re1.search (line)
            if result is None:
                continue
            item.level = result.group (1)
            item.ref = result.group (2)
            item.type = result.group (3)
            while 1:
                line = self.read_line ()
                result = self.__re1.search (line)
                if result is not None:
                    self.write_back_line ()
                    return item
                result = self.__re2.search (line)
                if result is None:
                    self.write_back_line ()
                    return item
                item.attributes[result.group (1)] = result.group (3)
        return item
    def find_struct (self, struct_type_name):
        return self.find_by_name ('DW_TAG_structure_type', struct_type_name)
    def find_by_name (self, type, name):
        item = self.read_one ()
        while item is not None:
            if item.type == type and \
                    item.attributes.has_key ('DW_AT_name') and \
                    item.attributes['DW_AT_name'] == name:
                return item
            item = self.read_one ()
        return item
    def find_by_ref (self, ref):
        item = self.read_one ()
        while item is not None:
            if item.ref == ref:
                return item
            item = self.read_one ()
        return item
    def find_member (self, member_name, parent):
        sub_item = self.read_one ()
        while sub_item is not None:
            if sub_item.level == parent.level:
                self.write_back_one ()
                return None
            if sub_item.type == 'DW_TAG_member' and \
                    sub_item.attributes.has_key ('DW_AT_name') and \
                    sub_item.attributes['DW_AT_name'] == member_name:
                return Data (sub_item.attributes['DW_AT_data_member_location'])
            sub_item = self.read_one ()
        return None
    # public methods below
    def get_struct_member_offset (self, struct_type_name, member_name):
        self.rewind ()
        item = self.find_struct (struct_type_name)
        if item is None:
            return None
        return self.find_member (member_name, item)
    def get_struct_size (self, struct_type_name):
        self.rewind ()
        item = self.find_struct (struct_type_name)
        if item is None:
            return None
        if not item.attributes.has_key ('DW_AT_byte_size'):
            return None
        return Data (item.attributes['DW_AT_byte_size'])    
    def get_typedef_member_offset (self, typename, member):
        self.rewind ()
        item = self.find_by_name ('DW_TAG_typedef', typename)
        if item is None:
            return None
        if not item.attributes.has_key ('DW_AT_type'):
            return None
        ref = item.attributes['DW_AT_type']
        self.rewind ()
        item = self.find_by_ref (ref)
        if item is None:
            return None
        return self.find_member (member, item)

        
def usage():
    print ''

def main(argv):
    config_filename = ''
    debug_filename = ''
    try:
        opts, args = getopt.getopt(argv, 'hc:d:',
                                   ['help', 'config=', 'debug='])
    except getopt.GetoptError:
        usage()
        sys.exit(2)
    for opt, arg in opts:
        if opt in ('-h', '--help'):
            usage()
            sys.exit()
        elif opt in ('-c', '--config'):
            config_filename = arg
        elif opt in ('-d', '--debug'):
            debug_filename = arg

    debug = DebugData (debug_filename)
    config = open (config_filename, 'w')
    data = debug.get_struct_size ('rtld_global')
    if data is None:
        sys.exit (1)
    config.write ('#define CONFIG_RTLD_GLOBAL_SIZE ' + str(data.data) + '\n')

    data = debug.get_struct_size ('rtld_global_ro')
    if data is None:
        sys.exit (1)
    config.write ('#define CONFIG_RTLD_GLOBAL_RO_SIZE ' + str(data.data) + '\n')

    data = debug.get_struct_member_offset ('rtld_global', '_dl_error_catch_tsd')
    if data is None:
        sys.exit (1)
    config.write ('#define CONFIG_DL_ERROR_CATCH_TSD_OFFSET ' + str(data.data) + '\n')

    data = debug.get_struct_size ('pthread')
    if data is None:
        sys.exit (1)
    config.write ('#define CONFIG_TCB_SIZE ' + str(data.data) + '\n')

    data = debug.get_typedef_member_offset ('tcbhead_t', 'tcb')
    if data is None:
        sys.exit (1)
    config.write ('#define CONFIG_TCB_TCB_OFFSET ' + str(data.data) + '\n')

    data = debug.get_typedef_member_offset ('tcbhead_t', 'dtv')
    if data is None:
        sys.exit (1)
    config.write ('#define CONFIG_TCB_DTV_OFFSET ' + str(data.data) + '\n')

    data = debug.get_typedef_member_offset ('tcbhead_t', 'self')
    if data is None:
        sys.exit (1)
    config.write ('#define CONFIG_TCB_SELF_OFFSET ' + str(data.data) + '\n')

    data = debug.get_typedef_member_offset ('tcbhead_t', 'sysinfo')
    if data is None:
        sys.exit (1)
    config.write ('#define CONFIG_TCB_SYSINFO_OFFSET ' + str(data.data) + '\n')

if __name__ == "__main__":
    main(sys.argv[1:])








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