aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--binutils/doc/ctf.options.texi10
-rw-r--r--binutils/objdump.c59
2 files changed, 61 insertions, 8 deletions
diff --git a/binutils/doc/ctf.options.texi b/binutils/doc/ctf.options.texi
index 2820946..0b04e9d 100644
--- a/binutils/doc/ctf.options.texi
+++ b/binutils/doc/ctf.options.texi
@@ -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.
diff --git a/binutils/objdump.c b/binutils/objdump.c
index f92e14b..70581c9 100644
--- a/binutils/objdump.c
+++ b/binutils/objdump.c
@@ -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;
}