binutils, objdump: Add --ctf-parent-section

This lets you examine CTF where the parent and child dicts are in entirely
different sections, rather than in a CTF archive with members with different
names.  The linker doesn't emit ELF objects structured like this, but some
third-party linkers may; it's also useful for objcopy-constructed files
in some cases.

(This is what the objdump --ctf-parent option used to do before commit
80b56fad5c in 2021.  The new semantics of that option are much more
useful, but that doesn't mean the old ones are never useful at all, so let's
bring them back.)

(I was specifically driven to add this by DTrace's obscure "ctypes" and
"dtypes" options, which dump its internal, dynamically-generated dicts out
to files for debugging purposes: there are two, one the parent of the other.
Since they're in two separate files rather than a CTF archive and we have no
tools that paste files together into archives, objdump wouldn't show them --
and even pasting them together into an ELF executable with objcopy didn't
help, since objdump had no options that could be used to look in specific
sections for the parent dict.  With --ctf-parent-section, this sort of
obscure use case becomes possible again.  You'll never need it for the
output of the normal linker.)

binutils/

	* doc/ctf.options.texi: Add --ctf-parent-section=.
	* objdump.c (dump_ctf): Implement it.
	(dump_bfd): Likewise.
	(main): Likewise.
This commit is contained in:
Nick Alcock
2023-10-02 15:37:17 +01:00
parent 0e6747d2a6
commit 6364617120
2 changed files with 61 additions and 8 deletions

View File

@@ -22,3 +22,13 @@ function at link time. When looking at CTF archives that have been
created by a linker that uses the name changer to rename the parent
archive member, @option{--ctf-parent} can be used to specify the name
used for the parent.
@item --ctf-parent-section=@var{section}
This option lets you pick a completely different section for the CTF
parent dictionary containing unambiguous types than for the child
dictionaries that contain the ambiguous remainder. The linker does
not emit ELF objects structured like this, but some third-party linkers
may. It's also convenient to inspect CTF written out as multiple raw
files to compose them with objcopy, which can put them in different
ELF sections but not in different members of a single CTF dict.

View File

