[lld] r283730 - [ELF][ARM] Initial implentation of ARM exceptions support

Peter Smith via llvm-commits llvm-commits at lists.llvm.org
Mon Oct 10 02:39:26 PDT 2016


Author: psmith
Date: Mon Oct 10 04:39:26 2016
New Revision: 283730

URL: http://llvm.org/viewvc/llvm-project?rev=283730&view=rev
Log:
[ELF][ARM] Initial implentation of ARM exceptions support

The .ARM.exidx sections contain a table. Each entry has two fields:
- PREL31 offset to the function the table entry describes
- Action to take, either cantunwind, inline unwind, or PREL31 offset to
  .ARM.extab section

The table entries must be sorted in order of the virtual addresses the
first entry of the table describes. Traditionally this is implemented by
the SHF_LINK_ORDER dependency. Instead of implementing this directly we
sort the table entries post relocation. 

The .ARM.exidx OutputSection is described by the PT_ARM_EXIDX program
header

Differential revision: https://reviews.llvm.org/D25127

Added:
    lld/trunk/test/ELF/Inputs/arm-exidx-cantunwind.s
    lld/trunk/test/ELF/arm-exidx-canunwind.s
    lld/trunk/test/ELF/arm-exidx-order.s
Modified:
    lld/trunk/ELF/InputSection.cpp
    lld/trunk/ELF/InputSection.h
    lld/trunk/ELF/OutputSections.cpp
    lld/trunk/ELF/Writer.cpp
    lld/trunk/test/ELF/arm-exidx-output.s

Modified: lld/trunk/ELF/InputSection.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/InputSection.cpp?rev=283730&r1=283729&r2=283730&view=diff
==============================================================================
--- lld/trunk/ELF/InputSection.cpp (original)
+++ lld/trunk/ELF/InputSection.cpp Mon Oct 10 04:39:26 2016
@@ -132,6 +132,15 @@ InputSectionBase<ELFT>::getOffset(const
   return getOffset(Sym.Value);
 }
 
+template<class ELFT>
+InputSectionBase<ELFT>*
+InputSectionBase<ELFT>::getLinkOrderDep() const {
+  const Elf_Shdr *Hdr = getSectionHdr();
+  if ((Hdr->sh_flags & SHF_LINK_ORDER) && Hdr->sh_link != 0)
+    return getFile()->getSections()[Hdr->sh_link];
+  return nullptr;
+}
+
 template <class ELFT>
 InputSection<ELFT>::InputSection(elf::ObjectFile<ELFT> *F,
                                  const Elf_Shdr *Header, StringRef Name)

Modified: lld/trunk/ELF/InputSection.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/InputSection.h?rev=283730&r1=283729&r2=283730&view=diff
==============================================================================
--- lld/trunk/ELF/InputSection.h (original)
+++ lld/trunk/ELF/InputSection.h Mon Oct 10 04:39:26 2016
@@ -110,7 +110,7 @@ public:
   const Elf_Shdr *getSectionHdr() const { return Header; }
   ObjectFile<ELFT> *getFile() const { return File; }
   uintX_t getOffset(const DefinedRegular<ELFT> &Sym) const;
-
+  InputSectionBase *getLinkOrderDep() const;
   // Translate an offset in the input section to an offset in the output
   // section.
   uintX_t getOffset(uintX_t Offset) const;

