aboutsummaryrefslogtreecommitdiff
path: root/libs/kstd/gdb/error_code.py
blob: 1569f59a494cbda81bda3fadb6222d622d451f98 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
import gdb


class KstdErrorCodePrinter(gdb.ValuePrinter):
    def __init__(self, val):
        self.__val = val

    def _error_value(self):
        return int(self.__val["m_value"])

    def _category_name(self):
        try:
            category_pointer = self.__val["m_category"]
            if int(category_pointer) == 0:
                return "<null category>"
            category = category_pointer.dereference()
            try:
                dynamic = category.dynamic_type
                name = str(dynamic)
            except gdb.error:
                name = str(category.type)
            name = name.replace("(anonymous namespace)::", "")
            if name.endswith("_t"):
                name = name[:-2]
            return name
        except (gdb.error, AttributeError):
            return "?"

    def _message(self):
        try:
            category_pointer = self.__val["m_category"]
            if int(category_pointer) == 0:
                return None
            value = self._error_value()
            address = int(category_pointer)
            result = gdb.parse_and_eval(
                f"((kstd::error_category const *){address:#x})->message({value})"
            )
            try:
                ptr = result["_M_str"]
                length = int(result["_M_len"])
                if int(ptr) != 0 and length > 0:
                    return ptr.string(length=length)
            except (gdb.error, AttributeError, KeyError):
                pass
            return str(result)
        except (gdb.error, RuntimeError):
            return None

    def to_string(self):
        value = self._error_value()
        category = self._category_name()
        msg = self._message()
        if msg is not None:
            return f"{category}:{value} ({msg})"
        return f"{category}:{value}"

    def children(self):
        yield ("value", self.__val["m_value"])
        category_pointer = self.__val["m_category"]
        if int(category_pointer) != 0:
            yield ("category", category_pointer.dereference())

    def display_hint(self):
        return None