| From a921aaf789912d981cbb2036bdc91ad7289e1523 Mon Sep 17 00:00:00 2001 |
| From: Stefan Agner <stefan@agner.ch> |
| Date: Wed, 24 Feb 2021 13:47:40 -0800 |
| Subject: [PATCH] [MC][ARM] make Thumb function also if type attribute is set |
| |
| Make sure to set the bottom bit of the symbol even when the type |
| attribute of a label is set after the label. |
| |
| GNU as sets the thumb state according to the thumb state of the label. |
| If a .type directive is placed after the label, set the symbol's thumb |
| state according to the thumb state of the .type directive. This matches |
| GNU as in most cases. |
| |
| From: Stefan Agner <stefan@agner.ch> |
| |
| This fixes: |
| https://bugs.llvm.org/show_bug.cgi?id=44860 |
| https://github.com/ClangBuiltLinux/linux/issues/866 |
| |
| Reviewed By: MaskRay |
| |
| Differential Revision: https://reviews.llvm.org/D74927 |
| --- |
| .../ARM/MCTargetDesc/ARMELFStreamer.cpp | 22 ++++++++++ |
| llvm/test/MC/ARM/thumb-function-address.s | 42 +++++++++++++++++++ |
| 2 files changed, 64 insertions(+) |
| create mode 100644 llvm/test/MC/ARM/thumb-function-address.s |
| |
| diff --git a/llvm/lib/Target/ARM/MCTargetDesc/ARMELFStreamer.cpp b/llvm/lib/Target/ARM/MCTargetDesc/ARMELFStreamer.cpp |
| index 2fc104b87221..5d3342a887d6 100644 |
| --- a/llvm/lib/Target/ARM/MCTargetDesc/ARMELFStreamer.cpp |
| +++ b/llvm/lib/Target/ARM/MCTargetDesc/ARMELFStreamer.cpp |
| @@ -579,6 +579,28 @@ public: |
| } |
| } |
| |
| + /// If a label is defined before the .type directive sets the label's type |
| + /// then the label can't be recorded as thumb function when the label is |
| + /// defined. We override emitSymbolAttribute() which is called as part of the |
| + /// parsing of .type so that if the symbol has already been defined we can |
| + /// record the label as Thumb. FIXME: there is a corner case where the state |
| + /// is changed in between the label definition and the .type directive, this |
| + /// is not expected to occur in practice and handling it would require the |
| + /// backend to track IsThumb for every label. |
| + bool emitSymbolAttribute(MCSymbol *Symbol, MCSymbolAttr Attribute) override { |
| + bool Val = MCELFStreamer::emitSymbolAttribute(Symbol, Attribute); |
| + |
| + if (!IsThumb) |
| + return Val; |
| + |
| + unsigned Type = cast<MCSymbolELF>(Symbol)->getType(); |
| + if ((Type == ELF::STT_FUNC || Type == ELF::STT_GNU_IFUNC) && |
| + Symbol->isDefined()) |
| + getAssembler().setIsThumbFunc(Symbol); |
| + |
| + return Val; |
| + }; |
| + |
| private: |
| enum ElfMappingSymbol { |
| EMS_None, |
| diff --git a/llvm/test/MC/ARM/thumb-function-address.s b/llvm/test/MC/ARM/thumb-function-address.s |
| new file mode 100644 |
| index 000000000000..9200b54a80e9 |
| --- /dev/null |
| +++ b/llvm/test/MC/ARM/thumb-function-address.s |
| @@ -0,0 +1,42 @@ |
| +@ RUN: llvm-mc -filetype=obj -triple=armv7-linux-gnueabi %s -o %t |
| +@ RUN: llvm-readelf -s %t | FileCheck %s |
| + |
| +@@ GNU as sets the thumb state according to the thumb state of the label. If a |
| +@@ .type directive is placed after the label, set the symbol's thumb state |
| +@@ according to the thumb state of the .type directive. This matches GNU as in |
| +@@ most cases. |
| + |
| +.syntax unified |
| +.text |
| +.thumb |
| +func_label: |
| +.type func_label, %function |
| + |
| +.type foo_impl, %function |
| +foo_impl: |
| + bx lr |
| +.type foo_resolver, %function |
| +foo_resolver: |
| + b foo_impl |
| +.type foo, %gnu_indirect_function |
| +.set foo, foo_resolver |
| + |
| +@@ Note: GNU as sets the value to 1. |
| +.thumb |
| +label: |
| + bx lr |
| +.arm |
| + bx lr |
| +.type label, %function |
| + |
| +@@ Check func_label, foo_impl, foo_resolver, and foo addresses have bit 0 set. |
| +@@ Check label has bit 0 unset. |
| +@ CHECK: Value Size Type Bind Vis Ndx Name |
| +@ CHECK-NEXT: 00000000 0 NOTYPE LOCAL DEFAULT UND |
| +@ CHECK-NEXT: 00000001 0 FUNC LOCAL DEFAULT 2 func_label |
| +@ CHECK-NEXT: 00000001 0 FUNC LOCAL DEFAULT 2 foo_impl |
| +@ CHECK-NEXT: 00000000 0 NOTYPE LOCAL DEFAULT 2 $t.0 |
| +@ CHECK-NEXT: 00000003 0 FUNC LOCAL DEFAULT 2 foo_resolver |
| +@ CHECK-NEXT: 00000003 0 IFUNC LOCAL DEFAULT 2 foo |
| +@ CHECK-NEXT: 00000004 0 FUNC LOCAL DEFAULT 2 label |
| +@ CHECK-NEXT: 00000006 0 NOTYPE LOCAL DEFAULT 2 $a.1 |
| -- |
| 2.30.0.617.g56c4b15f3c-goog |
| |