diff --git a/llvm/lib/Target/RISCV/MCTargetDesc/RISCVELFStreamer.cpp b/llvm/lib/Target/RISCV/MCTargetDesc/RISCVELFStreamer.cpp --- a/llvm/lib/Target/RISCV/MCTargetDesc/RISCVELFStreamer.cpp +++ b/llvm/lib/Target/RISCV/MCTargetDesc/RISCVELFStreamer.cpp @@ -28,6 +28,228 @@ using namespace llvm; +namespace { +class RISCVELFStreamer : public MCELFStreamer { + static std::pair getRelocPairForSize(unsigned Size) { + switch (Size) { + default: + llvm_unreachable("unsupported fixup size"); + case 1: + return std::make_pair(RISCV::fixup_riscv_add_8, RISCV::fixup_riscv_sub_8); + case 2: + return std::make_pair(RISCV::fixup_riscv_add_16, + RISCV::fixup_riscv_sub_16); + case 4: + return std::make_pair(RISCV::fixup_riscv_add_32, + RISCV::fixup_riscv_sub_32); + case 8: + return std::make_pair(RISCV::fixup_riscv_add_64, + RISCV::fixup_riscv_sub_64); + } + } + + static bool requiresFixups(MCContext &C, const MCExpr *Value, + const MCExpr *&LHS, const MCExpr *&RHS) { + const auto *MBE = dyn_cast(Value); + if (MBE == nullptr) + return false; + + MCValue E; + if (!Value->evaluateAsRelocatable(E, nullptr, nullptr)) + return false; + if (E.getSymA() == nullptr || E.getSymB() == nullptr) + return false; + + const auto &A = E.getSymA()->getSymbol(); + const auto &B = E.getSymB()->getSymbol(); + + LHS = + MCBinaryExpr::create(MCBinaryExpr::Add, MCSymbolRefExpr::create(&A, C), + MCConstantExpr::create(E.getConstant(), C), C); + RHS = E.getSymB(); + + // If either symbol is in a text section, we need to delay the relocation + // evaluation as relaxation may alter the size of the symbol. + // + // Unfortunately, we cannot identify if the symbol was built with relaxation + // as we do not track the state per symbol or section. However, BFD will + // always emit the relocation and so we follow suit which avoids the need to + // track that information. + if (A.isInSection() && A.getSection().getKind().isText()) + return true; + if (B.isInSection() && B.getSection().getKind().isText()) + return true; + + // Support cross-section symbolic differences ... + return A.isInSection() && B.isInSection() && + A.getSection().getName() != B.getSection().getName(); + } + + void reset() override { + static_cast(getTargetStreamer())->reset(); + MCELFStreamer::reset(); + } + +public: + RISCVELFStreamer(MCContext &C, std::unique_ptr MAB, + std::unique_ptr MOW, + std::unique_ptr MCE) + : MCELFStreamer(C, std::move(MAB), std::move(MOW), std::move(MCE)) {} + + void emitFill(const MCExpr &NumBytes, uint64_t FillValue, + SMLoc Loc) override { + emitDataMappingSymbol(); + MCObjectStreamer::emitFill(NumBytes, FillValue, Loc); + } + + void changeSection(MCSection *Section, const MCExpr *Subsection) override { + LastMappingSymbols[getCurrentSection().first] = std::move(LastEMSInfo); + MCELFStreamer::changeSection(Section, Subsection); + auto LastMappingSymbol = LastMappingSymbols.find(Section); + if (LastMappingSymbol != LastMappingSymbols.end()) { + LastEMSInfo = std::move(LastMappingSymbol->second); + return; + } + LastEMSInfo.reset(new ElfMappingSymbolInfo(SMLoc(), nullptr, EMS_None)); + } + + void setAttributeItem(unsigned Attribute, StringRef Value, + bool OverwriteExisting) { + if (Attribute == 5) + ChangeISAMappingSymbol(Value); + } + + void emitValueImpl(const MCExpr *Value, unsigned Size, SMLoc Loc) override { + emitDataMappingSymbol(); + const MCExpr *A, *B; + if (!requiresFixups(getContext(), Value, A, B)) + return MCELFStreamer::emitValueImpl(Value, Size, Loc); + + MCStreamer::emitValueImpl(Value, Size, Loc); + + MCDataFragment *DF = getOrCreateDataFragment(); + flushPendingLabels(DF, DF->getContents().size()); + MCDwarfLineEntry::make(this, getCurrentSectionOnly()); + + unsigned Add, Sub; + std::tie(Add, Sub) = getRelocPairForSize(Size); + + DF->getFixups().push_back(MCFixup::create( + DF->getContents().size(), A, static_cast(Add), Loc)); + DF->getFixups().push_back(MCFixup::create( + DF->getContents().size(), B, static_cast(Sub), Loc)); + + DF->getContents().resize(DF->getContents().size() + Size, 0); + } + + /// This function is the one used to emit instruction data into the ELF + /// streamer. We override it to add the appropriate mapping symbol if + /// necessary. + void emitInstruction(const MCInst &Inst, + const MCSubtargetInfo &STI) override { + EmitISAMappingSymbol(); + MCELFStreamer::emitInstruction(Inst, STI); + } + + /// This is one of the functions used to emit data into an ELF section, so the + /// RISCV streamer overrides it to add the appropriate mapping symbol ($d) if + /// necessary. + void emitBytes(StringRef Data) override { + emitDataMappingSymbol(); + MCELFStreamer::emitBytes(Data); + } + +private: + enum ElfMappingSymbol { EMS_None, EMS_ISA, EMS_Change, EMS_Data }; + + struct ElfMappingSymbolInfo { + explicit ElfMappingSymbolInfo(SMLoc Loc, MCFragment *F, uint64_t O) + : Loc(Loc), F(F), Offset(O), State(EMS_None) {} + void resetInfo() { + F = nullptr; + Offset = 0; + } + bool hasInfo() { return F != nullptr; } + SMLoc Loc; + MCFragment *F; + uint64_t Offset; + ElfMappingSymbol State; + std::string ISAInfo; + }; + + void emitDataMappingSymbol() { + if (LastEMSInfo->State == EMS_Data) + return; + else if (LastEMSInfo->State == EMS_None) { + ElfMappingSymbolInfo *EMS = LastEMSInfo.get(); + auto *DF = dyn_cast_or_null(getCurrentFragment()); + if (!DF) + return; + EMS->Loc = SMLoc(); + EMS->F = getCurrentFragment(); + EMS->Offset = DF->getContents().size(); + LastEMSInfo->State = EMS_Data; + return; + } + EmitMappingSymbol("$d"); + LastEMSInfo->State = EMS_Data; + } + + void FlushPendingMappingSymbol() { + if (!LastEMSInfo->hasInfo()) + return; + ElfMappingSymbolInfo *EMS = LastEMSInfo.get(); + EmitMappingSymbol("$d", EMS->Loc, EMS->F, EMS->Offset); + EMS->resetInfo(); + } + + void ChangeISAMappingSymbol(StringRef arch) { + if (arch != LastEMSInfo->ISAInfo) { + LastEMSInfo->State = EMS_Change; + LastEMSInfo->ISAInfo = std::string(arch); + } + } + + void EmitISAMappingSymbol() { + if (LastEMSInfo->State == EMS_ISA) + return; + FlushPendingMappingSymbol(); + if (LastEMSInfo->ISAInfo.empty()) + EmitMappingSymbol("$x"); + else + EmitMappingSymbol("$x<" + LastEMSInfo->ISAInfo + ">"); + LastEMSInfo->State = EMS_ISA; + } + + void EmitMappingSymbol(StringRef Name, SMLoc Loc, MCFragment *F, + uint64_t Offset) { + auto *Symbol = cast(getContext().getOrCreateSymbol( + Name + "." + Twine(MappingSymbolCounter++))); + emitLabelAtPos(Symbol, Loc, F, Offset); + Symbol->setType(ELF::STT_NOTYPE); + Symbol->setBinding(ELF::STB_LOCAL); + } + + void EmitMappingSymbol(StringRef Name) { + auto *Symbol = cast(getContext().getOrCreateSymbol( + Name + "." + Twine(MappingSymbolCounter++))); + getAssembler().registerSymbol(*Symbol); + Symbol->setType(ELF::STT_NOTYPE); + Symbol->setBinding(ELF::STB_LOCAL); + } + + int64_t MappingSymbolCounter = 0; + + DenseMap> + LastMappingSymbols; + + std::unique_ptr LastEMSInfo; +}; +} // namespace + +MCELFStreamer &RISCVTargetELFStreamer::getStreamer() { + return static_cast(Streamer); +} // This part is for ELF object output. RISCVTargetELFStreamer::RISCVTargetELFStreamer(MCStreamer &S, const MCSubtargetInfo &STI) @@ -39,10 +261,6 @@ MAB.getTargetOptions().getABIName())); } -MCELFStreamer &RISCVTargetELFStreamer::getStreamer() { - return static_cast(Streamer); -} - void RISCVTargetELFStreamer::emitDirectiveOptionPush() {} void RISCVTargetELFStreamer::emitDirectiveOptionPop() {} void RISCVTargetELFStreamer::emitDirectiveOptionPIC() {} @@ -59,6 +277,8 @@ void RISCVTargetELFStreamer::emitTextAttribute(unsigned Attribute, StringRef String) { setAttributeItem(Attribute, String, /*OverwriteExisting=*/true); + static_cast(getStreamer()) + .setAttributeItem(Attribute, String, true); } void RISCVTargetELFStreamer::emitIntTextAttribute(unsigned Attribute, @@ -187,98 +407,6 @@ Contents.clear(); } -namespace { -class RISCVELFStreamer : public MCELFStreamer { - static std::pair getRelocPairForSize(unsigned Size) { - switch (Size) { - default: - llvm_unreachable("unsupported fixup size"); - case 1: - return std::make_pair(RISCV::fixup_riscv_add_8, RISCV::fixup_riscv_sub_8); - case 2: - return std::make_pair(RISCV::fixup_riscv_add_16, - RISCV::fixup_riscv_sub_16); - case 4: - return std::make_pair(RISCV::fixup_riscv_add_32, - RISCV::fixup_riscv_sub_32); - case 8: - return std::make_pair(RISCV::fixup_riscv_add_64, - RISCV::fixup_riscv_sub_64); - } - } - - static bool requiresFixups(MCContext &C, const MCExpr *Value, - const MCExpr *&LHS, const MCExpr *&RHS) { - const auto *MBE = dyn_cast(Value); - if (MBE == nullptr) - return false; - - MCValue E; - if (!Value->evaluateAsRelocatable(E, nullptr, nullptr)) - return false; - if (E.getSymA() == nullptr || E.getSymB() == nullptr) - return false; - - const auto &A = E.getSymA()->getSymbol(); - const auto &B = E.getSymB()->getSymbol(); - - LHS = - MCBinaryExpr::create(MCBinaryExpr::Add, MCSymbolRefExpr::create(&A, C), - MCConstantExpr::create(E.getConstant(), C), C); - RHS = E.getSymB(); - - // If either symbol is in a text section, we need to delay the relocation - // evaluation as relaxation may alter the size of the symbol. - // - // Unfortunately, we cannot identify if the symbol was built with relaxation - // as we do not track the state per symbol or section. However, BFD will - // always emit the relocation and so we follow suit which avoids the need to - // track that information. - if (A.isInSection() && A.getSection().getKind().isText()) - return true; - if (B.isInSection() && B.getSection().getKind().isText()) - return true; - - // Support cross-section symbolic differences ... - return A.isInSection() && B.isInSection() && - A.getSection().getName() != B.getSection().getName(); - } - - void reset() override { - static_cast(getTargetStreamer())->reset(); - MCELFStreamer::reset(); - } - -public: - RISCVELFStreamer(MCContext &C, std::unique_ptr MAB, - std::unique_ptr MOW, - std::unique_ptr MCE) - : MCELFStreamer(C, std::move(MAB), std::move(MOW), std::move(MCE)) {} - - void emitValueImpl(const MCExpr *Value, unsigned Size, SMLoc Loc) override { - const MCExpr *A, *B; - if (!requiresFixups(getContext(), Value, A, B)) - return MCELFStreamer::emitValueImpl(Value, Size, Loc); - - MCStreamer::emitValueImpl(Value, Size, Loc); - - MCDataFragment *DF = getOrCreateDataFragment(); - flushPendingLabels(DF, DF->getContents().size()); - MCDwarfLineEntry::make(this, getCurrentSectionOnly()); - - unsigned Add, Sub; - std::tie(Add, Sub) = getRelocPairForSize(Size); - - DF->getFixups().push_back(MCFixup::create( - DF->getContents().size(), A, static_cast(Add), Loc)); - DF->getFixups().push_back(MCFixup::create( - DF->getContents().size(), B, static_cast(Sub), Loc)); - - DF->getContents().resize(DF->getContents().size() + Size, 0); - } -}; -} // namespace - namespace llvm { MCELFStreamer *createRISCVELFStreamer(MCContext &C, std::unique_ptr MAB, diff --git a/llvm/test/MC/RISCV/Inputs/1.s b/llvm/test/MC/RISCV/Inputs/1.s new file mode 100644 --- /dev/null +++ b/llvm/test/MC/RISCV/Inputs/1.s @@ -0,0 +1,3 @@ + .section .foobar,"ax",%progbits + nop + .word 32 diff --git a/llvm/test/MC/RISCV/Inputs/2.s b/llvm/test/MC/RISCV/Inputs/2.s new file mode 100644 --- /dev/null +++ b/llvm/test/MC/RISCV/Inputs/2.s @@ -0,0 +1,3 @@ + .section .foobar,"",%progbits + nop + .word 32 diff --git a/llvm/test/MC/RISCV/Inputs/3.s b/llvm/test/MC/RISCV/Inputs/3.s new file mode 100644 --- /dev/null +++ b/llvm/test/MC/RISCV/Inputs/3.s @@ -0,0 +1,3 @@ + .section .foobar,"aw",%progbits + nop + .word 32 diff --git a/llvm/test/MC/RISCV/Inputs/4.s b/llvm/test/MC/RISCV/Inputs/4.s new file mode 100644 --- /dev/null +++ b/llvm/test/MC/RISCV/Inputs/4.s @@ -0,0 +1,2 @@ + .section .foobar,"",%progbits + .word 32 diff --git a/llvm/test/MC/RISCV/Inputs/5.s b/llvm/test/MC/RISCV/Inputs/5.s new file mode 100644 --- /dev/null +++ b/llvm/test/MC/RISCV/Inputs/5.s @@ -0,0 +1,2 @@ + .section .foobar,"aw",%progbits + .word 32 diff --git a/llvm/test/MC/RISCV/Inputs/6.s b/llvm/test/MC/RISCV/Inputs/6.s new file mode 100644 --- /dev/null +++ b/llvm/test/MC/RISCV/Inputs/6.s @@ -0,0 +1,12 @@ + .section .foo + .word 30 + .word 31 + .word 32 + .word 33 + nop + .word 34 + .word 35 + .word 36 + .word 37 + .word 38 + nop diff --git a/llvm/test/MC/RISCV/Inputs/7.s b/llvm/test/MC/RISCV/Inputs/7.s new file mode 100644 --- /dev/null +++ b/llvm/test/MC/RISCV/Inputs/7.s @@ -0,0 +1,3 @@ + .section .foobar,"aw",%progbits + .word 32 + nop diff --git a/llvm/test/MC/RISCV/Inputs/ident.s b/llvm/test/MC/RISCV/Inputs/ident.s new file mode 100644 --- /dev/null +++ b/llvm/test/MC/RISCV/Inputs/ident.s @@ -0,0 +1 @@ + .ident "LLVM RISCV Compiler" diff --git a/llvm/test/MC/RISCV/mapping-isa.s b/llvm/test/MC/RISCV/mapping-isa.s new file mode 100644 --- /dev/null +++ b/llvm/test/MC/RISCV/mapping-isa.s @@ -0,0 +1,312 @@ +## Arch string with mapping symbols. + +# RUN: llvm-mc -triple=riscv32 -filetype=obj -o %t.o %s +# RUN: llvm-objdump -t %t.o | FileCheck %s -check-prefix=MAPPINGSYMBOLS +# RUN: llvm-mc -triple=riscv64 -filetype=obj -o %t.o %s +# RUN: llvm-objdump -t %t.o | FileCheck %s -check-prefix=MAPPINGSYMBOLS + +nop +.word 32 +# MAPPINGSYMBOLS: $x + +.attribute arch, "rv32i" +nop +.word 32 +# MAPPINGSYMBOLS: $x + +.attribute arch, "rv32i2" +nop +.word 32 +# MAPPINGSYMBOLS: $x + +.attribute arch, "rv32i2p0" +nop +.word 32 +# MAPPINGSYMBOLS: $x + +.attribute arch, "rv32i2_m2" +nop +.word 32 +# MAPPINGSYMBOLS: $x + +.attribute arch, "rv32i2_ma" +nop +.word 32 +# MAPPINGSYMBOLS: $x + +.attribute arch, "rv32g" +nop +.word 32 +# MAPPINGSYMBOLS: $x + +.attribute arch, "rv32imafdc" +nop +.word 32 +# MAPPINGSYMBOLS: $x + +.attribute arch, "rv32i2p0_mafdc" +nop +.word 32 +# MAPPINGSYMBOLS: $x + +.attribute arch, "rv32ima2p0_fdc" +nop +.word 32 +# MAPPINGSYMBOLS: $x + +.attribute arch, "rv32ima2p0_fdc" +nop +.word 32 +# MAPPINGSYMBOLS: $x + +.attribute arch, "rv32iv" +nop +.word 32 +# MAPPINGSYMBOLS: $x + +.attribute arch, "rv32ivzvl32b" +nop +.word 32 +# MAPPINGSYMBOLS: $x + +.attribute arch, "rv32ivzvl64b" +nop +.word 32 +# MAPPINGSYMBOLS: $x + +.attribute arch, "rv32ivzvl128b" +nop +.word 32 +# MAPPINGSYMBOLS: $x + +.attribute arch, "rv32ivzvl256b" +nop +.word 32 +# MAPPINGSYMBOLS: $x + +.attribute arch, "rv32ivzvl512b" +nop +.word 32 +# MAPPINGSYMBOLS: $x + +.attribute arch, "rv32ivzvl1024b" +nop +.word 32 +# MAPPINGSYMBOLS: $x + +.attribute arch, "rv32ivzvl2048b" +nop +.word 32 +# MAPPINGSYMBOLS: $x + +.attribute arch, "rv32ivzvl4096b" +nop +.word 32 +# MAPPINGSYMBOLS: $x + +.attribute arch, "rv32ivzvl8192b" +nop +.word 32 +# MAPPINGSYMBOLS: $x + +.attribute arch, "rv32ivzvl16384b" +nop +.word 32 +# MAPPINGSYMBOLS: $x + +.attribute arch, "rv32ivzvl32768b" +nop +.word 32 +# MAPPINGSYMBOLS: $x + +.attribute arch, "rv32ivzvl65536b" +nop +.word 32 +# MAPPINGSYMBOLS: $x + +.attribute arch, "rv32izve32x" +nop +.word 32 +# MAPPINGSYMBOLS: $x + +.attribute arch, "rv32ifzve32f" +nop +.word 32 +# MAPPINGSYMBOLS: $x + +.attribute arch, "rv32izve64x" +nop +.word 32 +# MAPPINGSYMBOLS: $x + +.attribute arch, "rv32ifzve64f" +nop +.word 32 +# MAPPINGSYMBOLS: $x + +.attribute arch, "rv32ifdzve64d" +nop +.word 32 +# MAPPINGSYMBOLS: $x + +.attribute arch, "rv32izicbom" +nop +.word 32 +# MAPPINGSYMBOLS: $x + +.attribute arch, "rv32izicboz" +nop +.word 32 +# MAPPINGSYMBOLS: $x + +.attribute arch, "rv32izicbop" +nop +.word 32 +# MAPPINGSYMBOLS: $x + +## Experimental extensions require version string to be explicitly specified + +.attribute arch, "rv32izba1p0" +nop +.word 32 +# MAPPINGSYMBOLS: $x + +.attribute arch, "rv32izbb1p0" +nop +.word 32 +# MAPPINGSYMBOLS: $x + +.attribute arch, "rv32izbc1p0" +nop +.word 32 +# MAPPINGSYMBOLS: $x + +.attribute arch, "rv32izbs1p0" +nop +.word 32 +# MAPPINGSYMBOLS: $x + +.attribute arch, "rv32ifzfhmin1p0" +nop +.word 32 +# MAPPINGSYMBOLS: $x + +.attribute arch, "rv32ifzfh1p0" +nop +.word 32 +# MAPPINGSYMBOLS: $x + +.attribute arch, "rv32izfinx" +nop +.word 32 +# MAPPINGSYMBOLS: $x + +.attribute arch, "rv32izfinx_zdinx" +nop +.word 32 +# MAPPINGSYMBOLS: $x + +.attribute arch, "rv32izfinx_zhinxmin" +nop +.word 32 +# MAPPINGSYMBOLS: $x + +.attribute arch, "rv32izfinx_zhinx1p0" +nop +.word 32 +# MAPPINGSYMBOLS: $x + +.attribute arch, "rv32i_zbkb1p0" +nop +.word 32 +# MAPPINGSYMBOLS: $x + +.attribute arch, "rv32i_zbkc1p0" +nop +.word 32 +# MAPPINGSYMBOLS: $x + +.attribute arch, "rv32i_zbkx1p0" +nop +.word 32 +# MAPPINGSYMBOLS: $x + +.attribute arch, "rv32i_zknd1p0" +nop +.word 32 +# MAPPINGSYMBOLS: $x + +.attribute arch, "rv32i_zkne1p0" +nop +.word 32 +# MAPPINGSYMBOLS: $x + +.attribute arch, "rv32i_zknh1p0" +nop +.word 32 +# MAPPINGSYMBOLS: $x + +.attribute arch, "rv32i_zksed1p0" +nop +.word 32 +# MAPPINGSYMBOLS: $x + +.attribute arch, "rv32i_zksh1p0" +nop +.word 32 +# MAPPINGSYMBOLS: $x + +.attribute arch, "rv32i_zkr1p0" +nop +.word 32 +# MAPPINGSYMBOLS: $x + +.attribute arch, "rv32i_zkn1p0" +nop +.word 32 +# MAPPINGSYMBOLS: $x + +.attribute arch, "rv32i_zks1p0" +nop +.word 32 +# MAPPINGSYMBOLS: $x + +.attribute arch, "rv32i_zkt1p0" +nop +.word 32 +# MAPPINGSYMBOLS: $x + +.attribute arch, "rv32i_zk1p0" +nop +.word 32 +# MAPPINGSYMBOLS: $x + +.attribute arch, "rv32izihintntl0p2" +nop +.word 32 +# MAPPINGSYMBOLS: $x + +.attribute arch, "rv32iczihintntl0p2" +nop +.word 32 +# MAPPINGSYMBOLS: $x + +.attribute arch, "rv32if_zkt1p0_zve32f1p0_zve32x1p0_zvl32b1p0" +nop +.word 32 +# MAPPINGSYMBOLS: $x + +.attribute arch, "rv32izca0p70" +nop +.word 32 +# MAPPINGSYMBOLS: $x + +.attribute arch, "rv32izawrs1p0" +nop +.word 32 +# MAPPINGSYMBOLS: $x + +.attribute arch, "rv32iztso0p1" +nop +.word 32 +# MAPPINGSYMBOLS: $x diff --git a/llvm/test/MC/RISCV/mapping-symbols.s b/llvm/test/MC/RISCV/mapping-symbols.s new file mode 100644 --- /dev/null +++ b/llvm/test/MC/RISCV/mapping-symbols.s @@ -0,0 +1,44 @@ +# Check section containing code and data with permission executable for the section. +# RUN: llvm-mc -triple=riscv64 -filetype=obj -o %t.o %p/Inputs/1.s +# RUN: llvm-readelf -s %t.o | FileCheck %s + +# Check section containing code and data with no permissions for the section. +# RUN: llvm-mc -triple=riscv64 -filetype=obj -o %t.o %p/Inputs/2.s +# RUN: llvm-readelf -s %t.o | FileCheck %s + +# Check section containing code and data with read/write permissions for the section. +# RUN: llvm-mc -triple=riscv64 -filetype=obj -o %t.o %p/Inputs/3.s +# RUN: llvm-readelf -s %t.o | FileCheck %s + +# Check section containing data with no permissions for the section. +# RUN: llvm-mc -triple=riscv64 -filetype=obj -o %t.o %p/Inputs/4.s +# RUN: llvm-readelf -s %t.o | FileCheck %s -check-prefix=MAPPINGSYMBOLS + +# Check section containing only data with read/write permissions for the section. +# RUN: llvm-mc -triple=riscv64 -filetype=obj -o %t.o %p/Inputs/5.s +# RUN: llvm-readelf -s %t.o | FileCheck %s -check-prefix=MAPPINGSYMBOLS + +# Check section containing the ident string with no permissions for the section. +# RUN: llvm-mc -triple=riscv64 -filetype=obj -o %t.o %p/Inputs/ident.s +# RUN: llvm-readelf -s %t.o | FileCheck %s -check-prefix=MAPPINGSYMBOLS + +# Check section containing code and data with no permissions for the section. +# data comes before code. +# RUN: llvm-mc -triple=riscv64 -filetype=obj -o %t.o %p/Inputs/6.s +# RUN: llvm-readelf -s %t.o | FileCheck %s -check-prefix=MIX + +# Check section containing code and data with no permissions for the section. +# data comes before code. +# RUN: llvm-mc -triple=riscv64 -filetype=obj -o %t.o %p/Inputs/7.s +# RUN: llvm-readelf -s %t.o | FileCheck %s + +#CHECK-DAG: $x +#CHECK-DAG: $d + +#MIX: $d +#MIX: $x +#MIX: $d +#MIX: $x + +#MAPPINGSYMBOLS-NOT: $x +#MAPPINGSYMBOLS-NOT: $d diff --git a/llvm/tools/llvm-objdump/llvm-objdump.cpp b/llvm/tools/llvm-objdump/llvm-objdump.cpp --- a/llvm/tools/llvm-objdump/llvm-objdump.cpp +++ b/llvm/tools/llvm-objdump/llvm-objdump.cpp @@ -458,8 +458,14 @@ return Elf && Elf->getEMachine() == ELF::EM_CSKY; } +static bool isRISCVElf(const ObjectFile &Obj) { + const auto *Elf = dyn_cast(&Obj); + return Elf && Elf->getEMachine() == ELF::EM_RISCV; +} + static bool hasMappingSymbols(const ObjectFile &Obj) { - return isArmElf(Obj) || isAArch64Elf(Obj) || isCSKYElf(Obj) ; + return isArmElf(Obj) || isAArch64Elf(Obj) || isCSKYElf(Obj) || + isRISCVElf(Obj); } static void printRelocation(formatted_raw_ostream &OS, StringRef FileName,