[lld] [lld] Add support for EC code map. (PR #69101)
Jacek Caban via llvm-commits
llvm-commits at lists.llvm.org
Sat Nov 11 08:25:29 PST 2023
https://github.com/cjacek updated https://github.com/llvm/llvm-project/pull/69101
>From 6252d72db441115d8c9a0f33eb6b677ed40267c7 Mon Sep 17 00:00:00 2001
From: Jacek Caban <jacek at codeweavers.com>
Date: Thu, 8 Jun 2023 22:59:53 +0200
Subject: [PATCH 1/3] [lld] Add support for EC code map.
---
lld/COFF/Chunks.cpp | 14 +++++
lld/COFF/Chunks.h | 21 +++++++
lld/COFF/Driver.cpp | 5 ++
lld/COFF/Writer.cpp | 66 +++++++++++++++++++++
lld/test/COFF/Inputs/loadconfig-arm64ec.s | 4 +-
lld/test/COFF/arm64ec-codemap.test | 70 ++++++-----------------
6 files changed, 125 insertions(+), 55 deletions(-)
diff --git a/lld/COFF/Chunks.cpp b/lld/COFF/Chunks.cpp
index 4e845afa8947a5f..39f4575031be549 100644
--- a/lld/COFF/Chunks.cpp
+++ b/lld/COFF/Chunks.cpp
@@ -896,6 +896,20 @@ void RVAFlagTableChunk::writeTo(uint8_t *buf) const {
"RVA tables should be de-duplicated");
}
+size_t ECCodeMapChunk::getSize() const {
+ return map.size() * sizeof(chpe_range_entry);
+}
+
+void ECCodeMapChunk::writeTo(uint8_t *buf) const {
+ auto table = reinterpret_cast<chpe_range_entry *>(buf);
+ for (uint32_t i = 0; i < map.size(); i++) {
+ const ECCodeMapEntry &entry = map[i];
+ uint32_t start = entry.first->getRVA();
+ table[i].StartOffset = start | entry.type;
+ table[i].Length = entry.last->getRVA() + entry.last->getSize() - start;
+ }
+}
+
// MinGW specific, for the "automatic import of variables from DLLs" feature.
size_t PseudoRelocTableChunk::getSize() const {
if (relocs.empty())
diff --git a/lld/COFF/Chunks.h b/lld/COFF/Chunks.h
index 156e7a807cb8fd7..7b6bdeae4234ef5 100644
--- a/lld/COFF/Chunks.h
+++ b/lld/COFF/Chunks.h
@@ -703,6 +703,27 @@ class EmptyChunk : public NonSectionChunk {
void writeTo(uint8_t *buf) const override {}
};
+class ECCodeMapEntry {
+public:
+ ECCodeMapEntry(Chunk *first, Chunk *last, chpe_range_type type)
+ : first(first), last(last), type(type) {}
+ Chunk *first;
+ Chunk *last;
+ chpe_range_type type;
+};
+
+// This is a chunk containing CHPE code map on EC targets. It's a table
+// of address ranges and their types.
+class ECCodeMapChunk : public NonSectionChunk {
+public:
+ ECCodeMapChunk(std::vector<ECCodeMapEntry> &map) : map(map) {}
+ size_t getSize() const override;
+ void writeTo(uint8_t *buf) const override;
+
+private:
+ std::vector<ECCodeMapEntry> ↦
+};
+
// MinGW specific, for the "automatic import of variables from DLLs" feature.
// This provides the table of runtime pseudo relocations, for variable
// references that turned out to need to be imported from a DLL even though
diff --git a/lld/COFF/Driver.cpp b/lld/COFF/Driver.cpp
index 5613c2e6993a5af..337b0e6bb0e99b2 100644
--- a/lld/COFF/Driver.cpp
+++ b/lld/COFF/Driver.cpp
@@ -2355,6 +2355,11 @@ void LinkerDriver::linkerMain(ArrayRef<const char *> argsArr) {
ctx.symtab.addAbsolute(mangle("__guard_eh_cont_count"), 0);
ctx.symtab.addAbsolute(mangle("__guard_eh_cont_table"), 0);
+ if (isArm64EC(config->machine)) {
+ ctx.symtab.addAbsolute("__hybrid_code_map", 0);
+ ctx.symtab.addAbsolute("__hybrid_code_map_count", 0);
+ }
+
if (config->pseudoRelocs) {
ctx.symtab.addAbsolute(mangle("__RUNTIME_PSEUDO_RELOC_LIST__"), 0);
ctx.symtab.addAbsolute(mangle("__RUNTIME_PSEUDO_RELOC_LIST_END__"), 0);
diff --git a/lld/COFF/Writer.cpp b/lld/COFF/Writer.cpp
index 960328d686852a3..4ff4b9412974aa1 100644
--- a/lld/COFF/Writer.cpp
+++ b/lld/COFF/Writer.cpp
@@ -221,6 +221,7 @@ class Writer {
uint16_t type, int margin);
bool createThunks(OutputSection *os, int margin);
bool verifyRanges(const std::vector<Chunk *> chunks);
+ void createECCodeMap();
void finalizeAddresses();
void removeEmptySections();
void assignOutputSectionIndices();
@@ -229,6 +230,7 @@ class Writer {
template <typename PEHeaderTy> void writeHeader();
void createSEHTable();
void createRuntimePseudoRelocs();
+ void createECChunks();
void insertCtorDtorSymbols();
void markSymbolsWithRelocations(ObjFile *file, SymbolRVASet &usedSymbols);
void createGuardCFTables();
@@ -271,6 +273,7 @@ class Writer {
std::map<PartialSectionKey, PartialSection *> partialSections;
std::vector<char> strtab;
std::vector<llvm::object::coff_symbol16> outputSymtab;
+ std::vector<ECCodeMapEntry> codeMap;
IdataContents idata;
Chunk *importTableStart = nullptr;
uint64_t importTableSize = 0;
@@ -528,6 +531,53 @@ bool Writer::createThunks(OutputSection *os, int margin) {
return addressesChanged;
}
+// Create a code map for CHPE metadata.
+void Writer::createECCodeMap() {
+ if (!isArm64EC(ctx.config.machine))
+ return;
+
+ // Clear the map in case we were're recomputing the map after adding
+ // a range extension thunk.
+ codeMap.clear();
+
+ std::optional<chpe_range_type> lastType;
+ Chunk *first, *last;
+
+ auto closeRange = [&]() {
+ if (lastType) {
+ codeMap.push_back({first, last, *lastType});
+ lastType.reset();
+ }
+ };
+
+ for (OutputSection *sec : ctx.outputSections) {
+ if (!sec->isCodeSection()) {
+ closeRange();
+ continue;
+ }
+
+ for (Chunk *c : sec->chunks) {
+ // Skip empty section chunks. MSVC does not seem to do that and
+ // generates empty code ranges in some cases.
+ if (isa<SectionChunk>(c) && !c->getSize())
+ continue;
+
+ std::optional<chpe_range_type> chunkType = c->getArm64ECRangeType();
+ if (chunkType != lastType) {
+ closeRange();
+ first = c;
+ lastType = chunkType;
+ }
+ last = c;
+ }
+ }
+
+ closeRange();
+
+ Symbol *tableCountSym = ctx.symtab.findUnderscore("__hybrid_code_map_count");
+ cast<DefinedAbsolute>(tableCountSym)->setVA(codeMap.size());
+}
+
// Verify that all relocations are in range, with no extra margin requirements.
bool Writer::verifyRanges(const std::vector<Chunk *> chunks) {
for (Chunk *c : chunks) {
@@ -1077,6 +1127,9 @@ void Writer::createMiscChunks() {
if (config->guardCF != GuardCFLevel::Off)
createGuardCFTables();
+ if (isArm64EC(config->machine))
+ createECChunks();
+
if (config->autoImport)
createRuntimePseudoRelocs();
@@ -1402,6 +1455,10 @@ void Writer::assignAddresses() {
llvm::TimeTraceScope timeScope("Assign addresses");
Configuration *config = &ctx.config;
+ // We need to create EC code map so that ECCodeMapChunk knows its size.
+ // We do it here to make sure that we account for range extension chunks.
+ createECCodeMap();
+
sizeOfHeaders = dosStubSize + sizeof(PEMagic) + sizeof(coff_file_header) +
sizeof(data_directory) * numberOfDataDirectory +
sizeof(coff_section) * ctx.outputSections.size();
@@ -1937,6 +1994,15 @@ void Writer::maybeAddRVATable(SymbolRVASet tableSymbols, StringRef tableSym,
cast<DefinedAbsolute>(c)->setVA(tableChunk->getSize() / (hasFlag ? 5 : 4));
}
+// Create CHPE metadata chunks.
+void Writer::createECChunks() {
+ auto codeMapChunk = make<ECCodeMapChunk>(codeMap);
+ rdataSec->addChunk(codeMapChunk);
+ Symbol *codeMapSym = ctx.symtab.findUnderscore("__hybrid_code_map");
+ replaceSymbol<DefinedSynthetic>(codeMapSym, codeMapSym->getName(),
+ codeMapChunk);
+}
+
// MinGW specific. Gather all relocations that are imported from a DLL even
// though the code didn't expect it to, produce the table that the runtime
// uses for fixing them up, and provide the synthetic symbols that the
diff --git a/lld/test/COFF/Inputs/loadconfig-arm64ec.s b/lld/test/COFF/Inputs/loadconfig-arm64ec.s
index 1efd02406ca691b..78ae594a21eff3f 100644
--- a/lld/test/COFF/Inputs/loadconfig-arm64ec.s
+++ b/lld/test/COFF/Inputs/loadconfig-arm64ec.s
@@ -64,8 +64,8 @@ __os_arm64x_helper8:
.p2align 3, 0
__chpe_metadata:
.word 1
- .rva code_map
- .word code_map_count
+ .rva __hybrid_code_map
+ .word __hybrid_code_map_count
.word 0 // __x64_code_ranges_to_entry_points
.word 0 //__arm64x_redirection_metadata
.rva __os_arm64x_dispatch_call_no_redirect
diff --git a/lld/test/COFF/arm64ec-codemap.test b/lld/test/COFF/arm64ec-codemap.test
index 24eedc6f8e96e20..f2ad0566c8d20a7 100644
--- a/lld/test/COFF/arm64ec-codemap.test
+++ b/lld/test/COFF/arm64ec-codemap.test
@@ -4,16 +4,15 @@ RUN: split-file %s %t.dir && cd %t.dir
RUN: llvm-mc -filetype=obj -triple=arm64-windows arm64-func-sym.s -o arm64-func-sym.obj
RUN: llvm-mc -filetype=obj -triple=arm64ec-windows arm64ec-func-sym.s -o arm64ec-func-sym.obj
RUN: llvm-mc -filetype=obj -triple=arm64ec-windows data-sec.s -o data-sec.obj
+RUN: llvm-mc -filetype=obj -triple=arm64ec-windows empty-sec.s -o arm64ec-empty-sec.obj
RUN: llvm-mc -filetype=obj -triple=x86_64-windows x86_64-func-sym.s -o x86_64-func-sym.obj
-RUN: llvm-mc -filetype=obj -triple=arm64ec-windows codemap.s -o codemap.obj
-RUN: llvm-mc -filetype=obj -triple=arm64ec-windows codemap2.s -o codemap2.obj
-RUN: llvm-mc -filetype=obj -triple=arm64ec-windows codemap3.s -o codemap3.obj
+RUN: llvm-mc -filetype=obj -triple=x86_64-windows empty-sec.s -o x86_64-empty-sec.obj
RUN: llvm-mc -filetype=obj -triple=arm64ec-windows %S/Inputs/loadconfig-arm64ec.s -o loadconfig-arm64ec.obj
Link ARM64EC DLL and verify that the code is arranged as expected.
RUN: lld-link -out:test.dll -machine:arm64ec arm64ec-func-sym.obj x86_64-func-sym.obj \
-RUN: codemap.obj loadconfig-arm64ec.obj -dll -noentry
+RUN: loadconfig-arm64ec.obj -dll -noentry
RUN: llvm-readobj --coff-load-config test.dll | FileCheck -check-prefix=CODEMAP %s
CODEMAP: CodeMap [
@@ -45,12 +44,18 @@ DISASM-NEXT: 180006005: c3 retq
Order of arguments doesn't matter in this case, chunks are sorted by target type anyway.
RUN: lld-link -out:test2.dll -machine:arm64ec x86_64-func-sym.obj arm64ec-func-sym.obj \
-RUN: codemap.obj loadconfig-arm64ec.obj -dll -noentry
+RUN: loadconfig-arm64ec.obj -dll -noentry
RUN: llvm-readobj --coff-load-config test2.dll | FileCheck -check-prefix=CODEMAP %s
RUN: llvm-objdump -d test2.dll | FileCheck -check-prefix=DISASM %s
RUN: lld-link -out:testx.dll -machine:arm64x arm64-func-sym.obj arm64ec-func-sym.obj \
-RUN: x86_64-func-sym.obj codemap2.obj loadconfig-arm64ec.obj -dll -noentry
+RUN: x86_64-func-sym.obj loadconfig-arm64ec.obj -dll -noentry
+
+Adding empty chunks does not affect code map ranges.
+
+RUN: lld-link -out:test3.dll -machine:arm64ec x86_64-empty-sec.obj arm64ec-empty-sec.obj \
+RUN: arm64ec-func-sym.obj x86_64-func-sym.obj loadconfig-arm64ec.obj -dll -noentry
+RUN: llvm-readobj --coff-load-config test3.dll | FileCheck -check-prefix=CODEMAP %s
Do the same with ARM64X target.
@@ -88,7 +93,7 @@ DISASMX-NEXT: 180007005: c3 retq
Test merged sections.
RUN: lld-link -out:testm.dll -machine:arm64ec arm64ec-func-sym.obj x86_64-func-sym.obj \
-RUN: codemap3.obj loadconfig-arm64ec.obj -dll -noentry -merge:test=.text
+RUN: loadconfig-arm64ec.obj -dll -noentry -merge:test=.text
RUN: llvm-readobj --coff-load-config testm.dll | FileCheck -check-prefix=CODEMAPM %s
CODEMAPM: CodeMap [
@@ -113,7 +118,7 @@ DISASMM-NEXT: 18000200d: c3 retq
Merging data sections into code sections causes data to be separated from the code when sorting chunks.
-RUN: lld-link -out:testdm.dll -machine:arm64ec arm64ec-func-sym.obj x86_64-func-sym.obj codemap.obj \
+RUN: lld-link -out:testdm.dll -machine:arm64ec arm64ec-func-sym.obj x86_64-func-sym.obj \
RUN: data-sec.obj loadconfig-arm64ec.obj -dll -noentry -merge:.testdata=.text -merge:.rdata=test
RUN: llvm-readobj --coff-load-config testdm.dll | FileCheck -check-prefix=CODEMAPDM %s
@@ -187,48 +192,7 @@ x86_64_func_sym2:
.section .testdata, "rd"
.xword 1
-#--- codemap.s
- .section .rdata,"dr"
- .globl code_map
-code_map:
- .rva arm64ec_func_sym + 1
- .word 8
- .rva x86_64_func_sym + 2
- .word 6
- .rva arm64ec_func_sym2 + 1
- .word 8
- .rva x86_64_func_sym2 + 2
- .word 6
-
- .globl code_map_count
-code_map_count = 4
-
-#--- codemap2.s
- .section .rdata,"dr"
- .globl code_map
-code_map:
- .rva arm64_func_sym
- .word 8
- .rva arm64ec_func_sym + 1
- .word 8
- .rva x86_64_func_sym + 2
- .word 6
- .rva arm64ec_func_sym2 + 1
- .word 8
- .rva x86_64_func_sym2 + 2
- .word 6
-
- .globl code_map_count
-code_map_count = 5
-
-#--- codemap3.s
- .section .rdata,"dr"
- .globl code_map
-code_map:
- .rva arm64ec_func_sym + 1
- .word 16
- .rva x86_64_func_sym + 2
- .word 14
-
- .globl code_map_count
-code_map_count = 2
+#--- empty-sec.s
+ .section .empty1, "xr"
+ .section .empty2, "xr"
+ .section .empty3, "xr"
>From 4d9f7fe00d33204c7176effdcba607a2b4c503e9 Mon Sep 17 00:00:00 2001
From: Jacek Caban <jacek at codeweavers.com>
Date: Sat, 11 Nov 2023 17:13:51 +0100
Subject: [PATCH 2/3] Fixed MS link.exe comment, added more tests, dropped
isCodeSection check to take into account code chunks merged into data
sections
---
lld/COFF/Writer.cpp | 7 +---
lld/test/COFF/arm64ec-codemap.test | 62 ++++++++++++++++++++++++++++++
2 files changed, 63 insertions(+), 6 deletions(-)
diff --git a/lld/COFF/Writer.cpp b/lld/COFF/Writer.cpp
index 4ff4b9412974aa1..0bf2c7487b26053 100644
--- a/lld/COFF/Writer.cpp
+++ b/lld/COFF/Writer.cpp
@@ -551,13 +551,8 @@ void Writer::createECCodeMap() {
};
for (OutputSection *sec : ctx.outputSections) {
- if (!sec->isCodeSection()) {
- closeRange();
- continue;
- }
-
for (Chunk *c : sec->chunks) {
- // Skip empty section chunks. MSVC does not seem to do that and
+ // Skip empty section chunks. MS link.exe does not seem to do that and
// generates empty code ranges in some cases.
if (isa<SectionChunk>(c) && !c->getSize())
continue;
diff --git a/lld/test/COFF/arm64ec-codemap.test b/lld/test/COFF/arm64ec-codemap.test
index f2ad0566c8d20a7..da3a4f9e47292c6 100644
--- a/lld/test/COFF/arm64ec-codemap.test
+++ b/lld/test/COFF/arm64ec-codemap.test
@@ -3,6 +3,7 @@ RUN: split-file %s %t.dir && cd %t.dir
RUN: llvm-mc -filetype=obj -triple=arm64-windows arm64-func-sym.s -o arm64-func-sym.obj
RUN: llvm-mc -filetype=obj -triple=arm64ec-windows arm64ec-func-sym.s -o arm64ec-func-sym.obj
+RUN: llvm-mc -filetype=obj -triple=arm64ec-windows arm64ec-func-sym2.s -o arm64ec-func-sym2.obj
RUN: llvm-mc -filetype=obj -triple=arm64ec-windows data-sec.s -o data-sec.obj
RUN: llvm-mc -filetype=obj -triple=arm64ec-windows empty-sec.s -o arm64ec-empty-sec.obj
RUN: llvm-mc -filetype=obj -triple=x86_64-windows x86_64-func-sym.s -o x86_64-func-sym.obj
@@ -150,6 +151,59 @@ DISASMDM-NEXT: ...
DISASMDM-NEXT: 180007000: b8 06 00 00 00 movl $0x6, %eax
DISASMDM-NEXT: 180007005: c3 retq
+Merging a code section into data section produces a valid code map.
+
+RUN: lld-link -out:testcm.dll -machine:arm64ec x86_64-func-sym.obj data-sec.obj \
+RUN: loadconfig-arm64ec.obj -dll -noentry -merge:test=.testdata -merge:.text=.testdata
+
+RUN: llvm-readobj --coff-load-config testcm.dll | FileCheck -check-prefix=CODEMAPCM %s
+CODEMAPCM: CodeMap [
+CODEMAPCM-NEXT: 0x3008 - 0x3016 X64
+CODEMAPCM-NEXT: ]
+
+RUN: llvm-objdump -d testcm.dll | FileCheck -check-prefix=DISASMCM %s
+DISASMCM: Disassembly of section .testdat:
+DISASMCM-EMPTY:
+DISASMCM-NEXT: 0000000180003000 <.testdat>:
+DISASMCM-NEXT: 180003000: 00000001 udf #0x1
+DISASMCM-NEXT: 180003004: 00000000 udf #0x0
+DISASMCM-NEXT: 180003008: b8 03 00 00 00 movl $0x3, %eax
+DISASMCM-NEXT: 18000300d: c3 retq
+DISASMCM-NEXT: 18000300e: 00 00 addb %al, (%rax)
+DISASMCM-NEXT: 180003010: b8 06 00 00 00 movl $0x6, %eax
+DISASMCM-NEXT: 180003015: c3
+
+Test code map range entry spanning over multiple sections.
+
+RUN: lld-link -out:testms.dll -machine:arm64ec arm64ec-func-sym.obj arm64ec-func-sym2.obj \
+RUN: loadconfig-arm64ec.obj -dll -noentry
+
+RUN: llvm-readobj --coff-load-config testms.dll | FileCheck -check-prefix=CODEMAPMS %s
+CODEMAPMS: CodeMap [
+CODEMAPMS-NEXT: 0x1000 - 0x1008 ARM64EC
+CODEMAPMS-NEXT: 0x4000 - 0x5008 ARM64EC
+CODEMAPMS-NEXT: ]
+
+RUN: llvm-objdump -d testms.dll | FileCheck -check-prefix=DISASMMS %s
+DISASMMS: Disassembly of section .text:
+DISASMMS-EMPTY:
+DISASMMS-NEXT: 0000000180001000 <.text>:
+DISASMMS-NEXT: 180001000: 52800040 mov w0, #0x2 // =2
+DISASMMS-NEXT: 180001004: d65f03c0 ret
+DISASMMS-EMPTY:
+DISASMMS-NEXT: Disassembly of section test:
+DISASMMS-EMPTY:
+DISASMMS-NEXT: 0000000180004000 <test>:
+DISASMMS-NEXT: 180004000: 528000a0 mov w0, #0x5 // =5
+DISASMMS-NEXT: 180004004: d65f03c0 ret
+DISASMMS-EMPTY:
+DISASMMS-NEXT: Disassembly of section test2:
+DISASMMS-EMPTY:
+DISASMMS-NEXT: 0000000180005000 <test2>:
+DISASMMS-NEXT: 180005000: 528000a0 mov w0, #0x5 // =5
+DISASMMS-NEXT: 180005004: d65f03c0 ret
+
+
#--- arm64-func-sym.s
.text
.globl arm64_func_sym
@@ -173,6 +227,14 @@ arm64ec_func_sym2:
mov w0, #5
ret
+#--- arm64ec-func-sym2.s
+ .section test2, "xr"
+ .globl arm64ec_func_sym3
+ .p2align 2, 0x0
+arm64ec_func_sym3:
+ mov w0, #5
+ ret
+
#--- x86_64-func-sym.s
.text
.globl x86_64_func_sym
>From b3f99780a177e0d65b90c60a3f230d8f2ff0981b Mon Sep 17 00:00:00 2001
From: Jacek Caban <jacek at codeweavers.com>
Date: Sat, 11 Nov 2023 15:57:48 +0100
Subject: [PATCH 3/3] [lld] Mark target section as code section when merging
code sections into a data section.
---
lld/COFF/Writer.cpp | 8 ++++++
lld/test/COFF/code-merge.s | 56 ++++++++++++++++++++++++++++++++++++++
2 files changed, 64 insertions(+)
create mode 100644 lld/test/COFF/code-merge.s
diff --git a/lld/COFF/Writer.cpp b/lld/COFF/Writer.cpp
index 0bf2c7487b26053..793550729313e85 100644
--- a/lld/COFF/Writer.cpp
+++ b/lld/COFF/Writer.cpp
@@ -349,6 +349,14 @@ void OutputSection::merge(OutputSection *other) {
contribSections.insert(contribSections.end(), other->contribSections.begin(),
other->contribSections.end());
other->contribSections.clear();
+
+ // MS link.exe compatibility: when merging a code section into a data section,
+ // mark the target section as a code section.
+ if (other->header.Characteristics & IMAGE_SCN_CNT_CODE) {
+ header.Characteristics |= IMAGE_SCN_CNT_CODE;
+ header.Characteristics &=
+ ~IMAGE_SCN_CNT_INITIALIZED_DATA | IMAGE_SCN_CNT_UNINITIALIZED_DATA;
+ }
}
// Write the section header to a given buffer.
diff --git a/lld/test/COFF/code-merge.s b/lld/test/COFF/code-merge.s
new file mode 100644
index 000000000000000..5728fbc93ff9b9d
--- /dev/null
+++ b/lld/test/COFF/code-merge.s
@@ -0,0 +1,56 @@
+# REQUIRES: x86
+
+# Test that merging code section into a data section changes its characteristics.
+
+# RUN: llvm-mc -triple x86_64-windows-msvc %s -filetype=obj -o %t.obj
+# RUN: lld-link -machine:amd64 -dll -noentry -out:%t.dll %t.obj -merge:.testx=.testd -merge:.testx2=.testbss
+# RUN: llvm-readobj --sections %t.dll | FileCheck %s
+
+# CHECK: Sections [
+# CHECK-NEXT: Section {
+# CHECK-NEXT: Number: 1
+# CHECK-NEXT: Name: .testbss (2E 74 65 73 74 62 73 73)
+# CHECK-NEXT: VirtualSize: 0xA
+# CHECK-NEXT: VirtualAddress: 0x1000
+# CHECK-NEXT: RawDataSize: 512
+# CHECK-NEXT: PointerToRawData: 0x400
+# CHECK-NEXT: PointerToRelocations: 0x0
+# CHECK-NEXT: PointerToLineNumbers: 0x0
+# CHECK-NEXT: RelocationCount: 0
+# CHECK-NEXT: LineNumberCount: 0
+# CHECK-NEXT: Characteristics [ (0x40000020)
+# CHECK-NEXT: IMAGE_SCN_CNT_CODE (0x20)
+# CHECK-NEXT: IMAGE_SCN_MEM_READ (0x40000000)
+# CHECK-NEXT: ]
+# CHECK-NEXT: }
+# CHECK-NEXT: Section {
+# CHECK-NEXT: Number: 2
+# CHECK-NEXT: Name: .testd (2E 74 65 73 74 64 00 00)
+# CHECK-NEXT: VirtualSize: 0xA
+# CHECK-NEXT: VirtualAddress: 0x2000
+# CHECK-NEXT: RawDataSize: 512
+# CHECK-NEXT: PointerToRawData: 0x600
+# CHECK-NEXT: PointerToRelocations: 0x0
+# CHECK-NEXT: PointerToLineNumbers: 0x0
+# CHECK-NEXT: RelocationCount: 0
+# CHECK-NEXT: LineNumberCount: 0
+# CHECK-NEXT: Characteristics [ (0x40000020)
+# CHECK-NEXT: IMAGE_SCN_CNT_CODE (0x20)
+# CHECK-NEXT: IMAGE_SCN_MEM_READ (0x40000000)
+# CHECK-NEXT: ]
+# CHECK-NEXT: }
+# CHECK-NEXT: ]
+
+ .section .testx, "xr"
+ movq $1, %rax
+ retq
+
+ .section .testx2, "xr"
+ movq $2, %rax
+ retq
+
+ .section .testd, "dr"
+ .word 1
+
+ .section .testbss, "br"
+ .word 0
More information about the llvm-commits
mailing list