@@ -47,54 +47,88 @@ bool X86MCSymbolizer::tryAddingSymbolicOperand(
4747 Inst.addOperand (MCOperand::createExpr (Expr));
4848 };
4949
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 ;
5761
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 ;
6065
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+ };
6680
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 );
68107
69108 return true ;
70109 }
71110
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);
78114
79- const unsigned DispOp = MemOp + X86::AddrDisp;
80- if (Inst.getNumOperands () != DispOp)
81- return false ;
115+ if (!Relocation)
116+ return processPCRelOperandNoRel ();
82117
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 ;
86121
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 ());
91124
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 ;
96130
97- addOperand (TargetSymbol, TargetOffset );
131+ addOperand (Relocation-> Symbol , Addend );
98132
99133 return true ;
100134}
0 commit comments