Skip to content

Commit d16b107

Browse files
[wasm-ld][Coverage] Align __llvm_{covfun,covmap} sections to 8 bytes
This patch aligns the `__llvm_{covfun,covmap}` sections to 8 bytes at the linking stage. This is required because llvm-cov assumes that records in the sections are 8-byte aligned. Unfortunately, custom sections does not have an alignment attribute in the WebAssembly linking spec, so we temporarily do a special case for the metadata sections. In the future, we should generalize this to support alignment for relocatable custom sections.
1 parent a633069 commit d16b107

File tree

4 files changed

+54
-6
lines changed

4 files changed

+54
-6
lines changed

lld/test/wasm/custom-section-align.s

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
# RUN: llvm-mc -filetype=obj -triple=wasm32-unknown-unknown -o %t.o %s
2+
# RUN: wasm-ld --no-entry %t.o -o %t.wasm
3+
# RUN: obj2yaml %t.wasm | FileCheck %s
4+
5+
# Check that "__llvm_covfun" custom section is aligned to 8 bytes.
6+
7+
.section .custom_section.__llvm_covfun,"GR",@,__covrec_A
8+
.int32 1
9+
.int8 2
10+
# pad .int8 0
11+
# .int8 0
12+
# .int8 0
13+
14+
.section .custom_section.__llvm_covfun,"GR",@,__covrec_B
15+
.int32 3
16+
17+
# CHECK: - Type: CUSTOM
18+
# CHECK-NEXT: Name: __llvm_covfun
19+
# CHECK-NEXT: Payload: '010000000200000003000000'
20+
21+
# Check that regular custom sections are not aligned.
22+
.section .custom_section.foo,"GR",@,foo_A
23+
.int32 1
24+
.int8 2
25+
26+
.section .custom_section.foo,"GR",@,foo_B
27+
.int32 3
28+
29+
# CHECK: - Type: CUSTOM
30+
# CHECK-NEXT: Name: foo
31+
# CHECK-NEXT: Payload: '010000000203000000'

lld/wasm/InputChunks.h

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -177,8 +177,9 @@ class MergeInputChunk : public InputChunk {
177177
inputSectionOffset = seg.SectionOffset;
178178
}
179179

180-
MergeInputChunk(const WasmSection &s, ObjFile *f)
181-
: InputChunk(f, Merge, s.Name, 0, llvm::wasm::WASM_SEG_FLAG_STRINGS) {
180+
MergeInputChunk(const WasmSection &s, ObjFile *f, uint32_t alignment)
181+
: InputChunk(f, Merge, s.Name, alignment,
182+
llvm::wasm::WASM_SEG_FLAG_STRINGS) {
182183
assert(s.Type == llvm::wasm::WASM_SEC_CUSTOM);
183184
comdat = s.Comdat;
184185
rawData = s.Content;
@@ -234,6 +235,7 @@ class SyntheticMergedChunk : public InputChunk {
234235

235236
void addMergeChunk(MergeInputChunk *ms) {
236237
comdat = ms->getComdat();
238+
alignment = std::max(alignment, ms->alignment);
237239
ms->parent = this;
238240
chunks.push_back(ms);
239241
}
@@ -337,8 +339,8 @@ class SyntheticFunction : public InputFunction {
337339
// Represents a single Wasm Section within an input file.
338340
class InputSection : public InputChunk {
339341
public:
340-
InputSection(const WasmSection &s, ObjFile *f)
341-
: InputChunk(f, InputChunk::Section, s.Name),
342+
InputSection(const WasmSection &s, ObjFile *f, uint32_t alignment)
343+
: InputChunk(f, InputChunk::Section, s.Name, alignment),
342344
tombstoneValue(getTombstoneForSection(s.Name)), section(s) {
343345
assert(section.Type == llvm::wasm::WASM_SEC_CUSTOM);
344346
comdat = section.Comdat;

lld/wasm/InputFiles.cpp

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
#include "llvm/BinaryFormat/Wasm.h"
1919
#include "llvm/Object/Binary.h"
2020
#include "llvm/Object/Wasm.h"
21+
#include "llvm/ProfileData/InstrProf.h"
2122
#include "llvm/Support/Path.h"
2223
#include "llvm/Support/TarWriter.h"
2324
#include "llvm/Support/raw_ostream.h"
@@ -451,6 +452,18 @@ void SharedFile::parse() {
451452
}
452453
}
453454

455+
/// Returns the alignment for a custom section. This is used to concatenate
456+
/// custom sections with the same name into a single custom section.
457+
static uint32_t getCustomSectionAlignment(const WasmSection &sec) {
458+
// TODO: Add a section attribute for alignment in the linking spec.
459+
if (sec.Name == getInstrProfSectionName(IPSK_covfun, Triple::Wasm) ||
460+
sec.Name == getInstrProfSectionName(IPSK_covmap, Triple::Wasm)) {
461+
// llvm-cov assumes that coverage metadata sections are 8-byte aligned.
462+
return 8;
463+
}
464+
return 1;
465+
}
466+
454467
WasmFileBase::WasmFileBase(Kind k, MemoryBufferRef m) : InputFile(k, m) {
455468
// Parse a memory buffer as a wasm file.
456469
LLVM_DEBUG(dbgs() << "Reading object: " << toString(this) << "\n");
@@ -520,10 +533,11 @@ void ObjFile::parse(bool ignoreComdats) {
520533
dataSection = &section;
521534
} else if (section.Type == WASM_SEC_CUSTOM) {
522535
InputChunk *customSec;
536+
uint32_t alignment = getCustomSectionAlignment(section);
523537
if (shouldMerge(section))
524-
customSec = make<MergeInputChunk>(section, this);
538+
customSec = make<MergeInputChunk>(section, this, alignment);
525539
else
526-
customSec = make<InputSection>(section, this);
540+
customSec = make<InputSection>(section, this, alignment);
527541
customSec->discarded = isExcludedByComdat(customSec);
528542
customSections.emplace_back(customSec);
529543
customSections.back()->setRelocations(section.Relocations);

lld/wasm/OutputSections.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -244,6 +244,7 @@ void CustomSection::finalizeContents() {
244244

245245
for (InputChunk *section : inputSections) {
246246
assert(!section->discarded);
247+
payloadSize = alignTo(payloadSize, section->alignment);
247248
section->outSecOff = payloadSize;
248249
payloadSize += section->getSize();
249250
}

0 commit comments

Comments
 (0)