From 320848458b5da8f5a41ca9aa51a05ffad36eda1a Mon Sep 17 00:00:00 2001 From: Weiming Zhao Date: Tue, 28 Mar 2017 05:40:36 +0000 Subject: [PATCH] Dont emit Mapping symbols for sections that contain only data. Summary: Dont emit mapping symbols for sections that contain only data. Patched by Shankar Easwaran Reviewers: rengolin, peter.smith, weimingz, kparzysz, t.p.northover Reviewed By: t.p.northover Subscribers: t.p.northover, llvm-commits Differential Revision: https://reviews.llvm.org/D30724 llvm-svn: 298901 --- llvm/include/llvm/MC/MCELFStreamer.h | 1 + llvm/include/llvm/MC/MCObjectStreamer.h | 1 + llvm/lib/MC/MCELFStreamer.cpp | 10 +++ llvm/lib/MC/MCObjectStreamer.cpp | 18 +++- .../ARM/MCTargetDesc/ARMELFStreamer.cpp | 82 +++++++++++++++---- llvm/test/MC/ARM/Inputs/1.s | 3 + llvm/test/MC/ARM/Inputs/2.s | 3 + llvm/test/MC/ARM/Inputs/3.s | 3 + llvm/test/MC/ARM/Inputs/4.s | 2 + llvm/test/MC/ARM/Inputs/5.s | 2 + llvm/test/MC/ARM/Inputs/6.s | 12 +++ llvm/test/MC/ARM/Inputs/7.s | 3 + llvm/test/MC/ARM/Inputs/attr.s | 5 ++ llvm/test/MC/ARM/Inputs/ident.s | 1 + llvm/test/MC/ARM/data-in-code.ll | 17 ---- llvm/test/MC/ARM/mappingsymbols.s | 48 +++++++++++ llvm/test/MC/ARM/multi-section-mapping.s | 1 - llvm/test/Object/ARM/nm-mapping-symbol.s | 1 + 18 files changed, 177 insertions(+), 36 deletions(-) create mode 100644 llvm/test/MC/ARM/Inputs/1.s create mode 100644 llvm/test/MC/ARM/Inputs/2.s create mode 100644 llvm/test/MC/ARM/Inputs/3.s create mode 100644 llvm/test/MC/ARM/Inputs/4.s create mode 100644 llvm/test/MC/ARM/Inputs/5.s create mode 100644 llvm/test/MC/ARM/Inputs/6.s create mode 100644 llvm/test/MC/ARM/Inputs/7.s create mode 100644 llvm/test/MC/ARM/Inputs/attr.s create mode 100644 llvm/test/MC/ARM/Inputs/ident.s create mode 100644 llvm/test/MC/ARM/mappingsymbols.s diff --git a/llvm/include/llvm/MC/MCELFStreamer.h b/llvm/include/llvm/MC/MCELFStreamer.h index ea9ade459e07..90434f34da5f 100644 --- a/llvm/include/llvm/MC/MCELFStreamer.h +++ b/llvm/include/llvm/MC/MCELFStreamer.h @@ -42,6 +42,7 @@ public: void InitSections(bool NoExecStack) override; void ChangeSection(MCSection *Section, const MCExpr *Subsection) override; void EmitLabel(MCSymbol *Symbol, SMLoc Loc = SMLoc()) override; + void EmitLabel(MCSymbol *Symbol, SMLoc Loc, MCFragment *F) override; void EmitAssemblerFlag(MCAssemblerFlag Flag) override; void EmitThumbFunc(MCSymbol *Func) override; void EmitWeakReference(MCSymbol *Alias, const MCSymbol *Symbol) override; diff --git a/llvm/include/llvm/MC/MCObjectStreamer.h b/llvm/include/llvm/MC/MCObjectStreamer.h index 978a24095267..11f8dfa24484 100644 --- a/llvm/include/llvm/MC/MCObjectStreamer.h +++ b/llvm/include/llvm/MC/MCObjectStreamer.h @@ -90,6 +90,7 @@ public: /// @{ void EmitLabel(MCSymbol *Symbol, SMLoc Loc = SMLoc()) override; + virtual void EmitLabel(MCSymbol *Symbol, SMLoc Loc, MCFragment *F); void EmitAssignment(MCSymbol *Symbol, const MCExpr *Value) override; void EmitValueImpl(const MCExpr *Value, unsigned Size, SMLoc Loc = SMLoc()) override; diff --git a/llvm/lib/MC/MCELFStreamer.cpp b/llvm/lib/MC/MCELFStreamer.cpp index de0791281d29..c8e0223c0573 100644 --- a/llvm/lib/MC/MCELFStreamer.cpp +++ b/llvm/lib/MC/MCELFStreamer.cpp @@ -103,6 +103,16 @@ void MCELFStreamer::EmitLabel(MCSymbol *S, SMLoc Loc) { Symbol->setType(ELF::STT_TLS); } +void MCELFStreamer::EmitLabel(MCSymbol *S, SMLoc Loc, MCFragment *F) { + auto *Symbol = cast(S); + MCObjectStreamer::EmitLabel(Symbol, Loc, F); + + const MCSectionELF &Section = + static_cast(*getCurrentSectionOnly()); + if (Section.getFlags() & ELF::SHF_TLS) + Symbol->setType(ELF::STT_TLS); +} + void MCELFStreamer::EmitAssemblerFlag(MCAssemblerFlag Flag) { // Let the target do whatever target specific stuff it needs to do. getAssembler().getBackend().handleAssemblerFlag(Flag); diff --git a/llvm/lib/MC/MCObjectStreamer.cpp b/llvm/lib/MC/MCObjectStreamer.cpp index 8f502fc3e2f8..726326be2ee1 100644 --- a/llvm/lib/MC/MCObjectStreamer.cpp +++ b/llvm/lib/MC/MCObjectStreamer.cpp @@ -171,6 +171,16 @@ void MCObjectStreamer::EmitLabel(MCSymbol *Symbol, SMLoc Loc) { } } +void MCObjectStreamer::EmitLabel(MCSymbol *Symbol, SMLoc Loc, MCFragment *F) { + MCStreamer::EmitLabel(Symbol, Loc); + getAssembler().registerSymbol(*Symbol); + auto *DF = dyn_cast_or_null(F); + if (DF) + Symbol->setFragment(F); + else + PendingLabels.push_back(Symbol); +} + void MCObjectStreamer::EmitULEB128Value(const MCExpr *Value) { int64_t IntValue; if (Value->evaluateAsAbsolute(IntValue, getAssembler())) { @@ -491,8 +501,8 @@ void MCObjectStreamer::EmitGPRel32Value(const MCExpr *Value) { MCDataFragment *DF = getOrCreateDataFragment(); flushPendingLabels(DF, DF->getContents().size()); - DF->getFixups().push_back(MCFixup::create(DF->getContents().size(), - Value, FK_GPRel_4)); + DF->getFixups().push_back( + MCFixup::create(DF->getContents().size(), Value, FK_GPRel_4)); DF->getContents().resize(DF->getContents().size() + 4, 0); } @@ -501,8 +511,8 @@ void MCObjectStreamer::EmitGPRel64Value(const MCExpr *Value) { MCDataFragment *DF = getOrCreateDataFragment(); flushPendingLabels(DF, DF->getContents().size()); - DF->getFixups().push_back(MCFixup::create(DF->getContents().size(), - Value, FK_GPRel_4)); + DF->getFixups().push_back( + MCFixup::create(DF->getContents().size(), Value, FK_GPRel_4)); DF->getContents().resize(DF->getContents().size() + 8, 0); } diff --git a/llvm/lib/Target/ARM/MCTargetDesc/ARMELFStreamer.cpp b/llvm/lib/Target/ARM/MCTargetDesc/ARMELFStreamer.cpp index f7bdda491cbb..2959f982c432 100644 --- a/llvm/lib/Target/ARM/MCTargetDesc/ARMELFStreamer.cpp +++ b/llvm/lib/Target/ARM/MCTargetDesc/ARMELFStreamer.cpp @@ -464,13 +464,14 @@ public: void emitUnwindRaw(int64_t Offset, const SmallVectorImpl &Opcodes); void ChangeSection(MCSection *Section, const MCExpr *Subsection) override { - // 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); - + LastMappingSymbols[getPreviousSection().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, 0)); } /// This function is the one used to emit instruction data into the ELF @@ -532,6 +533,14 @@ public: MCELFStreamer::EmitBytes(Data); } + void FlushPendingMappingSymbol() { + if (!LastEMSInfo->hasInfo()) + return; + ElfMappingSymbolInfo *EMS = LastEMSInfo.get(); + EmitMappingSymbol("$d", EMS->Loc, EMS->F, EMS->Offset); + EMS->resetInfo(); + } + /// This is one of the functions used to emit data into an ELF section, so the /// ARM streamer overrides it to add the appropriate mapping symbol ($d) if /// necessary. @@ -573,22 +582,54 @@ private: 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; + }; + void EmitDataMappingSymbol() { - if (LastEMS == EMS_Data) return; + if (LastEMSInfo->State == EMS_Data) + return; + else if (LastEMSInfo->State == EMS_None) { + // This is a tentative symbol, it won't really be emitted until it's + // actually needed. + 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"); - LastEMS = EMS_Data; + LastEMSInfo->State = EMS_Data; } void EmitThumbMappingSymbol() { - if (LastEMS == EMS_Thumb) return; + if (LastEMSInfo->State == EMS_Thumb) + return; + FlushPendingMappingSymbol(); EmitMappingSymbol("$t"); - LastEMS = EMS_Thumb; + LastEMSInfo->State = EMS_Thumb; } void EmitARMMappingSymbol() { - if (LastEMS == EMS_ARM) return; + if (LastEMSInfo->State == EMS_ARM) + return; + FlushPendingMappingSymbol(); EmitMappingSymbol("$a"); - LastEMS = EMS_ARM; + LastEMSInfo->State = EMS_ARM; } void EmitMappingSymbol(StringRef Name) { @@ -601,6 +642,17 @@ private: Symbol->setExternal(false); } + void EmitMappingSymbol(StringRef Name, SMLoc Loc, MCFragment *F, + uint64_t Offset) { + auto *Symbol = cast(getContext().getOrCreateSymbol( + Name + "." + Twine(MappingSymbolCounter++))); + EmitLabel(Symbol, Loc, F); + Symbol->setType(ELF::STT_NOTYPE); + Symbol->setBinding(ELF::STB_LOCAL); + Symbol->setExternal(false); + Symbol->setOffset(Offset); + } + void EmitThumbFunc(MCSymbol *Func) override { getAssembler().setIsThumbFunc(Func); EmitSymbolAttribute(Func, MCSA_ELF_TypeFunction); @@ -626,8 +678,10 @@ private: bool IsThumb; int64_t MappingSymbolCounter = 0; - DenseMap LastMappingSymbols; - ElfMappingSymbol LastEMS = EMS_None; + DenseMap> + LastMappingSymbols; + + std::unique_ptr LastEMSInfo; // ARM Exception Handling Frame Information MCSymbol *ExTab; diff --git a/llvm/test/MC/ARM/Inputs/1.s b/llvm/test/MC/ARM/Inputs/1.s new file mode 100644 index 000000000000..0afcc633f641 --- /dev/null +++ b/llvm/test/MC/ARM/Inputs/1.s @@ -0,0 +1,3 @@ + .section .foobar,"ax",%progbits + nop + .word 32 diff --git a/llvm/test/MC/ARM/Inputs/2.s b/llvm/test/MC/ARM/Inputs/2.s new file mode 100644 index 000000000000..0ecdb294ab86 --- /dev/null +++ b/llvm/test/MC/ARM/Inputs/2.s @@ -0,0 +1,3 @@ + .section .foobar,"",%progbits + nop + .word 32 diff --git a/llvm/test/MC/ARM/Inputs/3.s b/llvm/test/MC/ARM/Inputs/3.s new file mode 100644 index 000000000000..09392623fc10 --- /dev/null +++ b/llvm/test/MC/ARM/Inputs/3.s @@ -0,0 +1,3 @@ + .section .foobar,"aw",%progbits + nop + .word 32 diff --git a/llvm/test/MC/ARM/Inputs/4.s b/llvm/test/MC/ARM/Inputs/4.s new file mode 100644 index 000000000000..28d8244bb417 --- /dev/null +++ b/llvm/test/MC/ARM/Inputs/4.s @@ -0,0 +1,2 @@ + .section .foobar,"",%progbits + .word 32 diff --git a/llvm/test/MC/ARM/Inputs/5.s b/llvm/test/MC/ARM/Inputs/5.s new file mode 100644 index 000000000000..1faef539b135 --- /dev/null +++ b/llvm/test/MC/ARM/Inputs/5.s @@ -0,0 +1,2 @@ + .section .foobar,"aw",%progbits + .word 32 diff --git a/llvm/test/MC/ARM/Inputs/6.s b/llvm/test/MC/ARM/Inputs/6.s new file mode 100644 index 000000000000..0fdb9daaf295 --- /dev/null +++ b/llvm/test/MC/ARM/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/ARM/Inputs/7.s b/llvm/test/MC/ARM/Inputs/7.s new file mode 100644 index 000000000000..b92a61ec971f --- /dev/null +++ b/llvm/test/MC/ARM/Inputs/7.s @@ -0,0 +1,3 @@ + .section .foobar,"aw",%progbits + .word 32 + nop diff --git a/llvm/test/MC/ARM/Inputs/attr.s b/llvm/test/MC/ARM/Inputs/attr.s new file mode 100644 index 000000000000..412cad768425 --- /dev/null +++ b/llvm/test/MC/ARM/Inputs/attr.s @@ -0,0 +1,5 @@ + .text + .syntax unified + .eabi_attribute 67, "2.09" @ Tag_conformance + .cpu arm7tdmi + .eabi_attribute 6, 2 @ Tag_CPU_arch diff --git a/llvm/test/MC/ARM/Inputs/ident.s b/llvm/test/MC/ARM/Inputs/ident.s new file mode 100644 index 000000000000..19d65fcc7e07 --- /dev/null +++ b/llvm/test/MC/ARM/Inputs/ident.s @@ -0,0 +1 @@ + .ident "LLVM ARM Compiler" diff --git a/llvm/test/MC/ARM/data-in-code.ll b/llvm/test/MC/ARM/data-in-code.ll index c2194e9179c8..e579146acfb3 100644 --- a/llvm/test/MC/ARM/data-in-code.ll +++ b/llvm/test/MC/ARM/data-in-code.ll @@ -60,23 +60,6 @@ exit: ;; ARM-NEXT: Other: ;; ARM-NEXT: Section: [[MIXED_SECT]] -;; ARM: Symbol { -;; ARM: Name: $d -;; ARM-NEXT: Value: 0x0 -;; ARM-NEXT: Size: 0 -;; ARM-NEXT: Binding: Local (0x0) -;; ARM-NEXT: Type: None (0x0) -;; ARM-NEXT: Other: 0 -;; ARM-NEXT: Section: .ARM.exidx -;; ARM-NEXT: } - -;; ARM: Symbol { -;; ARM: Name: $d -;; ARM-NEXT: Value: 0 -;; ARM-NEXT: Size: 0 -;; ARM-NEXT: Binding: Local -;; ARM-NEXT: Type: None - ;; ARM-NOT: ${{[atd]}} ;; TMB: Symbol { diff --git a/llvm/test/MC/ARM/mappingsymbols.s b/llvm/test/MC/ARM/mappingsymbols.s new file mode 100644 index 000000000000..fff8e1047810 --- /dev/null +++ b/llvm/test/MC/ARM/mappingsymbols.s @@ -0,0 +1,48 @@ +# Check section containing code and data with permission executable for the section. +@ RUN: llvm-mc -triple armv7-none-linux -filetype=obj -o %t.o %p/Inputs/1.s +@ RUN: llvm-readobj -elf-output-style=GNU -symbols %t.o | FileCheck %s + +# Check section containing code and data with no permissions for the section. +@ RUN: llvm-mc -triple armv7-none-linux -filetype=obj -o %t.o %p/Inputs/2.s +@ RUN: llvm-readobj -elf-output-style=GNU -symbols %t.o | FileCheck %s + +# Check section containing code and data with read/write permissions for the section. +@ RUN: llvm-mc -triple armv7-none-linux -filetype=obj -o %t.o %p/Inputs/3.s +@ RUN: llvm-readobj -elf-output-style=GNU -symbols %t.o | FileCheck %s + +# Check section containing data with no permissions for the section. +@ RUN: llvm-mc -triple armv7-none-linux -filetype=obj -o %t.o %p/Inputs/4.s +@ RUN: llvm-readobj -elf-output-style=GNU -symbols %t.o | FileCheck %s -check-prefix=MAPPINGSYMBOLS + +# Check section containing only data with read/write permissions for the section. +@ RUN: llvm-mc -triple armv7-none-linux -filetype=obj -o %t.o %p/Inputs/5.s +@ RUN: llvm-readobj -elf-output-style=GNU -symbols %t.o | FileCheck %s -check-prefix=MAPPINGSYMBOLS + +# Check section containing the ident string with no permissions for the section. +@ RUN: llvm-mc -triple armv7-none-linux -filetype=obj -o %t.o %p/Inputs/ident.s +@ RUN: llvm-readobj -elf-output-style=GNU -symbols %t.o | FileCheck %s -check-prefix=MAPPINGSYMBOLS + +# Check section containing the attributes with no permissions for the section. +@ RUN: llvm-mc -triple armv7-none-linux -filetype=obj -o %t.o %p/Inputs/attr.s +@ RUN: llvm-readobj -elf-output-style=GNU -symbols %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 armv7-none-linux -filetype=obj -o %t.o %p/Inputs/6.s +@ RUN: llvm-readobj -elf-output-style=GNU -symbols %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 armv7-none-linux -filetype=obj -o %t.o %p/Inputs/7.s +@ RUN: llvm-readobj -elf-output-style=GNU -symbols %t.o | FileCheck %s + +#CHECK: $a +#CHECK: $d + +#MIX: $a +#MIX: $a +#MIX: $d +#MIX: $d + +#MAPPINGSYMBOLS-NOT: $a +#MAPPINGSYMBOLS-NOT: $d diff --git a/llvm/test/MC/ARM/multi-section-mapping.s b/llvm/test/MC/ARM/multi-section-mapping.s index 2b1b0efab53c..e4b7146e4b0f 100644 --- a/llvm/test/MC/ARM/multi-section-mapping.s +++ b/llvm/test/MC/ARM/multi-section-mapping.s @@ -29,7 +29,6 @@ @ CHECK: 00000000 .text 00000000 $a @ CHECK-NEXT: 00000000 .wibble 00000000 $a -@ CHECK-NEXT: 00000000 .starts_data 00000000 $d @ CHECK-NEXT: 00000000 .starts_thumb 00000000 $t @ CHECK-NOT: ${{[adt]}} diff --git a/llvm/test/Object/ARM/nm-mapping-symbol.s b/llvm/test/Object/ARM/nm-mapping-symbol.s index 485c1cc39d72..9b7b5b583ea0 100644 --- a/llvm/test/Object/ARM/nm-mapping-symbol.s +++ b/llvm/test/Object/ARM/nm-mapping-symbol.s @@ -9,3 +9,4 @@ .section .foobar,"",%progbits .asciz "foo" + nop