Re: GObject Introspection as part of the GNOME platform
- From: Mathieu Lacage <mathieu lacage sophia inria fr>
- To: muppet <scott asofyet org>
- Cc: gtk-devel-list gnome org
- Subject: Re: GObject Introspection as part of the GNOME platform
- Date: Wed, 11 Mar 2009 20:17:04 +0100
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]