aboutsummaryrefslogtreecommitdiff
path: root/libctf/ctf-archive.c
diff options
context:
space:
mode:
Diffstat (limited to 'libctf/ctf-archive.c')
-rw-r--r--libctf/ctf-archive.c35
1 files changed, 28 insertions, 7 deletions
diff --git a/libctf/ctf-archive.c b/libctf/ctf-archive.c
index dc312d3..a74ab47 100644
--- a/libctf/ctf-archive.c
+++ b/libctf/ctf-archive.c
@@ -36,7 +36,8 @@ 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,
const ctf_sect_t *symsect,
const ctf_sect_t *strsect,
- size_t offset, int *errp);
+ size_t offset, int little_endian,
+ int *errp);
static int sort_modent_by_name (const void *one, const void *two, void *n);
static void *arc_mmap_header (int fd, size_t headersz);
static void *arc_mmap_file (int fd, size_t size);
@@ -378,10 +379,21 @@ ctf_new_archive_internal (int is_archive, int unmap_on_close,
arci->ctfi_free_symsect = 0;
arci->ctfi_free_strsect = 0;
arci->ctfi_unmap_on_close = unmap_on_close;
+ arci->ctfi_symsect_little_endian = -1;
return arci;
}
+/* 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)
+{
+ arc->ctfi_symsect_little_endian = !!little_endian;
+ if (!arc->ctfi_is_archive)
+ ctf_symsect_endianness (arc->ctfi_dict, arc->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
@@ -536,7 +548,8 @@ static ctf_dict_t *
ctf_dict_open_internal (const struct ctf_archive *arc,
const ctf_sect_t *symsect,
const ctf_sect_t *strsect,
- const char *name, int *errp)
+ const char *name, int little_endian,
+ int *errp)
{
struct ctf_archive_modent *modent;
const char *search_nametbl;
@@ -564,7 +577,8 @@ ctf_dict_open_internal (const struct ctf_archive *arc,
}
return ctf_dict_open_by_offset (arc, symsect, strsect,
- le64toh (modent->ctf_offset), errp);
+ le64toh (modent->ctf_offset),
+ little_endian, errp);
}
/* Return the ctf_dict_t with the given name, or NULL if none, setting 'err' if
@@ -584,7 +598,8 @@ ctf_dict_open_sections (const ctf_archive_t *arc,
{
ctf_dict_t *ret;
ret = ctf_dict_open_internal (arc->ctfi_archive, symsect, strsect,
- name, errp);
+ name, arc->ctfi_symsect_little_endian,
+ errp);
if (ret)
{
ret->ctf_archive = (ctf_archive_t *) arc;
@@ -691,7 +706,7 @@ static ctf_dict_t *
ctf_dict_open_by_offset (const struct ctf_archive *arc,
const ctf_sect_t *symsect,
const ctf_sect_t *strsect, size_t offset,
- int *errp)
+ int little_endian, int *errp)
{
ctf_sect_t ctfsect;
ctf_dict_t *fp;
@@ -708,7 +723,11 @@ ctf_dict_open_by_offset (const struct ctf_archive *arc,
ctfsect.cts_data = (void *) ((char *) arc + offset + sizeof (uint64_t));
fp = ctf_bufopen (&ctfsect, symsect, strsect, errp);
if (fp)
- ctf_setmodel (fp, le64toh (arc->ctfa_model));
+ {
+ ctf_setmodel (fp, le64toh (arc->ctfa_model));
+ if (little_endian >= 0)
+ ctf_symsect_endianness (fp, little_endian);
+ }
return fp;
}
@@ -961,7 +980,9 @@ ctf_archive_iter_internal (const ctf_archive_t *wrapper,
name = &nametbl[le64toh (modent[i].name_offset)];
if ((f = ctf_dict_open_internal (arc, symsect, strsect,
- name, &rc)) == NULL)
+ name,
+ wrapper->ctfi_symsect_little_endian,
+ &rc)) == NULL)
return rc;
f->ctf_archive = (ctf_archive_t *) wrapper;