From fede1058ffbf7039b30d9fa95e4f54fe3c71b28f Mon Sep 17 00:00:00 2001 From: David Tardon Date: Nov 21 2011 05:35:46 +0000 Subject: add gdb pretty printers --- diff --git a/gdb-pretty-printers.patch b/gdb-pretty-printers.patch new file mode 100644 index 0000000..ba4047b --- /dev/null +++ b/gdb-pretty-printers.patch @@ -0,0 +1,2006 @@ +From b852c77e068a8f3dedf550470be99d913241d7a8 Mon Sep 17 00:00:00 2001 +From: David Tardon +Date: Fri, 29 Jul 2011 13:22:35 +0200 +Subject: [PATCH 1/2] add gdb pretty printers + +--- + solenv/gdb/libreoffice/__init__.py | 30 ++ + solenv/gdb/libreoffice/cppu.py | 164 ++++++++ + solenv/gdb/libreoffice/sal.py | 121 ++++++ + solenv/gdb/libreoffice/svl.py | 125 ++++++ + solenv/gdb/libreoffice/sw.py | 119 ++++++ + solenv/gdb/libreoffice/tl.py | 371 ++++++++++++++++++ + solenv/gdb/libreoffice/util/__init__.py | 30 ++ + solenv/gdb/libreoffice/util/compatibility.py | 38 ++ + solenv/gdb/libreoffice/util/printing.py | 139 +++++++ + solenv/gdb/libreoffice/util/string.py | 93 +++++ + solenv/gdb/libreoffice/util/uno.py | 539 ++++++++++++++++++++++++++ + 11 files changed, 1769 insertions(+), 0 deletions(-) + create mode 100644 solenv/gdb/libreoffice/__init__.py + create mode 100644 solenv/gdb/libreoffice/cppu.py + create mode 100644 solenv/gdb/libreoffice/sal.py + create mode 100644 solenv/gdb/libreoffice/svl.py + create mode 100644 solenv/gdb/libreoffice/sw.py + create mode 100644 solenv/gdb/libreoffice/tl.py + create mode 100644 solenv/gdb/libreoffice/util/__init__.py + create mode 100644 solenv/gdb/libreoffice/util/compatibility.py + create mode 100644 solenv/gdb/libreoffice/util/printing.py + create mode 100644 solenv/gdb/libreoffice/util/string.py + create mode 100644 solenv/gdb/libreoffice/util/uno.py + +diff --git a/solenv/gdb/libreoffice/__init__.py b/solenv/gdb/libreoffice/__init__.py +new file mode 100644 +index 0000000..90d8012 +--- /dev/null ++++ b/solenv/gdb/libreoffice/__init__.py +@@ -0,0 +1,30 @@ ++# Version: MPL 1.1 / GPLv3+ / LGPLv3+ ++# ++# The contents of this file are subject to the Mozilla Public License Version ++# 1.1 (the "License"); you may not use this file except in compliance with ++# the License or as specified alternatively below. You may obtain a copy of ++# the License at http://www.mozilla.org/MPL/ ++# ++# Software distributed under the License is distributed on an "AS IS" basis, ++# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License ++# for the specific language governing rights and limitations under the ++# License. ++# ++# The Initial Developer of the Original Code is ++# David Tardon, Red Hat Inc. ++# Portions created by the Initial Developer are Copyright (C) 2010 the ++# Initial Developer. All Rights Reserved. ++# ++# Major Contributor(s): ++# ++# For minor contributions see the git repository. ++# ++# Alternatively, the contents of this file may be used under the terms of ++# either the GNU General Public License Version 3 or later (the "GPLv3+"), or ++# the GNU Lesser General Public License Version 3 or later (the "LGPLv3+"), ++# in which case the provisions of the GPLv3+ or the LGPLv3+ are applicable ++# instead of those above. ++ ++ ++ ++# vim:set shiftwidth=4 softtabstop=4 expandtab: +diff --git a/solenv/gdb/libreoffice/cppu.py b/solenv/gdb/libreoffice/cppu.py +new file mode 100644 +index 0000000..8707ea5 +--- /dev/null ++++ b/solenv/gdb/libreoffice/cppu.py +@@ -0,0 +1,164 @@ ++# Version: MPL 1.1 / GPLv3+ / LGPLv3+ ++# ++# The contents of this file are subject to the Mozilla Public License Version ++# 1.1 (the "License"); you may not use this file except in compliance with ++# the License or as specified alternatively below. You may obtain a copy of ++# the License at http://www.mozilla.org/MPL/ ++# ++# Software distributed under the License is distributed on an "AS IS" basis, ++# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License ++# for the specific language governing rights and limitations under the ++# License. ++# ++# The Initial Developer of the Original Code is ++# David Tardon, Red Hat Inc. ++# Portions created by the Initial Developer are Copyright (C) 2010 the ++# Initial Developer. All Rights Reserved. ++# ++# Major Contributor(s): ++# ++# For minor contributions see the git repository. ++# ++# Alternatively, the contents of this file may be used under the terms of ++# either the GNU General Public License Version 3 or later (the "GPLv3+"), or ++# the GNU Lesser General Public License Version 3 or later (the "LGPLv3+"), ++# in which case the provisions of the GPLv3+ or the LGPLv3+ are applicable ++# instead of those above. ++ ++from libreoffice.util import printing ++from libreoffice.util.uno import TypeClass, make_uno_type, uno_cast ++ ++class UnoAnyPrinter(object): ++ '''Prints UNO any''' ++ ++ def __init__(self, typename, value): ++ self.value = value ++ self.typename = typename.replace('com::sun::star::', '') ++ ++ def to_string(self): ++ if self._is_set(): ++ return ('%s %s' % (self.typename, self._make_string())) ++ else: ++ return "empty %s" % self.typename ++ ++ def _is_set(self): ++ return self.value['pType'].dereference()['eTypeClass'] != TypeClass.VOID ++ ++ def _make_string(self): ++ ptr = self.value['pData'] ++ assert ptr ++ type_desc = self.value['pType'] ++ assert type_desc ++ type = make_uno_type(type_desc.dereference()) ++ assert type ++ return str(uno_cast(type, ptr).dereference()) ++ ++class UnoReferencePrinter(object): ++ '''Prints reference to a UNO interface''' ++ ++ def __init__(self, typename, value): ++ self.value = value ++ self.typename = typename.replace('com::sun::star::', '') ++ ++ def to_string(self): ++ iface = self.value['_pInterface'] ++ if iface: ++ impl = iface.cast(self._itype()).dereference() ++ return '%s to %s' % (self.typename, str(impl)) ++ else: ++ return "empty %s" % self.typename ++ ++ def _itype(self): ++ return self.value.type.template_argument(0).pointer() ++ ++class UnoSequencePrinter(object): ++ '''Prints UNO Sequence''' ++ ++ class iterator(object): ++ '''Sequence iterator''' ++ ++ def __init__(self, first, size): ++ self.item = first ++ self.size = size ++ self.count = 0 ++ ++ def __iter__(self): ++ return self ++ ++ def next(self): ++ if self.count == self.size: ++ raise StopIteration ++ count = self.count ++ self.count = self.count + 1 ++ elem = self.item.dereference() ++ self.item = self.item + 1 ++ return ('[%d]' % count, elem) ++ ++ ++ def __init__(self, typename, value): ++ self.value = value ++ self.typename = typename.replace('com::sun::star::', '') ++ ++ def to_string(self): ++ pimpl = self.value['_pSequence'] ++ if pimpl: ++ impl = pimpl.dereference() ++ elems = impl['nElements'] ++ if elems == 0: ++ return "empty %s" % self.typename ++ else: ++ return "%s of length %d" % (self.typename, elems) ++ else: ++ return "uninitialized %s" % self.typename ++ ++ def children(self): ++ pimpl = self.value['_pSequence'] ++ if pimpl: ++ impl = pimpl.dereference() ++ elemtype = self.value.type.template_argument(0) ++ elements = impl['elements'].cast(elemtype.pointer()) ++ return self.iterator(elements, int(impl['nElements'])) ++ else: ++ # TODO is that the best thing to do here? ++ return None ++ ++ def display_hint(self): ++ if self.value['_pSequence']: ++ return 'array' ++ else: ++ return None ++ ++class UnoTypePrinter(object): ++ '''Prints UNO Type''' ++ ++ def __init__(self, typename, value): ++ self.value = value ++ self.typename = typename.replace('com::sun::star::', '') ++ ++ def to_string(self): ++ uno = make_uno_type(self.value) ++ if uno: ++ return "%s %s" % (self.typename, uno.tag) ++ # return "%s %s" % (self.typename, uno.typename) ++ else: ++ return "invalid %s" % self.typename ++ ++printer = None ++ ++def build_pretty_printers(): ++ global printer ++ ++ printer = printing.Printer("libreoffice/cppu") ++ ++ # basic UNO stuff ++ printer.add('_uno_Any', UnoAnyPrinter) ++ printer.add('com::sun::star::uno::Any', UnoAnyPrinter) ++ printer.add('com::sun::star::uno::Sequence', UnoSequencePrinter) ++ printer.add('com::sun::star::uno::Type', UnoTypePrinter) ++ ++def register_pretty_printers(obj): ++ printing.register_pretty_printer(printer, obj) ++ ++build_pretty_printers() ++ ++# vim:set shiftwidth=4 softtabstop=4 expandtab: +diff --git a/solenv/gdb/libreoffice/sal.py b/solenv/gdb/libreoffice/sal.py +new file mode 100644 +index 0000000..e5a5d32 +--- /dev/null ++++ b/solenv/gdb/libreoffice/sal.py +@@ -0,0 +1,121 @@ ++# Version: MPL 1.1 / GPLv3+ / LGPLv3+ ++# ++# The contents of this file are subject to the Mozilla Public License Version ++# 1.1 (the "License"); you may not use this file except in compliance with ++# the License or as specified alternatively below. You may obtain a copy of ++# the License at http://www.mozilla.org/MPL/ ++# ++# Software distributed under the License is distributed on an "AS IS" basis, ++# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License ++# for the specific language governing rights and limitations under the ++# License. ++# ++# The Initial Developer of the Original Code is ++# David Tardon, Red Hat Inc. ++# Portions created by the Initial Developer are Copyright (C) 2010 the ++# Initial Developer. All Rights Reserved. ++# ++# Major Contributor(s): ++# ++# For minor contributions see the git repository. ++# ++# Alternatively, the contents of this file may be used under the terms of ++# either the GNU General Public License Version 3 or later (the "GPLv3+"), or ++# the GNU Lesser General Public License Version 3 or later (the "LGPLv3+"), ++# in which case the provisions of the GPLv3+ or the LGPLv3+ are applicable ++# instead of those above. ++ ++import gdb ++ ++from libreoffice.util import printing ++from libreoffice.util.string import StringPrinterHelper ++ ++class RtlStringPrinter(StringPrinterHelper): ++ '''Prints rtl_String or rtl_uString''' ++ ++ def __init__(self, typename, val, encoding = None): ++ super(RtlStringPrinter, self).__init__(typename, val, encoding) ++ ++ def data(self): ++ return self.val['buffer'] ++ ++ def length(self): ++ return self.val['length'] ++ ++class StringPrinter(StringPrinterHelper): ++ '''Prints rtl:: strings and string buffers''' ++ ++ def __init__(self, typename, val, encoding = None): ++ super(StringPrinter, self).__init__(typename, val, encoding) ++ ++ def valid(self): ++ return self.val['pData'] ++ ++ def data(self): ++ assert self.val['pData'] ++ return self.val['pData'].dereference()['buffer'] ++ ++ def length(self): ++ assert self.val['pData'] ++ return self.val['pData'].dereference()['length'] ++ ++class SalUnicodePrinter(StringPrinterHelper): ++ '''Prints a sal_Unicode*''' ++ ++ def __init__(self, typename, val): ++ super(SalUnicodePrinter, self).__init__(typename, val, 'utf-16') ++ ++ def data(self): ++ return self.val ++ ++ @staticmethod ++ def query(type): ++ type = type.unqualified() ++ if type.code != gdb.TYPE_CODE_PTR: ++ return False ++ return str(type.target()) == 'sal_Unicode' ++ ++class RtlReferencePrinter(object): ++ '''Prints rtl::Reference''' ++ ++ def __init__(self, typename, val): ++ self.typename = typename ++ self.val = val ++ ++ def to_string(self): ++ print("RtlReferencePrinter:to_string") ++ pointee = self.val['m_pBody'] ++ if pointee: ++ val = pointee.dereference() ++ return '%s to %s' % (self.typename, str(val)) ++ else: ++ return "empty %s" % self.typename ++ ++printer = None ++ ++def build_pretty_printers(): ++ global printer ++ ++ printer = printing.Printer("libreoffice/sal") ++ ++ # strings and string buffers ++ printer.add('_rtl_String', RtlStringPrinter) ++ printer.add('_rtl_uString', lambda name, val: RtlStringPrinter(name, ++ val, 'utf-16le')) ++ printer.add('rtl::OString', StringPrinter) ++ printer.add('rtl::OUString', lambda name, val: StringPrinter(name, val, 'utf-16')) ++ printer.add('rtl::OStringBuffer', StringPrinter) ++ printer.add('rtl::OUStringBuffer', lambda name, val: StringPrinter(name, val, 'utf-16')) ++ printer.add('sal_Unicode', SalUnicodePrinter, SalUnicodePrinter.query) ++ ++ # other stuff ++ printer.add('rtl::Reference', RtlReferencePrinter) ++ ++ return printer ++ ++def register_pretty_printers(obj): ++ printing.register_pretty_printer(printer, obj) ++ ++build_pretty_printers() ++ ++# vim:set shiftwidth=4 softtabstop=4 expandtab: +diff --git a/solenv/gdb/libreoffice/svl.py b/solenv/gdb/libreoffice/svl.py +new file mode 100644 +index 0000000..639f7c5 +--- /dev/null ++++ b/solenv/gdb/libreoffice/svl.py +@@ -0,0 +1,125 @@ ++# Version: MPL 1.1 / GPLv3+ / LGPLv3+ ++# ++# The contents of this file are subject to the Mozilla Public License Version ++# 1.1 (the "License"); you may not use this file except in compliance with ++# the License or as specified alternatively below. You may obtain a copy of ++# the License at http://www.mozilla.org/MPL/ ++# ++# Software distributed under the License is distributed on an "AS IS" basis, ++# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License ++# for the specific language governing rights and limitations under the ++# License. ++# ++# The Initial Developer of the Original Code is ++# David Tardon, Red Hat Inc. ++# Portions created by the Initial Developer are Copyright (C) 2010 the ++# Initial Developer. All Rights Reserved. ++# ++# Major Contributor(s): ++# ++# For minor contributions see the git repository. ++# ++# Alternatively, the contents of this file may be used under the terms of ++# either the GNU General Public License Version 3 or later (the "GPLv3+"), or ++# the GNU Lesser General Public License Version 3 or later (the "LGPLv3+"), ++# in which case the provisions of the GPLv3+ or the LGPLv3+ are applicable ++# instead of those above. ++ ++import gdb ++ ++from libreoffice.util import printing ++ ++class SvArrayPrinter(object): ++ '''Prints macro-declared arrays from svl module''' ++ ++ def __init__(self, typename, value): ++ self.typename = typename ++ self.value = value ++ ++ def to_string(self): ++ if int(self.value['nA']): ++ return "%s of length %d" % (self.typename, self.value['nA']) ++ else: ++ return "empty " + self.typename ++ ++ def children(self): ++ return self._iterator(self.value['pData'], self.value['nA']) ++ ++ def display_hint(self): ++ return 'array' ++ ++ class _iterator(object): ++ ++ def __init__(self, data, count): ++ self.data = data ++ self.count = count ++ self.pos = 0 ++ self._check_invariant() ++ ++ def __iter__(self): ++ return self ++ ++ def next(self): ++ if self.pos == self.count: ++ raise StopIteration() ++ ++ pos = self.pos ++ elem = self.data[pos] ++ self.pos = self.pos + 1 ++ ++ self._check_invariant() ++ return (str(pos), elem) ++ ++ def _check_invariant(self): ++ assert self.count >= 0 ++ if self.count > 0: ++ assert self.data ++ assert self.pos >= 0 ++ assert self.pos <= self.count ++ ++ @staticmethod ++ def query(type): ++ if type.code == gdb.TYPE_CODE_REF: ++ type = type.target() ++ type = type.unqualified().strip_typedefs() ++ ++ if not type.tag: ++ return False ++ ++ ushort = gdb.lookup_type('sal_uInt16') ++ conforming = True ++ for field in type.fields(): ++ if field.name == 'pData': ++ conforming = field.type.code == gdb.TYPE_CODE_PTR ++ elif field.name == 'nFree': ++ conforming = field.type == ushort ++ elif field.name == 'nA': ++ conforming = field.type == ushort ++ else: ++ conforming = False ++ if not conforming: ++ return False ++ ++ try: ++ gdb.lookup_type('FnForEach_' + type.tag) ++ except RuntimeError: ++ return False ++ ++ return True ++ ++printer = None ++ ++def build_pretty_printers(): ++ global printer ++ ++ printer = printing.Printer("libreoffice/svl") ++ ++ # macro-based arrays from svl module ++ printer.add('SvArray', SvArrayPrinter, SvArrayPrinter.query) ++ ++def register_pretty_printers(obj): ++ printing.register_pretty_printer(printer, obj) ++ ++build_pretty_printers() ++ ++# vim:set shiftwidth=4 softtabstop=4 expandtab: +diff --git a/solenv/gdb/libreoffice/sw.py b/solenv/gdb/libreoffice/sw.py +new file mode 100644 +index 0000000..761c153 +--- /dev/null ++++ b/solenv/gdb/libreoffice/sw.py +@@ -0,0 +1,119 @@ ++# Version: MPL 1.1 / GPLv3+ / LGPLv3+ ++# ++# The contents of this file are subject to the Mozilla Public License Version ++# 1.1 (the "License"); you may not use this file except in compliance with ++# the License or as specified alternatively below. You may obtain a copy of ++# the License at http://www.mozilla.org/MPL/ ++# ++# Software distributed under the License is distributed on an "AS IS" basis, ++# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License ++# for the specific language governing rights and limitations under the ++# License. ++# ++# The Initial Developer of the Original Code is ++# David Tardon, Red Hat Inc. ++# Portions created by the Initial Developer are Copyright (C) 2010 the ++# Initial Developer. All Rights Reserved. ++# ++# Major Contributor(s): ++# ++# For minor contributions see the git repository. ++# ++# Alternatively, the contents of this file may be used under the terms of ++# either the GNU General Public License Version 3 or later (the "GPLv3+"), or ++# the GNU Lesser General Public License Version 3 or later (the "LGPLv3+"), ++# in which case the provisions of the GPLv3+ or the LGPLv3+ are applicable ++# instead of those above. ++ ++from libreoffice.util import printing ++ ++ ++class BigPtrArrayPrinter(object): ++ '''Prints BigPtrArray.''' ++ ++ def __init__(self, typename, value): ++ self.typename = typename ++ self.value = value ++ ++ def to_string(self): ++ length = self.value['nSize'] ++ if length > 0: ++ return "%s of length %d" % (self.typename, length) ++ else: ++ return "empty %s" % self.typename ++ ++ def children(self): ++ return self._iterator(self.value) ++ ++ def display_hint(self): ++ return 'array' ++ ++ ++ class _iterator(object): ++ ++ def __init__(self, array): ++ self.blocks = array['ppInf'] ++ self.count = array['nSize'] ++ self.pos = 0 ++ self.block_count = array['nBlock'] ++ self.block_pos = 0 ++ self.block = None ++ self._next_block(False) ++ self._check_invariant() ++ ++ def __iter__(self): ++ return self ++ ++ def next(self): ++ if self.pos == self.count: ++ raise StopIteration() ++ ++ name = str(self.pos) ++ value = self.block['pData'][self.pos - self.block['nStart']] ++ if self.pos == self.block['nEnd']: ++ self._next_block() ++ self.pos += 1 ++ ++ self._check_invariant() ++ return (name, value) ++ ++ def _next_block(self, advance = True): ++ if advance: ++ self.block_pos += 1 ++ ++ if self.block_pos == self.block_count: ++ return ++ ++ pblock = self.blocks[self.block_pos] ++ assert pblock ++ block = pblock.dereference() ++ start = block['nStart'] ++ end = block['nEnd'] ++ assert end - start + 1 == block['nElem'] ++ if self.block: ++ assert start == self.block['nEnd'] + 1 ++ assert end <= self.count ++ else: ++ assert start == 0 ++ self.block = block ++ ++ def _check_invariant(self): ++ assert self.pos <= self.count ++ assert self.block_pos <= self.block_count ++ if self.pos == 0 and self.pos < self.count: ++ assert self.block != None ++ ++printer = None ++ ++def build_pretty_printers(): ++ global printer ++ ++ printer = printing.Printer("libreoffice/sw") ++ printer.add('BigPtrArray', BigPtrArrayPrinter) ++ ++def register_pretty_printers(obj): ++ printing.register_pretty_printer(printer, obj) ++ ++build_pretty_printers() ++ ++# vim:set shiftwidth=4 softtabstop=4 expandtab: +diff --git a/solenv/gdb/libreoffice/tl.py b/solenv/gdb/libreoffice/tl.py +new file mode 100644 +index 0000000..62c5ff5 +--- /dev/null ++++ b/solenv/gdb/libreoffice/tl.py +@@ -0,0 +1,371 @@ ++# Version: MPL 1.1 / GPLv3+ / LGPLv3+ ++# ++# The contents of this file are subject to the Mozilla Public License Version ++# 1.1 (the "License"); you may not use this file except in compliance with ++# the License or as specified alternatively below. You may obtain a copy of ++# the License at http://www.mozilla.org/MPL/ ++# ++# Software distributed under the License is distributed on an "AS IS" basis, ++# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License ++# for the specific language governing rights and limitations under the ++# License. ++# ++# The Initial Developer of the Original Code is ++# David Tardon, Red Hat Inc. ++# Portions created by the Initial Developer are Copyright (C) 2010 the ++# Initial Developer. All Rights Reserved. ++# ++# Major Contributor(s): ++# ++# For minor contributions see the git repository. ++# ++# Alternatively, the contents of this file may be used under the terms of ++# either the GNU General Public License Version 3 or later (the "GPLv3+"), or ++# the GNU Lesser General Public License Version 3 or later (the "LGPLv3+"), ++# in which case the provisions of the GPLv3+ or the LGPLv3+ are applicable ++# instead of those above. ++ ++import gdb ++ ++from libreoffice.util import printing ++from libreoffice.util.string import StringPrinterHelper ++ ++class StringPrinter(StringPrinterHelper): ++ '''Prints ByteString or UniString''' ++ ++ def __init__(self, typename, val, encoding = None): ++ super(StringPrinter, self).__init__(typename, val, encoding) ++ ++ def valid(self): ++ data = self.val['mpData'] ++ # mnRefCount is not a good indicator: it seems there could be ++ # cases where it is negative (-7FFFFFED) ++ return data #and data.dereference()['mnRefCount'] > 0 ++ ++ def data(self): ++ assert self.val['mpData'] ++ return self.val['mpData'].dereference()['maStr'] ++ ++ def length(self): ++ assert self.val['mpData'] ++ return self.val['mpData'].dereference()['mnLen'] ++ ++class BigIntPrinter(object): ++ '''Prints big integer''' ++ ++ def __init__(self, typename, val): ++ self.val = val ++ ++ def to_string(self): ++ if self.val['bIsSet']: ++ if self.val['bIsBig']: ++ return self._value() ++ else: ++ return self.val['nVal'] ++ else: ++ return "unset %s" % self.typename ++ ++ def _value(self): ++ len = self.val['nLen'] ++ digits = self.val['nNum'] ++ dsize = digits.dereference().type.sizeof * 8 ++ num = 0 ++ # The least significant byte is on index 0 ++ for i in reversed(range(0, len)): ++ num <<= dsize ++ num += digits[i] ++ return num ++ ++class ColorPrinter(object): ++ '''Prints color as rgb(r, g, b) or rgba(r, g, b, a)''' ++ ++ def __init__(self, typename, val): ++ self.val = val ++ ++ def to_string(self): ++ color = self.val['mnColor'] ++ b = color & 0xff ++ g = (color >> 8) & 0xff ++ r = (color >> 16) & 0xff ++ a = (color >> 24) & 0xff ++ if a: ++ return "rgba(%d, %d, %d, %d)" % (r, g, b, a) ++ else: ++ return "rgb(%d, %d, %d)" % (r, g, b) ++ ++class FractionPrinter(object): ++ '''Prints fraction''' ++ ++ def __init__(self, typename, val): ++ self.typename = typename ++ self.val = val ++ ++ def to_string(self): ++ numerator = self.val['nNumerator'] ++ denominator = self.val['nDenominator'] ++ if denominator > 0: ++ return "%d/%d" % (numerator, denominator) ++ else: ++ return "invalid %s" % self.typename ++ ++class DateTimeImpl(object): ++ ++ def __init__(self, date, time): ++ self.date = date ++ self.time = time ++ ++ def __str__(self): ++ result = '' ++ if self.date: ++ result += str(self.date) ++ if self.time: ++ result += ' ' ++ if self.time: ++ result += str(self.time) ++ return result ++ ++ @staticmethod ++ def parse(val): ++ return DateTimeImpl(DateImpl.parse(val), TimeImpl.parse(val)) ++ ++class DateTimePrinter(object): ++ '''Prints date and time''' ++ ++ def __init__(self, typename, val): ++ self.val = val ++ ++ def to_string(self): ++ return str(DateTimeImpl.parse(self.val)) ++ ++class DateImpl(DateTimeImpl): ++ ++ def __init__(self, year, month, day): ++ super(DateImpl, self).__init__(self, None) ++ self.year = year ++ self.month = month ++ self.day = day ++ ++ def __str__(self): ++ return "%d-%d-%d" % (self.year, self.month, self.day) ++ ++ @staticmethod ++ def parse(val): ++ date = val['nDate'] ++ d = date % 100 ++ m = (date / 100) % 100 ++ y = date / 10000 ++ return DateImpl(y, m, d) ++ ++class DatePrinter(object): ++ '''Prints date''' ++ ++ def __init__(self, typename, val): ++ self.val = val ++ ++ def to_string(self): ++ return str(DateImpl.parse(self.val)) ++ ++class TimeImpl(DateTimeImpl): ++ ++ def __init__(self, hour, minute, second, hundreth_of_second = 0): ++ super(TimeImpl, self).__init__(None, self) ++ self.hour = hour ++ self.minute = minute ++ self.second = second ++ self.hundreth_of_second = hundreth_of_second ++ ++ def __str__(self): ++ decimal = '' ++ if self.hundreth_of_second != 0: ++ decimal = '.%d' % self.hundreth_of_second ++ return "%d:%d:%d%s" % (self.hour, self.minute, self.second, decimal) ++ ++ @staticmethod ++ def parse(val): ++ time = val['nTime'] ++ h = time / 1000000 ++ m = (time / 10000) % 100 ++ s = (time / 100) % 100 ++ s_100 = time % 100 ++ return TimeImpl(h, m, s, s_100) ++ ++class TimePrinter(object): ++ '''Prints time''' ++ ++ def __init__(self, typename, val): ++ self.val = val ++ ++ def to_string(self): ++ return str(TimeImpl.parse(self.val)) ++ ++class IteratorHelper(object): ++ '''Implements a container iterator useable for both 'linear' ++ containers (like DynArray or List) and Tables ++ ''' ++ ++ def __init__(self, block, count, type = None): ++ self.count = count ++ self.type = type ++ self.pos = 0 ++ self.block = None ++ self.block_count = 0 ++ self.block_pos = 0 ++ if block: ++ self._next_block(block) ++ ++ self._check_invariant() ++ ++ def __iter__(self): ++ return self ++ ++ def next(self): ++ if self.pos == self.count: ++ raise StopIteration() ++ ++ if self.block_pos == self.block_count: ++ self._next_block(self.block['pNext']) ++ ++ name = self.name() ++ val = self.value() ++ self.advance() ++ ++ self._check_invariant() ++ return (name, val) ++ ++ def _next_block(self, block): ++ assert block ++ ++ self.block = block.dereference() ++ self.block_pos = 0 ++ self.block_count = block['nCount'] ++ ++ assert self.block_count <= block['nSize'] ++ assert self.block_count + self.pos <= self.count ++ ++ def _check_invariant(self): ++ assert self.count >= 0 ++ assert self.pos >= 0 ++ assert self.pos <= self.count ++ assert self.block_count >= 0 ++ if self.pos < self.count: ++ assert self.block_count > 0 ++ assert self.block != None ++ assert self.block_count <= self.count ++ assert self.block_pos >= 0 ++ assert self.block_pos <= self.block_count ++ ++class NoItemType(Exception): ++ pass ++ ++class ContainerHelper(object): ++ '''Provides support for specialized container printers''' ++ ++ def __init__(self, typename, val, iterator): ++ self.typename = typename ++ self.val = val ++ self.iterator = iterator ++ ++ def to_string(self): ++ size = self.val['nCount'] ++ if size > 0: ++ return "%s of length %d" % (self.typename, size) ++ elif size == 0: ++ return "empty %s" % self.typename ++ else: ++ return "invalid %s" % self.typename ++ ++ def children(self): ++ count = self.val.cast(gdb.lookup_type('Container'))['nCount'] ++ return self.iterator(self.val['pFirstBlock'], count) ++ ++class LinearIterator(IteratorHelper): ++ '''Is iterator for 'linear' container''' ++ ++ def __init__(self, block, count, type = None): ++ super(LinearIterator, self).__init__(block, count, type) ++ ++ def name(self): ++ return str(self.pos) ++ ++ def value(self): ++ nodes = self.block['pNodes']#.cast(self.type.pointer()) ++ return nodes[self.block_pos] ++ ++ def advance(self): ++ self.pos += 1 ++ self.block_pos += 1 ++ ++class LinearContainerPrinter(ContainerHelper): ++ '''Prints 'linear' container, like DynArray or List''' ++ ++ def __init__(self, typename, val): ++ super(LinearContainerPrinter, self).__init__(typename, val, LinearIterator) ++ ++ def display_hint(self): ++ return 'array' ++ ++class TableIterator(IteratorHelper): ++ '''Is iterator for Table''' ++ ++ def __init__(self, block, count, type = None): ++ super(TableIterator, self).__init__(block, count, type) ++ # ULONG doesn't work on 64-bit for some reason (gdb says it has ++ # size 4 and it's not a typedef to sal_uIntPtr) ++ self._key_type = gdb.lookup_type('sal_uIntPtr') ++ self.is_key = True ++ ++ def name(self): ++ return '' ++ ++ def value(self): ++ nodes = self.block['pNodes']#.cast(self.type.pointer()) ++ val = nodes[self.block_pos] ++ if self.is_key: ++ val = str(val.cast(self._key_type)) ++ return val ++ ++ def advance(self): ++ self.pos += 1 ++ self.block_pos += 1 ++ self.is_key = not self.is_key ++ ++class TablePrinter(ContainerHelper): ++ '''Prints table''' ++ ++ def __init__(self, typename, val): ++ super(TablePrinter, self).__init__(typename, val, TableIterator) ++ ++ def display_hint(self): ++ return 'map' ++ ++printer = None ++ ++def build_pretty_printers(): ++ global printer ++ ++ printer = printing.Printer('libreoffice/tl') ++ ++ # old-style strings ++ printer.add('ByteString', StringPrinter) ++ printer.add('String', lambda name, val: StringPrinter(name, val, 'utf-16')) ++ ++ # old-style containers ++ printer.add('DynArray', LinearContainerPrinter) ++ printer.add('List', LinearContainerPrinter) ++ printer.add('Stack', LinearContainerPrinter) ++ printer.add('Table', TablePrinter) ++ ++ # various types ++ printer.add('BigInt', BigIntPrinter) ++ printer.add('Color', ColorPrinter) ++ printer.add('Fraction', FractionPrinter) ++ printer.add('DateTime', DateTimePrinter) ++ printer.add('Date', DatePrinter) ++ printer.add('Time', TimePrinter) ++ ++def register_pretty_printers(obj): ++ printing.register_pretty_printer(printer, obj) ++ ++build_pretty_printers() ++ ++# vim:set shiftwidth=4 softtabstop=4 expandtab: +diff --git a/solenv/gdb/libreoffice/util/__init__.py b/solenv/gdb/libreoffice/util/__init__.py +new file mode 100644 +index 0000000..90d8012 +--- /dev/null ++++ b/solenv/gdb/libreoffice/util/__init__.py +@@ -0,0 +1,30 @@ ++# Version: MPL 1.1 / GPLv3+ / LGPLv3+ ++# ++# The contents of this file are subject to the Mozilla Public License Version ++# 1.1 (the "License"); you may not use this file except in compliance with ++# the License or as specified alternatively below. You may obtain a copy of ++# the License at http://www.mozilla.org/MPL/ ++# ++# Software distributed under the License is distributed on an "AS IS" basis, ++# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License ++# for the specific language governing rights and limitations under the ++# License. ++# ++# The Initial Developer of the Original Code is ++# David Tardon, Red Hat Inc. ++# Portions created by the Initial Developer are Copyright (C) 2010 the ++# Initial Developer. All Rights Reserved. ++# ++# Major Contributor(s): ++# ++# For minor contributions see the git repository. ++# ++# Alternatively, the contents of this file may be used under the terms of ++# either the GNU General Public License Version 3 or later (the "GPLv3+"), or ++# the GNU Lesser General Public License Version 3 or later (the "LGPLv3+"), ++# in which case the provisions of the GPLv3+ or the LGPLv3+ are applicable ++# instead of those above. ++ ++ ++ ++# vim:set shiftwidth=4 softtabstop=4 expandtab: +diff --git a/solenv/gdb/libreoffice/util/compatibility.py b/solenv/gdb/libreoffice/util/compatibility.py +new file mode 100644 +index 0000000..3011f93 +--- /dev/null ++++ b/solenv/gdb/libreoffice/util/compatibility.py +@@ -0,0 +1,38 @@ ++# Version: MPL 1.1 / GPLv3+ / LGPLv3+ ++# ++# The contents of this file are subject to the Mozilla Public License Version ++# 1.1 (the "License"); you may not use this file except in compliance with ++# the License or as specified alternatively below. You may obtain a copy of ++# the License at http://www.mozilla.org/MPL/ ++# ++# Software distributed under the License is distributed on an "AS IS" basis, ++# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License ++# for the specific language governing rights and limitations under the ++# License. ++# ++# The Initial Developer of the Original Code is ++# David Tardon, Red Hat Inc. ++# Portions created by the Initial Developer are Copyright (C) 2010 the ++# Initial Developer. All Rights Reserved. ++# ++# Major Contributor(s): ++# ++# For minor contributions see the git repository. ++# ++# Alternatively, the contents of this file may be used under the terms of ++# either the GNU General Public License Version 3 or later (the "GPLv3+"), or ++# the GNU Lesser General Public License Version 3 or later (the "LGPLv3+"), ++# in which case the provisions of the GPLv3+ or the LGPLv3+ are applicable ++# instead of those above. ++ ++import gdb ++ ++use_gdb_printing = True ++try: ++ import gdb.printing ++except ImportError: ++ use_gdb_printing = False ++ ++use_lazy_string = hasattr(gdb.Value, 'lazy_string') ++ ++# vim:set shiftwidth=4 softtabstop=4 expandtab: +diff --git a/solenv/gdb/libreoffice/util/printing.py b/solenv/gdb/libreoffice/util/printing.py +new file mode 100644 +index 0000000..e1f55b3 +--- /dev/null ++++ b/solenv/gdb/libreoffice/util/printing.py +@@ -0,0 +1,139 @@ ++# Version: MPL 1.1 / GPLv3+ / LGPLv3+ ++# ++# The contents of this file are subject to the Mozilla Public License Version ++# 1.1 (the "License"); you may not use this file except in compliance with ++# the License or as specified alternatively below. You may obtain a copy of ++# the License at http://www.mozilla.org/MPL/ ++# ++# Software distributed under the License is distributed on an "AS IS" basis, ++# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License ++# for the specific language governing rights and limitations under the ++# License. ++# ++# The Initial Developer of the Original Code is ++# David Tardon, Red Hat Inc. ++# Portions created by the Initial Developer are Copyright (C) 2010 the ++# Initial Developer. All Rights Reserved. ++# ++# Major Contributor(s): ++# ++# For minor contributions see the git repository. ++# ++# Alternatively, the contents of this file may be used under the terms of ++# either the GNU General Public License Version 3 or later (the "GPLv3+"), or ++# the GNU Lesser General Public License Version 3 or later (the "LGPLv3+"), ++# in which case the provisions of the GPLv3+ or the LGPLv3+ are applicable ++# instead of those above. ++ ++from collections import Mapping ++import gdb ++import re ++ ++from libreoffice.util.compatibility import use_gdb_printing ++ ++class SimplePrinter(object): ++ ++ def __init__(self, name, function): ++ self.name = name ++ self.function = function ++ self.enabled = True ++ ++ def invoke(self, val): ++ if not self.enabled: ++ return None ++ return self.function(self.name, val) ++ ++class NameLookup(Mapping): ++ ++ def __init__(self): ++ self.map = {} ++ self.name_regex = re.compile('^([\w:]+)(<.*>)?') ++ ++ def add(self, name, printer): ++ self.map[name] = printer ++ ++ def __len__(self): ++ return len(self.map) ++ ++ def __getitem__(self, type): ++ typename = self._basic_type(type) ++ if typename and typename in self.map: ++ return self.map[typename] ++ return None ++ ++ def __iter__(self): ++ return self.map ++ ++ def _basic_type(self, type): ++ basic_type = self.basic_type(type) ++ if basic_type: ++ match = self.name_regex.match(basic_type) ++ if match: ++ return match.group(1) ++ return None ++ ++ @staticmethod ++ def basic_type(type): ++ if type.code == gdb.TYPE_CODE_REF: ++ type = type.target() ++ type = type.unqualified().strip_typedefs() ++ return type.tag ++ ++class FunctionLookup(Mapping): ++ ++ def __init__(self): ++ self.map = {} ++ ++ def add(self, test, printer): ++ self.map[test] = printer ++ ++ def __len__(self): ++ return len(self.map) ++ ++ def __getitem__(self, type): ++ for (test, printer) in self.map.iteritems(): ++ if test(type): ++ return printer ++ return None ++ ++ def __iter__(self): ++ return self.map ++ ++class Printer(object): ++ ++ def __init__(self, name): ++ self.name = name ++ self.subprinters = [] ++ self.name_lookup = NameLookup() ++ self.func_lookup = FunctionLookup() ++ self.enabled = True ++ ++ def add(self, name, function, lookup = None): ++ printer = SimplePrinter(name, function) ++ self.subprinters.append(printer) ++ if not lookup: ++ self.name_lookup.add(name, printer) ++ else: ++ self.func_lookup.add(lookup, printer) ++ ++ ++ def __call__(self, val): ++ printer = self.name_lookup[val.type] ++ if not printer: ++ printer = self.func_lookup[val.type] ++ ++ if printer: ++ return printer.invoke(val) ++ return None ++ ++def register_pretty_printer(printer, obj): ++ '''Registers printer with objfile''' ++ ++ if use_gdb_printing: ++ gdb.printing.register_pretty_printer(obj, printer) ++ else: ++ if obj is None: ++ obj = gdb ++ obj.pretty_printers.append(printer) ++ ++# vim:set shiftwidth=4 softtabstop=4 expandtab: +diff --git a/solenv/gdb/libreoffice/util/string.py b/solenv/gdb/libreoffice/util/string.py +new file mode 100644 +index 0000000..e2db622 +--- /dev/null ++++ b/solenv/gdb/libreoffice/util/string.py +@@ -0,0 +1,93 @@ ++# Version: MPL 1.1 / GPLv3+ / LGPLv3+ ++# ++# The contents of this file are subject to the Mozilla Public License Version ++# 1.1 (the "License"); you may not use this file except in compliance with ++# the License or as specified alternatively below. You may obtain a copy of ++# the License at http://www.mozilla.org/MPL/ ++# ++# Software distributed under the License is distributed on an "AS IS" basis, ++# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License ++# for the specific language governing rights and limitations under the ++# License. ++# ++# The Initial Developer of the Original Code is ++# David Tardon, Red Hat Inc. ++# Portions created by the Initial Developer are Copyright (C) 2010 the ++# Initial Developer. All Rights Reserved. ++# ++# Major Contributor(s): ++# ++# For minor contributions see the git repository. ++# ++# Alternatively, the contents of this file may be used under the terms of ++# either the GNU General Public License Version 3 or later (the "GPLv3+"), or ++# the GNU Lesser General Public License Version 3 or later (the "LGPLv3+"), ++# in which case the provisions of the GPLv3+ or the LGPLv3+ are applicable ++# instead of those above. ++ ++import gdb ++ ++from libreoffice.util.compatibility import use_lazy_string ++ ++class StringPrinterHelper(object): ++ '''Base for all string pretty printers''' ++ ++ class MustBeImplemented(Exception): ++ pass ++ ++ def __init__(self, typename, val, encoding = None): ++ self.typename = typename ++ self.val = val ++ self.encoding = encoding ++ ++ def to_string(self): ++ data = self.data() ++ len = self.length() ++ if self.valid(): ++ return self.make_string(data, self.encoding, len) ++ else: ++ return "unintialized %s" % self.typename ++ ++ def display_hint(self): ++ if self.valid(): ++ return 'string' ++ else: ++ return None ++ ++ def valid(self): ++ return True ++ ++ def data(self): ++ raise self.MustBeImplemented() ++ ++ def length(self): ++ return -1 ++ ++ @staticmethod ++ def make_string(data, encoding = None, length = -1): ++ '''Creates a new string from memory''' ++ ++ if not encoding: ++ encoding = '' ++ ++ if use_lazy_string: ++ return data.lazy_string(encoding, length) ++ ++ # we need to determine length, if not given (for sal_Unicode*) ++ if length < 0: ++ length = 0 ++ while data[length] != 0 and length <= 512: # arbitrary limit ++ length += 1 ++ ++ # The gdb.Value.string() conversion works on array of bytes, but ++ # the length we have is the length of the string. So we must ++ # multiply it by width of character if the string is Unicode. ++ width = data[0].type.sizeof ++ if width > 1: ++ length = length * width ++ ++ char = gdb.lookup_type('char') ++ bytes = data.cast(char.pointer()) ++ return bytes.string(encoding, length = length) ++ ++# vim:set shiftwidth=4 softtabstop=4 expandtab: +diff --git a/solenv/gdb/libreoffice/util/uno.py b/solenv/gdb/libreoffice/util/uno.py +new file mode 100644 +index 0000000..23cf06a +--- /dev/null ++++ b/solenv/gdb/libreoffice/util/uno.py +@@ -0,0 +1,539 @@ ++# Version: MPL 1.1 / GPLv3+ / LGPLv3+ ++# ++# The contents of this file are subject to the Mozilla Public License Version ++# 1.1 (the "License"); you may not use this file except in compliance with ++# the License or as specified alternatively below. You may obtain a copy of ++# the License at http://www.mozilla.org/MPL/ ++# ++# Software distributed under the License is distributed on an "AS IS" basis, ++# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License ++# for the specific language governing rights and limitations under the ++# License. ++# ++# The Initial Developer of the Original Code is ++# David Tardon, Red Hat Inc. ++# Portions created by the Initial Developer are Copyright (C) 2010 the ++# Initial Developer. All Rights Reserved. ++# ++# Major Contributor(s): ++# ++# For minor contributions see the git repository. ++# ++# Alternatively, the contents of this file may be used under the terms of ++# either the GNU General Public License Version 3 or later (the "GPLv3+"), or ++# the GNU Lesser General Public License Version 3 or later (the "LGPLv3+"), ++# in which case the provisions of the GPLv3+ or the LGPLv3+ are applicable ++# instead of those above. ++ ++import gdb ++import re ++ ++class UnsupportedType(Exception): ++ '''Represents exception thrown when an unsupported UNO type(like ++ array or union) is used.''' ++ ++ def __init__(self, type): ++ self.type = type ++ ++class UnknownType(Exception): ++ '''Represents exception thrown when an unknown UNO type is used.''' ++ ++ def __init__(self, type): ++ self.type = type ++ ++class TypeClass(object): ++ '''Represents type class of UNO type.''' ++ ++ # type class of void ++ VOID = 0 ++ # type class of char ++ CHAR = 1 ++ # type class of boolean ++ BOOLEAN = 2 ++ # type class of byte ++ BYTE = 3 ++ # type class of short ++ SHORT = 4 ++ # type class of unsigned short ++ UNSIGNED_SHORT = 5 ++ # type class of long ++ LONG = 6 ++ # type class of unsigned long ++ UNSIGNED_LONG = 7 ++ # type class of hyper ++ HYPER = 8 ++ # type class of unsigned hyper ++ UNSIGNED_HYPER = 9 ++ # type class of float ++ FLOAT = 10 ++ # type class of double ++ DOUBLE = 11 ++ # type class of string ++ STRING = 12 ++ # type class of type ++ TYPE = 13 ++ # type class of any ++ ANY = 14 ++ # type class of enum ++ ENUM = 15 ++ # type class of typedef ++ TYPEDEF = 16 ++ # type class of struct ++ STRUCT = 17 ++ # type class of union (not implemented) ++ UNION = 18 ++ # type class of exception ++ EXCEPTION = 19 ++ # type class of sequence ++ SEQUENCE = 20 ++ # type class of array (not implemented) ++ ARRAY = 21 ++ # type class of interface ++ INTERFACE = 22 ++ # type class of service (not implemented) ++ SERVICE = 23 ++ # type class of module (not implemented) ++ MODULE = 24 ++ # type class of interface method ++ INTERFACE_METHOD = 25 ++ # type class of interface attribute ++ INTERFACE_ATTRIBUTE = 26 ++ # type class of unknown type ++ UNKNOWN = 27 ++ # type class of properties ++ PROPERTY = 28 ++ # type class of constants ++ CONSTANT = 29 ++ # type class of constants groups ++ CONSTANTS = 30 ++ # type class of singletons ++ SINGLETON = 31 ++ ++class TemplateType(object): ++ ++ def __init__(self, template, *args): ++ self.template = template ++ self.args = args ++ ++ def __str__(self): ++ argtypes = [str(gdb.lookup_type(arg).strip_typedefs()) for arg in self.args] ++ return self.template + '<' + ', '.join(argtypes) + '>' ++ ++class Type(object): ++ '''Describes a UNO type.''' ++ ++ def __init__(self, typeclass, tag): ++ '''Constructs a new Type. ++ @param[in] typeclass value of com::sun::star::uno::TypeClass ++ @param[in] tag UNO name of the type ++ ''' ++ self.typeclass = typeclass ++ self.tag = tag ++ # C++ name of the type ++ self.typename = None ++ ++ def type(self): ++ '''Gets gdb.Type for the type''' ++ if self.typename: ++ return gdb.lookup_type(str(self.typename)) ++ return None ++ ++ @staticmethod ++ def uno2cpp(typename): ++ return str(typename).replace('.', '::')[1:-1] ++ ++ def strip_typedefs(self): ++ copy = self.copy() ++ copy.typename = self._strip_typedefs(self.typename) ++ return copy ++ ++ def _strip_typedefs(self, typename): ++ template_args = re.compile('([^<]+)(<.*>)') ++ match = template_args.match(typename) ++ type = self._lookup_type(match.group(1)) ++ types = [] ++ if match.group(2): ++ list_delim = re.compile(', *') ++ # FIXME: this does not work with nested templates ++ for arg in match.group(2).split(list_delim): ++ types.append(self._lookup_type(arg)) ++ ++ typename = str(type) ++ if not types.empty(): ++ typename += '<' + types.join(', ') + '>' ++ ++ return typename ++ ++ def _lookup_type(self, typename): ++ if typename != '': ++ type = gdb.lookup_type(typename) ++ if type: ++ type = type.strip_typedefs() ++ return type ++ ++def make_uno_type(val): ++ '''Creates a UNO type from gdb.Value of type ++ com::sun::star::uno::Type, typelib_TypeDescription, or ++ typelib_TypeDescriptionReference ++ ''' ++ ++ cssu_type = 'com::sun::star::uno::Type' ++ type_desc = '_typelib_TypeDescription' ++ type_descs =( ++ type_desc, ++ '_typelib_CompoundTypeDescription', ++ '_typelib_StructTypeDescription', ++ '_typelib_IndirectTypeDescription', ++ '_typelib_EnumTypeDescription', ++ '_typelib_InterfaceMemberTypeDescription', ++ '_typelib_InterfaceMethodTypeDescription', ++ '_typelib_InterfaceAttributeTypeDescription', ++ '_typelib_InterfaceTypeDescription' ++ ) ++ type_desc_ref = '_typelib_TypeDescriptionReference' ++ ++ type = val.type.strip_typedefs() ++ ++ if type.tag == cssu_type: ++ pvalue = val['_pType'] ++ assert pvalue ++ val = pvalue.dereference() ++ type = val.type.strip_typedefs() ++ ++ while type.tag == type_desc_ref: ++ pvalue = val['pType'] ++ assert pvalue ++ val = pvalue.dereference() ++ type = val.type.strip_typedefs() ++ ++ if type.tag not in type_descs: ++ return None ++ ++ # determination of the UNO type ++ full_val = val ++ if type.tag != type_desc: ++ while 'aBase' in val: ++ val = val['aBase'] ++ type_class = int(val['eTypeClass']) ++ name = val['pTypeName'].dereference() ++ uno_type = None ++ if type_class == TypeClass.VOID: ++ uno_type = VoidType() ++ elif type_class == TypeClass.CHAR: ++ uno_type = PrimitiveType(type_class, name, 'sal_Char') ++ elif type_class == TypeClass.BOOLEAN: ++ uno_type = PrimitiveType(type_class, name, 'sal_Bool') ++ elif type_class == TypeClass.BYTE: ++ uno_type = PrimitiveType(type_class, name, 'sal_Int8') ++ elif type_class == TypeClass.SHORT: ++ uno_type = PrimitiveType(type_class, name, 'sal_Int16') ++ elif type_class == TypeClass.UNSIGNED_SHORT: ++ uno_type = PrimitiveType(type_class, name, 'sal_uInt16') ++ elif type_class == TypeClass.LONG: ++ uno_type = PrimitiveType(type_class, name, 'sal_Int32') ++ elif type_class == TypeClass.UNSIGNED_LONG: ++ uno_type = PrimitiveType(type_class, name, 'sal_uInt32') ++ elif type_class == TypeClass.HYPER: ++ uno_type = PrimitiveType(type_class, name, 'sal_Int64') ++ elif type_class == TypeClass.UNSIGNED_HYPER: ++ uno_type = PrimitiveType(type_class, name, 'sal_uInt64') ++ elif type_class == TypeClass.FLOAT: ++ uno_type = PrimitiveType(type_class, name, 'float') ++ elif type_class == TypeClass.DOUBLE: ++ uno_type = PrimitiveType(type_class, name, 'double') ++ elif type_class == TypeClass.STRING: ++ uno_type = PrimitiveType(type_class, name, 'rtl::OUString') ++ elif type_class == TypeClass.TYPE: ++ uno_type = PrimitiveType(type_class, name, 'com::sun::star::uno::Type') ++ elif type_class == TypeClass.ANY: ++ uno_type = PrimitiveType(type_class, name, 'com::sun::star::uno::Any') ++ elif type_class == TypeClass.ENUM: ++ uno_type = EnumType(val, full_val) ++ elif type_class == TypeClass.TYPEDEF: ++ pass ++ elif type_class == TypeClass.STRUCT: ++ uno_type = StructType(val, full_val) ++ elif type_class == TypeClass.UNION: ++ raise UnsupportedType('union') ++ elif type_class == TypeClass.EXCEPTION: ++ uno_type = CompoundType(val, full_val) ++ elif type_class == TypeClass.SEQUENCE: ++ uno_type = IndirectType(val, full_val) ++ elif type_class == TypeClass.ARRAY: ++ raise UnsupportedType('array') ++ elif type_class == TypeClass.INTERFACE: ++ uno_type = InterfaceType(val, full_val) ++ elif type_class == TypeClass.SERVICE: ++ raise UnsupportedType('service') ++ elif type_class == TypeClass.MODULE: ++ raise UnsupportedType('module') ++ elif type_class == TypeClass.INTERFACE_METHOD: ++ uno_type = InterfaceMethodType(val, full_val) ++ elif type_class == TypeClass.INTERFACE_ATTRIBUTE: ++ uno_type = InterfaceAttributeType(val, full_val) ++ elif type_class == TypeClass.UNKNOWN: ++ raise UnknownType(type) ++ elif type_class == TypeClass.PROPERTY: ++ pass ++ elif type_class == TypeClass.CONSTANT: ++ pass ++ elif type_class == TypeClass.CONSTANTS: ++ pass ++ elif type_class == TypeClass.SINGLETON: ++ pass ++ else: ++ raise UnknownType(type) ++ ++ assert uno_type ++ return uno_type ++ ++def uno_cast(type, val): ++ '''Casts val or pointer to UNO type represented by type''' ++ if val.type.code == gdb.TYPE_CODE_PTR: ++ return val.cast(type.type().pointer()) ++ else: ++ return val.cast(type.type()) ++ ++class VoidType(Type): ++ ++ def __init__(self): ++ super(VoidType, self).__init__(TypeClass.VOID, "void") ++ self.typename = "void" ++ ++class PrimitiveType(Type): ++ ++ def __init__(self, typeclass, typename_uno, typename_cpp): ++ super(PrimitiveType, self).__init__(typeclass, typename_uno) ++ self.typename = str(typename_cpp) ++ ++class CompoundType(Type): ++ ++ def __init__(self, type, full_type): ++ super(CompoundType, self).__init__(type['eTypeClass'], type['pTypeName'].dereference()) ++ self.typename = self.uno2cpp(self.tag) ++ self._type = full_type ++ ++ class _iterator(object): ++ ++ def __init__(self, count, types, names): ++ self.count = count ++ self.members = members ++ self.names = names ++ self.pos = 0 ++ ++ def __iter__(self): ++ return self ++ ++ def next(self): ++ assert self.pos >= 0 and self.pos <= self.count ++ if self.pos == self.count: ++ raise StopIteration ++ ++ pmember = self.members[self.pos] ++ assert pmember ++ pname = self.names[self.i] ++ assert pname ++ self.pos = self.pos + 1 ++ member = make_uno_type(pmember.dereference()) ++ assert member ++ name = str(pname.dereference()) ++ return (name, member) ++ ++ def attributes(self): ++ return _iterator(self._type['nMembers'], self._type['ppTypeRefs'], ++ self._type['ppMemberNames']) ++ ++class StructType(CompoundType): ++ ++ def __init__(self, type, full_type): ++ full_type = full_type.cast(gdb.lookup_type('_typelib_StructTypeDescription')) ++ super(StructType, self).__init__(type, full_type['aBase']) ++ ++class IndirectType(Type): ++ ++ def __init__(self, type, full_type): ++ super(IndirectType, self).__init__(type['eTypeClass'], type['pTypeName'].dereference()) ++ full_type = full_type.cast(gdb.lookup_type('_typelib_IndirectTypeDescription')) ++ pelem = full_type['pType'] ++ assert pelem ++ self.element = make_uno_type(pelem.dereference()) ++ assert self.element ++ self.typename = TemplateType('com::sun::star::uno::Sequence', self.element.typename) ++ ++class EnumType(Type): ++ ++ def __init__(self, type, full_type): ++ super(EnumType, self).__init__(TypeClass.ENUM, type['pTypeName'].dereference()) ++ self.typename = self.uno2cpp(self.tag) ++ self._type = full_type.cast(gdb.lookup_type('_typelib_EnumTypeDescription')) ++ ++ class _iterator(object): ++ ++ def __init__(self, count, values, names): ++ self.count = count ++ self.values = values ++ self.names = names ++ self.pos = 0 ++ ++ def __iter__(self): ++ return self ++ ++ def next(self): ++ assert self.pos >= 0 and self.pos <= self.count ++ if self.pos == self.count: ++ raise StopIteration ++ ++ pvalue = self.values[self.pos] ++ assert pvalue ++ pname = self.names[self.pos] ++ assert pname ++ self.pos = self.pos + 1 ++ val = int(pvalue.dereference()) ++ name = str(pname.dereference()) ++ return (name, val) ++ ++ def values(self): ++ return _iterator(self._type['nEnumValues'], ++ self._type['ppEnumNames'], self._type['pEnumValues']) ++ ++ def default_value(self): ++ return self._type['nDefaultEnumValue'] ++ ++class InterfaceMemberType(Type): ++ ++ def __init__(self, type, full_type): ++ super(InterfaceMemberType, self).__init__(type['eTypeClass'], type['pTypeName'].dereference()) ++ (interface, delim, member) = self.tag.partition('::') ++ self.typename = self.uno2cpp(interface) + '::*' + member ++ full_type = full_type.cast(gdb.lookup_type('_typelib_InterfaceMemberTypeDescription')) ++ self.position = full_type['nPosition'] ++ pname = full_type['pMemberName'] ++ assert pname ++ self.name = pname.dereference() ++ ++class InterfaceMethodType(InterfaceMemberType): ++ ++ def __init__(self, type, full_type): ++ full_type = full_type.cast(gdb.lookup_type('_typelib_InterfaceMethodTypeDescription')) ++ super(InterfaceMethodType, self).__init__(type, full_type['aBase']) ++ pret = full_type['pReturnTypeRef'] ++ assert pret ++ self.return_type = make_uno_type(pret.dereference()) ++ assert self.return_type ++ self.oneway = full_type['bOneWay'] ++ self._type = full_type ++ ++ class _iterator(object): ++ ++ def __init__(self, count, values): ++ self.count = count ++ self.values = values ++ self.pos = 0 ++ assert values ++ ++ def __iter__(self): ++ return self ++ ++ def next(self): ++ assert self.pos >= 0 and self.pos <= self.count ++ if self.pos == self.count: ++ raise StopIteration ++ ++ val = self.values[self.pos] ++ self.pos = self.pos + 1 ++ return val ++ ++ class parameter(tuple): ++ ++ def __init__(self, type): ++ self.__init_tuple(type) ++ self.input = type['bIn'] ++ self.output = type['bOut'] ++ ++ def _init_tuple(self, type): ++ pname = self['pName'] ++ assert pname ++ ptype = self['pTypeRef'] ++ assert ptype ++ name = str(pname.dereference()) ++ type = make_uno_type(ptype.dereference()) ++ assert type ++ super(parameter, self).__init__(name, type) ++ ++ def parameters(self): ++ for param in _iterator(self._type['nParams'], self._type['pParams']): ++ yield parameter(param) ++ ++ def exceptions(self): ++ def make_exception(self, pex): ++ assert pex ++ ex = make_uno_type(pex.dereference()) ++ assert ex ++ return ex ++ ++ for ex in _iterator( ++ self._type['nExceptions'], self._type['ppExceptions']): ++ yield make_exception(ex) ++ ++class InterfaceAttributeType(InterfaceMemberType): ++ ++ def __init__(self, type, full_type): ++ full_type = full_type.cast(gdb.lookup_type('_typelib_InterfaceAttributeTypeDescription')) ++ super(InterfaceAttributeType, self).__init__(type, full_type['aBase']) ++ self.readonly = full_type['bReadOnly'] ++ ptype = full_type['pAttributeTypeRef'] ++ assert ptype ++ self.type = make_uno_type(ptype.dereference()) ++ assert self.type ++ ++class MembersNotInitialized(Exception): ++ '''Represents exception raised when interface type' members haven't ++ been initialized(i.e. just level 1 initialization has been ++ performed)''' ++ pass ++ ++class InterfaceType(Type): ++ ++ def __init__(self, type, full_type): ++ super(InterfaceType, self).__init__(TypeClass.INTERFACE, type['pTypeName'].dereference()) ++ assert int(type['eTypeClass']) == TypeClass.INTERFACE ++ self.typename = self.uno2cpp(self.tag) ++ full_type = full_type.cast(gdb.lookup_type('_typelib_InterfaceTypeDescription')) ++ self.uik = full_type['aUik'] ++ self._type = full_type ++ ++ class _iterator(object): ++ ++ def __init__(self, count, values): ++ assert values ++ self.count = count ++ self.values = values ++ self.pos = 0 ++ ++ def __iter__(self): ++ return self ++ ++ def next(self): ++ assert self.pos >= 0 and self.pos <= self.count ++ pvalue = self.values[self.pos] ++ assert pvalue ++ self.pos = self.pos + 1 ++ uno = make_uno_type(pvalue.dereference()) ++ assert uno ++ return uno ++ ++ def members(self): ++ return __members(self._type['nMembers'], self._type['ppMembers']) ++ ++ def all_members(self): ++ return __members(self._type['nAllMembers'], self._type['ppAllMembers']) ++ ++ def __members(count, values): ++ if values == 0: ++ raise MembersNotInitialized ++ return _iterator(count, values) ++ ++ def bases(self): ++ return _iterator(self._type['nBaseTypes'], self._type['ppBaseTypes']) ++ ++# vim:set shiftwidth=4 softtabstop=4 expandtab: +-- +1.7.6 + +From 9c1e67838844b4826c5a47f03aa4b363c127a705 Mon Sep 17 00:00:00 2001 +From: David Tardon +Date: Tue, 9 Aug 2011 10:35:19 +0200 +Subject: [PATCH 2/2] install gdb pretty printers + +--- + Makefile.in | 4 ++- + solenv/bin/install-gdb-printers | 68 +++++++++++++++++++++++++++++++++++++++ + solenv/gdb/autoload.template | 42 ++++++++++++++++++++++++ + 3 files changed, 113 insertions(+), 1 deletions(-) + create mode 100755 solenv/bin/install-gdb-printers + create mode 100644 solenv/gdb/autoload.template + +diff --git a/solenv/bin/install-gdb-printers b/solenv/bin/install-gdb-printers +new file mode 100755 +index 0000000..719c280 +--- /dev/null ++++ b/solenv/bin/install-gdb-printers +@@ -0,0 +1,68 @@ ++#!/bin/bash ++ ++GDBDIR="${SOLARENV}/gdb" ++ ++die() { ++ echo "$1" >&2 ++ exit 1 ++} ++ ++make_autoload() { ++ local dir="${DESTDIR}${autoloaddir}/$2" ++ local gdbfile="${dir}/$3-gdb.py" ++ ++ if ${create}; then ++ mkdir -p "${dir}" || die "cannot create dir '${dir}'" ++ elif ${follow}; then ++ gdbfile="$(readlink -f "${dir}/$3")-gdb.py" ++ fi ++ sed -e "s!%PYTHONDIR%!${pythondir}!" -e "s!%MODULE%!libreoffice.$1!" \ ++ "${GDBDIR}/autoload.template" > "${gdbfile}" ++} ++ ++# dir where the autoloaders will be placed ++autoloaddir= ++# dir where the pretty printers will be placed ++pythondir="${GDBDIR}" ++# Create autoload dir if it does not exist. This only makes sense when ++# installing into system gdb dir, so $autoloaddir must be absolute path. ++create=false ++# Follow links when looking up the path for the autoload file. This only ++# makes sense for dev-install. ++follow=false ++ ++# b defghijklmno qrstuvwxyzABCDEFGHIJK MNOPQRSTUVWXYZ0123456789 ++while getopts :a:cp:L opt; do ++ case ${opt} in ++ a) autoloaddir="${OPTARG}" ;; ++ c) create=true ;; ++ p) pythondir="${OPTARG}" ;; ++ L) follow=true ;; ++ *) die "unknown option ${OPTARG}" ;; ++ esac ++done ++ ++${create} && ${follow} && die "-c and -L cannot be used together" ++if [[ -n ${DESTDIR} ]]; then ++ [[ ${autoloaddir:0:1} = / ]] || die 'the arg to -a must be an absolute path' ++ [[ ${pythondir:0:1} = / ]] || die 'the arg to -p must be an absolute path' ++fi ++if ${create}; then ++ [[ ${autoloaddir:0:1} = / ]] || die 'the arg to -a must be an absolute path' ++else ++ [[ ! -d ${DESTDIR}${autoloaddir} ]] && die "directory '${DESTDIR}${autoloaddir}' does not exist" ++fi ++[[ ! -d ${GDBDIR} ]] && die "directory '${GDBDIR}' does not exist" ++ ++if [[ ${DESTDIR}${pythondir} != ${GDBDIR} ]]; then ++ mkdir -p "${DESTDIR}${pythondir}" || die "cannot create dir '${DESTDIR}${pythondir}'" ++ cp -r "${GDBDIR}/libreoffice" "${DESTDIR}${pythondir}" ++fi ++ ++make_autoload cppu ure/lib libuno_cppu.so.3 ++make_autoload sal ure/lib libuno_sal.so.3 ++make_autoload svl basis3.3/program libsvllo.so ++make_autoload sw basis3.3/program libswlo.so ++make_autoload tl basis3.3/program libtllo.so ++ ++# vim:set shiftwidth=4 softtabstop=4 expandtab: +diff --git a/solenv/gdb/autoload.template b/solenv/gdb/autoload.template +new file mode 100644 +index 0000000..3351606 +--- /dev/null ++++ b/solenv/gdb/autoload.template +@@ -0,0 +1,42 @@ ++# Version: MPL 1.1 / GPLv3+ / LGPLv3+ ++# ++# The contents of this file are subject to the Mozilla Public License Version ++# 1.1 (the "License"); you may not use this file except in compliance with ++# the License or as specified alternatively below. You may obtain a copy of ++# the License at http://www.mozilla.org/MPL/ ++# ++# Software distributed under the License is distributed on an "AS IS" basis, ++# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License ++# for the specific language governing rights and limitations under the ++# License. ++# ++# The Initial Developer of the Original Code is ++# David Tardon, Red Hat Inc. ++# Portions created by the Initial Developer are Copyright (C) 2010 the ++# Initial Developer. All Rights Reserved. ++# ++# Major Contributor(s): ++# ++# For minor contributions see the git repository. ++# ++# Alternatively, the contents of this file may be used under the terms of ++# either the GNU General Public License Version 3 or later (the "GPLv3+"), or ++# the GNU Lesser General Public License Version 3 or later (the "LGPLv3+"), ++# in which case the provisions of the GPLv3+ or the LGPLv3+ are applicable ++# instead of those above. ++ ++import os.path ++import sys ++ ++import gdb ++ ++pythondir = os.path.normpath('%PYTHONDIR%') ++ ++if gdb.current_objfile(): ++ if pythondir not in sys.path: ++ sys.path.insert(0, pythondir) ++ ++from %MODULE% import register_pretty_printers ++register_pretty_printers(gdb.current_objfile()) ++ ++# vim:set filetype=python shiftwidth=4 softtabstop=4 expandtab: +-- +1.7.6 + diff --git a/libreoffice.spec b/libreoffice.spec index 05a4325..b818da9 100644 --- a/libreoffice.spec +++ b/libreoffice.spec @@ -164,6 +164,7 @@ Patch72: 0001-Resolves-rhbz-738255-avoid-crash-on-NULL-pointer.patch Patch73: 0001-On-recovery-from-an-autosave-file-use-DefaultFilter-.patch Patch74: 0001-Fix-for-fdo-35513-avoid-crash-while-processing-incor.patch Patch75: 0001-let-Qt-call-XInitThreads-so-that-it-knows-it-s-been-.patch +Patch76: gdb-pretty-printers.patch %{!?python_sitearch: %global python_sitearch %(%{__python} -c "from distutils.sysconfig import get_python_lib; print(get_python_lib(1))")} %define instdir %{_libdir} @@ -541,6 +542,41 @@ Requires: %{name}-core = %{epoch}:%{version}-%{release} %description kde A plug-in for LibreOffice that enables integration into the KDE desktop environment. +%if 0%{?_enable_debug_packages} + +%define debug_package %{nil} +%global __debug_package 1 + +%package debuginfo +Summary: Debug information for package %{name} +Group: Development/Debug +AutoReqProv: 0 +Requires: libreoffice-core = %{epoch}:%{version}-%{release} +Requires: libreoffice-gdb-debug-support = %{epoch}:%{version}-%{release} + +%description debuginfo +This package provides debug information for package %{name}. +Debug information is useful when developing applications that use this +package or when debugging this package. + +%files debuginfo -f debugfiles.list +%defattr(-,root,root) + +%package gdb-debug-support +Summary: Additional support for debugging with gdb +Group: Development/Debug +Requires: gdb +AutoReqProv: 0 + +%description gdb-debug-support +This package provides gdb pretty printers for package %{name}. + +%files gdb-debug-support +%defattr(-,root,root) +%{_datadir}/gdb/auto-load%{baseinstdir} +%{_datadir}/libreoffice/gdb + +%endif # Defines a language pack subpackage. # @@ -844,6 +880,7 @@ mv -f redhat.soc extras/source/palettes/standard.soc %patch73 -p1 -b .On-recovery-from-an-autosave-file-use-DefaultFilter-.patch %patch74 -p1 -b .fdo-35513-avoid-crash-while-processing-incor.patch %patch75 -p1 -b .let-Qt-call-XInitThreads-so-that-it-knows-it-s-been-.patch +%patch76 -p1 -b .gdb-pretty-printers.patch touch scripting/source/pyprov/delzip touch scripting/util/provider/beanshell/delzip @@ -852,6 +889,8 @@ touch scripting/util/provider/javascript/delzip cp %{PATCH44} mdds cp %{PATCH45} mdds +chmod +x solenv/bin/install-gdb-printers + %build echo build start time is `date`, diskspace: `df -h . | tail -n 1` #don't build localized helps which are poorly translated @@ -1387,6 +1426,21 @@ cp -r psprint_config/configuration/ppds/SGENPRT.PS $RPM_BUILD_ROOT/%{basisinstdi # rhbz#465664 to get lucene working for functional help sed -i -e "s#URE_MORE_JAVA_CLASSPATH_URLS.*#& file:///usr/share/java/lucene.jar file:///usr/share/java/lucene-contrib/lucene-analyzers.jar file:///usr/share/java/postgresql-jdbc.jar#" $RPM_BUILD_ROOT/%{basisinstdir}/program/fundamentalbasisrc +export DESTDIR=$RPM_BUILD_ROOT +install-gdb-printers -a %{_datadir}/gdb/auto-load%{baseinstdir} -c -p %{_datadir}/libreoffice/gdb +# fix arch-dependent library suffix +cd solenv/gdb +cat < dllpostfix.mk +PRJ=.. +.INCLUDE : settings.mk +print-DLLPOSTFIX : + @echo \$(DLLPOSTFIX) +EOF +libsuffix=`dmake -f dllpostfix.mk print-DLLPOSTFIX` +for f in `find $RPM_BUILD_ROOT/%{_datadir}/gdb/auto-load%{baseinstdir} -type f -name '*lo-gdb.py'`; do + mv "$f" "${f%lo-gdb.py}${libsuffix}-gdb.py" +done + %check source ./Linux*Env.Set.sh cd test @@ -2191,6 +2245,7 @@ update-desktop-database %{_datadir}/applications &> /dev/null || : * Fri Nov 11 2011 David Tardon 1:3.3.4.1-1-UNBUILT - Resolves: rhbz#747356 let Qt call XInitThreads - new upstream version 3.3.4 +- add gdb pretty printers * Wed Oct 05 2011 Caolán McNamara 1:3.3.3.1-7 - Resolves: CVE-2011-2713, binary .doc parsing fixes