From 7d9813f196bd1a98d49c2b9b7b90351cb2435b0d Mon Sep 17 00:00:00 2001 From: Nick Alcock Date: Wed, 24 Apr 2019 12:04:33 +0100 Subject: [PATCH] binutils: CTF support for objdump and readelf This introduces CTF support for objdump and readelf. objdump has the following new arguments: --ctf=SECTION: display CTF in the given SECTION --ctf-parent=SECTION: name of CTF section that is the parent of this section readelf has the above, and these two as well: --ctf-symbols=SECTION: name of symbol table section (optional) --ctf-strings=SECTION: name of string table section (optional) (objdump can always use BFD machinery to determine the applicable string and symbol tables automatically, so these arguments are unnecessary.) Nearly all the work is done by the ctf_dump machinery in libctf: most of the remaining work is option-processing and section-reading, and thus is different for objdump and readelf: the minimal amount of similar code remaining is, in my view, too small to share, particularly given that objdump uses ctf_bfdopen() and readelf uses ctf_simple_open() since it doesn't have a bfd. I am not particularly satisfied with the way resources are freed in either of these (I was forced to do it at the top level, for lack of anywhere else to free resources allocated during option processing), but I can't see any better way to do it without introducing new infrastructure for no other purpose. There are essentially arbitrary ordering changes to the Makefile.in's order of libtool-related stuff that I can't get rid of, but they have no semantic effect. (It is possible that some hunks of these changes could be dropped, but that seems a bit risky to me.) binutils/ * objdump.c (ctf-api.h): New include. (dump_ctf_section_info): New variable. (dump_ctf_section_name): Likewise. (usage): Describe new options. (enum option_values): Add OPTION_CTF and OPTION_CTF_PARENT. (main): Use them to add --ctf and --ctf-parent. (read_section_stabs): Add new parameter, entsize_ptr. (find_stabs_section): Adjust accordingly. (make_ctfsect): New. (dump_ctf_indent_lines): New. (dump_ctf_archive_member): New. (dump_ctf): New. (dump_bfd): Call it. Free resources afterwards. * readelf.c (ctf-api.h): New include. (CTF_DUMP): New. (static bfd_boolean do_ctf): Likewise. (dump_ctf_parent_name): Likewise. (dump_ctf_symtab_name): Likewise. (dump_ctf_strtab_name): Likewise. (OPTION_CTF_DUMP): Likewise. (OPTION_CTF_PARENT): Likewise. (OPTION_CTF_SYMBOLS): Likewise. (OPTION_CTF_STRINGS): Likewise. (options): Add them. (usage): Likewise. (parse_args): Handle the new options, requesting CTF_DUMP. (process_section_contents): Handle CTF_DUMP. (shdr_to_ctf_sect): New. (dump_ctf_indent_lines): New. (dump_section_as_ctf): New. (main): Free resources. * Makefile.am (LIBCTF): New variable. (objdump_DEPENDENCIES): Use it. (readelf_DEPENDENCIES): Likewise. (objdump_LDADD): Likewise. (readelf_LDADD): Likewise. * aclocal.m4: Regenerated. * Makefile.in: Likewise. * doc/binutils.texi (objdump): Document the new options. (readelf): Likewise. * doc/ctf.options.texi: New. * doc/Makefile.in: Regenerated. * NEWS: Mention the new feature. --- binutils/ChangeLog | 47 ++++++++ binutils/Makefile.am | 10 +- binutils/Makefile.in | 18 +-- binutils/NEWS | 5 +- binutils/aclocal.m4 | 10 +- binutils/doc/Makefile.in | 9 +- binutils/doc/binutils.texi | 19 ++++ binutils/doc/ctf.options.texi | 14 +++ binutils/objdump.c | 169 +++++++++++++++++++++++++++- binutils/readelf.c | 206 ++++++++++++++++++++++++++++++++++ 10 files changed, 480 insertions(+), 27 deletions(-) create mode 100644 binutils/doc/ctf.options.texi diff --git a/binutils/ChangeLog b/binutils/ChangeLog index 18ec1826c16..b66f0b29d3e 100644 --- a/binutils/ChangeLog +++ b/binutils/ChangeLog @@ -1,3 +1,50 @@ +2019-05-28 Nick Alcock + + * objdump.c (ctf-api.h): New include. + (dump_ctf_section_info): New variable. + (dump_ctf_section_name): Likewise. + (usage): Describe new options. + (enum option_values): Add OPTION_CTF and OPTION_CTF_PARENT. + (main): Use them to add --ctf and --ctf-parent. + (read_section_stabs): Add new parameter, entsize_ptr. + (find_stabs_section): Adjust accordingly. + (make_ctfsect): New. + (dump_ctf_indent_lines): New. + (dump_ctf_archive_member): New. + (dump_ctf): New. + (dump_bfd): Call it. Free resources afterwards. + * readelf.c (ctf-api.h): New include. + (CTF_DUMP): New. + (static bfd_boolean do_ctf): Likewise. + (dump_ctf_parent_name): Likewise. + (dump_ctf_symtab_name): Likewise. + (dump_ctf_strtab_name): Likewise. + (OPTION_CTF_DUMP): Likewise. + (OPTION_CTF_PARENT): Likewise. + (OPTION_CTF_SYMBOLS): Likewise. + (OPTION_CTF_STRINGS): Likewise. + (options): Add them. + (usage): Likewise. + (parse_args): Handle the new options, requesting CTF_DUMP. + (process_section_contents): Handle CTF_DUMP. + (shdr_to_ctf_sect): New. + (dump_ctf_indent_lines): New. + (dump_section_as_ctf): New. + (main): Free resources. + * Makefile.am (LIBCTF): New variable. + (objdump_DEPENDENCIES): Use it. + (readelf_DEPENDENCIES): Likewise. + (objdump_LDADD): Likewise. + (readelf_LDADD): Likewise. + * aclocal.m4: Regenerated. + * Makefile.in: Likewise. + + * doc/binutils.texi (objdump): Document the new options. + (readelf): Likewise. + * doc/ctf.options.texi: New. + * doc/Makefile.in: Regenerated. + * NEWS: Mention the new feature. + 2019-05-27 Alan Modra * readelf.c (process_section_groups): Continue processing groups diff --git a/binutils/Makefile.am b/binutils/Makefile.am index 7d59d8c4b5c..128494ca9ee 100644 --- a/binutils/Makefile.am +++ b/binutils/Makefile.am @@ -161,6 +161,8 @@ BFDLIB = ../bfd/libbfd.la OPCODES = ../opcodes/libopcodes.la +LIBCTF = ../libctf/libctf.a + LIBIBERTY = ../libiberty/libiberty.a POTFILES = $(CFILES) $(DEBUG_SRCS) $(HFILES) @@ -211,7 +213,7 @@ installcheck-local: # which depends on libintl, since we don't know whether LIBINTL_DEP will be # non-empty until configure time. Ugh! size_DEPENDENCIES = $(LIBINTL_DEP) $(LIBIBERTY) $(BFDLIB) -objdump_DEPENDENCIES = $(LIBINTL_DEP) $(LIBIBERTY) $(BFDLIB) $(OPCODES) $(OBJDUMP_PRIVATE_OFILES) +objdump_DEPENDENCIES = $(LIBINTL_DEP) $(LIBIBERTY) $(BFDLIB) $(OPCODES) $(LIBCTF) $(OBJDUMP_PRIVATE_OFILES) nm_new_DEPENDENCIES = $(LIBINTL_DEP) $(LIBIBERTY) $(BFDLIB) ar_DEPENDENCIES = $(LIBINTL_DEP) $(LIBIBERTY) $(BFDLIB) strings_DEPENDENCIES = $(LIBINTL_DEP) $(LIBIBERTY) $(BFDLIB) @@ -226,7 +228,7 @@ dlltool_DEPENDENCIES = $(LIBINTL_DEP) $(LIBIBERTY) $(BFDLIB) windres_DEPENDENCIES = $(LIBINTL_DEP) $(LIBIBERTY) $(BFDLIB) windmc_DEPENDENCIES = $(LIBINTL_DEP) $(LIBIBERTY) $(BFDLIB) addr2line_DEPENDENCIES = $(LIBINTL_DEP) $(LIBIBERTY) $(BFDLIB) -readelf_DEPENDENCIES = $(LIBINTL_DEP) $(LIBIBERTY) +readelf_DEPENDENCIES = $(LIBINTL_DEP) $(LIBIBERTY) $(LIBCTF) elfedit_DEPENDENCIES = $(LIBINTL_DEP) $(LIBIBERTY) dllwrap_DEPENDENCIES = $(LIBINTL_DEP) $(LIBIBERTY) bfdtest1_DEPENDENCIES = $(LIBINTL_DEP) $(LIBIBERTY) $(BFDLIB) @@ -241,7 +243,7 @@ objcopy_SOURCES = objcopy.c not-strip.c rename.c $(WRITE_DEBUG_SRCS) $(BULIBS) strings_SOURCES = strings.c $(BULIBS) readelf_SOURCES = readelf.c version.c unwind-ia64.c dwarf.c $(ELFLIBS) -readelf_LDADD = $(LIBINTL) $(LIBIBERTY) $(ZLIB) +readelf_LDADD = $(LIBINTL) $(LIBCTF) $(LIBIBERTY) $(ZLIB) elfedit_SOURCES = elfedit.c version.c $(ELFLIBS) elfedit_LDADD = $(LIBINTL) $(LIBIBERTY) @@ -252,7 +254,7 @@ nm_new_SOURCES = nm.c $(BULIBS) objdump_SOURCES = objdump.c dwarf.c prdbg.c $(DEBUG_SRCS) $(BULIBS) $(ELFLIBS) EXTRA_objdump_SOURCES = od-xcoff.c -objdump_LDADD = $(OBJDUMP_PRIVATE_OFILES) $(OPCODES) $(BFDLIB) $(LIBIBERTY) $(LIBINTL) +objdump_LDADD = $(OBJDUMP_PRIVATE_OFILES) $(OPCODES) $(LIBCTF) $(BFDLIB) $(LIBIBERTY) $(LIBINTL) objdump.@OBJEXT@:objdump.c if am__fastdepCC diff --git a/binutils/Makefile.in b/binutils/Makefile.in index f6cb22f95a3..480385bd67b 100644 --- a/binutils/Makefile.in +++ b/binutils/Makefile.in @@ -119,7 +119,10 @@ EXTRA_PROGRAMS = srconv$(EXEEXT) sysdump$(EXEEXT) coffdump$(EXEEXT) \ $(am__EXEEXT_4) subdir = . ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 -am__aclocal_m4_deps = $(top_srcdir)/../bfd/acinclude.m4 \ +am__aclocal_m4_deps = $(top_srcdir)/../libtool.m4 \ + $(top_srcdir)/../ltoptions.m4 $(top_srcdir)/../ltsugar.m4 \ + $(top_srcdir)/../ltversion.m4 $(top_srcdir)/../lt~obsolete.m4 \ + $(top_srcdir)/../bfd/acinclude.m4 \ $(top_srcdir)/../bfd/warning.m4 $(top_srcdir)/../config/acx.m4 \ $(top_srcdir)/../config/depstand.m4 \ $(top_srcdir)/../config/gettext-sister.m4 \ @@ -135,9 +138,7 @@ am__aclocal_m4_deps = $(top_srcdir)/../bfd/acinclude.m4 \ $(top_srcdir)/../config/plugins.m4 \ $(top_srcdir)/../config/po.m4 \ $(top_srcdir)/../config/progtest.m4 \ - $(top_srcdir)/../config/zlib.m4 $(top_srcdir)/../libtool.m4 \ - $(top_srcdir)/../ltoptions.m4 $(top_srcdir)/../ltsugar.m4 \ - $(top_srcdir)/../ltversion.m4 $(top_srcdir)/../lt~obsolete.m4 \ + $(top_srcdir)/../config/zlib.m4 \ $(top_srcdir)/../bfd/version.m4 $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) @@ -647,6 +648,7 @@ BULIBS = bucomm.c version.c filemode.c ELFLIBS = elfcomm.c BFDLIB = ../bfd/libbfd.la OPCODES = ../opcodes/libopcodes.la +LIBCTF = ../libctf/libctf.a LIBIBERTY = ../libiberty/libiberty.a POTFILES = $(CFILES) $(DEBUG_SRCS) $(HFILES) EXPECT = expect @@ -671,7 +673,7 @@ CC_FOR_TARGET = ` \ # which depends on libintl, since we don't know whether LIBINTL_DEP will be # non-empty until configure time. Ugh! size_DEPENDENCIES = $(LIBINTL_DEP) $(LIBIBERTY) $(BFDLIB) -objdump_DEPENDENCIES = $(LIBINTL_DEP) $(LIBIBERTY) $(BFDLIB) $(OPCODES) $(OBJDUMP_PRIVATE_OFILES) +objdump_DEPENDENCIES = $(LIBINTL_DEP) $(LIBIBERTY) $(BFDLIB) $(OPCODES) $(LIBCTF) $(OBJDUMP_PRIVATE_OFILES) nm_new_DEPENDENCIES = $(LIBINTL_DEP) $(LIBIBERTY) $(BFDLIB) ar_DEPENDENCIES = $(LIBINTL_DEP) $(LIBIBERTY) $(BFDLIB) strings_DEPENDENCIES = $(LIBINTL_DEP) $(LIBIBERTY) $(BFDLIB) @@ -686,7 +688,7 @@ dlltool_DEPENDENCIES = $(LIBINTL_DEP) $(LIBIBERTY) $(BFDLIB) windres_DEPENDENCIES = $(LIBINTL_DEP) $(LIBIBERTY) $(BFDLIB) windmc_DEPENDENCIES = $(LIBINTL_DEP) $(LIBIBERTY) $(BFDLIB) addr2line_DEPENDENCIES = $(LIBINTL_DEP) $(LIBIBERTY) $(BFDLIB) -readelf_DEPENDENCIES = $(LIBINTL_DEP) $(LIBIBERTY) +readelf_DEPENDENCIES = $(LIBINTL_DEP) $(LIBIBERTY) $(LIBCTF) elfedit_DEPENDENCIES = $(LIBINTL_DEP) $(LIBIBERTY) dllwrap_DEPENDENCIES = $(LIBINTL_DEP) $(LIBIBERTY) bfdtest1_DEPENDENCIES = $(LIBINTL_DEP) $(LIBIBERTY) $(BFDLIB) @@ -696,14 +698,14 @@ size_SOURCES = size.c $(BULIBS) objcopy_SOURCES = objcopy.c not-strip.c rename.c $(WRITE_DEBUG_SRCS) $(BULIBS) strings_SOURCES = strings.c $(BULIBS) readelf_SOURCES = readelf.c version.c unwind-ia64.c dwarf.c $(ELFLIBS) -readelf_LDADD = $(LIBINTL) $(LIBIBERTY) $(ZLIB) +readelf_LDADD = $(LIBINTL) $(LIBCTF) $(LIBIBERTY) $(ZLIB) elfedit_SOURCES = elfedit.c version.c $(ELFLIBS) elfedit_LDADD = $(LIBINTL) $(LIBIBERTY) strip_new_SOURCES = objcopy.c is-strip.c rename.c $(WRITE_DEBUG_SRCS) $(BULIBS) nm_new_SOURCES = nm.c $(BULIBS) objdump_SOURCES = objdump.c dwarf.c prdbg.c $(DEBUG_SRCS) $(BULIBS) $(ELFLIBS) EXTRA_objdump_SOURCES = od-xcoff.c -objdump_LDADD = $(OBJDUMP_PRIVATE_OFILES) $(OPCODES) $(BFDLIB) $(LIBIBERTY) $(LIBINTL) +objdump_LDADD = $(OBJDUMP_PRIVATE_OFILES) $(OPCODES) $(LIBCTF) $(BFDLIB) $(LIBIBERTY) $(LIBINTL) cxxfilt_SOURCES = cxxfilt.c $(BULIBS) ar_SOURCES = arparse.y arlex.l ar.c not-ranlib.c arsup.c rename.c binemul.c \ emul_$(EMULATION).c $(BULIBS) diff --git a/binutils/NEWS b/binutils/NEWS index 8383a6a91b2..b8921814eeb 100644 --- a/binutils/NEWS +++ b/binutils/NEWS @@ -18,7 +18,10 @@ displayed. In addition when combined with --disassemble the --dwarf= follow-links option will ensure that any symbol tables in the linked files are read and used when disassembling code in the main file. - + + * Add support for dumping types encoded in the Compact Type Format + to objdump and readelf. + Changes in 2.32: * The addr2line, c++filt, nm and objdump tools now have a limit on the diff --git a/binutils/aclocal.m4 b/binutils/aclocal.m4 index 4fa32fffd8c..1b1320fd1a9 100644 --- a/binutils/aclocal.m4 +++ b/binutils/aclocal.m4 @@ -1185,6 +1185,11 @@ AC_SUBST([am__tar]) AC_SUBST([am__untar]) ]) # _AM_PROG_TAR +m4_include([../libtool.m4]) +m4_include([../ltoptions.m4]) +m4_include([../ltsugar.m4]) +m4_include([../ltversion.m4]) +m4_include([../lt~obsolete.m4]) m4_include([../bfd/acinclude.m4]) m4_include([../bfd/warning.m4]) m4_include([../config/acx.m4]) @@ -1203,8 +1208,3 @@ m4_include([../config/plugins.m4]) m4_include([../config/po.m4]) m4_include([../config/progtest.m4]) m4_include([../config/zlib.m4]) -m4_include([../libtool.m4]) -m4_include([../ltoptions.m4]) -m4_include([../ltsugar.m4]) -m4_include([../ltversion.m4]) -m4_include([../lt~obsolete.m4]) diff --git a/binutils/doc/Makefile.in b/binutils/doc/Makefile.in index a0777d8fcc7..7fa622a3649 100644 --- a/binutils/doc/Makefile.in +++ b/binutils/doc/Makefile.in @@ -108,7 +108,10 @@ host_triplet = @host@ target_triplet = @target@ subdir = doc ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 -am__aclocal_m4_deps = $(top_srcdir)/../bfd/acinclude.m4 \ +am__aclocal_m4_deps = $(top_srcdir)/../libtool.m4 \ + $(top_srcdir)/../ltoptions.m4 $(top_srcdir)/../ltsugar.m4 \ + $(top_srcdir)/../ltversion.m4 $(top_srcdir)/../lt~obsolete.m4 \ + $(top_srcdir)/../bfd/acinclude.m4 \ $(top_srcdir)/../bfd/warning.m4 $(top_srcdir)/../config/acx.m4 \ $(top_srcdir)/../config/depstand.m4 \ $(top_srcdir)/../config/gettext-sister.m4 \ @@ -124,9 +127,7 @@ am__aclocal_m4_deps = $(top_srcdir)/../bfd/acinclude.m4 \ $(top_srcdir)/../config/plugins.m4 \ $(top_srcdir)/../config/po.m4 \ $(top_srcdir)/../config/progtest.m4 \ - $(top_srcdir)/../config/zlib.m4 $(top_srcdir)/../libtool.m4 \ - $(top_srcdir)/../ltoptions.m4 $(top_srcdir)/../ltsugar.m4 \ - $(top_srcdir)/../ltversion.m4 $(top_srcdir)/../lt~obsolete.m4 \ + $(top_srcdir)/../config/zlib.m4 \ $(top_srcdir)/../bfd/version.m4 $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) diff --git a/binutils/doc/binutils.texi b/binutils/doc/binutils.texi index 4a7f0f97d1f..f3c4eaea4f5 100644 --- a/binutils/doc/binutils.texi +++ b/binutils/doc/binutils.texi @@ -2110,6 +2110,7 @@ objdump [@option{-a}|@option{--archive-headers}] [@option{-s}|@option{--full-contents}] [@option{-W[lLiaprmfFsoRtUuTgAckK]}| @option{--dwarf}[=rawline,=decodedline,=info,=abbrev,=pubnames,=aranges,=macro,=frames,=frames-interp,=str,=loc,=Ranges,=pubtypes,=trace_info,=trace_abbrev,=trace_aranges,=gdb_index,=addr,=cu_index,=links,=follow-links]] + [@option{--ctf=}@var{section}] [@option{-G}|@option{--stabs}] [@option{-t}|@option{--syms}] [@option{-T}|@option{--dynamic-syms}] @@ -2122,6 +2123,9 @@ objdump [@option{-a}|@option{--archive-headers}] [@option{--adjust-vma=}@var{offset}] [@option{--dwarf-depth=@var{n}}] [@option{--dwarf-start=@var{n}}] + [@option{--ctf-parent=}@var{section}] + [@option{--ctf-symbols=}@var{section}] + [@option{--ctf-strings=}@var{section}] [@option{--no-recurse-limit}|@option{--recurse-limit}] [@option{--special-syms}] [@option{--prefix=}@var{prefix}] @@ -2637,6 +2641,8 @@ instructions. @item --dwarf-check Enable additional checks for consistency of Dwarf information. +@include ctf.options.texi + @item -G @itemx --stabs @cindex stab @@ -4636,6 +4642,10 @@ readelf [@option{-a}|@option{--all}] @option{--debug-dump}[=rawline,=decodedline,=info,=abbrev,=pubnames,=aranges,=macro,=frames,=frames-interp,=str,=loc,=Ranges,=pubtypes,=trace_info,=trace_abbrev,=trace_aranges,=gdb_index,=addr,=cu_index,=links,=follow-links]] [@option{--dwarf-depth=@var{n}}] [@option{--dwarf-start=@var{n}}] + [@option{--ctf=}@var{section}] + [@option{--ctf-parent=}@var{section}] + [@option{--ctf-symbols=}@var{section}] + [@option{--ctf-strings=}@var{section}] [@option{-I}|@option{--histogram}] [@option{-v}|@option{--version}] [@option{-W}|@option{--wide}] @@ -4816,6 +4826,15 @@ command to @command{ar}, but without using the BFD library. @xref{ar}. @itemx --debug-dump[=rawline,=decodedline,=info,=abbrev,=pubnames,=aranges,=macro,=frames,=frames-interp,=str,=loc,=Ranges,=pubtypes,=trace_info,=trace_abbrev,=trace_aranges,=gdb_index,=addr,=cu_index,=links,=follow-links] @include debug.options.texi +@include ctf.options.texi +@item --ctf-symbols=@var{section} +@item --ctf-strings=@var{section} +Specify the name of another section from which the CTF file can inherit +strings and symbols. + +If either of @option{--ctf-symbols} or @option{--ctf-strings} is specified, the +other must be specified as well. + @item -I @itemx --histogram Display a histogram of bucket list lengths when displaying the contents diff --git a/binutils/doc/ctf.options.texi b/binutils/doc/ctf.options.texi new file mode 100644 index 00000000000..cf0528044a5 --- /dev/null +++ b/binutils/doc/ctf.options.texi @@ -0,0 +1,14 @@ +@c This file contains the entry for the --ctf, --ctf-parent, --ctf-symbols, -and +@c --ctf-strings options that are common to both readelf and objdump. + +@item --ctf=@var{section} +@cindex CTF +@cindex Compact Type Format + +Display the contents of the specified CTF section. CTF sections themselves +contain many subsections, all of which are displayed in order. + +@item --ctf-parent=@var{section} + +Specify the name of another section from which the CTF file can inherit +types. diff --git a/binutils/objdump.c b/binutils/objdump.c index 7381e4885d5..156331b502e 100644 --- a/binutils/objdump.c +++ b/binutils/objdump.c @@ -56,6 +56,7 @@ #include "bucomm.h" #include "elfcomm.h" #include "dwarf.h" +#include "ctf-api.h" #include "getopt.h" #include "safe-ctype.h" #include "dis-asm.h" @@ -98,6 +99,9 @@ static bfd_boolean with_source_code; /* -S */ static int show_raw_insn; /* --show-raw-insn */ static int dump_dwarf_section_info; /* --dwarf */ 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 int do_demangle; /* -C, --demangle */ static bfd_boolean disassemble; /* -d */ static bfd_boolean disassemble_all; /* -D */ @@ -225,6 +229,7 @@ usage (FILE *stream, int status) =gdb_index,=trace_info,=trace_abbrev,=trace_aranges,\n\ =addr,=cu_index,=links,=follow-links]\n\ Display DWARF info in the file\n\ + --ctf=SECTION Display CTF info from SECTION\n\ -t, --syms Display the contents of the symbol table(s)\n\ -T, --dynamic-syms Display the contents of the dynamic symbol table\n\ -r, --reloc Display the relocation entries in the file\n\ @@ -273,7 +278,8 @@ usage (FILE *stream, int status) --dwarf-start=N Display DIEs starting with N, at the same depth\n\ or deeper\n\ --dwarf-check Make additional dwarf internal consistency checks.\ - \n\n")); + \n\ + --ctf-parent=SECTION Use SECTION as the CTF parent\n\n")); list_supported_targets (program_name, stream); list_supported_architectures (program_name, stream); @@ -308,7 +314,9 @@ enum option_values OPTION_DWARF_START, OPTION_RECURSE_LIMIT, OPTION_NO_RECURSE_LIMIT, - OPTION_INLINES + OPTION_INLINES, + OPTION_CTF, + OPTION_CTF_PARENT }; static struct option long_options[]= @@ -351,6 +359,8 @@ static struct option long_options[]= {"special-syms", no_argument, &dump_special_syms, 1}, {"include", required_argument, NULL, 'I'}, {"dwarf", optional_argument, NULL, OPTION_DWARF}, + {"ctf", required_argument, NULL, OPTION_CTF}, + {"ctf-parent", required_argument, NULL, OPTION_CTF_PARENT}, {"stabs", no_argument, NULL, 'G'}, {"start-address", required_argument, NULL, OPTION_START_ADDRESS}, {"stop-address", required_argument, NULL, OPTION_STOP_ADDRESS}, @@ -2971,7 +2981,8 @@ dump_dwarf (bfd *abfd) it. Return NULL on failure. */ static bfd_byte * -read_section_stabs (bfd *abfd, const char *sect_name, bfd_size_type *size_ptr) +read_section_stabs (bfd *abfd, const char *sect_name, bfd_size_type *size_ptr, + bfd_size_type *entsize_ptr) { asection *stabsect; bfd_byte *contents; @@ -2995,6 +3006,8 @@ read_section_stabs (bfd *abfd, const char *sect_name, bfd_size_type *size_ptr) } *size_ptr = bfd_section_size (abfd, stabsect); + if (entsize_ptr) + *entsize_ptr = stabsect->entsize; return contents; } @@ -3118,11 +3131,11 @@ find_stabs_section (bfd *abfd, asection *section, void *names) { if (strtab == NULL) strtab = read_section_stabs (abfd, sought->string_section_name, - &stabstr_size); + &stabstr_size, NULL); if (strtab) { - stabs = read_section_stabs (abfd, section->name, &stab_size); + stabs = read_section_stabs (abfd, section->name, &stab_size, NULL); if (stabs) print_section_stabs (abfd, section->name, &sought->string_offset); } @@ -3184,6 +3197,140 @@ dump_bfd_header (bfd *abfd) bfd_printf_vma (abfd, abfd->start_address); printf ("\n"); } + + +/* Formatting callback function passed to ctf_dump. Returns either the pointer + it is passed, or a pointer to newly-allocated storage, in which case + dump_ctf() will free it when it no longer needs it. */ + +static char * +dump_ctf_indent_lines (ctf_sect_names_t sect ATTRIBUTE_UNUSED, + char *s, void *arg) +{ + char *spaces = arg; + char *new_s; + + if (asprintf (&new_s, "%s%s", spaces, s) < 0) + return s; + return new_s; +} + +/* Make a ctfsect suitable for ctf_bfdopen_ctfsect(). */ +static ctf_sect_t +make_ctfsect (const char *name, bfd_byte *data, + bfd_size_type size) +{ + ctf_sect_t ctfsect; + + ctfsect.cts_name = name; + ctfsect.cts_type = SHT_PROGBITS; + ctfsect.cts_flags = 0; + ctfsect.cts_entsize = 1; + ctfsect.cts_offset = 0; + ctfsect.cts_size = size; + ctfsect.cts_data = data; + + return ctfsect; +} + +/* Dump one CTF archive member. */ + +static int +dump_ctf_archive_member (ctf_file_t *ctf, const char *name, void *arg) +{ + ctf_file_t *parent = (ctf_file_t *) arg; + const char *things[] = {"Labels", "Data objects", "Function objects", + "Variables", "Types", "Strings", ""}; + const char **thing; + size_t i; + + /* Only print out the name of non-default-named archive members. + The name .ctf appears everywhere, even for things that aren't + really archives, so printing it out is liable to be confusing. */ + if (strcmp (name, ".ctf") != 0) + printf (_("\nCTF archive member: %s:\n"), sanitize_string (name)); + + ctf_import (ctf, parent); + for (i = 1, thing = things; *thing[0]; thing++, i++) + { + ctf_dump_state_t *s = NULL; + char *item; + + printf ("\n %s:\n", *thing); + while ((item = ctf_dump (ctf, &s, i, dump_ctf_indent_lines, + (void *) " ")) != NULL) + { + printf ("%s\n", item); + free (item); + } + + if (ctf_errno (ctf)) + { + non_fatal (_("Iteration failed: %s, %s\n"), *thing, + ctf_errmsg (ctf_errno (ctf))); + break; + } + } + return 0; +} + +/* Dump the CTF debugging information. */ + +static void +dump_ctf (bfd *abfd, const char *sect_name, const char *parent_name) +{ + ctf_archive_t *ctfa, *parenta = NULL; + bfd_byte *ctfdata, *parentdata = NULL; + bfd_size_type ctfsize, parentsize; + ctf_sect_t ctfsect; + ctf_file_t *parent = NULL; + int err; + + if ((ctfdata = read_section_stabs (abfd, sect_name, &ctfsize, NULL)) == NULL) + bfd_fatal (bfd_get_filename (abfd)); + + if (parent_name + && (parentdata = read_section_stabs (abfd, parent_name, &parentsize, + NULL)) == NULL) + bfd_fatal (bfd_get_filename (abfd)); + + /* Load the CTF file and dump it. */ + + ctfsect = make_ctfsect (sect_name, ctfdata, ctfsize); + if ((ctfa = ctf_bfdopen_ctfsect (abfd, &ctfsect, &err)) == NULL) + { + non_fatal (_("CTF open failure: %s\n"), ctf_errmsg (err)); + bfd_fatal (bfd_get_filename (abfd)); + } + + if (parentdata) + { + ctfsect = make_ctfsect (parent_name, parentdata, parentsize); + if ((parenta = ctf_bfdopen_ctfsect (abfd, &ctfsect, &err)) == NULL) + { + non_fatal (_("CTF open failure: %s\n"), ctf_errmsg (err)); + bfd_fatal (bfd_get_filename (abfd)); + } + + /* Assume that the applicable parent archive member is the default one. + (This is what all known implementations are expected to do, if they + put CTFs and their parents in archives together.) */ + if ((parent = ctf_arc_open_by_name (parenta, NULL, &err)) == NULL) + { + non_fatal (_("CTF open failure: %s\n"), ctf_errmsg (err)); + bfd_fatal (bfd_get_filename (abfd)); + } + } + + printf (_("Contents of CTF section %s:\n"), sanitize_string (sect_name)); + + ctf_archive_iter (ctfa, dump_ctf_archive_member, parent); + ctf_file_close (parent); + ctf_close (ctfa); + ctf_close (parenta); + free (parentdata); + free (ctfdata); +} static void @@ -3896,6 +4043,8 @@ dump_bfd (bfd *abfd, bfd_boolean is_mainfile) dump_symbols (abfd, TRUE); if (dump_dwarf_section_info) dump_dwarf (abfd); + if (dump_ctf_section_info) + dump_ctf (abfd, dump_ctf_section_name, dump_ctf_parent_name); if (dump_stab_section_info) dump_stabs (abfd); if (dump_reloc_info && ! disassemble) @@ -4335,6 +4484,14 @@ main (int argc, char **argv) case OPTION_DWARF_CHECK: dwarf_check = TRUE; break; + case OPTION_CTF: + dump_ctf_section_info = TRUE; + dump_ctf_section_name = xstrdup (optarg); + seenflag = TRUE; + break; + case OPTION_CTF_PARENT: + dump_ctf_parent_name = xstrdup (optarg); + break; case 'G': dump_stab_section_info = TRUE; seenflag = TRUE; @@ -4394,6 +4551,8 @@ main (int argc, char **argv) } free_only_list (); + free (dump_ctf_section_name); + free (dump_ctf_parent_name); END_PROGRESS (program_name); diff --git a/binutils/readelf.c b/binutils/readelf.c index 424624e0e4d..5ae58574fb4 100644 --- a/binutils/readelf.c +++ b/binutils/readelf.c @@ -60,6 +60,7 @@ #include "bucomm.h" #include "elfcomm.h" #include "dwarf.h" +#include "ctf-api.h" #include "elf/common.h" #include "elf/external.h" @@ -183,6 +184,7 @@ typedef struct elf_section_list #define DEBUG_DUMP (1 << 2) /* The -w command line switch. */ #define STRING_DUMP (1 << 3) /* The -p command line switch. */ #define RELOC_DUMP (1 << 4) /* The -R command line switch. */ +#define CTF_DUMP (1 << 5) /* The --ctf command line switch. */ typedef unsigned char dump_type; @@ -249,12 +251,17 @@ static bfd_boolean do_dump = FALSE; static bfd_boolean do_version = FALSE; static bfd_boolean do_histogram = FALSE; static bfd_boolean do_debugging = FALSE; +static bfd_boolean do_ctf = FALSE; static bfd_boolean do_arch = FALSE; static bfd_boolean do_notes = FALSE; static bfd_boolean do_archive_index = FALSE; static bfd_boolean is_32bit_elf = FALSE; static bfd_boolean decompress_dumps = FALSE; +static char *dump_ctf_parent_name; +static char *dump_ctf_symtab_name; +static char *dump_ctf_strtab_name; + struct group_list { struct group_list * next; @@ -4394,6 +4401,10 @@ get_section_type_name (Filedata * filedata, unsigned int sh_type) #define OPTION_DWARF_DEPTH 514 #define OPTION_DWARF_START 515 #define OPTION_DWARF_CHECK 516 +#define OPTION_CTF_DUMP 517 +#define OPTION_CTF_PARENT 518 +#define OPTION_CTF_SYMBOLS 519 +#define OPTION_CTF_STRINGS 520 static struct option options[] = { @@ -4432,6 +4443,12 @@ static struct option options[] = {"dwarf-start", required_argument, 0, OPTION_DWARF_START}, {"dwarf-check", no_argument, 0, OPTION_DWARF_CHECK}, + {"ctf", required_argument, 0, OPTION_CTF_DUMP}, + + {"ctf-symbols", required_argument, 0, OPTION_CTF_SYMBOLS}, + {"ctf-strings", required_argument, 0, OPTION_CTF_STRINGS}, + {"ctf-parent", required_argument, 0, OPTION_CTF_PARENT}, + {"version", no_argument, 0, 'v'}, {"wide", no_argument, 0, 'W'}, {"help", no_argument, 0, 'H'}, @@ -4481,6 +4498,15 @@ usage (FILE * stream) --dwarf-depth=N Do not display DIEs at depth N or greater\n\ --dwarf-start=N Display DIEs starting with N, at the same depth\n\ or deeper\n")); + fprintf (stream, _("\ + --ctf= Display CTF info from section \n\ + --ctf-parent=\n\ + Use section as the CTF parent\n\n\ + --ctf-symbols=\n\ + Use section as the CTF external symtab\n\n\ + --ctf-strings=\n\ + Use section as the CTF external strtab\n\n")); + #ifdef SUPPORT_DISASSEMBLY fprintf (stream, _("\ -i --instruction-dump=\n\ @@ -4708,6 +4734,19 @@ parse_args (Filedata * filedata, int argc, char ** argv) case OPTION_DWARF_CHECK: dwarf_check = TRUE; break; + case OPTION_CTF_DUMP: + do_ctf = TRUE; + request_dump (filedata, CTF_DUMP); + break; + case OPTION_CTF_SYMBOLS: + dump_ctf_symtab_name = strdup (optarg); + break; + case OPTION_CTF_STRINGS: + dump_ctf_strtab_name = strdup (optarg); + break; + case OPTION_CTF_PARENT: + dump_ctf_parent_name = strdup (optarg); + break; case OPTION_DYN_SYMS: do_dyn_syms = TRUE; break; @@ -13769,6 +13808,163 @@ dump_section_as_bytes (Elf_Internal_Shdr * section, return TRUE; } +static ctf_sect_t * +shdr_to_ctf_sect (ctf_sect_t *buf, Elf_Internal_Shdr *shdr, Filedata *filedata) +{ + buf->cts_name = SECTION_NAME(shdr); + buf->cts_type = shdr->sh_type; + buf->cts_flags = shdr->sh_flags; + buf->cts_size = shdr->sh_size; + buf->cts_entsize = shdr->sh_entsize; + buf->cts_offset = (off64_t) shdr->sh_offset; + + return buf; +} + +/* Formatting callback function passed to ctf_dump. Returns either the pointer + it is passed, or a pointer to newly-allocated storage, in which case + dump_ctf() will free it when it no longer needs it. */ + +static char *dump_ctf_indent_lines (ctf_sect_names_t sect ATTRIBUTE_UNUSED, + char *s, void *arg) +{ + char *spaces = arg; + char *new_s; + + if (asprintf (&new_s, "%s%s", spaces, s) < 0) + return s; + return new_s; +} + +static bfd_boolean +dump_section_as_ctf (Elf_Internal_Shdr * section, Filedata * filedata) +{ + Elf_Internal_Shdr * parent_sec = NULL; + Elf_Internal_Shdr * symtab_sec = NULL; + Elf_Internal_Shdr * strtab_sec = NULL; + void * data = NULL; + void * symdata = NULL; + void * strdata = NULL; + void * parentdata = NULL; + ctf_sect_t ctfsect, symsect, strsect, parentsect; + ctf_sect_t * symsectp = NULL; + ctf_sect_t * strsectp = NULL; + ctf_file_t * ctf = NULL; + ctf_file_t * parent = NULL; + + const char *things[] = {"Labels", "Data objects", "Function objects", + "Variables", "Types", "Strings", ""}; + const char **thing; + int err; + bfd_boolean ret = FALSE; + size_t i; + + shdr_to_ctf_sect (&ctfsect, section, filedata); + data = get_section_contents (section, filedata); + ctfsect.cts_data = data; + + if (dump_ctf_symtab_name) + { + if ((symtab_sec = find_section (filedata, dump_ctf_symtab_name)) == NULL) + { + error (_("No symbol section named %s\n"), dump_ctf_symtab_name); + goto fail; + } + if ((symdata = (void *) get_data (NULL, filedata, + symtab_sec->sh_offset, 1, + symtab_sec->sh_size, + _("symbols"))) == NULL) + goto fail; + symsectp = shdr_to_ctf_sect (&symsect, symtab_sec, filedata); + symsect.cts_data = symdata; + } + if (dump_ctf_strtab_name) + { + if ((strtab_sec = find_section (filedata, dump_ctf_strtab_name)) == NULL) + { + error (_("No string table section named %s\n"), + dump_ctf_strtab_name); + goto fail; + } + if ((strdata = (void *) get_data (NULL, filedata, + strtab_sec->sh_offset, 1, + strtab_sec->sh_size, + _("strings"))) == NULL) + goto fail; + strsectp = shdr_to_ctf_sect (&strsect, strtab_sec, filedata); + strsect.cts_data = strdata; + } + if (dump_ctf_parent_name) + { + if ((parent_sec = find_section (filedata, dump_ctf_parent_name)) == NULL) + { + error (_("No CTF parent section named %s\n"), dump_ctf_parent_name); + goto fail; + } + if ((parentdata = (void *) get_data (NULL, filedata, + parent_sec->sh_offset, 1, + parent_sec->sh_size, + _("CTF parent"))) == NULL) + goto fail; + shdr_to_ctf_sect (&parentsect, parent_sec, filedata); + parentsect.cts_data = parentdata; + } + + /* Load the CTF file and dump it. */ + + if ((ctf = ctf_bufopen (&ctfsect, symsectp, strsectp, &err)) == NULL) + { + error (_("CTF open failure: %s\n"), ctf_errmsg (err)); + goto fail; + } + + if (parentdata) + { + if ((parent = ctf_bufopen (&parentsect, symsectp, strsectp, &err)) == NULL) + { + error (_("CTF open failure: %s\n"), ctf_errmsg (err)); + goto fail; + } + + ctf_import (ctf, parent); + } + + ret = TRUE; + + printf (_("\nDump of CTF section '%s':\n"), + printable_section_name (filedata, section)); + + for (i = 1, thing = things; *thing[0]; thing++, i++) + { + ctf_dump_state_t *s = NULL; + char *item; + + printf ("\n %s:\n", *thing); + while ((item = ctf_dump (ctf, &s, i, dump_ctf_indent_lines, + (void *) " ")) != NULL) + { + printf ("%s\n", item); + free (item); + } + + if (ctf_errno (ctf)) + { + error (_("Iteration failed: %s, %s\n"), *thing, + ctf_errmsg (ctf_errno (ctf))); + ret = FALSE; + } + } + + fail: + ctf_file_close (ctf); + ctf_file_close (parent); + free (parentdata); + free (data); + free (symdata); + free (strdata); + return ret; +} + static bfd_boolean load_specific_debug_section (enum dwarf_section_display_enum debug, const Elf_Internal_Shdr * sec, @@ -14106,6 +14302,12 @@ process_section_contents (Filedata * filedata) if (! display_debug_section (i, section, filedata)) res = FALSE; } + + if (dump & CTF_DUMP) + { + if (! dump_section_as_ctf (section, filedata)) + res = FALSE; + } } /* Check to see if the user requested a @@ -19985,5 +20187,9 @@ main (int argc, char ** argv) if (cmdline.dump_sects != NULL) free (cmdline.dump_sects); + free (dump_ctf_symtab_name); + free (dump_ctf_strtab_name); + free (dump_ctf_parent_name); + return err ? EXIT_FAILURE : EXIT_SUCCESS; } -- 2.30.2