📄 ctf_open.c
字号:
} ctf_dprintf("%lu total types processed\n", fp->ctf_typemax); ctf_dprintf("%u enum names hashed\n", ctf_hash_size(&fp->ctf_enums)); ctf_dprintf("%u struct names hashed (%d long)\n", ctf_hash_size(&fp->ctf_structs), nlstructs); ctf_dprintf("%u union names hashed (%d long)\n", ctf_hash_size(&fp->ctf_unions), nlunions); ctf_dprintf("%u base type names hashed\n", ctf_hash_size(&fp->ctf_names)); /* * Make an additional pass through the pointer table to find pointers * that point to anonymous typedef nodes. If we find one, modify the * pointer table so that the pointer is also known to point to the * node that is referenced by the anonymous typedef node. */ for (id = 1; id <= fp->ctf_typemax; id++) { if ((dst = fp->ctf_ptrtab[id]) != 0) { tp = LCTF_INDEX_TO_TYPEPTR(fp, id); if (LCTF_INFO_KIND(fp, tp->ctt_info) == CTF_K_TYPEDEF && strcmp(ctf_strptr(fp, tp->ctt_name), "") == 0 && CTF_TYPE_ISCHILD(tp->ctt_type) == child && CTF_TYPE_TO_INDEX(tp->ctt_type) <= fp->ctf_typemax) fp->ctf_ptrtab[ CTF_TYPE_TO_INDEX(tp->ctt_type)] = dst; } } return (0);}/* * Decode the specified CTF buffer and optional symbol table and create a new * CTF container representing the symbolic debugging information. This code * can be used directly by the debugger, or it can be used as the engine for * ctf_fdopen() or ctf_open(), below. */ctf_file_t *ctf_bufopen(const ctf_sect_t *ctfsect, const ctf_sect_t *symsect, const ctf_sect_t *strsect, int *errp){ const ctf_preamble_t *pp; ctf_header_t hp; ctf_file_t *fp; void *buf, *base; size_t size, hdrsz; int err; if (ctfsect == NULL || ((symsect == NULL) != (strsect == NULL))) return (ctf_set_open_errno(errp, EINVAL)); if (symsect != NULL && symsect->cts_entsize != sizeof (Elf32_Sym) && symsect->cts_entsize != sizeof (Elf64_Sym)) return (ctf_set_open_errno(errp, ECTF_SYMTAB)); if (symsect != NULL && symsect->cts_data == NULL) return (ctf_set_open_errno(errp, ECTF_SYMBAD)); if (strsect != NULL && strsect->cts_data == NULL) return (ctf_set_open_errno(errp, ECTF_STRBAD)); if (ctfsect->cts_size < sizeof (ctf_preamble_t)) return (ctf_set_open_errno(errp, ECTF_NOCTFBUF)); pp = (const ctf_preamble_t *)ctfsect->cts_data; ctf_dprintf("ctf_bufopen: magic=0x%x version=%u\n", pp->ctp_magic, pp->ctp_version); /* * Validate each part of the CTF header (either V1 or V2). * First, we validate the preamble (common to all versions). At that * point, we know specific header version, and can validate the * version-specific parts including section offsets and alignments. */ if (pp->ctp_magic != CTF_MAGIC) return (ctf_set_open_errno(errp, ECTF_NOCTFBUF)); if (pp->ctp_version == CTF_VERSION_2) { if (ctfsect->cts_size < sizeof (ctf_header_t)) return (ctf_set_open_errno(errp, ECTF_NOCTFBUF)); bcopy(ctfsect->cts_data, &hp, sizeof (hp)); hdrsz = sizeof (ctf_header_t); } else if (pp->ctp_version == CTF_VERSION_1) { const ctf_header_v1_t *h1p = (const ctf_header_v1_t *)ctfsect->cts_data; if (ctfsect->cts_size < sizeof (ctf_header_v1_t)) return (ctf_set_open_errno(errp, ECTF_NOCTFBUF)); bzero(&hp, sizeof (hp)); hp.cth_preamble = h1p->cth_preamble; hp.cth_objtoff = h1p->cth_objtoff; hp.cth_funcoff = h1p->cth_funcoff; hp.cth_typeoff = h1p->cth_typeoff; hp.cth_stroff = h1p->cth_stroff; hp.cth_strlen = h1p->cth_strlen; hdrsz = sizeof (ctf_header_v1_t); } else return (ctf_set_open_errno(errp, ECTF_CTFVERS)); size = hp.cth_stroff + hp.cth_strlen; ctf_dprintf("ctf_bufopen: uncompressed size=%lu\n", (ulong_t)size); if (hp.cth_lbloff > size || hp.cth_objtoff > size || hp.cth_funcoff > size || hp.cth_typeoff > size || hp.cth_stroff > size) return (ctf_set_open_errno(errp, ECTF_CORRUPT)); if (hp.cth_lbloff > hp.cth_objtoff || hp.cth_objtoff > hp.cth_funcoff || hp.cth_funcoff > hp.cth_typeoff || hp.cth_typeoff > hp.cth_stroff) return (ctf_set_open_errno(errp, ECTF_CORRUPT)); if ((hp.cth_lbloff & 3) || (hp.cth_objtoff & 1) || (hp.cth_funcoff & 1) || (hp.cth_typeoff & 3)) return (ctf_set_open_errno(errp, ECTF_CORRUPT)); /* * Once everything is determined to be valid, attempt to decompress * the CTF data buffer if it is compressed. Otherwise we just put * the data section's buffer pointer into ctf_buf, below. */ if (hp.cth_flags & CTF_F_COMPRESS) { size_t srclen, dstlen; const void *src; int rc = Z_OK; if (ctf_zopen(errp) == NULL) return (NULL); /* errp is set for us */ if ((base = ctf_data_alloc(size + hdrsz)) == MAP_FAILED) return (ctf_set_open_errno(errp, ECTF_ZALLOC)); bcopy(ctfsect->cts_data, base, hdrsz); ((ctf_preamble_t *)base)->ctp_flags &= ~CTF_F_COMPRESS; buf = (uchar_t *)base + hdrsz; src = (uchar_t *)ctfsect->cts_data + hdrsz; srclen = ctfsect->cts_size - hdrsz; dstlen = size; if ((rc = z_uncompress(buf, &dstlen, src, srclen)) != Z_OK) { ctf_dprintf("zlib inflate err: %s\n", z_strerror(rc)); ctf_data_free(base, size + hdrsz); return (ctf_set_open_errno(errp, ECTF_DECOMPRESS)); } if (dstlen != size) { ctf_dprintf("zlib inflate short -- got %lu of %lu " "bytes\n", (ulong_t)dstlen, (ulong_t)size); ctf_data_free(base, size + hdrsz); return (ctf_set_open_errno(errp, ECTF_CORRUPT)); } ctf_data_protect(base, size + hdrsz); } else { base = (void *)ctfsect->cts_data; buf = (uchar_t *)base + hdrsz; } /* * Once we have uncompressed and validated the CTF data buffer, we can * proceed with allocating a ctf_file_t and initializing it. */ if ((fp = ctf_alloc(sizeof (ctf_file_t))) == NULL) return (ctf_set_open_errno(errp, EAGAIN)); bzero(fp, sizeof (ctf_file_t)); fp->ctf_version = hp.cth_version; fp->ctf_fileops = &ctf_fileops[hp.cth_version]; bcopy(ctfsect, &fp->ctf_data, sizeof (ctf_sect_t)); if (symsect != NULL) { bcopy(symsect, &fp->ctf_symtab, sizeof (ctf_sect_t)); bcopy(strsect, &fp->ctf_strtab, sizeof (ctf_sect_t)); } if (fp->ctf_data.cts_name != NULL) fp->ctf_data.cts_name = ctf_strdup(fp->ctf_data.cts_name); if (fp->ctf_symtab.cts_name != NULL) fp->ctf_symtab.cts_name = ctf_strdup(fp->ctf_symtab.cts_name); if (fp->ctf_strtab.cts_name != NULL) fp->ctf_strtab.cts_name = ctf_strdup(fp->ctf_strtab.cts_name); if (fp->ctf_data.cts_name == NULL) fp->ctf_data.cts_name = _CTF_NULLSTR; if (fp->ctf_symtab.cts_name == NULL) fp->ctf_symtab.cts_name = _CTF_NULLSTR; if (fp->ctf_strtab.cts_name == NULL) fp->ctf_strtab.cts_name = _CTF_NULLSTR; fp->ctf_str[CTF_STRTAB_0].cts_strs = (const char *)buf + hp.cth_stroff; fp->ctf_str[CTF_STRTAB_0].cts_len = hp.cth_strlen; if (strsect != NULL) { fp->ctf_str[CTF_STRTAB_1].cts_strs = strsect->cts_data; fp->ctf_str[CTF_STRTAB_1].cts_len = strsect->cts_size; } fp->ctf_base = base; fp->ctf_buf = buf; fp->ctf_size = size + hdrsz; /* * If we have a parent container name and label, store the relocated * string pointers in the CTF container for easy access later. */ if (hp.cth_parlabel != 0) fp->ctf_parlabel = ctf_strptr(fp, hp.cth_parlabel); if (hp.cth_parname != 0) fp->ctf_parname = ctf_strptr(fp, hp.cth_parname); ctf_dprintf("ctf_bufopen: parent name %s (label %s)\n", fp->ctf_parname ? fp->ctf_parname : "<NULL>", fp->ctf_parlabel ? fp->ctf_parlabel : "<NULL>"); /* * If we have a symbol table section, allocate and initialize * the symtab translation table, pointed to by ctf_sxlate. */ if (symsect != NULL) { fp->ctf_nsyms = symsect->cts_size / symsect->cts_entsize; fp->ctf_sxlate = ctf_alloc(fp->ctf_nsyms * sizeof (uint_t)); if (fp->ctf_sxlate == NULL) { (void) ctf_set_open_errno(errp, EAGAIN); goto bad; } if ((err = init_symtab(fp, &hp, symsect, strsect)) != 0) { (void) ctf_set_open_errno(errp, err); goto bad; } } if ((err = init_types(fp, &hp)) != 0) { (void) ctf_set_open_errno(errp, err); goto bad; } /* * Initialize the ctf_lookup_by_name top-level dictionary. We keep an * array of type name prefixes and the corresponding ctf_hash to use. * NOTE: This code must be kept in sync with the code in ctf_update(). */ fp->ctf_lookups[0].ctl_prefix = "struct"; fp->ctf_lookups[0].ctl_len = strlen(fp->ctf_lookups[0].ctl_prefix); fp->ctf_lookups[0].ctl_hash = &fp->ctf_structs; fp->ctf_lookups[1].ctl_prefix = "union"; fp->ctf_lookups[1].ctl_len = strlen(fp->ctf_lookups[1].ctl_prefix); fp->ctf_lookups[1].ctl_hash = &fp->ctf_unions; fp->ctf_lookups[2].ctl_prefix = "enum"; fp->ctf_lookups[2].ctl_len = strlen(fp->ctf_lookups[2].ctl_prefix); fp->ctf_lookups[2].ctl_hash = &fp->ctf_enums; fp->ctf_lookups[3].ctl_prefix = _CTF_NULLSTR; fp->ctf_lookups[3].ctl_len = strlen(fp->ctf_lookups[3].ctl_prefix); fp->ctf_lookups[3].ctl_hash = &fp->ctf_names; fp->ctf_lookups[4].ctl_prefix = NULL; fp->ctf_lookups[4].ctl_len = 0; fp->ctf_lookups[4].ctl_hash = NULL; if (symsect != NULL) { if (symsect->cts_entsize == sizeof (Elf64_Sym)) (void) ctf_setmodel(fp, CTF_MODEL_LP64); else (void) ctf_setmodel(fp, CTF_MODEL_ILP32); } else (void) ctf_setmodel(fp, CTF_MODEL_NATIVE); fp->ctf_refcnt = 1; return (fp);bad: ctf_close(fp); return (NULL);}/* * Close the specified CTF container and free associated data structures. Note * that ctf_close() is a reference counted operation: if the specified file is * the parent of other active containers, its reference count will be greater * than one and it will be freed later when no active children exist. */voidctf_close(ctf_file_t *fp){ ctf_dtdef_t *dtd, *ntd; ctf_dmdef_t *dmd, *nmd; if (fp == NULL) return; /* allow ctf_close(NULL) to simplify caller code */ ctf_dprintf("ctf_close(%p) refcnt=%u\n", (void *)fp, fp->ctf_refcnt); if (fp->ctf_refcnt > 1) { fp->ctf_refcnt--; return; } for (dtd = ctf_list_next(&fp->ctf_dtdefs); dtd != NULL; dtd = ntd) { switch (CTF_INFO_KIND(dtd->dtd_data.ctt_info)) { case CTF_K_STRUCT: case CTF_K_UNION: case CTF_K_ENUM: for (dmd = ctf_list_next(&dtd->dtd_u.dtu_members); dmd != NULL; dmd = nmd) { if (dmd->dmd_name != NULL) { ctf_free(dmd->dmd_name, strlen(dmd->dmd_name) + 1); } nmd = ctf_list_next(dmd); ctf_free(dmd, sizeof (ctf_dmdef_t)); } break; case CTF_K_FUNCTION: ctf_free(dtd->dtd_u.dtu_argv, sizeof (ctf_id_t) * CTF_INFO_VLEN(dtd->dtd_data.ctt_info)); break; } if (dtd->dtd_name != NULL) ctf_free(dtd->dtd_name, strlen(dtd->dtd_name) + 1); ntd = ctf_list_next(dtd); ctf_free(dtd, sizeof (ctf_dtdef_t)); } if (fp->ctf_parent != NULL) ctf_close(fp->ctf_parent); if (fp->ctf_flags & LCTF_MMAP) { if (fp->ctf_data.cts_data != NULL) ctf_sect_munmap(&fp->ctf_data); if (fp->ctf_symtab.cts_data != NULL) ctf_sect_munmap(&fp->ctf_symtab); if (fp->ctf_strtab.cts_data != NULL) ctf_sect_munmap(&fp->ctf_strtab); } if (fp->ctf_data.cts_name != _CTF_NULLSTR && fp->ctf_data.cts_name != NULL) { ctf_free((char *)fp->ctf_data.cts_name, strlen(fp->ctf_data.cts_name) + 1); } if (fp->ctf_symtab.cts_name != _CTF_NULLSTR && fp->ctf_symtab.cts_name != NULL) { ctf_free((char *)fp->ctf_symtab.cts_name, strlen(fp->ctf_symtab.cts_name) + 1); } if (fp->ctf_strtab.cts_name != _CTF_NULLSTR && fp->ctf_strtab.cts_name != NULL) { ctf_free((char *)fp->ctf_strtab.cts_name, strlen(fp->ctf_strtab.cts_name) + 1); } if (fp->ctf_base != fp->ctf_data.cts_data && fp->ctf_base != NULL) ctf_data_free((void *)fp->ctf_base, fp->ctf_size); if (fp->ctf_sxlate != NULL) ctf_free(fp->ctf_sxlate, sizeof (uint_t) * fp->ctf_nsyms); if (fp->ctf_txlate != NULL) { ctf_free(fp->ctf_txlate, sizeof (uint_t) * (fp->ctf_typemax + 1)); } if (fp->ctf_ptrtab != NULL) { ctf_free(fp->ctf_ptrtab, sizeof (ushort_t) * (fp->ctf_typemax + 1)); } ctf_hash_destroy(&fp->ctf_structs); ctf_hash_destroy(&fp->ctf_unions); ctf_hash_destroy(&fp->ctf_enums); ctf_hash_destroy(&fp->ctf_names); ctf_free(fp, sizeof (ctf_file_t));}/* * Return the CTF handle for the parent CTF container, if one exists. * Otherwise return NULL to indicate this container has no imported parent. */ctf_file_t *ctf_parent_file(ctf_file_t *fp){ return (fp->ctf_parent);}/* * Return the name of the parent CTF container, if one exists. Otherwise * return NULL to indicate this container is a root container. */const char *ctf_parent_name(ctf_file_t *fp){ return (fp->ctf_parname);}/* * Import the types from the specified parent container by storing a pointer * to it in ctf_parent and incrementing its reference count. Only one parent * is allowed: if a parent already exists, it is replaced by the new parent. */intctf_import(ctf_file_t *fp, ctf_file_t *pfp){ if (fp == NULL || fp == pfp || (pfp != NULL && pfp->ctf_refcnt == 0)) return (ctf_set_errno(fp, EINVAL)); if (pfp != NULL && pfp->ctf_dmodel != fp->ctf_dmodel) return (ctf_set_errno(fp, ECTF_DMODEL)); if (fp->ctf_parent != NULL) ctf_close(fp->ctf_parent); if (pfp != NULL) { fp->ctf_flags |= LCTF_CHILD; pfp->ctf_refcnt++; } fp->ctf_parent = pfp; return (0);}/* * Set the data model constant for the CTF container. */intctf_setmodel(ctf_file_t *fp, int model){ const ctf_dmodel_t *dp; for (dp = _libctf_models; dp->ctd_name != NULL; dp++) { if (dp->ctd_code == model) { fp->ctf_dmodel = dp; return (0); } } return (ctf_set_errno(fp, EINVAL));}/* * Return the data model constant for the CTF container. */intctf_getmodel(ctf_file_t *fp){ return (fp->ctf_dmodel->ctd_code);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -