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).

Patch based on work by Greg Fitzgerald.

llvm-svn: 169609
This commit is contained in:
Tim Northover 2012-12-07 16:50:23 +00:00
parent 75f8418bfa
commit 2dbbd221f7
19 changed files with 515 additions and 39 deletions

View File

@ -12,7 +12,6 @@
//===----------------------------------------------------------------------===//
#include "llvm/MC/MCELFObjectWriter.h"
#include "MCELF.h"
#include "llvm/ADT/OwningPtr.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/SmallPtrSet.h"
@ -22,6 +21,7 @@
#include "llvm/MC/MCAsmLayout.h"
#include "llvm/MC/MCAssembler.h"
#include "llvm/MC/MCContext.h"
#include "llvm/MC/MCELF.h"
#include "llvm/MC/MCELFSymbolFlags.h"
#include "llvm/MC/MCExpr.h"
#include "llvm/MC/MCFixupKindInfo.h"

View File

@ -11,7 +11,7 @@
//
//===----------------------------------------------------------------------===//
#include "MCELF.h"
#include "llvm/MC/MCELF.h"
#include "llvm/MC/MCAssembler.h"
#include "llvm/MC/MCELFSymbolFlags.h"
#include "llvm/MC/MCFixupKindInfo.h"

View File

@ -12,15 +12,11 @@
//===----------------------------------------------------------------------===//
#include "llvm/MC/MCELFStreamer.h"
#include "MCELF.h"
#include "llvm/ADT/SmallPtrSet.h"
#include "llvm/ADT/StringExtras.h"
#include "llvm/ADT/Twine.h"
#include "llvm/MC/MCAsmBackend.h"
#include "llvm/MC/MCAssembler.h"
#include "llvm/MC/MCCodeEmitter.h"
#include "llvm/MC/MCContext.h"
#include "llvm/MC/MCELF.h"
#include "llvm/MC/MCELFSymbolFlags.h"
#include "llvm/MC/MCExpr.h"
#include "llvm/MC/MCInst.h"
@ -104,15 +100,6 @@ void MCELFStreamer::EmitAssemblerFlag(MCAssemblerFlag Flag) {
llvm_unreachable("invalid assembler flag!");
}
void MCELFStreamer::EmitThumbFunc(MCSymbol *Func) {
// FIXME: Anything needed here to flag the function as thumb?
getAssembler().setIsThumbFunc(Func);
MCSymbolData &SD = getAssembler().getOrCreateSymbolData(*Func);
SD.setFlags(SD.getFlags() | ELF_Other_ThumbFunc);
}
void MCELFStreamer::EmitAssignment(MCSymbol *Symbol, const MCExpr *Value) {
// TODO: This is exactly the same as WinCOFFStreamer. Consider merging into
// MCObjectStreamer.
@ -396,9 +383,7 @@ void MCELFStreamer::FinishImpl() {
this->MCObjectStreamer::FinishImpl();
}
void MCELFStreamer::EmitTCEntry(const MCSymbol &S)
{
void MCELFStreamer::EmitTCEntry(const MCSymbol &S) {
// Creates a R_PPC64_TOC relocation
MCObjectStreamer::EmitSymbolValue(&S, 8, 0);
}
@ -414,6 +399,10 @@ MCStreamer *llvm::createELFStreamer(MCContext &Context, MCAsmBackend &MAB,
return S;
}
void MCELFStreamer::EmitThumbFunc(MCSymbol *Func) {
llvm_unreachable("Generic ELF doesn't support this directive");
}
void MCELFStreamer::EmitSymbolDesc(MCSymbol *Symbol, unsigned DescValue) {
llvm_unreachable("ELF doesn't support this directive");
}

View File

@ -0,0 +1,201 @@
//===- lib/MC/ARMELFStreamer.cpp - ELF Object Output for ARM --------------===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file assembles .s files and emits ARM ELF .o object files. Different
// from generic ELF streamer in emitting mapping symbols ($a, $t and $d) to
// delimit regions of data and code.
//
//===----------------------------------------------------------------------===//
#include "llvm/MC/MCELFStreamer.h"
#include "llvm/ADT/SmallPtrSet.h"
#include "llvm/ADT/StringExtras.h"
#include "llvm/MC/MCAssembler.h"
#include "llvm/MC/MCCodeEmitter.h"
#include "llvm/MC/MCContext.h"
#include "llvm/MC/MCSectionELF.h"
#include "llvm/MC/MCStreamer.h"
#include "llvm/MC/MCELF.h"
#include "llvm/MC/MCELFStreamer.h"
#include "llvm/MC/MCELFSymbolFlags.h"
#include "llvm/MC/MCExpr.h"
#include "llvm/MC/MCInst.h"
#include "llvm/MC/MCObjectStreamer.h"
#include "llvm/MC/MCSection.h"
#include "llvm/MC/MCSymbol.h"
#include "llvm/MC/MCValue.h"
#include "llvm/MC/MCAsmBackend.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/ELF.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/raw_ostream.h"
using namespace llvm;
namespace {
/// Extend the generic ELFStreamer class so that it can emit mapping symbols at
/// the appropriate points in the object files. These symbols are defined in the
/// ARM ELF ABI: infocenter.arm.com/help/topic/com.arm.../IHI0044D_aaelf.pdf.
///
/// In brief: $a, $t or $d should be emitted at the start of each contiguous
/// region of ARM code, Thumb code or data in a section. In practice, this
/// emission does not rely on explicit assembler directives but on inherent
/// properties of the directives doing the emission (e.g. ".byte" is data, "add
/// r0, r0, r0" an instruction).
///
/// As a result this system is orthogonal to the DataRegion infrastructure used
/// by MachO. Beware!
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), LastEMS(EMS_None) {
}
~ARMELFStreamer() {}
virtual void ChangeSection(const MCSection *Section) {
// 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()] = LastEMS;
LastEMS = LastMappingSymbols.lookup(Section);
MCELFStreamer::ChangeSection(Section);
}
/// 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.
virtual void EmitInstruction(const MCInst& Inst) {
if (IsThumb)
EmitThumbMappingSymbol();
else
EmitARMMappingSymbol();
MCELFStreamer::EmitInstruction(Inst);
}
/// 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.
virtual void EmitBytes(StringRef Data, unsigned AddrSpace) {
EmitDataMappingSymbol();
MCELFStreamer::EmitBytes(Data, AddrSpace);
}
/// 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.
virtual void EmitValueImpl(const MCExpr *Value, unsigned Size,
unsigned AddrSpace) {
EmitDataMappingSymbol();
MCELFStreamer::EmitValueImpl(Value, Size, AddrSpace);
}
virtual void EmitAssemblerFlag(MCAssemblerFlag Flag) {
MCELFStreamer::EmitAssemblerFlag(Flag);
switch (Flag) {
case MCAF_SyntaxUnified:
return; // no-op here.
case MCAF_Code16:
IsThumb = true;
return; // Change to Thumb mode
case MCAF_Code32:
IsThumb = false;
return; // Change to ARM mode
case MCAF_Code64:
return;
case MCAF_SubsectionsViaSymbols:
return;
}
}
private:
enum ElfMappingSymbol {
EMS_None,
EMS_ARM,
EMS_Thumb,
EMS_Data
};
void EmitDataMappingSymbol() {
if (LastEMS == EMS_Data) return;
EmitMappingSymbol("$d");
LastEMS = EMS_Data;
}
void EmitThumbMappingSymbol() {
if (LastEMS == EMS_Thumb) return;
EmitMappingSymbol("$t");
LastEMS = EMS_Thumb;
}
void EmitARMMappingSymbol() {
if (LastEMS == EMS_ARM) return;
EmitMappingSymbol("$a");
LastEMS = EMS_ARM;
}
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);
}
void EmitThumbFunc(MCSymbol *Func) {
// FIXME: Anything needed here to flag the function as thumb?
getAssembler().setIsThumbFunc(Func);
MCSymbolData &SD = getAssembler().getOrCreateSymbolData(*Func);
SD.setFlags(SD.getFlags() | ELF_Other_ThumbFunc);
}
bool IsThumb;
int64_t MappingSymbolCounter;
DenseMap<const MCSection *, ElfMappingSymbol> LastMappingSymbols;
ElfMappingSymbol LastEMS;
/// @}
};
}
namespace llvm {
MCELFStreamer* createARMELFStreamer(MCContext &Context, MCAsmBackend &TAB,
raw_ostream &OS, MCCodeEmitter *Emitter,
bool RelaxAll, bool NoExecStack,
bool IsThumb) {
ARMELFStreamer *S = new ARMELFStreamer(Context, TAB, OS, Emitter, IsThumb);
if (RelaxAll)
S->getAssembler().setRelaxAll(true);
if (NoExecStack)
S->getAssembler().setNoExecStack(true);
return S;
}
}

