1Devel::MAT::Dumper::HelUpseerr(3C)ontributed Perl DocumeDnetvaetli:o:nMAT::Dumper::Helper(3)
2
3
4
6 "Devel::MAT::Dumper::Helper" - give XS modules extensions for memory
7 dumping
8
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 # WANT_DMD_API_044
20 # include "DMD_helper.h"
21 #endif
22
23 ...
24
25 #ifdef HAVE_DMD_HELPER
26 static int dumpstruct(pTHX_ 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_ 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
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
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
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
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
312 Paul Evans <leonerd@leonerd.org.uk>
313
314
315
316perl v5.36.0 2022-07-22 Devel::MAT::Dumper::Helper(3)