>From b53810d863ed9e4184686b4bd07b3d4eb7a0c38d Mon Sep 17 00:00:00 2001 From: Greg Fitzgerald Date: Tue, 23 Oct 2012 10:31:17 -0700 Subject: [PATCH] Added Mapping Symbols for ARM ELF Before this patch, when you objdump an LLVM-compiled file, objdump tried to decode data-in-code sections as if they were code. This patch adds the missing Mapping Symbols, as defined by "ELF for the ARM Architecture" (ARM IHI 0044D). Unit-test added at 'test/MC/ARM/data-in-code.ll' --- include/llvm/MC/MCStreamer.h | 7 ++ lib/MC/MCELFStreamer.cpp | 94 ++++++++++++++++++ lib/Target/ARM/MCTargetDesc/ARMMCTargetDesc.cpp | 3 +- test/CodeGen/ARM/2010-11-30-reloc-movt.ll | 4 +- test/MC/ARM/data-in-code.ll | 121 ++++++++++++++++++++++++ test/MC/ARM/elf-reloc-01.ll | 4 +- test/MC/ARM/elf-reloc-02.ll | 6 +- test/MC/ARM/elf-reloc-03.ll | 6 +- test/MC/ARM/elf-reloc-condcall.s | 12 +-- test/MC/ARM/elf-thumbfunc-reloc.ll | 4 +- test/MC/ARM/elf-thumbfunc.s | 4 +- 11 files changed, 244 insertions(+), 21 deletions(-) create mode 100644 test/MC/ARM/data-in-code.ll diff --git a/include/llvm/MC/MCStreamer.h b/include/llvm/MC/MCStreamer.h index 230d27e..107343a 100644 --- a/include/llvm/MC/MCStreamer.h +++ b/include/llvm/MC/MCStreamer.h @@ -626,6 +626,13 @@ namespace llvm { MCStreamer *createPureStreamer(MCContext &Ctx, MCAsmBackend &TAB, raw_ostream &OS, MCCodeEmitter *CE); + /// createARMELFStreamer - Create a machine code streamer which will generate + /// ELF format object files for ARM targets. + MCStreamer *createARMELFStreamer(MCContext &Ctx, MCAsmBackend &TAB, + raw_ostream &OS, MCCodeEmitter *CE, + bool RelaxAll, bool NoExecStack, + bool IsThumb); + } // end namespace llvm #endif diff --git a/lib/MC/MCELFStreamer.cpp b/lib/MC/MCELFStreamer.cpp index 14fbc1e..6d825ee 100644 --- a/lib/MC/MCELFStreamer.cpp +++ b/lib/MC/MCELFStreamer.cpp @@ -146,6 +146,88 @@ private: EmitCodeAlignment(4, 0); } }; + +class ARMELFStreamer : public MCELFStreamer { +public: + ARMELFStreamer(MCContext &Context, MCAsmBackend &TAB, + raw_ostream &OS, MCCodeEmitter *Emitter, bool IsThumb) + : MCELFStreamer(Context, TAB, OS, Emitter), + IsThumb(IsThumb), MappingSymbolCounter(0) { + } + + ~ARMELFStreamer() {} + + /// @name ARMELFStreamer Interface + /// @{ + virtual void EmitDataRegion(MCDataRegionType Kind) { + switch (Kind) { + case MCDR_DataRegion: + case MCDR_DataRegionJT8: + case MCDR_DataRegionJT16: + case MCDR_DataRegionJT32: + EmitDataMappingSymbol(); + break; + case MCDR_DataRegionEnd: + EmitCodeMappingSymbol(); + break; + } + } + +private: + void EmitDataMappingSymbol() { + EmitMappingSymbol("$d"); + } + void EmitCodeMappingSymbol() { + if (IsThumb) { + EmitCodeAlignment(2); + EmitMappingSymbol("$t"); + } else { + EmitCodeAlignment(4); + EmitMappingSymbol("$a"); + } + } + void EmitMappingSymbol(StringRef Name) { + MCSymbol *Start = getContext().CreateTempSymbol(); + EmitLabel(Start); + + StringRef UniqueName = Name.str() + "." + itostr(MappingSymbolCounter++); + MCSymbol *Symbol = getContext().GetOrCreateSymbol(UniqueName); + + MCSymbolData &SD = getAssembler().getOrCreateSymbolData(*Symbol); + MCELF::SetType(SD, ELF::STT_NOTYPE); + MCELF::SetBinding(SD, ELF::STB_LOCAL); + SD.setExternal(false); + Symbol->setSection(*getCurrentSection()); + + const MCExpr *Value = MCSymbolRefExpr::Create(Start, getContext()); + Symbol->setVariableValue(Value); + } + + // Add a Code Mapping symbol any time we change to a Text section + // for the first time. + // + // Note: We are not provided with a 'CreateSection' hook, so we + // maintain a short list to detect when 'ChangeSection' + // causes a section to be created. + void ChangeSection(const MCSection *Section) { + MCELFStreamer::ChangeSection(Section); + if (Section->getKind().isText()) { + bool IsNew = std::find(SectionStack.begin(), SectionStack.end(), + Section) == SectionStack.end(); + if (IsNew) { + SectionStack.push_back(Section); + EmitCodeMappingSymbol(); + } + } + } + + bool IsThumb; + int64_t MappingSymbolCounter; + SmallVector SectionStack; + + /// @} +}; + } void MCELFStreamer::InitSections() { @@ -487,3 +569,15 @@ MCStreamer *llvm::createELFStreamer(MCContext &Context, MCAsmBackend &MAB, S->getAssembler().setNoExecStack(true); return S; } + +MCStreamer *llvm::createARMELFStreamer(MCContext &Context, MCAsmBackend &MAB, + raw_ostream &OS, MCCodeEmitter *CE, + bool RelaxAll, bool NoExecStack, + bool IsThumb) { + ARMELFStreamer *S = new ARMELFStreamer(Context, MAB, OS, CE, IsThumb); + if (RelaxAll) + S->getAssembler().setRelaxAll(true); + if (NoExecStack) + S->getAssembler().setNoExecStack(true); + return S; +} diff --git a/lib/Target/ARM/MCTargetDesc/ARMMCTargetDesc.cpp b/lib/Target/ARM/MCTargetDesc/ARMMCTargetDesc.cpp index 00ffc94..ce15794 100644 --- a/lib/Target/ARM/MCTargetDesc/ARMMCTargetDesc.cpp +++ b/lib/Target/ARM/MCTargetDesc/ARMMCTargetDesc.cpp @@ -186,7 +186,8 @@ static MCStreamer *createMCStreamer(const Target &T, StringRef TT, llvm_unreachable("ARM does not support Windows COFF format"); } - return createELFStreamer(Ctx, MAB, OS, Emitter, false, NoExecStack); + return createARMELFStreamer(Ctx, MAB, OS, Emitter, false, NoExecStack, + TheTriple.getArch() == Triple::thumb); } static MCInstPrinter *createARMMCInstPrinter(const Target &T, diff --git a/test/CodeGen/ARM/2010-11-30-reloc-movt.ll b/test/CodeGen/ARM/2010-11-30-reloc-movt.ll index 8b164c5..c7289b0 100644 --- a/test/CodeGen/ARM/2010-11-30-reloc-movt.ll +++ b/test/CodeGen/ARM/2010-11-30-reloc-movt.ll @@ -23,7 +23,7 @@ entry: ; OBJ: Relocation 0 ; OBJ-NEXT: 'r_offset', 0x00000004 -; OBJ-NEXT: 'r_sym', 0x000007 +; OBJ-NEXT: 'r_sym', 0x000008 ; OBJ-NEXT: 'r_type', 0x2b ; OBJ: Relocation 1 @@ -33,7 +33,7 @@ entry: ; OBJ: # Relocation 2 ; OBJ-NEXT: 'r_offset', 0x0000000c -; OBJ-NEXT: 'r_sym', 0x000008 +; OBJ-NEXT: 'r_sym', 0x000009 ; OBJ-NEXT: 'r_type', 0x1c } diff --git a/test/MC/ARM/data-in-code.ll b/test/MC/ARM/data-in-code.ll new file mode 100644 index 0000000..f1a74cf --- /dev/null +++ b/test/MC/ARM/data-in-code.ll @@ -0,0 +1,121 @@ +;; RUN: llc -O0 -mtriple=armv7-linux-gnueabi -filetype=obj %s -o - | \ +;; RUN: elf-dump --dump-section-data | FileCheck -check-prefix=OBJ %s + +;; Ensure that if a jump table is generated that it has Mapping Symbols +;; marking the data-in-code region. + +target triple = "armv7-none-linux-gnueabi" + +define void @foo(i32* %ptr) nounwind ssp { + %tmp = load i32* %ptr, align 4 + switch i32 %tmp, label %default [ + i32 11, label %bb0 + i32 10, label %bb1 + i32 8, label %bb2 + i32 4, label %bb3 + i32 2, label %bb4 + i32 6, label %bb5 + i32 9, label %bb6 + i32 15, label %bb7 + i32 1, label %bb8 + i32 3, label %bb9 + i32 5, label %bb10 + i32 30, label %bb11 + i32 31, label %bb12 + i32 13, label %bb13 + i32 14, label %bb14 + i32 20, label %bb15 + i32 19, label %bb16 + i32 17, label %bb17 + i32 18, label %bb18 + i32 21, label %bb19 + i32 22, label %bb20 + i32 16, label %bb21 + i32 24, label %bb22 + i32 25, label %bb23 + i32 26, label %bb24 + i32 27, label %bb25 + i32 28, label %bb26 + i32 23, label %bb27 + i32 12, label %bb28 + ] + +default: + br label %exit +bb0: + br label %exit +bb1: + br label %exit +bb2: + br label %exit +bb3: + br label %exit +bb4: + br label %exit +bb5: + br label %exit +bb6: + br label %exit +bb7: + br label %exit +bb8: + br label %exit +bb9: + br label %exit +bb10: + br label %exit +bb11: + br label %exit +bb12: + br label %exit +bb13: + br label %exit +bb14: + br label %exit +bb15: + br label %exit +bb16: + br label %exit +bb17: + br label %exit +bb18: + br label %exit +bb19: + br label %exit +bb20: + br label %exit +bb21: + br label %exit +bb22: + br label %exit +bb23: + br label %exit +bb24: + br label %exit +bb25: + br label %exit +bb26: + br label %exit +bb27: + br label %exit +bb28: + br label %exit + + +exit: + + ret void +} + +;; OBJ: # Symbol 2 +;; OBJ-NEXT: $a +;; OBJ-NEXT: 'st_value', 0x00000000 + +;; OBJ: # Symbol 3 +;; OBJ-NEXT: $a +;; OBJ-NEXT: 'st_value', 0x000000ac + +;; OBJ: # Symbol 4 +;; OBJ-NEXT: $d +;; OBJ-NEXT: 'st_value', 0x00000030 + diff --git a/test/MC/ARM/elf-reloc-01.ll b/test/MC/ARM/elf-reloc-01.ll index c98026b..96dcf7e 100644 --- a/test/MC/ARM/elf-reloc-01.ll +++ b/test/MC/ARM/elf-reloc-01.ll @@ -62,9 +62,9 @@ declare void @exit(i32) noreturn nounwind ;; OBJ: Relocation 1 ;; OBJ-NEXT: 'r_offset', -;; OBJ-NEXT: 'r_sym', 0x000002 +;; OBJ-NEXT: 'r_sym', 0x000005 ;; OBJ-NEXT: 'r_type', 0x2b -;; OBJ: Symbol 2 +;; OBJ: Symbol 5 ;; OBJ-NEXT: '_MergedGlobals' ;; OBJ-NEXT: 'st_value', 0x00000010 diff --git a/test/MC/ARM/elf-reloc-02.ll b/test/MC/ARM/elf-reloc-02.ll index e51bac3..4208954 100644 --- a/test/MC/ARM/elf-reloc-02.ll +++ b/test/MC/ARM/elf-reloc-02.ll @@ -42,9 +42,9 @@ declare i32 @write(...) declare void @exit(i32) noreturn nounwind ;; OBJ: Relocation 0 -;; OBJ-NEXT: 'r_offset', -;; OBJ-NEXT: 'r_sym', 0x000002 +;; OBJ-NEXT: 'r_offset', +;; OBJ-NEXT: 'r_sym', 0x000003 ;; OBJ-NEXT: 'r_type', 0x2b -;; OBJ: Symbol 2 +;; OBJ: Symbol 3 ;; OBJ-NEXT: '.L.str' diff --git a/test/MC/ARM/elf-reloc-03.ll b/test/MC/ARM/elf-reloc-03.ll index 922242f..bb41842 100644 --- a/test/MC/ARM/elf-reloc-03.ll +++ b/test/MC/ARM/elf-reloc-03.ll @@ -89,9 +89,9 @@ entry: declare void @exit(i32) noreturn nounwind ;; OBJ: Relocation 1 -;; OBJ-NEXT: 'r_offset', -;; OBJ-NEXT: 'r_sym', 0x00000c +;; OBJ-NEXT: 'r_offset', +;; OBJ-NEXT: 'r_sym', 0x00000d ;; OBJ-NEXT: 'r_type', 0x2b -;; OBJ: Symbol 12 +;; OBJ: Symbol 13 ;; OBJ-NEXT: 'vtable' diff --git a/test/MC/ARM/elf-reloc-condcall.s b/test/MC/ARM/elf-reloc-condcall.s index 08b4ecc..3fafb43 100644 --- a/test/MC/ARM/elf-reloc-condcall.s +++ b/test/MC/ARM/elf-reloc-condcall.s @@ -9,25 +9,25 @@ // OBJ: .rel.text // OBJ: 'r_offset', 0x00000000 -// OBJ-NEXT: 'r_sym', 0x000004 +// OBJ-NEXT: 'r_sym', 0x000005 // OBJ-NEXT: 'r_type', 0x1d // OBJ: 'r_offset', 0x00000004 -// OBJ-NEXT: 'r_sym', 0x000004 +// OBJ-NEXT: 'r_sym', 0x000005 // OBJ-NEXT: 'r_type', 0x1c // OBJ: 'r_offset', 0x00000008 -// OBJ-NEXT: 'r_sym', 0x000004 +// OBJ-NEXT: 'r_sym', 0x000005 // OBJ-NEXT: 'r_type', 0x1c // OBJ: 'r_offset', 0x0000000c -// OBJ-NEXT: 'r_sym', 0x000004 +// OBJ-NEXT: 'r_sym', 0x000005 // OBJ-NEXT: 'r_type', 0x1d // OBJ: 'r_offset', 0x00000010 -// OBJ-NEXT: 'r_sym', 0x000004 +// OBJ-NEXT: 'r_sym', 0x000005 // OBJ-NEXT: 'r_type', 0x1d // OBJ: .symtab -// OBJ: Symbol 4 +// OBJ: Symbol 5 // OBJ-NEXT: some_label diff --git a/test/MC/ARM/elf-thumbfunc-reloc.ll b/test/MC/ARM/elf-thumbfunc-reloc.ll index ecac11d..d84cd47 100644 --- a/test/MC/ARM/elf-thumbfunc-reloc.ll +++ b/test/MC/ARM/elf-thumbfunc-reloc.ll @@ -28,10 +28,10 @@ entry: ; 00000008 0000070a R_ARM_THM_CALL 00000001 foo ; CHECK: Relocation 0 ; CHECK-NEXT: 'r_offset', 0x00000008 -; CHECK-NEXT: 'r_sym', 0x000007 +; CHECK-NEXT: 'r_sym', 0x000008 ; CHECK-NEXT: 'r_type', 0x0a ; make sure foo is thumb function: bit 0 = 1 -; CHECK: Symbol 7 +; CHECK: Symbol 8 ; CHECK-NEXT: 'foo' ; CHECK-NEXT: 'st_value', 0x00000001 diff --git a/test/MC/ARM/elf-thumbfunc.s b/test/MC/ARM/elf-thumbfunc.s index 0aa7f41..ab1d7d7 100644 --- a/test/MC/ARM/elf-thumbfunc.s +++ b/test/MC/ARM/elf-thumbfunc.s @@ -12,8 +12,8 @@ foo: bx lr @@ make sure foo is thumb function: bit 0 = 1 (st_value) -@CHECK: Symbol 4 -@CHECK-NEXT: 'st_name', 0x00000001 +@CHECK: Symbol 5 +@CHECK-NEXT: 'st_name', 0x00000006 @CHECK-NEXT: 'st_value', 0x00000001 @CHECK-NEXT: 'st_size', 0x00000000 @CHECK-NEXT: 'st_bind', 0x1 -- 1.7.12