View File

@ -0,0 +1,27 @@
//===-- ARMELFStreamer.h - ELF Streamer for ARM ------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file implements ELF streamer information for the ARM backend.
//
//===----------------------------------------------------------------------===//
#ifndef ARM_ELF_STREAMER_H
#define ARM_ELF_STREAMER_H
#include "llvm/MC/MCELFStreamer.h"
namespace llvm {
MCELFStreamer* createARMELFStreamer(MCContext &Context, MCAsmBackend &TAB,
raw_ostream &OS, MCCodeEmitter *Emitter,
bool RelaxAll, bool NoExecStack,
bool IsThumb);
}
#endif // ARM_ELF_STREAMER_H

View File

@ -12,6 +12,8 @@
//===----------------------------------------------------------------------===//
#include "ARMMCTargetDesc.h"
#include "ARMELFStreamer.h"
#include "ARMMCAsmInfo.h"
#include "ARMBaseInfo.h"
#include "ARMMCAsmInfo.h"
#include "InstPrinter/ARMInstPrinter.h"
@ -186,7 +188,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,

View File

@ -1,6 +1,7 @@
add_llvm_library(LLVMARMDesc
ARMAsmBackend.cpp
ARMELFObjectWriter.cpp
ARMELFStreamer.cpp
ARMMCAsmInfo.cpp
ARMMCCodeEmitter.cpp
ARMMCExpr.cpp

View File

@ -23,7 +23,7 @@ entry:
; OBJ: Relocation 0
; OBJ-NEXT: 'r_offset', 0x00000004
; OBJ-NEXT: 'r_sym', 0x000007
; OBJ-NEXT: 'r_sym', 0x000009
; 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', 0x00000a
; OBJ-NEXT: 'r_type', 0x1c
}

