Files
qt6-migration-pipeline/specs/external/gdb/lts_printers/gdb_helper.py
T

243 lines
7.7 KiB
Python
Executable File

# -*- coding: utf-8 -*-
"""
Pretty Printer for use with pain gdb.
To activate, put this section into your ~/.gdbinit:
@code
set python print-stack full
python
import sys
sys.path.insert(0, '/shd/CTC/TOOLS/TDS/TDS-source/Lts/Tools/DebuggingHelpers/')
import gdb_helper
gdb_helper.registerPrettyPrinters()
end
@endcode
@author Christian Fröbel
"""
import gdb
import gdb.printing
import gdb.types
from datetime import datetime
import sys
if sys.version_info[0] >= 3:
long = int
class DdsStringPrinter(object):
def __init__(self, val):
self._val = val
def to_string(self):
return '"{}"'.format(self._val['str_'].string())
class DdsVectorPrinter(object):
def __init__(self, val):
self._val = val
def to_string(self):
capacity = self._val['seq_']['_maximum']
size = self._val['seq_']['_length']
formatted = 'dds::core::vector of length {}, capacity {} = {{'.format(capacity, size)
containedType = self._val.type.template_argument(0)
rawBuffer = self._val['seq_']['_contiguous_buffer'] # unsigned char*
typedBuffer = rawBuffer.cast(containedType.pointer())
for i in range(size):
if i > 0:
formatted += ', '
formatted += str(typedBuffer.dereference())
typedBuffer = typedBuffer+1
formatted += '}'
return formatted
class DdsOptionalPrinter(object):
"""Default implementation for dds::core::optional<T>"""
def __init__(self, value):
self._val = value
def to_string(self):
ptrToValue = self._val['value_']
isInitialized = _targetAddress(ptrToValue) != 0
if isInitialized:
return str(ptrToValue.dereference())
else:
return '{uninitialized}'
class DdsOptionalStringPrinter(object):
"""Specialization for dds::core::optional<dds::core::string>"""
def __init__(self, value):
self._val = value
def to_string(self):
strValue = self._val['value_']
isInitialized = _targetAddress(strValue['str_']) != 0
if isInitialized:
return str(strValue)
else:
return '{uninitialized}'
class StdChronoDurationPrinter(object):
def __init__(self, value):
self._val = value
def to_string(self):
seconds = _createSecondsFromDuration(self._val)
ms = long(seconds*1000)
formatted = 'std::chrono::duration, {}ms'.format(ms)
return formatted
def children(self):
return _namedChildren(self._val)
class StdChronoTimePointPrinter(object):
def __init__(self, value):
self._val = value
def to_string(self):
#
# Somehow registering a printer directly for AudioVideoManagement::AvaTimePoint does not work.
# As a workaround we simply query the type here.
#
if self._val.type.name == 'AudioVideoManagement::AvaTimePoint':
return AvaTimePointPrinter(self._val).to_string()
dt = _createDateTimeFromTimePoint(self._val)
formatted = 'std::chrono::time_point, {}'.format(_isoFormat(dt, nachkommaStellen=6))
return formatted
def children(self):
return _namedChildren(self._val)
class AvaTimePointPrinter(object):
def __init__(self, value):
self._val = value
def to_string(self):
dt = _createDateTimeFromTimePoint(self._val)
formatted = 'AudioVideoManagement::AvaTimePoint, {}'.format(_isoFormat(dt, nachkommaStellen=2))
return formatted
class AvsNtpTimestampPrinter(object):
"""Printer for AVS NTPTimestamp"""
def __init__(self, value):
self._val = value
def to_string(self):
dt = _createDateTimeFromNtpTimestamp(self._val)
formatted = _isoFormat(dt, nachkommaStellen=3)
return formatted
def children(self):
return _namedChildren(self._val)
class AvsNtpRangePrinter(object):
"""Printer for AVS NTPRange"""
def __init__(self, value):
self._val = value
def to_string(self):
dtBegin = _createDateTimeFromNtpTimestamp(self._val['m_begin'])
dtEnd = _createDateTimeFromNtpTimestamp(self._val['m_end'])
delta = dtEnd - dtBegin
seconds = delta.total_seconds() # float
fractionInMilli = long(seconds * 1000 + 0.5) % 1000
formatted = '{} - {}, {:d}.{:03d}s'.format(_isoFormat(dtBegin, nachkommaStellen=3), _isoFormat(dtEnd, nachkommaStellen=3), long(seconds), fractionInMilli)
return formatted
def children(self):
return _namedChildren(self._val)
def _createDateTimeFromTimePoint(value):
"""Create a datatime from a std::chrono::timepoint value"""
sSinceEpoch = _createSecondsFromDuration(value['__d'])
return datetime.utcfromtimestamp(sSinceEpoch)
def _createSecondsFromDuration(value):
"""Create seconds as float from a std::chrono::duration value"""
durationType = value.type
ratioType = durationType.template_argument(1)
dividend = long(ratioType.template_argument(0))
divisor = long(ratioType.template_argument(1))
duration = long(value['__r'])
seconds = duration * dividend / float(divisor)
return seconds
NTP_OFFSET = 2208988800 # in s; NTP starts at 1900-01-01 where unix epoch is 1970-01-01; difference is 70 years plus 17 leap years
def _createSecondsFromNtpTimestamp(value):
"""Create seconds as float from AVS NTPTimestamp. The format is a fixed 64 bit floating point number
where the upper 32 bit denote the seconds and the lower 32 bit denote the fraction of a second."""
fixedFloatValue = long(value['m_data'])
seconds = fixedFloatValue >> 32
fract = fixedFloatValue & 0xffffffff
return seconds + float(fract) / (1 << 32) - NTP_OFFSET
def _createDateTimeFromNtpTimestamp(value):
"""Create a datetime from AVS NTPTimestamp"""
sSinceEpoch = _createSecondsFromNtpTimestamp(value)
return datetime.utcfromtimestamp(sSinceEpoch)
def _isoFormat(dt, nachkommaStellen):
"""Return the ISO-representation for a given datetime instance with the requested number of Nachkommastellen"""
assert nachkommaStellen >= 0 and nachkommaStellen <= 6
s = dt.isoformat(' ')
if dt.microsecond > 0:
if nachkommaStellen == 6:
return s
return s[:-(6-nachkommaStellen)]
return s + '.' + nachkommaStellen * '0'
def _namedChildren(value):
"""Helper function; the result can directly be used in a Printer.children()."""
return ((f.name, value[f]) for f in value.type.fields())
#
# ptr must be a gdb.Value of pointer type.
# @return The address the pointer is pointing to as int.
#
def _targetAddress(ptr):
assert ptr.type.code == gdb.TYPE_CODE_PTR
return long(ptr)
def _buildPrettyPrinters():
pp = gdb.printing.RegexpCollectionPrettyPrinter("Excon")
pp.add_printer('dds::core::string', '^dds::core::basic_string<char,.*>$', DdsStringPrinter)
pp.add_printer('dds::core::vector', '^rti::core::vector<.*>$', DdsVectorPrinter)
pp.add_printer('dds::core::optional<dds::core::string>', '^rti::core::optional<dds::core::basic_string<.*>$', DdsOptionalStringPrinter)
pp.add_printer('dds::core::optional', '^rti::core::optional<.*>$', DdsOptionalPrinter)
# pp.add_printer('AudioVideoManagement::AvaTimePoint', '^AudioVideoManagement::AvaTimePoint$', AvaTimePointPrinter) # somehow doesn't work
pp.add_printer('std::chrono::duration', '^std::chrono::duration<.*>$', StdChronoDurationPrinter)
pp.add_printer('std::chrono::time_point', '^std::chrono::time_point<.*>$', StdChronoTimePointPrinter)
pp.add_printer('NTPTimestamp', '^NTPTimestamp$', AvsNtpTimestampPrinter)
pp.add_printer('NTPRange', '^NTPRange$', AvsNtpRangePrinter)
return pp
def registerPrettyPrinters():
gdb.printing.register_pretty_printer(gdb.current_objfile(), _buildPrettyPrinters())