1Devel::MAT::Dumper::HelUpseerr(3Cpomn)tributed Perl DocuDmeevnetla:t:iMoAnT::Dumper::Helper(3pm)
2
3
4

NAME

6       "Devel::MAT::Dumper::Helper" - give XS modules extensions for memory
7       dumping
8

SYNOPSIS

10       In Build.PL
11
12          if( eval { require Devel::MAT::Dumper::Helper } ) {
13             Devel::MAT::Dumper::Helper->extend_module_build( $build );
14          }
15
16       In your module's XS source:
17
18          #ifdef HAVE_DMD_HELPER
19          #  define WANT_DMD_API_044
20          #  include "DMD_helper.h"
21          #endif
22
23          ...
24
25          #ifdef HAVE_DMD_HELPER
26          static int dumpstruct(pTHX_ DMDContext *ctx, const SV *sv)
27          {
28            int ret = 0;
29
30            ret += DMD_ANNOTATE_SV(sv, another_sv,
31              "the description of this field");
32            ...
33
34            return ret;
35          }
36
37          static int dumpmagic(pTHX_ DMDContext *ctx, const SV *sv, MAGIC *mg)
38          {
39            int ret = 0;
40
41            ret += DMD_ANNOTATE_SV(sv, another_sv,
42              "the description of this field");
43            ...
44
45            return ret;
46          }
47          #endif
48
49          ...
50
51          BOOT:
52          #ifdef HAVE_DMD_HELPER
53            DMD_SET_PACKAGE_HELPER("My::Package", dumpstruct);
54            DMD_SET_MAGIC_HELPER(&vtbl, dumpmagic);
55          #endif
56

DESCRIPTION

58       This module provides a build-time helper to assist in writing XS
59       modules that can provide extra information to a Devel::MAT heap dump
60       file when dumping data structures relating to that module.
61
62       Following the example in the "SYNOPSIS" section above, the "dumpstruct"
63       function is called whenever Devel::MAT::Dumper finds an SV blessed into
64       the given package, and the "dumpmagic" function is called whenever
65       Devel::MAT::Dumper finds an SV with extension magic matching the given
66       magic virtual table pointer. These functions may then inspect the
67       module's state from the SV or MAGIC pointers, and invoke the
68       "DMD_ANNOTATE_SV" macro to provide extra annotations into the heap dump
69       file about how this SV is related to another one.
70
71       The "WANT_DMD_API_044" macro is required before "#include"ing the file,
72       so as to enable the API structure described here. Without that, an
73       earlier version of the module is provided instead, which will
74       eventually be removed in some later version.
75
76       Under this code structure, a module will cleanly build, install and run
77       just fine if Devel::MAT::Dumper::Helper is not available at build time,
78       so it is not necessary to list that as a "configure_requires" or
79       "build_requires" requirement.
80
81       Additionally, the way the inserted code is structured does not cause
82       the XS module to load "Devel::MAT::Dumper" itself, so there is no
83       runtime dependency either, even if the support was made available. The
84       newly inserted code is only invoked if both "Devel::MAT::Dumper" and
85       this XS module are actually loaded.
86
87       Note that this entire mechanism is currently experimental.
88

FUNCTIONS

90   write_DMD_helper_h
91          Devel::MAT::Dumper::Helper->write_DMD_helper_h
92
93       Writes the DMD_helper.h file to the current working directory. To cause
94       the compiler to actually find this file, see extra_compiler_flags.
95
96   extra_compiler_flags
97          @flags = Devel::MAT::Dumper::Helper->extra_compiler_flags
98
99       Returns a list of extra flags that the build scripts should add to the
100       compiler invocation. This enables the C compiler to find the
101       DMD_helper.h file, and also defines a symbol "HAVE_DMD_HELPER" which
102       the XS code can then use in "#ifdef" guards:
103
104          #ifdef HAVE_DMD_HELPER
105          ...
106          #endif
107
108   extend_module_build
109          Devel::MAT::Dumper::Helper->extend_module_build( $build )
110
111       A convenient shortcut for performing all the tasks necessary to make a
112       Module::Build-based distribution use the helper.
113

XS MACROS

