Skip to content

Commit

Permalink
Revert commit rXXXXXX, feat debug: refactor pretty printers for userver
Browse files Browse the repository at this point in the history
Сейчас отравился распределённый кеш из-за узла HIDDEN_URL
Это вызывает падения в релизах - HIDDEN_URL

В рамках тикита завтра посмотрим
- почему дистбилд не поймал ошибку
- почему оно закешировалось в таком виде в yt store
commit_hash:bd1a5d3c866133adb55616898b51e9b9f9d45f4d
  • Loading branch information
frazenshtein committed Oct 21, 2024
1 parent 7883972 commit cd6fa5c
Show file tree
Hide file tree
Showing 10 changed files with 306 additions and 5 deletions.
12 changes: 12 additions & 0 deletions .mapping.json
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,12 @@
"devtools/gdb/test/test.py":"devtools/gdb/test/test.py",
"devtools/gdb/test/test_tconts.py":"devtools/gdb/test/test_tconts.py",
"devtools/gdb/test/ya.make":"devtools/gdb/test/ya.make",
"devtools/gdb/userver_printers/Readme.md":"devtools/gdb/userver_printers/Readme.md",
"devtools/gdb/userver_printers/__init__.py":"devtools/gdb/userver_printers/__init__.py",
"devtools/gdb/userver_printers/formats/__init__.py":"devtools/gdb/userver_printers/formats/__init__.py",
"devtools/gdb/userver_printers/formats/json/__init__.py":"devtools/gdb/userver_printers/formats/json/__init__.py",
"devtools/gdb/userver_printers/formats/json/printers.py":"devtools/gdb/userver_printers/formats/json/printers.py",
"devtools/gdb/userver_printers/formats/yaml/__init__.py":"devtools/gdb/userver_printers/formats/yaml/__init__.py",
"devtools/gdb/ya.make":"devtools/gdb/ya.make",
"devtools/gdb/yabs_printers.py":"devtools/gdb/yabs_printers.py",
"devtools/gdb/yt_fibers_printer.py":"devtools/gdb/yt_fibers_printer.py",
Expand Down Expand Up @@ -94,6 +100,12 @@
"ynd/gdb/14/pretty_printers/test/test.py":"devtools/gdb/test/test.py",
"ynd/gdb/14/pretty_printers/test/test_tconts.py":"devtools/gdb/test/test_tconts.py",
"ynd/gdb/14/pretty_printers/test/ya.make":"devtools/gdb/test/ya.make",
"ynd/gdb/14/pretty_printers/userver_printers/Readme.md":"devtools/gdb/userver_printers/Readme.md",
"ynd/gdb/14/pretty_printers/userver_printers/__init__.py":"devtools/gdb/userver_printers/__init__.py",
"ynd/gdb/14/pretty_printers/userver_printers/formats/__init__.py":"devtools/gdb/userver_printers/formats/__init__.py",
"ynd/gdb/14/pretty_printers/userver_printers/formats/json/__init__.py":"devtools/gdb/userver_printers/formats/json/__init__.py",
"ynd/gdb/14/pretty_printers/userver_printers/formats/json/printers.py":"devtools/gdb/userver_printers/formats/json/printers.py",
"ynd/gdb/14/pretty_printers/userver_printers/formats/yaml/__init__.py":"devtools/gdb/userver_printers/formats/yaml/__init__.py",
"ynd/gdb/14/pretty_printers/ya.make":"devtools/gdb/ya.make",
"ynd/gdb/14/pretty_printers/yabs_printers.py":"devtools/gdb/yabs_printers.py",
"ynd/gdb/14/pretty_printers/yt_fibers_printer.py":"devtools/gdb/yt_fibers_printer.py",
Expand Down
5 changes: 4 additions & 1 deletion ynd/gdb/14/pretty_printers/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@
sys.dont_write_bytecode = True
sys.path.insert(0, os.path.dirname(os.path.abspath(__file__)))


import libstdcpp_printers
import arcadia_printers
import libc_printers
Expand All @@ -19,6 +18,8 @@

import tcont_printer

import userver_printers

def register_printers():
libc_printers.register_printers()

