@@ -1866,8 +1866,11 @@ class X86MCPlusBuilder : public MCPlusBuilder {
18661866 return true ;
18671867 }
18681868
1869+ // / Analyzes PIC-style jump table code template and return identified
1870+ // / IndirectBranchType, MemLocInstr (all cases) and FixedEntryLoadInstr
1871+ // / (POSSIBLE_PIC_FIXED_BRANCH case).
18691872 template <typename Itr>
1870- std::pair <IndirectBranchType, MCInst *>
1873+ std::tuple <IndirectBranchType, MCInst * , MCInst *>
18711874 analyzePICJumpTable (Itr II, Itr IE, MCPhysReg R1, MCPhysReg R2) const {
18721875 // Analyze PIC-style jump table code template:
18731876 //
@@ -1876,6 +1879,13 @@ class X86MCPlusBuilder : public MCPlusBuilder {
18761879 // add %r2, %r1
18771880 // jmp *%r1
18781881 //
1882+ // or a fixed indirect jump template:
1883+ //
1884+ // movslq En(%rip), {%r2|%r1} <- FixedEntryLoadInstr
1885+ // lea PIC_JUMP_TABLE(%rip), {%r1|%r2} <- MemLocInstr
1886+ // add %r2, %r1
1887+ // jmp *%r1
1888+ //
18791889 // (with any irrelevant instructions in-between)
18801890 //
18811891 // When we call this helper we've already determined %r1 and %r2, and
@@ -1916,8 +1926,13 @@ class X86MCPlusBuilder : public MCPlusBuilder {
19161926 MO.SegRegNum == X86::NoRegister;
19171927 };
19181928 LLVM_DEBUG (dbgs () << " Checking for PIC jump table\n " );
1919- MCInst *MemLocInstr = nullptr ;
1920- const MCInst *MovInstr = nullptr ;
1929+ MCInst *FirstInstr = nullptr ;
1930+ MCInst *SecondInstr = nullptr ;
1931+ enum {
1932+ NOMATCH = 0 ,
1933+ MATCH_JUMP_TABLE,
1934+ MATCH_FIXED_BRANCH,
1935+ } MatchingState = NOMATCH;
19211936 while (++II != IE) {
19221937 MCInst &Instr = *II;
19231938 const MCInstrDesc &InstrDesc = Info->get (Instr.getOpcode ());
@@ -1926,68 +1941,76 @@ class X86MCPlusBuilder : public MCPlusBuilder {
19261941 // Ignore instructions that don't affect R1, R2 registers.
19271942 continue ;
19281943 }
1929- if (!MovInstr) {
1930- // Expect to see MOV instruction.
1931- if (!isMOVSX64rm32 (Instr)) {
1932- LLVM_DEBUG (dbgs () << " MOV instruction expected.\n " );
1944+ const bool IsMOVSXInstr = isMOVSX64rm32 (Instr);
1945+ const bool IsLEAInstr = isLEA64r (Instr);
1946+ if (MatchingState == NOMATCH) {
1947+ if (IsMOVSXInstr)
1948+ MatchingState = MATCH_JUMP_TABLE;
1949+ else if (IsLEAInstr)
1950+ MatchingState = MATCH_FIXED_BRANCH;
1951+ else
19331952 break ;
1934- }
19351953
1936- // Check if it's setting %r1 or %r2. In canonical form it sets %r2.
1937- // If it sets %r1 - rename the registers so we have to only check
1938- // a single form.
1939- unsigned MovDestReg = Instr.getOperand (0 ).getReg ();
1940- if (MovDestReg != R2)
1954+ // Check if the first instruction is setting %r1 or %r2. In canonical
1955+ // form lea sets %r1 and mov sets %r2. If it's the opposite - rename so
1956+ // we have to only check a single form.
1957+ unsigned DestReg = Instr.getOperand (0 ).getReg ();
1958+ MCPhysReg &ExpectReg = MatchingState == MATCH_JUMP_TABLE ? R2 : R1;
1959+ if (DestReg != ExpectReg)
19411960 std::swap (R1, R2);
1942- if (MovDestReg != R2) {
1943- LLVM_DEBUG (dbgs () << " MOV instruction expected to set %r2\n " );
1961+ if (DestReg != ExpectReg)
19441962 break ;
1945- }
19461963
1947- // Verify operands for MOV.
1964+ // Verify operands
19481965 std::optional<X86MemOperand> MO = evaluateX86MemoryOperand (Instr);
19491966 if (!MO)
19501967 break ;
1951- if (!isIndexed (*MO, R1))
1952- // POSSIBLE_PIC_JUMP_TABLE
1968+ if ((MatchingState == MATCH_JUMP_TABLE && isIndexed (*MO, R1)) ||
1969+ (MatchingState == MATCH_FIXED_BRANCH && isRIPRel (*MO)))
1970+ FirstInstr = &Instr;
1971+ else
19531972 break ;
1954- MovInstr = &Instr;
19551973 } else {
1956- if (!InstrDesc.hasDefOfPhysReg (Instr, R1, *RegInfo))
1974+ unsigned ExpectReg = MatchingState == MATCH_JUMP_TABLE ? R1 : R2;
1975+ if (!InstrDesc.hasDefOfPhysReg (Instr, ExpectReg, *RegInfo))
19571976 continue ;
1958- if (! isLEA64r (Instr)) {
1959- LLVM_DEBUG ( dbgs () << " LEA instruction expected \n " );
1977+ if ((MatchingState == MATCH_JUMP_TABLE && !IsLEAInstr) ||
1978+ (MatchingState == MATCH_FIXED_BRANCH && !IsMOVSXInstr))
19601979 break ;
1961- }
1962- if (Instr.getOperand (0 ).getReg () != R1) {
1963- LLVM_DEBUG (dbgs () << " LEA instruction expected to set %r1\n " );
1980+ if (Instr.getOperand (0 ).getReg () != ExpectReg)
19641981 break ;
1965- }
19661982
1967- // Verify operands for LEA .
1983+ // Verify operands.
19681984 std::optional<X86MemOperand> MO = evaluateX86MemoryOperand (Instr);
19691985 if (!MO)
19701986 break ;
19711987 if (!isRIPRel (*MO))
19721988 break ;
1973- MemLocInstr = &Instr;
1989+ SecondInstr = &Instr;
19741990 break ;
19751991 }
19761992 }
19771993
1978- if (!MemLocInstr )
1979- return std::make_pair (IndirectBranchType::UNKNOWN, nullptr );
1994+ if (!SecondInstr )
1995+ return std::make_tuple (IndirectBranchType::UNKNOWN, nullptr , nullptr );
19801996
1997+ if (MatchingState == MATCH_FIXED_BRANCH) {
1998+ LLVM_DEBUG (dbgs () << " checking potential fixed indirect branch\n " );
1999+ return std::make_tuple (IndirectBranchType::POSSIBLE_PIC_FIXED_BRANCH,
2000+ FirstInstr, SecondInstr);
2001+ }
19812002 LLVM_DEBUG (dbgs () << " checking potential PIC jump table\n " );
1982- return std::make_pair (IndirectBranchType::POSSIBLE_PIC_JUMP_TABLE,
1983- MemLocInstr );
2003+ return std::make_tuple (IndirectBranchType::POSSIBLE_PIC_JUMP_TABLE,
2004+ SecondInstr, nullptr );
19842005 }
19852006
1986- IndirectBranchType analyzeIndirectBranch (
1987- MCInst &Instruction, InstructionIterator Begin, InstructionIterator End,
1988- const unsigned PtrSize, MCInst *&MemLocInstrOut, unsigned &BaseRegNumOut,
1989- unsigned &IndexRegNumOut, int64_t &DispValueOut,
1990- const MCExpr *&DispExprOut, MCInst *&PCRelBaseOut) const override {
2007+ IndirectBranchType
2008+ analyzeIndirectBranch (MCInst &Instruction, InstructionIterator Begin,
2009+ InstructionIterator End, const unsigned PtrSize,
2010+ MCInst *&MemLocInstrOut, unsigned &BaseRegNumOut,
2011+ unsigned &IndexRegNumOut, int64_t &DispValueOut,
2012+ const MCExpr *&DispExprOut, MCInst *&PCRelBaseOut,
2013+ MCInst *&FixedEntryLoadInst) const override {
19912014 // Try to find a (base) memory location from where the address for
19922015 // the indirect branch is loaded. For X86-64 the memory will be specified
19932016 // in the following format:
@@ -2014,6 +2037,7 @@ class X86MCPlusBuilder : public MCPlusBuilder {
20142037 IndexRegNumOut = X86::NoRegister;
20152038 DispValueOut = 0 ;
20162039 DispExprOut = nullptr ;
2040+ FixedEntryLoadInst = nullptr ;
20172041
20182042 std::reverse_iterator<InstructionIterator> II (End);
20192043 std::reverse_iterator<InstructionIterator> IE (Begin);
@@ -2046,7 +2070,8 @@ class X86MCPlusBuilder : public MCPlusBuilder {
20462070 unsigned R2 = PrevInstr.getOperand (2 ).getReg ();
20472071 if (R1 == R2)
20482072 return IndirectBranchType::UNKNOWN;
2049- std::tie (Type, MemLocInstr) = analyzePICJumpTable (PrevII, IE, R1, R2);
2073+ std::tie (Type, MemLocInstr, FixedEntryLoadInst) =
2074+ analyzePICJumpTable (PrevII, IE, R1, R2);
20502075 break ;
20512076 }
20522077 return IndirectBranchType::UNKNOWN;
@@ -2090,6 +2115,8 @@ class X86MCPlusBuilder : public MCPlusBuilder {
20902115 if (MO->ScaleImm != 1 || MO->BaseRegNum != RIPRegister)
20912116 return IndirectBranchType::UNKNOWN;
20922117 break ;
2118+ case IndirectBranchType::POSSIBLE_PIC_FIXED_BRANCH:
2119+ break ;
20932120 default :
20942121 if (MO->ScaleImm != PtrSize)
20952122 return IndirectBranchType::UNKNOWN;
0 commit comments