@@ -47,54 +47,88 @@ bool X86MCSymbolizer::tryAddingSymbolicOperand(
47
47
Inst.addOperand (MCOperand::createExpr (Expr));
48
48
};
49
49
50
- // Check for relocations against the operand.
51
- const uint64_t InstOffset = InstAddress - Function.getAddress ();
52
- if (const Relocation *Relocation =
53
- Function.getRelocationAt (InstOffset + ImmOffset)) {
54
- uint64_t SymbolValue = Relocation->Value - Relocation->Addend ;
55
- if (Relocation->isPCRelative ())
56
- SymbolValue += InstAddress + ImmOffset;
50
+ // Check if the operand being added is a displacement part of a compound
51
+ // memory operand that uses PC-relative addressing. If it is, try to symbolize
52
+ // it without relocations. Return true on success, false otherwise.
53
+ auto processPCRelOperandNoRel = [&]() {
54
+ const int MemOp = BC.MIB ->getMemoryOperandNo (Inst);
55
+ if (MemOp == -1 )
56
+ return false ;
57
+
58
+ const unsigned DispOp = MemOp + X86::AddrDisp;
59
+ if (Inst.getNumOperands () != DispOp)
60
+ return false ;
57
61
58
- // Process reference to the symbol.
59
- BC.handleAddressRef (SymbolValue, Function, Relocation->isPCRelative ());
62
+ const MCOperand &Base = Inst.getOperand (MemOp + X86::AddrBaseReg);
63
+ if (Base.getReg () != BC.MRI ->getProgramCounter ())
64
+ return false ;
60
65
61
- uint64_t Addend = Relocation->Addend ;
62
- // Real addend for pc-relative targets is adjusted with a delta from
63
- // the relocation placement to the next instruction.
64
- if (Relocation->isPCRelative ())
65
- Addend += InstOffset + InstSize - Relocation->Offset ;
66
+ const MCOperand &Scale = Inst.getOperand (MemOp + X86::AddrScaleAmt);
67
+ const MCOperand &Index = Inst.getOperand (MemOp + X86::AddrIndexReg);
68
+ if (Scale.getImm () != 0 && Index.getReg () != MCRegister::NoRegister)
69
+ return false ;
70
+
71
+ const MCSymbol *TargetSymbol;
72
+ uint64_t TargetOffset;
73
+ std::tie (TargetSymbol, TargetOffset) =
74
+ BC.handleAddressRef (Value, Function, /* IsPCRel=*/ true );
75
+
76
+ addOperand (TargetSymbol, TargetOffset);
77
+
78
+ return true ;
79
+ };
66
80
67
- addOperand (Relocation->Symbol , Addend);
81
+ // Check for GOTPCRELX relocations first. Because these relocations allow the
82
+ // linker to modify the instruction, we have to check the offset range
83
+ // corresponding to the instruction, not the offset of the operand.
84
+ // Note that if there is GOTPCRELX relocation against the instruction, there
85
+ // will be no other relocation in this range, since GOTPCRELX applies only to
86
+ // certain instruction types.
87
+ const uint64_t InstOffset = InstAddress - Function.getAddress ();
88
+ const Relocation *Relocation =
89
+ Function.getRelocationInRange (InstOffset, InstOffset + InstSize);
90
+ if (Relocation && Relocation::isX86GOTPCRELX (Relocation->Type )) {
91
+ // If the operand is PC-relative, convert it without using the relocation
92
+ // information. For GOTPCRELX, it is safe to use the absolute address
93
+ // instead of extracting the addend from the relocation, as non-standard
94
+ // forms will be rejected by linker conversion process and the operand
95
+ // will always reference GOT which we don't rewrite.
96
+ if (processPCRelOperandNoRel ())
97
+ return true ;
98
+
99
+ // The linker converted the PC-relative address to an absolute one.
100
+ // Symbolize this address.
101
+ BC.handleAddressRef (Value, Function, /* IsPCRel=*/ false );
102
+ const BinaryData *Target = BC.getBinaryDataAtAddress (Value);
103
+ assert (Target &&
104
+ " BinaryData should exist at converted GOTPCRELX destination" );
105
+
106
+ addOperand (Target->getSymbol (), /* Addend=*/ 0 );
68
107
69
108
return true ;
70
109
}
71
110
72
- // Check if the operand being added is a displacement part of a compound
73
- // memory operand that uses PC-relative addressing. If it is, try to symbolize
74
- // it without relocations.
75
- const int MemOp = BC.MIB ->getMemoryOperandNo (Inst);
76
- if (MemOp == -1 )
77
- return false ;
111
+ // Check for relocations against the operand.
112
+ if (!Relocation || Relocation->Offset != InstOffset + ImmOffset)
113
+ Relocation = Function.getRelocationAt (InstOffset + ImmOffset);
78
114
79
- const unsigned DispOp = MemOp + X86::AddrDisp;
80
- if (Inst.getNumOperands () != DispOp)
81
- return false ;
115
+ if (!Relocation)
116
+ return processPCRelOperandNoRel ();
82
117
83
- const MCOperand &Base = Inst. getOperand (MemOp + X86::AddrBaseReg) ;
84
- if (Base. getReg () != BC. MRI -> getProgramCounter ())
85
- return false ;
118
+ uint64_t SymbolValue = Relocation-> Value - Relocation-> Addend ;
119
+ if (Relocation-> isPCRelative ())
120
+ SymbolValue += InstAddress + ImmOffset ;
86
121
87
- const MCOperand &Scale = Inst.getOperand (MemOp + X86::AddrScaleAmt);
88
- const MCOperand &Index = Inst.getOperand (MemOp + X86::AddrIndexReg);
89
- if (Scale.getImm () != 0 && Index.getReg () != MCRegister::NoRegister)
90
- return false ;
122
+ // Process reference to the symbol.
123
+ BC.handleAddressRef (SymbolValue, Function, Relocation->isPCRelative ());
91
124
92
- const MCSymbol *TargetSymbol;
93
- uint64_t TargetOffset;
94
- std::tie (TargetSymbol, TargetOffset) =
95
- BC.handleAddressRef (Value, Function, /* IsPCRel*/ true );
125
+ uint64_t Addend = Relocation->Addend ;
126
+ // Real addend for pc-relative targets is adjusted with a delta from
127
+ // the relocation placement to the next instruction.
128
+ if (Relocation->isPCRelative ())
129
+ Addend += InstOffset + InstSize - Relocation->Offset ;
96
130
97
- addOperand (TargetSymbol, TargetOffset );
131
+ addOperand (Relocation-> Symbol , Addend );
98
132
99
133
return true ;
100
134
}
0 commit comments