Expand All @@ -38,6 +39,8 @@ def register_printers():

tcont_printer.register_commands()

userver_printers.register_printers()

print('[arc] Arcadia GDB pretty-printers enabled')

register_printers()
2 changes: 1 addition & 1 deletion ynd/gdb/14/pretty_printers/test/gdbtest/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -146,7 +146,7 @@ std::list<int> test_list_empty;
std::list<int> test_list{1, 2, 3};

formats::json::Value test_json = formats::json::FromString(
R"({"a":[1,{},[]],"b":[true,false],"c":{"internal":{"subkey":2}},"i":-1,"u":1,"i64":-18446744073709551614,"u64":18446744073709551614,"d":0.4})");
R"({"a":[1,{}],"b":[true,false],"c":{"internal":{"subkey":2}},"i":-1,"u":1,"i64":-18446744073709551614,"u64":18446744073709551614,"d":0.4})");
formats::json::Value test_json_empty;

// Variable which can't be statically initialized due to undetermined order
Expand Down
6 changes: 3 additions & 3 deletions ynd/gdb/14/pretty_printers/test/test.py
Original file line number Diff line number Diff line change
Expand Up @@ -105,9 +105,9 @@ def data(field):
test_atomic_array='std::atomic = {load() = {__elems_ = {1, 2, 3}}}',
test_list_empty='empty std::__y1::list',
test_list='std::__y1::list = {[0] = 1, [1] = 2, [2] = 3}',
# test_json=r'formats::json::Value = {value = {["a"] = {1, {}, []}, ["b"] = {true, false},'
# r' ["c"] = {["internal"] = {["subkey"] = 2}}, ["i"] = -1, ["u"] = 1, ["i64"] ='
# r' -1.8446744073709552e+19, ["u64"] = 18446744073709551614, ["d"] = 0.40000000000000002}}',
# test_json=r'formats::json::Value = {value = object of size 8 = {["a"] = array of size 2 = {1, object of size 0}, '
# r'["b"] = array of size 2 = {true, false}, ["c"] = object of size 1 = {["internal"] = object of size 1 = '
# r'{["subkey"] = 2}}, ["i"] = -1, ["u"] = 1, ["i64"] = -1.8446744073709552e+19, ["u64"] = 18446744073709551614, ["d"] = 0.40000000000000002}}',
# test_json_empty=r'formats::json::Value = {value = null}',
)

Expand Down
1 change: 1 addition & 0 deletions ynd/gdb/14/pretty_printers/userver_printers/Readme.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
`formats` is a mirror of `taxi/uservices/userver/scripts/gdb/pretty_printers/formats`
8 changes: 8 additions & 0 deletions ynd/gdb/14/pretty_printers/userver_printers/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
import gdb

import userver_printers.formats as formats

def register_printers():
pp = gdb.printing.RegexpCollectionPrettyPrinter("userver")
formats.register_printers(pp)
gdb.printing.register_pretty_printer(None, pp)
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
import userver_printers.formats.json.printers as formats_json


def register_printers(pp_collection):
formats_json.register_printers(pp_collection)
Empty file.
272 changes: 272 additions & 0 deletions ynd/gdb/14/pretty_printers/userver_printers/formats/json/printers.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,272 @@
from dataclasses import dataclass

import gdb


@dataclass
class Constants:
# @see RAPIDJSON_UINT64_C2 at rapidjson/rapidjson.h
RJ_UINT64_C2 = (0x0000FFFF << 32) | 0xFFFFFFFF

# @see `info types` at rapidjson/document.h
RJ_TALLOC = 'rapidjson::CrtAllocator'
RJ_TENCODING = 'rapidjson::UTF8<char>'

RJ_GENERIC_VALUE = f'rapidjson::GenericValue<{RJ_TENCODING}, {RJ_TALLOC}>'
RJ_GENERIC_MEMBER = (
f'rapidjson::GenericMember<{RJ_TENCODING}, {RJ_TALLOC}>'
)

RJ_GENERIC_OBJECT = f'rapidjson::GenericObject<true, {RJ_GENERIC_VALUE} >'

