From nobody Tue Dec 2 02:04:15 2025 Received: from mx0b-00069f02.pphosted.com (mx0b-00069f02.pphosted.com [205.220.177.32]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 7E540344031 for ; Fri, 21 Nov 2025 09:54:11 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=205.220.177.32 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1763718853; cv=none; b=OT1X4UCI7fCQ0McgdA1ayNTw1zLf1oPvDNweQT9ja1TuAHEEpbb9cI5t+Og0sT44ywDM4bytr8d0hVqFfQ33B5WNpeJtgL4gvUr0qhXXsgVeSmB6wCaAXrEc+sQJq7wZbgBpah792sZ98t+VxO5bS2Pdb9eK/6LPGzXB1xCC4dw= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1763718853; c=relaxed/simple; bh=vh0GRZVlVEeA7W1dK7AFJ3L+PZ4+byzRcYFkNuJoBZ0=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=aJr3eVn/SKJet9pBV9JseRgR5llzceyC0vkqEsdqtE4PEnho3IWFQTgfO9xvlkCTKffTwh+Pkn1IUanCRxOSXsMh0Py/qm7mE3fC/id6tcsZhhP1GRiX8WfabwB1wkcfiOk/v9lchPL77Hu4fwXPPAxvHYTq1uwkx6a+K3gRtUE= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=oracle.com; spf=pass smtp.mailfrom=oracle.com; dkim=pass (2048-bit key) header.d=oracle.com header.i=@oracle.com header.b=cU+LsiOr; arc=none smtp.client-ip=205.220.177.32 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=oracle.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=oracle.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=oracle.com header.i=@oracle.com header.b="cU+LsiOr" Received: from pps.filterd (m0333520.ppops.net [127.0.0.1]) by mx0b-00069f02.pphosted.com (8.18.1.2/8.18.1.2) with ESMTP id 5AL1uj0x024789; Fri, 21 Nov 2025 09:54:04 GMT DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=oracle.com; h=cc :content-transfer-encoding:date:from:in-reply-to:message-id :mime-version:references:subject:to; s=corp-2025-04-25; bh=52J1S eZm5vwekljiUGKBD5RCv9kbaKZnjN33R/4C9j0=; b=cU+LsiOrrtqWTEiduQTZy dk/DqI1A9VT8KQmAkhUf3WwmAzGMIha1wPIHLy/br50nneoCbvksZAeK+zFjpgJf mHMOvaR1pOEWWau4dk7dkzqCY6pMD8dzJYtp+B9pbY1b1Dptf3T+iwRi7OuAEE9M 44HXzjVc0yVqaqbHLMmWSe50lD5IxP7xYRKcAH10ClvM1vp4Z18YwKcik7j4tKT8 y0clQpPkN7ktTB2+YW8IxEZZpWaEpWb2GoC+nIdFvyZ8RXcIH5NTYQU6WAyRPKEX j54rftmqto+GV7Mc2MyGR2OxH6NeXoN6eXktkvj7pKUzQ0NYBKaBWqu/0NfvtZ1b w== Received: from phxpaimrmta01.imrmtpd1.prodappphxaev1.oraclevcn.com (phxpaimrmta01.appoci.oracle.com [138.1.114.2]) by mx0b-00069f02.pphosted.com (PPS) with ESMTPS id 4aejbbk431-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=OK); Fri, 21 Nov 2025 09:54:04 +0000 (GMT) Received: from pps.filterd (phxpaimrmta01.imrmtpd1.prodappphxaev1.oraclevcn.com [127.0.0.1]) by phxpaimrmta01.imrmtpd1.prodappphxaev1.oraclevcn.com (8.18.1.2/8.18.1.2) with ESMTP id 5AL8s0K0004268; Fri, 21 Nov 2025 09:54:03 GMT Received: from pps.reinject (localhost [127.0.0.1]) by phxpaimrmta01.imrmtpd1.prodappphxaev1.oraclevcn.com (PPS) with ESMTPS id 4aefyd4ukk-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=OK); Fri, 21 Nov 2025 09:54:03 +0000 Received: from phxpaimrmta01.imrmtpd1.prodappphxaev1.oraclevcn.com (phxpaimrmta01.imrmtpd1.prodappphxaev1.oraclevcn.com [127.0.0.1]) by pps.reinject (8.17.1.5/8.17.1.5) with ESMTP id 5AL9rgUQ021648; Fri, 21 Nov 2025 09:54:03 GMT Received: from laptop-dell-latitude7430.nl.oracle.com (dhcp-10-154-175-150.vpn.oracle.com [10.154.175.150]) by phxpaimrmta01.imrmtpd1.prodappphxaev1.oraclevcn.com (PPS) with ESMTP id 4aefyd4ub2-12; Fri, 21 Nov 2025 09:54:03 +0000 From: Alexandre Chartre To: linux-kernel@vger.kernel.org, mingo@kernel.org, jpoimboe@kernel.org, peterz@infradead.org, david.laight.linux@gmail.com Cc: alexandre.chartre@oracle.com Subject: [PATCH v6 11/30] objtool: Trace instruction state changes during function validation Date: Fri, 21 Nov 2025 10:53:21 +0100 Message-ID: <20251121095340.464045-12-alexandre.chartre@oracle.com> X-Mailer: git-send-email 2.43.5 In-Reply-To: <20251121095340.464045-1-alexandre.chartre@oracle.com> References: <20251121095340.464045-1-alexandre.chartre@oracle.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-Proofpoint-Virus-Version: vendor=baseguard engine=ICAP:2.0.293,Aquarius:18.0.1121,Hydra:6.1.9,FMLib:17.12.100.49 definitions=2025-11-21_03,2025-11-20_01,2025-10-01_01 X-Proofpoint-Spam-Details: rule=notspam policy=default score=0 spamscore=0 mlxlogscore=999 suspectscore=0 malwarescore=0 mlxscore=0 bulkscore=0 phishscore=0 adultscore=0 classifier=spam adjust=0 reason=mlx scancount=1 engine=8.12.0-2510240000 definitions=main-2511210075 X-Authority-Analysis: v=2.4 cv=BoqQAIX5 c=1 sm=1 tr=0 ts=692036bc cx=c_pps a=XiAAW1AwiKB2Y8Wsi+sD2Q==:117 a=XiAAW1AwiKB2Y8Wsi+sD2Q==:17 a=6UeiqGixMTsA:10 a=VkNPw1HP01LnGYTKEx00:22 a=yPCof4ZbAAAA:8 a=n0rf_ozDEmcaLxr6z3oA:9 X-Proofpoint-ORIG-GUID: IygU54V5A7CVZwIFvZcwz2l0ogvJYhHn X-Proofpoint-Spam-Details-Enc: AW1haW4tMjUxMTE1MDAzMiBTYWx0ZWRfXxTejclaRbRx+ b3jzhLq2lrvaiyvdfzho/NGVsXB9b4LNBHRKVn1n9pY648kstz3g8hqtrb/cibH26FTuUuO4hmM DxKoudYUqgWsTskAW97cpjVROmhehlmM/nBm4LCP/egYRaGWU4ZQw9M/2v4JwKkMcet4KoIizNZ StD4LTDXfZC6tbLMdvL61TaET+OTqmtUQAWzvTQr8juezqiOwpLcsdbnCV6OiApPcD65IvT9oM9 h2cFADus9yzuuNiPdkOEiko0PpaXKaHI8OsMtiZNlrl+gkqQ/LIg4Ip2Q//KtuRea4jvkTS6nTQ k6kUOROVuSXckhqRZO8gbT7x+HzRlaGu7dI0h8Wp2OakZln70DEHi9JUoyp6UAbwiYr/SScbF9d hCOt9wTZxEyEUZnxUE0xZs/preF2BQ== X-Proofpoint-GUID: IygU54V5A7CVZwIFvZcwz2l0ogvJYhHn Content-Type: text/plain; charset="utf-8" During function validation, objtool maintains a per-instruction state, in particular to track call frame information. When tracing validation, print any instruction state changes. Signed-off-by: Alexandre Chartre --- tools/objtool/check.c | 8 +- tools/objtool/include/objtool/trace.h | 10 ++ tools/objtool/trace.c | 132 ++++++++++++++++++++++++++ 3 files changed, 149 insertions(+), 1 deletion(-) diff --git a/tools/objtool/check.c b/tools/objtool/check.c index 2352b9668b126..e12dba144731f 100644 --- a/tools/objtool/check.c +++ b/tools/objtool/check.c @@ -3729,6 +3729,8 @@ static int validate_insn(struct objtool_file *file, s= truct symbol *func, struct instruction *prev_insn, struct instruction *next_insn, bool *dead_end) { + /* prev_state is not used if there is no disassembly support */ + struct insn_state prev_state __maybe_unused; struct alternative *alt; u8 visited; int ret; @@ -3837,7 +3839,11 @@ static int validate_insn(struct objtool_file *file, = struct symbol *func, if (skip_alt_group(insn)) return 0; =20 - if (handle_insn_ops(insn, next_insn, statep)) + prev_state =3D *statep; + ret =3D handle_insn_ops(insn, next_insn, statep); + TRACE_INSN_STATE(insn, &prev_state, statep); + + if (ret) return 1; =20 switch (insn->type) { diff --git a/tools/objtool/include/objtool/trace.h b/tools/objtool/include/= objtool/trace.h index 3f3c830ed114e..33fe9c6acb4fd 100644 --- a/tools/objtool/include/objtool/trace.h +++ b/tools/objtool/include/objtool/trace.h @@ -30,6 +30,12 @@ extern int trace_depth; } \ }) =20 +#define TRACE_INSN_STATE(insn, sprev, snext) \ +({ \ + if (trace) \ + trace_insn_state(insn, sprev, snext); \ +}) + static inline void trace_enable(void) { trace =3D true; @@ -53,10 +59,14 @@ static inline void trace_depth_dec(void) trace_depth--; } =20 +void trace_insn_state(struct instruction *insn, struct insn_state *sprev, + struct insn_state *snext); + #else /* DISAS */ =20 #define TRACE(fmt, ...) ({}) #define TRACE_INSN(insn, fmt, ...) ({}) +#define TRACE_INSN_STATE(insn, sprev, snext) ({}) =20 static inline void trace_enable(void) {} static inline void trace_disable(void) {} diff --git a/tools/objtool/trace.c b/tools/objtool/trace.c index 134cc33ffe970..12bbad09d9c02 100644 --- a/tools/objtool/trace.c +++ b/tools/objtool/trace.c @@ -7,3 +7,135 @@ =20 bool trace; int trace_depth; + +/* + * Macros to trace CFI state attributes changes. + */ + +#define TRACE_CFI_ATTR(attr, prev, next, fmt, ...) \ +({ \ + if ((prev)->attr !=3D (next)->attr) \ + TRACE("%s=3D" fmt " ", #attr, __VA_ARGS__); \ +}) + +#define TRACE_CFI_ATTR_BOOL(attr, prev, next) \ + TRACE_CFI_ATTR(attr, prev, next, \ + "%s", (next)->attr ? "true" : "false") + +#define TRACE_CFI_ATTR_NUM(attr, prev, next, fmt) \ + TRACE_CFI_ATTR(attr, prev, next, fmt, (next)->attr) + +#define CFI_REG_NAME_MAXLEN 16 + +/* + * Return the name of a register. Note that the same static buffer + * is returned if the name is dynamically generated. + */ +static const char *cfi_reg_name(unsigned int reg) +{ + static char rname_buffer[CFI_REG_NAME_MAXLEN]; + + switch (reg) { + case CFI_UNDEFINED: + return ""; + case CFI_CFA: + return "cfa"; + case CFI_SP_INDIRECT: + return "(sp)"; + case CFI_BP_INDIRECT: + return "(bp)"; + } + + if (snprintf(rname_buffer, CFI_REG_NAME_MAXLEN, "r%d", reg) =3D=3D -1) + return ""; + + return (const char *)rname_buffer; +} + +/* + * Functions and macros to trace CFI registers changes. + */ + +static void trace_cfi_reg(const char *prefix, int reg, const char *fmt, + int base_prev, int offset_prev, + int base_next, int offset_next) +{ + char *rname; + + if (base_prev =3D=3D base_next && offset_prev =3D=3D offset_next) + return; + + if (prefix) + TRACE("%s:", prefix); + + if (base_next =3D=3D CFI_UNDEFINED) { + TRACE("%1$s=3D ", cfi_reg_name(reg)); + } else { + rname =3D strdup(cfi_reg_name(reg)); + TRACE(fmt, rname, cfi_reg_name(base_next), offset_next); + free(rname); + } +} + +static void trace_cfi_reg_val(const char *prefix, int reg, + int base_prev, int offset_prev, + int base_next, int offset_next) +{ + trace_cfi_reg(prefix, reg, "%1$s=3D%2$s%3$+d ", + base_prev, offset_prev, base_next, offset_next); +} + +static void trace_cfi_reg_ref(const char *prefix, int reg, + int base_prev, int offset_prev, + int base_next, int offset_next) +{ + trace_cfi_reg(prefix, reg, "%1$s=3D(%2$s%3$+d) ", + base_prev, offset_prev, base_next, offset_next); +} + +#define TRACE_CFI_REG_VAL(reg, prev, next) \ + trace_cfi_reg_val(NULL, reg, prev.base, prev.offset, \ + next.base, next.offset) + +#define TRACE_CFI_REG_REF(reg, prev, next) \ + trace_cfi_reg_ref(NULL, reg, prev.base, prev.offset, \ + next.base, next.offset) + +void trace_insn_state(struct instruction *insn, struct insn_state *sprev, + struct insn_state *snext) +{ + struct cfi_state *cprev, *cnext; + int i; + + if (!memcmp(sprev, snext, sizeof(struct insn_state))) + return; + + cprev =3D &sprev->cfi; + cnext =3D &snext->cfi; + + disas_print_insn(stderr, objtool_disas_ctx, insn, + trace_depth - 1, "state: "); + + /* print registers changes */ + TRACE_CFI_REG_VAL(CFI_CFA, cprev->cfa, cnext->cfa); + for (i =3D 0; i < CFI_NUM_REGS; i++) { + TRACE_CFI_REG_VAL(i, cprev->vals[i], cnext->vals[i]); + TRACE_CFI_REG_REF(i, cprev->regs[i], cnext->regs[i]); + } + + /* print attributes changes */ + TRACE_CFI_ATTR_NUM(stack_size, cprev, cnext, "%d"); + TRACE_CFI_ATTR_BOOL(drap, cprev, cnext); + if (cnext->drap) { + trace_cfi_reg_val("drap", cnext->drap_reg, + cprev->drap_reg, cprev->drap_offset, + cnext->drap_reg, cnext->drap_offset); + } + TRACE_CFI_ATTR_BOOL(bp_scratch, cprev, cnext); + TRACE_CFI_ATTR_NUM(instr, sprev, snext, "%d"); + TRACE_CFI_ATTR_NUM(uaccess_stack, sprev, snext, "%u"); + + TRACE("\n"); + + insn->trace =3D 1; +} --=20 2.43.5