microfmt
Zero-allocation C++ formatting for constrained environments
Loading...
Searching...
No Matches
include
microfmt
gdb_printers.hpp
Go to the documentation of this file.
1
// SPDX-FileCopyrightText: 2026 Jarosław Pelczar <jarek@jpelczar.com>
2
//
3
// SPDX-License-Identifier: BSD-2-Clause
4
5
#pragma once
6
41
#if (defined(__clang__) || defined(__GNUC__)) && defined(__ELF__)
42
43
// clang-format off
44
asm
(
45
".pushsection \".debug_gdb_scripts\", \"MS\",@progbits,1\n"
46
".byte 4\n"
/* SECTION_SCRIPT_ID_PYTHON_TEXT */
47
".ascii \"microfmt-pretty-printers.py\\n# SPDX-FileCopyrightText: 2026 Jarosław Pelczar <jarek@jpelczar.com>\"\n"
48
".ascii \"\\n#\\n# SPDX-License-Identifier: BSD-2-Clause\\n\\n\\\"\\\"\\\"GDB pretty printers for the microfmt header-only \"\n"
49
".ascii \"library.\\n\\nThis module can be used in three interchangeable ways:\\n\\n 1. Sourced directly in a run\"\n"
50
".ascii \"ning GDB session::\\n\\n (gdb) source /path/to/microfmt/tools/gdb/microfmt_printers.py\\n\\n 2.\"\n"
51
".ascii \" Auto-loaded for a specific binary by placing a ``<binary>-gdb.py``\\n next to it (or anywhere\"\n"
52
".ascii \" on GDB's auto-load path) containing::\\n\\n import sys\\n sys.path.insert(0, \\\"/path/t\"\n"
53
".ascii \"o/microfmt/tools/gdb\\\")\\n import microfmt_printers\\n microfmt_printers.register_mic\"\n"
54
".ascii \"rofmt_printers()\\n\\n 3. Embedded directly into the binary's ``.debug_gdb_scripts`` section via\\n \"\n"
55
".ascii \" ``include/microfmt/gdb_printers.hpp`` (see that header for details); GDB\\n then loads and \"\n"
56
".ascii \"runs this exact source automatically when the binary is\\n loaded, with no external file or pa\"\n"
57
".ascii \"th configuration required.\\n\\nIn all three cases the printers are registered against ``objfile`` (\"\n"
58
".ascii \"or the\\nglobal printer list, when there is no current object file) the moment this\\nmodule is load\"\n"
59
".ascii \"ed -- see the bottom of the file.\\n\\nType-erased sinks/views whose stored data can only be recover\"\n"
60
".ascii \"ed by calling\\nthrough a function pointer or an externally-owned abstract interface (e.g.\\n``micro\"\n"
61
".ascii \"fmt::sink``, ``microfmt::format_args``, ``microfmt::sinks::sbuf_sink``)\\nare intentionally not co\"\n"
62
".ascii \"vered: invoking that callback from GDB's Python API\\nisn't reliably callable, and they add little\"\n"
63
".ascii \" value over default struct\\nprinting.\\n\\\"\\\"\\\"\\n\\ntry:\\n import gdb\\n import gdb.printing\\nexcept Imp\"\n"
64
".ascii \"ortError: # pragma: no cover - only importable inside GDB.\\n gdb = None\\n\\n\\ndef _char_pointer_s\"\n"
65
".ascii \"tring(ptr_val, length):\\n \\\"\\\"\\\"Renders a ``char*`` + length pair the way GDB renders C strings.\\\"\"\n"
66
".ascii \"\\\"\\\"\\n if length == 0:\\n return '\\\"\\\"'\\n try:\\n return ptr_val.lazy_string(length=in\"\n"
67
".ascii \"t(length))\\n except gdb.error:\\n return \\\"<unreadable>\\\"\\n\\n\\nclass MicrofmtSpanSinkPrinter:\\n\"\n"
68
".ascii \" \\\"\\\"\\\"Pretty printer for `microfmt::span_sink`.\\\"\\\"\\\"\\n\\n def __init__(self, val):\\n self.v\"\n"
69
".ascii \"al = val\\n\\n def to_string(self):\\n buf = self.val[\\\"m_buf\\\"]\\n pos = int(self.val[\\\"m\"\n"
70
".ascii \"_pos\\\"])\\n cap = int(buf[\\\"m_size\\\"])\\n return \\\"microfmt::span_sink written %d of %d by\"\n"
71
".ascii \"tes = %s\\\" % (\\n pos,\\n cap,\\n _char_pointer_string(buf[\\\"m_ptr\\\"], p\"\n"
72
".ascii \"os),\\n )\\n\\n\\nclass MicrofmtBufferSinkPrinter:\\n \\\"\\\"\\\"Pretty printer for `microfmt::buffer_si\"\n"
73
".ascii \"nk<N>`.\\\"\\\"\\\"\\n\\n def __init__(self, val):\\n self.val = val\\n\\n def to_string(self):\\n \"\n"
74
".ascii \" capacity = int(self.val.type.template_argument(0))\\n pos = int(self.val[\\\"m_pos\\\"])\\n \"\n"
75
".ascii \" return \\\"microfmt::buffer_sink written %d of %d bytes = %s\\\" % (\\n pos,\\n ca\"\n"
76
".ascii \"pacity,\\n _char_pointer_string(self.val[\\\"m_data\\\"], pos),\\n )\\n\\n\\nclass MicrofmtCSt\"\n"
77
".ascii \"ringSinkPrinter:\\n \\\"\\\"\\\"Pretty printer for `microfmt::c_string_sink<N>`.\\\"\\\"\\\"\\n\\n def __init__(se\"\n"
78
".ascii \"lf, val):\\n self.val = val\\n\\n def to_string(self):\\n pos = int(self.val[\\\"m_pos\\\"])\\n\"\n"
79
".ascii \" max_payload = int(self.val[\\\"m_max_payload\\\"])\\n return \\\"microfmt::c_string_sink wri\"\n"
80
".ascii \"tten %d of %d bytes = %s\\\" % (\\n pos,\\n max_payload,\\n _char_pointe\"\n"
81
".ascii \"r_string(self.val[\\\"m_data\\\"], pos),\\n )\\n\\n\\nclass MicrofmtCStringSpanSinkPrinter:\\n \\\"\\\"\\\"Pret\"\n"
82
".ascii \"ty printer for `microfmt::c_string_span_sink`.\\\"\\\"\\\"\\n\\n def __init__(self, val):\\n self.val\"\n"
83
".ascii \" = val\\n\\n def to_string(self):\\n data = self.val[\\\"m_data\\\"]\\n pos = int(self.val[\\\"m\"\n"
84
".ascii \"_pos\\\"])\\n max_payload = int(self.val[\\\"m_max_payload\\\"])\\n if int(data) == 0:\\n \"\n"
85
".ascii \" return \\\"microfmt::c_string_span_sink [discarding, no buffer]\\\"\\n return \\\"microfmt::c_st\"\n"
86
".ascii \"ring_span_sink written %d of %d bytes = %s\\\" % (\\n pos,\\n max_payload,\\n \"\n"
87
".ascii \" _char_pointer_string(data, pos),\\n )\\n\\n\\nclass MicrofmtCountingSinkPrinter:\\n \\\"\\\"\\\"Pre\"\n"
88
".ascii \"tty printer for `microfmt::counting_sink`.\\\"\\\"\\\"\\n\\n def __init__(self, val):\\n self.val = v\"\n"
89
".ascii \"al\\n\\n def to_string(self):\\n return \\\"microfmt::counting_sink counted %d byte(s)\\\" % int(s\"\n"
90
".ascii \"elf.val[\\\"m_count\\\"])\\n\\n\\nclass MicrofmtIteratorSinkPrinter:\\n \\\"\\\"\\\"Pretty printer for `microfmt::it\"\n"
91
".ascii \"erator_sink<OutputIt>`.\\\"\\\"\\\"\\n\\n def __init__(self, val):\\n self.val = val\\n\\n def to_stri\"\n"
92
".ascii \"ng(self):\\n return \\\"microfmt::iterator_sink at %s\\\" % str(self.val[\\\"m_it\\\"])\\n\\n\\nclass Microfm\"\n"
93
".ascii \"tMemoryBufferPrinter:\\n \\\"\\\"\\\"Pretty printer for `microfmt::memory_buffer<N>` (and its base class\"\n"
94
".ascii \").\\\"\\\"\\\"\\n\\n def __init__(self, val):\\n self.val = val\\n\\n def to_string(self):\\n siz\"\n"
95
".ascii \"e = int(self.val[\\\"m_size\\\"])\\n capacity = int(self.val[\\\"m_capacity\\\"])\\n return \\\"micro\"\n"
96
".ascii \"fmt::memory_buffer of length %d, capacity %d = %s\\\" % (\\n size,\\n capacity,\\n \"\n"
97
".ascii \" _char_pointer_string(self.val[\\\"m_data\\\"], size),\\n )\\n\\n\\nclass MicrofmtLoggerPrint\"\n"
98
".ascii \"er:\\n \\\"\\\"\\\"Pretty printer for `microfmt::log::basic_logger<MaxSinks, MsgBufferCapacity>`.\\\"\\\"\\\"\\n\\n \"\n"
99
".ascii \" def __init__(self, val):\\n self.val = val\\n\\n def to_string(self):\\n name = self.\"\n"
100
".ascii \"val[\\\"name_\\\"]\\n level = self.val[\\\"level_\\\"]\\n sink_count = int(self.val[\\\"sink_count_\\\"]\"\n"
101
".ascii \")\\n return \\\"microfmt::log::basic_logger %s level=%s sinks=%d\\\" % (\\n _char_pointe\"\n"
102
".ascii \"r_string(name[\\\"data_\\\"], name[\\\"size_\\\"]),\\n str(level),\\n sink_count,\\n \"\n"
103
".ascii \")\\n\\n\\ndef _build_pretty_printer():\\n pp = gdb.printing.RegexpCollectionPrettyPrinter(\\\"microfmt\\\")\"\n"
104
".ascii \"\\n pp.add_printer(\\\"microfmt::span_sink\\\", r\\\"^microfmt::span_sink$\\\", MicrofmtSpanSinkPrinter)\\n \"\n"
105
".ascii \" pp.add_printer(\\\"microfmt::buffer_sink\\\", r\\\"^microfmt::buffer_sink<.*>$\\\", MicrofmtBufferSinkPrin\"\n"
106
".ascii \"ter)\\n pp.add_printer(\\\"microfmt::c_string_sink\\\", r\\\"^microfmt::c_string_sink<.*>$\\\", MicrofmtCSt\"\n"
107
".ascii \"ringSinkPrinter)\\n pp.add_printer(\\n \\\"microfmt::c_string_span_sink\\\", r\\\"^microfmt::c_stri\"\n"
108
".ascii \"ng_span_sink$\\\", MicrofmtCStringSpanSinkPrinter\\n )\\n pp.add_printer(\\\"microfmt::counting_sink\"\n"
109
".ascii \"\\\", r\\\"^microfmt::counting_sink$\\\", MicrofmtCountingSinkPrinter)\\n pp.add_printer(\\\"microfmt::iter\"\n"
110
".ascii \"ator_sink\\\", r\\\"^microfmt::iterator_sink<.*>$\\\", MicrofmtIteratorSinkPrinter)\\n pp.add_printer(\\\"m\"\n"
111
".ascii \"icrofmt::memory_buffer\\\", r\\\"^microfmt::(detail::)?memory_buffer(_base)?(<.*>)?$\\\",\\n \"\n"
112
".ascii \" MicrofmtMemoryBufferPrinter)\\n pp.add_printer(\\n \\\"microfmt::log::basic_logger\\\", r\\\"^\"\n"
113
".ascii \"microfmt::log::basic_logger<.*>$\\\", MicrofmtLoggerPrinter\\n )\\n return pp\\n\\n\\ndef register_micr\"\n"
114
".ascii \"ofmt_printers(objfile=None):\\n \\\"\\\"\\\"Registers the microfmt pretty printers with GDB.\\n\\n Idempo\"\n"
115
".ascii \"tent: re-registering (e.g. because this module was sourced twice,\\n or embedded in several obj\"\n"
116
".ascii \"ect files) simply replaces the previous\\n registration under the same name.\\n \\\"\\\"\\\"\\n if gdb\"\n"
117
".ascii \" is None:\\n return\\n\\n target = objfile if objfile is not None else gdb\\n gdb.printing.\"\n"
118
".ascii \"register_pretty_printer(target, _build_pretty_printer(), replace=True)\\n\\n\\nif gdb is not None:\\n \"\n"
119
".ascii \" register_microfmt_printers(gdb.current_objfile())\\n\"\n"
120
".byte 0\n"
121
".popsection\n"
122
);
123
// clang-format on
124
125
#endif
// (defined(__clang__) || defined(__GNUC__)) && defined(__ELF__)
Generated by
1.9.8