mirror of
https://github.com/bminor/binutils-gdb.git
synced 2025-12-25 16:57:52 +00:00
libctf: generalize the ref system
Despite the removal of the separate movable ref list, the ref system as a whole is more than complex enough to be worth generalizing now that we are adding different kinds of ref. Refs now are lists of uint32_t * which can be updated through the pointer for all entries in the list and moved to new sites for all pointers in a given range: they are no longer references to string offsets in particular and can be references to other uint32_t-sized things instead (note that ctf_id_t is a typedef to a uint32_t). ctf-string.c has been adjusted accordingly (the adjustments are tiny, more or less just turning a bunch of references to atom into &atom->csa_refs).
This commit is contained in:
@@ -1118,7 +1118,7 @@ ctf_add_enumerator (ctf_dict_t *fp, ctf_id_t enid, const char *name,
|
|||||||
|
|
||||||
/* Remove refs in the old vlen region and reapply them. */
|
/* Remove refs in the old vlen region and reapply them. */
|
||||||
|
|
||||||
ctf_str_move_refs (fp, old_vlen, sizeof (ctf_enum_t) * vlen, dtd->dtd_vlen);
|
ctf_move_refs (fp, old_vlen, sizeof (ctf_enum_t) * vlen, dtd->dtd_vlen);
|
||||||
|
|
||||||
/* Check for constant duplication within any given enum: only needed for
|
/* Check for constant duplication within any given enum: only needed for
|
||||||
non-root-visible types, since the duplicate detection above does the job
|
non-root-visible types, since the duplicate detection above does the job
|
||||||
@@ -1209,7 +1209,7 @@ ctf_add_member_offset (ctf_dict_t *fp, ctf_id_t souid, const char *name,
|
|||||||
|
|
||||||
/* Remove refs in the old vlen region and reapply them. */
|
/* Remove refs in the old vlen region and reapply them. */
|
||||||
|
|
||||||
ctf_str_move_refs (fp, old_vlen, sizeof (ctf_lmember_t) * vlen, dtd->dtd_vlen);
|
ctf_move_refs (fp, old_vlen, sizeof (ctf_lmember_t) * vlen, dtd->dtd_vlen);
|
||||||
|
|
||||||
if (name != NULL)
|
if (name != NULL)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -228,13 +228,13 @@ typedef struct ctf_str_atom
|
|||||||
int csa_flags; /* CTF_STR_ATOM_* flags. */
|
int csa_flags; /* CTF_STR_ATOM_* flags. */
|
||||||
} ctf_str_atom_t;
|
} ctf_str_atom_t;
|
||||||
|
|
||||||
/* The refs of a single string in the atoms table. */
|
/* A single ref. */
|
||||||
|
|
||||||
typedef struct ctf_str_atom_ref
|
typedef struct ctf_ref
|
||||||
{
|
{
|
||||||
ctf_list_t caf_list; /* List forward/back pointers. */
|
ctf_list_t cre_list; /* List forward/back pointers. */
|
||||||
uint32_t *caf_ref; /* A single ref to this string. */
|
uint32_t *cre_ref; /* A single ref to this string. */
|
||||||
} ctf_str_atom_ref_t;
|
} ctf_ref_t;
|
||||||
|
|
||||||
/* A single linker-provided symbol, during symbol addition, possibly before we
|
/* A single linker-provided symbol, during symbol addition, possibly before we
|
||||||
have been given external strtab refs. */
|
have been given external strtab refs. */
|
||||||
@@ -392,7 +392,7 @@ struct ctf_dict
|
|||||||
ctf_strs_t ctf_str[2]; /* Array of string table base and bounds. */
|
ctf_strs_t ctf_str[2]; /* Array of string table base and bounds. */
|
||||||
ctf_strs_writable_t *ctf_dynstrtab; /* Dynamically allocated string table, if any. */
|
ctf_strs_writable_t *ctf_dynstrtab; /* Dynamically allocated string table, if any. */
|
||||||
ctf_dynhash_t *ctf_str_atoms; /* Hash table of ctf_str_atoms_t. */
|
ctf_dynhash_t *ctf_str_atoms; /* Hash table of ctf_str_atoms_t. */
|
||||||
ctf_dynhash_t *ctf_str_movable_refs; /* Hash table of void * -> ctf_str_atom_ref_movable_t. */
|
ctf_dynhash_t *ctf_movable_refs; /* Hash table of void * -> ctf_ref_t. */
|
||||||
uint32_t ctf_str_prov_offset; /* Latest provisional offset assigned so far. */
|
uint32_t ctf_str_prov_offset; /* Latest provisional offset assigned so far. */
|
||||||
unsigned char *ctf_base; /* CTF file pointer. */
|
unsigned char *ctf_base; /* CTF file pointer. */
|
||||||
unsigned char *ctf_dynbase; /* Freeable CTF file pointer. */
|
unsigned char *ctf_dynbase; /* Freeable CTF file pointer. */
|
||||||
@@ -765,13 +765,21 @@ extern uint32_t ctf_str_add_no_dedup_ref (ctf_dict_t *, const char *,
|
|||||||
uint32_t *ref);
|
uint32_t *ref);
|
||||||
extern uint32_t ctf_str_add_movable_ref (ctf_dict_t *, const char *,
|
extern uint32_t ctf_str_add_movable_ref (ctf_dict_t *, const char *,
|
||||||
uint32_t *ref);
|
uint32_t *ref);
|
||||||
extern int ctf_str_move_refs (ctf_dict_t *fp, void *src, size_t len, void *dest);
|
|
||||||
extern int ctf_str_add_external (ctf_dict_t *, const char *, uint32_t offset);
|
extern int ctf_str_add_external (ctf_dict_t *, const char *, uint32_t offset);
|
||||||
extern void ctf_str_remove_ref (ctf_dict_t *, const char *, uint32_t *ref);
|
extern void ctf_str_remove_ref (ctf_dict_t *, const char *, uint32_t *ref);
|
||||||
extern void ctf_str_purge_refs (ctf_dict_t *fp);
|
extern void ctf_str_purge_refs (ctf_dict_t *fp);
|
||||||
extern void ctf_str_rollback (ctf_dict_t *, ctf_snapshot_id_t);
|
extern void ctf_str_rollback (ctf_dict_t *, ctf_snapshot_id_t);
|
||||||
extern const ctf_strs_writable_t *ctf_str_write_strtab (ctf_dict_t *);
|
extern const ctf_strs_writable_t *ctf_str_write_strtab (ctf_dict_t *);
|
||||||
|
|
||||||
|
extern int ctf_init_refs (ctf_dict_t *);
|
||||||
|
extern void ctf_free_refs (ctf_dict_t *);
|
||||||
|
extern ctf_ref_t *ctf_create_ref (ctf_dict_t *, ctf_list_t *, uint32_t *ref,
|
||||||
|
int movable);
|
||||||
|
extern void ctf_remove_ref (ctf_dict_t *fp, ctf_list_t *, uint32_t *ref);
|
||||||
|
extern int ctf_move_refs (ctf_dict_t *fp, void *src, size_t len, void *dest);
|
||||||
|
extern void ctf_purge_ref_list (ctf_dict_t *, ctf_list_t *);
|
||||||
|
extern void ctf_update_refs (ctf_list_t *, uint32_t value);
|
||||||
|
|
||||||
extern int ctf_preserialize (ctf_dict_t *fp);
|
extern int ctf_preserialize (ctf_dict_t *fp);
|
||||||
extern void ctf_depreserialize (ctf_dict_t *fp);
|
extern void ctf_depreserialize (ctf_dict_t *fp);
|
||||||
|
|
||||||
|
|||||||
@@ -1798,7 +1798,7 @@ ctf_bufopen (const ctf_sect_t *ctfsect, const ctf_sect_t *symsect,
|
|||||||
fp->ctf_str[CTF_STRTAB_0].cts_strs = (const char *) fp->ctf_buf
|
fp->ctf_str[CTF_STRTAB_0].cts_strs = (const char *) fp->ctf_buf
|
||||||
+ hp->cth_stroff;
|
+ hp->cth_stroff;
|
||||||
fp->ctf_str[CTF_STRTAB_0].cts_len = hp->cth_strlen;
|
fp->ctf_str[CTF_STRTAB_0].cts_len = hp->cth_strlen;
|
||||||
if (ctf_str_create_atoms (fp) < 0)
|
if (ctf_init_refs (fp) < 0 || ctf_str_create_atoms (fp) < 0)
|
||||||
{
|
{
|
||||||
err = ENOMEM;
|
err = ENOMEM;
|
||||||
goto bad;
|
goto bad;
|
||||||
@@ -2032,6 +2032,7 @@ ctf_dict_close (ctf_dict_t *fp)
|
|||||||
ctf_dynhash_destroy (fp->ctf_link_out_cu_mapping);
|
ctf_dynhash_destroy (fp->ctf_link_out_cu_mapping);
|
||||||
|
|
||||||
ctf_str_free_atoms (fp);
|
ctf_str_free_atoms (fp);
|
||||||
|
ctf_free_refs (fp);
|
||||||
free (fp->ctf_tmp_typeslice);
|
free (fp->ctf_tmp_typeslice);
|
||||||
|
|
||||||
if (fp->ctf_data.cts_name != _CTF_NULLSTR)
|
if (fp->ctf_data.cts_name != _CTF_NULLSTR)
|
||||||
|
|||||||
@@ -154,21 +154,6 @@ ctf_strptr_validate (ctf_dict_t *fp, uint32_t name)
|
|||||||
return str;
|
return str;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Remove all refs to a given atom. */
|
|
||||||
static void
|
|
||||||
ctf_str_purge_atom_refs (ctf_dict_t *fp, ctf_str_atom_t *atom)
|
|
||||||
{
|
|
||||||
ctf_str_atom_ref_t *ref, *next;
|
|
||||||
|
|
||||||
for (ref = ctf_list_next (&atom->csa_refs); ref != NULL; ref = next)
|
|
||||||
{
|
|
||||||
next = ctf_list_next (ref);
|
|
||||||
ctf_list_delete (&atom->csa_refs, ref);
|
|
||||||
ctf_dynhash_remove (fp->ctf_str_movable_refs, ref);
|
|
||||||
free (ref);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Free an atom. */
|
/* Free an atom. */
|
||||||
static void
|
static void
|
||||||
ctf_str_free_atom (void *a, void *fp_)
|
ctf_str_free_atom (void *a, void *fp_)
|
||||||
@@ -176,7 +161,7 @@ ctf_str_free_atom (void *a, void *fp_)
|
|||||||
ctf_str_atom_t *atom = a;
|
ctf_str_atom_t *atom = a;
|
||||||
ctf_dict_t *fp = fp_;
|
ctf_dict_t *fp = fp_;
|
||||||
|
|
||||||
ctf_str_purge_atom_refs (fp, atom);
|
ctf_purge_ref_list (fp, &atom->csa_refs);
|
||||||
|
|
||||||
if (atom->csa_flags & CTF_STR_ATOM_FREEABLE)
|
if (atom->csa_flags & CTF_STR_ATOM_FREEABLE)
|
||||||
free (atom->csa_str);
|
free (atom->csa_str);
|
||||||
@@ -212,12 +197,6 @@ ctf_str_create_atoms (ctf_dict_t *fp)
|
|||||||
if (!fp->ctf_prov_strtab)
|
if (!fp->ctf_prov_strtab)
|
||||||
goto oom_prov_strtab;
|
goto oom_prov_strtab;
|
||||||
|
|
||||||
fp->ctf_str_movable_refs = ctf_dynhash_create (ctf_hash_integer,
|
|
||||||
ctf_hash_eq_integer,
|
|
||||||
NULL, NULL);
|
|
||||||
if (!fp->ctf_str_movable_refs)
|
|
||||||
goto oom_movable_refs;
|
|
||||||
|
|
||||||
errno = 0;
|
errno = 0;
|
||||||
ctf_str_add (fp, "");
|
ctf_str_add (fp, "");
|
||||||
if (errno == ENOMEM)
|
if (errno == ENOMEM)
|
||||||
@@ -252,9 +231,6 @@ ctf_str_create_atoms (ctf_dict_t *fp)
|
|||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
oom_str_add:
|
oom_str_add:
|
||||||
ctf_dynhash_destroy (fp->ctf_str_movable_refs);
|
|
||||||
fp->ctf_str_movable_refs = NULL;
|
|
||||||
oom_movable_refs:
|
|
||||||
ctf_dynhash_destroy (fp->ctf_prov_strtab);
|
ctf_dynhash_destroy (fp->ctf_prov_strtab);
|
||||||
fp->ctf_prov_strtab = NULL;
|
fp->ctf_prov_strtab = NULL;
|
||||||
oom_prov_strtab:
|
oom_prov_strtab:
|
||||||
@@ -269,7 +245,6 @@ ctf_str_free_atoms (ctf_dict_t *fp)
|
|||||||
{
|
{
|
||||||
ctf_dynhash_destroy (fp->ctf_prov_strtab);
|
ctf_dynhash_destroy (fp->ctf_prov_strtab);
|
||||||
ctf_dynhash_destroy (fp->ctf_str_atoms);
|
ctf_dynhash_destroy (fp->ctf_str_atoms);
|
||||||
ctf_dynhash_destroy (fp->ctf_str_movable_refs);
|
|
||||||
if (fp->ctf_dynstrtab)
|
if (fp->ctf_dynstrtab)
|
||||||
{
|
{
|
||||||
free (fp->ctf_dynstrtab->cts_strs);
|
free (fp->ctf_dynstrtab->cts_strs);
|
||||||
@@ -283,37 +258,6 @@ ctf_str_free_atoms (ctf_dict_t *fp)
|
|||||||
#define CTF_STR_COPY 0x8
|
#define CTF_STR_COPY 0x8
|
||||||
#define CTF_STR_NO_DEDUP 0x10
|
#define CTF_STR_NO_DEDUP 0x10
|
||||||
|
|
||||||
/* Allocate a ref and bind it into a ref list. */
|
|
||||||
|
|
||||||
static ctf_str_atom_ref_t *
|
|
||||||
aref_create (ctf_dict_t *fp, ctf_str_atom_t *atom, uint32_t *ref, int flags)
|
|
||||||
{
|
|
||||||
ctf_str_atom_ref_t *aref;
|
|
||||||
|
|
||||||
aref = malloc (sizeof (struct ctf_str_atom_ref));
|
|
||||||
|
|
||||||
if (!aref)
|
|
||||||
return NULL;
|
|
||||||
|
|
||||||
aref->caf_ref = ref;
|
|
||||||
|
|
||||||
/* Movable refs get a backpointer to them in ctf_str_movable_refs: they can be
|
|
||||||
moved later in batches via a call to ctf_str_move_refs. */
|
|
||||||
|
|
||||||
if (flags & CTF_STR_MOVABLE)
|
|
||||||
{
|
|
||||||
if (ctf_dynhash_insert (fp->ctf_str_movable_refs, ref, aref) < 0)
|
|
||||||
{
|
|
||||||
free (aref);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
ctf_list_append (&atom->csa_refs, aref);
|
|
||||||
|
|
||||||
return aref;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Add a string to the atoms table, copying the passed-in string if
|
/* Add a string to the atoms table, copying the passed-in string if
|
||||||
necessary. Return the atom added. Return NULL only when out of memory
|
necessary. Return the atom added. Return NULL only when out of memory
|
||||||
(and do not touch the passed-in string in that case).
|
(and do not touch the passed-in string in that case).
|
||||||
@@ -357,7 +301,8 @@ ctf_str_add_ref_internal (ctf_dict_t *fp, const char *str,
|
|||||||
|
|
||||||
if (flags & CTF_STR_ADD_REF)
|
if (flags & CTF_STR_ADD_REF)
|
||||||
{
|
{
|
||||||
if (!aref_create (fp, atom, ref, flags))
|
if (!ctf_create_ref (fp, &atom->csa_refs, ref,
|
||||||
|
flags & CTF_STR_MOVABLE))
|
||||||
{
|
{
|
||||||
ctf_set_errno (fp, ENOMEM);
|
ctf_set_errno (fp, ENOMEM);
|
||||||
return NULL;
|
return NULL;
|
||||||
@@ -429,7 +374,7 @@ ctf_str_add_ref_internal (ctf_dict_t *fp, const char *str,
|
|||||||
|
|
||||||
if (flags & CTF_STR_ADD_REF)
|
if (flags & CTF_STR_ADD_REF)
|
||||||
{
|
{
|
||||||
if (!aref_create (fp, atom, ref, flags))
|
if (!ctf_create_ref (fp, &atom->csa_refs, ref, flags & CTF_STR_MOVABLE))
|
||||||
goto oom;
|
goto oom;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -559,62 +504,17 @@ ctf_str_add_external (ctf_dict_t *fp, const char *str, uint32_t offset)
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Note that refs have moved from (SRC, LEN) to DEST. We use the movable
|
/* Remove a single ref to a string. */
|
||||||
refs backpointer for this, because it is done an amortized-constant
|
|
||||||
number of times during structure member and enumerand addition, and if we
|
|
||||||
did a linear search this would turn such addition into an O(n^2)
|
|
||||||
operation. */
|
|
||||||
int
|
|
||||||
ctf_str_move_refs (ctf_dict_t *fp, void *src, size_t len, void *dest)
|
|
||||||
{
|
|
||||||
uintptr_t p;
|
|
||||||
|
|
||||||
if (src == dest)
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
for (p = (uintptr_t) src; p - (uintptr_t) src < len; p++)
|
|
||||||
{
|
|
||||||
ctf_str_atom_ref_t *ref;
|
|
||||||
|
|
||||||
if ((ref = ctf_dynhash_lookup (fp->ctf_str_movable_refs,
|
|
||||||
(ctf_str_atom_ref_t *) p)) != NULL)
|
|
||||||
{
|
|
||||||
int out_of_memory;
|
|
||||||
|
|
||||||
ref->caf_ref = (uint32_t *) (((uintptr_t) ref->caf_ref +
|
|
||||||
(uintptr_t) dest - (uintptr_t) src));
|
|
||||||
ctf_dynhash_remove (fp->ctf_str_movable_refs,
|
|
||||||
(ctf_str_atom_ref_t *) p);
|
|
||||||
out_of_memory = ctf_dynhash_insert (fp->ctf_str_movable_refs,
|
|
||||||
ref->caf_ref, ref);
|
|
||||||
assert (out_of_memory == 0);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Remove a single ref. */
|
|
||||||
void
|
void
|
||||||
ctf_str_remove_ref (ctf_dict_t *fp, const char *str, uint32_t *ref)
|
ctf_str_remove_ref (ctf_dict_t *fp, const char *str, uint32_t *ref)
|
||||||
{
|
{
|
||||||
ctf_str_atom_ref_t *aref, *anext;
|
|
||||||
ctf_str_atom_t *atom = NULL;
|
ctf_str_atom_t *atom = NULL;
|
||||||
|
|
||||||
atom = ctf_dynhash_lookup (fp->ctf_str_atoms, str);
|
atom = ctf_dynhash_lookup (fp->ctf_str_atoms, str);
|
||||||
if (!atom)
|
if (!atom)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
for (aref = ctf_list_next (&atom->csa_refs); aref != NULL; aref = anext)
|
ctf_remove_ref (fp, &atom->csa_refs, ref);
|
||||||
{
|
|
||||||
anext = ctf_list_next (aref);
|
|
||||||
if (aref->caf_ref == ref)
|
|
||||||
{
|
|
||||||
ctf_list_delete (&atom->csa_refs, aref);
|
|
||||||
ctf_dynhash_remove (fp->ctf_str_movable_refs, ref);
|
|
||||||
free (aref);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* A ctf_dynhash_iter_remove() callback that removes atoms later than a given
|
/* A ctf_dynhash_iter_remove() callback that removes atoms later than a given
|
||||||
@@ -638,7 +538,7 @@ ctf_str_rollback (ctf_dict_t *fp, ctf_snapshot_id_t id)
|
|||||||
ctf_dynhash_iter_remove (fp->ctf_str_atoms, ctf_str_rollback_atom, &id);
|
ctf_dynhash_iter_remove (fp->ctf_str_atoms, ctf_str_rollback_atom, &id);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* An adaptor around ctf_purge_atom_refs. */
|
/* An adaptor around ctf_purge_ref_list. */
|
||||||
static void
|
static void
|
||||||
ctf_str_purge_one_atom_refs (void *key _libctf_unused_, void *value,
|
ctf_str_purge_one_atom_refs (void *key _libctf_unused_, void *value,
|
||||||
void *arg)
|
void *arg)
|
||||||
@@ -646,7 +546,7 @@ ctf_str_purge_one_atom_refs (void *key _libctf_unused_, void *value,
|
|||||||
ctf_str_atom_t *atom = (ctf_str_atom_t *) value;
|
ctf_str_atom_t *atom = (ctf_str_atom_t *) value;
|
||||||
ctf_dict_t *fp = (ctf_dict_t *) arg;
|
ctf_dict_t *fp = (ctf_dict_t *) arg;
|
||||||
|
|
||||||
ctf_str_purge_atom_refs (fp, atom);
|
ctf_purge_ref_list (fp, &atom->csa_refs);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Remove all the recorded refs from the atoms table. */
|
/* Remove all the recorded refs from the atoms table. */
|
||||||
@@ -656,17 +556,6 @@ ctf_str_purge_refs (ctf_dict_t *fp)
|
|||||||
ctf_dynhash_iter (fp->ctf_str_atoms, ctf_str_purge_one_atom_refs, fp);
|
ctf_dynhash_iter (fp->ctf_str_atoms, ctf_str_purge_one_atom_refs, fp);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Update a list of refs to the specified value. */
|
|
||||||
static void
|
|
||||||
ctf_str_update_refs (ctf_str_atom_t *refs, uint32_t value)
|
|
||||||
{
|
|
||||||
ctf_str_atom_ref_t *ref;
|
|
||||||
|
|
||||||
for (ref = ctf_list_next (&refs->csa_refs); ref != NULL;
|
|
||||||
ref = ctf_list_next (ref))
|
|
||||||
*(ref->caf_ref) = value;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Sort the strtab. */
|
/* Sort the strtab. */
|
||||||
static int
|
static int
|
||||||
ctf_str_sort_strtab (const void *a, const void *b)
|
ctf_str_sort_strtab (const void *a, const void *b)
|
||||||
@@ -893,7 +782,7 @@ ctf_str_write_strtab (ctf_dict_t *fp)
|
|||||||
offset = atom->csa_offset + fp->ctf_header->cth_parent_strlen;
|
offset = atom->csa_offset + fp->ctf_header->cth_parent_strlen;
|
||||||
}
|
}
|
||||||
|
|
||||||
ctf_str_update_refs (atom, offset);
|
ctf_update_refs (&atom->csa_refs, offset);
|
||||||
}
|
}
|
||||||
if (err != ECTF_NEXT_END)
|
if (err != ECTF_NEXT_END)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -146,6 +146,136 @@ ctf_str_append_noerr (char *s, const char *append)
|
|||||||
return new_s;
|
return new_s;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Initialize the ref system. */
|
||||||
|
int
|
||||||
|
ctf_init_refs (ctf_dict_t *fp)
|
||||||
|
{
|
||||||
|
fp->ctf_movable_refs = ctf_dynhash_create (ctf_hash_integer,
|
||||||
|
ctf_hash_eq_integer,
|
||||||
|
NULL, NULL);
|
||||||
|
if (!fp->ctf_movable_refs)
|
||||||
|
return -ENOMEM;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
/* Destroy the ref system. */
|
||||||
|
void
|
||||||
|
ctf_free_refs (ctf_dict_t *fp)
|
||||||
|
{
|
||||||
|
ctf_dynhash_destroy (fp->ctf_movable_refs);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Allocate a ref and bind it into a ref list. Does not actually
|
||||||
|
initialize anything through the ref: the caller must do that. */
|
||||||
|
|
||||||
|
ctf_ref_t *
|
||||||
|
ctf_create_ref (ctf_dict_t *fp, ctf_list_t *reflist, uint32_t *ref, int movable)
|
||||||
|
{
|
||||||
|
ctf_ref_t *aref;
|
||||||
|
|
||||||
|
aref = malloc (sizeof (struct ctf_ref));
|
||||||
|
|
||||||
|
if (!aref)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
aref->cre_ref = ref;
|
||||||
|
|
||||||
|
/* Movable refs get a backpointer to them in ctf_movable_refs: they can be
|
||||||
|
moved later in batches via a call to ctf_move_refs. */
|
||||||
|
|
||||||
|
if (movable)
|
||||||
|
{
|
||||||
|
if (ctf_dynhash_insert (fp->ctf_movable_refs, ref, aref) < 0)
|
||||||
|
{
|
||||||
|
free (aref);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ctf_list_append (reflist, aref);
|
||||||
|
|
||||||
|
return aref;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Note that refs have moved from (SRC, LEN) to DEST. We use the movable
|
||||||
|
refs backpointer for this, because it is done an amortized-constant
|
||||||
|
number of times during structure member and enumerand addition, and if we
|
||||||
|
did a linear search this would turn such addition into an O(n^2)
|
||||||
|
operation. */
|
||||||
|
int
|
||||||
|
ctf_move_refs (ctf_dict_t *fp, void *src, size_t len, void *dest)
|
||||||
|
{
|
||||||
|
uintptr_t p;
|
||||||
|
|
||||||
|
if (src == dest)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
for (p = (uintptr_t) src; p - (uintptr_t) src < len; p++)
|
||||||
|
{
|
||||||
|
ctf_ref_t *ref;
|
||||||
|
|
||||||
|
if ((ref = ctf_dynhash_lookup (fp->ctf_movable_refs,
|
||||||
|
(ctf_ref_t *) p)) != NULL)
|
||||||
|
{
|
||||||
|
int out_of_memory;
|
||||||
|
|
||||||
|
ref->cre_ref = (uint32_t *) (((uintptr_t) ref->cre_ref +
|
||||||
|
(uintptr_t) dest - (uintptr_t) src));
|
||||||
|
ctf_dynhash_remove (fp->ctf_movable_refs, (ctf_ref_t *) p);
|
||||||
|
out_of_memory = ctf_dynhash_insert (fp->ctf_movable_refs,
|
||||||
|
ref->cre_ref, ref);
|
||||||
|
assert (out_of_memory == 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Remove a single ref. */
|
||||||
|
void
|
||||||
|
ctf_remove_ref (ctf_dict_t *fp, ctf_list_t *reflist, uint32_t *ref)
|
||||||
|
{
|
||||||
|
ctf_ref_t *aref, *anext;
|
||||||
|
|
||||||
|
for (aref = ctf_list_next (reflist); aref != NULL; aref = anext)
|
||||||
|
{
|
||||||
|
anext = ctf_list_next (aref);
|
||||||
|
if (aref->cre_ref == ref)
|
||||||
|
{
|
||||||
|
ctf_list_delete (reflist, aref);
|
||||||
|
ctf_dynhash_remove (fp->ctf_movable_refs, ref);
|
||||||
|
free (aref);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* Remove all refs to a given entity. */
|
||||||
|
void
|
||||||
|
ctf_purge_ref_list (ctf_dict_t *fp, ctf_list_t *reflist)
|
||||||
|
{
|
||||||
|
ctf_ref_t *ref, *next;
|
||||||
|
|
||||||
|
for (ref = ctf_list_next (reflist); ref != NULL; ref = next)
|
||||||
|
{
|
||||||
|
next = ctf_list_next (ref);
|
||||||
|
ctf_list_delete (reflist, ref);
|
||||||
|
ctf_dynhash_remove (fp->ctf_movable_refs, ref);
|
||||||
|
free (ref);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* Update a list of refs to the specified value. */
|
||||||
|
void
|
||||||
|
ctf_update_refs (ctf_list_t *reflist, uint32_t value)
|
||||||
|
{
|
||||||
|
ctf_ref_t *ref;
|
||||||
|
|
||||||
|
for (ref = ctf_list_next (reflist); ref != NULL;
|
||||||
|
ref = ctf_list_next (ref))
|
||||||
|
*(ref->cre_ref) = value;
|
||||||
|
}
|
||||||
|
|
||||||
/* Create a ctf_next_t. */
|
/* Create a ctf_next_t. */
|
||||||
|
|
||||||
ctf_next_t *
|
ctf_next_t *
|
||||||
|
|||||||
Reference in New Issue
Block a user