@@ -1265,51 +1265,6 @@ bool BinaryFunction::disassemble() {
12651265 }
12661266 }
12671267
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-
13131268 if (MIB->isBranch (Instruction) || MIB->isCall (Instruction)) {
13141269 uint64_t TargetAddress = 0 ;
13151270 if (MIB->evaluateBranch (Instruction, AbsoluteInstrAddr, Size,
@@ -1394,8 +1349,75 @@ bool BinaryFunction::disassemble() {
13941349 if (BC.isAArch64 ())
13951350 handleAArch64IndirectCall (Instruction, Offset);
13961351 }
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);
13991421 }
14001422
14011423add_instruction:
@@ -1565,6 +1587,8 @@ bool BinaryFunction::scanExternalRefs() {
15651587 ItrE = Relocations.lower_bound (Offset + Size);
15661588 Itr != ItrE; ++Itr) {
15671589 Relocation &Relocation = Itr->second ;
1590+ if (Relocation.isPCRelative () && BC.isX86 ())
1591+ continue ;
15681592 if (ignoreReference (Relocation.Symbol ))
15691593 continue ;
15701594
0 commit comments