+
+boolean_t gzalloc_element_size(void *gzaddr, zone_t *z, vm_size_t *gzsz) {
+ uintptr_t a = (uintptr_t)gzaddr;
+ if (__improbable(gzalloc_mode && (a >= gzalloc_map_min) && (a <= gzalloc_map_max))) {
+ gzhdr_t *gzh;
+
+ /* Locate the gzalloc metadata adjoining the element */
+ if (gzalloc_uf_mode == TRUE) {
+ boolean_t vmef;
+ vm_map_entry_t gzvme = NULL;
+
+ /* In underflow detection mode, locate the map entry describing
+ * the element, and then locate the copy of the gzalloc
+ * header at the trailing edge of the range.
+ */
+ vm_map_lock_read(gzalloc_map);
+ vmef = vm_map_lookup_entry(gzalloc_map, (vm_map_offset_t)a, &gzvme);
+ vm_map_unlock(gzalloc_map);
+ if (vmef == FALSE) {
+ panic("GZALLOC: unable to locate map entry for %p\n", (void *)a);
+ }
+ assertf(gzvme->vme_atomic != 0, "GZALLOC: VM map entry inconsistency, vme: %p, start: %llu end: %llu", gzvme, gzvme->vme_start, gzvme->vme_end);
+ gzh = (gzhdr_t *)(gzvme->vme_end - GZHEADER_SIZE);
+ } else {
+ gzh = (gzhdr_t *)(a - GZHEADER_SIZE);
+ }
+
+ if (gzh->gzsig != GZALLOC_SIGNATURE) {
+ panic("GZALLOC signature mismatch for element %p, expected 0x%x, found 0x%x", (void *)a, GZALLOC_SIGNATURE, gzh->gzsig);
+ }
+
+ *gzsz = gzh->gzone->elem_size;
+ if ((*gzsz < gzalloc_min) || (*gzsz > gzalloc_max)) {
+ panic("GZALLOC: invalid element size %lu\n", *gzsz);
+ }
+
+ if (z) {
+ *z = gzh->gzone;
+ }
+ return TRUE;
+ } else {
+ return FALSE;
+ }
+}