[llvm] a0d8a53 - [RISCV][MC] Implement mapping symbols
Job Noorman via llvm-commits
llvm-commits at lists.llvm.org
Fri Jul 28 02:13:11 PDT 2023
Author: Job Noorman
Date: 2023-07-28T11:13:03+02:00
New Revision: a0d8a53c7d0e6ca1c94b5d5c4a65790dd5705ef8
URL: https://github.com/llvm/llvm-project/commit/a0d8a53c7d0e6ca1c94b5d5c4a65790dd5705ef8
DIFF: https://github.com/llvm/llvm-project/commit/a0d8a53c7d0e6ca1c94b5d5c4a65790dd5705ef8.diff
LOG: [RISCV][MC] Implement mapping symbols
Mapping symbols [1] are special ELF symbols that can be inserted to
indicate regions of code or data. A sequence of data bytes is indicated
by a `$d` (or `$d.<any>`) symbol pointing to its start while a sequence
of instructions uses a `$x` (or `$x.<any>`) symbol. This can be used,
for example, to assist disassembling a memory region containing both
data and code.
This patch implements mapping symbols for RISC-V, copying the
implementation mostly from the AArch64 target.
Note that the `$x<ISA>` mapping symbol, indicating an instruction
sequence with a specific ISA extension, is not implemented by this
patch. As far as I can tell, binutils doesn't implement this yet either.
Note that this patch uses the same symbol naming convention as the
AArch64 target: always use `$x.i` and `$d.i` (where `i` is a
monotonically increasing counter). This differs from binutils where all
symbols are named `$x` or `$d` (causing multiple symbol having the same
name). I'm not not sure whether it makes more sense to avoid duplicate
symbol names or be consistent with binutils.
Note that the handling of nop-slides inserted for alignment differs from
binutils: binutils always marks the nops as instructions (`$x`) while
this patch doesn't insert a symbol for the nops (so the last inserted
symbol is used). I believe binutil's behavior makes most sense but this
seems difficult to implement in LLVM as the insertion of nops is handled
by `RISCVAsmBackend`. At this point, inserting ELF symbols seems
impossible. Any ideas for how to handle this would be appreciated.
[1]: https://github.com/riscv-non-isa/riscv-elf-psabi-doc/blob/master/riscv-elf.adoc#mapping-symbol
Depends on D156190 and D156236
Differential Revision: https://reviews.llvm.org/D153260
Added:
llvm/test/MC/RISCV/mapping-across-sections.s
llvm/test/MC/RISCV/mapping-within-section.s
Modified:
lld/test/ELF/riscv-variant-cc.s
llvm/lib/Target/RISCV/MCTargetDesc/RISCVELFStreamer.cpp
llvm/lib/Target/RISCV/MCTargetDesc/RISCVELFStreamer.h
Removed:
################################################################################
diff --git a/lld/test/ELF/riscv-variant-cc.s b/lld/test/ELF/riscv-variant-cc.s
index ac1a1606fad577..024266d236a67d 100644
--- a/lld/test/ELF/riscv-variant-cc.s
+++ b/lld/test/ELF/riscv-variant-cc.s
@@ -45,7 +45,7 @@
# CHECK5: 0 NOTYPE GLOBAL DEFAULT [VARIANT_CC] UND func_global_undef
# CHECK5-NEXT: 0 NOTYPE GLOBAL DEFAULT [VARIANT_CC] [[#]] func_global_def
# CHECK5-NEXT: 0 IFUNC GLOBAL DEFAULT [VARIANT_CC] [[#]] ifunc_global_def
-# CHECK5: Symbol table '.symtab' contains 9 entries:
+# CHECK5: Symbol table '.symtab' contains 10 entries:
# CHECK5: 0 NOTYPE LOCAL DEFAULT [VARIANT_CC] [[#]] func_local
# CHECK5-NEXT: 0 IFUNC LOCAL DEFAULT [VARIANT_CC] [[#]] ifunc_local
# CHECK5: 0 NOTYPE LOCAL HIDDEN [VARIANT_CC] [[#]] func_global_hidden
diff --git a/llvm/lib/Target/RISCV/MCTargetDesc/RISCVELFStreamer.cpp b/llvm/lib/Target/RISCV/MCTargetDesc/RISCVELFStreamer.cpp
index e43cb8b40d8377..9db5148208b3ec 100644
--- a/llvm/lib/Target/RISCV/MCTargetDesc/RISCVELFStreamer.cpp
+++ b/llvm/lib/Target/RISCV/MCTargetDesc/RISCVELFStreamer.cpp
@@ -125,6 +125,65 @@ void RISCVTargetELFStreamer::emitDirectiveVariantCC(MCSymbol &Symbol) {
void RISCVELFStreamer::reset() {
static_cast<RISCVTargetStreamer *>(getTargetStreamer())->reset();
MCELFStreamer::reset();
+ MappingSymbolCounter = 0;
+ LastMappingSymbols.clear();
+ LastEMS = EMS_None;
+}
+
+void RISCVELFStreamer::emitDataMappingSymbol() {
+ if (LastEMS == EMS_Data)
+ return;
+ emitMappingSymbol("$d");
+ LastEMS = EMS_Data;
+}
+
+void RISCVELFStreamer::emitInstructionsMappingSymbol() {
+ if (LastEMS == EMS_Instructions)
+ return;
+ emitMappingSymbol("$x");
+ LastEMS = EMS_Instructions;
+}
+
+void RISCVELFStreamer::emitMappingSymbol(StringRef Name) {
+ auto *Symbol = cast<MCSymbolELF>(getContext().getOrCreateSymbol(
+ Name + "." + Twine(MappingSymbolCounter++)));
+ emitLabel(Symbol);
+ Symbol->setType(ELF::STT_NOTYPE);
+ Symbol->setBinding(ELF::STB_LOCAL);
+}
+
+void RISCVELFStreamer::changeSection(MCSection *Section,
+ const MCExpr *Subsection) {
+ // We have to keep track of the mapping symbol state of any sections we
+ // use. Each one should start off as EMS_None, which is provided as the
+ // default constructor by DenseMap::lookup.
+ LastMappingSymbols[getPreviousSection().first] = LastEMS;
+ LastEMS = LastMappingSymbols.lookup(Section);
+
+ MCELFStreamer::changeSection(Section, Subsection);
+}
+
+void RISCVELFStreamer::emitInstruction(const MCInst &Inst,
+ const MCSubtargetInfo &STI) {
+ emitInstructionsMappingSymbol();
+ MCELFStreamer::emitInstruction(Inst, STI);
+}
+
+void RISCVELFStreamer::emitBytes(StringRef Data) {
+ emitDataMappingSymbol();
+ MCELFStreamer::emitBytes(Data);
+}
+
+void RISCVELFStreamer::emitFill(const MCExpr &NumBytes, uint64_t FillValue,
+ SMLoc Loc) {
+ emitDataMappingSymbol();
+ MCELFStreamer::emitFill(NumBytes, FillValue, Loc);
+}
+
+void RISCVELFStreamer::emitValueImpl(const MCExpr *Value, unsigned Size,
+ SMLoc Loc) {
+ emitDataMappingSymbol();
+ MCELFStreamer::emitValueImpl(Value, Size, Loc);
}
namespace llvm {
diff --git a/llvm/lib/Target/RISCV/MCTargetDesc/RISCVELFStreamer.h b/llvm/lib/Target/RISCV/MCTargetDesc/RISCVELFStreamer.h
index e68f70261146f7..f14c531b2e2968 100644
--- a/llvm/lib/Target/RISCV/MCTargetDesc/RISCVELFStreamer.h
+++ b/llvm/lib/Target/RISCV/MCTargetDesc/RISCVELFStreamer.h
@@ -16,12 +16,27 @@ using namespace llvm;
class RISCVELFStreamer : public MCELFStreamer {
void reset() override;
+ void emitDataMappingSymbol();
+ void emitInstructionsMappingSymbol();
+ void emitMappingSymbol(StringRef Name);
+
+ enum ElfMappingSymbol { EMS_None, EMS_Instructions, EMS_Data };
+
+ int64_t MappingSymbolCounter;
+ DenseMap<const MCSection *, ElfMappingSymbol> LastMappingSymbols;
+ ElfMappingSymbol LastEMS;
public:
RISCVELFStreamer(MCContext &C, std::unique_ptr<MCAsmBackend> MAB,
std::unique_ptr<MCObjectWriter> MOW,
std::unique_ptr<MCCodeEmitter> MCE)
: MCELFStreamer(C, std::move(MAB), std::move(MOW), std::move(MCE)) {}
+
+ void changeSection(MCSection *Section, const MCExpr *Subsection) override;
+ void emitInstruction(const MCInst &Inst, const MCSubtargetInfo &STI) override;
+ void emitBytes(StringRef Data) override;
+ void emitFill(const MCExpr &NumBytes, uint64_t FillValue, SMLoc Loc) override;
+ void emitValueImpl(const MCExpr *Value, unsigned Size, SMLoc Loc) override;
};
namespace llvm {
diff --git a/llvm/test/MC/RISCV/mapping-across-sections.s b/llvm/test/MC/RISCV/mapping-across-sections.s
new file mode 100644
index 00000000000000..700e86a0eb70e3
--- /dev/null
+++ b/llvm/test/MC/RISCV/mapping-across-sections.s
@@ -0,0 +1,33 @@
+# RUN: llvm-mc -triple=riscv32 -filetype=obj < %s | llvm-readelf -Ss - | FileCheck %s
+# RUN: llvm-mc -triple=riscv64 -filetype=obj < %s | llvm-readelf -Ss - | FileCheck %s
+
+ .text
+ nop
+
+# .wibble should *not* inherit .text's mapping symbol. It's a completely
+#
diff erent section.
+ .section .wibble
+ nop
+
+# A section should be able to start with a $d.
+ .section .starts_data
+ .word 42
+
+# Changing back to .text should not emit a redundant $x.
+ .text
+ nop
+
+# With all those constraints, we want:
+# + .text to have $x at 0 and no others
+# + .wibble to have $x at 0
+# + .starts_data to have $d at 0
+
+## Capture section indices.
+# CHECK: [[#TEXT:]]] .text
+# CHECK: [[#WIBBLE:]]] .wibble
+# CHECK: [[#STARTS_DATA:]]] .starts_data
+
+# CHECK: Value Size Type Bind Vis Ndx Name
+# CHECK: 00000000 0 NOTYPE LOCAL DEFAULT [[#TEXT]] $x
+# CHECK: 00000000 0 NOTYPE LOCAL DEFAULT [[#WIBBLE]] $x
+# CHECK: 00000000 0 NOTYPE LOCAL DEFAULT [[#STARTS_DATA]] $d
diff --git a/llvm/test/MC/RISCV/mapping-within-section.s b/llvm/test/MC/RISCV/mapping-within-section.s
new file mode 100644
index 00000000000000..15fffe82edd6f0
--- /dev/null
+++ b/llvm/test/MC/RISCV/mapping-within-section.s
@@ -0,0 +1,27 @@
+# RUN: llvm-mc -triple=riscv32 -filetype=obj %s | llvm-readelf -Ss - | FileCheck %s
+# RUN: llvm-mc -triple=riscv64 -filetype=obj %s | llvm-readelf -Ss - | FileCheck %s
+
+ .text
+# $x at 0x0000
+ nop
+# $d at 0x0004
+ .ascii "012"
+ .byte 1
+ .hword 2
+ .word 4
+ .single 4.0
+ .double 8.0
+ .space 10
+ .zero 3
+ .fill 10, 2, 42
+ .org 100, 12
+# $x at 0x0064
+ nop
+
+## Capture section index.
+# CHECK: [[#TEXT:]]] .text
+
+# CHECK: Value Size Type Bind Vis Ndx Name
+# CHECK: 00000000 0 NOTYPE LOCAL DEFAULT [[#TEXT]] $x
+# CHECK: 00000004 0 NOTYPE LOCAL DEFAULT [[#TEXT]] $d
+# CHECK: 00000064 0 NOTYPE LOCAL DEFAULT [[#TEXT]] $x
More information about the llvm-commits
mailing list