public inbox for binutils@sourceware.org
 help / color / mirror / Atom feed
From: Palmer Dabbelt <palmer@dabbelt.com>
To: nelson.chu@sifive.com
Cc: binutils@sourceware.org, gdb-patches@sourceware.org,
	Jim Wilson <jimw@sifive.com>,
	andrew.burgess@embecosm.com, kito.cheng@sifive.com,
	 Andrew Waterman <andrew@sifive.com>,
	nelson.chu@sifive.com
Subject: Re: [PATCH v2 2/3] RISC-V: PR27916, Support mapping symbols.
Date: Thu, 15 Jul 2021 08:16:53 -0700 (PDT)	[thread overview]
Message-ID: <mhng-25bd6f14-4df8-4298-965d-d87d67f97995@palmerdabbelt-glaptop> (raw)
In-Reply-To: <20210709072825.13709-3-nelson.chu@sifive.com>

On Fri, 09 Jul 2021 00:28:24 PDT (-0700), nelson.chu@sifive.com wrote:
> Similar to ARM/AARCH64, we add mapping symbols in the symbol table,
> to mark the start addresses of data and instructions.  The $d means
> data, the $x means instruction, and the $a means code alignment.
> Then the disassembler uses these symbols to decide whether we should
> dump data or instruction.
>
> For example,
> $ cat tmp.s
>   .text
>   .option norelax
>   .option norvc
>   .fill 2, 4, 0x1001    # $d for 8 bytes fill data.
>   .byte 1               # $d1
>   .word 0               # $d4
>   .align 3              # $a1 for align.byte, $a for align.nop.
>   nop                   # $x
>   .fill 5, 2, 0x2002    # $d for 10 bytes fill data.
>   nop                   # $x
>   .data
>   .word 0x1             # No need to add mapping symbols.
>   .word 0x2
>
> $ riscv64-unknown-elf-as tmp.s -o tmp.o
> $ riscv64-unknown-elf-objdump -D tmp.o
>
> Disassembly of section .text:
>
> 0000000000000000 <.text>:
>    0:   00001001                .word   0x00001001
>    4:   00001001                .word   0x00001001
>    8:   01                      .byte   0x01
>    9:   00000000                .word   0x00000000
>    d:   00                      align.byte
>    e:   0001                    align.nop
>   10:   00000013                nop
>   14:   10001000                .word   0x20022002
>   18:   10001000                .word   0x20022002
>   1c:   1000                    .short  0x2002
>   1e:   00000013                nop
>   22:   0001                    align.nop
>   24:   00000013                align.nop
>
> Disassembly of section .data:
>
> 0000000000000000 <.data>:
>    0:   00000001                .word   0x00000001
>    4:   00000002                .word   0x00000002
>
> Disassembly of section .riscv.attributes:
>
> 0000000000000000 <.riscv.attributes>:
>    0:   00002d41                .word   0x00002d41
> ... skip ...
>
> There are too many issues we can discuss from the above example,
> so I just pick some of them that I think are important to mention.
>
> * The documentation for -D says that on ARM platforms -D should
>   disassemble instructions.  Therefore, they dump data by searching
>   mapping symbols only when the DISASSEMBLE_DATA is set.  That causes
>   the mapping symbols are useless for -D.  I am not sure if any riscv
>   document had mentioned this, so I prefer to keep them useful, but
>   only for text sections.  Otherwise, dump other sections as datas.
>
> * If the data are written by cons_worker, then we add mapping symbols
>   with the data size, to show more detials.  For example,
>
>   .text
>   .byte 1
>   .word 0
>
>   The $d1 is added for .byte, and $d4 is added for .word, so that
>   we can show the code that is closer to the user's original code,
>   rather than the data with 5 bytes size.
>
> * Add the align.<insn> prefix if the instructions are used for
>   alignment and marked with $a/$a1.  One of the benefits is that,
>   we can distinguish c.nop and align.nop, when the rvc is disabled.
>   The c.nop is illegal, but the align.nop is legal.
>
>   Besides, we may dump .align.unimp at the end of sections when relax
>   is enabled, this is expected.  Since the tail section alignments are
>   not handled in the riscv_frag_align_code, and it cannot be filled with
>   nops in the riscv_handle_align either.
>
> The elf/linux toolchain regressions all passed.  Besides, I also
> disable the mapping symbols internally, but use the new objudmp, the
> regressions passed, too.  Therefore, the new objudmp should dump
> the objects corretly, even if they don't have any mapping symbols.
>
> ChangeLog:
>
> bfd/
>
> 	pr 27916
> 	* cpu-riscv.c (riscv_elf_is_mapping_symbols): Define mapping symbols.
> 	* cpu-riscv.h: extern riscv_elf_is_mapping_symbols.
> 	* elfnn-riscv.c (riscv_maybe_function_sym): Do not choose mapping
> 	symbols as a function name.
> 	(riscv_elf_is_target_special_symbol): Add mapping symbols.
>
> binutils/
>
> 	pr 27916
> 	* readelf (get_symbol_for_build_attribute): Filter data mapping
> 	symbols with size.
> 	* testsuite/binutils-all/readelf.s: Updated.
> 	* testsuite/binutils-all/readelf.s-64: Likewise.
> 	* testsuite/binutils-all/readelf.s-64-unused: Likewise.
> 	* testsuite/binutils-all/readelf.ss: Likewise.
> 	* testsuite/binutils-all/readelf.ss-64: Likewise.
> 	* testsuite/binutils-all/readelf.ss-64-unused: Likewise.
>
> gas/
>
> 	pr 27916
> 	config/tc-riscv.c (make_mapping_symbol): Create a new mapping symbol.
> 	(riscv_mapping_state): Decide whether to create mapping symbol for
> 	frag_now.  Only add the mapping symbols to text sections.
> 	(riscv_add_odd_padding_symbol): Add the odd bytes of paddings for
> 	riscv_handle_align.
> 	(riscv_check_mapping_symbols): Remove any excess mapping symbols.
> 	(md_assemble): Marked as MAP_INSN.
> 	(riscv_frag_align_code): Marked as MAP_ALIGN.
> 	(riscv_init_frag): Add mapping symbols for frag, it usually called
> 	by frag_var.  Marked as MAP_DATA for rs_align and rs_fill, and
> 	marked as alignment MAP_ALIGN for rs_align_code.
> 	(s_riscv_insn): Marked as MAP_INSN.
> 	(riscv_adjust_symtab): Call riscv_check_mapping_symbols.
> 	* config/tc-riscv.h (md_cons_align): Defined to riscv_mapping_state
> 	with MAP_DATA_CONS[0|1|2|3].
> 	(TC_SEGMENT_INFO_TYPE): Record mapping state for each segment.
> 	(TC_FRAG_TYPE): Record the first and last mapping symbols for the
> 	fragments.  The first mapping symbol must be placed at the start
> 	of the fragment.
> 	(TC_FRAG_INIT): Defined to riscv_init_frag.
> 	* testsuite/gas/riscv/mapping-01.s: New testcase.
> 	* testsuite/gas/riscv/mapping-01a.d: Likewise.
> 	* testsuite/gas/riscv/mapping-01b.d: Likewise.
> 	* testsuite/gas/riscv/mapping-02.s: Likewise.
> 	* testsuite/gas/riscv/mapping-02a.d: Likewise.
> 	* testsuite/gas/riscv/mapping-02b.d: Likewise.
> 	* testsuite/gas/riscv/mapping-03.s: Likewise.
> 	* testsuite/gas/riscv/mapping-03a.d: Likewise.
> 	* testsuite/gas/riscv/mapping-03b.d: Likewise.
> 	* testsuite/gas/riscv/mapping-04.s: Likewise.
> 	* testsuite/gas/riscv/mapping-04a.d: Likewise.
> 	* testsuite/gas/riscv/mapping-04b.d: Likewise.
> 	* testsuite/gas/riscv/mapping-norelax-04a.d: Likewise.
> 	* testsuite/gas/riscv/mapping-norelax-04b.d: Likewise.
> 	* testsuite/gas/riscv/no-relax-align.d: Updated.
> 	* testsuite/gas/riscv/no-relax-align-2.d: Likewise.
>
> include/
>
> 	pr 27916
> 	* opcode/riscv.h (enum riscv_seg_mstate): Added.
>
> opcodes/
>
> 	pr 27916
> 	* riscv-dis.c (last_map_symbol, last_stop_offset, last_section,
> 	last_map_state): Added to dump sections with mapping symbols.
> 	(riscv_get_map_state): Get the mapping state from the symbol.
> 	(riscv_search_mapping_symbol): Check the sorted symbol table, and
> 	then find the suitable mapping symbol.
> 	(riscv_data_length): Decide which data size we should print.
> 	(riscv_disassemble_data): Dump the data contents.
> 	(riscv_disassemble_insn): Dump align.<insn> for MAP_ALIGN.
> 	(print_insn_riscv): Handle the mapping symbols.
> 	(riscv_symbol_is_valid): Marked mapping symbols as invalid.
> ---
>  bfd/cpu-riscv.c                               |  10 +
>  bfd/cpu-riscv.h                               |   3 +
>  bfd/elfnn-riscv.c                             |  25 +-
>  binutils/readelf.c                            |   8 +-
>  binutils/testsuite/binutils-all/readelf.s-64  |   5 +-
>  .../binutils-all/readelf.s-64-unused          |   5 +-
>  binutils/testsuite/binutils-all/readelf.ss    |   2 +
>  binutils/testsuite/binutils-all/readelf.ss-64 |   7 +-
>  .../binutils-all/readelf.ss-64-unused         |   7 +-
>  .../testsuite/binutils-all/readelf.ss-unused  |   2 +
>  gas/config/tc-riscv.c                         | 223 ++++++++++++-
>  gas/config/tc-riscv.h                         |  32 ++
>  gas/testsuite/gas/riscv/mapping-01.s          |  18 +
>  gas/testsuite/gas/riscv/mapping-01a.d         |  17 +
>  gas/testsuite/gas/riscv/mapping-01b.d         |  21 ++
>  gas/testsuite/gas/riscv/mapping-02.s          |  13 +
>  gas/testsuite/gas/riscv/mapping-02a.d         |  15 +
>  gas/testsuite/gas/riscv/mapping-02b.d         |  16 +
>  gas/testsuite/gas/riscv/mapping-03.s          |  10 +
>  gas/testsuite/gas/riscv/mapping-03a.d         |  16 +
>  gas/testsuite/gas/riscv/mapping-03b.d         |  16 +
>  gas/testsuite/gas/riscv/mapping-04.s          |  11 +
>  gas/testsuite/gas/riscv/mapping-04a.d         |  21 ++
>  gas/testsuite/gas/riscv/mapping-04b.d         |  24 ++
>  gas/testsuite/gas/riscv/mapping-norelax-04a.d |  23 ++
>  gas/testsuite/gas/riscv/mapping-norelax-04b.d |  25 ++
>  gas/testsuite/gas/riscv/no-relax-align-2.d    |  19 +-
>  gas/testsuite/gas/riscv/no-relax-align.d      |   4 +-
>  include/opcode/riscv.h                        |  13 +
>  opcodes/riscv-dis.c                           | 313 +++++++++++++++++-
>  30 files changed, 885 insertions(+), 39 deletions(-)
>  create mode 100644 gas/testsuite/gas/riscv/mapping-01.s
>  create mode 100644 gas/testsuite/gas/riscv/mapping-01a.d
>  create mode 100644 gas/testsuite/gas/riscv/mapping-01b.d
>  create mode 100644 gas/testsuite/gas/riscv/mapping-02.s
>  create mode 100644 gas/testsuite/gas/riscv/mapping-02a.d
>  create mode 100644 gas/testsuite/gas/riscv/mapping-02b.d
>  create mode 100644 gas/testsuite/gas/riscv/mapping-03.s
>  create mode 100644 gas/testsuite/gas/riscv/mapping-03a.d
>  create mode 100644 gas/testsuite/gas/riscv/mapping-03b.d
>  create mode 100644 gas/testsuite/gas/riscv/mapping-04.s
>  create mode 100644 gas/testsuite/gas/riscv/mapping-04a.d
>  create mode 100644 gas/testsuite/gas/riscv/mapping-04b.d
>  create mode 100644 gas/testsuite/gas/riscv/mapping-norelax-04a.d
>  create mode 100644 gas/testsuite/gas/riscv/mapping-norelax-04b.d
>
> diff --git a/bfd/cpu-riscv.c b/bfd/cpu-riscv.c
> index 025e94afd34..dae76e7fdcc 100644
> --- a/bfd/cpu-riscv.c
> +++ b/bfd/cpu-riscv.c
> @@ -140,3 +140,13 @@ riscv_get_priv_spec_class_from_numbers (unsigned int major,
>    RISCV_GET_PRIV_SPEC_CLASS (buf, class_t);
>    *class = class_t;
>  }
> +
> +/* Define mapping symbols for riscv.  */
> +
> +bool
> +riscv_elf_is_mapping_symbols (const char *name)
> +{
> +  return (!strncmp (name, "$d", 2)
> +	  || !strncmp (name, "$x", 2)
> +	  || !strncmp (name, "$a", 2));
> +}

