@@ -385,7 +385,7 @@ void ObjFile::parseSections(ArrayRef<SectionHeader> sectionHeaders) {
385
385
}
386
386
387
387
void ObjFile::splitEhFrames (ArrayRef<uint8_t > data, Section &ehFrameSection) {
388
- EhReader reader (this , data, /* dataOff=*/ 0 , target-> wordSize );
388
+ EhReader reader (this , data, /* dataOff=*/ 0 );
389
389
size_t off = 0 ;
390
390
while (off < reader.size ()) {
391
391
uint64_t frameOff = off;
@@ -1293,19 +1293,32 @@ void ObjFile::registerCompactUnwind(Section &compactUnwindSection) {
1293
1293
1294
1294
struct CIE {
1295
1295
macho::Symbol *personalitySymbol = nullptr ;
1296
- bool fdesHaveLsda = false ;
1297
1296
bool fdesHaveAug = false ;
1297
+ uint8_t lsdaPtrSize = 0 ; // 0 => no LSDA
1298
+ uint8_t funcPtrSize = 0 ;
1298
1299
};
1299
1300
1301
+ static uint8_t pointerEncodingToSize (uint8_t enc) {
1302
+ switch (enc & 0xf ) {
1303
+ case dwarf::DW_EH_PE_absptr:
1304
+ return target->wordSize ;
1305
+ case dwarf::DW_EH_PE_sdata4:
1306
+ return 4 ;
1307
+ case dwarf::DW_EH_PE_sdata8:
1308
+ // ld64 doesn't actually support sdata8, but this seems simple enough...
1309
+ return 8 ;
1310
+ default :
1311
+ return 0 ;
1312
+ };
1313
+ }
1314
+
1300
1315
static CIE parseCIE (const InputSection *isec, const EhReader &reader,
1301
1316
size_t off) {
1302
1317
// Handling the full generality of possible DWARF encodings would be a major
1303
1318
// pain. We instead take advantage of our knowledge of how llvm-mc encodes
1304
1319
// DWARF and handle just that.
1305
1320
constexpr uint8_t expectedPersonalityEnc =
1306
1321
dwarf::DW_EH_PE_pcrel | dwarf::DW_EH_PE_indirect | dwarf::DW_EH_PE_sdata4;
1307
- constexpr uint8_t expectedPointerEnc =
1308
- dwarf::DW_EH_PE_pcrel | dwarf::DW_EH_PE_absptr;
1309
1322
1310
1323
CIE cie;
1311
1324
uint8_t version = reader.readByte (&off);
@@ -1332,16 +1345,17 @@ static CIE parseCIE(const InputSection *isec, const EhReader &reader,
1332
1345
break ;
1333
1346
}
1334
1347
case ' L' : {
1335
- cie.fdesHaveLsda = true ;
1336
1348
uint8_t lsdaEnc = reader.readByte (&off);
1337
- if (lsdaEnc != expectedPointerEnc)
1349
+ cie.lsdaPtrSize = pointerEncodingToSize (lsdaEnc);
1350
+ if (cie.lsdaPtrSize == 0 )
1338
1351
reader.failOn (off, " unexpected LSDA encoding 0x" +
1339
1352
Twine::utohexstr (lsdaEnc));
1340
1353
break ;
1341
1354
}
1342
1355
case ' R' : {
1343
1356
uint8_t pointerEnc = reader.readByte (&off);
1344
- if (pointerEnc != expectedPointerEnc)
1357
+ cie.funcPtrSize = pointerEncodingToSize (pointerEnc);
1358
+ if (cie.funcPtrSize == 0 || !(pointerEnc & dwarf::DW_EH_PE_pcrel))
1345
1359
reader.failOn (off, " unexpected pointer encoding 0x" +
1346
1360
Twine::utohexstr (pointerEnc));
1347
1361
break ;
@@ -1471,7 +1485,7 @@ void ObjFile::registerEhFrames(Section &ehFrameSection) {
1471
1485
else if (isec->symbols [0 ]->value != 0 )
1472
1486
fatal (" found symbol at unexpected offset in __eh_frame" );
1473
1487
1474
- EhReader reader (this , isec->data , subsec.offset , target-> wordSize );
1488
+ EhReader reader (this , isec->data , subsec.offset );
1475
1489
size_t dataOff = 0 ; // Offset from the start of the EH frame.
1476
1490
reader.skipValidLength (&dataOff); // readLength() already validated this.
1477
1491
// cieOffOff is the offset from the start of the EH frame to the cieOff
@@ -1510,20 +1524,20 @@ void ObjFile::registerEhFrames(Section &ehFrameSection) {
1510
1524
continue ;
1511
1525
}
1512
1526
1527
+ assert (cieMap.count (cieIsec));
1528
+ const CIE &cie = cieMap[cieIsec];
1513
1529
// Offset of the function address within the EH frame.
1514
1530
const size_t funcAddrOff = dataOff;
1515
- uint64_t funcAddr = reader.readPointer (&dataOff) + ehFrameSection. addr +
1516
- isecOff + funcAddrOff;
1517
- uint32_t funcLength = reader.readPointer (&dataOff);
1531
+ uint64_t funcAddr = reader.readPointer (&dataOff, cie. funcPtrSize ) +
1532
+ ehFrameSection. addr + isecOff + funcAddrOff;
1533
+ uint32_t funcLength = reader.readPointer (&dataOff, cie. funcPtrSize );
1518
1534
size_t lsdaAddrOff = 0 ; // Offset of the LSDA address within the EH frame.
1519
- assert (cieMap.count (cieIsec));
1520
- const CIE &cie = cieMap[cieIsec];
1521
1535
Optional<uint64_t > lsdaAddrOpt;
1522
1536
if (cie.fdesHaveAug ) {
1523
1537
reader.skipLeb128 (&dataOff);
1524
1538
lsdaAddrOff = dataOff;
1525
- if (cie.fdesHaveLsda ) {
1526
- uint64_t lsdaOff = reader.readPointer (&dataOff);
1539
+ if (cie.lsdaPtrSize != 0 ) {
1540
+ uint64_t lsdaOff = reader.readPointer (&dataOff, cie. lsdaPtrSize );
1527
1541
if (lsdaOff != 0 ) // FIXME possible to test this?
1528
1542
lsdaAddrOpt = ehFrameSection.addr + isecOff + lsdaAddrOff + lsdaOff;
1529
1543
}
0 commit comments