From 9748eae3dd471d16c4c8cde3e7b8a8575db925bb Mon Sep 17 00:00:00 2001
From: clc5q <clc5q@git.zephyr-software.com>
Date: Wed, 20 Jan 2016 00:58:22 +0000
Subject: [PATCH] Apply computed-goto pattern detection to functions just as it
 was applied to orphaned code to emit IBT annotations.

Former-commit-id: a9d8aace7a5d1070e2741697a7a265883c22764d
---
 src/base/SMPFunction.cpp | 27 ++++++++++++++++++++++++++-
 1 file changed, 26 insertions(+), 1 deletion(-)

diff --git a/src/base/SMPFunction.cpp b/src/base/SMPFunction.cpp
index 25cf054f..e959fce1 100644
--- a/src/base/SMPFunction.cpp
+++ b/src/base/SMPFunction.cpp
@@ -9558,7 +9558,9 @@ void SMPFunction::EmitAnnotations(FILE *AnnotFile, FILE *InfoAnnotFile) {
 #endif
 	bool AllocSeen = false; // Reached LocalVarsAllocInstr yet?
 	bool DeallocTrigger = false;
-	for ( ; InstIter != Instrs.end(); ++InstIter) {
+	bool PrefetchInstSeenLast = false; // inst before current inst was a prefetch
+	bool UndefinedOpcodeSeenLast = false; // inst before current inst was an undefined opcode
+	for (; InstIter != Instrs.end(); ++InstIter) {
 		SMPInstr *CurrInst = (*InstIter);
 		STARS_ea_t addr = CurrInst->GetAddr();
 		if (CurrInst->IsFloatNop()) {
@@ -9634,6 +9636,29 @@ void SMPFunction::EmitAnnotations(FILE *AnnotFile, FILE *InfoAnnotFile) {
 
 		if (CurrInst->MDIsReturnInstr() && this->GetReturnAddressStatus() == FUNC_SAFE)
 			CurrInst->EmitSafeReturn(AnnotFile);
+
+		// Emit IBT annotations for instructions that fit computed-goto patterns in libc/glibc, such
+		//  as prefetch instructions and the instructions that follow them (computed goto often chooses
+		//  between going to the prefetch or jumping just past it, and IDA Pro cannot analyze these libc
+		//  macro-generated computed gotos even if they are not orphaned code). Likewise, an undefined opcode
+		//  often separates an indirect jump and its first target, so inst after undefined opcode is IBT.
+		bool EmitIBTAnnotation = (PrefetchInstSeenLast || UndefinedOpcodeSeenLast);
+		if (CurrInst->MDIsPrefetchOpcode()) {
+			PrefetchInstSeenLast = true;
+			UndefinedOpcodeSeenLast = false;
+			EmitIBTAnnotation = true;
+		}
+		else if (CurrInst->MDIsUndefinedOpcode()) {
+			UndefinedOpcodeSeenLast = true;
+			PrefetchInstSeenLast = false;
+		}
+		else {
+			PrefetchInstSeenLast = false;
+			UndefinedOpcodeSeenLast = false;
+		}
+		if (EmitIBTAnnotation) {
+			global_STARS_program->PrintUnknownCodeXref(addr, CurrInst->GetSize());
+		}
 	}  // end for all instructions
 
 	// Loop through all basic blocks and emit profiling request annotations
-- 
GitLab