11
11
#include " Error.h"
12
12
#include " InputFiles.h"
13
13
#include " Symbols.h"
14
+ #include " Writer.h"
14
15
#include " llvm/ADT/Twine.h"
15
16
#include " llvm/BinaryFormat/COFF.h"
16
17
#include " llvm/Object/COFF.h"
@@ -52,9 +53,27 @@ static void add32(uint8_t *P, int32_t V) { write32le(P, read32le(P) + V); }
52
53
static void add64 (uint8_t *P, int64_t V) { write64le (P, read64le (P) + V); }
53
54
static void or16 (uint8_t *P, uint16_t V) { write16le (P, read16le (P) | V); }
54
55
55
- void SectionChunk::applyRelX64 (uint8_t *Off, uint16_t Type, Defined *Sym,
56
- uint64_t P) const {
57
- uint64_t S = Sym->getRVA ();
56
+ static void applySecRel (const SectionChunk *Sec, uint8_t *Off,
57
+ OutputSection *OS, uint64_t S) {
58
+ if (!OS) {
59
+ if (Sec->isCodeView ())
60
+ return ;
61
+ fatal (" SECREL relocation cannot be applied to absolute symbols" );
62
+ }
63
+ uint64_t SecRel = S - OS->getRVA ();
64
+ assert (SecRel < INT32_MAX && " overflow in SECREL relocation" );
65
+ add32 (Off, SecRel);
66
+ }
67
+
68
+ static void applySecIdx (uint8_t *Off, OutputSection *OS) {
69
+ // If we have no output section, this must be an absolute symbol. Use the
70
+ // sentinel absolute symbol section index.
71
+ uint16_t SecIdx = OS ? OS->SectionIndex : DefinedAbsolute::OutputSectionIndex;
72
+ add16 (Off, SecIdx);
73
+ }
74
+
75
+ void SectionChunk::applyRelX64 (uint8_t *Off, uint16_t Type, OutputSection *OS,
76
+ uint64_t S, uint64_t P) const {
58
77
switch (Type) {
59
78
case IMAGE_REL_AMD64_ADDR32: add32 (Off, S + Config->ImageBase ); break ;
60
79
case IMAGE_REL_AMD64_ADDR64: add64 (Off, S + Config->ImageBase ); break ;
@@ -65,23 +84,22 @@ void SectionChunk::applyRelX64(uint8_t *Off, uint16_t Type, Defined *Sym,
65
84
case IMAGE_REL_AMD64_REL32_3: add32 (Off, S - P - 7 ); break ;
66
85
case IMAGE_REL_AMD64_REL32_4: add32 (Off, S - P - 8 ); break ;
67
86
case IMAGE_REL_AMD64_REL32_5: add32 (Off, S - P - 9 ); break ;
68
- case IMAGE_REL_AMD64_SECTION: add16 (Off, Sym-> getSectionIndex () ); break ;
69
- case IMAGE_REL_AMD64_SECREL: add32 ( Off, Sym-> getSecrel () ); break ;
87
+ case IMAGE_REL_AMD64_SECTION: applySecIdx (Off, OS ); break ;
88
+ case IMAGE_REL_AMD64_SECREL: applySecRel ( this , Off, OS, S ); break ;
70
89
default :
71
90
fatal (" unsupported relocation type 0x" + Twine::utohexstr (Type));
72
91
}
73
92
}
74
93
75
- void SectionChunk::applyRelX86 (uint8_t *Off, uint16_t Type, Defined *Sym,
76
- uint64_t P) const {
77
- uint64_t S = Sym->getRVA ();
94
+ void SectionChunk::applyRelX86 (uint8_t *Off, uint16_t Type, OutputSection *OS,
95
+ uint64_t S, uint64_t P) const {
78
96
switch (Type) {
79
97
case IMAGE_REL_I386_ABSOLUTE: break ;
80
98
case IMAGE_REL_I386_DIR32: add32 (Off, S + Config->ImageBase ); break ;
81
99
case IMAGE_REL_I386_DIR32NB: add32 (Off, S); break ;
82
100
case IMAGE_REL_I386_REL32: add32 (Off, S - P - 4 ); break ;
83
- case IMAGE_REL_I386_SECTION: add16 (Off, Sym-> getSectionIndex () ); break ;
84
- case IMAGE_REL_I386_SECREL: add32 ( Off, Sym-> getSecrel () ); break ;
101
+ case IMAGE_REL_I386_SECTION: applySecIdx (Off, OS ); break ;
102
+ case IMAGE_REL_I386_SECREL: applySecRel ( this , Off, OS, S ); break ;
85
103
default :
86
104
fatal (" unsupported relocation type 0x" + Twine::utohexstr (Type));
87
105
}
@@ -128,20 +146,21 @@ static void applyBranch24T(uint8_t *Off, int32_t V) {
128
146
write16le (Off + 2 , (read16le (Off + 2 ) & 0xd000 ) | (J1 << 13 ) | (J2 << 11 ) | ((V >> 1 ) & 0x7ff ));
129
147
}
130
148
131
- void SectionChunk::applyRelARM (uint8_t *Off, uint16_t Type, Defined *Sym,
132
- uint64_t P) const {
133
- uint64_t S = Sym->getRVA ();
149
+ void SectionChunk::applyRelARM (uint8_t *Off, uint16_t Type, OutputSection *OS,
150
+ uint64_t S, uint64_t P) const {
134
151
// Pointer to thumb code must have the LSB set.
135
- if (Sym->isExecutable ())
136
- S |= 1 ;
152
+ uint64_t SX = S;
153
+ if (OS && (OS->getPermissions () & IMAGE_SCN_MEM_EXECUTE))
154
+ SX |= 1 ;
137
155
switch (Type) {
138
- case IMAGE_REL_ARM_ADDR32: add32 (Off, S + Config->ImageBase ); break ;
139
- case IMAGE_REL_ARM_ADDR32NB: add32 (Off, S); break ;
140
- case IMAGE_REL_ARM_MOV32T: applyMOV32T (Off, S + Config->ImageBase ); break ;
141
- case IMAGE_REL_ARM_BRANCH20T: applyBranch20T (Off, S - P - 4 ); break ;
142
- case IMAGE_REL_ARM_BRANCH24T: applyBranch24T (Off, S - P - 4 ); break ;
143
- case IMAGE_REL_ARM_BLX23T: applyBranch24T (Off, S - P - 4 ); break ;
144
- case IMAGE_REL_ARM_SECREL: add32 (Off, Sym->getSecrel ()); break ;
156
+ case IMAGE_REL_ARM_ADDR32: add32 (Off, SX + Config->ImageBase ); break ;
157
+ case IMAGE_REL_ARM_ADDR32NB: add32 (Off, SX); break ;
158
+ case IMAGE_REL_ARM_MOV32T: applyMOV32T (Off, SX + Config->ImageBase ); break ;
159
+ case IMAGE_REL_ARM_BRANCH20T: applyBranch20T (Off, SX - P - 4 ); break ;
160
+ case IMAGE_REL_ARM_BRANCH24T: applyBranch24T (Off, SX - P - 4 ); break ;
161
+ case IMAGE_REL_ARM_BLX23T: applyBranch24T (Off, SX - P - 4 ); break ;
162
+ case IMAGE_REL_ARM_SECTION: applySecIdx (Off, OS); break ;
163
+ case IMAGE_REL_ARM_SECREL: applySecRel (this , Off, OS, S); break ;
145
164
default :
146
165
fatal (" unsupported relocation type 0x" + Twine::utohexstr (Type));
147
166
}
@@ -157,18 +176,39 @@ void SectionChunk::writeTo(uint8_t *Buf) const {
157
176
// Apply relocations.
158
177
for (const coff_relocation &Rel : Relocs) {
159
178
uint8_t *Off = Buf + OutputSectionOff + Rel.VirtualAddress ;
179
+
180
+ // Get the output section of the symbol for this relocation. The output
181
+ // section is needed to compute SECREL and SECTION relocations used in debug
182
+ // info.
160
183
SymbolBody *Body = File->getSymbolBody (Rel.SymbolTableIndex );
161
184
Defined *Sym = cast<Defined>(Body);
185
+ Chunk *C = Sym->getChunk ();
186
+ OutputSection *OS = C ? C->getOutputSection () : nullptr ;
187
+
188
+ // Only absolute and __ImageBase symbols lack an output section. For any
189
+ // other symbol, this indicates that the chunk was discarded. Normally
190
+ // relocations against discarded sections are an error. However, debug info
191
+ // sections are not GC roots and can end up with these kinds of relocations.
192
+ // Skip these relocations.
193
+ if (!OS && !isa<DefinedAbsolute>(Sym) && !isa<DefinedSynthetic>(Sym)) {
194
+ if (isCodeView ())
195
+ continue ;
196
+ fatal (" relocation against symbol in discarded section: " +
197
+ Sym->getName ());
198
+ }
199
+ uint64_t S = Sym->getRVA ();
200
+
201
+ // Compute the RVA of the relocation for relative relocations.
162
202
uint64_t P = RVA + Rel.VirtualAddress ;
163
203
switch (Config->Machine ) {
164
204
case AMD64:
165
- applyRelX64 (Off, Rel.Type , Sym , P);
205
+ applyRelX64 (Off, Rel.Type , OS, S , P);
166
206
break ;
167
207
case I386:
168
- applyRelX86 (Off, Rel.Type , Sym , P);
208
+ applyRelX86 (Off, Rel.Type , OS, S , P);
169
209
break ;
170
210
case ARMNT:
171
- applyRelARM (Off, Rel.Type , Sym , P);
211
+ applyRelARM (Off, Rel.Type , OS, S , P);
172
212
break ;
173
213
default :
174
214
llvm_unreachable (" unknown machine type" );
0 commit comments