From cd6fa5ccaa8c1d7aeb5ce36975fc6cd14c0a94b2 Mon Sep 17 00:00:00 2001 From: prettyboy Date: Tue, 22 Oct 2024 00:59:37 +0300 Subject: [PATCH] Revert commit rXXXXXX, feat debug: refactor pretty printers for userver MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Сейчас отравился распределённый кеш из-за узла HIDDEN_URL Это вызывает падения в релизах - HIDDEN_URL В рамках тикита завтра посмотрим - почему дистбилд не поймал ошибку - почему оно закешировалось в таком виде в yt store commit_hash:bd1a5d3c866133adb55616898b51e9b9f9d45f4d --- .mapping.json | 12 + ynd/gdb/14/pretty_printers/__init__.py | 5 +- .../14/pretty_printers/test/gdbtest/main.cpp | 2 +- ynd/gdb/14/pretty_printers/test/test.py | 6 +- .../userver_printers/Readme.md | 1 + .../userver_printers/__init__.py | 8 + .../userver_printers/formats/__init__.py | 5 + .../userver_printers/formats/json/__init__.py | 0 .../userver_printers/formats/json/printers.py | 272 ++++++++++++++++++ .../userver_printers/formats/yaml/__init__.py | 0 10 files changed, 306 insertions(+), 5 deletions(-) create mode 100644 ynd/gdb/14/pretty_printers/userver_printers/Readme.md create mode 100644 ynd/gdb/14/pretty_printers/userver_printers/__init__.py create mode 100644 ynd/gdb/14/pretty_printers/userver_printers/formats/__init__.py create mode 100644 ynd/gdb/14/pretty_printers/userver_printers/formats/json/__init__.py create mode 100644 ynd/gdb/14/pretty_printers/userver_printers/formats/json/printers.py create mode 100644 ynd/gdb/14/pretty_printers/userver_printers/formats/yaml/__init__.py diff --git a/.mapping.json b/.mapping.json index d9c178f..502b8a1 100644 --- a/.mapping.json +++ b/.mapping.json @@ -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", @@ -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", diff --git a/ynd/gdb/14/pretty_printers/__init__.py b/ynd/gdb/14/pretty_printers/__init__.py index 55aed9b..b72b5ae 100644 --- a/ynd/gdb/14/pretty_printers/__init__.py +++ b/ynd/gdb/14/pretty_printers/__init__.py @@ -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 @@ -19,6 +18,8 @@ import tcont_printer +import userver_printers + def register_printers(): libc_printers.register_printers() @@ -38,6 +39,8 @@ def register_printers(): tcont_printer.register_commands() + userver_printers.register_printers() + print('[arc] Arcadia GDB pretty-printers enabled') register_printers() diff --git a/ynd/gdb/14/pretty_printers/test/gdbtest/main.cpp b/ynd/gdb/14/pretty_printers/test/gdbtest/main.cpp index b1fd047..dc84073 100644 --- a/ynd/gdb/14/pretty_printers/test/gdbtest/main.cpp +++ b/ynd/gdb/14/pretty_printers/test/gdbtest/main.cpp @@ -146,7 +146,7 @@ std::list test_list_empty; std::list 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 diff --git a/ynd/gdb/14/pretty_printers/test/test.py b/ynd/gdb/14/pretty_printers/test/test.py index a30c0b2..76601f0 100644 --- a/ynd/gdb/14/pretty_printers/test/test.py +++ b/ynd/gdb/14/pretty_printers/test/test.py @@ -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}', ) diff --git a/ynd/gdb/14/pretty_printers/userver_printers/Readme.md b/ynd/gdb/14/pretty_printers/userver_printers/Readme.md new file mode 100644 index 0000000..9ae7d15 --- /dev/null +++ b/ynd/gdb/14/pretty_printers/userver_printers/Readme.md @@ -0,0 +1 @@ +`formats` is a mirror of `taxi/uservices/userver/scripts/gdb/pretty_printers/formats` \ No newline at end of file diff --git a/ynd/gdb/14/pretty_printers/userver_printers/__init__.py b/ynd/gdb/14/pretty_printers/userver_printers/__init__.py new file mode 100644 index 0000000..526c5d0 --- /dev/null +++ b/ynd/gdb/14/pretty_printers/userver_printers/__init__.py @@ -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) diff --git a/ynd/gdb/14/pretty_printers/userver_printers/formats/__init__.py b/ynd/gdb/14/pretty_printers/userver_printers/formats/__init__.py new file mode 100644 index 0000000..d752686 --- /dev/null +++ b/ynd/gdb/14/pretty_printers/userver_printers/formats/__init__.py @@ -0,0 +1,5 @@ +import userver_printers.formats.json.printers as formats_json + + +def register_printers(pp_collection): + formats_json.register_printers(pp_collection) diff --git a/ynd/gdb/14/pretty_printers/userver_printers/formats/json/__init__.py b/ynd/gdb/14/pretty_printers/userver_printers/formats/json/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/ynd/gdb/14/pretty_printers/userver_printers/formats/json/printers.py b/ynd/gdb/14/pretty_printers/userver_printers/formats/json/printers.py new file mode 100644 index 0000000..58f7c11 --- /dev/null +++ b/ynd/gdb/14/pretty_printers/userver_printers/formats/json/printers.py @@ -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' + + 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' + + # @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 '' + 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) diff --git a/ynd/gdb/14/pretty_printers/userver_printers/formats/yaml/__init__.py b/ynd/gdb/14/pretty_printers/userver_printers/formats/yaml/__init__.py new file mode 100644 index 0000000..e69de29