From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (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 E64C1391830 for ; Thu, 5 Mar 2026 15:51:49 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1772725910; cv=none; b=XVVZebMzmsrY/xT9U6u89i80+kT6D1TXdnAVC1dcWMM14qn/NmHwdDTn+BNmF+Pkv52RYG/7goGoxVnvPphoD7568xBfr+uabNtBmGMWCXQWzINarqy6j2kuf2BB4oEktRYYfW46K+rq7ITQ20xIm7s2GCUM9RCIEmwIQXJDTnc= ARC-Message-Signature:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1772725910; c=relaxed/simple; bh=sOLdSQl0iS5V2M+uolTH2HzozerZLA+u6vssiqHTcjo=; h=Date:From:To:Cc:Subject:Message-ID:References:MIME-Version: Content-Type:Content-Disposition:In-Reply-To; b=Tt6GRbBYVEWme3W9tTZQveZCbg9+MJKi9nomtHesyd7un45cdQYQGQZ1zFVmYjZBFrji3AIbjDrquvkA12Bc/G30bPwi+see528o3uPOt2ZzL8GnBuQx+7ySggBlDbgFYjKt4JOPAX9JQbpG2YjKmXtJkV6eewTD9my0FNlUtRU= ARC-Authentication-Results:i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=L3nldxWB; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="L3nldxWB" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 139F7C116C6; Thu, 5 Mar 2026 15:51:48 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1772725909; bh=sOLdSQl0iS5V2M+uolTH2HzozerZLA+u6vssiqHTcjo=; h=Date:From:To:Cc:Subject:References:In-Reply-To:From; b=L3nldxWB7G9JJWk8gT/e3H/H4dVEFt3h1hgehWDFIyM1ar8QPKsAW2qeBmQWYiIDD z7wEjdI6g1WLWnwIMI3Q5hIovEf5vIMavBIvXawGKbn57vXoN15zP/1Z10pKsh6P5L j8JIGOLCVQswNFhT6RqR/+NZyttZIsJ/v8HJ/M6ZDHXHA1P2cv3bEiLTt3gtAqytBF LN5DyR1sOvFy0SeGz487Wmt0N3I0cYidRXQ0HavmmZLzwRtRDu4uExHyL3XMkK6wGl YysB2sRJC+R0oN/LpZ4xRRnKlz/qYS84MSqpM8QG5Lo7w5rx8L0WWLzgaIpqJZ1EOc FDBk04xMd3xeA== Date: Thu, 5 Mar 2026 10:51:47 -0500 From: Sasha Levin To: "Masami Hiramatsu (Google)" Cc: Matthieu Baerts , Andrew Morton , Carlos Llamas , Luca Ceresoli , linux-kernel@vger.kernel.org Subject: Re: [PATCH] decode_stacktrace: Support heuristic caller address search Message-ID: References: <177268753893.3271988.11559821020066428486.stgit@mhiramat.tok.corp.google.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii; format=flowed Content-Disposition: inline In-Reply-To: <177268753893.3271988.11559821020066428486.stgit@mhiramat.tok.corp.google.com> On Thu, 5 Mar 2026 14:12:19 +0900, Masami Hiramatsu (Google) wrote: > Add -c option to search call address search to decode_stacktrace. > This tries to decode line info backwards, starting from 1byte before > the return address, and displays the first line info it founds as > the caller address. > If it tries up to 10bytes before (or the symbol address) and still > can not find it, it gives up and decodes the return address. The commit message says "up to 10bytes" but the code passes $offset (the function offset from the symbol) as the max iteration count to search_call_site(). There's no 10-byte cap anywhere in the code? $offset can easily be hundreds or thousands of bytes into a function. > +search_call_site() { > + # Instead of using the return address, use the nearest line info > + # address before given address. > + local return_addr=${2} > + local max=${3} > + local i > + > + for i in $(seq 1 ${max}); do > + local expr=$((0x$return_addr-$i)) > + local address=$(printf "%x\n" "$expr") > + > + local code=$(${ADDR2LINE} -i -e "${1}" "$address" 2>/dev/null) > + local first=${code% *} > + if [[ "$code" != "" && "$code" != ${UNKNOWN_LINE} && "${first#*:}" != "?" ]]; then To also address Matthieu's question about performance: I think this whole iterative search could be replaced by simply subtracting 1 from the return address before passing it to addr2line. DWARF line tables map address *ranges* to source lines, so any address within the CALL instruction resolves to the correct source line. return_addr-1 is guaranteed to land inside the CALL instruction (it's the last byte of it), so a single addr2line call is sufficient. This is exactly what the kernel itself does in sprint_backtrace() (kernel/kallsyms.c:570): it passes symbol_offset=-1 to __sprint_symbol(), which does `address += symbol_offset` before lookup. GDB, perf, and libunwind all use the same addr-1 trick for the same reason. That would make this both correct and free. > + if [[ "$code" != "" && "$code" != ${UNKNOWN_LINE} && "${first#*:}" != "?" ]]; then Minor: ${UNKNOWN_LINE} is "??:0" -- when unquoted on the RHS of != inside [[ ]], the ? characters are interpreted as glob wildcards (each matching any single character). It happens to work here because ? also matches '?' itself, but it should be quoted as "${UNKNOWN_LINE}" for correctness. Same issue on the other != ${UNKNOWN_LINE} below. -- Thanks, Sasha