COFF: Support exception table.
authorRui Ueyama <ruiu@google.com>
Sun, 21 Jun 2015 04:00:54 +0000 (04:00 +0000)
committerRui Ueyama <ruiu@google.com>
Sun, 21 Jun 2015 04:00:54 +0000 (04:00 +0000)
.pdata section contains a list of triplets of function start address,
function end address and its unwind information. Linkers have to
sort section contents by function start address and set the section
address to the file header (so that runtime is able to find it and
do binary search.)

This change seems to resolve all but one remaining test failures in
check{,-clang,-lld} when building the entire stuff with clang-cl and
lld-link.

llvm-svn: 240231

lld/COFF/Writer.cpp
lld/COFF/Writer.h
lld/test/COFF/unwind.test [new file with mode: 0644]

index a6cdb94..9771034 100644 (file)
@@ -51,6 +51,7 @@ std::error_code Writer::write(StringRef OutputPath) {
     return EC;
   writeHeader();
   writeSections();
+  sortExceptionTable();
   return Buffer->commit();
 }
 
@@ -322,6 +323,10 @@ void Writer::writeHeader() {
     DataDirectory[BASE_RELOCATION_TABLE].RelativeVirtualAddress = Sec->getRVA();
     DataDirectory[BASE_RELOCATION_TABLE].Size = Sec->getVirtualSize();
   }
+  if (OutputSection *Sec = findSection(".pdata")) {
+    DataDirectory[EXCEPTION_TABLE].RelativeVirtualAddress = Sec->getRVA();
+    DataDirectory[EXCEPTION_TABLE].Size = Sec->getVirtualSize();
+  }
 
   // Section table
   // Name field in the section table is 8 byte long. Longer names need
@@ -383,6 +388,18 @@ void Writer::writeSections() {
   }
 }
 
