static ut64 resolve_symbols_off(RDyldCache *cache, ut64 pa) {
	struct MACH0_(mach_header) mh;
	if (r_buf_fread_at (cache->buf, pa, (ut8*) &mh, "8i", 1) != sizeof (struct MACH0_(mach_header))) {
		return 0;
	}
	if (mh.magic != MH_MAGIC_64 || mh.sizeofcmds == 0) {
		return 0;
	}
	ut64 cmds_at = pa + sizeof (struct MACH0_(mach_header));
	ut64 cursor = cmds_at;
	ut64 end = cursor + mh.sizeofcmds;
	while (cursor < end) {
		ut32 cmd = r_buf_read_le32_at (cache->buf, cursor);
		if (cmd == UT32_MAX) {
			return 0;
		}
		ut32 cmdsize = r_buf_read_le32_at (cache->buf, cursor + sizeof (ut32));
		if (cmdsize == UT32_MAX) {
			return 0;
		}
		if (cmd == LC_SEGMENT || cmd == LC_SEGMENT_64) {
			char segname[17];
			segname[16] = 0;
			if (r_buf_read_at (cache->buf, cursor + 2 * sizeof (ut32), (ut8 *)segname, 16) != 16) {
				return 0;
			}
			if (!strncmp (segname, "__LINKEDIT", 16)) {
				ut64 vmaddr = r_buf_read_le64_at (cache->buf, cursor + 2 * sizeof (ut32) + 16);
				if (vmaddr == UT64_MAX) {
					return 0;
				}

				ut32 i,j;
				for (i = 0; i < cache->n_hdr; i++) {
					cache_hdr_t *hdr = &cache->hdr[i];
					ut64 hdr_offset = cache->hdr_offset[i];
					ut32 maps_index = cache->maps_index[i];
					for (j = 0; j < hdr->mappingCount; j++) {
						ut64 map_start = cache->maps[maps_index + j].address;
						ut64 map_end = map_start + cache->maps[maps_index + j].size;
						if (vmaddr >= map_start && vmaddr < map_end) {
							return hdr_offset;
						}
					}
				}
			}
		}
		cursor += cmdsize;
	}
	return 0;
}
static ut64 resolve_symbols_off(RDyldCache *cache, ut64 pa) {
	struct MACH0_(mach_header) mh;
	if (r_buf_fread_at (cache->buf, pa, (ut8*) &mh, "8i", 1) != sizeof (struct MACH0_(mach_header))) {
		return 0;
	}
	if (mh.magic != MH_MAGIC_64 || mh.sizeofcmds == 0) {
		return 0;
	}
	ut64 cmds_at = pa + sizeof (struct MACH0_(mach_header));
	ut64 cursor = cmds_at;
	ut64 end = cursor + mh.sizeofcmds;
	while (cursor < end) {
		ut32 cmd = r_buf_read_le32_at (cache->buf, cursor);
		if (cmd == UT32_MAX) {
			return 0;
		}
		ut32 cmdsize = r_buf_read_le32_at (cache->buf, cursor + sizeof (ut32));
		if (cmdsize == UT32_MAX) {
			return 0;
		}
		if (cmd == LC_SEGMENT || cmd == LC_SEGMENT_64) {
			char segname[17];
			segname[16] = 0;
			if (r_buf_read_at (cache->buf, cursor + 2 * sizeof (ut32), (ut8 *)segname, 16) != 16) {
				return 0;
			}
			if (!strncmp (segname, "__LINKEDIT", 16)) {
				ut64 vmaddr = r_buf_read_le64_at (cache->buf, cursor + 2 * sizeof (ut32) + 16);
				if (vmaddr == UT64_MAX) {
					return 0;
				}

				ut32 i,j;
				for (i = 0; i < cache->n_hdr; i++) {
					cache_hdr_t *hdr = &cache->hdr[i];
					ut64 hdr_offset = cache->hdr_offset[i];
					ut32 maps_index = cache->maps_index[i];
					for (j = 0; j < hdr->mappingCount; j++) {
						ut64 map_start = cache->maps[maps_index + j].address;
						ut64 map_end = map_start + cache->maps[maps_index + j].size;
						if (vmaddr >= map_start && vmaddr < map_end) {
							return hdr_offset;
						}
					}
				}
			}
		}
		cursor += cmdsize;
	}
	return 0;
}