1 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
2  * Copyright by The HDF Group.                                               *
3  * Copyright by the Board of Trustees of the University of Illinois.         *
4  * All rights reserved.                                                      *
5  *                                                                           *
6  * This file is part of HDF5.  The full HDF5 copyright notice, including     *
7  * terms governing use, modification, and redistribution, is contained in    *
8  * the COPYING file, which can be found at the root of the source code       *
9  * distribution tree, or in https://www.hdfgroup.org/licenses.               *
10  * If you do not have access to either file, you may request a copy from     *
11  * help@hdfgroup.org.                                                        *
12  * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
13 
14 /*-------------------------------------------------------------------------
15  *
16  * Created:		H5Odbg.c
17  *			Nov 17 2006
18  *			Quincey Koziol
19  *
20  * Purpose:		Object header debugging routines.
21  *
22  *-------------------------------------------------------------------------
23  */
24 
25 /****************/
26 /* Module Setup */
27 /****************/
28 
29 #include "H5Omodule.h" /* This source code file is part of the H5O module */
30 
31 /***********/
32 /* Headers */
33 /***********/
34 #include "H5private.h"   /* Generic Functions			*/
35 #include "H5Eprivate.h"  /* Error handling		  	*/
36 #include "H5MMprivate.h" /* Memory management			*/
37 #include "H5Opkg.h"      /* Object headers			*/
38 #include "H5Ppublic.h"   /* Property Lists			*/
39 
40 /****************/
41 /* Local Macros */
42 /****************/
43 
44 /******************/
45 /* Local Typedefs */
46 /******************/
47 
48 /********************/
49 /* Package Typedefs */
50 /********************/
51 
52 /********************/
53 /* Local Prototypes */
54 /********************/
55 
56 /*********************/
57 /* Package Variables */
58 /*********************/
59 
60 /*****************************/
61 /* Library Private Variables */
62 /*****************************/
63 
64 /*******************/
65 /* Local Variables */
66 /*******************/
67 
68 #ifdef H5O_DEBUG
69 
70 /*-------------------------------------------------------------------------
71  * Function:    H5O__assert
72  *
73  * Purpose:     Sanity check the information for an object header data
74  *              structure.
75  *
76  * Return:      SUCCEED (Doesn't fail, just crashes)
77  *
78  * Programmer:	Quincey Koziol
79  *		Oct 17 2006
80  *
81  *-------------------------------------------------------------------------
82  */
83 herr_t
H5O__assert(const H5O_t * oh)84 H5O__assert(const H5O_t *oh)
85 {
86     H5O_mesg_t *curr_msg;            /* Pointer to current message to examine */
87     H5O_mesg_t *tmp_msg;             /* Pointer to temporary message to examine */
88     unsigned    cont_msgs_found = 0; /* # of continuation messages for object */
89     size_t      meta_space;          /* Size of header metadata */
90     size_t      mesg_space;          /* Size of message raw data */
91     size_t      free_space;          /* Size of free space in header */
92     size_t      hdr_size;            /* Size of header's chunks */
93     unsigned    u, v;                /* Local index variables */
94 
95     FUNC_ENTER_PACKAGE_NOERR
96 
97     /* Initialize the tracking variables */
98     hdr_size   = 0;
99     meta_space = (size_t)H5O_SIZEOF_HDR(oh) + (size_t)(H5O_SIZEOF_CHKHDR_OH(oh) * (oh->nchunks - 1));
100     mesg_space = 0;
101     free_space = 0;
102 
103     /* Loop over all chunks in object header */
104     for (u = 0; u < oh->nchunks; u++) {
105         /* Accumulate the size of the header on header */
106         hdr_size += oh->chunk[u].size;
107 
108         /* If the chunk has a gap, add it to the free space */
109         free_space += oh->chunk[u].gap;
110 
111         /* Check for valid raw data image */
112         HDassert(oh->chunk[u].image);
113         HDassert(oh->chunk[u].size > (size_t)H5O_SIZEOF_CHKHDR_OH(oh));
114 
115         /* All chunks must be allocated on disk */
116         HDassert(H5F_addr_defined(oh->chunk[u].addr));
117 
118         /* Version specific checks */
119         if (oh->version > H5O_VERSION_1) {
120             /* Make certain that the magic number is correct for each chunk */
121             HDassert(
122                 !HDmemcmp(oh->chunk[u].image, (u == 0 ? H5O_HDR_MAGIC : H5O_CHK_MAGIC), H5_SIZEOF_MAGIC));
123 
124             /* Check for valid gap size */
125             HDassert(oh->chunk[u].gap < (size_t)H5O_SIZEOF_MSGHDR_OH(oh));
126         } /* end if */
127         else
128             /* Gaps should never occur in version 1 of the format */
129             HDassert(oh->chunk[u].gap == 0);
130     } /* end for */
131 
132     /* Check for correct chunk #0 size flags */
133     if (oh->version > H5O_VERSION_1) {
134         uint64_t chunk0_size = oh->chunk[0].size - (size_t)H5O_SIZEOF_HDR(oh);
135 
136         if (chunk0_size <= 255)
137             HDassert((oh->flags & H5O_HDR_CHUNK0_SIZE) == H5O_HDR_CHUNK0_1);
138         else if (chunk0_size <= 65535)
139             HDassert((oh->flags & H5O_HDR_CHUNK0_SIZE) == H5O_HDR_CHUNK0_2);
140         else if (chunk0_size <= 4294967295)
141             HDassert((oh->flags & H5O_HDR_CHUNK0_SIZE) == H5O_HDR_CHUNK0_4);
142         else
143             HDassert((oh->flags & H5O_HDR_CHUNK0_SIZE) == H5O_HDR_CHUNK0_8);
144     } /* end if */
145 
146     /* Loop over all messages in object header */
147     for (u = 0, curr_msg = &oh->mesg[0]; u < oh->nmesgs; u++, curr_msg++) {
148         uint8_t H5_ATTR_NDEBUG_UNUSED *curr_hdr;      /* Start of current message header */
149         size_t                         curr_tot_size; /* Total size of current message (including header) */
150 
151         curr_hdr      = curr_msg->raw - H5O_SIZEOF_MSGHDR_OH(oh);
152         curr_tot_size = curr_msg->raw_size + (size_t)H5O_SIZEOF_MSGHDR_OH(oh);
153 
154         /* Accumulate information, based on the type of message */
155         if (H5O_NULL_ID == curr_msg->type->id)
156             free_space += curr_tot_size;
157         else if (H5O_CONT_ID == curr_msg->type->id) {
158             H5O_cont_t *                  cont        = (H5O_cont_t *)curr_msg->native;
159             hbool_t H5_ATTR_NDEBUG_UNUSED found_chunk = FALSE; /* Found a chunk that matches */
160 
161             HDassert(cont);
162 
163             /* Increment # of continuation messages found */
164             cont_msgs_found++;
165 
166             /* Sanity check that every continuation message has a matching chunk */
167             /* (and only one) */
168             for (v = 0; v < oh->nchunks; v++) {
169                 if (H5F_addr_eq(cont->addr, oh->chunk[v].addr) && cont->size == oh->chunk[v].size) {
170                     HDassert(cont->chunkno == v);
171                     HDassert(!found_chunk);
172                     found_chunk = TRUE;
173                 } /* end if */
174             }     /* end for */
175             HDassert(found_chunk);
176 
177             meta_space += curr_tot_size;
178         } /* end if */
179         else {
180             meta_space += (size_t)H5O_SIZEOF_MSGHDR_OH(oh);
181             mesg_space += curr_msg->raw_size;
182 
183             /* Make sure the message has a native form if it is marked dirty */
184             HDassert(curr_msg->native || !curr_msg->dirty);
185         } /* end else */
186 
187         /* Make certain that the message is in a valid chunk */
188         HDassert(curr_msg->chunkno < oh->nchunks);
189 
190         /* Make certain null messages aren't in chunks with gaps */
191         if (H5O_NULL_ID == curr_msg->type->id)
192             HDassert(oh->chunk[curr_msg->chunkno].gap == 0);
193 
194         /* Make certain that the message is completely in a chunk message area */
195         HDassert(curr_tot_size <= (oh->chunk[curr_msg->chunkno].size) -
196                                       (H5O_SIZEOF_CHKSUM_OH(oh) + oh->chunk[curr_msg->chunkno].gap));
197         if (curr_msg->chunkno == 0)
198             HDassert(curr_hdr >=
199                      oh->chunk[curr_msg->chunkno].image + (H5O_SIZEOF_HDR(oh) - H5O_SIZEOF_CHKSUM_OH(oh)));
200         else
201             HDassert(curr_hdr >= oh->chunk[curr_msg->chunkno].image +
202                                      (H5O_SIZEOF_CHKHDR_OH(oh) - H5O_SIZEOF_CHKSUM_OH(oh)));
203         HDassert(curr_msg->raw + curr_msg->raw_size <=
204                  (oh->chunk[curr_msg->chunkno].image + oh->chunk[curr_msg->chunkno].size) -
205                      (H5O_SIZEOF_CHKSUM_OH(oh) + oh->chunk[curr_msg->chunkno].gap));
206 
207         /* Make certain that no other messages overlap this message */
208         for (v = 0, tmp_msg = &oh->mesg[0]; v < oh->nmesgs; v++, tmp_msg++) {
209             if (u != v)
210                 HDassert(!((tmp_msg->raw - H5O_SIZEOF_MSGHDR_OH(oh)) >= curr_hdr &&
211                            (tmp_msg->raw - H5O_SIZEOF_MSGHDR_OH(oh)) < (curr_hdr + curr_tot_size)));
212         } /* end for */
213     }     /* end for */
214 
215     /* Sanity check that the # of cont. messages is correct for the # of chunks */
216     HDassert(oh->nchunks == (cont_msgs_found + 1));
217 
218     /* Sanity check that all the bytes are accounted for */
219     HDassert(hdr_size == (free_space + meta_space + mesg_space));
220 
221     FUNC_LEAVE_NOAPI(SUCCEED)
222 } /* end H5O__assert() */
223 #endif /* H5O_DEBUG */
224 
225 /*-------------------------------------------------------------------------
226  * Function:	H5O_debug_id
227  *
228  * Purpose:	Act as a proxy for calling the 'debug' method for a
229  *              particular class of object header.
230  *
231  * Return:	Non-negative on success/Negative on failure
232  *
233  * Programmer:	Quincey Koziol
234  *		Feb 13 2003
235  *
236  *-------------------------------------------------------------------------
237  */
238 herr_t
H5O_debug_id(unsigned type_id,H5F_t * f,const void * mesg,FILE * stream,int indent,int fwidth)239 H5O_debug_id(unsigned type_id, H5F_t *f, const void *mesg, FILE *stream, int indent, int fwidth)
240 {
241     const H5O_msg_class_t *type;             /* Actual H5O class type for the ID */
242     herr_t                 ret_value = FAIL; /* Return value */
243 
244     FUNC_ENTER_NOAPI(FAIL)
245 
246     /* Check args */
247     HDassert(type_id < NELMTS(H5O_msg_class_g));
248     type = H5O_msg_class_g[type_id]; /* map the type ID to the actual type object */
249     HDassert(type);
250     HDassert(type->debug);
251     HDassert(f);
252     HDassert(mesg);
253     HDassert(stream);
254     HDassert(indent >= 0);
255     HDassert(fwidth >= 0);
256 
257     /* Call the debug method in the class */
258     if ((ret_value = (type->debug)(f, mesg, stream, indent, fwidth)) < 0)
259         HGOTO_ERROR(H5E_OHDR, H5E_BADTYPE, FAIL, "unable to debug message")
260 
261 done:
262     FUNC_LEAVE_NOAPI(ret_value)
263 } /* end H5O_debug_id() */
264 
265 /*-------------------------------------------------------------------------
266  * Function:    H5O__debug_real
267  *
268  * Purpose:     Prints debugging info about an object header.
269  *
270  * Return:      SUCCEED/FAIL
271  *
272  * Programmer:	Robb Matzke
273  *		Aug  6 1997
274  *
275  *-------------------------------------------------------------------------
276  */
277 herr_t
H5O__debug_real(H5F_t * f,H5O_t * oh,haddr_t addr,FILE * stream,int indent,int fwidth)278 H5O__debug_real(H5F_t *f, H5O_t *oh, haddr_t addr, FILE *stream, int indent, int fwidth)
279 {
280     size_t    mesg_total = 0, chunk_total = 0, gap_total = 0;
281     unsigned *sequence = NULL;
282     unsigned  i; /* Local index variable */
283     herr_t    ret_value = SUCCEED;
284 
285     FUNC_ENTER_PACKAGE
286 
287     /* check args */
288     HDassert(f);
289     HDassert(oh);
290     HDassert(H5F_addr_defined(addr));
291     HDassert(stream);
292     HDassert(indent >= 0);
293     HDassert(fwidth >= 0);
294 
295     /* debug */
296     HDfprintf(stream, "%*sObject Header...\n", indent, "");
297 
298     HDfprintf(stream, "%*s%-*s %s\n", indent, "", fwidth,
299               "Dirty:", oh->cache_info.is_dirty ? "TRUE" : "FALSE");
300     HDfprintf(stream, "%*s%-*s %u\n", indent, "", fwidth, "Version:", oh->version);
301     HDfprintf(stream, "%*s%-*s %u\n", indent, "", fwidth,
302               "Header size (in bytes):", (unsigned)H5O_SIZEOF_HDR(oh));
303     HDfprintf(stream, "%*s%-*s %u\n", indent, "", fwidth, "Number of links:", oh->nlink);
304 
305     /* Extra information for later versions */
306     if (oh->version > H5O_VERSION_1) {
307         /* Display object's status flags */
308         HDfprintf(stream, "%*s%-*s %s\n", indent, "", fwidth, "Attribute creation order tracked:",
309                   (oh->flags & H5O_HDR_ATTR_CRT_ORDER_TRACKED) ? "Yes" : "No");
310         HDfprintf(stream, "%*s%-*s %s\n", indent, "", fwidth, "Attribute creation order indexed:",
311                   (oh->flags & H5O_HDR_ATTR_CRT_ORDER_INDEXED) ? "Yes" : "No");
312         HDfprintf(stream, "%*s%-*s %s\n", indent, "", fwidth, "Attribute storage phase change values:",
313                   (oh->flags & H5O_HDR_ATTR_STORE_PHASE_CHANGE) ? "Non-default" : "Default");
314         HDfprintf(stream, "%*s%-*s %s\n", indent, "", fwidth,
315                   "Timestamps:", (oh->flags & H5O_HDR_STORE_TIMES) ? "Enabled" : "Disabled");
316         if (oh->flags & ~H5O_HDR_ALL_FLAGS)
317             HDfprintf(stream, "*** UNKNOWN OBJECT HEADER STATUS FLAG: %02x!\n", (unsigned)oh->flags);
318 
319         /* Only dump times, if they are tracked */
320         if (oh->flags & H5O_HDR_STORE_TIMES) {
321             struct tm *tm;       /* Time structure */
322             char       buf[128]; /* Buffer for formatting time info */
323 
324             /* Time fields */
325             tm = HDlocaltime(&oh->atime);
326             HDstrftime(buf, sizeof(buf), "%Y-%m-%d %H:%M:%S %Z", tm);
327             HDfprintf(stream, "%*s%-*s %s\n", indent, "", fwidth, "Access Time:", buf);
328             tm = HDlocaltime(&oh->mtime);
329             HDstrftime(buf, sizeof(buf), "%Y-%m-%d %H:%M:%S %Z", tm);
330             HDfprintf(stream, "%*s%-*s %s\n", indent, "", fwidth, "Modification Time:", buf);
331             tm = HDlocaltime(&oh->ctime);
332             HDstrftime(buf, sizeof(buf), "%Y-%m-%d %H:%M:%S %Z", tm);
333             HDfprintf(stream, "%*s%-*s %s\n", indent, "", fwidth, "Change Time:", buf);
334             tm = HDlocaltime(&oh->btime);
335             HDstrftime(buf, sizeof(buf), "%Y-%m-%d %H:%M:%S %Z", tm);
336             HDfprintf(stream, "%*s%-*s %s\n", indent, "", fwidth, "Birth Time:", buf);
337         } /* end if */
338 
339         /* Attribute tracking fields */
340         if (oh->flags & H5O_HDR_ATTR_STORE_PHASE_CHANGE) {
341             HDfprintf(stream, "%*s%-*s %u\n", indent, "", fwidth,
342                       "Max. compact attributes:", (unsigned)oh->max_compact);
343             HDfprintf(stream, "%*s%-*s %u\n", indent, "", fwidth,
344                       "Min. dense attributes:", (unsigned)oh->min_dense);
345         } /* end if */
346     }     /* end if */
347 
348     HDfprintf(stream, "%*s%-*s %zu (%zu)\n", indent, "", fwidth,
349               "Number of messages (allocated):", oh->nmesgs, oh->alloc_nmesgs);
350     HDfprintf(stream, "%*s%-*s %zu (%zu)\n", indent, "", fwidth, "Number of chunks (allocated):", oh->nchunks,
351               oh->alloc_nchunks);
352 
353     /* debug each chunk */
354     for (i = 0, chunk_total = 0; i < oh->nchunks; i++) {
355         size_t chunk_size;
356 
357         HDfprintf(stream, "%*sChunk %d...\n", indent, "", i);
358 
359         HDfprintf(stream, "%*s%-*s %" PRIuHADDR "\n", indent + 3, "", MAX(0, fwidth - 3),
360                   "Address:", oh->chunk[i].addr);
361 
362         /* Decrement chunk 0's size by the object header prefix size */
363         if (0 == i) {
364             if (H5F_addr_ne(oh->chunk[i].addr, addr))
365                 HDfprintf(stream, "*** WRONG ADDRESS FOR CHUNK #0!\n");
366             chunk_size = oh->chunk[i].size - (size_t)H5O_SIZEOF_HDR(oh);
367         } /* end if */
368         else
369             chunk_size = oh->chunk[i].size;
370 
371         /* Accumulate chunk's size to total */
372         chunk_total += chunk_size;
373         gap_total += oh->chunk[i].gap;
374 
375         HDfprintf(stream, "%*s%-*s %zu\n", indent + 3, "", MAX(0, fwidth - 3), "Size in bytes:", chunk_size);
376 
377         HDfprintf(stream, "%*s%-*s %zu\n", indent + 3, "", MAX(0, fwidth - 3), "Gap:", oh->chunk[i].gap);
378     } /* end for */
379 
380     /* debug each message */
381     if (NULL == (sequence = (unsigned *)H5MM_calloc(NELMTS(H5O_msg_class_g) * sizeof(unsigned))))
382         HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed")
383     for (i = 0, mesg_total = 0; i < oh->nmesgs; i++) {
384         const H5O_msg_class_t *debug_type; /* Type of message to use for callbacks */
385         unsigned               chunkno;    /* Chunk for message */
386 
387         /* Accumulate message's size to total */
388         mesg_total += (size_t)H5O_SIZEOF_MSGHDR_OH(oh) + oh->mesg[i].raw_size;
389 
390         /* For version 2 object header, add size of "OCHK" for continuation chunk */
391         if (oh->mesg[i].type->id == H5O_CONT_ID)
392             mesg_total += H5O_SIZEOF_CHKHDR_OH(oh);
393 
394         HDfprintf(stream, "%*sMessage %d...\n", indent, "", i);
395 
396         /* check for bad message id */
397         if (oh->mesg[i].type->id >= (int)NELMTS(H5O_msg_class_g)) {
398             HDfprintf(stream, "*** BAD MESSAGE ID 0x%04x\n", oh->mesg[i].type->id);
399             continue;
400         } /* end if */
401 
402         /* message name and size */
403         HDfprintf(stream, "%*s%-*s 0x%04x `%s' (%d)\n", indent + 3, "", MAX(0, fwidth - 3),
404                   "Message ID (sequence number):", (unsigned)(oh->mesg[i].type->id), oh->mesg[i].type->name,
405                   sequence[oh->mesg[i].type->id]++);
406         HDfprintf(stream, "%*s%-*s %s\n", indent + 3, "", MAX(0, fwidth - 3),
407                   "Dirty:", oh->mesg[i].dirty ? "TRUE" : "FALSE");
408         HDfprintf(stream, "%*s%-*s ", indent + 3, "", MAX(0, fwidth - 3), "Message flags:");
409         if (oh->mesg[i].flags) {
410             hbool_t flag_printed = FALSE;
411 
412             /* Sanity check that all flags in format are covered below */
413             HDcompile_assert(H5O_MSG_FLAG_BITS ==
414                              (H5O_MSG_FLAG_CONSTANT | H5O_MSG_FLAG_SHARED | H5O_MSG_FLAG_DONTSHARE |
415                               H5O_MSG_FLAG_FAIL_IF_UNKNOWN_AND_OPEN_FOR_WRITE | H5O_MSG_FLAG_MARK_IF_UNKNOWN |
416                               H5O_MSG_FLAG_WAS_UNKNOWN | H5O_MSG_FLAG_SHAREABLE |
417                               H5O_MSG_FLAG_FAIL_IF_UNKNOWN_ALWAYS));
418 
419             if (oh->mesg[i].flags & H5O_MSG_FLAG_CONSTANT) {
420                 HDfprintf(stream, "%sC", (flag_printed ? ", " : "<"));
421                 flag_printed = TRUE;
422             } /* end if */
423             if (oh->mesg[i].flags & H5O_MSG_FLAG_SHARED) {
424                 HDfprintf(stream, "%sS", (flag_printed ? ", " : "<"));
425                 flag_printed = TRUE;
426             } /* end if */
427             if (oh->mesg[i].flags & H5O_MSG_FLAG_DONTSHARE) {
428                 HDfprintf(stream, "%sDS", (flag_printed ? ", " : "<"));
429                 flag_printed = TRUE;
430             } /* end if */
431             if (oh->mesg[i].flags & H5O_MSG_FLAG_FAIL_IF_UNKNOWN_AND_OPEN_FOR_WRITE) {
432                 HDfprintf(stream, "%sFIUW", (flag_printed ? ", " : "<"));
433                 flag_printed = TRUE;
434             } /* end if */
435             if (oh->mesg[i].flags & H5O_MSG_FLAG_MARK_IF_UNKNOWN) {
436                 HDfprintf(stream, "%sMIU", (flag_printed ? ", " : "<"));
437                 flag_printed = TRUE;
438             } /* end if */
439             if (oh->mesg[i].flags & H5O_MSG_FLAG_WAS_UNKNOWN) {
440                 HDassert(oh->mesg[i].flags & H5O_MSG_FLAG_MARK_IF_UNKNOWN);
441                 HDfprintf(stream, "%sWU", (flag_printed ? ", " : "<"));
442                 flag_printed = TRUE;
443             } /* end if */
444             if (oh->mesg[i].flags & H5O_MSG_FLAG_SHAREABLE) {
445                 HDfprintf(stream, "%sSA", (flag_printed ? ", " : "<"));
446                 flag_printed = TRUE;
447             } /* end if */
448             if (oh->mesg[i].flags & H5O_MSG_FLAG_FAIL_IF_UNKNOWN_ALWAYS) {
449                 HDfprintf(stream, "%sFIUA", (flag_printed ? ", " : "<"));
450                 flag_printed = TRUE;
451             } /* end if */
452             if (!flag_printed)
453                 HDfprintf(stream, "-");
454             HDfprintf(stream, ">\n");
455             if (oh->mesg[i].flags & ~H5O_MSG_FLAG_BITS)
456                 HDfprintf(stream, "%*s%-*s 0x%02x\n", indent + 3, "", MAX(0, fwidth - 3),
457                           "*** ADDITIONAL UNKNOWN FLAGS --->", oh->mesg[i].flags & ~H5O_MSG_FLAG_BITS);
458         } /* end if */
459         else
460             HDfprintf(stream, "<none>\n");
461 
462         HDfprintf(stream, "%*s%-*s %u\n", indent + 3, "", MAX(0, fwidth - 3),
463                   "Chunk number:", oh->mesg[i].chunkno);
464         chunkno = oh->mesg[i].chunkno;
465         if (chunkno >= oh->nchunks)
466             HDfprintf(stream, "*** BAD CHUNK NUMBER\n");
467         HDfprintf(stream, "%*s%-*s (%zu, %zu) bytes\n", indent + 3, "", MAX(0, fwidth - 3),
468                   "Raw message data (offset, size) in chunk:",
469                   (size_t)(oh->mesg[i].raw - oh->chunk[chunkno].image), oh->mesg[i].raw_size);
470 
471         /* check the size */
472         if ((oh->mesg[i].raw + oh->mesg[i].raw_size > oh->chunk[chunkno].image + oh->chunk[chunkno].size) ||
473             (oh->mesg[i].raw < oh->chunk[chunkno].image))
474             HDfprintf(stream, "*** BAD MESSAGE RAW ADDRESS\n");
475 
476         /* decode the message */
477         debug_type = oh->mesg[i].type;
478         if (NULL == oh->mesg[i].native && debug_type->decode)
479             H5O_LOAD_NATIVE(f, H5O_DECODEIO_NOCHANGE, oh, &oh->mesg[i], FAIL)
480 
481         /* print the message */
482         HDfprintf(stream, "%*s%-*s\n", indent + 3, "", MAX(0, fwidth - 3), "Message Information:");
483         if (debug_type->debug && oh->mesg[i].native != NULL)
484             (debug_type->debug)(f, oh->mesg[i].native, stream, indent + 6, MAX(0, fwidth - 6));
485         else
486             HDfprintf(stream, "%*s<No info for this message>\n", indent + 6, "");
487     } /* end for */
488 
489     if ((mesg_total + gap_total) != chunk_total)
490         HDfprintf(stream, "*** TOTAL SIZE DOES NOT MATCH ALLOCATED SIZE!\n");
491 
492 done:
493     /* Release resources */
494     if (sequence)
495         sequence = (unsigned *)H5MM_xfree(sequence);
496 
497     FUNC_LEAVE_NOAPI(ret_value)
498 } /* end H5O__debug_real() */
499 
500 /*-------------------------------------------------------------------------
501  * Function:	H5O_debug
502  *
503  * Purpose:	Prints debugging info about an object header.
504  *
505  * Return:	Non-negative on success/Negative on failure
506  *
507  * Programmer:	Robb Matzke
508  *		Aug  6 1997
509  *
510  *-------------------------------------------------------------------------
511  */
512 herr_t
H5O_debug(H5F_t * f,haddr_t addr,FILE * stream,int indent,int fwidth)513 H5O_debug(H5F_t *f, haddr_t addr, FILE *stream, int indent, int fwidth)
514 {
515     H5O_t *   oh = NULL;           /* Object header to display */
516     H5O_loc_t loc;                 /* Object location for object to delete */
517     herr_t    ret_value = SUCCEED; /* Return value */
518 
519     FUNC_ENTER_NOAPI(FAIL)
520 
521     /* check args */
522     HDassert(f);
523     HDassert(H5F_addr_defined(addr));
524     HDassert(stream);
525     HDassert(indent >= 0);
526     HDassert(fwidth >= 0);
527 
528     /* Set up the object location */
529     loc.file         = f;
530     loc.addr         = addr;
531     loc.holding_file = FALSE;
532 
533     if (NULL == (oh = H5O_protect(&loc, H5AC__READ_ONLY_FLAG, FALSE)))
534         HGOTO_ERROR(H5E_OHDR, H5E_CANTPROTECT, FAIL, "unable to load object header")
535 
536     /* debug */
537     if (H5O__debug_real(f, oh, addr, stream, indent, fwidth) < 0)
538         HGOTO_ERROR(H5E_OHDR, H5E_SYSTEM, FAIL, "debug dump call failed")
539 
540 done:
541     if (oh && H5O_unprotect(&loc, oh, H5AC__NO_FLAGS_SET) < 0)
542         HDONE_ERROR(H5E_OHDR, H5E_CANTUNPROTECT, FAIL, "unable to release object header")
543 
544     FUNC_LEAVE_NOAPI(ret_value)
545 } /* end H5O_debug() */
546