@@ -1265,51 +1265,6 @@ bool BinaryFunction::disassemble() {
1265
1265
}
1266
1266
}
1267
1267
1268
- // Check if there's a relocation associated with this instruction.
1269
- bool UsedReloc = false ;
1270
- for (auto Itr = Relocations.lower_bound (Offset),
1271
- ItrE = Relocations.lower_bound (Offset + Size );
1272
- Itr != ItrE; ++Itr) {
1273
- const Relocation &Relocation = Itr->second ;
1274
-
1275
- LLVM_DEBUG (dbgs () << " BOLT-DEBUG: replacing immediate 0x"
1276
- << Twine::utohexstr (Relocation.Value )
1277
- << " with relocation"
1278
- " against "
1279
- << Relocation.Symbol << " +" << Relocation.Addend
1280
- << " in function " << *this
1281
- << " for instruction at offset 0x"
1282
- << Twine::utohexstr (Offset) << ' \n ' );
1283
-
1284
- // Process reference to the primary symbol.
1285
- if (!Relocation.isPCRelative ())
1286
- BC.handleAddressRef (Relocation.Value - Relocation.Addend , *this ,
1287
- /* IsPCRel*/ false );
1288
-
1289
- int64_t Value = Relocation.Value ;
1290
- const bool Result = BC.MIB ->replaceImmWithSymbolRef (
1291
- Instruction, Relocation.Symbol , Relocation.Addend , Ctx.get (), Value,
1292
- Relocation.Type );
1293
- (void )Result;
1294
- assert (Result && " cannot replace immediate with relocation" );
1295
-
1296
- // For aarch, if we replaced an immediate with a symbol from a
1297
- // relocation, we mark it so we do not try to further process a
1298
- // pc-relative operand. All we need is the symbol.
1299
- if (BC.isAArch64 ())
1300
- UsedReloc = true ;
1301
-
1302
- // Make sure we replaced the correct immediate (instruction
1303
- // can have multiple immediate operands).
1304
- if (BC.isX86 ()) {
1305
- assert (truncateToSize (static_cast <uint64_t >(Value),
1306
- Relocation::getSizeForType (Relocation.Type )) ==
1307
- truncateToSize (Relocation.Value , Relocation::getSizeForType (
1308
- Relocation.Type )) &&
1309
- " immediate value mismatch in function" );
1310
- }
1311
- }
1312
-
1313
1268
if (MIB->isBranch (Instruction) || MIB->isCall (Instruction)) {
1314
1269
uint64_t TargetAddress = 0 ;
1315
1270
if (MIB->evaluateBranch (Instruction, AbsoluteInstrAddr, Size ,
@@ -1394,8 +1349,75 @@ bool BinaryFunction::disassemble() {
1394
1349
if (BC.isAArch64 ())
1395
1350
handleAArch64IndirectCall (Instruction, Offset);
1396
1351
}
1397
- } else if (MIB->hasPCRelOperand (Instruction) && !UsedReloc) {
1398
- handlePCRelOperand (Instruction, AbsoluteInstrAddr, Size );
1352
+ } else {
1353
+ // Check if there's a relocation associated with this instruction.
1354
+ bool UsedReloc = false ;
1355
+ for (auto Itr = Relocations.lower_bound (Offset),
1356
+ ItrE = Relocations.lower_bound (Offset + Size );
1357
+ Itr != ItrE; ++Itr) {
1358
+ const Relocation &Relocation = Itr->second ;
1359
+ uint64_t SymbolValue = Relocation.Value - Relocation.Addend ;
1360
+ if (Relocation.isPCRelative ())
1361
+ SymbolValue += getAddress () + Relocation.Offset ;
1362
+
1363
+ // Process reference to the symbol.
1364
+ if (BC.isX86 ())
1365
+ BC.handleAddressRef (SymbolValue, *this , Relocation.isPCRelative ());
1366
+
1367
+ if (BC.isAArch64 () || !Relocation.isPCRelative ()) {
1368
+ int64_t Value = Relocation.Value ;
1369
+ const bool Result = BC.MIB ->replaceImmWithSymbolRef (
1370
+ Instruction, Relocation.Symbol , Relocation.Addend , Ctx.get (),
1371
+ Value, Relocation.Type );
1372
+ (void )Result;
1373
+ assert (Result && " cannot replace immediate with relocation" );
1374
+
1375
+ if (BC.isX86 ()) {
1376
+ // Make sure we replaced the correct immediate (instruction
1377
+ // can have multiple immediate operands).
1378
+ assert (
1379
+ truncateToSize (static_cast <uint64_t >(Value),
1380
+ Relocation::getSizeForType (Relocation.Type )) ==
1381
+ truncateToSize (Relocation.Value , Relocation::getSizeForType (
1382
+ Relocation.Type )) &&
1383
+ " immediate value mismatch in function" );
1384
+ } else if (BC.isAArch64 ()) {
1385
+ // For aarch, if we replaced an immediate with a symbol from a
1386
+ // relocation, we mark it so we do not try to further process a
1387
+ // pc-relative operand. All we need is the symbol.
1388
+ UsedReloc = true ;
1389
+ }
1390
+ } else {
1391
+ // Check if the relocation matches memop's Disp.
1392
+ uint64_t TargetAddress;
1393
+ if (!BC.MIB ->evaluateMemOperandTarget (Instruction, TargetAddress,
1394
+ AbsoluteInstrAddr, Size )) {
1395
+ errs () << " BOLT-ERROR: PC-relative operand can't be evaluated\n " ;
1396
+ exit (1 );
1397
+ }
1398
+ assert (TargetAddress == Relocation.Value + AbsoluteInstrAddr + Size &&
1399
+ " Immediate value mismatch detected." );
1400
+
1401
+ const MCExpr *Expr = MCSymbolRefExpr::create (
1402
+ Relocation.Symbol , MCSymbolRefExpr::VK_None, *BC.Ctx );
1403
+ // Real addend for pc-relative targets is adjusted with a delta
1404
+ // from relocation placement to the next instruction.
1405
+ const uint64_t TargetAddend =
1406
+ Relocation.Addend + Offset + Size - Relocation.Offset ;
1407
+ if (TargetAddend) {
1408
+ const MCConstantExpr *Offset =
1409
+ MCConstantExpr::create (TargetAddend, *BC.Ctx );
1410
+ Expr = MCBinaryExpr::createAdd (Expr, Offset, *BC.Ctx );
1411
+ }
1412
+ BC.MIB ->replaceMemOperandDisp (
1413
+ Instruction, MCOperand::createExpr (BC.MIB ->getTargetExprFor (
1414
+ Instruction, Expr, *BC.Ctx , 0 )));
1415
+ UsedReloc = true ;
1416
+ }
1417
+ }
1418
+
1419
+ if (MIB->hasPCRelOperand (Instruction) && !UsedReloc)
1420
+ handlePCRelOperand (Instruction, AbsoluteInstrAddr, Size );
1399
1421
}
1400
1422
1401
1423
add_instruction:
@@ -1565,6 +1587,8 @@ bool BinaryFunction::scanExternalRefs() {
1565
1587
ItrE = Relocations.lower_bound (Offset + Size );
1566
1588
Itr != ItrE; ++Itr) {
1567
1589
Relocation &Relocation = Itr->second ;
1590
+ if (Relocation.isPCRelative () && BC.isX86 ())
1591
+ continue ;
1568
1592
if (ignoreReference (Relocation.Symbol ))
1569
1593
continue ;
1570
1594
0 commit comments