+// Sort .pdata section contents according to PE/COFF spec 5.5.
+void Writer::sortExceptionTable() {
+  if (auto *Sec = findSection(".pdata")) {
+    // We assume .pdata contains function table entries only.
+    struct Entry { ulittle32_t Begin, End, Unwind; };
+    uint8_t *Buf = Buffer->getBufferStart() + Sec->getFileOff();
+    std::sort(reinterpret_cast<Entry *>(Buf),
+              reinterpret_cast<Entry *>(Buf + Sec->getVirtualSize()),
+              [](const Entry &A, const Entry &B) { return A.Begin < B.Begin; });
+  }
+}
+
 OutputSection *Writer::findSection(StringRef Name) {
   for (OutputSection *Sec : OutputSections)
     if (Sec->getName() == Name)
index 78fc953..a23dc2f 100644 (file)
@@ -84,6 +84,7 @@ private:
   std::error_code openFile(StringRef OutputPath);
   void writeHeader();
   void writeSections();
+  void sortExceptionTable();
   void applyRelocations();
 
   OutputSection *findSection(StringRef Name);
diff --git a/lld/test/COFF/unwind.test b/lld/test/COFF/unwind.test
new file mode 100644 (file)
index 0000000..deec0da
--- /dev/null
@@ -0,0 +1,198 @@
+# RUN: yaml2obj < %s > %t.obj
+#
+# RUN: lld -flavor link2 /out:%t.exe %t.obj
+# RUN: llvm-readobj -file-headers %t.exe | FileCheck -check-prefix=HEADER %s
+# RUN: llvm-objdump -unwind-info %t.exe | FileCheck -check-prefix=UNWIND %s
+#
+# HEADER: ExceptionTableRVA: 0x1000
+#
+# UNWIND: Function Table:
+# UNWIND:   Start Address: 0x2000
+# UNWIND:   End Address: 0x201b
+# UNWIND:   Unwind Info Address: 0x3000
+# UNWIND:     Version: 1
+# UNWIND:     Flags: 1 UNW_ExceptionHandler
+# UNWIND:     Size of prolog: 18
+# UNWIND:     Number of Codes: 8
+# UNWIND:     Frame register: RBX
+# UNWIND:     Frame offset: 0
+# UNWIND:     Unwind Codes:
+# UNWIND:       0x12: UOP_SetFPReg
+# UNWIND:       0x0f: UOP_PushNonVol RBX
+# UNWIND:       0x0e: UOP_SaveXMM128 XMM8 [0x0000]
+# UNWIND:       0x09: UOP_SaveNonVol RSI [0x0010]
+# UNWIND:       0x04: UOP_AllocSmall 24
+# UNWIND:       0x00: UOP_PushMachFrame w/o error code
+# UNWIND: Function Table:
+# UNWIND:   Start Address: 0x2012
+# UNWIND:   End Address: 0x2012
+# UNWIND:   Unwind Info Address: 0x301c
+# UNWIND:     Version: 1
+# UNWIND:     Flags: 4 UNW_ChainInfo
+# UNWIND:     Size of prolog: 0
+# UNWIND:     Number of Codes: 0
+# UNWIND:     No frame pointer used
+# UNWIND: Function Table:
+# UNWIND:   Start Address: 0x201b
+# UNWIND:   End Address: 0x201c
+# UNWIND:   Unwind Info Address: 0x302c
+# UNWIND:     Version: 1
+# UNWIND:     Flags: 0
+# UNWIND:     Size of prolog: 0
+# UNWIND:     Number of Codes: 0
+# UNWIND:     No frame pointer used
+# UNWIND: Function Table:
+# UNWIND:   Start Address: 0x201c
+# UNWIND:   End Address: 0x2039
+# UNWIND:   Unwind Info Address: 0x3034
+# UNWIND:     Version: 1
+# UNWIND:     Flags: 0
+# UNWIND:     Size of prolog: 14
+# UNWIND:     Number of Codes: 6
+# UNWIND:     No frame pointer used
+# UNWIND:     Unwind Codes:
+# UNWIND:       0x0e: UOP_AllocLarge 8454128
+# UNWIND:       0x07: UOP_AllocLarge 8190
+# UNWIND:       0x00: UOP_PushMachFrame w/o error code
+
+---
+header:
+  Machine:         IMAGE_FILE_MACHINE_AMD64
+  Characteristics: [  ]
+sections:
+  - Name:            .text
+    Characteristics: [ IMAGE_SCN_CNT_CODE, IMAGE_SCN_MEM_EXECUTE, IMAGE_SCN_MEM_READ ]
+    Alignment:       4
+    SectionData:     4883EC184889742410440F110424534889E3488D235B4883C418C3C34881ECF0FF00004881ECF0FF80004881C4F0FF80004881C4F0FF0000C3
+  - Name:            .xdata
+    Characteristics: [ IMAGE_SCN_CNT_INITIALIZED_DATA, IMAGE_SCN_MEM_READ ]
+    Alignment:       4
+    SectionData:     0912080312030F300E880000096402000422001A000000000000000021000000000000001B000000000000000100000000000000010E06000E11F0FF80000701FE1F001A
+    Relocations:
+      - VirtualAddress:  20
+        SymbolName:      __C_specific_handler
+        Type:            IMAGE_REL_AMD64_ADDR32NB
+      - VirtualAddress:  32
+        SymbolName:      func
+        Type:            IMAGE_REL_AMD64_ADDR32NB
+      - VirtualAddress:  36
+        SymbolName:      func
+        Type:            IMAGE_REL_AMD64_ADDR32NB
+      - VirtualAddress:  40
+        SymbolName:      .xdata
+        Type:            IMAGE_REL_AMD64_ADDR32NB
+  - Name:            .pdata
+    Characteristics: [ IMAGE_SCN_CNT_INITIALIZED_DATA, IMAGE_SCN_MEM_READ ]
+    Alignment:       4
+    SectionData:     000000001B0000000000000012000000120000001C00000000000000010000002C000000000000001D00000034000000
+    Relocations:
+      - VirtualAddress:  0
+        SymbolName:      func
+        Type:            IMAGE_REL_AMD64_ADDR32NB
+      - VirtualAddress:  4
+        SymbolName:      func
+        Type:            IMAGE_REL_AMD64_ADDR32NB
+      - VirtualAddress:  8
+        SymbolName:      .xdata
+        Type:            IMAGE_REL_AMD64_ADDR32NB
+      - VirtualAddress:  12
+        SymbolName:      func
+        Type:            IMAGE_REL_AMD64_ADDR32NB
+      - VirtualAddress:  16
+        SymbolName:      func
+        Type:            IMAGE_REL_AMD64_ADDR32NB
+      - VirtualAddress:  20
+        SymbolName:      .xdata
+        Type:            IMAGE_REL_AMD64_ADDR32NB
+      - VirtualAddress:  24
+        SymbolName:      smallFunc
+        Type:            IMAGE_REL_AMD64_ADDR32NB
+      - VirtualAddress:  28
+        SymbolName:      smallFunc
+        Type:            IMAGE_REL_AMD64_ADDR32NB
+      - VirtualAddress:  32
+        SymbolName:      .xdata
+        Type:            IMAGE_REL_AMD64_ADDR32NB
+      - VirtualAddress:  36
+        SymbolName:      allocFunc
+        Type:            IMAGE_REL_AMD64_ADDR32NB
+      - VirtualAddress:  40
+        SymbolName:      allocFunc
+        Type:            IMAGE_REL_AMD64_ADDR32NB
+      - VirtualAddress:  44
+        SymbolName:      .xdata
+        Type:            IMAGE_REL_AMD64_ADDR32NB
+symbols:
+  - Name:            .text
+    Value:           0
+    SectionNumber:   1
+    SimpleType:      IMAGE_SYM_TYPE_NULL
+    ComplexType:     IMAGE_SYM_DTYPE_NULL
+    StorageClass:    IMAGE_SYM_CLASS_STATIC
+    SectionDefinition:
+      Length:          57
+      NumberOfRelocations: 0
+      NumberOfLinenumbers: 0
+      CheckSum:        0
+      Number:          1
+  - Name:            .xdata
+    Value:           0
+    SectionNumber:   2
+    SimpleType:      IMAGE_SYM_TYPE_NULL
+    ComplexType:     IMAGE_SYM_DTYPE_NULL
+    StorageClass:    IMAGE_SYM_CLASS_STATIC
+    SectionDefinition:
+      Length:          68
+      NumberOfRelocations: 4
+      NumberOfLinenumbers: 0
+      CheckSum:        0
+      Number:          2
+  - Name:            .pdata
+    Value:           0
+    SectionNumber:   3
+    SimpleType:      IMAGE_SYM_TYPE_NULL
+    ComplexType:     IMAGE_SYM_DTYPE_NULL
+    StorageClass:    IMAGE_SYM_CLASS_STATIC
+    SectionDefinition:
+      Length:          48
+      NumberOfRelocations: 12
+      NumberOfLinenumbers: 0
+      CheckSum:        0
+      Number:          3
+  - Name:            func
+    Value:           0
+    SectionNumber:   1
+    SimpleType:      IMAGE_SYM_TYPE_NULL
+    ComplexType:     IMAGE_SYM_DTYPE_FUNCTION
+    StorageClass:    IMAGE_SYM_CLASS_EXTERNAL
+  - Name:            __C_specific_handler
+    Value:           0
+    SectionNumber:   0
+    SimpleType:      IMAGE_SYM_TYPE_NULL
+    ComplexType:     IMAGE_SYM_DTYPE_NULL
+    StorageClass:    IMAGE_SYM_CLASS_EXTERNAL
+  - Name:            smallFunc
+    Value:           27
+    SectionNumber:   1
+    SimpleType:      IMAGE_SYM_TYPE_NULL
+    ComplexType:     IMAGE_SYM_DTYPE_FUNCTION
+    StorageClass:    IMAGE_SYM_CLASS_EXTERNAL
+  - Name:            allocFunc
+    Value:           28
+    SectionNumber:   1
+    SimpleType:      IMAGE_SYM_TYPE_NULL
+    ComplexType:     IMAGE_SYM_DTYPE_FUNCTION
+    StorageClass:    IMAGE_SYM_CLASS_EXTERNAL
+  - Name:            mainCRTStartup
+    Value:           0
+    SectionNumber:   1
+    SimpleType:      IMAGE_SYM_TYPE_NULL
+    ComplexType:     IMAGE_SYM_DTYPE_NULL
+    StorageClass:    IMAGE_SYM_CLASS_EXTERNAL
+  - Name:            __C_specific_handler
+    Value:           0
+    SectionNumber:   1
+    SimpleType:      IMAGE_SYM_TYPE_NULL
+    ComplexType:     IMAGE_SYM_DTYPE_NULL
+    StorageClass:    IMAGE_SYM_CLASS_EXTERNAL
+...