115       The header file provides the following macros, which may be used by the
116       XS module.
117
118   DMD_SET_PACKAGE_HELPER
119          typedef int DMD_Helper(pTHX_ DMDContext *ctx, const SV *sv);
120
121          DMD_SET_PACKAGE_HELPER(char *packagename, DMD_Helper *helper);
122
123       This macro should be called from the "BOOT" section of the XS module to
124       associate a helper function with a named package. Whenever an instance
125       of an object blessed into that package is encountered by the dumper,
126       the helper function will be called to provide extra information about
127       it.
128
129       When invoked, the helper function is passed a pointer to the blessed SV
130       directly - remember this will be the underlying object storage and not
131       the "RV" that the Perl code uses to refer to it. It should return an
132       integer that is the sum total of the return values of all the calls to
133       "DMD_ANNOTATE_SV" that it made, or 0 if it did not make any.
134
135       The ctx pointer to the helper function points at an opaque structure
136       internal to the "Devel::MAT::Dumper" module. Helper functions are not
137       expected to interact with it, except to pass it on any
138       "DMD_DUMP_STRUCT" calls it may make.
139
140   DMD_SET_MAGIC_HELPER
141          typedef int DMD_MagicHelper(pTHX_ DMDContext *ctx, const SV *sv, MAGIC *mg);
142
143          DMD_SET_MAGIC_HELPER(MGVTBL *vtbl, DMD_MagicHelper *helper);
144
145       This macro should be called from the "BOOT" section of the XS module to
146       associate a helper function with a given magic virtual method table.
147       Whenever an SV with that kind of magic is encountered by the dumper,
148       the helper function will be called to provide extra information about
149       it.
150
151       When invoked, the helper function is passed a pointer to the magical SV
152       as well as the specific "MAGIC" instance responsible for this call. It
153       should return an integer that is the sum total of the return values of
154       all the calls to "DMD_ANNOTATE_SV" that it made, or 0 if it did not
155       make any.
156
157       The ctx pointer to the helper function points at an opaque structure
158       internal to the "Devel::MAT::Dumper" module. Helper functions are not
159       expected to interact with it, except to pass it on any
160       "DMD_DUMP_STRUCT" calls it may make.
161
162   DMD_ADD_ROOT
163          DMD_ADD_ROOT(SV *sv, const char *name);
164
165       This macro should be called from the "BOOT" section of the XS module to
166       add another root SV pointer to be added to the root SVs table. This is
167       useful for annotating static SV pointers or other storage that can
168       refer to SVs or memory structures within the module, but which would
169       not be discovered by a normal heap walk.
170
171       The name argument is also used as the description string within the
172       "Devel::MAT" UI. It should begin with either a "+" or "-" character to
173       annotate that the root contains a strong or weak reference,
174       respectively.
175
176   DMD_ANNOTATE_SV
177          DMD_ANNOTATE_SV(const SV *referrer, const SV *referrant, const char *label);
178
179       This macro should be called by a helper function, in order to provide
180       extra information about the SV it has encountered. The macro notes that
181       a pointer exists from the SV given by referrer, pointing at the SV
182       given by referrant, described by the given string label.
183
184       Each call to this macro returns an integer, which the helper function
185       must accumulate the total of, and return that number to the caller.
186
187       Not that it is not necessary that either the referrer nor the referrant
188       actually are the SV that the helper function encountered. Arbitrary
189       annotations between SVs are permitted. Additionally, it is permitted
190       that the SV addresses do not in fact point at Perl SVs, but instead
191       point to arbitarary data structures, which should be written about
192       using "DMD_DUMP_STRUCT".
193
194   DMD_DUMP_STRUCT
195          typedef struct {
196            const char *name;
197            enum {
198              DMD_FIELD_PTR,
199              DMD_FIELD_BOOL,
200              DMD_FIELD_U8,
201              DMD_FIELD_U32,
202              DMD_FIELD_UINT,
203            } type;
204
205            void *ptr;  /* for type=PTR */
206            bool  b;    /* for type=BOOL */
207            long  n;    /* for the remaining numerical types */
208          } DMDNamedField;
209
210          DMD_DUMP_STRUCT(DMDContext *ctx, const char *name, void *addr, size_t size,
211             size_t nfields, const DMDNamedField fields[]);
212
213       This macro should be called by a helper function, in order to provide
214       extra information about a memory structure that is not a Perl SV. By
215       using this macro, the module can write information into the dumpfile
216       about the memory structure types and values that it operates on,
217       allowing the "Devel::MAT" tooling to operate on it - such as by
218       following pointers and finding or identifying the contents.
219
220       The code invoked by this macro at runtime actually does two separate
221       tasks, which are closely related. The first time a call is made for any
222       particular string value in name, the function will write metadata
223       information into the dumpfile which gives the name and type of each of
224       the fields. Every call, including this first one, will write the values
225       of the fields associated with a single instance of the structure, by
226       reusing the information provided to the first call.
227
228       The ctx argument must be the value given to the helper function. addr
229       gives the pointer address of the structure itself. size should give its
230       total size in bytes (often sizeof(*ptr) is sufficient here).
231
232       The name, nfields, and fields parameters between them are used both by
233       the initial metadata call, and for every structure instance. name gives
234       a unique name to this type of structure - it should be composed of the
235       base name of the XS module, and a local name within the module,
236       separated by "/".  nfields gives the number of individual field
237       instances given in the fields array, which itself provides a label
238       name, a type, and an actual value.
239
240       The first two fields of the "DMDNamedField" structure give its name and
241       type, and one subsequent field should be set to give the value for it.
242       Which field to use depends on the type.
243
244       Note that it is very important, once a structure name has been seen the
245       first time, that every subsequent call for the same must have exactly
246       the same count of fields, and the types of each of them. The values of
247       the fields, as well as the size of the structure overall, are recorded
248       for every call, but the typing information is stored only once on that
249       first call. It is best to ensure that the module source contains only a
250       single instance of this macro for a given structure name, thus ensuring
251       the type information will always be consistent.
252

