@@ -150,14 +150,15 @@ class UnwindInfoSectionImpl final : public UnwindInfoSection {
150
150
public:
151
151
UnwindInfoSectionImpl () : cuOffsets(target->wordSize) {}
152
152
uint64_t getSize () const override { return unwindInfoSize; }
153
- void prepareRelocations () override ;
153
+ void prepare () override ;
154
154
void finalize () override ;
155
155
void writeTo (uint8_t *buf) const override ;
156
156
157
157
private:
158
158
void prepareRelocations (ConcatInputSection *);
159
159
void relocateCompactUnwind (std::vector<CompactUnwindEntry> &);
160
160
void encodePersonalities ();
161
+ Symbol *canonicalizePersonality (Symbol *);
161
162
162
163
uint64_t unwindInfoSize = 0 ;
163
164
std::vector<decltype (symbols)::value_type> symbolsVec;
@@ -210,14 +211,24 @@ void UnwindInfoSection::addSymbol(const Defined *d) {
210
211
}
211
212
}
212
213
213
- void UnwindInfoSectionImpl::prepareRelocations () {
214
+ void UnwindInfoSectionImpl::prepare () {
214
215
// This iteration needs to be deterministic, since prepareRelocations may add
215
216
// entries to the GOT. Hence the use of a MapVector for
216
217
// UnwindInfoSection::symbols.
217
218
for (const Defined *d : make_second_range (symbols))
218
- if (d->unwindEntry &&
219
- d->unwindEntry ->getName () == section_names::compactUnwind)
220
- prepareRelocations (d->unwindEntry );
219
+ if (d->unwindEntry ) {
220
+ if (d->unwindEntry ->getName () == section_names::compactUnwind) {
221
+ prepareRelocations (d->unwindEntry );
222
+ } else {
223
+ // We don't have to add entries to the GOT here because FDEs have
224
+ // explicit GOT relocations, so Writer::scanRelocations() will add those
225
+ // GOT entries. However, we still need to canonicalize the personality
226
+ // pointers (like prepareRelocations() does for CU entries) in order
227
+ // to avoid overflowing the 3-personality limit.
228
+ FDE &fde = cast<ObjFile>(d->getFile ())->fdes [d->unwindEntry ];
229
+ fde.personality = canonicalizePersonality (fde.personality );
230
+ }
231
+ }
221
232
}
222
233
223
234
// Compact unwind relocations have different semantics, so we handle them in a
@@ -271,6 +282,7 @@ void UnwindInfoSectionImpl::prepareRelocations(ConcatInputSection *isec) {
271
282
continue ;
272
283
}
273
284
285
+ // Similar to canonicalizePersonality(), but we also register a GOT entry.
274
286
if (auto *defined = dyn_cast<Defined>(s)) {
275
287
// Check if we have created a synthetic symbol at the same address.
276
288
Symbol *&personality =
@@ -283,6 +295,7 @@ void UnwindInfoSectionImpl::prepareRelocations(ConcatInputSection *isec) {
283
295
}
284
296
continue ;
285
297
}
298
+
286
299
assert (isa<DylibSymbol>(s));
287
300
in.got ->addEntry (s);
288
301
continue ;
@@ -312,6 +325,18 @@ void UnwindInfoSectionImpl::prepareRelocations(ConcatInputSection *isec) {
312
325
}
313
326
}
314
327
328
+ Symbol *UnwindInfoSectionImpl::canonicalizePersonality (Symbol *personality) {
329
+ if (auto *defined = dyn_cast_or_null<Defined>(personality)) {
330
+ // Check if we have created a synthetic symbol at the same address.
331
+ Symbol *&synth = personalityTable[{defined->isec , defined->value }];
332
+ if (synth == nullptr )
333
+ synth = defined;
334
+ else if (synth != defined)
335
+ return synth;
336
+ }
337
+ return personality;
338
+ }
339
+
315
340
// We need to apply the relocations to the pre-link compact unwind section
316
341
// before converting it to post-link form. There should only be absolute
317
342
// relocations here: since we are not emitting the pre-link CU section, there
0 commit comments