forked from Imagelibrary/binutils-gdb
libctf: strings: no external strings in BTF
One of the things BTF doesn't have is the concept of external strings which can be shared with the ELF strtab. Therefore, even if the linker has reported strings which the dict is reusing, when we generate the strtab for a BTF dict we should emit those strings into it (and we should certainly not cause the presence of external strings to prevent BTF emission!) Note that since already-written strtab entries are never erased, writing a dict as BTF and then CTF will cause external strings to be emitted even for the CTF. This sort of repeated writing in different formats seems to be very rare: in any case, the problem can be avoided by simply doing the CTF writeout first (the following BTF writeout will spot the missing external- in-CTF strings and add them). We also throw away the internal-only function ctf_strraw_explicit(), which was used to add strings with a hardwired strtab: it was only ever used to write out the variable section, which is gone in v4.
This commit is contained in:
@@ -3156,8 +3156,9 @@ ctf_dedup_emit (ctf_dict_t *output, ctf_dict_t **inputs, uint32_t ninputs,
|
|||||||
return outputs;
|
return outputs;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Deduplicate strings. This must be done after parent serialization.
|
/* Deduplicate strings. This must be done after parent serialization and child
|
||||||
The child dict ctf_parent_strlen is not updated yet. */
|
preserialization. The child dict ctf_parent_strlen is not updated yet.
|
||||||
|
(ctf_arc_write_*() does the right thing.) */
|
||||||
|
|
||||||
int
|
int
|
||||||
ctf_dedup_strings (ctf_dict_t *fp)
|
ctf_dedup_strings (ctf_dict_t *fp)
|
||||||
@@ -3191,7 +3192,7 @@ ctf_dedup_strings (ctf_dict_t *fp)
|
|||||||
if (ctf_list_empty_p (&atom->csa_refs))
|
if (ctf_list_empty_p (&atom->csa_refs))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (atom->csa_external_offset
|
if ((!fp->ctf_serialize.cs_is_btf && atom->csa_external_offset)
|
||||||
|| atom->csa_str[0] == '\0'
|
|| atom->csa_str[0] == '\0'
|
||||||
|| atom->csa_flags & CTF_STR_ATOM_NO_DEDUP)
|
|| atom->csa_flags & CTF_STR_ATOM_NO_DEDUP)
|
||||||
continue;
|
continue;
|
||||||
@@ -3240,7 +3241,7 @@ ctf_dedup_strings (ctf_dict_t *fp)
|
|||||||
if (ctf_list_empty_p (&atom->csa_refs))
|
if (ctf_list_empty_p (&atom->csa_refs))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (atom->csa_external_offset
|
if ((!fp->ctf_serialize.cs_is_btf && atom->csa_external_offset)
|
||||||
|| atom->csa_str[0] == '\0'
|
|| atom->csa_str[0] == '\0'
|
||||||
|| atom->csa_flags & CTF_STR_ATOM_NO_DEDUP)
|
|| atom->csa_flags & CTF_STR_ATOM_NO_DEDUP)
|
||||||
continue;
|
continue;
|
||||||
|
|||||||
@@ -783,8 +783,6 @@ extern char *ctf_decl_buf (ctf_decl_t *cd);
|
|||||||
|
|
||||||
extern const char *ctf_strptr (ctf_dict_t *, uint32_t);
|
extern const char *ctf_strptr (ctf_dict_t *, uint32_t);
|
||||||
extern const char *ctf_strraw (ctf_dict_t *, uint32_t);
|
extern const char *ctf_strraw (ctf_dict_t *, uint32_t);
|
||||||
extern const char *ctf_strraw_explicit (ctf_dict_t *, uint32_t,
|
|
||||||
ctf_strs_t *);
|
|
||||||
extern const char *ctf_strptr_validate (ctf_dict_t *, uint32_t);
|
extern const char *ctf_strptr_validate (ctf_dict_t *, uint32_t);
|
||||||
extern int ctf_str_create_atoms (ctf_dict_t *);
|
extern int ctf_str_create_atoms (ctf_dict_t *);
|
||||||
extern void ctf_str_free_atoms (ctf_dict_t *);
|
extern void ctf_str_free_atoms (ctf_dict_t *);
|
||||||
|
|||||||
@@ -1447,6 +1447,11 @@ ctf_link_add_strtab (ctf_dict_t *fp, ctf_link_strtab_string_f *add_string,
|
|||||||
if (fp->ctf_stypes > 0)
|
if (fp->ctf_stypes > 0)
|
||||||
return ctf_set_errno (fp, ECTF_RDONLY);
|
return ctf_set_errno (fp, ECTF_RDONLY);
|
||||||
|
|
||||||
|
/* If emitting BTF, there is no external string table. */
|
||||||
|
|
||||||
|
if (fp->ctf_serialize.cs_is_btf)
|
||||||
|
return 0;
|
||||||
|
|
||||||
while ((str = add_string (&offset, arg)) != NULL)
|
while ((str = add_string (&offset, arg)) != NULL)
|
||||||
{
|
{
|
||||||
ctf_link_out_string_cb_arg_t iter_arg = { str, offset, 0 };
|
ctf_link_out_string_cb_arg_t iter_arg = { str, offset, 0 };
|
||||||
|
|||||||
@@ -46,11 +46,10 @@ set_prov_offset (ctf_dict_t *fp, uint32_t prov_offset)
|
|||||||
fp->ctf_str_prov_offset = prov_offset;
|
fp->ctf_str_prov_offset = prov_offset;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Convert an encoded CTF string name into a pointer to a C string, possibly
|
/* Convert an encoded CTF string name into a pointer to a C string by looking
|
||||||
using an explicit internal provisional strtab rather than the fp-based
|
up the appropriate string table buffer and then adding the offset. */
|
||||||
one. */
|
|
||||||
const char *
|
const char *
|
||||||
ctf_strraw_explicit (ctf_dict_t *fp, uint32_t name, ctf_strs_t *strtab)
|
ctf_strraw (ctf_dict_t *fp, uint32_t name)
|
||||||
{
|
{
|
||||||
int stid_tab = CTF_NAME_STID (name);
|
int stid_tab = CTF_NAME_STID (name);
|
||||||
ctf_strs_t *ctsp = &fp->ctf_str[stid_tab];
|
ctf_strs_t *ctsp = &fp->ctf_str[stid_tab];
|
||||||
@@ -129,20 +128,20 @@ ctf_strraw_explicit (ctf_dict_t *fp, uint32_t name, ctf_strs_t *strtab)
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
name -= fp->ctf_header->cth_parent_strlen;
|
name -= fp->ctf_header->cth_parent_strlen;
|
||||||
|
ctsp = &fp->ctf_str[CTF_STRTAB_0];
|
||||||
if (strtab != NULL)
|
|
||||||
ctsp = strtab;
|
|
||||||
else
|
|
||||||
ctsp = &fp->ctf_str[CTF_STRTAB_0];
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* If this name is in the external strtab, and there is a synthetic strtab,
|
/* If this name is in the external strtab, and there is a synthetic strtab,
|
||||||
use it in preference. (This is used to add the set of strings -- symbol
|
and we are not serializing BTF right now, use it in preference. (This is
|
||||||
names, etc -- the linker knows about before the strtab is written out.
|
used to add the set of strings -- symbol names, etc -- the linker knows
|
||||||
The set is added to every dict, so we don't need to scan the parent.) */
|
about before the strtab is written out. The set is added to every dict, so
|
||||||
|
we don't need to scan the parent. Preventing this from operating during
|
||||||
|
BTF serialization is sufficient to prevent external refs from appearing in
|
||||||
|
BTF, because every string gets rescanned at that stage.) */
|
||||||
|
|
||||||
if (stid_tab == CTF_STRTAB_1 && fp->ctf_syn_ext_strtab != NULL)
|
if (stid_tab == CTF_STRTAB_1 && fp->ctf_syn_ext_strtab != NULL
|
||||||
|
&& !fp->ctf_serialize.cs_is_btf)
|
||||||
return ctf_dynhash_lookup (fp->ctf_syn_ext_strtab,
|
return ctf_dynhash_lookup (fp->ctf_syn_ext_strtab,
|
||||||
(void *) (uintptr_t) name);
|
(void *) (uintptr_t) name);
|
||||||
|
|
||||||
@@ -156,14 +155,6 @@ ctf_strraw_explicit (ctf_dict_t *fp, uint32_t name, ctf_strs_t *strtab)
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Convert an encoded CTF string name into a pointer to a C string by looking
|
|
||||||
up the appropriate string table buffer and then adding the offset. */
|
|
||||||
const char *
|
|
||||||
ctf_strraw (ctf_dict_t *fp, uint32_t name)
|
|
||||||
{
|
|
||||||
return ctf_strraw_explicit (fp, name, NULL);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Return a guaranteed-non-NULL pointer to the string with the given CTF
|
/* Return a guaranteed-non-NULL pointer to the string with the given CTF
|
||||||
name. */
|
name. */
|
||||||
const char *
|
const char *
|
||||||
@@ -342,11 +333,11 @@ ctf_str_add_ref_internal (ctf_dict_t *fp, const char *str,
|
|||||||
atom->csa_flags |= CTF_STR_ATOM_NO_DEDUP;
|
atom->csa_flags |= CTF_STR_ATOM_NO_DEDUP;
|
||||||
|
|
||||||
if (atom->csa_offset < get_prov_offset (fp)
|
if (atom->csa_offset < get_prov_offset (fp)
|
||||||
|| atom->csa_external_offset != 0)
|
|| (!fp->ctf_serialize.cs_is_btf && atom->csa_external_offset))
|
||||||
{
|
{
|
||||||
if (flags & CTF_STR_ADD_REF)
|
if (flags & CTF_STR_ADD_REF)
|
||||||
{
|
{
|
||||||
if (atom->csa_external_offset)
|
if (!fp->ctf_serialize.cs_is_btf && atom->csa_external_offset)
|
||||||
*ref = atom->csa_external_offset;
|
*ref = atom->csa_external_offset;
|
||||||
else
|
else
|
||||||
*ref = atom->csa_offset + lookup_fp->ctf_header->cth_parent_strlen;
|
*ref = atom->csa_offset + lookup_fp->ctf_header->cth_parent_strlen;
|
||||||
@@ -428,8 +419,7 @@ ctf_str_add_ref_internal (ctf_dict_t *fp, const char *str,
|
|||||||
|
|
||||||
Special-case "" again: it gets a real offset of zero, not a high
|
Special-case "" again: it gets a real offset of zero, not a high
|
||||||
provisional one. This atom's offset is never returned (see the special
|
provisional one. This atom's offset is never returned (see the special
|
||||||
case in ctf_strraw_explicit) and mostly exists for the sake of the
|
case in ctf_strraw) and mostly exists for the sake of the deduplicator. */
|
||||||
deduplicator. */
|
|
||||||
|
|
||||||
if (flags & CTF_STR_PROVISIONAL)
|
if (flags & CTF_STR_PROVISIONAL)
|
||||||
{
|
{
|
||||||
@@ -479,7 +469,7 @@ ctf_str_add_flagged (ctf_dict_t *fp, const char *str, uint32_t *ref,
|
|||||||
if (!atom)
|
if (!atom)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
if (atom->csa_external_offset)
|
if (!fp->ctf_serialize.cs_is_btf && atom->csa_external_offset)
|
||||||
offset = atom->csa_external_offset;
|
offset = atom->csa_external_offset;
|
||||||
else
|
else
|
||||||
offset = atom->csa_offset;
|
offset = atom->csa_offset;
|
||||||
@@ -702,10 +692,11 @@ ctf_str_write_strtab (ctf_dict_t *fp)
|
|||||||
|
|
||||||
/* The strtab contains the existing string table at its start: figure out how
|
/* The strtab contains the existing string table at its start: figure out how
|
||||||
many new strings we need to add. We only need to add new strings that have
|
many new strings we need to add. We only need to add new strings that have
|
||||||
no external offset, that have refs, and that are found in the provisional
|
no external offset (or are BTF, for which external offsets are ignored),
|
||||||
strtab. If the existing strtab is empty and has no parent strings, we also
|
that have refs, and that are found in the provisional strtab. If the
|
||||||
need to add the null string at its start. (Dicts promoted from CTFv3 and
|
existing strtab is empty and has no parent strings, we also need to add the
|
||||||
below always have no parent strings in this sense.) */
|
null string at its start. (Dicts promoted from CTFv3 and below always have
|
||||||
|
no parent strings in this sense.) */
|
||||||
|
|
||||||
strtab->cts_len = fp->ctf_str[CTF_STRTAB_0].cts_len;
|
strtab->cts_len = fp->ctf_str[CTF_STRTAB_0].cts_len;
|
||||||
|
|
||||||
@@ -730,7 +721,8 @@ ctf_str_write_strtab (ctf_dict_t *fp)
|
|||||||
if (!ctf_assert (fp, atom))
|
if (!ctf_assert (fp, atom))
|
||||||
goto err_strtab;
|
goto err_strtab;
|
||||||
|
|
||||||
if (atom->csa_str[0] == 0 || atom->csa_external_offset
|
if (atom->csa_str[0] == 0
|
||||||
|
|| (!fp->ctf_serialize.cs_is_btf && atom->csa_external_offset)
|
||||||
|| atom->csa_offset < prov_offset
|
|| atom->csa_offset < prov_offset
|
||||||
|| ctf_list_empty_p (&atom->csa_refs))
|
|| ctf_list_empty_p (&atom->csa_refs))
|
||||||
continue;
|
continue;
|
||||||
@@ -767,7 +759,8 @@ ctf_str_write_strtab (ctf_dict_t *fp)
|
|||||||
if (!ctf_assert (fp, atom))
|
if (!ctf_assert (fp, atom))
|
||||||
goto err_sorttab;
|
goto err_sorttab;
|
||||||
|
|
||||||
if (atom->csa_str[0] == 0 || atom->csa_external_offset
|
if (atom->csa_str[0] == 0
|
||||||
|
|| (!fp->ctf_serialize.cs_is_btf && atom->csa_external_offset)
|
||||||
|| atom->csa_offset < prov_offset
|
|| atom->csa_offset < prov_offset
|
||||||
|| ctf_list_empty_p (&atom->csa_refs))
|
|| ctf_list_empty_p (&atom->csa_refs))
|
||||||
continue;
|
continue;
|
||||||
@@ -821,7 +814,7 @@ ctf_str_write_strtab (ctf_dict_t *fp)
|
|||||||
if (ctf_list_empty_p (&atom->csa_refs))
|
if (ctf_list_empty_p (&atom->csa_refs))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (atom->csa_external_offset)
|
if (!fp->ctf_serialize.cs_is_btf && atom->csa_external_offset)
|
||||||
offset = atom->csa_external_offset;
|
offset = atom->csa_external_offset;
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|||||||
Reference in New Issue
Block a user