HANDLING C-LEVEL STRUCTURES

254       For example, given a C struct definition such as:
255
256         struct MyData {
257           SV *buf;
258           int state;
259
260           AV *more_stuff;
261         };
262
263       A call to provide this to the dumpfile could look like:
264
265         struct MyData *dat = ...;
266
267         DMD_DUMP_STRUCT(ctx, "Module::Name/MyData", dat, sizeof(struct MyData),
268           3, ((const DMDNamedField []){
269             {"the buf SV",        DMD_FIELD_PTR,  .ptr = dat->buf},
270             {"the state",         DMD_FIELD_UINT, .n   = dat->state},
271             {"the more_stuff AV", DMD_FIELD_PTR,  .ptr = dat->more_stuff},
272           })
273         );
274
275       Conventionally, names of unique fields all begin "the ...". Fields that
276       point to other Perl SVs should explain what kind of SV they point to,
277       so any discrepencies can be observed in the tooling later on.
278
279       A call to this macro alone is likely not enough to fully link the
280       information in the dumpfile, however. It is unlikely that any pointer
281       value that the dumper itself will encounter would point to this data
282       structure - if so, Perl would not know how to deal with it. It's likely
283       that the module would use some technique such as storing a pointer in
284       the UV field of a blessed SCALAR SV, as a way to retain it. In that
285       typical example, a helper function should be attached to the package
286       name that SV would be blessed into. When the dumper encounters that
287       blessed SV it will invoke the helper function, which can then call
288       "DMD_DUMP_STRUCT" and also use "DMD_ANNOTATE_SV" to provide a linkage
289       between the blessed SV containing the UV value, and this structure.
290
291         static int dumppackage_mydata(pTHX_ DMDContext *ctx, const SV *sv)
292         {
293           int ret = 0;
294
295           struct MyData *dat = NUM2PTR(struct MyData *, SvUV((SV *)sv));
296           DMD_DUMP_STRUCT(...);
297
298           ret += DMD_ANNOTATE_SV(sv, (SV *)dat, "the MyData structure");
299
300           return ret;
301         }
302
303         BOOT:
304
305       There is no ordering requirement between these two - the annotation
306       linking the pointers can be made before, or after, the structure itself
307       has been written. In fact, there are no ordering constraints at all;
308       feel free to write the data structures and annotations in whatever
309       order is most natural to the dumper code,
310

AUTHOR

312       Paul Evans <leonerd@leonerd.org.uk>
313
314
315
316perl v5.38.0                      2023-07-20   Devel::MAT::Dumper::Helper(3pm)
Impressum