# @see `enum Type` in rapidjson.h
RJType_kNullType = 0 # //!< null
RJType_kFalseType = 1 # //!< false
RJType_kTrueType = 2 # //!< true
RJType_kObjectType = 3 # //!< object
RJType_kArrayType = 4 # //!< array
RJType_kStringType = 5 # //!< string
RJType_kNumberType = 6 # //!< number

# @see `enum` in rapidjson.h:
RJFlag_kBoolFlag = 0x0008
RJFlag_kNumberFlag = 0x0010
RJFlag_kIntFlag = 0x0020
RJFlag_kUintFlag = 0x0040
RJFlag_kInt64Flag = 0x0080
RJFlag_kUint64Flag = 0x0100
RJFlag_kDoubleFlag = 0x0200
RJFlag_kStringFlag = 0x0400
RJFlag_kCopyFlag = 0x0800
RJFlag_kInlineStrFlag = 0x1000

# // Initial flags of different types.
RJFlag_kNullFlag = RJType_kNullType
# // These casts are added to suppress the warning on MSVC about
# // bitwise operations between enums of different types.
RJFlag_kTrueFlag = RJType_kTrueType | RJFlag_kBoolFlag
RJFlag_kFalseFlag = RJType_kFalseType | RJFlag_kBoolFlag

RJFlag_kNumberIntFlag = (
RJType_kNumberType
| RJFlag_kNumberFlag
| RJFlag_kIntFlag
| RJFlag_kInt64Flag
)
RJFlag_kNumberUintFlag = (
RJType_kNumberType
| RJFlag_kNumberFlag
| RJFlag_kUintFlag
| RJFlag_kUint64Flag
| RJFlag_kInt64Flag
)
RJFlag_kNumberInt64Flag = (
RJType_kNumberType | RJFlag_kNumberFlag | RJFlag_kInt64Flag
)
RJFlag_kNumberUint64Flag = (
RJType_kNumberType | RJFlag_kNumberFlag | RJFlag_kUint64Flag
)
RJFlag_kNumberDoubleFlag = (
RJType_kNumberType | RJFlag_kNumberFlag | RJFlag_kDoubleFlag
)
RJFlag_kNumberAnyFlag = (
RJType_kNumberType
| RJFlag_kNumberFlag
| RJFlag_kIntFlag
| RJFlag_kInt64Flag
| RJFlag_kUintFlag
| RJFlag_kUint64Flag
| RJFlag_kDoubleFlag
)

RJFlag_kObjectFlag = RJType_kObjectType
RJFlag_kArrayFlag = RJType_kArrayType
RJFlag_kConstStringFlag = RJType_kStringType | RJFlag_kStringFlag
RJFlag_kCopyStringFlag = (
RJType_kStringType | RJFlag_kStringFlag | RJFlag_kCopyFlag
)
RJFlag_kShortStringFlag = (
RJType_kStringType
| RJFlag_kStringFlag
| RJFlag_kCopyFlag
| RJFlag_kInlineStrFlag
)

RJFlag_kTypeMask = 0x07


def rj_get_pointer(ptr, rj_type):
# FIXME: support native pointer in case of w/o 48bit optimization
# @see RAPIDJSON_48BITPOINTER_OPTIMIZATION,
# RAPIDJSON_GETPOINTER,
# RAPIDJSON_UINT64_C2 at rapidjson/rapidjson.h
newptr = int(ptr) & Constants.RJ_UINT64_C2
# just check rj_type is known or throw
gdb.lookup_type(rj_type)
return gdb.parse_and_eval(f'({rj_type}*){newptr}\n')


class RJBaseType:
def __init__(self, val: gdb.Value, flags: gdb.Value):
self.val = val
self.flags = flags


class RJObjectType(RJBaseType):
def __init__(self, val, flags):
super().__init__(val, flags)
data = val['data_']['o']
self.size = int(data['size'])
self.members = rj_get_pointer(
data['members'], Constants.RJ_GENERIC_MEMBER,
)
if self.size:
self.children = self.children_impl

def children_impl(self):
for i in range(self.size):
member = self.members[i]
name, value = member['name'], member['value']
yield (f'[{i * 2}]', name)
yield (f'[{i * 2 + 1}]', value)

