sync with FreeBSD
This commit is contained in:
parent
fbb8599f9a
commit
74f0118d99
226
external/cddl/osnet/dist/common/ctf/ctf_create.c
vendored
226
external/cddl/osnet/dist/common/ctf/ctf_create.c
vendored
@ -24,13 +24,15 @@
|
||||
* Copyright 2006 Sun Microsystems, Inc. All rights reserved.
|
||||
* Use is subject to license terms.
|
||||
*/
|
||||
|
||||
#pragma ident "%Z%%M% %I% %E% SMI"
|
||||
/*
|
||||
* Copyright (c) 2013, Joyent, Inc. All rights reserved.
|
||||
*/
|
||||
|
||||
#include <sys/sysmacros.h>
|
||||
#include <sys/param.h>
|
||||
#include <sys/mman.h>
|
||||
#include <ctf_impl.h>
|
||||
#include <sys/debug.h>
|
||||
|
||||
/*
|
||||
* This static string is used as the template for initially populating a
|
||||
@ -170,6 +172,51 @@ ctf_copy_membnames(ctf_dtdef_t *dtd, uchar_t *s)
|
||||
return (s);
|
||||
}
|
||||
|
||||
/*
|
||||
* Only types of dyanmic CTF containers contain reference counts. These
|
||||
* containers are marked RD/WR. Because of that we basically make this a no-op
|
||||
* for compatability with non-dynamic CTF sections. This is also a no-op for
|
||||
* types which are not dynamic types. It is the responsibility of the caller to
|
||||
* make sure it is a valid type. We help that caller out on debug builds.
|
||||
*
|
||||
* Note that the reference counts are not maintained for types that are not
|
||||
* within this container. In other words if we have a type in a parent, that
|
||||
* will not have its reference count increased. On the flip side, the parent
|
||||
* will not be allowed to remove dynamic types if it has children.
|
||||
*/
|
||||
static void
|
||||
ctf_ref_inc(ctf_file_t *fp, ctf_id_t tid)
|
||||
{
|
||||
ctf_dtdef_t *dtd = ctf_dtd_lookup(fp, tid);
|
||||
|
||||
if (dtd == NULL)
|
||||
return;
|
||||
|
||||
if (!(fp->ctf_flags & LCTF_RDWR))
|
||||
return;
|
||||
|
||||
dtd->dtd_ref++;
|
||||
}
|
||||
|
||||
/*
|
||||
* Just as with ctf_ref_inc, this is a no-op on non-writeable containers and the
|
||||
* caller should ensure that this is already a valid type.
|
||||
*/
|
||||
static void
|
||||
ctf_ref_dec(ctf_file_t *fp, ctf_id_t tid)
|
||||
{
|
||||
ctf_dtdef_t *dtd = ctf_dtd_lookup(fp, tid);
|
||||
|
||||
if (dtd == NULL)
|
||||
return;
|
||||
|
||||
if (!(fp->ctf_flags & LCTF_RDWR))
|
||||
return;
|
||||
|
||||
ASSERT(dtd->dtd_ref >= 1);
|
||||
dtd->dtd_ref--;
|
||||
}
|
||||
|
||||
/*
|
||||
* If the specified CTF container is writable and has been modified, reload
|
||||
* this container with the updated type definitions. In order to make this
|
||||
@ -184,6 +231,10 @@ ctf_copy_membnames(ctf_dtdef_t *dtd, uchar_t *s)
|
||||
* ctf_bufopen() will return a new ctf_file_t, but we want to keep the fp
|
||||
* constant for the caller, so after ctf_bufopen() returns, we use bcopy to
|
||||
* swap the interior of the old and new ctf_file_t's, and then free the old.
|
||||
*
|
||||
* Note that the lists of dynamic types stays around and the resulting container
|
||||
* is still writeable. Furthermore, the reference counts that are on the dtd's
|
||||
* are still valid.
|
||||
*/
|
||||
int
|
||||
ctf_update(ctf_file_t *fp)
|
||||
@ -368,7 +419,7 @@ ctf_update(ctf_file_t *fp)
|
||||
* is successful, we then switch nfp and fp and free the old container.
|
||||
*/
|
||||
ctf_data_protect(buf, size);
|
||||
cts.cts_name = __UNCONST(_CTF_SECTION);
|
||||
cts.cts_name = _CTF_SECTION;
|
||||
cts.cts_type = SHT_PROGBITS;
|
||||
cts.cts_flags = 0;
|
||||
cts.cts_data = buf;
|
||||
@ -436,6 +487,7 @@ ctf_dtd_delete(ctf_file_t *fp, ctf_dtdef_t *dtd)
|
||||
ctf_dtdef_t *p, **q = &fp->ctf_dthash[h];
|
||||
ctf_dmdef_t *dmd, *nmd;
|
||||
size_t len;
|
||||
int kind, i;
|
||||
|
||||
for (p = *q; p != NULL; p = p->dtd_hash) {
|
||||
if (p != dtd)
|
||||
@ -447,7 +499,8 @@ ctf_dtd_delete(ctf_file_t *fp, ctf_dtdef_t *dtd)
|
||||
if (p != NULL)
|
||||
*q = p->dtd_hash;
|
||||
|
||||
switch (CTF_INFO_KIND(dtd->dtd_data.ctt_info)) {
|
||||
kind = CTF_INFO_KIND(dtd->dtd_data.ctt_info);
|
||||
switch (kind) {
|
||||
case CTF_K_STRUCT:
|
||||
case CTF_K_UNION:
|
||||
case CTF_K_ENUM:
|
||||
@ -458,14 +511,33 @@ ctf_dtd_delete(ctf_file_t *fp, ctf_dtdef_t *dtd)
|
||||
ctf_free(dmd->dmd_name, len);
|
||||
fp->ctf_dtstrlen -= len;
|
||||
}
|
||||
if (kind != CTF_K_ENUM)
|
||||
ctf_ref_dec(fp, dmd->dmd_type);
|
||||
nmd = ctf_list_next(dmd);
|
||||
ctf_free(dmd, sizeof (ctf_dmdef_t));
|
||||
}
|
||||
break;
|
||||
case CTF_K_FUNCTION:
|
||||
ctf_ref_dec(fp, dtd->dtd_data.ctt_type);
|
||||
for (i = 0; i < CTF_INFO_VLEN(dtd->dtd_data.ctt_info); i++)
|
||||
if (dtd->dtd_u.dtu_argv[i] != 0)
|
||||
ctf_ref_dec(fp, dtd->dtd_u.dtu_argv[i]);
|
||||
ctf_free(dtd->dtd_u.dtu_argv, sizeof (ctf_id_t) *
|
||||
CTF_INFO_VLEN(dtd->dtd_data.ctt_info));
|
||||
break;
|
||||
case CTF_K_ARRAY:
|
||||
ctf_ref_dec(fp, dtd->dtd_u.dtu_arr.ctr_contents);
|
||||
ctf_ref_dec(fp, dtd->dtd_u.dtu_arr.ctr_index);
|
||||
break;
|
||||
case CTF_K_TYPEDEF:
|
||||
ctf_ref_dec(fp, dtd->dtd_data.ctt_type);
|
||||
break;
|
||||
case CTF_K_POINTER:
|
||||
case CTF_K_VOLATILE:
|
||||
case CTF_K_CONST:
|
||||
case CTF_K_RESTRICT:
|
||||
ctf_ref_dec(fp, dtd->dtd_data.ctt_type);
|
||||
break;
|
||||
}
|
||||
|
||||
if (dtd->dtd_name) {
|
||||
@ -499,12 +571,14 @@ ctf_dtd_lookup(ctf_file_t *fp, ctf_id_t type)
|
||||
* Discard all of the dynamic type definitions that have been added to the
|
||||
* container since the last call to ctf_update(). We locate such types by
|
||||
* scanning the list and deleting elements that have type IDs greater than
|
||||
* ctf_dtoldid, which is set by ctf_update(), above.
|
||||
* ctf_dtoldid, which is set by ctf_update(), above. Note that to work properly
|
||||
* with our reference counting schemes, we must delete the dynamic list in
|
||||
* reverse.
|
||||
*/
|
||||
int
|
||||
ctf_discard(ctf_file_t *fp)
|
||||
{
|
||||
ctf_dtdef_t *dtd, *ntd = NULL;
|
||||
ctf_dtdef_t *dtd, *ntd;
|
||||
|
||||
if (!(fp->ctf_flags & LCTF_RDWR))
|
||||
return (ctf_set_errno(fp, ECTF_RDONLY));
|
||||
@ -512,11 +586,11 @@ ctf_discard(ctf_file_t *fp)
|
||||
if (!(fp->ctf_flags & LCTF_DIRTY))
|
||||
return (0); /* no update required */
|
||||
|
||||
for (dtd = ctf_list_next(&fp->ctf_dtdefs); dtd != NULL; dtd = ntd) {
|
||||
if (dtd->dtd_type <= fp->ctf_dtoldid)
|
||||
for (dtd = ctf_list_prev(&fp->ctf_dtdefs); dtd != NULL; dtd = ntd) {
|
||||
ntd = ctf_list_prev(dtd);
|
||||
if (CTF_TYPE_TO_INDEX(dtd->dtd_type) <= fp->ctf_dtoldid)
|
||||
continue; /* skip types that have been committed */
|
||||
|
||||
ntd = ctf_list_next(dtd);
|
||||
ctf_dtd_delete(fp, dtd);
|
||||
}
|
||||
|
||||
@ -618,6 +692,8 @@ ctf_add_reftype(ctf_file_t *fp, uint_t flag, ctf_id_t ref, uint_t kind)
|
||||
if ((type = ctf_add_generic(fp, flag, NULL, &dtd)) == CTF_ERR)
|
||||
return (CTF_ERR); /* errno is set for us */
|
||||
|
||||
ctf_ref_inc(fp, ref);
|
||||
|
||||
dtd->dtd_data.ctt_info = CTF_TYPE_INFO(kind, flag, 0);
|
||||
dtd->dtd_data.ctt_type = (ushort_t)ref;
|
||||
|
||||
@ -649,16 +725,29 @@ ctf_add_array(ctf_file_t *fp, uint_t flag, const ctf_arinfo_t *arp)
|
||||
{
|
||||
ctf_dtdef_t *dtd;
|
||||
ctf_id_t type;
|
||||
ctf_file_t *fpd;
|
||||
|
||||
if (arp == NULL)
|
||||
return (ctf_set_errno(fp, EINVAL));
|
||||
|
||||
fpd = fp;
|
||||
if (ctf_lookup_by_id(&fpd, arp->ctr_contents) == NULL &&
|
||||
ctf_dtd_lookup(fp, arp->ctr_contents) == NULL)
|
||||
return (ctf_set_errno(fp, ECTF_BADID));
|
||||
|
||||
fpd = fp;
|
||||
if (ctf_lookup_by_id(&fpd, arp->ctr_index) == NULL &&
|
||||
ctf_dtd_lookup(fp, arp->ctr_index) == NULL)
|
||||
return (ctf_set_errno(fp, ECTF_BADID));
|
||||
|
||||
if ((type = ctf_add_generic(fp, flag, NULL, &dtd)) == CTF_ERR)
|
||||
return (CTF_ERR); /* errno is set for us */
|
||||
|
||||
dtd->dtd_data.ctt_info = CTF_TYPE_INFO(CTF_K_ARRAY, flag, 0);
|
||||
dtd->dtd_data.ctt_size = 0;
|
||||
dtd->dtd_u.dtu_arr = *arp;
|
||||
ctf_ref_inc(fp, arp->ctr_contents);
|
||||
ctf_ref_inc(fp, arp->ctr_index);
|
||||
|
||||
return (type);
|
||||
}
|
||||
@ -666,6 +755,7 @@ ctf_add_array(ctf_file_t *fp, uint_t flag, const ctf_arinfo_t *arp)
|
||||
int
|
||||
ctf_set_array(ctf_file_t *fp, ctf_id_t type, const ctf_arinfo_t *arp)
|
||||
{
|
||||
ctf_file_t *fpd;
|
||||
ctf_dtdef_t *dtd = ctf_dtd_lookup(fp, type);
|
||||
|
||||
if (!(fp->ctf_flags & LCTF_RDWR))
|
||||
@ -674,8 +764,22 @@ ctf_set_array(ctf_file_t *fp, ctf_id_t type, const ctf_arinfo_t *arp)
|
||||
if (dtd == NULL || CTF_INFO_KIND(dtd->dtd_data.ctt_info) != CTF_K_ARRAY)
|
||||
return (ctf_set_errno(fp, ECTF_BADID));
|
||||
|
||||
fpd = fp;
|
||||
if (ctf_lookup_by_id(&fpd, arp->ctr_contents) == NULL &&
|
||||
ctf_dtd_lookup(fp, arp->ctr_contents) == NULL)
|
||||
return (ctf_set_errno(fp, ECTF_BADID));
|
||||
|
||||
fpd = fp;
|
||||
if (ctf_lookup_by_id(&fpd, arp->ctr_index) == NULL &&
|
||||
ctf_dtd_lookup(fp, arp->ctr_index) == NULL)
|
||||
return (ctf_set_errno(fp, ECTF_BADID));
|
||||
|
||||
ctf_ref_dec(fp, dtd->dtd_u.dtu_arr.ctr_contents);
|
||||
ctf_ref_dec(fp, dtd->dtd_u.dtu_arr.ctr_index);
|
||||
fp->ctf_flags |= LCTF_DIRTY;
|
||||
dtd->dtd_u.dtu_arr = *arp;
|
||||
ctf_ref_inc(fp, arp->ctr_contents);
|
||||
ctf_ref_inc(fp, arp->ctr_index);
|
||||
|
||||
return (0);
|
||||
}
|
||||
@ -687,7 +791,9 @@ ctf_add_function(ctf_file_t *fp, uint_t flag,
|
||||
ctf_dtdef_t *dtd;
|
||||
ctf_id_t type;
|
||||
uint_t vlen;
|
||||
int i;
|
||||
ctf_id_t *vdat = NULL;
|
||||
ctf_file_t *fpd;
|
||||
|
||||
if (ctc == NULL || (ctc->ctc_flags & ~CTF_FUNC_VARARG) != 0 ||
|
||||
(ctc->ctc_argc != 0 && argv == NULL))
|
||||
@ -700,6 +806,18 @@ ctf_add_function(ctf_file_t *fp, uint_t flag,
|
||||
if (vlen > CTF_MAX_VLEN)
|
||||
return (ctf_set_errno(fp, EOVERFLOW));
|
||||
|
||||
fpd = fp;
|
||||
if (ctf_lookup_by_id(&fpd, ctc->ctc_return) == NULL &&
|
||||
ctf_dtd_lookup(fp, ctc->ctc_return) == NULL)
|
||||
return (ctf_set_errno(fp, ECTF_BADID));
|
||||
|
||||
for (i = 0; i < ctc->ctc_argc; i++) {
|
||||
fpd = fp;
|
||||
if (ctf_lookup_by_id(&fpd, argv[i]) == NULL &&
|
||||
ctf_dtd_lookup(fp, argv[i]) == NULL)
|
||||
return (ctf_set_errno(fp, ECTF_BADID));
|
||||
}
|
||||
|
||||
if (vlen != 0 && (vdat = ctf_alloc(sizeof (ctf_id_t) * vlen)) == NULL)
|
||||
return (ctf_set_errno(fp, EAGAIN));
|
||||
|
||||
@ -711,6 +829,10 @@ ctf_add_function(ctf_file_t *fp, uint_t flag,
|
||||
dtd->dtd_data.ctt_info = CTF_TYPE_INFO(CTF_K_FUNCTION, flag, vlen);
|
||||
dtd->dtd_data.ctt_type = (ushort_t)ctc->ctc_return;
|
||||
|
||||
ctf_ref_inc(fp, ctc->ctc_return);
|
||||
for (i = 0; i < ctc->ctc_argc; i++)
|
||||
ctf_ref_inc(fp, argv[i]);
|
||||
|
||||
bcopy(argv, vdat, sizeof (ctf_id_t) * ctc->ctc_argc);
|
||||
if (ctc->ctc_flags & CTF_FUNC_VARARG)
|
||||
vdat[vlen - 1] = 0; /* add trailing zero to indicate varargs */
|
||||
@ -829,8 +951,11 @@ ctf_add_typedef(ctf_file_t *fp, uint_t flag, const char *name, ctf_id_t ref)
|
||||
{
|
||||
ctf_dtdef_t *dtd;
|
||||
ctf_id_t type;
|
||||
ctf_file_t *fpd;
|
||||
|
||||
if (ref == CTF_ERR || ref < 0 || ref > CTF_MAX_TYPE)
|
||||
fpd = fp;
|
||||
if (ref == CTF_ERR || (ctf_lookup_by_id(&fpd, ref) == NULL &&
|
||||
ctf_dtd_lookup(fp, ref) == NULL))
|
||||
return (ctf_set_errno(fp, EINVAL));
|
||||
|
||||
if ((type = ctf_add_generic(fp, flag, name, &dtd)) == CTF_ERR)
|
||||
@ -838,6 +963,7 @@ ctf_add_typedef(ctf_file_t *fp, uint_t flag, const char *name, ctf_id_t ref)
|
||||
|
||||
dtd->dtd_data.ctt_info = CTF_TYPE_INFO(CTF_K_TYPEDEF, flag, 0);
|
||||
dtd->dtd_data.ctt_type = (ushort_t)ref;
|
||||
ctf_ref_inc(fp, ref);
|
||||
|
||||
return (type);
|
||||
}
|
||||
@ -1012,6 +1138,45 @@ ctf_add_member(ctf_file_t *fp, ctf_id_t souid, const char *name, ctf_id_t type)
|
||||
if (s != NULL)
|
||||
fp->ctf_dtstrlen += strlen(s) + 1;
|
||||
|
||||
ctf_ref_inc(fp, type);
|
||||
fp->ctf_flags |= LCTF_DIRTY;
|
||||
return (0);
|
||||
}
|
||||
|
||||
/*
|
||||
* This removes a type from the dynamic section. This will fail if the type is
|
||||
* referenced by another type. Note that the CTF ID is never reused currently by
|
||||
* CTF. Note that if this container is a parent container then we just outright
|
||||
* refuse to remove the type. There currently is no notion of searching for the
|
||||
* ctf_dtdef_t in parent containers. If there is, then this constraint could
|
||||
* become finer grained.
|
||||
*/
|
||||
int
|
||||
ctf_delete_type(ctf_file_t *fp, ctf_id_t type)
|
||||
{
|
||||
ctf_file_t *fpd;
|
||||
ctf_dtdef_t *dtd = ctf_dtd_lookup(fp, type);
|
||||
|
||||
if (!(fp->ctf_flags & LCTF_RDWR))
|
||||
return (ctf_set_errno(fp, ECTF_RDONLY));
|
||||
|
||||
/*
|
||||
* We want to give as useful an errno as possible. That means that we
|
||||
* want to distinguish between a type which does not exist and one for
|
||||
* which the type is not dynamic.
|
||||
*/
|
||||
fpd = fp;
|
||||
if (ctf_lookup_by_id(&fpd, type) == NULL &&
|
||||
ctf_dtd_lookup(fp, type) == NULL)
|
||||
return (CTF_ERR); /* errno is set for us */
|
||||
|
||||
if (dtd == NULL)
|
||||
return (ctf_set_errno(fp, ECTF_NOTDYN));
|
||||
|
||||
if (dtd->dtd_ref != 0 || fp->ctf_refcnt > 1)
|
||||
return (ctf_set_errno(fp, ECTF_REFERENCED));
|
||||
|
||||
ctf_dtd_delete(fp, dtd);
|
||||
fp->ctf_flags |= LCTF_DIRTY;
|
||||
return (0);
|
||||
}
|
||||
@ -1107,6 +1272,9 @@ ctf_add_type(ctf_file_t *dst_fp, ctf_file_t *src_fp, ctf_id_t src_type)
|
||||
ctf_hash_t *hp;
|
||||
ctf_helem_t *hep;
|
||||
|
||||
if (dst_fp == src_fp)
|
||||
return (src_type);
|
||||
|
||||
if (!(dst_fp->ctf_flags & LCTF_RDWR))
|
||||
return (ctf_set_errno(dst_fp, ECTF_RDONLY));
|
||||
|
||||
@ -1149,10 +1317,13 @@ ctf_add_type(ctf_file_t *dst_fp, ctf_file_t *src_fp, ctf_id_t src_type)
|
||||
* unless dst_type is a forward declaration and src_type is a struct,
|
||||
* union, or enum (i.e. the definition of the previous forward decl).
|
||||
*/
|
||||
if (dst_type != CTF_ERR && dst_kind != kind && (
|
||||
dst_kind != CTF_K_FORWARD || (kind != CTF_K_ENUM &&
|
||||
kind != CTF_K_STRUCT && kind != CTF_K_UNION)))
|
||||
if (dst_type != CTF_ERR && dst_kind != kind) {
|
||||
if (dst_kind != CTF_K_FORWARD || (kind != CTF_K_ENUM &&
|
||||
kind != CTF_K_STRUCT && kind != CTF_K_UNION))
|
||||
return (ctf_set_errno(dst_fp, ECTF_CONFLICT));
|
||||
else
|
||||
dst_type = CTF_ERR;
|
||||
}
|
||||
|
||||
/*
|
||||
* If the non-empty name was not found in the appropriate hash, search
|
||||
@ -1161,14 +1332,27 @@ ctf_add_type(ctf_file_t *dst_fp, ctf_file_t *src_fp, ctf_id_t src_type)
|
||||
* we are looking for. This is necessary to permit ctf_add_type() to
|
||||
* operate recursively on entities such as a struct that contains a
|
||||
* pointer member that refers to the same struct type.
|
||||
*
|
||||
* In the case of integer and floating point types, we match using the
|
||||
* type encoding as well - else we may incorrectly return a bitfield
|
||||
* type, for instance.
|
||||
*/
|
||||
if (dst_type == CTF_ERR && name[0] != '\0') {
|
||||
for (dtd = ctf_list_prev(&dst_fp->ctf_dtdefs); dtd != NULL &&
|
||||
dtd->dtd_type > dst_fp->ctf_dtoldid;
|
||||
CTF_TYPE_TO_INDEX(dtd->dtd_type) > dst_fp->ctf_dtoldid;
|
||||
dtd = ctf_list_prev(dtd)) {
|
||||
if (CTF_INFO_KIND(dtd->dtd_data.ctt_info) == kind &&
|
||||
dtd->dtd_name != NULL &&
|
||||
strcmp(dtd->dtd_name, name) == 0)
|
||||
if (CTF_INFO_KIND(dtd->dtd_data.ctt_info) != kind ||
|
||||
dtd->dtd_name == NULL ||
|
||||
strcmp(dtd->dtd_name, name) != 0)
|
||||
continue;
|
||||
if (kind == CTF_K_INTEGER || kind == CTF_K_FLOAT) {
|
||||
if (ctf_type_encoding(src_fp, src_type,
|
||||
&src_en) != 0)
|
||||
continue;
|
||||
if (bcmp(&src_en, &dtd->dtd_u.dtu_enc,
|
||||
sizeof (ctf_encoding_t)) != 0)
|
||||
continue;
|
||||
}
|
||||
return (dtd->dtd_type);
|
||||
}
|
||||
}
|
||||
@ -1317,6 +1501,14 @@ ctf_add_type(ctf_file_t *dst_fp, ctf_file_t *src_fp, ctf_id_t src_type)
|
||||
|
||||
if (errs)
|
||||
return (CTF_ERR); /* errno is set for us */
|
||||
|
||||
/*
|
||||
* Now that we know that we can't fail, we go through and bump
|
||||
* all the reference counts on the member types.
|
||||
*/
|
||||
for (dmd = ctf_list_next(&dtd->dtd_u.dtu_members);
|
||||
dmd != NULL; dmd = ctf_list_next(dmd))
|
||||
ctf_ref_inc(dst_fp, dmd->dmd_type);
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -23,8 +23,9 @@
|
||||
* Copyright 2003 Sun Microsystems, Inc. All rights reserved.
|
||||
* Use is subject to license terms.
|
||||
*/
|
||||
|
||||
#pragma ident "%Z%%M% %I% %E% SMI"
|
||||
/*
|
||||
* Copyright (c) 2012, Joyent, Inc.
|
||||
*/
|
||||
|
||||
#include <ctf_impl.h>
|
||||
|
||||
@ -73,6 +74,8 @@ static const char *const _ctf_errlist[] = {
|
||||
"Limit on number of dynamic types reached", /* ECTF_FULL */
|
||||
"Duplicate member name definition", /* ECTF_DUPMEMBER */
|
||||
"Conflicting type is already defined", /* ECTF_CONFLICT */
|
||||
"Type has outstanding references", /* ECTF_REFERENCED */
|
||||
"Type is not a dynamic type" /* ECTF_NOTDYN */
|
||||
};
|
||||
|
||||
static const int _ctf_nerr = sizeof (_ctf_errlist) / sizeof (_ctf_errlist[0]);
|
||||
|
10
external/cddl/osnet/dist/common/ctf/ctf_impl.h
vendored
10
external/cddl/osnet/dist/common/ctf/ctf_impl.h
vendored
@ -24,12 +24,13 @@
|
||||
* Copyright 2006 Sun Microsystems, Inc. All rights reserved.
|
||||
* Use is subject to license terms.
|
||||
*/
|
||||
/*
|
||||
* Copyright (c) 2012, Joyent, Inc. All rights reserved.
|
||||
*/
|
||||
|
||||
#ifndef _CTF_IMPL_H
|
||||
#define _CTF_IMPL_H
|
||||
|
||||
#pragma ident "%Z%%M% %I% %E% SMI"
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/errno.h>
|
||||
#include <sys/sysmacros.h>
|
||||
@ -149,6 +150,7 @@ typedef struct ctf_dtdef {
|
||||
char *dtd_name; /* name associated with definition (if any) */
|
||||
ctf_id_t dtd_type; /* type identifier for this definition */
|
||||
ctf_type_t dtd_data; /* type node (see <sys/ctf.h>) */
|
||||
int dtd_ref; /* recfount for dyanmic types */
|
||||
union {
|
||||
ctf_list_t dtu_members; /* struct, union, or enum */
|
||||
ctf_arinfo_t dtu_arr; /* array */
|
||||
@ -269,7 +271,9 @@ enum {
|
||||
ECTF_DTFULL, /* CTF type is full (no more members allowed) */
|
||||
ECTF_FULL, /* CTF container is full */
|
||||
ECTF_DUPMEMBER, /* duplicate member name definition */
|
||||
ECTF_CONFLICT /* conflicting type definition present */
|
||||
ECTF_CONFLICT, /* conflicting type definition present */
|
||||
ECTF_REFERENCED, /* type has outstanding references */
|
||||
ECTF_NOTDYN /* type is not a dynamic type */
|
||||
};
|
||||
|
||||
extern ssize_t ctf_get_ctt_size(const ctf_file_t *, const ctf_type_t *,
|
||||
|
@ -54,9 +54,9 @@ extract_label_info(ctf_file_t *fp, const ctf_lblent_t **ctl, uint_t *num_labels)
|
||||
const char *
|
||||
ctf_label_topmost(ctf_file_t *fp)
|
||||
{
|
||||
const ctf_lblent_t *ctlp = NULL;
|
||||
const ctf_lblent_t *ctlp = NULL; // XXX: gcc
|
||||
const char *s;
|
||||
uint_t num_labels = 0;
|
||||
uint_t num_labels = 0; // XXX: gcc
|
||||
|
||||
if (extract_label_info(fp, &ctlp, &num_labels) == CTF_ERR)
|
||||
return (NULL); /* errno is set */
|
||||
@ -79,8 +79,8 @@ ctf_label_topmost(ctf_file_t *fp)
|
||||
int
|
||||
ctf_label_iter(ctf_file_t *fp, ctf_label_f *func, void *arg)
|
||||
{
|
||||
const ctf_lblent_t *ctlp = NULL;
|
||||
uint_t i, num_labels = 0;
|
||||
const ctf_lblent_t *ctlp = NULL; // XXX: gcc
|
||||
uint_t i, num_labels = 0; // XXX: gcc
|
||||
ctf_lblinfo_t linfo;
|
||||
const char *lname;
|
||||
int rc;
|
||||
|
105
external/cddl/osnet/dist/common/ctf/ctf_open.c
vendored
105
external/cddl/osnet/dist/common/ctf/ctf_open.c
vendored
@ -24,8 +24,9 @@
|
||||
* Copyright 2006 Sun Microsystems, Inc. All rights reserved.
|
||||
* Use is subject to license terms.
|
||||
*/
|
||||
|
||||
#pragma ident "%Z%%M% %I% %E% SMI"
|
||||
/*
|
||||
* Copyright (c) 2013, Joyent, Inc. All rights reserved.
|
||||
*/
|
||||
|
||||
#include <ctf_impl.h>
|
||||
#include <sys/mman.h>
|
||||
@ -786,6 +787,92 @@ bad:
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
/*
|
||||
* Dupliate a ctf_file_t and its underlying section information into a new
|
||||
* container. This works by copying the three ctf_sect_t's of the original
|
||||
* container if they exist and passing those into ctf_bufopen. To copy those, we
|
||||
* mmap anonymous memory with ctf_data_alloc and bcopy the data across. It's not
|
||||
* the cheapest thing, but it's what we've got.
|
||||
*/
|
||||
ctf_file_t *
|
||||
ctf_dup(ctf_file_t *ofp)
|
||||
{
|
||||
ctf_file_t *fp;
|
||||
ctf_sect_t ctfsect, symsect, strsect;
|
||||
ctf_sect_t *ctp, *symp, *strp;
|
||||
void *cbuf, *symbuf, *strbuf;
|
||||
int err;
|
||||
|
||||
cbuf = symbuf = strbuf = NULL;
|
||||
/*
|
||||
* The ctfsect isn't allowed to not exist, but the symbol and string
|
||||
* section might not. We only need to copy the data of the section, not
|
||||
* the name, as ctf_bufopen will take care of that.
|
||||
*/
|
||||
bcopy(&ofp->ctf_data, &ctfsect, sizeof (ctf_sect_t));
|
||||
cbuf = ctf_data_alloc(ctfsect.cts_size);
|
||||
if (cbuf == NULL) {
|
||||
(void) ctf_set_errno(ofp, ECTF_MMAP);
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
bcopy(ctfsect.cts_data, cbuf, ctfsect.cts_size);
|
||||
ctf_data_protect(cbuf, ctfsect.cts_size);
|
||||
ctfsect.cts_data = cbuf;
|
||||
ctfsect.cts_offset = 0;
|
||||
ctp = &ctfsect;
|
||||
|
||||
if (ofp->ctf_symtab.cts_data != NULL) {
|
||||
bcopy(&ofp->ctf_symtab, &symsect, sizeof (ctf_sect_t));
|
||||
symbuf = ctf_data_alloc(symsect.cts_size);
|
||||
if (symbuf == NULL) {
|
||||
(void) ctf_set_errno(ofp, ECTF_MMAP);
|
||||
goto err;
|
||||
}
|
||||
bcopy(symsect.cts_data, symbuf, symsect.cts_size);
|
||||
ctf_data_protect(symbuf, symsect.cts_size);
|
||||
symsect.cts_data = symbuf;
|
||||
symsect.cts_offset = 0;
|
||||
symp = &symsect;
|
||||
} else {
|
||||
symp = NULL;
|
||||
}
|
||||
|
||||
if (ofp->ctf_strtab.cts_data != NULL) {
|
||||
bcopy(&ofp->ctf_strtab, &strsect, sizeof (ctf_sect_t));
|
||||
strbuf = ctf_data_alloc(strsect.cts_size);
|
||||
if (strbuf == NULL) {
|
||||
(void) ctf_set_errno(ofp, ECTF_MMAP);
|
||||
goto err;
|
||||
}
|
||||
bcopy(strsect.cts_data, strbuf, strsect.cts_size);
|
||||
ctf_data_protect(strbuf, strsect.cts_size);
|
||||
strsect.cts_data = strbuf;
|
||||
strsect.cts_offset = 0;
|
||||
strp = &strsect;
|
||||
} else {
|
||||
strp = NULL;
|
||||
}
|
||||
|
||||
fp = ctf_bufopen(ctp, symp, strp, &err);
|
||||
if (fp == NULL) {
|
||||
(void) ctf_set_errno(ofp, err);
|
||||
goto err;
|
||||
}
|
||||
|
||||
fp->ctf_flags |= LCTF_MMAP;
|
||||
|
||||
return (fp);
|
||||
|
||||
err:
|
||||
ctf_data_free(cbuf, ctfsect.cts_size);
|
||||
if (symbuf != NULL)
|
||||
ctf_data_free(symbuf, symsect.cts_size);
|
||||
if (strbuf != NULL)
|
||||
ctf_data_free(strbuf, strsect.cts_size);
|
||||
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
|
||||
@ -810,8 +897,12 @@ ctf_close(ctf_file_t *fp)
|
||||
if (fp->ctf_parent != NULL)
|
||||
ctf_close(fp->ctf_parent);
|
||||
|
||||
for (dtd = ctf_list_next(&fp->ctf_dtdefs); dtd != NULL; dtd = ntd) {
|
||||
ntd = ctf_list_next(dtd);
|
||||
/*
|
||||
* Note, to work properly with reference counting on the dynamic
|
||||
* section, we must delete the list in reverse.
|
||||
*/
|
||||
for (dtd = ctf_list_prev(&fp->ctf_dtdefs); dtd != NULL; dtd = ntd) {
|
||||
ntd = ctf_list_prev(dtd);
|
||||
ctf_dtd_delete(fp, dtd);
|
||||
}
|
||||
|
||||
@ -828,19 +919,19 @@ ctf_close(ctf_file_t *fp)
|
||||
|
||||
if (fp->ctf_data.cts_name != _CTF_NULLSTR &&
|
||||
fp->ctf_data.cts_name != NULL) {
|
||||
ctf_free((char *)fp->ctf_data.cts_name,
|
||||
ctf_free(__UNCONST(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,
|
||||
ctf_free(__UNCONST(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,
|
||||
ctf_free(__UNCONST(fp->ctf_strtab.cts_name),
|
||||
strlen(fp->ctf_strtab.cts_name) + 1);
|
||||
}
|
||||
|
||||
|
43
external/cddl/osnet/dist/common/ctf/ctf_types.c
vendored
43
external/cddl/osnet/dist/common/ctf/ctf_types.c
vendored
@ -25,8 +25,6 @@
|
||||
* Use is subject to license terms.
|
||||
*/
|
||||
|
||||
#pragma ident "%Z%%M% %I% %E% SMI"
|
||||
|
||||
#include <ctf_impl.h>
|
||||
|
||||
ssize_t
|
||||
@ -199,8 +197,9 @@ ctf_type_resolve(ctf_file_t *fp, ctf_id_t type)
|
||||
* Lookup the given type ID and print a string name for it into buf. Return
|
||||
* the actual number of bytes (not including \0) needed to format the name.
|
||||
*/
|
||||
ssize_t
|
||||
ctf_type_lname(ctf_file_t *fp, ctf_id_t type, char *buf, size_t len)
|
||||
static ssize_t
|
||||
ctf_type_qlname(ctf_file_t *fp, ctf_id_t type, char *buf, size_t len,
|
||||
const char *qname)
|
||||
{
|
||||
ctf_decl_t cd;
|
||||
ctf_decl_node_t *cdp;
|
||||
@ -255,6 +254,8 @@ ctf_type_lname(ctf_file_t *fp, ctf_id_t type, char *buf, size_t len)
|
||||
case CTF_K_INTEGER:
|
||||
case CTF_K_FLOAT:
|
||||
case CTF_K_TYPEDEF:
|
||||
if (qname != NULL)
|
||||
ctf_decl_sprintf(&cd, "%s`", qname);
|
||||
ctf_decl_sprintf(&cd, "%s", name);
|
||||
break;
|
||||
case CTF_K_POINTER:
|
||||
@ -268,13 +269,22 @@ ctf_type_lname(ctf_file_t *fp, ctf_id_t type, char *buf, size_t len)
|
||||
break;
|
||||
case CTF_K_STRUCT:
|
||||
case CTF_K_FORWARD:
|
||||
ctf_decl_sprintf(&cd, "struct %s", name);
|
||||
ctf_decl_sprintf(&cd, "struct ");
|
||||
if (qname != NULL)
|
||||
ctf_decl_sprintf(&cd, "%s`", qname);
|
||||
ctf_decl_sprintf(&cd, "%s", name);
|
||||
break;
|
||||
case CTF_K_UNION:
|
||||
ctf_decl_sprintf(&cd, "union %s", name);
|
||||
ctf_decl_sprintf(&cd, "union ");
|
||||
if (qname != NULL)
|
||||
ctf_decl_sprintf(&cd, "%s`", qname);
|
||||
ctf_decl_sprintf(&cd, "%s", name);
|
||||
break;
|
||||
case CTF_K_ENUM:
|
||||
ctf_decl_sprintf(&cd, "enum %s", name);
|
||||
ctf_decl_sprintf(&cd, "enum ");
|
||||
if (qname != NULL)
|
||||
ctf_decl_sprintf(&cd, "%s`", qname);
|
||||
ctf_decl_sprintf(&cd, "%s", name);
|
||||
break;
|
||||
case CTF_K_VOLATILE:
|
||||
ctf_decl_sprintf(&cd, "volatile");
|
||||
@ -301,6 +311,12 @@ ctf_type_lname(ctf_file_t *fp, ctf_id_t type, char *buf, size_t len)
|
||||
return (cd.cd_len);
|
||||
}
|
||||
|
||||
ssize_t
|
||||
ctf_type_lname(ctf_file_t *fp, ctf_id_t type, char *buf, size_t len)
|
||||
{
|
||||
return (ctf_type_qlname(fp, type, buf, len, NULL));
|
||||
}
|
||||
|
||||
/*
|
||||
* Lookup the given type ID and print a string name for it into buf. If buf
|
||||
* is too small, return NULL: the ECTF_NAMELEN error is set on 'fp' for us.
|
||||
@ -308,10 +324,19 @@ ctf_type_lname(ctf_file_t *fp, ctf_id_t type, char *buf, size_t len)
|
||||
char *
|
||||
ctf_type_name(ctf_file_t *fp, ctf_id_t type, char *buf, size_t len)
|
||||
{
|
||||
ssize_t rv = ctf_type_lname(fp, type, buf, len);
|
||||
ssize_t rv = ctf_type_qlname(fp, type, buf, len, NULL);
|
||||
return (rv >= 0 && rv < len ? buf : NULL);
|
||||
}
|
||||
|
||||
char *
|
||||
ctf_type_qname(ctf_file_t *fp, ctf_id_t type, char *buf, size_t len,
|
||||
const char *qname)
|
||||
{
|
||||
ssize_t rv = ctf_type_qlname(fp, type, buf, len, qname);
|
||||
return (rv >= 0 && rv < len ? buf : NULL);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Resolve the type down to a base type node, and then return the size
|
||||
* of the type storage in bytes.
|
||||
@ -395,7 +420,7 @@ ctf_type_align(ctf_file_t *fp, ctf_id_t type)
|
||||
const void *vmp;
|
||||
|
||||
(void) ctf_get_ctt_size(fp, tp, &size, &increment);
|
||||
vmp = (const uchar_t *)tp + increment;
|
||||
vmp = (uchar_t *)__UNCONST(tp) + increment;
|
||||
|
||||
if (LCTF_INFO_KIND(fp, tp->ctt_info) == CTF_K_STRUCT)
|
||||
n = MIN(n, 1); /* only use first member for structs */
|
||||
|
Loading…
Reference in New Issue
Block a user