176
test/MC/ARM/data-in-code.ll Normal file
View File

@ -0,0 +1,176 @@
;; RUN: llc -O0 -mtriple=armv7-linux-gnueabi -filetype=obj %s -o - | \
;; RUN: elf-dump | FileCheck -check-prefix=ARM %s
;; RUN: llc -O0 -mtriple=thumbv7-linux-gnueabi -filetype=obj %s -o - | \
;; RUN: elf-dump --dump-section-data | FileCheck -check-prefix=TMB %s
;; Ensure that if a jump table is generated that it has Mapping Symbols
;; marking the data-in-code region.
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
}
;; ARM: # Symbol 2
;; ARM-NEXT: $a
;; ARM-NEXT: 'st_value', 0x00000000
;; ARM-NEXT: 'st_size', 0x00000000
;; ARM-NEXT: 'st_bind', 0x0
;; ARM-NEXT: 'st_type', 0x0
;; ARM-NEXT: 'st_other'
;; ARM-NEXT: 'st_shndx', [[MIXED_SECT:0x[0-9a-f]+]]
;; ARM: # Symbol 3
;; ARM-NEXT: $a
;; ARM-NEXT: 'st_value', 0x000000ac
;; ARM-NEXT: 'st_size', 0x00000000
;; ARM-NEXT: 'st_bind', 0x0
;; ARM-NEXT: 'st_type', 0x0
;; ARM-NEXT: 'st_other'
;; ARM-NEXT: 'st_shndx', [[MIXED_SECT]]
;; ARM: # Symbol 4
;; ARM-NEXT: $d
;; ARM-NEXT: 'st_value', 0x00000000
;; ARM-NEXT: 'st_size', 0x00000000
;; ARM-NEXT: 'st_bind', 0x0
;; ARM-NEXT: 'st_type', 0x0
;; ARM: # Symbol 5
;; ARM-NEXT: $d
;; ARM-NEXT: 'st_value', 0x00000030
;; ARM-NEXT: 'st_size', 0x00000000
;; ARM-NEXT: 'st_bind', 0x0
;; ARM-NEXT: 'st_type', 0x0
;; ARM-NEXT: 'st_other'
;; ARM-NEXT: 'st_shndx', [[MIXED_SECT]]
;; ARM-NOT: ${{[atd]}}
;; TMB: # Symbol 3
;; TMB-NEXT: $d
;; TMB-NEXT: 'st_value', 0x00000016
;; TMB-NEXT: 'st_size', 0x00000000
;; TMB-NEXT: 'st_bind', 0x0
;; TMB-NEXT: 'st_type', 0x0
;; TMB-NEXT: 'st_other'
;; TMB-NEXT: 'st_shndx', [[MIXED_SECT:0x[0-9a-f]+]]
;; TMB: # Symbol 4
;; TMB-NEXT: $t
;; TMB-NEXT: 'st_value', 0x00000000
;; TMB-NEXT: 'st_size', 0x00000000
;; TMB-NEXT: 'st_bind', 0x0
;; TMB-NEXT: 'st_type', 0x0
;; TMB-NEXT: 'st_other'
;; TMB-NEXT: 'st_shndx', [[MIXED_SECT]]
;; TMB: # Symbol 5
;; TMB-NEXT: $t
;; TMB-NEXT: 'st_value', 0x00000036
;; TMB-NEXT: 'st_size', 0x00000000
;; TMB-NEXT: 'st_bind', 0x0
;; TMB-NEXT: 'st_type', 0x0
;; TMB-NEXT: 'st_other'
;; TMB-NEXT: 'st_shndx', [[MIXED_SECT]]
;; TMB-NOT: ${{[atd]}}