def display_hint(self):
return 'map'

def to_string(self):
return f'object of size {self.size}'


class RJArrayType(RJBaseType):
def __init__(self, val, flags):
super().__init__(val, flags)
data = self.val['data_']['a']
self.size = int(data['size'])
self.elements = rj_get_pointer(
data['elements'], Constants.RJ_GENERIC_VALUE,
)

def children(self):
for i in range(self.size):
yield (f'[{i}]', self.elements[i])

def display_hint(self):
return 'array'

def to_string(self):
return f'array of size {self.size}'


class RJNumberType(RJBaseType):
def _is(self, flag):
return (self.flags & flag) == flag

def to_string(self):
data = self.val['data_']['n']
if self._is(Constants.RJFlag_kNumberIntFlag):
res = data['i']['i']
elif self._is(Constants.RJFlag_kNumberUintFlag):
res = data['u']['u']
elif self._is(Constants.RJFlag_kNumberInt64Flag):
res = data['i64']
elif self._is(Constants.RJFlag_kNumberUint64Flag):
res = data['u64']
elif self._is(Constants.RJFlag_kNumberDoubleFlag):
res = data['d']
else:
res = data
return str(res)


class RJStringType(RJBaseType):
def display_hint(self):
return 'string'

def to_string(self):
data = self.val['data_']
if (self.flags & Constants.RJFlag_kShortStringFlag) != 0:
# FIXME: support other architectures
# @see definition of LenPos in rapidjson/document.h
return data['ss']['str'].string()
return data['s']['str'].string()


class RJBoolType(RJBaseType):
def to_string(self):
if (self.flags & Constants.RJFlag_kBoolFlag) == 0:
return '<bad-bool>'
if self.flags == Constants.RJFlag_kFalseFlag:
return 'false'
if self.flags == Constants.RJFlag_kTrueFlag:
return 'true'
return str(self.val)


class RJNullType(RJBaseType):
def to_string(self):
return 'null'


def rj_get_type(flags):
if flags == Constants.RJFlag_kArrayFlag:
return RJArrayType
if flags == Constants.RJFlag_kObjectFlag:
return RJObjectType
if (flags & Constants.RJFlag_kNumberFlag) == Constants.RJFlag_kNumberFlag:
return RJNumberType
if (flags & Constants.RJFlag_kStringFlag) == Constants.RJFlag_kStringFlag:
return RJStringType
if (flags & Constants.RJFlag_kBoolFlag) == Constants.RJFlag_kBoolFlag:
return RJBoolType
if flags == Constants.RJFlag_kNullFlag:
return RJNullType
raise Exception(f'Unsupported rapidjson flag assigning to type: {flags}')


class RapidJsonValue:
"Print rapidjson::Value"

def __init__(self, val: gdb.Value):
flags = val['data_']['f']['flags']
data_type = rj_get_type(flags)
self.data = data_type(val, flags)
if hasattr(self.data, 'to_string'):
self.to_string = self.data.to_string
if hasattr(self.data, 'display_hint'):
self.display_hint = self.data.display_hint
if hasattr(self.data, 'children'):
self.children = self.data.children


class FormatsJsonValue:
"Print formats::json::Value"

def __init__(self, val: gdb.Value):
self.value = val['value_ptr_']

def to_string(self):
return 'formats::json::Value'

def children(self):
yield ('value', self.value.dereference() if self.value else None)


def register_printers(
pp_collection: gdb.printing.RegexpCollectionPrettyPrinter,
):
pp_collection.add_printer(
'formats::json::Value',
r'(^.*::|^)formats::json::Value$',
FormatsJsonValue,
)
pp_collection.add_printer(
'formats::json::impl::Value',
r'(^.*::|^)rapidjson::GenericValue<.*>$',
RapidJsonValue,
)


if __name__ == '__main__':
pp = gdb.printing.RegexpCollectionPrettyPrinter('userver.formats.json')
register_printers(pp)
gdb.printing.register_pretty_printer(gdb.current_objfile(), pp)
Empty file.

0 comments on commit cd6fa5c

Please sign in to comment.