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