View File

@ -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', 0x000007
;; OBJ-NEXT: 'r_type', 0x2b
;; OBJ: Symbol 2
;; OBJ: Symbol 7
;; OBJ-NEXT: '_MergedGlobals'
;; OBJ-NEXT: 'st_value', 0x00000010

View File

@ -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', 0x000005
;; OBJ-NEXT: 'r_type', 0x2b
;; OBJ: Symbol 2
;; OBJ: Symbol 5
;; OBJ-NEXT: '.L.str'

View File

@ -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', 0x000010
;; OBJ-NEXT: 'r_type', 0x2b
;; OBJ: Symbol 12
;; OBJ: Symbol 16
;; OBJ-NEXT: 'vtable'

View File

@ -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

View File

@ -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', 0x000009
; CHECK-NEXT: 'r_type', 0x0a
; make sure foo is thumb function: bit 0 = 1
; CHECK: Symbol 7
; CHECK: Symbol 9
; CHECK-NEXT: 'foo'
; CHECK-NEXT: 'st_value', 0x00000001

View File

@ -12,7 +12,7 @@ foo:
bx lr
@@ make sure foo is thumb function: bit 0 = 1 (st_value)
@CHECK: Symbol 4
@CHECK: Symbol 5
@CHECK-NEXT: 'st_name', 0x00000001
@CHECK-NEXT: 'st_value', 0x00000001
@CHECK-NEXT: 'st_size', 0x00000000

View File

@ -0,0 +1,33 @@
@ RUN: llvm-mc -triple=arm-linux-gnueabi -filetype=obj < %s | llvm-objdump -t - | FileCheck %s
.text
@ $a at 0x0000
add r0, r0, r0
@ $d at 0x0004
.word 42
.thumb
@ $t at 0x0008
adds r0, r0, r0
adds r0, r0, r0
@ $a at 0x000c
.arm
add r0, r0, r0
@ $t at 0x0010
.thumb
adds r0, r0, r0
@ $d at 0x0012
.ascii "012"
.byte 1
.byte 2
.byte 3
@ $a at 0x0018
.arm
add r0, r0, r0
@ CHECK: 00000000 .text 00000000 $a
@ CHECK-NEXT: 0000000c .text 00000000 $a
@ CHECK-NEXT: 00000018 .text 00000000 $a
@ CHECK-NEXT: 00000004 .text 00000000 $d
@ CHECK-NEXT: 00000012 .text 00000000 $d
@ CHECK-NEXT: 00000008 .text 00000000 $t
@ CHECK-NEXT: 00000010 .text 00000000 $t

View File

@ -0,0 +1,35 @@
@ RUN: llvm-mc -triple=arm-linux-gnueabi -filetype=obj < %s | llvm-objdump -t - | FileCheck %s
.text
add r0, r0, r0
@ .wibble should *not* inherit .text's mapping symbol. It's a completely different section.
.section .wibble
add r0, r0, r0
@ A section should be able to start with a $t
.section .starts_thumb
.thumb
adds r0, r0, r0
@ A setion should be able to start with a $d
.section .starts_data
.word 42
@ Changing back to .text should not emit a redundant $a
.text
.arm
add r0, r0, r0
@ With all those constraints, we want:
@ + .text to have $a at 0 and no others
@ + .wibble to have $a at 0
@ + .starts_thumb to have $t at 0
@ + .starts_data to have $d at 0
@ 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]}}

View File

@ -0,0 +1,11 @@
@ RUN: llvm-mc -triple=arm-linux-gnueabi -filetype=obj < %s | llvm-objdump -t - | FileCheck %s
@ Implementation-detail test (unfortunately): values that are relocated do not
@ go via MCStreamer::EmitBytes; make sure they still emit a mapping symbol.
add r0, r0, r0
.word somewhere
add r0, r0, r0
@ CHECK: 00000000 .text 00000000 $a
@ CHECK-NEXT: 00000008 .text 00000000 $a
@ CHECK-NEXT: 00000004 .text 00000000 $d