Modified: lld/trunk/ELF/OutputSections.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/OutputSections.cpp?rev=283730&r1=283729&r2=283730&view=diff
==============================================================================
--- lld/trunk/ELF/OutputSections.cpp (original)
+++ lld/trunk/ELF/OutputSections.cpp Mon Oct 10 04:39:26 2016
@@ -878,6 +878,9 @@ OutputSection<ELFT>::OutputSection(Strin
 
 template <class ELFT> void OutputSection<ELFT>::finalize() {
   uint32_t Type = this->Header.sh_type;
+  // SHF_LINK_ORDER only has meaning in relocatable objects
+  if (!Config->Relocatable)
+    this->Header.sh_flags &= ~SHF_LINK_ORDER;
   if (Type != SHT_RELA && Type != SHT_REL)
     return;
   this->Header.sh_link = Out<ELFT>::SymTab->SectionIndex;

Modified: lld/trunk/ELF/Writer.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/Writer.cpp?rev=283730&r1=283729&r2=283730&view=diff
==============================================================================
--- lld/trunk/ELF/Writer.cpp (original)
+++ lld/trunk/ELF/Writer.cpp Mon Oct 10 04:39:26 2016
@@ -26,6 +26,8 @@
 using namespace llvm;
 using namespace llvm::ELF;
 using namespace llvm::object;
+using namespace llvm::support;
+using namespace llvm::support::endian;
 
 using namespace lld;
 using namespace lld::elf;
@@ -1036,6 +1038,7 @@ std::vector<PhdrEntry<ELFT>> Writer<ELFT
   Phdr TlsHdr(PT_TLS, PF_R);
   Phdr RelRo(PT_GNU_RELRO, PF_R);
   Phdr Note(PT_NOTE, PF_R);
+  Phdr ARMExidx(PT_ARM_EXIDX, PF_R);
   for (OutputSectionBase<ELFT> *Sec : OutputSections) {
     if (!(Sec->getFlags() & SHF_ALLOC))
       break;
@@ -1066,6 +1069,8 @@ std::vector<PhdrEntry<ELFT>> Writer<ELFT
       RelRo.add(Sec);
     if (Sec->getType() == SHT_NOTE)
       Note.add(Sec);
+    if (Config->EMachine == EM_ARM && Sec->getType() == SHT_ARM_EXIDX)
+      ARMExidx.add(Sec);
   }
 
   // Add the TLS segment unless it's empty.
@@ -1089,6 +1094,10 @@ std::vector<PhdrEntry<ELFT>> Writer<ELFT
     Hdr.add(Out<ELFT>::EhFrameHdr);
   }
 
+  // PT_ARM_EXIDX is the ARM EHABI equivalent of PT_GNU_EH_FRAME
+  if (ARMExidx.First)
+    Ret.push_back(std::move(ARMExidx));
+
   // PT_GNU_STACK is a special section to tell the loader to make the
   // pages for the stack non-executable.
   if (!Config->ZExecStack) {
@@ -1366,6 +1375,61 @@ template <class ELFT> void Writer<ELFT>:
       Sec->writeTo(Buf + Sec->getFileOff());
 }
 
+// Convert the .ARM.exidx table entries that use relative PREL31 offsets to
+// Absolute addresses. This form is internal to LLD and is only used to
+// make reordering the table simpler.
+static void ARMExidxEntryPrelToAbs(uint8_t *Loc, uint64_t EntryVA) {
+  uint64_t Addr = Target->getImplicitAddend(Loc, R_ARM_PREL31) + EntryVA;
+  bool InlineEntry =
+      (read32le(Loc + 4) == 1 || (read32le(Loc + 4) & 0x80000000));
+  if (InlineEntry)
+    // Set flag in unused bit of code address so that when we convert back we
+    // know which table entries to leave alone.
+    Addr |= 0x1;
+  else
+    write32le(Loc + 4,
+              Target->getImplicitAddend(Loc + 4, R_ARM_PREL31) + EntryVA + 4);
+  write32le(Loc, Addr);
+}
+
+// Convert the .ARM.exidx table entries from the internal to LLD form using
+// absolute addresses back to relative PREL31 offsets.
+static void ARMExidxEntryAbsToPrel(uint8_t *Loc, uint64_t EntryVA) {
+  uint64_t Off = read32le(Loc) - EntryVA;
+  // ARMExidxEntryPreltoAbs sets bit 0 if the table entry has inline data
+  // that is not an address
+  bool InlineEntry = Off & 0x1;
+  Target->relocateOne(Loc, R_ARM_PREL31, Off & ~0x1);
+  if (!InlineEntry)
+    Target->relocateOne(Loc + 4, R_ARM_PREL31,
+                        read32le(Loc + 4) - (EntryVA + 4));
+}
+
+// The table formed by the .ARM.exidx OutputSection has entries with two
+// 4-byte fields:
+// | PREL31 offset to function | Action to take for function |
+// The table must be ordered in ascending virtual address of the functions
+// identified by the first field of the table. Instead of using the
+// SHF_LINK_ORDER dependency to reorder the sections prior to relocation we
+// sort the table post-relocation.
+// Ref: Exception handling ABI for the ARM architecture
+static void sortARMExidx(uint8_t *Buf, uint64_t OutSecVA, uint64_t Size) {
+  struct ARMExidxEntry {
+    ulittle32_t Target;
+    ulittle32_t Action;
+  };
+  ARMExidxEntry *Start = (ARMExidxEntry *)Buf;
+  size_t NumEnt = Size / sizeof(ARMExidxEntry);
+  for (uint64_t Off = 0; Off < Size; Off += 8)
+    ARMExidxEntryPrelToAbs(Buf + Off, OutSecVA + Off);
+  std::stable_sort(Start, Start + NumEnt,
+                   [](const ARMExidxEntry &A, const ARMExidxEntry &B) {
+                     return A.Target < B.Target;
+                   });
+  for (uint64_t Off = 0; Off < Size; Off += 8)
+    ARMExidxEntryAbsToPrel(Buf + Off, OutSecVA + Off);
+}
+
 // Write section contents to a mmap'ed file.
 template <class ELFT> void Writer<ELFT>::writeSections() {
   uint8_t *Buf = Buffer->getBufferStart();
@@ -1382,6 +1446,11 @@ template <class ELFT> void Writer<ELFT>:
     if (Sec != Out<ELFT>::Opd && Sec != Out<ELFT>::EhFrameHdr)
       Sec->writeTo(Buf + Sec->getFileOff());
 
+  OutputSectionBase<ELFT> *ARMExidx = findSection(".ARM.exidx");
+  if (!Config->Relocatable)
+    if (auto *OS = dyn_cast_or_null<OutputSection<ELFT>>(ARMExidx))
+      sortARMExidx(Buf + OS->getFileOff(), OS->getVA(), OS->getSize());
+
   // The .eh_frame_hdr depends on .eh_frame section contents, therefore
   // it should be written after .eh_frame is written.
   if (!Out<ELFT>::EhFrame->empty() && Out<ELFT>::EhFrameHdr)

Added: lld/trunk/test/ELF/Inputs/arm-exidx-cantunwind.s
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/ELF/Inputs/arm-exidx-cantunwind.s?rev=283730&view=auto
==============================================================================
--- lld/trunk/test/ELF/Inputs/arm-exidx-cantunwind.s (added)
+++ lld/trunk/test/ELF/Inputs/arm-exidx-cantunwind.s Mon Oct 10 04:39:26 2016
@@ -0,0 +1,40 @@
+// Functions that will generate a .ARM.exidx section with SHF_LINK_ORDER
+// dependency on the progbits section containing the .cantunwind directive
+ .syntax unified
+ .section .func1, "ax",%progbits
+ .globl func1
+func1:
+ .fnstart
+ bx lr
+ .cantunwind
+ .fnend
+
+ .section .func2, "ax", %progbits
+ .globl func2
+func2:
+ .fnstart
+ bx lr
+ .cantunwind
+ .fnend
+
+ .section .func3, "ax",%progbits
+ .globl func3
+func3:
+ .fnstart
+ bx lr
+ .cantunwind
+ .fnend
+
+ .section .text, "ax",%progbits
+ .globl func4
+func4:
+ .fnstart
+ bx lr
+ .cantunwind
+ .fnend
+ .globl func5
+func5:
+ .fnstart
+ bx lr
+ .cantunwind
+ .fnend

Added: lld/trunk/test/ELF/arm-exidx-canunwind.s
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/ELF/arm-exidx-canunwind.s?rev=283730&view=auto
==============================================================================
--- lld/trunk/test/ELF/arm-exidx-canunwind.s (added)
+++ lld/trunk/test/ELF/arm-exidx-canunwind.s Mon Oct 10 04:39:26 2016
@@ -0,0 +1,96 @@
+// RUN: llvm-mc -filetype=obj -triple=armv7a-none-linux-gnueabi %s -o %t
+// RUN: ld.lld %t -o %t2 2>&1
+// RUN: llvm-objdump -d -triple=armv7a-none-linux-gnueabi %t2 | FileCheck %s
+// RUN: llvm-objdump -s -triple=armv7a-none-linux-gnueabi %t2 | FileCheck -check-prefix=CHECK-EXIDX %s
+// RUN: llvm-readobj --program-headers --sections %t2 | FileCheck -check-prefix=CHECK-PT %s
+// REQUIRES: arm
+
+// Test that inline unwinding table entries and references to .ARM.extab
+// entries survive the re-ordering of the .ARM.exidx section
+
+ .syntax unified
+ // Will produce an ARM.exidx entry with inline unwinding instructions
+ .section .text.func1, "ax",%progbits
+ .global func1
+func1:
+ .fnstart
+ bx lr
+ .save {r7, lr}
+ .setfp r7, sp, #0
+ .fnend
+
+ // Unwinding instructions for .text2 too large for an inline entry ARM.exidx
+ // entry. A separate .ARM.extab section is created to hold the unwind entries
+ // The .ARM.exidx table entry has a reference to the .ARM.extab section.
+ .section .text.func2, "ax",%progbits
+ .global func2
+func2:
+ .fnstart
+ bx lr
+ .personality __gxx_personality_v0
+ .handlerdata
+ .long 0
+ .section .text.func2
+ .fnend
+
+ // Dummy implementation of personality routines to satisfy reference from
+ // exception tables
+ .section .text.__gcc_personality_v0, "ax", %progbits
+ .global __gxx_personality_v0
+__gxx_personality_v0:
+ bx lr
+
+ .section .text.__aeabi_unwind_cpp_pr0, "ax", %progbits
+ .global __aeabi_unwind_cpp_pr0
+__aeabi_unwind_cpp_pr0:
+ bx lr
+
+ .text
+ .global _start
+_start:
+ bl func1
+ bl func2
+ bx lr
+
+// CHECK: Disassembly of section .text:
+// CHECK-NEXT: _start:
+// CHECK-NEXT:    11000:       01 00 00 eb     bl      #4 <func1>
+// CHECK-NEXT:    11004:       01 00 00 eb     bl      #4 <func2>
+// CHECK-NEXT:    11008:       1e ff 2f e1     bx      lr
+// CHECK:      func1:
+// CHECK-NEXT:    1100c:       1e ff 2f e1     bx      lr
+// CHECK:      func2:
+// CHECK-NEXT:    11010:       1e ff 2f e1     bx      lr
+// CHECK:      __gxx_personality_v0:
+// CHECK-NEXT:    11014:       1e ff 2f e1     bx      lr
+// CHECK:      __aeabi_unwind_cpp_pr0:
+// CHECK-NEXT:    11018:       1e ff 2f e1     bx      lr
+
+// CHECK-EXIDX: Contents of section .ARM.exidx:
+// 100d4 + f38 = 1100c = func1 (inline unwinding data)
+// 100dc + f34 = 11010 = func2 (100e0 + 4 = 100e4 = .ARM.extab entry)
+// CHECK-EXIDX-NEXT: 100d4 380f0000 08849780 340f0000 04000000
+// 100e4 + f30 = 11014 = __gxx_personality_v0
+// CHECK-EXIDX-NEXT: Contents of section .ARM.extab.text.func2:
+// CHECK-EXIDX-NEXT: 100e4 300f0000 b0b0b000 00000000
+
+// CHECK-PT:          Name: .ARM.exidx
+// CHECK-PT-NEXT:     Type: SHT_ARM_EXIDX (0x70000001)
+// CHECK-PT-NEXT:     Flags [ (0x2)
+// CHECK-PT-NEXT:       SHF_ALLOC (0x2)
+// CHECK-PT-NEXT:     ]
+// CHECK-PT-NEXT:     Address: 0x100D4
+// CHECK-PT-NEXT:     Offset: 0xD4
+// CHECK-PT-NEXT:     Size: 16
+
+// CHECK-PT:          Type: PT_ARM_EXIDX (0x70000001)
+// CHECK-PT-NEXT:     Offset: 0xD4
+// CHECK-PT-NEXT:     VirtualAddress: 0x100D4
+// CHECK-PT-NEXT:     PhysicalAddress: 0x100D4
+// CHECK-PT-NEXT:     FileSize: 16
+// CHECK-PT-NEXT:     MemSize: 16
+// CHECK-PT-NEXT:     Flags [ (0x4)
+// CHECK-PT-NEXT:       PF_R (0x4)
+// CHECK-PT-NEXT:     ]
+// CHECK-PT-NEXT:     Alignment: 4
+// CHECK-PT-NEXT:   }

Added: lld/trunk/test/ELF/arm-exidx-order.s
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/ELF/arm-exidx-order.s?rev=283730&view=auto
==============================================================================
--- lld/trunk/test/ELF/arm-exidx-order.s (added)
+++ lld/trunk/test/ELF/arm-exidx-order.s Mon Oct 10 04:39:26 2016
@@ -0,0 +1,168 @@
+// RUN: llvm-mc -filetype=obj -triple=armv7a-none-linux-gnueabi %s -o %t
+// RUN: llvm-mc -filetype=obj -triple=armv7a-none-linux-gnueabi %S/Inputs/arm-exidx-cantunwind.s -o %tcantunwind
+// RUN: ld.lld %t %tcantunwind -o %t2 2>&1
+// RUN: llvm-objdump -d -triple=armv7a-none-linux-gnueabi %t2 | FileCheck %s
+// RUN: llvm-objdump -s -triple=armv7a-none-linux-gnueabi %t2 | FileCheck -check-prefix=CHECK-EXIDX %s
+// RUN: llvm-readobj --program-headers --sections %t2 | FileCheck -check-prefix=CHECK-PT %s
+// Use Linker script to place .ARM.exidx in between .text and orphan sections
+// RUN: echo "SECTIONS { \
+// RUN:          .text 0x11000 : { *(.text*) } \
+// RUN:          .ARM.exidx : { *(.ARM.exidx) } } " > %t.script
+// RUN: ld.lld --script %t.script %tcantunwind %t -o %t3 2>&1
+// RUN: llvm-objdump -d -triple=armv7a-none-linux-gnueabi %t3 | FileCheck -check-prefix=CHECK-SCRIPT %s
+// RUN: llvm-objdump -s -triple=armv7a-none-linux-gnueabi %t3 | FileCheck -check-prefix=CHECK-SCRIPT-EXIDX %s
+// REQUIRES: arm
+
+// Each assembler created .ARM.exidx section has the SHF_LINK_ORDER flag set
+// with the sh_link containing the section index of the executable section
+// containing the function it describes. The linker must combine the .ARM.exidx
+// InputSections in the same order that it has combined the executable section,
+// such that the combined .ARM.exidx OutputSection can be used as a binary
+// search table.
+
+ .syntax unified
+ .section .text, "ax",%progbits
+ .globl _start
+_start:
+ .fnstart
+ bx lr
+ .cantunwind
+ .fnend
+
+ .section .text.f1, "ax", %progbits
+ .globl f1
+f1:
+ .fnstart
+ bx lr
+ .cantunwind
+ .fnend
+
+ .section .text.f2, "ax", %progbits
+ .globl f2
+f2:
+ .fnstart
+ bx lr
+ .cantunwind
+ .fnend
+ .globl f3
+f3:
+ .fnstart
+ bx lr
+ .cantunwind
+ .fnend
+
+// Check default no linker script order.
+
+// CHECK: Disassembly of section .text:
+// CHECK: _start:
+// CHECK-NEXT:    11000:       1e ff 2f e1     bx      lr
+// CHECK: f1:
+// CHECK-NEXT:    11004:       1e ff 2f e1     bx      lr
+// CHECK: f2:
+// CHECK-NEXT:    11008:       1e ff 2f e1     bx      lr
+// CHECK: f3:
+// CHECK-NEXT:    1100c:       1e ff 2f e1     bx      lr
+// CHECK: func4:
+// CHECK-NEXT:    11010:       1e ff 2f e1     bx      lr
+// CHECK: func5:
+// CHECK-NEXT:    11014:       1e ff 2f e1     bx      lr
+// CHECK: Disassembly of section .func1:
+// CHECK-NEXT: func1:
+// CHECK-NEXT:    11018:       1e ff 2f e1     bx      lr
+// CHECK: Disassembly of section .func2:
+// CHECK-NEXT: func2:
+// CHECK-NEXT:    1101c:       1e ff 2f e1     bx      lr
+// CHECK: Disassembly of section .func3:
+// CHECK-NEXT: func3:
+// CHECK-NEXT:    11020:       1e ff 2f e1     bx      lr
+
+// Each .ARM.exidx section has two 4 byte fields
+// Field 1 is the 31-bit offset to the function. The top bit is used to
+// indicate whether Field 2 is a pointer or an inline table entry.
+// Field 2 is either a pointer to a .ARM.extab section or an inline table
+// In this example all Field 2 entries are inline can't unwind (0x1)
+// We expect to see the entries in the same order as the functions
+
+// CHECK-EXIDX: Contents of section .ARM.exidx:
+// 100d4 + f2c = 11000 = _start
+// 100dc + f28 = 11004 = f1
+// CHECK-EXIDX-NEXT:       100d4 2c0f0000 01000000 280f0000 01000000
+// 100e4 + f24 = 11008 = f2
+// 100ec + f20 = 1100c = f3
+// CHECK-EXIDX-NEXT:  100e4 240f0000 01000000 200f0000 01000000
+// 100f4 + f1c = 11010 = func4
+// 100fc + f18 = 11014 = func5
+// CHECK-EXIDX-NEXT:  100f4 1c0f0000 01000000 180f0000 01000000
+// 10104 + f14 = 11018 = func1
+// 1010c + f10 = 1101c = func2
+// CHECK-EXIDX-NEXT:  10104 140f0000 01000000 100f0000 01000000
+// 10114 + f0c = 11020 = func3
+// CHECK-EXIDX-NEXT:  10114 0c0f0000 01000000
+
+// Check that PT_ARM_EXIDX program header has been generated that describes
+// the .ARM.exidx output section
+// CHECK-PT:          Name: .ARM.exidx
+// CHECK-PT-NEXT:     Type: SHT_ARM_EXIDX (0x70000001)
+// CHECK-PT-NEXT:     Flags [ (0x2)
+// CHECK-PT-NEXT:       SHF_ALLOC (0x2)
+// CHECK-PT-NEXT:     ]
+// CHECK-PT-NEXT:     Address: 0x100D4
+// CHECK-PT-NEXT:     Offset: 0xD4
+// CHECK-PT-NEXT:     Size: 72
+
+// CHECK-PT:          Type: PT_ARM_EXIDX (0x70000001)
+// CHECK-PT-NEXT:     Offset: 0xD4
+// CHECK-PT-NEXT:     VirtualAddress: 0x100D4
+// CHECK-PT-NEXT:     PhysicalAddress: 0x100D4
+// CHECK-PT-NEXT:     FileSize: 72
+// CHECK-PT-NEXT:     MemSize: 72
+// CHECK-PT-NEXT:     Flags [ (0x4)
+// CHECK-PT-NEXT:       PF_R (0x4)
+// CHECK-PT-NEXT:     ]
+// CHECK-PT-NEXT:     Alignment: 4
+// CHECK-PT-NEXT:   }
+
+
+// Check linker script order. The .ARM.exidx section will be inserted after
+// the .text section but before the orphan sections
+
+// CHECK-SCRIPT: Disassembly of section .text:
+// CHECK-SCRIPT-NEXT: func4:
+// CHECK-SCRIPT-NEXT:    11000:       1e ff 2f e1     bx      lr
+// CHECK-SCRIPT:      func5:
+// CHECK-SCRIPT-NEXT:    11004:       1e ff 2f e1     bx      lr
+// CHECK-SCRIPT:      _start:
+// CHECK-SCRIPT-NEXT:    11008:       1e ff 2f e1     bx      lr
+// CHECK-SCRIPT:      f1:
+// CHECK-SCRIPT-NEXT:    1100c:       1e ff 2f e1     bx      lr
+// CHECK-SCRIPT:      f2:
+// CHECK-SCRIPT-NEXT:    11010:       1e ff 2f e1     bx      lr
+// CHECK-SCRIPT:      f3:
+// CHECK-SCRIPT-NEXT:    11014:       1e ff 2f e1     bx      lr
+// CHECK-SCRIPT-NEXT: Disassembly of section .func1:
+// CHECK-SCRIPT-NEXT: func1:
+// CHECK-SCRIPT-NEXT:    11060:       1e ff 2f e1     bx      lr
+// CHECK-SCRIPT-NEXT: Disassembly of section .func2:
+// CHECK-SCRIPT-NEXT: func2:
+// CHECK-SCRIPT-NEXT:    11064:       1e ff 2f e1     bx      lr
+// CHECK-SCRIPT-NEXT: Disassembly of section .func3:
+// CHECK-SCRIPT-NEXT: func3:
+// CHECK-SCRIPT-NEXT:    11068:       1e ff 2f e1     bx      lr
+
+// Check that the .ARM.exidx section is sorted in order as the functions
+// The offset in field 1, is 32-bit so in the binary the most significant bit
+// CHECK-SCRIPT-EXIDX: Contents of section .ARM.exidx:
+// 11018 - 18 = 11000 func4
+// 11020 - 1c = 11004 func5
+// CHECK-SCRIPT-EXIDX-NEXT:  11018 e8ffff7f 01000000 e4ffff7f 01000000
+// 11028 - 20 = 11008 _start
+// 11030 - 24 = 1100c f1
+// CHECK-SCRIPT-EXIDX-NEXT:  11028 e0ffff7f 01000000 dcffff7f 01000000
+// 11038 - 28 = 11010 f2
+// 11040 - 2c = 11014 f3
+// CHECK-SCRIPT-EXIDX-NEXT:  11038 d8ffff7f 01000000 d4ffff7f 01000000
+// 11048 + 18 = 11060 = func1
+// 11050 + 14 = 11064 = func2
+// CHECK-SCRIPT-EXIDX-NEXT:  11048 18000000 01000000 14000000 01000000
+// 11058 + 10 = 11068 = func3
+// CHECK-SCRIPT-EXIDX-NEXT:  11058 10000000 01000000

Modified: lld/trunk/test/ELF/arm-exidx-output.s
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/ELF/arm-exidx-output.s?rev=283730&r1=283729&r2=283730&view=diff
==============================================================================
--- lld/trunk/test/ELF/arm-exidx-output.s (original)
+++ lld/trunk/test/ELF/arm-exidx-output.s Mon Oct 10 04:39:26 2016
@@ -10,8 +10,6 @@
  .syntax unified
  .section .text, "ax",%progbits
  .globl _start
- .align 2
- .type _start,%function
 _start:
  .fnstart
  bx lr
@@ -20,8 +18,6 @@ _start:
 
  .section .text.f1, "ax", %progbits
  .globl f1
- .align 2
- .type f1,%function
 f1:
  .fnstart
  bx lr
@@ -30,8 +26,6 @@ f1:
 
  .section .text.f2, "ax", %progbits
  .globl f2
- .align 2
- .type f2,%function
 f2:
  .fnstart
  bx lr
@@ -41,9 +35,8 @@ f2:
 // CHECK:         Section {
 // CHECK:         Name: .ARM.exidx
 // CHECK-NEXT:    Type: SHT_ARM_EXIDX (0x70000001)
-// CHECK-NEXT:    Flags [ (0x82)
+// CHECK-NEXT:    Flags [ (0x2)
 // CHECK-NEXT:      SHF_ALLOC (0x2)
-// CHECK-NEXT:      SHF_LINK_ORDER (0x80)
 // CHECK-NEXT:    ]
 
 // CHECK-NOT:     Name: .ARM.exidx.text.f1




More information about the llvm-commits mailing list