From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from mail-pg1-x529.google.com (mail-pg1-x529.google.com [IPv6:2607:f8b0:4864:20::529]) by sourceware.org (Postfix) with ESMTPS id A1014385B836 for ; Thu, 15 Jul 2021 15:16:55 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.1 sourceware.org A1014385B836 Authentication-Results: sourceware.org; dmarc=none (p=none dis=none) header.from=dabbelt.com Authentication-Results: sourceware.org; spf=pass smtp.mailfrom=dabbelt.com Received: by mail-pg1-x529.google.com with SMTP id s18so6693325pgg.8 for ; Thu, 15 Jul 2021 08:16:55 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=dabbelt-com.20150623.gappssmtp.com; s=20150623; h=date:subject:in-reply-to:cc:from:to:message-id:mime-version :content-transfer-encoding; bh=A5EBDM/dU0UzLOSw3Kp4mD8MQ/A/XzJWtK5qm01pb58=; b=PSQXfhkHiVgZajtdXTRPMtkoKB9T0Y1q/2Y59zkKFNzUNbfCy9a7rTP1js3Hi3f5vd c7wWXZqnozNFxFTRsQoOkziIYi9vOpyhZKXgAUluHwavgh9OebKDfWEpfBqceo3H1zPk W315aN7aB0CywPsY9XEdSImha1fBVIFeNPw9vF7ycHij7CHKai0l32K8rk1rOT/9989B 6Pjhn3SPwMW1MaKh5qLoB+XmPG7K03E7vSDpTAgoEZkozbZBzXVdzp9cMJntQpUbcJ2K zVAMGDb2rS1/l93JzEY0A+WdGwxVGyrhF5YvRseL72AD9Yvs7WU4nWKXReAAawsNpWga 3/fQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:date:subject:in-reply-to:cc:from:to:message-id :mime-version:content-transfer-encoding; bh=A5EBDM/dU0UzLOSw3Kp4mD8MQ/A/XzJWtK5qm01pb58=; b=fVXWO92zpb6uoCZdv/5diA0P8K5JoNlRlybrcAw5kcOAOj0rZoc2LJxM/mzNlpVoBR KxgRO8dnbcrAXNXVzKhNvdUr5g1EoxSrfTxFYh+cbGmo8oLhvlkkrqnGHzwteS/Kwce2 OeGXQ2RzODum0SJV+jK9nkpcMoZDFp9ounwaeX2ig2SG5GrQkc1KXmBbHiTC86N03s5/ 0uRIjeQlKdMVbvqsZpGnrMMbW1Ny/aNuX6HS+caBiP+H3F1QQiwQ1ptgQONfO49grhfy nhl7UFyeulgINFqY6moBtlFbELymbgzKqLUbCSnzBD0A1wWHumtMFchPwA6XW/1rhiph TBKA== X-Gm-Message-State: AOAM531FHN6GBvMzxWKaki6V7pDqKtWypOlN3DjxSjPDuSPhstSkbWGP 4zFvkm5Cuqv1ATgv5vCiQ3H0HxA949vazQ== X-Google-Smtp-Source: ABdhPJxoFOQvc4dWZOCzNoM1ulf5ALN69VDLZy6wAeX3Uv7eg1AzMYCSYyUJr2jIZbIvUPvHLUna/g== X-Received: by 2002:a63:4c49:: with SMTP id m9mr5058120pgl.419.1626362214238; Thu, 15 Jul 2021 08:16:54 -0700 (PDT) Received: from localhost (76-210-143-223.lightspeed.sntcca.sbcglobal.net. [76.210.143.223]) by smtp.gmail.com with ESMTPSA id f6sm6569606pfj.28.2021.07.15.08.16.53 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 15 Jul 2021 08:16:53 -0700 (PDT) Date: Thu, 15 Jul 2021 08:16:53 -0700 (PDT) X-Google-Original-Date: Thu, 15 Jul 2021 08:16:50 PDT (-0700) Subject: Re: [PATCH v2 2/3] RISC-V: PR27916, Support mapping symbols. In-Reply-To: <20210709072825.13709-3-nelson.chu@sifive.com> CC: binutils@sourceware.org, gdb-patches@sourceware.org, Jim Wilson , andrew.burgess@embecosm.com, kito.cheng@sifive.com, Andrew Waterman , nelson.chu@sifive.com From: Palmer Dabbelt To: nelson.chu@sifive.com Message-ID: Mime-Version: 1.0 (MHng) Content-Type: text/plain; charset=utf-8; format=flowed Content-Transfer-Encoding: 8bit X-Spam-Status: No, score=-12.8 required=5.0 tests=BAYES_00, DKIM_SIGNED, DKIM_VALID, GIT_PATCH_0, RCVD_IN_DNSWL_NONE, SPF_HELO_NONE, SPF_PASS, TXREP autolearn=ham autolearn_force=no version=3.4.4 X-Spam-Checker-Version: SpamAssassin 3.4.4 (2020-01-24) on server2.sourceware.org X-BeenThere: binutils@sourceware.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Binutils mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Thu, 15 Jul 2021 15:17:00 -0000 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. 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. 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 > 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 : > +[ ]+0:[ ]+00000013[ ]+nop > +[ ]+4:[ ]+0040006f[ ]+j[ ]+8 > + > +0+008 : > +[ ]+8:[ ]+00000013[ ]+nop > +[ ]+c:[ ]+feb51ee3[ ]+bne[ ]+a0,a1,8 > + > +Disassembly of section .foo: > + > +0+000 : > +[ ]+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
: > +[ ]+0:[ ]+00000013[ ]+nop > + > +0+004 : > +[ ]+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