@@ -108,6 +108,7 @@ static int dump_stab_section_info; /* --stabs */
static int dump_ctf_section_info; /* --ctf */
static char *dump_ctf_section_name;
static char *dump_ctf_parent_name; /* --ctf-parent */
static char *dump_ctf_parent_section_name; /* --ctf-parent-section */
static int dump_sframe_section_info; /* --sframe */
static char *dump_sframe_section_name;
static int do_demangle; /* -C, --demangle */
@@ -485,6 +486,7 @@ enum option_values
#ifdef ENABLE_LIBCTF
OPTION_CTF,
OPTION_CTF_PARENT,
OPTION_CTF_PARENT_SECTION,
#endif
OPTION_SFRAME,
OPTION_VISUALIZE_JUMPS,
@@ -500,6 +502,7 @@ static struct option long_options[]=
#ifdef ENABLE_LIBCTF
{"ctf", optional_argument, NULL, OPTION_CTF},
{"ctf-parent", required_argument, NULL, OPTION_CTF_PARENT},
{"ctf-parent-section", required_argument, NULL, OPTION_CTF_PARENT_SECTION},
#endif
{"debugging", no_argument, NULL, 'g'},
{"debugging-tags", no_argument, NULL, 'e'},
@@ -4854,11 +4857,14 @@ dump_ctf_archive_member (ctf_dict_t *ctf, const char *name, ctf_dict_t *parent,
/* Dump the CTF debugging information. */
static void
dump_ctf (bfd *abfd, const char *sect_name, const char *parent_name)
dump_ctf (bfd *abfd, const char *sect_name, const char *parent_name,
const char *parent_sect_name)
{
asection *sec;
ctf_archive_t *ctfa = NULL;
bfd_byte *ctfdata;
asection *sec, *psec = NULL;
ctf_archive_t *ctfa;
ctf_archive_t *ctfpa = NULL;
bfd_byte *ctfdata = NULL;
bfd_byte *ctfpdata = NULL;
ctf_sect_t ctfsect;
ctf_dict_t *parent;
ctf_dict_t *fp;
@@ -4878,7 +4884,8 @@ dump_ctf (bfd *abfd, const char *sect_name, const char *parent_name)
}
/* Load the CTF file and dump it. Preload the parent dict, since it will
need to be imported into every child in turn. */
need to be imported into every child in turn. The parent dict may come
from a different section entirely. */
ctfsect = make_ctfsect (sect_name, ctfdata, bfd_section_size (sec));
if ((ctfa = ctf_bfdopen_ctfsect (abfd, &ctfsect, &err)) == NULL)
@@ -4890,13 +4897,38 @@ dump_ctf (bfd *abfd, const char *sect_name, const char *parent_name)
return;
}
if ((parent = ctf_dict_open (ctfa, parent_name, &err)) == NULL)
if (parent_sect_name)
{
psec = read_section (abfd, parent_sect_name, &ctfpdata);
if (sec == NULL)
{
my_bfd_nonfatal (bfd_get_filename (abfd));
free (ctfdata);
return;
}
ctfsect = make_ctfsect (parent_sect_name, ctfpdata, bfd_section_size (psec));
if ((ctfpa = ctf_bfdopen_ctfsect (abfd, &ctfsect, &err)) == NULL)
{
dump_ctf_errs (NULL);
non_fatal (_("CTF open failure: %s"), ctf_errmsg (err));
my_bfd_nonfatal (bfd_get_filename (abfd));
free (ctfdata);
free (ctfpdata);
return;
}
}
else
ctfpa = ctfa;
if ((parent = ctf_dict_open (ctfpa, parent_name, &err)) == NULL)
{
dump_ctf_errs (NULL);
non_fatal (_("CTF open failure: %s"), ctf_errmsg (err));
my_bfd_nonfatal (bfd_get_filename (abfd));
ctf_close (ctfa);
free (ctfdata);
free (ctfpdata);
return;
}
@@ -4913,11 +4945,17 @@ dump_ctf (bfd *abfd, const char *sect_name, const char *parent_name)
ctf_dict_close (parent);
ctf_close (ctfa);
free (ctfdata);
if (parent_sect_name)
{
ctf_close (ctfpa);
free (ctfpdata);
}
}
#else
static void
dump_ctf (bfd *abfd ATTRIBUTE_UNUSED, const char *sect_name ATTRIBUTE_UNUSED,
const char *parent_name ATTRIBUTE_UNUSED) {}
const char *parent_name ATTRIBUTE_UNUSED,
const char *parent_sect_name ATTRIBUTE_UNUSED) {}
#endif
static void
@@ -5733,7 +5771,8 @@ dump_bfd (bfd *abfd, bool is_mainfile)
if (is_mainfile || process_links)
{
if (dump_ctf_section_info)
dump_ctf (abfd, dump_ctf_section_name, dump_ctf_parent_name);
dump_ctf (abfd, dump_ctf_section_name, dump_ctf_parent_name,
dump_ctf_parent_section_name);
if (dump_sframe_section_info)
dump_section_sframe (abfd, dump_sframe_section_name);
if (dump_stab_section_info)
@@ -6243,6 +6282,9 @@ main (int argc, char **argv)
case OPTION_CTF_PARENT:
dump_ctf_parent_name = xstrdup (optarg);
break;
case OPTION_CTF_PARENT_SECTION:
dump_ctf_parent_section_name = xstrdup (optarg);
break;
#endif
case OPTION_SFRAME:
dump_sframe_section_info = true;
@@ -6337,6 +6379,7 @@ main (int argc, char **argv)
free (dump_ctf_section_name);
free (dump_ctf_parent_name);
free ((void *) source_comment);
free (dump_ctf_parent_section_name);
return exit_status;
}