#include <sys/mman.h>
#endif
+/* Note on datatypes: the datatype known outside this file as ctf_archive_t
+ is here known as struct ctf_archive_internal, to emphasise its role as a
+ wrapper with no on-disk representation.
+
+ The on-disk structure is struct ctf_archive. */
+
static off_t arc_write_one_ctf (ctf_dict_t * f, int fd, size_t threshold);
-static ctf_dict_t *ctf_dict_open_by_offset (const struct ctf_archive *arc,
+static off_t arc_write_one (int fd, const void *item, size_t size, int align);
+static int ctf_arc_value_write (int fd, const void *, size_t, uint64_t *start_off);
+static ctf_dict_t *ctf_dict_open_by_offset (const struct ctf_archive_internal *,
const ctf_sect_t *symsect,
const ctf_sect_t *strsect,
- size_t offset, int little_endian,
- int *errp);
+ size_t offset,
+ int little_endian_symtab, int *errp);
static int sort_modent_by_name (const void *one, const void *two, void *n);
+static void ctf_arc_close_internal (struct ctf_archive *arc);
static void *arc_mmap_header (int fd, size_t headersz);
static void *arc_mmap_file (int fd, size_t size);
static int arc_mmap_writeout (int fd, void *header, size_t headersz,
const char **errmsg);
static int arc_mmap_unmap (void *header, size_t headersz, const char **errmsg);
-static int ctf_arc_import_parent (const ctf_archive_t *arc, ctf_dict_t *fp,
- int *errp);
+static int ctf_arc_import_parent (const struct ctf_archive_internal *arci,
+ ctf_dict_t *fp, int *errp);
/* Flag to indicate "symbol not present" in ctf_archive_internal.ctfi_symdicts
and ctfi_symnamedicts. Never initialized. */
ssize_t namesz;
size_t ctf_startoffs; /* Start of the section we are working over. */
char *nametbl = NULL; /* The name table. */
- char *np;
- off_t nameoffs;
+ int multiple_parents = 0;
+ const char *known_parent = NULL;
int err;
- struct ctf_archive_modent *modent;
+ size_t prop_off = 0;
+ ctf_archive_modent_t *modent;
/* Prepare by serializing everything. Done first because it allocates a lot
of space and thus is more likely to fail. */
(unsigned long) ctf_dict_cnt);
/* Figure out the size of the mmap()ed header, including the
- ctf_archive_modent array. We assume that all of this needs no
- padding: a likely assumption, given that it's all made up of
- uint64_t's. */
+ ctf_archive_modent array immediately following the header itself. We
+ assume that all of this needs no padding: a likely assumption, given
+ that it's all made up of uint64_t's. */
headersz = sizeof (struct ctf_archive)
+ (ctf_dict_cnt * sizeof (uint64_t) * 2);
ctf_dprintf ("headersz is %lu\n", (unsigned long) headersz);
}
/* Fill in everything we can, which is everything other than the name
- table offset. */
- archdr->ctfa_magic = htole64 (CTFA_MAGIC);
- archdr->ctfa_ndicts = htole64 (ctf_dict_cnt);
- archdr->ctfa_ctfs = htole64 (ctf_startoffs);
+ table and shared properties table offsets. */
+ archdr->ctfa_magic = CTFA_MAGIC;
+ archdr->ctfa_ndicts = ctf_dict_cnt;
+ archdr->ctfa_ctfs = ctf_startoffs;
+ archdr->ctfa_nprops = 0; /* Updated later. */
+ archdr->ctfa_propents = 0; /* Updated later. */
+ archdr->ctfa_modents = sizeof (struct ctf_archive);
/* We could validate that all CTF files have the same data model, but
since any reasonable construction process will be building things of
memory.) */
if (ctf_dict_cnt > 0)
- archdr->ctfa_model = htole64 (ctf_getmodel (ctf_dicts[0]));
+ archdr->ctfa_model = ctf_getmodel (ctf_dicts[0]);
/* Now write out the CTFs: ctf_archive_modent array via the mapping,
ctfs via write(). The names themselves have not been written yet: we
track them in a local strtab until the time is right, and sort the
modents array after construction.
- The name table is not sorted. */
+ We also keep track of the parent of each dict, so we can easily tell if
+ all dicts have a consistent parent (or none). (This is usually the
+ case, e.g. for all archives resulting from a ctf_link() operation.)
+
+ The name table is not sorted. */
- for (i = 0, namesz = 0; i < le64toh (archdr->ctfa_ndicts); i++)
+ for (i = 0, namesz = 0; i < archdr->ctfa_ndicts; i++)
namesz += strlen (names[i]) + 1;
nametbl = malloc (namesz);
for (i = 0, namesz = 0,
modent = (ctf_archive_modent_t *) ((char *) archdr
+ sizeof (struct ctf_archive));
- i < le64toh (archdr->ctfa_ndicts); i++)
+ i < archdr->ctfa_ndicts; i++)
{
off_t off;
strcpy (&nametbl[namesz], names[i]);
off = arc_write_one_ctf (ctf_dicts[i], fd, threshold);
- if ((off < 0) && (off > -ECTF_BASE))
- {
- errmsg = N_("ctf_arc_write(): cannot determine file "
- "position while writing to archive");
- goto err_free;
- }
- if (off < 0)
+ if (off == -1)
{
errmsg = N_("ctf_arc_write(): cannot write CTF file to archive");
- errno = off * -1;
goto err_free;
}
- modent->name_offset = htole64 (namesz);
- modent->ctf_offset = htole64 (off - ctf_startoffs);
+ modent->name_offset = namesz;
+ modent->ctf_offset = off - ctf_startoffs;
namesz += strlen (names[i]) + 1;
modent++;
+
+ if (!multiple_parents)
+ {
+ if (!known_parent)
+ known_parent = ctf_dicts[i]->ctf_parent_name;
+ else
+ if (ctf_dicts[i]->ctf_parent_name
+ && strcmp (known_parent, ctf_dicts[i]->ctf_parent_name) != 0)
+ multiple_parents = 1;
+ }
}
ctf_qsort_r ((ctf_archive_modent_t *) ((char *) archdr
+ sizeof (struct ctf_archive)),
- le64toh (archdr->ctfa_ndicts),
- sizeof (struct ctf_archive_modent), sort_modent_by_name,
+ archdr->ctfa_ndicts,
+ sizeof (ctf_archive_modent_t), sort_modent_by_name,
nametbl);
+ /* Properties. We have only one property so far, defined only if we have
+ exactly one parent in common across all dicts. */
+ if (!multiple_parents && known_parent)
+ {
+ char *new_nametbl;
+
+ archdr->ctfa_nprops++;
+ if ((new_nametbl = realloc (nametbl, namesz
+ + strlen ("parent_name") + 1)) == NULL)
+ {
+ errmsg = N_("ctf_arc_write(): error allocating properties");
+ goto err_free;
+ }
+ nametbl = new_nametbl;
+ strcpy (&nametbl[namesz], "parent_name");
+ prop_off = namesz;
+ namesz += strlen ("parent_name") + 1;
+ }
+
/* Now the name table. */
- if ((nameoffs = lseek (fd, 0, SEEK_CUR)) < 0)
+ if (ctf_arc_value_write (fd, nametbl, namesz, &archdr->ctfa_names) < 0)
{
- errmsg = N_("ctf_arc_write(): cannot get current file position "
- "in archive");
+ errmsg = N_("ctf_arc_write(): cannot write name table to archive");
goto err_free;
}
- archdr->ctfa_names = htole64 (nameoffs);
- np = nametbl;
- while (namesz > 0)
+ free (nametbl);
+
+ /* Now the properties. There is only one currently: the parent name,
+ which means the sorted nature of the name table is trivial. (When
+ multiple properties are written out, only the last will be
+ aligned.) */
+
+ if (!multiple_parents && known_parent)
{
- ssize_t len;
- if ((len = write (fd, np, namesz)) < 0)
+ ctf_archive_modent_t props;
+ off_t prop_values;
+ uint64_t propents;
+
+ memset (&props, 0, sizeof (ctf_archive_modent_t));
+
+ props.name_offset = prop_off;
+ props.ctf_offset = 0;
+
+ if ((prop_values = arc_write_one (fd, known_parent,
+ strlen (known_parent) + 1, 1)) < 0
+ || (ctf_arc_value_write (fd, &props, sizeof (ctf_archive_modent_t),
+ &propents) < 0))
{
- errmsg = N_("ctf_arc_write(): cannot write name table to archive");
- goto err_free;
+ /* Something went wrong: just blank out the props and keep going. */
+ archdr->ctfa_prop_values = 0;
+ archdr->ctfa_propents = 0;
+ }
+ else
+ {
+ archdr->ctfa_prop_values = prop_values;
+ archdr->ctfa_propents = propents;
}
- namesz -= len;
- np += len;
}
- free (nametbl);
if (arc_mmap_writeout (fd, archdr, headersz, &errmsg) < 0)
goto err_unmap;
/* Write one CTF dict out. Return the file position of the written file (or
rather, of the file-size uint64_t that precedes it): negative return is a
- negative errno or ctf_errno value. On error, the file position may no longer
- be at the end of the file. */
+ negative errno or ctf_errno value. On error, the file position may no
+ longer be at the end of the file, but if it is, it will be at an 8-byte
+ aligned offset. Sets errno on error. */
static off_t
-arc_write_one_ctf (ctf_dict_t *f, int fd, size_t threshold)
+arc_write_one_ctf (ctf_dict_t *fp, int fd, size_t threshold)
{
- off_t off, end_off;
- uint64_t ctfsz = 0;
- char *ctfszp;
- size_t ctfsz_len;
+ uint64_t off, ctfsz = 0;
+ off_t end_off;
- if ((off = lseek (fd, 0, SEEK_CUR)) < 0)
- return errno * -1;
+ /* This zero write turns into the size in a moment... */
+ if (ctf_arc_value_write (fd, &ctfsz, sizeof (ctfsz), &off) < 0)
+ return -1;
- /* This zero-write turns into the size in a moment. */
- ctfsz_len = sizeof (ctfsz);
- ctfszp = (char *) &ctfsz;
- while (ctfsz_len > 0)
+ if (ctf_write_thresholded (fp, fd, threshold) != 0)
{
- ssize_t writelen = write (fd, ctfszp, ctfsz_len);
- if (writelen < 0)
- return errno * -1;
- ctfsz_len -= writelen;
- ctfszp += writelen;
+ errno = fp->ctf_errno;
+ return -1;
}
- if (ctf_write_thresholded (f, fd, threshold) != 0)
- return f->ctf_errno * -1;
-
if ((end_off = lseek (fd, 0, SEEK_CUR)) < 0)
- return errno * -1;
- ctfsz = htole64 (end_off - off);
+ return -1;
+ ctfsz = end_off - (off + sizeof (ctfsz));
if ((lseek (fd, off, SEEK_SET)) < 0)
- return errno * -1;
+ return -1;
/* ... here. */
- ctfsz_len = sizeof (ctfsz);
- ctfszp = (char *) &ctfsz;
- while (ctfsz_len > 0)
- {
- ssize_t writelen = write (fd, ctfszp, ctfsz_len);
- if (writelen < 0)
- return errno * -1;
- ctfsz_len -= writelen;
- ctfszp += writelen;
- }
+ if (ctf_arc_value_write (fd, &ctfsz, sizeof (ctfsz), &off) < 0)
+ return -1;
+
+ /* Align the end byte and move there. */
end_off = LCTF_ALIGN_OFFS (end_off, 8);
if ((lseek (fd, end_off, SEEK_SET)) < 0)
- return errno * -1;
+ return -1;
- return off;
+ return (off_t) off;
}
-/* qsort() function to sort the array of struct ctf_archive_modents into
+/* Write one size-prepended thing out. On error, the file position may no
+ longer be at the end of the file. Sets errno on error. */
+
+static off_t
+arc_write_one (int fd, const void *item, size_t size, int align)
+{
+ uint64_t sz64 = (uint64_t) size;
+ uint64_t off;
+
+ if (ctf_arc_value_write (fd, &sz64, sizeof (sz64), &off) < 0)
+ return -1;
+
+ if (ctf_arc_value_write (fd, item, size, NULL) < 0)
+ return -1;
+
+ if (align)
+ {
+ off_t end_off;
+
+ if ((end_off = lseek (fd, 0, SEEK_CUR)) < 0)
+ return -1;
+
+ end_off = LCTF_ALIGN_OFFS (end_off, 8);
+ if ((lseek (fd, end_off, SEEK_SET)) < 0)
+ return -1;
+ }
+
+ return (off_t) off;
+}
+
+/* Write out one value in the archive. Sets errno and returns -1 on
+ error. */
+
+static int
+ctf_arc_value_write (int fd, const void *tbl_, size_t tblsz,
+ uint64_t *start_off)
+{
+ off_t off;
+ const unsigned char *tbl = (const unsigned char *) tbl_;
+
+ if ((off = lseek (fd, 0, SEEK_CUR)) < 0)
+ return -1;
+
+ if (start_off)
+ *start_off = off;
+
+ while (tblsz > 0)
+ {
+ ssize_t len;
+
+ if ((len = write (fd, tbl, tblsz)) < 0)
+ {
+ *start_off = 0;
+ return -1;
+ }
+ tblsz -= len;
+ tbl += len;
+ }
+ return 0;
+}
+
+/* qsort() function to sort the array of ctf_archive_modents_t into
ascending name order. */
static int
sort_modent_by_name (const void *one, const void *two, void *n)
{
- const struct ctf_archive_modent *a = one;
- const struct ctf_archive_modent *b = two;
+ const ctf_archive_modent_t *a = one;
+ const ctf_archive_modent_t *b = two;
char *nametbl = n;
- return strcmp (&nametbl[le64toh (a->name_offset)],
- &nametbl[le64toh (b->name_offset)]);
+ return strcmp (&nametbl[a->name_offset], &nametbl[b->name_offset]);
}
/* bsearch_r() function to search for a given name in the sorted array of struct
search_modent_by_name (const void *key, const void *ent, void *arg)
{
const char *k = key;
- const struct ctf_archive_modent *v = ent;
- const char *search_nametbl = arg;
+ const ctf_archive_modent_t *v = ent;
+ const struct ctf_archive_internal *arci;
+ const char *search_nametbl;
+
+ arci = (const struct ctf_archive_internal *) arg;
- return strcmp (k, &search_nametbl[le64toh (v->name_offset)]);
+ search_nametbl = (char *) arci->ctfi_archive + arci->ctfi_hdr->ctfa_names;
+ return strcmp (k, &search_nametbl[v->name_offset]);
}
/* Make a new struct ctf_archive_internal wrapper for a ctf_archive or a
- ctf_dict. Closes ARC and/or FP on error. Arrange to free the SYMSECT or
- STRSECT, as needed, on close. Possibly do not unmap on close. */
+ ctf_dict: endian-swap the archive header as necessary, and check all its
+ offsets for validity. Close ARC and/or FP on error. Arrange to free or
+ unmap the SYMSECT or STRSECT, as needed, on close. */
struct ctf_archive_internal *
-ctf_new_archive_internal (int is_archive, int unmap_on_close,
- struct ctf_archive *arc,
+ctf_new_archive_internal (int is_archive, int is_v1, int unmap_on_close,
+ struct ctf_archive *arc, size_t arc_len,
ctf_dict_t *fp, const ctf_sect_t *symsect,
const ctf_sect_t *strsect,
int *errp)
{
- struct ctf_archive_internal *arci;
+ struct ctf_archive_internal *arci = NULL;
if ((arci = calloc (1, sizeof (struct ctf_archive_internal))) == NULL)
+ goto err;
+
+ ctf_set_open_errno (errp, 0);
+
+ arci->ctfi_is_archive = is_archive;
+ arci->ctfi_archive_v1 = is_v1;
+
+ if (is_archive)
{
- if (is_archive)
+ arci->ctfi_archive = (unsigned char *) arc;
+ if (is_v1)
+ arci->ctfi_hdr_len = sizeof (struct ctf_archive_v1);
+ else
+ arci->ctfi_hdr_len = sizeof (struct ctf_archive);
+
+ if ((arci->ctfi_hdr = malloc (sizeof (struct ctf_archive))) == NULL)
+ goto err;
+
+ /* Upgrade the v1 header if needed. */
+
+ if (!is_v1)
+ memcpy (arci->ctfi_hdr, arc, sizeof (struct ctf_archive));
+ else
{
- if (unmap_on_close)
- ctf_arc_close_internal (arc);
+ struct ctf_archive_v1 *v1hdr = (struct ctf_archive_v1 *) arc;
+
+ memset (arci->ctfi_hdr, 0, sizeof (struct ctf_archive));
+ arci->ctfi_hdr->ctfa_magic = v1hdr->ctfa_magic;
+ arci->ctfi_hdr->ctfa_model = v1hdr->ctfa_model;
+ arci->ctfi_hdr->ctfa_ndicts = v1hdr->ctfa_ndicts;
+ arci->ctfi_hdr->ctfa_names = v1hdr->ctfa_names;
+ arci->ctfi_hdr->ctfa_ctfs = v1hdr->ctfa_ctfs;
+ arci->ctfi_hdr->ctfa_modents = sizeof (struct ctf_archive_v1);
}
- else
- ctf_dict_close (fp);
- return (ctf_set_open_errno (errp, errno));
+
+ if (ctf_arc_flip_archive (arci, arc_len, errp) < 0)
+ goto err_set;
+
+ if (ctf_arc_range_check (arci, arc_len, errp) < 0)
+ goto err_set;
}
- arci->ctfi_is_archive = is_archive;
- if (is_archive)
- arci->ctfi_archive = arc;
else
arci->ctfi_dict = fp;
if (symsect)
arci->ctfi_symsect_little_endian = -1;
return arci;
+
+ err:
+ ctf_set_open_errno (errp, errno);
+ err_set:
+ if (is_archive)
+ {
+ if (unmap_on_close)
+ ctf_arc_close_internal (arc);
+ }
+ else
+ ctf_dict_close (fp);
+ if (arci)
+ {
+ free (arci->ctfi_hdr);
+ free (arci);
+ }
+ return NULL;
}
/* Set the symbol-table endianness of an archive (defaulting the symtab
endianness of all ctf_file_t's opened from that archive). */
void
-ctf_arc_symsect_endianness (ctf_archive_t *arc, int little_endian)
+ctf_arc_symsect_endianness (struct ctf_archive_internal *arci, int little_endian)
{
- arc->ctfi_symsect_little_endian = !!little_endian;
- if (!arc->ctfi_is_archive)
- ctf_symsect_endianness (arc->ctfi_dict, arc->ctfi_symsect_little_endian);
+ arci->ctfi_symsect_little_endian = !!little_endian;
+ if (!arci->ctfi_is_archive)
+ ctf_symsect_endianness (arci->ctfi_dict, arci->ctfi_symsect_little_endian);
}
/* Get the CTF preamble from data in a buffer, which may be either an archive or
a CTF dict. If multiple dicts are present in an archive, the preamble comes
from an arbitrary dict. The preamble is a pointer into the ctfsect passed
- in. */
+ in. Returns NULL if called on non-v1 archives. (Backward-compatibility
+ only.) */
const ctf_preamble_t *
-ctf_arc_bufpreamble (const ctf_sect_t *ctfsect)
+ctf_arc_bufpreamble_v1 (const ctf_sect_t *ctfsect)
{
- if (ctfsect->cts_data != NULL
- && ctfsect->cts_size > sizeof (uint64_t)
- && (le64toh ((*(uint64_t *) ctfsect->cts_data)) == CTFA_MAGIC))
+ if (ctfsect->cts_data == NULL
+ || ctfsect->cts_size <= sizeof (uint64_t))
+ {
+ errno = EOVERFLOW;
+ return NULL;
+ }
+
+ if (le64toh ((*(uint64_t *) ctfsect->cts_data)) == CTFA_V1_MAGIC)
{
- struct ctf_archive *arc = (struct ctf_archive *) ctfsect->cts_data;
+ struct ctf_archive_v1 *arc = (struct ctf_archive_v1 *) ctfsect->cts_data;
return (const ctf_preamble_t *) ((char *) arc + le64toh (arc->ctfa_ctfs)
+ sizeof (uint64_t));
}
- else
- return (const ctf_preamble_t *) ctfsect->cts_data;
+
+ return NULL;
}
/* Open a CTF archive or dictionary from data in a buffer (which the caller must
const ctf_sect_t *strsect, int *errp)
{
struct ctf_archive *arc = NULL;
- int is_archive;
+ int is_archive, is_v1 = 0;
ctf_dict_t *fp = NULL;
if (ctfsect->cts_data != NULL
&& ctfsect->cts_size > sizeof (uint64_t)
- && (le64toh ((*(uint64_t *) ctfsect->cts_data)) == CTFA_MAGIC))
+ && (*(uint64_t *) ctfsect->cts_data == CTFA_MAGIC
+ || bswap_64 ((*(uint64_t *) ctfsect->cts_data)) == CTFA_MAGIC
+ || le64toh ((*(uint64_t *) ctfsect->cts_data)) == CTFA_V1_MAGIC))
{
/* The archive is mmappable, so this operation is trivial.
- This buffer is nonmodifiable, so the trick involving mmapping only part
- of it and storing the length in the magic number is not applicable: so
- record this fact in the archive-wrapper header. (We cannot record it
- in the archive, because the archive may very well be a read-only
- mapping.) */
+ This buffer is nonmodifiable, so the trick involving mmapping only
+ part of it and storing the length in the magic number is not
+ applicable: so record this fact in the archive-wrapper header. (We
+ cannot record it in the archive, because the archive may very well
+ be a read-only mapping. unmap_on_close is left unset in the
+ ctf_new_archive_internal call so that we don't try to unmap it
+ ourselves.) */
is_archive = 1;
arc = (struct ctf_archive *) ctfsect->cts_data;
+
+ if (le64toh ((*(uint64_t *) ctfsect->cts_data)) == CTFA_V1_MAGIC)
+ is_v1 = 1;
}
else
{
return NULL;
}
}
- return ctf_new_archive_internal (is_archive, 0, arc, fp, symsect, strsect,
- errp);
+ return ctf_new_archive_internal (is_archive, is_v1, 0, arc, ctfsect->cts_size,
+ fp, symsect, strsect, errp);
}
-/* Open a CTF archive. Returns the archive, or NULL and an error in *err (if
- not NULL). */
-struct ctf_archive *
+/* Open a CTF archive from a given file. Returns the archive (wrapper), or
+ NULL and an error in *err (if not NULL). Only archives are supported,
+ not dicts (because our only caller already handles those itself). */
+struct ctf_archive_internal *
ctf_arc_open_internal (const char *filename, int *errp)
{
const char *errmsg;
- int fd;
+ int fd, is_v1 = 0;
struct stat s;
struct ctf_archive *arc; /* (Actually the whole file.) */
goto err_close;
}
+ /* This will fail if the file is too big -- e.g. > 4GiB on 32-bit
+ platforms -- and thus free us from having to do integer-overflow checks
+ elsewhere. */
if ((arc = arc_mmap_file (fd, s.st_size)) == NULL)
{
errmsg = N_("ctf_arc_open(): cannot read in %s");
goto err_close;
}
- if (le64toh (arc->ctfa_magic) != CTFA_MAGIC)
+ if (arc->ctfa_magic != CTFA_MAGIC && bswap_64 (arc->ctfa_magic) != CTFA_MAGIC
+ && le64toh (arc->ctfa_magic) != CTFA_V1_MAGIC)
{
errmsg = N_("ctf_arc_open(): %s: invalid magic number");
errno = ECTF_FMT;
goto err_unmap;
}
+ if (le64toh (arc->ctfa_magic) == CTFA_V1_MAGIC)
+ is_v1 = 1;
+
/* This horrible hack lets us know how much to unmap when the file is
closed. (We no longer need the magic number, and the mapping
is private.) */
arc->ctfa_magic = s.st_size;
close (fd);
- if (errp)
- *errp = 0;
-
- return arc;
+ return ctf_new_archive_internal (1, is_v1, 1, arc, s.st_size, NULL,
+ NULL, NULL, errp);
err_unmap:
arc_mmap_unmap (arc, s.st_size, NULL);
}
/* Close an archive. */
-void
+static void
ctf_arc_close_internal (struct ctf_archive *arc)
{
if (arc == NULL)
arc_mmap_unmap (arc, arc->ctfa_magic, NULL);
}
-/* Public entry point: close an archive, or CTF file. */
+/* Public entry point: close an archive (via its wrapper), or CTF dict. */
void
-ctf_arc_close (ctf_archive_t *arc)
+ctf_arc_close (struct ctf_archive_internal *arci)
{
- if (arc == NULL)
+ if (arci == NULL)
return;
- if (arc->ctfi_is_archive)
+ if (arci->ctfi_is_archive)
{
- if (arc->ctfi_unmap_on_close)
- ctf_arc_close_internal (arc->ctfi_archive);
+ if (arci->ctfi_unmap_on_close)
+ ctf_arc_close_internal ((struct ctf_archive *) arci->ctfi_archive);
}
else
- ctf_dict_close (arc->ctfi_dict);
- free (arc->ctfi_symdicts);
- free (arc->ctfi_symnamedicts);
- ctf_dynhash_destroy (arc->ctfi_dicts);
- if (arc->ctfi_free_symsect)
- free ((void *) arc->ctfi_symsect.cts_data);
- if (arc->ctfi_free_strsect)
- free ((void *) arc->ctfi_strsect.cts_data);
- free (arc->ctfi_data);
- if (arc->ctfi_bfd_close)
- arc->ctfi_bfd_close (arc);
- free (arc);
+ ctf_dict_close (arci->ctfi_dict);
+ free (arci->ctfi_hdr);
+ free (arci->ctfi_symdicts);
+ free (arci->ctfi_symnamedicts);
+ ctf_dynhash_destroy (arci->ctfi_dicts);
+ if (arci->ctfi_free_symsect)
+ free ((void *) arci->ctfi_symsect.cts_data);
+ if (arci->ctfi_free_strsect)
+ free ((void *) arci->ctfi_strsect.cts_data);
+ free (arci->ctfi_data);
+ if (arci->ctfi_bfd_close)
+ arci->ctfi_bfd_close (arci);
+ free (arci);
}
/* Return the ctf_dict_t with the given name, or NULL if none, setting 'err' if
non-NULL. A name of NULL means to open the default file. */
static ctf_dict_t *
-ctf_dict_open_internal (const struct ctf_archive *arc,
+ctf_dict_open_internal (const struct ctf_archive_internal *arci,
const ctf_sect_t *symsect,
const ctf_sect_t *strsect,
- const char *name, int little_endian,
+ const char *name, int little_endian_symtab,
int *errp)
{
- struct ctf_archive_modent *modent;
- const char *search_nametbl;
+ ctf_archive_modent_t *modent;
if (name == NULL)
name = _CTF_SECTION; /* The default name. */
ctf_dprintf ("ctf_dict_open_internal(%s): opening\n", name);
- modent = (ctf_archive_modent_t *) ((char *) arc
- + sizeof (struct ctf_archive));
+ modent = (ctf_archive_modent_t *) (arci->ctfi_archive
+ + arci->ctfi_hdr->ctfa_modents);
- search_nametbl = (const char *) arc + le64toh (arc->ctfa_names);
- modent = bsearch_r (name, modent, le64toh (arc->ctfa_ndicts),
- sizeof (struct ctf_archive_modent),
- search_modent_by_name, (void *) search_nametbl);
+ modent = bsearch_r (name, modent, arci->ctfi_hdr->ctfa_ndicts,
+ sizeof (ctf_archive_modent_t),
+ search_modent_by_name, (void *) arci);
/* This is actually a common case and normal operation: no error
debug output. */
return NULL;
}
- return ctf_dict_open_by_offset (arc, symsect, strsect,
- le64toh (modent->ctf_offset),
- little_endian, errp);
+ return ctf_dict_open_by_offset (arci, symsect, strsect, modent->ctf_offset,
+ little_endian_symtab, errp);
}
/* Return the ctf_dict_t with the given name, or NULL if none, setting 'err' if
Public entry point. */
ctf_dict_t *
-ctf_dict_open_sections (const ctf_archive_t *arc,
+ctf_dict_open_sections (const struct ctf_archive_internal *arci,
const ctf_sect_t *symsect,
const ctf_sect_t *strsect,
const char *name,
if (errp)
*errp = 0;
- if (arc->ctfi_is_archive)
+ if (arci->ctfi_is_archive)
{
- ctf_dict_t *ret;
- ret = ctf_dict_open_internal (arc->ctfi_archive, symsect, strsect,
- name, arc->ctfi_symsect_little_endian,
- errp);
- if (ret)
+ ctf_dict_t *fp;
+ fp = ctf_dict_open_internal (arci, symsect, strsect, name,
+ arci->ctfi_symsect_little_endian,
+ errp);
+ if (fp)
{
- ret->ctf_archive = (ctf_archive_t *) arc;
- if (ctf_arc_import_parent (arc, ret, errp) < 0)
+ fp->ctf_archive = (struct ctf_archive_internal *) arci;
+ if (ctf_arc_import_parent (arci, fp, errp) < 0)
{
- ctf_dict_close (ret);
+ ctf_dict_close (fp);
return NULL;
}
}
- return ret;
+ return fp;
}
if ((name != NULL) && (strcmp (name, _CTF_SECTION) != 0))
*errp = ECTF_ARNNAME;
return NULL;
}
- arc->ctfi_dict->ctf_archive = (ctf_archive_t *) arc;
+ arci->ctfi_dict->ctf_archive = (struct ctf_archive_internal *) arci;
/* Bump the refcount so that the user can ctf_dict_close() it. */
- arc->ctfi_dict->ctf_refcnt++;
- return arc->ctfi_dict;
+ arci->ctfi_dict->ctf_refcnt++;
+ return arci->ctfi_dict;
}
/* Return the ctf_dict_t with the given name, or NULL if none, setting 'err' if
Public entry point. */
ctf_dict_t *
-ctf_dict_open (const ctf_archive_t *arc, const char *name, int *errp)
+ctf_dict_open (const struct ctf_archive_internal *arci, const char *name, int *errp)
{
- const ctf_sect_t *symsect = &arc->ctfi_symsect;
- const ctf_sect_t *strsect = &arc->ctfi_strsect;
+ const ctf_sect_t *symsect = &arci->ctfi_symsect;
+ const ctf_sect_t *strsect = &arci->ctfi_strsect;
if (symsect->cts_name == NULL)
symsect = NULL;
if (strsect->cts_name == NULL)
strsect = NULL;
- return ctf_dict_open_sections (arc, symsect, strsect, name, errp);
+ return ctf_dict_open_sections (arci, symsect, strsect, name, errp);
}
static void
ctfi_dicts. If this is the first cached dict, designate it the
crossdict_cache. */
static ctf_dict_t *
-ctf_dict_open_cached (ctf_archive_t *arc, const char *name, int *errp)
+ctf_dict_open_cached (struct ctf_archive_internal *arci, const char *name, int *errp)
{
ctf_dict_t *fp;
char *dupname = NULL;
/* Just return from the cache if possible. */
- if (arc->ctfi_dicts
- && ((fp = ctf_dynhash_lookup (arc->ctfi_dicts, name)) != NULL))
+ if (arci->ctfi_dicts
+ && ((fp = ctf_dynhash_lookup (arci->ctfi_dicts, name)) != NULL))
{
fp->ctf_refcnt++;
return fp;
}
/* Not yet cached: open it. */
- if ((fp = ctf_dict_open (arc, name, errp)) == NULL)
+ if ((fp = ctf_dict_open (arci, name, errp)) == NULL)
goto err;
if ((dupname = strdup (name)) == NULL)
goto oom;
- if (arc->ctfi_dicts == NULL)
- if ((arc->ctfi_dicts
+ if (arci->ctfi_dicts == NULL)
+ if ((arci->ctfi_dicts
= ctf_dynhash_create (ctf_hash_string, ctf_hash_eq_string,
free, ctf_cached_dict_close)) == NULL)
goto oom;
- if (ctf_dynhash_insert (arc->ctfi_dicts, dupname, fp) < 0)
+ if (ctf_dynhash_insert (arci->ctfi_dicts, dupname, fp) < 0)
goto oom;
fp->ctf_refcnt++;
- if (arc->ctfi_crossdict_cache == NULL)
- arc->ctfi_crossdict_cache = fp;
+ if (arci->ctfi_crossdict_cache == NULL)
+ arci->ctfi_crossdict_cache = fp;
/* If this archive has multiple members, and this is a parent, pretend
that we have opened at least one child. This forces type and string
allocations in the parent to use provisional IDs, permitting you to
import children into it even if you modify the parent before you import
any. */
- if (arc->ctfi_is_archive && arc->ctfi_archive->ctfa_ndicts > 1
+ if (arci->ctfi_is_archive && arci->ctfi_hdr->ctfa_ndicts > 1
&& !(fp->ctf_flags & LCTF_CHILD))
{
ctf_dprintf ("archived parent: max children bumped.\n");
/* Flush any caches the CTF archive may have open. */
void
-ctf_arc_flush_caches (ctf_archive_t *wrapper)
+ctf_arc_flush_caches (struct ctf_archive_internal *arci)
{
- free (wrapper->ctfi_symdicts);
- ctf_dynhash_destroy (wrapper->ctfi_symnamedicts);
- ctf_dynhash_destroy (wrapper->ctfi_dicts);
- wrapper->ctfi_symdicts = NULL;
- wrapper->ctfi_symnamedicts = NULL;
- wrapper->ctfi_dicts = NULL;
- wrapper->ctfi_crossdict_cache = NULL;
+ free (arci->ctfi_symdicts);
+ ctf_dynhash_destroy (arci->ctfi_symnamedicts);
+ ctf_dynhash_destroy (arci->ctfi_dicts);
+ arci->ctfi_symdicts = NULL;
+ arci->ctfi_symnamedicts = NULL;
+ arci->ctfi_dicts = NULL;
+ arci->ctfi_crossdict_cache = NULL;
}
/* Return the ctf_dict_t at the given ctfa_ctfs-relative offset, or NULL if
none, setting 'err' if non-NULL. */
static ctf_dict_t *
-ctf_dict_open_by_offset (const struct ctf_archive *arc,
+ctf_dict_open_by_offset (const struct ctf_archive_internal *arci,
const ctf_sect_t *symsect,
const ctf_sect_t *strsect, size_t offset,
- int little_endian, int *errp)
+ int little_endian_symtab,
+ int *errp)
{
ctf_sect_t ctfsect;
ctf_dict_t *fp;
memset (&ctfsect, 0, sizeof (ctf_sect_t));
- offset += le64toh (arc->ctfa_ctfs);
+ offset += arci->ctfi_hdr->ctfa_ctfs;
ctfsect.cts_name = _CTF_SECTION;
- ctfsect.cts_size = le64toh (*((uint64_t *) ((char *) arc + offset)));
+ ctfsect.cts_size = *((uint64_t *) (arci->ctfi_archive + offset));
ctfsect.cts_entsize = 1;
- ctfsect.cts_data = (void *) ((char *) arc + offset + sizeof (uint64_t));
+ ctfsect.cts_data = (void *) (arci->ctfi_archive + offset + sizeof (uint64_t));
+
fp = ctf_bufopen (&ctfsect, symsect, strsect, errp);
if (fp)
{
- ctf_setmodel (fp, le64toh (arc->ctfa_model));
- if (little_endian >= 0)
- ctf_symsect_endianness (fp, little_endian);
+ ctf_setmodel (fp, arci->ctfi_hdr->ctfa_model);
+ if (little_endian_symtab >= 0)
+ ctf_symsect_endianness (fp, little_endian_symtab);
}
return fp;
}
/* Backward compatibility. */
ctf_dict_t *
-ctf_arc_open_by_name (const ctf_archive_t *arc, const char *name,
+ctf_arc_open_by_name (const ctf_archive_t *arci, const char *name,
int *errp)
{
- return ctf_dict_open (arc, name, errp);
+ return ctf_dict_open (arci, name, errp);
}
ctf_dict_t *
-ctf_arc_open_by_name_sections (const ctf_archive_t *arc,
+ctf_arc_open_by_name_sections (const struct ctf_archive_internal *arci,
const ctf_sect_t *symsect,
const ctf_sect_t *strsect,
const char *name,
int *errp)
{
- return ctf_dict_open_sections (arc, symsect, strsect, name, errp);
+ return ctf_dict_open_sections (arci, symsect, strsect, name, errp);
+}
+
+/* Get a property value from the shared properties table of an archive,
+ given a name, or NULL. */
+
+static const char *
+ctf_arc_get_property (const struct ctf_archive_internal *arci, const char *prop)
+{
+ ctf_archive_modent_t *modent;
+ uint64_t *size;
+
+ if (!arci->ctfi_archive)
+ return NULL;
+
+ if (arci->ctfi_hdr->ctfa_propents == 0
+ || arci->ctfi_hdr->ctfa_prop_values == 0)
+ return NULL;
+
+ modent = (ctf_archive_modent_t *) (arci->ctfi_archive
+ + arci->ctfi_hdr->ctfa_modents);
+
+ modent = bsearch_r (prop, modent, arci->ctfi_hdr->ctfa_nprops,
+ sizeof (ctf_archive_modent_t),
+ search_modent_by_name, (void *) arci);
+
+ if (modent == NULL)
+ return NULL;
+
+ /* Currently, all property values we use are strings: we can exploit this
+ and skip the size, with one special case for no value at all meaning
+ the null string. */
+
+ size = (uint64_t *) (arci->ctfi_archive
+ + arci->ctfi_hdr->ctfa_propents
+ + modent->ctf_offset);
+ if (*size == 0)
+ return "";
+
+ return (char *) (arci->ctfi_archive
+ + arci->ctfi_hdr->ctfa_propents
+ + modent->ctf_offset
+ + sizeof (uint64_t));
}
/* Import the parent into a ctf archive, if this is a child, the parent is not
this is not possible: this is just a best-effort helper operation to give
people useful dicts to start with. */
static int
-ctf_arc_import_parent (const ctf_archive_t *arc, ctf_dict_t *fp, int *errp)
+ctf_arc_import_parent (const struct ctf_archive_internal *arci, ctf_dict_t *fp,
+ int *errp)
{
if ((fp->ctf_flags & LCTF_CHILD) && !fp->ctf_parent)
{
ctf_dict_t *parent;
const char *parent_name = fp->ctf_parent_name;
- /* If no parent is set, and this is an archive, assume that the parent
- is the first dict in the archive, which matches what ctf_link
- produces. UPTODO: add a dedicated header entry for parent
- name. */
-
- if (!parent_name && arc->ctfi_archive)
- {
- struct ctf_archive_modent *modent;
- const char *nametbl;
-
- modent = (ctf_archive_modent_t *) ((char *) arc->ctfi_archive
- + sizeof (struct ctf_archive));
-
- nametbl = (((const char *) arc->ctfi_archive)
- + le64toh (arc->ctfi_archive->ctfa_names));
- parent_name = &nametbl[le64toh (modent[0].name_offset)];
- }
-
- parent = ctf_dict_open_cached ((ctf_archive_t *) arc, parent_name, &err);
+ /* If no parent is set, and this is an archive, check the parent name
+ in the properties table. (v1 archives will not have one, but v1
+ archives will only ever contain CTF dicts, which will always have
+ a parent name set if they need one. This contingency is for BTF,
+ which can only appear in v2 archives.)
+
+ There may not be a parent name set even in this case: in the
+ (admittedly pathological) case of archives which contain a mix of
+ parents and some BTF children, the parent name will not be set
+ because no consistent name exists. In this case,
+ ctf_archive_next's callers will simply have to import the parent
+ themselves. Such archives cannot be created by ctf_link, so
+ callers are only expected to need this in conjunction with
+ special-case archive construction tools, and general-purpose
+ callers don't need to worry. */
+
+ if (!parent_name && arci->ctfi_archive)
+ parent_name = ctf_arc_get_property (arci, "parent_name");
+
+ parent = ctf_dict_open_cached ((ctf_archive_t *) arci, parent_name, &err);
if (errp)
*errp = err;
/* Return the number of members in an archive. */
size_t
-ctf_archive_count (const ctf_archive_t *wrapper)
+ctf_archive_count (const struct ctf_archive_internal *arci)
{
- if (!wrapper->ctfi_is_archive)
+ if (!arci->ctfi_is_archive)
return 1;
- return le64toh (wrapper->ctfi_archive->ctfa_ndicts);
+ return arci->ctfi_hdr->ctfa_ndicts;
}
/* Look up a symbol in an archive by name or index (if the name is set, a lookup
Returns NULL on error, and an error in errp (if set). */
static ctf_dict_t *
-ctf_arc_lookup_sym_or_name (ctf_archive_t *wrapper, unsigned long symidx,
+ctf_arc_lookup_sym_or_name (struct ctf_archive_internal *arci, unsigned long symidx,
const char *symname, ctf_id_t *typep, int *errp)
{
ctf_dict_t *fp;
ctf_id_t type;
/* The usual non-archive-transparent-wrapper special case. */
- if (!wrapper->ctfi_is_archive)
+ if (!arci->ctfi_is_archive)
{
if (!symname)
{
- if ((type = ctf_lookup_by_symbol (wrapper->ctfi_dict, symidx)) == CTF_ERR)
+ if ((type = ctf_lookup_by_symbol (arci->ctfi_dict, symidx)) == CTF_ERR)
{
if (errp)
- *errp = ctf_errno (wrapper->ctfi_dict);
+ *errp = ctf_errno (arci->ctfi_dict);
return NULL;
}
}
else
{
- if ((type = ctf_lookup_by_symbol_name (wrapper->ctfi_dict,
+ if ((type = ctf_lookup_by_symbol_name (arci->ctfi_dict,
symname)) == CTF_ERR)
{
if (errp)
- *errp = ctf_errno (wrapper->ctfi_dict);
+ *errp = ctf_errno (arci->ctfi_dict);
return NULL;
}
}
if (typep)
*typep = type;
- wrapper->ctfi_dict->ctf_refcnt++;
- return wrapper->ctfi_dict;
+ arci->ctfi_dict->ctf_refcnt++;
+ return arci->ctfi_dict;
}
- if (wrapper->ctfi_symsect.cts_name == NULL
- || wrapper->ctfi_symsect.cts_data == NULL
- || wrapper->ctfi_symsect.cts_size == 0
- || wrapper->ctfi_symsect.cts_entsize == 0)
+ if (arci->ctfi_symsect.cts_name == NULL
+ || arci->ctfi_symsect.cts_data == NULL
+ || arci->ctfi_symsect.cts_size == 0
+ || arci->ctfi_symsect.cts_entsize == 0)
{
if (errp)
*errp = ECTF_NOSYMTAB;
We also cache similar mappings for symbol names: these are ordinary
dynhashes, with weak links to dicts. */
- if (!wrapper->ctfi_symdicts)
+ if (!arci->ctfi_symdicts)
{
- if ((wrapper->ctfi_symdicts = calloc (wrapper->ctfi_symsect.cts_size
- / wrapper->ctfi_symsect.cts_entsize,
- sizeof (ctf_dict_t *))) == NULL)
+ if ((arci->ctfi_symdicts = calloc (arci->ctfi_symsect.cts_size
+ / arci->ctfi_symsect.cts_entsize,
+ sizeof (ctf_dict_t *))) == NULL)
{
if (errp)
*errp = ENOMEM;
return NULL;
}
}
- if (!wrapper->ctfi_symnamedicts)
+ if (!arci->ctfi_symnamedicts)
{
- if ((wrapper->ctfi_symnamedicts = ctf_dynhash_create (ctf_hash_string,
- ctf_hash_eq_string,
- free, NULL)) == NULL)
+ if ((arci->ctfi_symnamedicts = ctf_dynhash_create (ctf_hash_string,
+ ctf_hash_eq_string,
+ free, NULL)) == NULL)
{
if (errp)
*errp = ENOMEM;
found: this should never happen, but shouldn't be allowed to cause trouble
if it does. */
- if ((symname && ctf_dynhash_lookup_kv (wrapper->ctfi_symnamedicts,
+ if ((symname && ctf_dynhash_lookup_kv (arci->ctfi_symnamedicts,
symname, NULL, &fpkey))
- || (!symname && wrapper->ctfi_symdicts[symidx] != NULL))
+ || (!symname && arci->ctfi_symdicts[symidx] != NULL))
{
if (symname)
fp = (ctf_dict_t *) fpkey;
else
- fp = wrapper->ctfi_symdicts[symidx];
+ fp = arci->ctfi_symdicts[symidx];
if (fp == &enosym)
goto no_sym;
else
local_errp = &local_err;
- while ((fp = ctf_archive_next (wrapper, &i, &name, 0, local_errp)) != NULL)
+ while ((fp = ctf_archive_next (arci, &i, &name, 0, local_errp)) != NULL)
{
if (!symname)
{
if ((type = ctf_lookup_by_symbol (fp, symidx)) != CTF_ERR)
- wrapper->ctfi_symdicts[symidx] = fp;
+ arci->ctfi_symdicts[symidx] = fp;
}
else
{
char *tmp;
/* No error checking, as above. */
if ((tmp = strdup (symname)) != NULL)
- ctf_dynhash_insert (wrapper->ctfi_symnamedicts, tmp, fp);
+ ctf_dynhash_insert (arci->ctfi_symnamedicts, tmp, fp);
}
}
cache_no_sym:
if (!symname)
- wrapper->ctfi_symdicts[symidx] = &enosym;
+ arci->ctfi_symdicts[symidx] = &enosym;
else
{
char *tmp;
/* No error checking: if caching fails, there is only a slight performance
impact. */
if ((tmp = strdup (symname)) != NULL)
- if (ctf_dynhash_insert (wrapper->ctfi_symnamedicts, tmp, &enosym) < 0)
+ if (ctf_dynhash_insert (arci->ctfi_symnamedicts, tmp, &enosym) < 0)
free (tmp);
}
/* The public API for looking up a symbol by index. */
ctf_dict_t *
-ctf_arc_lookup_symbol (ctf_archive_t *wrapper, unsigned long symidx,
+ctf_arc_lookup_symbol (struct ctf_archive_internal *arci, unsigned long symidx,
ctf_id_t *typep, int *errp)
{
- return ctf_arc_lookup_sym_or_name (wrapper, symidx, NULL, typep, errp);
+ return ctf_arc_lookup_sym_or_name (arci, symidx, NULL, typep, errp);
}
/* The public API for looking up a symbol by name. */
ctf_dict_t *
-ctf_arc_lookup_symbol_name (ctf_archive_t *wrapper, const char *symname,
+ctf_arc_lookup_symbol_name (struct ctf_archive_internal *arci, const char *symname,
ctf_id_t *typep, int *errp)
{
- return ctf_arc_lookup_sym_or_name (wrapper, 0, symname, typep, errp);
+ return ctf_arc_lookup_sym_or_name (arci, 0, symname, typep, errp);
}
/* Return all enumeration constants with a given NAME across all dicts in an
not optional. */
ctf_id_t
-ctf_arc_lookup_enumerator_next (ctf_archive_t *arc, const char *name,
- ctf_next_t **it, int64_t *enum_value,
- ctf_dict_t **dict, int *errp)
+ctf_arc_lookup_enumerator_next (struct ctf_archive_internal *arci,
+ const char *name, ctf_next_t **it,
+ int64_t *enum_value, ctf_dict_t **dict,
+ int *errp)
{
ctf_next_t *i = *it;
ctf_id_t type;
goto err;
}
i->ctn_iter_fun = (void (*) (void)) ctf_arc_lookup_enumerator_next;
- i->cu.ctn_arc = arc;
+ i->cu.ctn_arc = arci;
*it = i;
}
goto err;
}
- if (arc != i->cu.ctn_arc)
+ if (arci != i->cu.ctn_arc)
{
err = ECTF_NEXT_WRONGFP;
goto err;
opened_this_time = 0;
}
- *dict = ctf_archive_next (arc, &i->ctn_next, NULL, 0, &err);
+ *dict = ctf_archive_next (arci, &i->ctn_next, NULL, 0, &err);
if (!*dict)
goto err;
opened_this_time = 1;
return CTF_ERR;
}
-/* Raw iteration over all CTF files in an archive. We pass the raw data for all
- CTF files in turn to the specified callback function. */
-static int
-ctf_archive_raw_iter_internal (const struct ctf_archive *arc,
- ctf_archive_raw_member_f *func, void *data)
+/* Raw iteration over all CTF files in an archive: public entry point.
+
+ Returns -EINVAL if not supported for this sort of archive. */
+int
+ctf_archive_raw_iter (const struct ctf_archive_internal *arci,
+ ctf_archive_raw_member_f * func, void *data)
{
int rc;
size_t i;
- struct ctf_archive_modent *modent;
+ ctf_archive_modent_t *modent;
const char *nametbl;
- modent = (ctf_archive_modent_t *) ((char *) arc
- + sizeof (struct ctf_archive));
- nametbl = (((const char *) arc) + le64toh (arc->ctfa_names));
+ if (!arci->ctfi_is_archive || !arci->ctfi_archive)
+ return -EINVAL; /* Not supported. */
+
+ modent = (ctf_archive_modent_t *) (arci->ctfi_archive
+ + arci->ctfi_hdr->ctfa_modents);
+ nametbl = (const char *) arci->ctfi_archive + arci->ctfi_hdr->ctfa_names;
- for (i = 0; i < le64toh (arc->ctfa_ndicts); i++)
+ for (i = 0; i < arci->ctfi_hdr->ctfa_ndicts; i++)
{
const char *name;
- char *fp;
+ unsigned char *content;
+ size_t name_offset, ctf_offset, ctf_size;
+
+ name_offset = modent[i].name_offset;
+ ctf_offset = modent[i].ctf_offset;
- name = &nametbl[le64toh (modent[i].name_offset)];
- fp = ((char *) arc + le64toh (arc->ctfa_ctfs)
- + le64toh (modent[i].ctf_offset));
+ name = &nametbl[name_offset];
+ content = arci->ctfi_archive + arci->ctfi_hdr->ctfa_ctfs + ctf_offset;
+ ctf_size = *((uint64_t *) content);
- if ((rc = func (name, (void *) (fp + sizeof (uint64_t)),
- le64toh (*((uint64_t *) fp)), data)) != 0)
+ if ((rc = func (name, (void *) (content + sizeof (uint64_t)),
+ ctf_size, data)) != 0)
return rc;
}
return 0;
}
-/* Raw iteration over all CTF files in an archive: public entry point.
-
- Returns -EINVAL if not supported for this sort of archive. */
-int
-ctf_archive_raw_iter (const ctf_archive_t *arc,
- ctf_archive_raw_member_f * func, void *data)
-{
- if (arc->ctfi_is_archive)
- return ctf_archive_raw_iter_internal (arc->ctfi_archive, func, data);
-
- return -EINVAL; /* Not supported. */
-}
-
/* Iterate over all CTF files in an archive: public entry point. We pass all
CTF files in turn to the specified callback function. */
int
-ctf_archive_iter (const ctf_archive_t *arc, ctf_archive_member_f *func,
- void *data)
+ctf_archive_iter (const struct ctf_archive_internal *arci,
+ ctf_archive_member_f *func, void *data)
{
ctf_next_t *i = NULL;
ctf_dict_t *fp;
const char *name;
int err = 0;
- while ((fp = ctf_archive_next (arc, &i, &name, 0, &err)) != NULL)
+ while ((fp = ctf_archive_next (arci, &i, &name, 0, &err)) != NULL)
{
int rc;
linker only emitting parents named _CTF_SECTION, this works well enough. */
ctf_dict_t *
-ctf_archive_next (const ctf_archive_t *wrapper, ctf_next_t **it, const char **name,
- int skip_parent, int *errp)
+ctf_archive_next (const struct ctf_archive_internal *arci, ctf_next_t **it,
+ const char **name, int skip_parent, int *errp)
{
ctf_dict_t *f;
ctf_next_t *i = *it;
- struct ctf_archive *arc;
- struct ctf_archive_modent *modent;
+ ctf_archive_modent_t *modent;
const char *nametbl;
const char *name_;
*errp = ENOMEM;
return NULL;
}
- i->cu.ctn_arc = wrapper;
+ i->cu.ctn_arc = arci;
i->ctn_iter_fun = (void (*) (void)) ctf_archive_next;
*it = i;
}
return NULL;
}
- if (wrapper != i->cu.ctn_arc)
+ if (arci != i->cu.ctn_arc)
{
if (errp)
*errp = ECTF_NEXT_WRONGFP;
skip_parent is on, they are skipped and the iterator terminates
immediately. */
- if (!wrapper->ctfi_is_archive && i->ctn_n == 0)
+ if (!arci->ctfi_is_archive && i->ctn_n == 0)
{
i->ctn_n++;
if (!skip_parent)
{
- wrapper->ctfi_dict->ctf_refcnt++;
+ arci->ctfi_dict->ctf_refcnt++;
if (name)
*name = _CTF_SECTION;
- return wrapper->ctfi_dict;
+ return arci->ctfi_dict;
}
}
- arc = wrapper->ctfi_archive;
-
/* The loop keeps going when skip_parent is on as long as the member we find
is the parent (i.e. at most two iterations, but possibly an early return if
*all* we have is a parent). */
do
{
- if ((!wrapper->ctfi_is_archive) || (i->ctn_n >= le64toh (arc->ctfa_ndicts)))
+ if ((!arci->ctfi_is_archive) || (i->ctn_n >= arci->ctfi_hdr->ctfa_ndicts))
{
ctf_next_destroy (i);
*it = NULL;
return NULL;
}
- modent = (ctf_archive_modent_t *) ((char *) arc
- + sizeof (struct ctf_archive));
- nametbl = (((const char *) arc) + le64toh (arc->ctfa_names));
-
- name_ = &nametbl[le64toh (modent[i->ctn_n].name_offset)];
+ modent = (ctf_archive_modent_t *) ((char *) arci->ctfi_archive
+ + arci->ctfi_hdr->ctfa_modents);
+ nametbl = (const char *) arci->ctfi_archive + arci->ctfi_hdr->ctfa_names;
+ name_ = &nametbl[modent[i->ctn_n].name_offset];
i->ctn_n++;
}
while (skip_parent && strcmp (name_, _CTF_SECTION) == 0);
if (name)
*name = name_;
- f = ctf_dict_open_cached ((ctf_archive_t *) wrapper, name_, errp);
+ f = ctf_dict_open_cached ((ctf_archive_t *) arci, name_, errp);
return f;
}