From 42b6953bbad652d3f7cba405c941ad9c6eab26b0 Mon Sep 17 00:00:00 2001 From: Indu Bhagat Date: Tue, 15 Nov 2022 15:07:09 -0800 Subject: readelf/objdump: support for SFrame section This patch adds support for SFrame in readelf and objdump. The arguments of --sframe are optional for both readelf and objdump. include/ChangeLog: * sframe-api.h (dump_sframe): New function declaration. ChangeLog: * binutils/Makefile.am: Add dependency on libsframe for readelf and objdump. * binutils/Makefile.in: Regenerate. * binutils/doc/binutils.texi: Document --sframe=[section]. * binutils/doc/sframe.options.texi: New file. * binutils/objdump.c: Add support for SFrame format. * binutils/readelf.c: Likewise. * include/sframe-api.h: Add new API for dumping .sframe section. * libsframe/Makefile.am: Add sframe-dump.c. * libsframe/Makefile.in: Regenerate. * libsframe/sframe-dump.c: New file. --- libsframe/Makefile.am | 2 +- libsframe/Makefile.in | 12 +++- libsframe/sframe-dump.c | 181 ++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 192 insertions(+), 3 deletions(-) create mode 100644 libsframe/sframe-dump.c (limited to 'libsframe') diff --git a/libsframe/Makefile.am b/libsframe/Makefile.am index 940494d..d8198a16 100644 --- a/libsframe/Makefile.am +++ b/libsframe/Makefile.am @@ -33,7 +33,7 @@ include_HEADERS = noinst_LTLIBRARIES = libsframe.la endif -libsframe_la_SOURCES = sframe.c sframe-error.c +libsframe_la_SOURCES = sframe.c sframe-dump.c sframe-error.c libsframe_la_CPPFLAGS = $(AM_CPPFLAGS) include testsuite/local.mk diff --git a/libsframe/Makefile.in b/libsframe/Makefile.in index 2d1ea89..340bfe8 100644 --- a/libsframe/Makefile.in +++ b/libsframe/Makefile.in @@ -149,7 +149,7 @@ am__installdirs = "$(DESTDIR)$(libdir)" "$(DESTDIR)$(includedir)" LTLIBRARIES = $(lib_LTLIBRARIES) $(noinst_LTLIBRARIES) libsframe_la_LIBADD = am_libsframe_la_OBJECTS = libsframe_la-sframe.lo \ - libsframe_la-sframe-error.lo + libsframe_la-sframe-dump.lo libsframe_la-sframe-error.lo libsframe_la_OBJECTS = $(am_libsframe_la_OBJECTS) AM_V_lt = $(am__v_lt_@AM_V@) am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@) @@ -427,7 +427,7 @@ AM_CFLAGS = @ac_libsframe_warn_cflags@ @INSTALL_LIBBFD_FALSE@include_HEADERS = @INSTALL_LIBBFD_TRUE@include_HEADERS = $(INCDIR)/sframe.h $(INCDIR)/sframe-api.h @INSTALL_LIBBFD_FALSE@noinst_LTLIBRARIES = libsframe.la -libsframe_la_SOURCES = sframe.c sframe-error.c +libsframe_la_SOURCES = sframe.c sframe-dump.c sframe-error.c libsframe_la_CPPFLAGS = $(AM_CPPFLAGS) # Setup the testing framework @@ -607,6 +607,7 @@ mostlyclean-compile: distclean-compile: -rm -f *.tab.c +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libsframe_la-sframe-dump.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libsframe_la-sframe-error.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libsframe_la-sframe.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@testsuite/libsframe.decode/$(DEPDIR)/testsuite_libsframe_decode_be_flipping-be-flipping.Po@am__quote@ @@ -645,6 +646,13 @@ libsframe_la-sframe.lo: sframe.c @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libsframe_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libsframe_la-sframe.lo `test -f 'sframe.c' || echo '$(srcdir)/'`sframe.c +libsframe_la-sframe-dump.lo: sframe-dump.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libsframe_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libsframe_la-sframe-dump.lo -MD -MP -MF $(DEPDIR)/libsframe_la-sframe-dump.Tpo -c -o libsframe_la-sframe-dump.lo `test -f 'sframe-dump.c' || echo '$(srcdir)/'`sframe-dump.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libsframe_la-sframe-dump.Tpo $(DEPDIR)/libsframe_la-sframe-dump.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='sframe-dump.c' object='libsframe_la-sframe-dump.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libsframe_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libsframe_la-sframe-dump.lo `test -f 'sframe-dump.c' || echo '$(srcdir)/'`sframe-dump.c + libsframe_la-sframe-error.lo: sframe-error.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libsframe_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libsframe_la-sframe-error.lo -MD -MP -MF $(DEPDIR)/libsframe_la-sframe-error.Tpo -c -o libsframe_la-sframe-error.lo `test -f 'sframe-error.c' || echo '$(srcdir)/'`sframe-error.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libsframe_la-sframe-error.Tpo $(DEPDIR)/libsframe_la-sframe-error.Plo diff --git a/libsframe/sframe-dump.c b/libsframe/sframe-dump.c new file mode 100644 index 0000000..5b063c9 --- /dev/null +++ b/libsframe/sframe-dump.c @@ -0,0 +1,181 @@ +/* sframe-dump.c - Textual dump of .sframe. + + Copyright (C) 2022 Free Software Foundation, Inc. + + his file is part of libsframe. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . */ + +#include +#include +#include +#include +#include "sframe-impl.h" + +#define SFRAME_HEADER_FLAGS_STR_MAX_LEN 50 + +static void +dump_sframe_header (sframe_decoder_ctx *sfd_ctx) +{ + const char *verstr = NULL; + const sframe_header *header = &(sfd_ctx->sfd_header); + + /* Prepare SFrame section version string. */ + const char *version_names[] + = { "NULL", + "SFRAME_VERSION_1" }; + unsigned char ver = header->sfh_preamble.sfp_version; + if (ver <= SFRAME_VERSION) + verstr = version_names[ver]; + + /* Prepare SFrame section flags string. */ + unsigned char flags = header->sfh_preamble.sfp_flags; + char *flags_str + = (char*) calloc (sizeof (char), SFRAME_HEADER_FLAGS_STR_MAX_LEN); + if (flags) + { + const char *flag_names[] + = { "SFRAME_F_FDE_SORTED", + "SFRAME_F_FRAME_POINTER" }; + unsigned char flags = header->sfh_preamble.sfp_flags; + if (flags & SFRAME_F_FDE_SORTED) + strcpy (flags_str, flag_names[0]); + if (flags & SFRAME_F_FRAME_POINTER) + { + if (strlen (flags_str) > 0) + strcpy (flags_str, ","); + strcpy (flags_str, flag_names[1]); + } + } + else + strcpy (flags_str, "NONE"); + + const char* subsec_name = "Header"; + printf ("\n"); + printf (" %s :\n", subsec_name); + printf ("\n"); + printf (" Version: %s\n", verstr); + printf (" Flags: %s\n", flags_str); + printf (" Num FDEs: %d\n", header->sfh_num_fdes); + printf (" Num FREs: %d\n", header->sfh_num_fres); + + free (flags_str); +} + +static void +dump_sframe_func_with_fres (sframe_decoder_ctx *sfd_ctx, + unsigned int funcidx, + uint64_t sec_addr) +{ + uint32_t j = 0; + uint32_t num_fres = 0; + uint32_t func_size = 0; + int32_t func_start_address = 0; + unsigned char func_info = 0; + + uint64_t func_start_pc_vma = 0; + uint64_t fre_start_pc_vma = 0; + const char *base_reg_str[] = {"fp", "sp"}; + int32_t cfa_offset = 0; + int32_t fp_offset = 0; + int32_t ra_offset = 0; + unsigned int base_reg_id = 0; + int err[3] = {0, 0, 0}; + + sframe_frame_row_entry fre; + + /* Get the SFrame function descriptor. */ + sframe_decoder_get_funcdesc (sfd_ctx, funcidx, &num_fres, + &func_size, &func_start_address, &func_info); + /* Calculate the virtual memory address for function start pc. */ + func_start_pc_vma = func_start_address + sec_addr; + + /* Mark FDEs with [m] where the FRE start address is interpreted as a + mask. */ + int fde_type_addrmask_p = (SFRAME_V1_FUNC_FDE_TYPE (func_info) + == SFRAME_FDE_TYPE_PCMASK); + const char *fde_type_marker + = (fde_type_addrmask_p ? "[m]" : " "); + + printf ("\n func idx [%d]: pc = 0x%"PRIx64 ", size = %d bytes", + funcidx, + func_start_pc_vma, + func_size); + + char temp[100]; + memset (temp, 0, 100); + + printf ("\n %-7s%-8s %-10s%-10s%-10s", "STARTPC", fde_type_marker, "CFA", "FP", "RA"); + for (j = 0; j < num_fres; j++) + { + sframe_decoder_get_fre (sfd_ctx, funcidx, j, &fre); + + fre_start_pc_vma = (fde_type_addrmask_p + ? fre.fre_start_addr + : func_start_pc_vma + fre.fre_start_addr); + + /* FIXME - fixup the err caching in array. + assert no error for base reg id. */ + base_reg_id = sframe_fre_get_base_reg_id (&fre, &err[0]); + cfa_offset = sframe_fre_get_cfa_offset (sfd_ctx, &fre, &err[0]); + fp_offset = sframe_fre_get_fp_offset (sfd_ctx, &fre, &err[1]); + ra_offset = sframe_fre_get_ra_offset (sfd_ctx, &fre, &err[2]); + + /* Dump CFA info. */ + printf ("\n"); + printf (" %016"PRIx64, fre_start_pc_vma); + sprintf (temp, "%s+%d", base_reg_str[base_reg_id], cfa_offset); + printf (" %-10s", temp); + + /* Dump SP/FP info. */ + memset (temp, 0, 100); + if (err[1] == 0) + sprintf (temp, "c%+d", fp_offset); + else + strcpy (temp, "u"); + printf ("%-10s", temp); + + /* Dump RA info. */ + memset (temp, 0, 100); + if (err[2] == 0) + sprintf (temp, "c%+d", ra_offset); + else + strcpy (temp, "u"); + printf ("%-10s", temp); + } +} + +static void +dump_sframe_functions (sframe_decoder_ctx *sfd_ctx, uint64_t sec_addr) +{ + uint32_t i; + uint32_t num_fdes; + + const char* subsec_name = "Function Index"; + printf ("\n %s :\n", subsec_name); + + num_fdes = sframe_decoder_get_num_fidx (sfd_ctx); + for (i = 0; i < num_fdes; i++) + { + dump_sframe_func_with_fres (sfd_ctx, i, sec_addr); + printf ("\n"); + } +} + +void +dump_sframe (sframe_decoder_ctx *sfd_ctx, uint64_t sec_addr) +{ + dump_sframe_header (sfd_ctx); + dump_sframe_functions (sfd_ctx, sec_addr); +} -- cgit v1.1