I can't quite figure this one out: this will treat something like 
"$aWHATEVER" as a mapping symbol, does that cause binutils to crash 
somewhere?  All I'm seeing it do is mark these as hidden symbols, which 
I guess is OK (we've kind of set the "anything with $ is inernal 
precedent").

Either way,

Reviewed-by: Palmer Dabbelt <palmerdabbelt@google.com>

> diff --git a/bfd/cpu-riscv.h b/bfd/cpu-riscv.h
> index cafaca23be0..ed5ee7e60d5 100644
> --- a/bfd/cpu-riscv.h
> +++ b/bfd/cpu-riscv.h
> @@ -79,3 +79,6 @@ riscv_get_priv_spec_class_from_numbers (unsigned int,
>  					unsigned int,
>  					unsigned int,
>  					enum riscv_spec_class *);
> +
> +extern bool
> +riscv_elf_is_mapping_symbols (const char *);
> diff --git a/bfd/elfnn-riscv.c b/bfd/elfnn-riscv.c
> index 85a99f3d610..a10384cd4d3 100644
> --- a/bfd/elfnn-riscv.c
> +++ b/bfd/elfnn-riscv.c
> @@ -5150,14 +5150,32 @@ riscv_elf_obj_attrs_arg_type (int tag)
>    return (tag & 1) != 0 ? ATTR_TYPE_FLAG_STR_VAL : ATTR_TYPE_FLAG_INT_VAL;
>  }
>
> -/* PR27584, Omit local and empty symbols since they usually generated
> -   for pcrel relocations.  */
> +/* Do not choose mapping symbols as a function name.  */
> +
> +static bfd_size_type
> +riscv_maybe_function_sym (const asymbol *sym,
> +			  asection *sec,
> +			  bfd_vma *code_off)
> +{
> +  if (sym->flags & BSF_LOCAL
> +      && riscv_elf_is_mapping_symbols (sym->name))
> +    return 0;
> +
> +  return _bfd_elf_maybe_function_sym (sym, sec, code_off);
> +}
> +
> +/* Treat the following cases as target special symbols, they are
> +   usually omitted.  */
>
>  static bool
>  riscv_elf_is_target_special_symbol (bfd *abfd, asymbol *sym)
>  {
> +  /* PR27584, local and empty symbols.  Since they are usually
> +     generated for pcrel relocations.  */
>    return (!strcmp (sym->name, "")
> -	  || _bfd_elf_is_local_label_name (abfd, sym->name));
> +	  || _bfd_elf_is_local_label_name (abfd, sym->name)
> +	  /* PR27916, mapping symbols.  */
> +	  || riscv_elf_is_mapping_symbols (sym->name));
>  }
>
>  static int
> @@ -5245,6 +5263,7 @@ riscv_elf_modify_segment_map (bfd *abfd,
>  #define elf_backend_grok_psinfo			riscv_elf_grok_psinfo
>  #define elf_backend_object_p			riscv_elf_object_p
>  #define elf_backend_write_core_note		riscv_write_core_note
> +#define elf_backend_maybe_function_sym		riscv_maybe_function_sym
>  #define elf_info_to_howto_rel			NULL
>  #define elf_info_to_howto			riscv_info_to_howto_rela
>  #define bfd_elfNN_bfd_relax_section		_bfd_riscv_relax_section
> diff --git a/binutils/readelf.c b/binutils/readelf.c
> index 24ff069edf4..7560e0f6a51 100644
> --- a/binutils/readelf.c
> +++ b/binutils/readelf.c
> @@ -20283,10 +20283,14 @@ get_symbol_for_build_attribute (Filedata *filedata,
>  	  continue;
>
>  	/* The AArch64 and ARM architectures define mapping symbols
> -	   (eg $d, $x, $t) which we want to ignore.  */
> +	   (eg $d, $x, $t) which we want to ignore.  Besides, riscv
> +	   may defines data mapping symbols with size (eg $d1, $d2,
> +	   $d4, $d8), which we also want to ignore.  */
>  	if (ba_cache.strtab[sym->st_name] == '$'
>  	    && ba_cache.strtab[sym->st_name + 1] != 0
> -	    && ba_cache.strtab[sym->st_name + 2] == 0)
> +	    && (ba_cache.strtab[sym->st_name + 2] == 0
> +		|| (ba_cache.strtab[sym->st_name + 2] != 0
> +		    && ba_cache.strtab[sym->st_name + 3] == 0)))
>  	  continue;
>
>  	if (is_open_attr)
> diff --git a/binutils/testsuite/binutils-all/readelf.s-64 b/binutils/testsuite/binutils-all/readelf.s-64
> index 4c957f7a938..0b1bafee537 100644
> --- a/binutils/testsuite/binutils-all/readelf.s-64
> +++ b/binutils/testsuite/binutils-all/readelf.s-64
> @@ -19,8 +19,9 @@ Section Headers:
>   +\[ .\] .symtab +SYMTAB +0000000000000000 +0+.*
>  # aarch64-elf targets have one more data symbol.
>  # x86 targets may have .note.gnu.property.
> -# riscv targets have .riscv.attributes.
> - +0+.* +0000000000000018 +(6|7) +(3|4) +8
> +# riscv targets have five more symbols, one is .riscv.attributes,
> +# others are mapping data symbols.
> + +0+.* +0000000000000018 +(6|7) +(3|4|8) +8
>   +\[ .\] .strtab +STRTAB +0000000000000000 +0+.*
>   +0+.* +0000000000000000 .* +0 +0 +1
>   +\[ .\] .shstrtab +STRTAB +0000000000000000 +[0-9a-f]+
> diff --git a/binutils/testsuite/binutils-all/readelf.s-64-unused b/binutils/testsuite/binutils-all/readelf.s-64-unused
> index 771439411a0..542bbb70064 100644
> --- a/binutils/testsuite/binutils-all/readelf.s-64-unused
> +++ b/binutils/testsuite/binutils-all/readelf.s-64-unused
> @@ -19,8 +19,9 @@ Section Headers:
>   +\[ .\] .symtab +SYMTAB +0000000000000000 +0+.*
>  # aarch64-elf targets have one more data symbol.
>  # x86 targets may have .note.gnu.property.
> -# riscv targets have .riscv.attributes.
> - +0+.* +0000000000000018 +(6|7) +(6|7) +8
> +# riscv targets have five more symbols, one is .riscv.attributes,
> +# others are mapping data symbols.
> + +0+.* +0000000000000018 +(6|7) +(6|7|11) +8
>   +\[ .\] .strtab +STRTAB +0000000000000000 +0+.*
>   +0+.* +0000000000000000 .* +0 +0 +1
>   +\[ .\] .shstrtab +STRTAB +0000000000000000 +[0-9a-f]+
> diff --git a/binutils/testsuite/binutils-all/readelf.ss b/binutils/testsuite/binutils-all/readelf.ss
> index b81c016e9e7..5d96649c2a0 100644
> --- a/binutils/testsuite/binutils-all/readelf.ss
> +++ b/binutils/testsuite/binutils-all/readelf.ss
> @@ -5,8 +5,10 @@ Symbol table '.symtab' contains .* entries:
>   +1: 00000000 +0 +NOTYPE +LOCAL +DEFAULT +1 static_text_symbol
>  # ARM targets add the $d mapping symbol here...
>  # NDS32 targets add the $d2 mapping symbol here...
> +# riscv targets add the $d4 mapping symbols here...
>  #...
>   +.: 00000000 +0 +NOTYPE +LOCAL +DEFAULT +[34] static_data_symbol
> +# ... or here ...
>  # v850 targets include extra SECTION symbols here for the .call_table_data
>  # and .call_table_text sections.
>  # riscv targets add .riscv.attribute symbol here...
> diff --git a/binutils/testsuite/binutils-all/readelf.ss-64 b/binutils/testsuite/binutils-all/readelf.ss-64
> index c6ffb0fc523..105f1b88361 100644
> --- a/binutils/testsuite/binutils-all/readelf.ss-64
> +++ b/binutils/testsuite/binutils-all/readelf.ss-64
> @@ -4,13 +4,14 @@ Symbol table '.symtab' contains .* entries:
>   +0: 0000000000000000 +0 +NOTYPE +LOCAL +DEFAULT +UND
>   +1: 0000000000000000 +0 +NOTYPE +LOCAL +DEFAULT +1 static_text_symbol
>  # aarch64-elf targets add the $d mapping symbol here...
> +# riscv targets add the $d4 mapping symbols here...
>  #...
>   +.: 0000000000000000 +0 +NOTYPE +LOCAL +DEFAULT +3 static_data_symbol
>  # ... or here ...
>  # riscv targets add .riscv.attribute symbol here...
>  #...
> -.* +.: 0000000000000000 +0 +NOTYPE +GLOBAL +DEFAULT +1 text_symbol
> - +.: 0000000000000000 +0 +NOTYPE +GLOBAL +DEFAULT +UND external_symbol
> - +.: 0000000000000000 +0 +NOTYPE +GLOBAL +DEFAULT +3 data_symbol
> +.* +[0-9]+: 0000000000000000 +0 +NOTYPE +GLOBAL +DEFAULT +1 text_symbol
> + +[0-9]+: 0000000000000000 +0 +NOTYPE +GLOBAL +DEFAULT +UND external_symbol
> + +[0-9]+: 0000000000000000 +0 +NOTYPE +GLOBAL +DEFAULT +3 data_symbol
>   +[0-9]+: 0000000000000004 +4 +(COMMON|OBJECT) +GLOBAL +DEFAULT +COM common_symbol
>  #pass
> diff --git a/binutils/testsuite/binutils-all/readelf.ss-64-unused b/binutils/testsuite/binutils-all/readelf.ss-64-unused
> index cf515aa60d0..50fca025b31 100644
> --- a/binutils/testsuite/binutils-all/readelf.ss-64-unused
> +++ b/binutils/testsuite/binutils-all/readelf.ss-64-unused
> @@ -7,13 +7,14 @@ Symbol table '.symtab' contains .* entries:
>   +3: 0000000000000000 +0 +SECTION +LOCAL +DEFAULT +4.*
>   +4: 0000000000000000 +0 +NOTYPE +LOCAL +DEFAULT +1 static_text_symbol
>  # aarch64-elf targets add the $d mapping symbol here...
> +# riscv targets add the $d4 mapping symbols here...
>  #...
>   +.: 0000000000000000 +0 +NOTYPE +LOCAL +DEFAULT +3 static_data_symbol
>  # ... or here ...
>  # riscv targets add .riscv.attribute symbol here...
>  #...
> -.* +.: 0000000000000000 +0 +NOTYPE +GLOBAL +DEFAULT +1 text_symbol
> - +.: 0000000000000000 +0 +NOTYPE +GLOBAL +DEFAULT +UND external_symbol
> - +.: 0000000000000000 +0 +NOTYPE +GLOBAL +DEFAULT +3 data_symbol
> +.* +[0-9]+: 0000000000000000 +0 +NOTYPE +GLOBAL +DEFAULT +1 text_symbol
> + +[0-9]+: 0000000000000000 +0 +NOTYPE +GLOBAL +DEFAULT +UND external_symbol
> + +[0-9]+: 0000000000000000 +0 +NOTYPE +GLOBAL +DEFAULT +3 data_symbol
>   +[0-9]+: 0000000000000004 +4 +(COMMON|OBJECT) +GLOBAL +DEFAULT +COM common_symbol
>  #pass
> diff --git a/binutils/testsuite/binutils-all/readelf.ss-unused b/binutils/testsuite/binutils-all/readelf.ss-unused
> index 3107af930eb..944ab45cc46 100644
> --- a/binutils/testsuite/binutils-all/readelf.ss-unused
> +++ b/binutils/testsuite/binutils-all/readelf.ss-unused
> @@ -8,8 +8,10 @@ Symbol table '.symtab' contains .* entries:
>   +4: 00000000 +0 +NOTYPE +LOCAL +DEFAULT +1 static_text_symbol
>  # ARM targets add the $d mapping symbol here...
>  # NDS32 targets add the $d2 mapping symbol here...
> +# riscv targets add the $d4 mapping symbols here...
>  #...
>   +.: 00000000 +0 +NOTYPE +LOCAL +DEFAULT +[34] static_data_symbol
> +# ... or here ...
>  # v850 targets include extra SECTION symbols here for the .call_table_data
>  # and .call_table_text sections.
>  #...
> diff --git a/gas/config/tc-riscv.c b/gas/config/tc-riscv.c
> index df37579c843..55c49471825 100644
> --- a/gas/config/tc-riscv.c
> +++ b/gas/config/tc-riscv.c
> @@ -561,6 +561,179 @@ static bool explicit_priv_attr = false;
>
>  static char *expr_end;
>
> +/* Create a new mapping symbol for the transition to STATE.  */
> +
> +static void
> +make_mapping_symbol (enum riscv_seg_mstate state,
> +		     valueT value,
> +		     fragS *frag)
> +{
> +  const char *name;
> +  switch (state)
> +    {
> +    case MAP_DATA:
> +      name = "$d";
> +      break;
> +    case MAP_DATA_CONS0:
> +      name = "$d1";
> +      break;
> +    case MAP_DATA_CONS1:
> +      name = "$d2";
> +      break;
> +    case MAP_DATA_CONS2:
> +      name = "$d4";
> +      break;
> +    case MAP_DATA_CONS3:
> +      name = "$d8";
> +      break;
> +    case MAP_INSN:
> +      name = "$x";
> +      break;
> +    case MAP_ALIGN:
> +      name = "$a";
> +      break;
> +    case MAP_ALIGN_ODD:
> +      name = "$a1";
> +      break;
> +    default:
> +      abort ();
> +    }
> +
> +  symbolS *symbol = symbol_new (name, now_seg, frag, value);
> +  symbol_get_bfdsym (symbol)->flags |= (BSF_NO_FLAGS | BSF_LOCAL);
> +
> +  /* If .fill or other data filling directive generates zero sized data,
> +     or we are adding odd alignemnts, then the mapping symbol for the
> +     following code will have the same value.  */
> +  if (value == 0)
> +    {
> +       if (frag->tc_frag_data.first_map_symbol != NULL)
> +	{
> +	  know (S_GET_VALUE (frag->tc_frag_data.first_map_symbol)
> +		== S_GET_VALUE (symbol));
> +	  /* Remove the old one.  */
> +	  symbol_remove (frag->tc_frag_data.first_map_symbol,
> +			 &symbol_rootP, &symbol_lastP);
> +	}
> +      frag->tc_frag_data.first_map_symbol = symbol;
> +    }
> +  if (frag->tc_frag_data.last_map_symbol != NULL)
> +    {
> +      /* The mapping symbols should be added in offset order.  */
> +      know (S_GET_VALUE (frag->tc_frag_data.last_map_symbol)
> +			 <= S_GET_VALUE (symbol));
> +      /* Remove the old one.  */
> +      if (S_GET_VALUE (frag->tc_frag_data.last_map_symbol)
> +	  == S_GET_VALUE (symbol))
> +	symbol_remove (frag->tc_frag_data.last_map_symbol,
> +		       &symbol_rootP, &symbol_lastP);
> +    }
> +  frag->tc_frag_data.last_map_symbol = symbol;
> +}
> +
> +/* Set the mapping state for frag_now.  */
> +
> +void
> +riscv_mapping_state (enum riscv_seg_mstate to_state,
> +		     int max_chars)
> +{
> +  enum riscv_seg_mstate from_state =
> +	seg_info (now_seg)->tc_segment_info_data.map_state;
> +
> +  if (!SEG_NORMAL (now_seg)
> +      /* For now I only add the mapping symbols to text sections.
> +	 Therefore, the dis-assembler only show the actual contents
> +	 distribution for text.  Other sections will be shown as
> +	 data without the details.  */
> +      || !subseg_text_p (now_seg))
> +    return;
> +
> +  /* Keep inserting the MAP_DATA_CONS in text.  Otherwise, the mapping
> +     symbol should be emitted.  */
> +  if (from_state == to_state
> +      && from_state != MAP_DATA_CONS0
> +      && from_state != MAP_DATA_CONS1
> +      && from_state != MAP_DATA_CONS2
> +      && from_state != MAP_DATA_CONS3)
> +    return;
> +
> +  valueT value = (valueT) (frag_now_fix () - max_chars);
> +  seg_info (now_seg)->tc_segment_info_data.map_state = to_state;
> +  make_mapping_symbol (to_state, value, frag_now);
> +}
> +
> +/* Add the odd bytes of paddings for riscv_handle_align.  */
> +
> +static void
> +riscv_add_odd_padding_symbol (fragS *frag)
> +{
> +  /* If there was already a mapping symbol, it should be
> +     removed in the make_mapping_symbol.  */
> +  make_mapping_symbol (MAP_ALIGN_ODD, frag->fr_fix, frag);
> +  make_mapping_symbol (MAP_ALIGN, frag->fr_fix + 1, frag);
> +}
> +
> +/* Remove any excess mapping symbols generated for alignment frags in
> +   SEC.  We may have created a mapping symbol before a zero byte
> +   alignment; remove it if there's a mapping symbol after the
> +   alignment.  */
> +
> +static void
> +riscv_check_mapping_symbols (bfd *abfd ATTRIBUTE_UNUSED,
> +			     asection *sec,
> +			     void *dummy ATTRIBUTE_UNUSED)
> +{
> +  segment_info_type *seginfo = seg_info (sec);
> +  fragS *fragp;
> +
> +  if (seginfo == NULL || seginfo->frchainP == NULL)
> +    return;
> +
> +  for (fragp = seginfo->frchainP->frch_root;
> +       fragp != NULL;
> +       fragp = fragp->fr_next)
> +    {
> +      symbolS *last = fragp->tc_frag_data.last_map_symbol;
> +      fragS *next = fragp->fr_next;
> +
> +      if (last == NULL || next == NULL)
> +	continue;
> +
> +      /* Check the last mapping symbol if it is at the boundary of
> +	 fragmnet.  */
> +      if (S_GET_VALUE (last) < next->fr_address)
> +	continue;
> +      know (S_GET_VALUE (last) == next->fr_address);
> +
> +      do
> +	{
> +	  if (next->tc_frag_data.first_map_symbol != NULL)
> +	    {
> +	      /* The last mapping symbol overlaps with another one
> +		 which at the start of the next frag.  */
> +	      symbol_remove (last, &symbol_rootP, &symbol_lastP);
> +	      break;
> +	    }
> +
> +	  if (next->fr_next == NULL)
> +	    {
> +	      /* The last mapping symbol is at the end of the section.  */
> +	      know (next->fr_fix == 0 && next->fr_var == 0);
> +	      symbol_remove (last, &symbol_rootP, &symbol_lastP);
> +	      break;
> +	    }
> +
> +	  /* Since we may have empty frags without any mapping symbols,
> +	     keep looking until the non-empty frag.  */
> +	  if (next->fr_address != next->fr_next->fr_address)
> +	    break;
> +
> +	  next = next->fr_next;
> +	}
> +      while (next != NULL);
> +    }
> +}
> +
>  /* The default target format to use.  */
>
>  const char *
> @@ -2767,6 +2940,8 @@ md_assemble (char *str)
>         return;
>      }
>
> +  riscv_mapping_state (MAP_INSN, 0);
> +
>    const char *error = riscv_ip (str, &insn, &imm_expr, &imm_reloc, op_hash);
>
>    if (error)
> @@ -3422,6 +3597,8 @@ riscv_frag_align_code (int n)
>    fix_new_exp (frag_now, nops - frag_now->fr_literal, 0,
>  	       &ex, false, BFD_RELOC_RISCV_ALIGN);
>
> +  riscv_mapping_state (MAP_ALIGN, worst_case_bytes);
> +
>    return true;
>  }
>
> @@ -3441,6 +3618,7 @@ riscv_handle_align (fragS *fragP)
>  	  /* We have 4 byte uncompressed nops.  */
>  	  bfd_signed_vma size = 4;
>  	  bfd_signed_vma excess = bytes % size;
> +	  bfd_boolean odd_padding = (excess % 2 == 1);
>  	  char *p = fragP->fr_literal + fragP->fr_fix;
>
>  	  if (bytes <= 0)
> @@ -3449,12 +3627,20 @@ riscv_handle_align (fragS *fragP)
>  	  /* Insert zeros or compressed nops to get 4 byte alignment.  */
>  	  if (excess)
>  	    {
> +	      if (odd_padding)
> +		riscv_add_odd_padding_symbol (fragP);
>  	      riscv_make_nops (p, excess);
>  	      fragP->fr_fix += excess;
>  	      p += excess;
>  	    }
>
> -	  /* Insert variable number of 4 byte uncompressed nops.  */
> +	  /* The frag will be changed to `rs_fill` later.  The function
> +	     `write_contents` will try to fill the remaining spaces
> +	     according to the patterns we give.  In this case, we give
> +	     a 4 byte uncompressed nop as the pattern, and set the size
> +	     of the pattern into `fr_var`.  The nop will be output to the
> +	     file `fr_offset` times.  However, `fr_offset` could be zero
> +	     if we don't need to pad the boundary finally.  */
>  	  riscv_make_nops (p, size);
>  	  fragP->fr_var = size;
>  	}
> @@ -3465,6 +3651,30 @@ riscv_handle_align (fragS *fragP)
>      }
>  }
>
> +/* This usually called from frag_var.  */
> +
> +void
> +riscv_init_frag (fragS * fragP, int max_chars)
> +{
> +  /* Do not add mapping symbol to debug sections.  */
> +  if (bfd_section_flags (now_seg) & SEC_DEBUGGING)
> +    return;
> +
> +  switch (fragP->fr_type)
> +    {
> +    case rs_fill:
> +    case rs_align:
> +    case rs_align_test:
> +      riscv_mapping_state (MAP_DATA, max_chars);
> +      break;
> +    case rs_align_code:
> +      riscv_mapping_state (MAP_ALIGN, max_chars);
> +      break;
> +    default:
> +      break;
> +    }
> +}
> +
>  int
>  md_estimate_size_before_relax (fragS *fragp, asection *segtype)
>  {
> @@ -3721,6 +3931,8 @@ s_riscv_insn (int x ATTRIBUTE_UNUSED)
>    save_c = *input_line_pointer;
>    *input_line_pointer = '\0';
>
> +  riscv_mapping_state (MAP_INSN, 0);
> +
>    const char *error = riscv_ip (str, &insn, &imm_expr,
>  				&imm_reloc, insn_type_hash);
>
> @@ -3811,6 +4023,15 @@ riscv_md_end (void)
>    riscv_set_public_attributes ();
>  }
>
> +/* Adjust the symbol table.  */
> +
> +void
> +riscv_adjust_symtab (void)
> +{
> +  bfd_map_over_sections (stdoutput, riscv_check_mapping_symbols, (char *) 0);
> +  elf_adjust_symtab ();
> +}
> +
>  /* Given a symbolic attribute NAME, return the proper integer value.
>     Returns -1 if the attribute is not known.  */
>
> diff --git a/gas/config/tc-riscv.h b/gas/config/tc-riscv.h
> index 1de138458d8..1702b25bc51 100644
> --- a/gas/config/tc-riscv.h
> +++ b/gas/config/tc-riscv.h
> @@ -128,4 +128,36 @@ extern void riscv_elf_final_processing (void);
>  extern void riscv_md_end (void);
>  extern int riscv_convert_symbolic_attribute (const char *);
>
> +/* Set mapping symbol states.  */
> +#define md_cons_align(nbytes)					\
> +  switch (nbytes)						\
> +    {								\
> +    default: riscv_mapping_state (MAP_DATA, 0); break;		\
> +    case 1:  riscv_mapping_state (MAP_DATA_CONS0, 0); break;	\
> +    case 2:  riscv_mapping_state (MAP_DATA_CONS1, 0); break;	\
> +    case 4:  riscv_mapping_state (MAP_DATA_CONS2, 0); break;	\
> +    case 8:  riscv_mapping_state (MAP_DATA_CONS3, 0); break;	\
> +    }
> +void riscv_mapping_state (enum riscv_seg_mstate, int);
> +
> +/* Define target segment type.  */
> +#define TC_SEGMENT_INFO_TYPE struct riscv_segment_info_type
> +struct riscv_segment_info_type
> +{
> +  enum riscv_seg_mstate map_state;
> +};
> +
> +/* Define target fragment type.  */
> +#define TC_FRAG_TYPE struct riscv_frag_type
> +struct riscv_frag_type
> +{
> +  symbolS *first_map_symbol, *last_map_symbol;
> +};
> +
> +#define TC_FRAG_INIT(fragp, max_bytes) riscv_init_frag (fragp, max_bytes)
> +extern void riscv_init_frag (struct frag *, int);
> +
> +#define obj_adjust_symtab() riscv_adjust_symtab ()
> +extern void riscv_adjust_symtab (void);
> +
>  #endif /* TC_RISCV */
> diff --git a/gas/testsuite/gas/riscv/mapping-01.s b/gas/testsuite/gas/riscv/mapping-01.s
> new file mode 100644
> index 00000000000..0a270454b1b
> --- /dev/null
> +++ b/gas/testsuite/gas/riscv/mapping-01.s
> @@ -0,0 +1,18 @@
> +	.option norvc
> +	.text
> +	.global	funcA
> +funcA:
> +	nop
> +	j	funcB
> +
> +	.global	funcB
> +funcB:
> +	nop
> +	bne	a0, a1, funcB
> +
> +	.data
> +	.word 0x123456
> +
> +	.section	.foo, "ax"
> +foo:
> +	nop
> diff --git a/gas/testsuite/gas/riscv/mapping-01a.d b/gas/testsuite/gas/riscv/mapping-01a.d
> new file mode 100644
> index 00000000000..32e0027a13d
> --- /dev/null
> +++ b/gas/testsuite/gas/riscv/mapping-01a.d
> @@ -0,0 +1,17 @@
> +#as:
> +#source: mapping-01.s
> +#objdump: --syms --special-syms
> +
> +.*file format.*riscv.*
> +
> +SYMBOL TABLE:
> +0+00 l    d  .text	0+00 .text
> +0+00 l    d  .data	0+00 .data
> +0+00 l    d  .bss	0+00 .bss
> +0+00 l       .text	0+00 \$x
> +0+00 l    d  .foo	0+00 .foo
> +0+00 l       .foo	0+00 foo
> +0+00 l       .foo	0+00 \$x
> +0+00 l    d  .riscv.attributes	0+00 .riscv.attributes
> +0+00 g       .text	0+00 funcA
> +0+08 g       .text	0+00 funcB
> diff --git a/gas/testsuite/gas/riscv/mapping-01b.d b/gas/testsuite/gas/riscv/mapping-01b.d
> new file mode 100644
> index 00000000000..723bd5951cb
> --- /dev/null
> +++ b/gas/testsuite/gas/riscv/mapping-01b.d
> @@ -0,0 +1,21 @@
> +#as:
> +#source: mapping-01.s
> +#objdump: -d
> +
> +.*:[ 	]+file format .*
> +
> +
> +Disassembly of section .text:
> +
> +0+000 <funcA>:
> +[ 	]+0:[ 	]+00000013[ 	]+nop
> +[ 	]+4:[ 	]+0040006f[ 	]+j[ 	]+8 <funcB>
> +
> +0+008 <funcB>:
> +[ 	]+8:[ 	]+00000013[ 	]+nop
> +[ 	]+c:[ 	]+feb51ee3[ 	]+bne[ 	]+a0,a1,8 <funcB>
> +
> +Disassembly of section .foo:
> +
> +0+000 <foo>:
> +[ 	]+0:[ 	]+00000013[ 	]+nop
> diff --git a/gas/testsuite/gas/riscv/mapping-02.s b/gas/testsuite/gas/riscv/mapping-02.s
> new file mode 100644
> index 00000000000..d3de6dedac8
> --- /dev/null
> +++ b/gas/testsuite/gas/riscv/mapping-02.s
> @@ -0,0 +1,13 @@
> +	.option norvc
> +	.text
> +	.global main
> +	.type   main, %function
> +main:
> +	nop
> +foo:
> +	nop
> +	nop
> +	.size   main, .-main
> +	.ident  ""
> +
> +	nop
> diff --git a/gas/testsuite/gas/riscv/mapping-02a.d b/gas/testsuite/gas/riscv/mapping-02a.d
> new file mode 100644
> index 00000000000..d0cb460e08e
> --- /dev/null
> +++ b/gas/testsuite/gas/riscv/mapping-02a.d
> @@ -0,0 +1,15 @@
> +#as:
> +#source: mapping-02.s
> +#objdump: --syms --special-syms
> +
> +.*file format.*riscv.*
> +
> +SYMBOL TABLE:
> +0+00 l    d  .text	0+00 .text
> +0+00 l    d  .data	0+00 .data
> +0+00 l    d  .bss	0+00 .bss
> +0+00 l       .text	0+00 \$x
> +0+04 l       .text	0+00 foo
> +0+00 l    d  .comment	0+00 .comment
> +0+00 l    d  .riscv.attributes	0+00 .riscv.attributes
> +0+00 g     F .text	0+0c main
> diff --git a/gas/testsuite/gas/riscv/mapping-02b.d b/gas/testsuite/gas/riscv/mapping-02b.d
> new file mode 100644
> index 00000000000..3e875600a9c
> --- /dev/null
> +++ b/gas/testsuite/gas/riscv/mapping-02b.d
> @@ -0,0 +1,16 @@
> +#as:
> +#source: mapping-02.s
> +#objdump: -d
> +
> +.*:[ 	]+file format .*
> +
> +
> +Disassembly of section .text:
> +
> +0+000 <main>:
> +[ 	]+0:[ 	]+00000013[ 	]+nop
> +
> +0+004 <foo>:
> +[ 	]+4:[ 	]+00000013[ 	]+nop
> +[ 	]+8:[ 	]+00000013[ 	]+nop
> +[ 	]+c:[ 	]+00000013[ 	]+nop
> diff --git a/gas/testsuite/gas/riscv/mapping-03.s b/gas/testsuite/gas/riscv/mapping-03.s
> new file mode 100644
> index 00000000000..49964f20288
> --- /dev/null
> +++ b/gas/testsuite/gas/riscv/mapping-03.s
> @@ -0,0 +1,10 @@
> +	.option norvc
> +	.text
> +	.word 0
> +	nop
> +	.data
> +	.word 0
> +	.text
> +	nop
> +	.short 0
> +	nop
> diff --git a/gas/testsuite/gas/riscv/mapping-03a.d b/gas/testsuite/gas/riscv/mapping-03a.d
> new file mode 100644
> index 00000000000..8567820b941
> --- /dev/null
> +++ b/gas/testsuite/gas/riscv/mapping-03a.d
> @@ -0,0 +1,16 @@
> +#as:
> +#source: mapping-03.s
> +#objdump: --syms --special-syms
> +
> +.*file format.*riscv.*
> +
> +SYMBOL TABLE:
> +0+00 l    d  .text	0+00 .text
> +0+00 l    d  .data	0+00 .data
> +0+00 l    d  .bss	0+00 .bss
> +0+00 l       .text	0+00 \$d4
> +0+04 l       .text	0+00 \$x
> +0+0c l       .text	0+00 \$d2
> +0+0e l       .text	0+00 \$x
> +0+12 l       .text	0+00 \$a
> +0+00 l    d  .riscv.attributes	0+00 .riscv.attributes
> diff --git a/gas/testsuite/gas/riscv/mapping-03b.d b/gas/testsuite/gas/riscv/mapping-03b.d
> new file mode 100644
> index 00000000000..ed87fcf33d2
> --- /dev/null
> +++ b/gas/testsuite/gas/riscv/mapping-03b.d
> @@ -0,0 +1,16 @@
> +#as:
> +#source: mapping-03.s
> +#objdump: -d
> +
> +.*:[ 	]+file format .*
> +
> +
> +Disassembly of section .text:
> +
> +0+000 <.text>:
> +[ 	]+0:[ 	]+00000000[ 	]+.word[ 	]+0x00000000
> +[ 	]+4:[ 	]+00000013[ 	]+nop
> +[ 	]+8:[ 	]+00000013[ 	]+nop
> +[ 	]+c:[ 	]+0000[ 	]+.short[ 	]+0x0000
> +[ 	]+e:[ 	]+00000013[ 	]+nop
> +#...
> diff --git a/gas/testsuite/gas/riscv/mapping-04.s b/gas/testsuite/gas/riscv/mapping-04.s
> new file mode 100644
> index 00000000000..36bfac11050
> --- /dev/null
> +++ b/gas/testsuite/gas/riscv/mapping-04.s
> @@ -0,0 +1,11 @@
> +	.option norvc
> +	.text
> +	nop
> +	.long	0
> +	.align	4
> +	.word	0x12345678
> +	nop
> +	.byte	1
> +	.long	0
> +	.align	4
> +	.word	0x12345678
> diff --git a/gas/testsuite/gas/riscv/mapping-04a.d b/gas/testsuite/gas/riscv/mapping-04a.d
> new file mode 100644
> index 00000000000..a3bb31a98b4
> --- /dev/null
> +++ b/gas/testsuite/gas/riscv/mapping-04a.d
> @@ -0,0 +1,21 @@
> +#as:
> +#source: mapping-04.s
> +#objdump: --syms --special-syms
> +
> +.*file format.*riscv.*
> +
> +SYMBOL TABLE:
> +0+00 l    d  .text	0+00 .text
> +0+00 l    d  .data	0+00 .data
> +0+00 l    d  .bss	0+00 .bss
> +0+00 l       .text	0+00 \$x
> +0+04 l       .text	0+00 \$d4
> +0+08 l       .text	0+00 \$a
> +0+14 l       .text	0+00 \$d4
> +0+18 l       .text	0+00 \$x
> +0+1c l       .text	0+00 \$d1
> +0+1d l       .text	0+00 \$d4
> +0+21 l       .text	0+00 \$a
> +0+2d l       .text	0+00 \$d4
> +0+31 l       .text	0+00 \$a
> +0+00 l    d  .riscv.attributes	0+00 .riscv.attributes
> diff --git a/gas/testsuite/gas/riscv/mapping-04b.d b/gas/testsuite/gas/riscv/mapping-04b.d
> new file mode 100644
> index 00000000000..d27b98db2ae
> --- /dev/null
> +++ b/gas/testsuite/gas/riscv/mapping-04b.d
> @@ -0,0 +1,24 @@
> +#as:
> +#source: mapping-04.s
> +#objdump: -d
> +
> +.*:[ 	]+file format .*
> +
> +
> +Disassembly of section .text:
> +
> +0+000 <.text>:
> +[ 	]+0:[ 	]+00000013[ 	]+nop
> +[ 	]+4:[ 	]+00000000[ 	]+.word[ 	]+0x00000000
> +[ 	]+8:[ 	]+00000013[ 	]+align.nop
> +[ 	]+c:[ 	]+00000013[ 	]+align.nop
> +[ 	]+10:[ 	]+00000013[ 	]+align.nop
> +[ 	]+14:[ 	]+12345678[ 	]+.word[ 	]+0x12345678
> +[ 	]+18:[ 	]+00000013[ 	]+nop
> +[ 	]+1c:[ 	]+01[ 	]+.byte[ 	]+0x01
> +[ 	]+1d:[ 	]+00000000[ 	]+.word[ 	]+0x00000000
> +[ 	]+21:[ 	]+00000013[ 	]+align.nop
> +[ 	]+25:[ 	]+00000013[ 	]+align.nop
> +[ 	]+29:[ 	]+00000013[ 	]+align.nop
> +[ 	]+2d:[ 	]+12345678[ 	]+.word[ 	]+0x12345678
> +#...
> diff --git a/gas/testsuite/gas/riscv/mapping-norelax-04a.d b/gas/testsuite/gas/riscv/mapping-norelax-04a.d
> new file mode 100644
> index 00000000000..785b9d9f922
> --- /dev/null
> +++ b/gas/testsuite/gas/riscv/mapping-norelax-04a.d
> @@ -0,0 +1,23 @@
> +#as: -mno-relax
> +#source: mapping-04.s
> +#objdump: --syms --special-syms
> +
> +.*file format.*riscv.*
> +
> +SYMBOL TABLE:
> +0+00 l    d  .text	0+00 .text
> +0+00 l    d  .data	0+00 .data
> +0+00 l    d  .bss	0+00 .bss
> +0+00 l       .text	0+00 \$x
> +0+04 l       .text	0+00 \$d4
> +0+08 l       .text	0+00 \$a
> +0+10 l       .text	0+00 \$d4
> +0+14 l       .text	0+00 \$x
> +0+18 l       .text	0+00 \$d1
> +0+19 l       .text	0+00 \$d4
> +0+20 l       .text	0+00 \$d4
> +0+24 l       .text	0+00 \$a
> +0+1d l       .text	0+00 \$a1
> +0+1e l       .text	0+00 \$a
> +# Maybe section symbol for .riscv.attributes
> +#...
> diff --git a/gas/testsuite/gas/riscv/mapping-norelax-04b.d b/gas/testsuite/gas/riscv/mapping-norelax-04b.d
> new file mode 100644
> index 00000000000..8765c6cd129
> --- /dev/null
> +++ b/gas/testsuite/gas/riscv/mapping-norelax-04b.d
> @@ -0,0 +1,25 @@
> +#as: -mno-relax
> +#source: mapping-04.s
> +#objdump: -d
> +
> +.*:[ 	]+file format .*
> +
> +
> +Disassembly of section .text:
> +
> +0+000 <.text>:
> +[ 	]+0:[ 	]+00000013[ 	]+nop
> +[ 	]+4:[ 	]+00000000[ 	]+.word[ 	]+0x00000000
> +[ 	]+8:[ 	]+00000013[ 	]+align.nop
> +[ 	]+c:[ 	]+00000013[ 	]+align.nop
> +[ 	]+10:[ 	]+12345678[ 	]+.word[ 	]+0x12345678
> +[ 	]+14:[ 	]+00000013[ 	]+nop
> +[ 	]+18:[ 	]+01[ 	]+.byte[ 	]+0x01
> +[ 	]+19:[ 	]+00000000[ 	]+.word[ 	]+0x00000000
> +[ 	]+1d:[ 	]+00[ 	]+align.byte
> +[ 	]+1e:[ 	]+0001[ 	]+align.nop
> +[ 	]+20:[ 	]+12345678[ 	]+.word[ 	]+0x12345678
> +[ 	]+24:[ 	]+00000013[ 	]+align.nop
> +[ 	]+28:[ 	]+00000013[ 	]+align.nop
> +[ 	]+2c:[ 	]+00000013[ 	]+align.nop
> +#...
> diff --git a/gas/testsuite/gas/riscv/no-relax-align-2.d b/gas/testsuite/gas/riscv/no-relax-align-2.d
> index 7407b495a8f..3c4323cc186 100644
> --- a/gas/testsuite/gas/riscv/no-relax-align-2.d
> +++ b/gas/testsuite/gas/riscv/no-relax-align-2.d
> @@ -7,13 +7,14 @@
>  Disassembly of section .text:
>
>  0+000 <.text>:
> -[ 	]+0:[ 	]+0000[ 	]+unimp
> -[ 	]+2:[ 	]+0001[ 	]+nop
> -[ 	]+4:[ 	]+00000013[ 	]+nop
> -[ 	]+8:[ 	]+00000013[ 	]+nop
> -[ 	]+c:[ 	]+00000013[ 	]+nop
> +[ 	]+0:[ 	]+00[ 	]+.byte[ 	]+0x00
> +[ 	]+1:[ 	]+00[ 	]+align.byte
> +[ 	]+2:[ 	]+0001[ 	]+align.nop
> +[ 	]+4:[ 	]+00000013[ 	]+align.nop
> +[ 	]+8:[ 	]+00000013[ 	]+align.nop
> +[ 	]+c:[ 	]+00000013[ 	]+align.nop
>  [ 	]+10:[ 	]+0001[ 	]+nop
> -[ 	]+12:[ 	]+0001[ 	]+nop
> -[ 	]+14:[ 	]+00000013[ 	]+nop
> -[ 	]+18:[ 	]+00000013[ 	]+nop
> -[ 	]+1c:[ 	]+00000013[ 	]+nop
> +[ 	]+12:[ 	]+0001[ 	]+align.nop
> +[ 	]+14:[ 	]+00000013[ 	]+align.nop
> +[ 	]+18:[ 	]+00000013[ 	]+align.nop
> +[ 	]+1c:[ 	]+00000013[ 	]+align.nop
> diff --git a/gas/testsuite/gas/riscv/no-relax-align.d b/gas/testsuite/gas/riscv/no-relax-align.d
> index ced07d3c830..960db2a58bc 100644
> --- a/gas/testsuite/gas/riscv/no-relax-align.d
> +++ b/gas/testsuite/gas/riscv/no-relax-align.d
> @@ -9,5 +9,5 @@ Disassembly of section .text:
>  0+000 <.text>:
>  [ 	]+0:[ 	]+00000013[ 	]+nop
>  [ 	]+4:[ 	]+00000013[ 	]+nop
> -[ 	]+8:[ 	]+00000013[ 	]+nop
> -[ 	]+c:[ 	]+00000013[ 	]+nop
> +[ 	]+8:[ 	]+00000013[ 	]+align.nop
> +[ 	]+c:[ 	]+00000013[ 	]+align.nop
> diff --git a/include/opcode/riscv.h b/include/opcode/riscv.h
> index fdf3df4f5c1..3cea9e93c96 100644
> --- a/include/opcode/riscv.h
> +++ b/include/opcode/riscv.h
> @@ -425,6 +425,19 @@ enum
>    M_NUM_MACROS
>  };
>
> +/* The mapping symbol states.  */
> +enum riscv_seg_mstate
> +{
> +  MAP_NONE = 0,		/* Must be zero, for seginfo in new sections.  */
> +  MAP_DATA,		/* The rs_fill and rs_align.  */
> +  MAP_DATA_CONS0,	/* Added for cons_worker, with the data size.  */
> +  MAP_DATA_CONS1,
> +  MAP_DATA_CONS2,
> +  MAP_DATA_CONS3,
> +  MAP_INSN,		/* Instructions.  */
> +  MAP_ALIGN,		/* The rs_align_code, added nops.  */
> +  MAP_ALIGN_ODD,	/* The rs_align_code, added odd byte.  */
> +};
>
>  extern const char * const riscv_gpr_names_numeric[NGPR];
>  extern const char * const riscv_gpr_names_abi[NGPR];
> diff --git a/opcodes/riscv-dis.c b/opcodes/riscv-dis.c
> index fe8dfb88d90..b41cad8f4aa 100644
> --- a/opcodes/riscv-dis.c
> +++ b/opcodes/riscv-dis.c
> @@ -41,6 +41,12 @@ struct riscv_private_data
>    bfd_vma hi_addr[OP_MASK_RD + 1];
>  };
>
> +/* Used for mapping symbols.  */
> +static int last_map_symbol = -1;
> +static bfd_vma last_stop_offset = 0;
> +static asection *last_section = NULL;
> +enum riscv_seg_mstate last_map_state;
> +
>  static const char * const *riscv_gpr_names;
>  static const char * const *riscv_fpr_names;
>
> @@ -507,6 +513,27 @@ riscv_disassemble_insn (bfd_vma memaddr, insn_t word, disassemble_info *info)
>  	  if ((op->xlen_requirement != 0) && (op->xlen_requirement != xlen))
>  	    continue;
>
> +	  /* Add the "align." prefix if it is used for alignment.
> +
> +	     Consider the following case,
> +	     .text
> +	     .byte 0
> +	     nop
> +
> +	     0000000000000000 <.text>:
> +	     0:	00		.byte   0x00
> +	     1:	00000013	nop
> +	     5:	0000		align.unimp
> +		...
> +
> +	     The tail section alignments are not handled in the
> +	     riscv_frag_align_code, and since the relax is enable,
> +	     it cannot be filled with nops in the riscv_handle_align
> +	     either.  Therefore, we may get align.unimp at the end
> +	     of the sections, I think this is expected.  */
> +	  if (last_map_state == MAP_ALIGN)
> +	    (*info->fprintf_func) (info->stream, "align.");
> +
>  	  /* It's a match.  */
>  	  (*info->fprintf_func) (info->stream, "%s", op->name);
>  	  print_insn_args (op->args, word, memaddr, info);
> @@ -556,13 +583,238 @@ riscv_disassemble_insn (bfd_vma memaddr, insn_t word, disassemble_info *info)
>    return insnlen;
>  }
>
> +/* Return true if we find the suitable mapping symbol,
> +   and also update the STATE.  Otherwise, return false.  */
> +
> +static bool
> +riscv_get_map_state (int n,
> +		     enum riscv_seg_mstate *state,
> +		     struct disassemble_info *info)
> +{
> +  const char *name;
> +
> +  /* If the symbol is in a different section, ignore it.  */
> +  if (info->section != NULL
> +      && info->section != info->symtab[n]->section)
> +    return false;
> +
> +  name = bfd_asymbol_name(info->symtab[n]);
> +  if (strcmp (name, "$x") == 0)
> +    *state = MAP_INSN;
> +  else if (strcmp (name, "$d") == 0)
> +    *state = MAP_DATA;
> +  else if (strcmp (name, "$d1") == 0)
> +    *state = MAP_DATA_CONS0;
> +  else if (strcmp (name, "$d2") == 0)
> +    *state = MAP_DATA_CONS1;
> +  else if (strcmp (name, "$d4") == 0)
> +    *state = MAP_DATA_CONS2;
> +  else if (strcmp (name, "$d8") == 0)
> +    *state = MAP_DATA_CONS3;
> +  else if (strcmp (name, "$a") == 0)
> +    *state = MAP_ALIGN;
> +  else if (strcmp (name, "$a1") == 0)
> +    *state = MAP_ALIGN_ODD;
> +  else
> +    return false;
> +
> +  return true;
> +}
> +
> +/* Check the sorted symbol table (sorted by the symbol value), find the
> +   suitable mapping symbols.  */
> +
> +static enum riscv_seg_mstate
> +riscv_search_mapping_symbol (bfd_vma memaddr,
> +			     struct disassemble_info *info)
> +{
> +  enum riscv_seg_mstate mstate;
> +  bool from_last_map_symbol;
> +  bool found = false;
> +  int symbol = -1;
> +  int n;
> +
> +  /* Decide whether to print the data or instruction by default, in case
> +     we can not find the corresponding mapping symbols.  */
> +  mstate = MAP_DATA;
> +  if ((info->section
> +       && info->section->flags & SEC_CODE)
> +      || !info->section)
> +    mstate = MAP_INSN;
> +
> +  if (info->symtab_size == 0
> +      || bfd_asymbol_flavour (*info->symtab) != bfd_target_elf_flavour)
> +    return mstate;
> +
> +  /* Reset the last_map_symbol if we start to dump a new section.  */
> +  if (memaddr <= 0)
> +    last_map_symbol = -1;
> +
> +  /* If the last stop offset is different from the current one, then
> +     don't use the last_map_symbol to search.  We usually reset the
> +     info->stop_offset when handling a new section.  */
> +  from_last_map_symbol = (last_map_symbol >= 0
> +			  && info->stop_offset == last_stop_offset);
> +
> +  /* Start scanning at the start of the function, or wherever
> +     we finished last time.  */
> +  n = info->symtab_pos + 1;
> +  if (from_last_map_symbol && n >= last_map_symbol)
> +    n = last_map_symbol;
> +
> +  /* Find the suitable mapping symbol to dump.  */
> +  for (; n < info->symtab_size; n++)
> +    {
> +      bfd_vma addr = bfd_asymbol_value (info->symtab[n]);
> +      /* We have searched all possible symbols in the range.  */
> +      if (addr > memaddr)
> +	break;
> +      if (riscv_get_map_state (n, &mstate, info))
> +	{
> +	  symbol = n;
> +	  found = true;
> +	  /* Do not stop searching, in case there are some mapping
> +	     symbols have the same value, but have different names.
> +	     Use the last one.  */
> +	}
> +    }
> +
> +  /* We can not find the suitable mapping symbol above.  Therefore, we
> +     look forwards and try to find it again, but don't go pass the start
> +     of the section.  Otherwise a data section without mapping symbols
> +     can pick up a text mapping symbol of a preceeding section.  */
> +  if (!found)
> +    {
> +      n = info->symtab_pos;
> +      if (from_last_map_symbol && n >= last_map_symbol)
> +	n = last_map_symbol;
> +
> +      for (; n >= 0; n--)
> +	{
> +	  bfd_vma addr = bfd_asymbol_value (info->symtab[n]);
> +	  /* We have searched all possible symbols in the range.  */
> +	  if (addr < (info->section ? info->section->vma : 0))
> +	    break;
> +	  /* Stop searching once we find the closed mapping symbol.  */
> +	  if (riscv_get_map_state (n, &mstate, info))
> +	    {
> +	      symbol = n;
> +	      found = true;
> +	      break;
> +	    }
> +	}
> +    }
> +
> +  /* Save the information for next use.  */
> +  last_map_symbol = symbol;
> +  last_stop_offset = info->stop_offset;
> +  last_section = info->section;
> +
> +  return mstate;
> +}
> +
> +/* Decide which data size we should print.  */
> +
> +static bfd_vma
> +riscv_data_length (bfd_vma memaddr,
> +		   enum riscv_seg_mstate mstate,
> +		   disassemble_info *info)
> +{
> +  bfd_vma length;
> +  bool found = false;
> +
> +  switch (mstate)
> +    {
> +    case MAP_DATA:	 length = 0; break;
> +    case MAP_DATA_CONS0: length = 1; break;
> +    case MAP_DATA_CONS1: length = 2; break;
> +    case MAP_DATA_CONS2: length = 4; break;
> +    case MAP_DATA_CONS3: length = 8; break;
> +    default: abort ();
> +    }
> +  if (length > 0)
> +    return length;
> +
> +  length = 4;
> +  if (info->symtab_size != 0
> +      && bfd_asymbol_flavour (*info->symtab) == bfd_target_elf_flavour
> +      && last_map_symbol >= 0)
> +    {
> +      int n;
> +      enum riscv_seg_mstate m = MAP_NONE;
> +      for (n = last_map_symbol + 1; n < info->symtab_size; n++)
> +	{
> +	  bfd_vma addr = bfd_asymbol_value (info->symtab[n]);
> +	  if (addr > memaddr
> +	      && riscv_get_map_state (n, &m, info))
> +	    {
> +	      if (addr - memaddr < length)
> +		length = addr - memaddr;
> +	      found = true;
> +	      break;
> +	    }
> +	}
> +    }
> +  if (!found)
> +    {
> +      /* Do not set the length which exceeds the section size.  */
> +      bfd_vma offset = info->section->vma + info->section->size;
> +      offset -= memaddr;
> +      length = (offset < length) ? offset : length;
> +    }
> +  length = length == 3 ? 2 : length;
> +  return length;
> +}
> +
> +/* Dump the data contents.  */
> +
> +static int
> +riscv_disassemble_data (bfd_vma memaddr ATTRIBUTE_UNUSED,
> +			insn_t data,
> +			disassemble_info *info)
> +{
> +  info->display_endian = info->endian;
> +
> +  switch (info->bytes_per_chunk)
> +    {
> +    case 1:
> +      info->bytes_per_line = 6;
> +      if (last_map_state == MAP_ALIGN_ODD)
> +	(*info->fprintf_func) (info->stream, "align.byte");
> +      else
> +	(*info->fprintf_func) (info->stream, ".byte\t0x%02llx",
> +			       (unsigned long long) data);
> +      break;
> +    case 2:
> +      info->bytes_per_line = 8;
> +      (*info->fprintf_func) (info->stream, ".short\t0x%04llx",
> +			     (unsigned long long) data);
> +      break;
> +    case 4:
> +      info->bytes_per_line = 8;
> +      (*info->fprintf_func) (info->stream, ".word\t0x%08llx",
> +			     (unsigned long long) data);
> +      break;
> +    case 8:
> +      info->bytes_per_line = 8;
> +      (*info->fprintf_func) (info->stream, ".dword\t0x%016llx",
> +			     (unsigned long long) data);
> +      break;
> +    default:
> +      abort ();
> +    }
> +  return info->bytes_per_chunk;
> +}
> +
>  int
>  print_insn_riscv (bfd_vma memaddr, struct disassemble_info *info)
>  {
> -  bfd_byte packet[2];
> +  bfd_byte packet[8];
>    insn_t insn = 0;
> -  bfd_vma n;
> +  bfd_vma dump_size;
>    int status;
> +  enum riscv_seg_mstate mstate;
> +  int (*riscv_disassembler) (bfd_vma, insn_t, struct disassemble_info *);
>
>    if (info->disassembler_options != NULL)
>      {
> @@ -573,23 +825,59 @@ print_insn_riscv (bfd_vma memaddr, struct disassemble_info *info)
>    else if (riscv_gpr_names == NULL)
>      set_default_riscv_dis_options ();
>
> -  /* Instructions are a sequence of 2-byte packets in little-endian order.  */
> -  for (n = 0; n < sizeof (insn) && n < riscv_insn_length (insn); n += 2)
> +  mstate = riscv_search_mapping_symbol (memaddr, info);
> +  /* Save the last mapping state.  */
> +  last_map_state = mstate;
> +
> +  /* Set the size to dump.  */
> +  if (mstate == MAP_DATA
> +      || mstate == MAP_DATA_CONS0
> +      || mstate == MAP_DATA_CONS1
> +      || mstate == MAP_DATA_CONS2
> +      || mstate == MAP_DATA_CONS3)
>      {
> -      status = (*info->read_memory_func) (memaddr + n, packet, 2, info);
> +      /* The documentation for -D says that on Arm platforms -D should
> +	 disassemble instructions.  Therefore, they dump data by searching
> +	 mapping symbols only when the DISASSEMBLE_DATA is set.  That causes
> +	 the mapping symbols are useless for -D.  I am not sure if any riscv
> +	 document had mentioned this, so I prefer to keep them useful, but
> +	 only for text sections.  If we decide not only to support mapping
> +	 symbols for text sections, then the riscv_mapping_state in the
> +	 gas/config/tc-riscv.c should be updated.  */
> +      dump_size = riscv_data_length (memaddr, mstate, info);
> +      info->bytes_per_chunk = dump_size;
> +      riscv_disassembler = riscv_disassemble_data;
> +    }
> +  else if (mstate == MAP_ALIGN_ODD)
> +    {
> +      dump_size = 1;
> +      info->bytes_per_chunk = dump_size;
> +      riscv_disassembler = riscv_disassemble_data;
> +    }
> +  else
> +    {
> +      /* Get the first 2-bytes to check the lenghth of instruction.  */
> +      status = (*info->read_memory_func) (memaddr, packet, 2, info);
>        if (status != 0)
>  	{
> -	  /* Don't fail just because we fell off the end.  */
> -	  if (n > 0)
> -	    break;
>  	  (*info->memory_error_func) (status, memaddr, info);
> -	  return status;
> +	  return 1;
>  	}
> +      insn = (insn_t) bfd_getl16 (packet);
> +      dump_size = riscv_insn_length (insn);
> +      riscv_disassembler = riscv_disassemble_insn;
> +    }
>
> -      insn |= ((insn_t) bfd_getl16 (packet)) << (8 * n);
> +  /* Fetch the instruction to dump.  */
> +  status = (*info->read_memory_func) (memaddr, packet, dump_size, info);
> +  if (status != 0)
> +    {
> +      (*info->memory_error_func) (status, memaddr, info);
> +      return 1;
>      }
> +  insn = (insn_t) bfd_get_bits (packet, dump_size * 8, false);
>
> -  return riscv_disassemble_insn (memaddr, insn, info);
> +  return (*riscv_disassembler) (memaddr, insn, info);
>  }
>
>  disassembler_ftype
> @@ -631,7 +919,8 @@ riscv_symbol_is_valid (asymbol * sym,
>
>    name = bfd_asymbol_name (sym);
>
> -  return (strcmp (name, RISCV_FAKE_LABEL_NAME) != 0);
> +  return (strcmp (name, RISCV_FAKE_LABEL_NAME) != 0
> +	  && !riscv_elf_is_mapping_symbols (name));
>  }
>
>  void

  reply	other threads:[~2021-07-15 15:16 UTC|newest]

Thread overview: 13+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2021-07-09  7:28 [PATCH v2 0/3] RISC-V: The series to supporting " Nelson Chu
2021-07-09  7:28 ` [PATCH v2 1/3] RISC-V: Enable elf attributes when default configure option isn't set Nelson Chu
2021-07-09  8:00   ` Kito Cheng
2021-07-13  7:07     ` Nelson Chu
2021-07-13 20:38   ` Palmer Dabbelt
2021-07-15  1:47     ` Nelson Chu
2022-02-25 13:57   ` Sebastian Huber
2021-07-09  7:28 ` [PATCH v2 2/3] RISC-V: PR27916, Support mapping symbols Nelson Chu
2021-07-15 15:16   ` Palmer Dabbelt [this message]
2021-07-16  2:58     ` Nelson Chu
2021-07-09  7:28 ` [PATCH v2 3/3] RISC-V: PR27916, Extend .insn directive to support hardcode encoding Nelson Chu
2021-07-09  8:01   ` Kito Cheng
2021-07-14 20:38     ` Palmer Dabbelt

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=mhng-25bd6f14-4df8-4298-965d-d87d67f97995@palmerdabbelt-glaptop \
    --to=palmer@dabbelt.com \
    --cc=andrew.burgess@embecosm.com \
    --cc=andrew@sifive.com \
    --cc=binutils@sourceware.org \
    --cc=gdb-patches@sourceware.org \
    --cc=jimw@sifive.com \
    --cc=kito.cheng@sifive.com \
    --cc=nelson.chu@sifive.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).