Skip to content

Commit d2752aa

Browse files
committedAug 14, 2017
[COFF] Add support for aligncomm directives
These are emitted for comm symbols in object files, when targeting a GNU environment. Alternatively, just ignore them since we already align CommonChunk to the natural size of the content (up to 32 bytes). That would only trade away the possibility to overalign small symbols, which doesn't sound like something that might not need to be handled? Differential Revision: https://reviews.llvm.org/D36304 llvm-svn: 310871
1 parent 914c836 commit d2752aa

File tree

9 files changed

+129
-1
lines changed

9 files changed

+129
-1
lines changed
 

‎lld/COFF/Chunks.cpp

+4
Original file line numberDiff line numberDiff line change
@@ -377,6 +377,10 @@ CommonChunk::CommonChunk(const COFFSymbolRef S) : Sym(S) {
377377
Align = std::min(uint64_t(32), PowerOf2Ceil(Sym.getValue()));
378378
}
379379

380+
void CommonChunk::setAlign(uint32_t NewAlign) {
381+
Align = std::max(Align, NewAlign);
382+
}
383+
380384
uint32_t CommonChunk::getPermissions() const {
381385
return IMAGE_SCN_CNT_UNINITIALIZED_DATA | IMAGE_SCN_MEM_READ |
382386
IMAGE_SCN_MEM_WRITE;

‎lld/COFF/Chunks.h

+1
Original file line numberDiff line numberDiff line change
@@ -243,6 +243,7 @@ class CommonChunk : public Chunk {
243243
bool hasData() const override { return false; }
244244
uint32_t getPermissions() const override;
245245
StringRef getSectionName() const override { return ".bss"; }
246+
void setAlign(uint32_t NewAlign);
246247

247248
private:
248249
const COFFSymbolRef Sym;

‎lld/COFF/Config.h

+3
Original file line numberDiff line numberDiff line change
@@ -139,6 +139,9 @@ struct Configuration {
139139
StringRef ManifestUIAccess = "'false'";
140140
StringRef ManifestFile;
141141

142+
// Used for /aligncomm.
143+
std::map<std::string, int> AlignComm;
144+
142145
// Used for /failifmismatch.
143146
std::map<StringRef, StringRef> MustMatch;
144147

‎lld/COFF/Driver.cpp

+24
Original file line numberDiff line numberDiff line change
@@ -202,6 +202,9 @@ void LinkerDriver::parseDirectives(StringRef S) {
202202

203203
for (auto *Arg : Args) {
204204
switch (Arg->getOption().getUnaliasedOption().getID()) {
205+
case OPT_aligncomm:
206+
parseAligncomm(Arg->getValue());
207+
break;
205208
case OPT_alternatename:
206209
parseAlternateName(Arg->getValue());
207210
break;
@@ -899,6 +902,10 @@ void LinkerDriver::link(ArrayRef<const char *> ArgsArr) {
899902
for (auto *Arg : Args.filtered(OPT_section))
900903
parseSection(Arg->getValue());
901904

905+
// Handle /aligncomm
906+
for (auto *Arg : Args.filtered(OPT_aligncomm))
907+
parseAligncomm(Arg->getValue());
908+
902909
// Handle /manifestdependency. This enables /manifest unless /manifest:no is
903910
// also passed.
904911
if (auto *Arg = Args.getLastArg(OPT_manifestdependency)) {
@@ -1158,6 +1165,23 @@ void LinkerDriver::link(ArrayRef<const char *> ArgsArr) {
11581165
assignExportOrdinals();
11591166
}
11601167

1168+
// Set extra alignment for .comm symbols
1169+
for (auto Pair : Config->AlignComm) {
1170+
StringRef Name = Pair.first;
1171+
int Align = Pair.second;
1172+
Symbol *Sym = Symtab.find(Name);
1173+
if (!Sym) {
1174+
warn("/aligncomm symbol " + Name + " not found");
1175+
continue;
1176+
}
1177+
auto *DC = dyn_cast<DefinedCommon>(Sym->body());
1178+
if (!DC) {
1179+
warn("/aligncomm symbol " + Name + " of wrong kind");
1180+
continue;
1181+
}
1182+
DC->getChunk()->setAlign(Align);
1183+
}
1184+
11611185
// Windows specific -- Create a side-by-side manifest file.
11621186
if (Config->Manifest == Configuration::SideBySide)
11631187
createSideBySideManifest();

‎lld/COFF/Driver.h

+1
Original file line numberDiff line numberDiff line change
@@ -145,6 +145,7 @@ void parseSubsystem(StringRef Arg, WindowsSubsystem *Sys, uint32_t *Major,
145145
void parseAlternateName(StringRef);
146146
void parseMerge(StringRef);
147147
void parseSection(StringRef);
148+
void parseAligncomm(StringRef);
148149

149150
// Parses a string in the form of "EMBED[,=<integer>]|NO".
150151
void parseManifest(StringRef Arg);

‎lld/COFF/DriverUtils.cpp

+16
Original file line numberDiff line numberDiff line change
@@ -221,6 +221,22 @@ void parseSection(StringRef S) {
221221
Config->Section[Name] = parseSectionAttributes(Attrs);
222222
}
223223

224+
// Parses /aligncomm option argument.
225+
void parseAligncomm(StringRef S) {
226+
StringRef Name, Align;
227+
std::tie(Name, Align) = S.split(',');
228+
if (Name.empty() || Align.empty()) {
229+
error("/aligncomm: invalid argument: " + S);
230+
return;
231+
}
232+
int V;
233+
if (Align.getAsInteger(0, V)) {
234+
error("/aligncomm: invalid argument: " + S);
235+
return;
236+
}
237+
Config->AlignComm[Name] = std::max(Config->AlignComm[Name], 1 << V);
238+
}
239+
224240
// Parses a string in the form of "EMBED[,=<integer>]|NO".
225241
// Results are directly written to Config.
226242
void parseManifest(StringRef Arg) {

‎lld/COFF/Options.td

+1
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ multiclass B<string name, string help> {
1616
}
1717

1818
def align : P<"align", "Section alignment">;
19+
def aligncomm : P<"aligncomm", "Set common symbol alignment">;
1920
def alternatename : P<"alternatename", "Define weak alias">;
2021
def base : P<"base", "Base address of the program">;
2122
def defaultlib : P<"defaultlib", "Add the library to the list of input files">;

‎lld/COFF/Symbols.h

+1-1
Original file line numberDiff line numberDiff line change
@@ -182,7 +182,7 @@ class DefinedCommon : public DefinedCOFF {
182182
}
183183

184184
uint64_t getRVA() { return Data->getRVA(); }
185-
Chunk *getChunk() { return Data; }
185+
CommonChunk *getChunk() { return Data; }
186186

187187
private:
188188
friend SymbolTable;

‎lld/test/COFF/common-alignment.test

+78
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
# REQUIRES: x86
2+
# RUN: yaml2obj %s > %t.obj
3+
# RUN: lld-link /out:%t.exe /entry:main %t.obj %t.obj
4+
# RUN: llvm-objdump -d %t.exe | FileCheck %s
5+
6+
# Operands of B8 (MOV EAX) are common symbols
7+
# CHECK: 3000: b8 00 10 00 40
8+
# CHECK: 3005: b8 10 10 00 40
9+
10+
--- !COFF
11+
header:
12+
Machine: IMAGE_FILE_MACHINE_AMD64
13+
Characteristics: []
14+
sections:
15+
- Name: .text
16+
Characteristics: [ IMAGE_SCN_CNT_CODE, IMAGE_SCN_MEM_EXECUTE, IMAGE_SCN_MEM_READ ]
17+
Alignment: 4
18+
SectionData: b800000000b800000000
19+
Relocations:
20+
- VirtualAddress: 1
21+
SymbolName: bssdata4
22+
Type: IMAGE_REL_AMD64_ADDR32
23+
- VirtualAddress: 6
24+
SymbolName: bssdata4_align16
25+
Type: IMAGE_REL_AMD64_ADDR32
26+
- Name: .data
27+
Characteristics: [ IMAGE_SCN_CNT_INITIALIZED_DATA, IMAGE_SCN_MEM_READ, IMAGE_SCN_MEM_WRITE ]
28+
Alignment: 4
29+
SectionData: 03000000
30+
- Name: .drectve
31+
Characteristics: [ IMAGE_SCN_LNK_INFO, IMAGE_SCN_LNK_REMOVE ]
32+
Alignment: 1
33+
SectionData: 202d616c69676e636f6d6d3a62737364617461345f616c69676e31362c340a # -aligncomm:bssdata4_align16,4
34+
35+
symbols:
36+
- Name: .text
37+
Value: 0
38+
SectionNumber: 1
39+
SimpleType: IMAGE_SYM_TYPE_NULL
40+
ComplexType: IMAGE_SYM_DTYPE_NULL
41+
StorageClass: IMAGE_SYM_CLASS_STATIC
42+
SectionDefinition:
43+
Length: 0
44+
NumberOfRelocations: 5
45+
NumberOfLinenumbers: 0
46+
CheckSum: 0
47+
Number: 0
48+
- Name: .data
49+
Value: 0
50+
SectionNumber: 2
51+
SimpleType: IMAGE_SYM_TYPE_NULL
52+
ComplexType: IMAGE_SYM_DTYPE_NULL
53+
StorageClass: IMAGE_SYM_CLASS_STATIC
54+
SectionDefinition:
55+
Length: 4
56+
NumberOfRelocations: 0
57+
NumberOfLinenumbers: 0
58+
CheckSum: 0
59+
Number: 0
60+
- Name: main
61+
Value: 0
62+
SectionNumber: 1
63+
SimpleType: IMAGE_SYM_TYPE_NULL
64+
ComplexType: IMAGE_SYM_DTYPE_FUNCTION
65+
StorageClass: IMAGE_SYM_CLASS_EXTERNAL
66+
- Name: bssdata4
67+
Value: 4
68+
SectionNumber: 0
69+
SimpleType: IMAGE_SYM_TYPE_NULL
70+
ComplexType: IMAGE_SYM_DTYPE_NULL
71+
StorageClass: IMAGE_SYM_CLASS_EXTERNAL
72+
- Name: bssdata4_align16
73+
Value: 4
74+
SectionNumber: 0
75+
SimpleType: IMAGE_SYM_TYPE_NULL
76+
ComplexType: IMAGE_SYM_DTYPE_NULL
77+
StorageClass: IMAGE_SYM_CLASS_EXTERNAL
78+
...

0 commit comments

Comments
 (0)
Please sign in to comment.