From: Yonghong Song <yonghong.song@linux.dev>
To: Alan Maguire <alan.maguire@oracle.com>,
Arnaldo Carvalho de Melo <arnaldo.melo@gmail.com>,
dwarves@vger.kernel.org
Cc: Alexei Starovoitov <ast@kernel.org>,
Andrii Nakryiko <andrii@kernel.org>,
bpf@vger.kernel.org, kernel-team@fb.com
Subject: [PATCH dwarves v4 03/11] dwarf_loader: Handle signatures with dead arguments
Date: Wed, 25 Mar 2026 18:31:59 -0700 [thread overview]
Message-ID: <20260326013159.2904078-1-yonghong.song@linux.dev> (raw)
In-Reply-To: <20260326013144.2901265-1-yonghong.song@linux.dev>
For llvm dwarf, the dead argument may be in the middle of
DW_TAG_subprogram. So we introduce skip_idx in order to
match expected registers properly.
For example:
0x00042897: DW_TAG_subprogram
DW_AT_name ("create_dev")
DW_AT_calling_convention (DW_CC_nocall)
DW_AT_type (0x0002429a "int")
...
0x000428ab: DW_TAG_formal_parameter
DW_AT_name ("name")
DW_AT_type (0x000242ed "char *")
...
0x000428b5: DW_TAG_formal_parameter
DW_AT_location (indexed (0x3f) loclist = 0x000027f8:
[0xffffffff87681370, 0xffffffff8768137a): DW_OP_reg5 RDI
[0xffffffff8768137a, 0xffffffff87681392): DW_OP_reg3 RBX
[0xffffffff87681392, 0xffffffff876813ae): DW_OP_entry_value(DW_OP_reg5 RDI), DW_OP_stack_value)
DW_AT_name ("dev")
DW_AT_type (0x00026859 "dev_t")
...
With skip_idx, we can identify that the second original argument
'dev' becomes the first one after optimization.
The previous patch has the following:
0x0533fd03: DW_TAG_subprogram
DW_AT_name ("acpi_irq_penalty_update")
DW_AT_calling_convention (DW_CC_nocall)
DW_AT_type (0x05334dc7 "int")
...
0x0533fd15: DW_TAG_formal_parameter
DW_AT_name ("str")
DW_AT_type (0x05335918 "char *")
...
0x0533fd1f: DW_TAG_formal_parameter
DW_AT_location (indexed (0x3b) loclist = 0x00eb9d83:
[0xffff80008419f2e0, 0xffff80008419f324): DW_OP_reg1 W1
[0xffff80008419f324, 0xffff80008419f47c): DW_OP_reg19 W19
[0xffff80008419f47c, 0xffff80008419f494): DW_OP_entry_value(DW_OP_reg1 W1), DW_OP_stack_value
[0xffff80008419f494, 0xffff80008419f498): DW_OP_reg19 W19)
DW_AT_name ("used")
DW_AT_type (0x05334dc7 "int")
...
It is also handled properly with parameter 'str' will have W0 register.
With this patch, I checked x86_64 that the number of invalid true signatures is reduced
from 532 to 96. This suggests that majority of optimized functions are caused by
dead arguments.
Signed-off-by: Yonghong Song <yonghong.song@linux.dev>
---
dwarf_loader.c | 93 +++++++++++++++++++++++++++++++++++++++++++++++---
1 file changed, 88 insertions(+), 5 deletions(-)
diff --git a/dwarf_loader.c b/dwarf_loader.c
index 412a73e..c1b7763 100644
--- a/dwarf_loader.c
+++ b/dwarf_loader.c
@@ -1195,10 +1195,62 @@ static ptrdiff_t __dwarf_getlocations(Dwarf_Attribute *attr,
struct func_info {
bool signature_changed;
+ int skip_idx;
int nr_params;
int param_start_regs[MAX_PRESCAN_PARAMS];
};
+static int __get_type_byte_size(Dwarf_Die *die, struct cu *cu)
+{
+ Dwarf_Attribute attr;
+ if (dwarf_attr(die, DW_AT_type, &attr) == NULL)
+ return 0;
+
+ Dwarf_Die type_die;
+ if (dwarf_formref_die(&attr, &type_die) == NULL)
+ return 0;
+
+ /* A type does not have byte_size.
+ * 0x000dac83: DW_TAG_formal_parameter
+ DW_AT_location (indexed (0x385) loclist = 0x00016175:
+ [0xffff800080098cb0, 0xffff800080098cb4): DW_OP_breg8 W8+0
+ [0xffff800080098cb4, 0xffff800080098ff4): DW_OP_breg31 WSP+16, DW_OP_deref
+ [0xffff800080099054, 0xffff80008009908c): DW_OP_breg31 WSP+16, DW_OP_deref)
+ DW_AT_name ("ubuf")
+ DW_AT_decl_file ("/home/yhs/work/bpf-next/arch/arm64/kernel/ptrace.c")
+ DW_AT_decl_line (886)
+ DW_AT_type (0x000d467e "const void *")
+
+ * 0x000d467e: DW_TAG_pointer_type
+ DW_AT_type (0x000c4320 "const void")
+
+ * 0x000c4320: DW_TAG_const_type
+ */
+ if (dwarf_tag(&type_die) == DW_TAG_pointer_type)
+ return cu->addr_size;
+
+ uint64_t bsize = attr_numeric(&type_die, DW_AT_byte_size);
+ if (bsize == 0)
+ return __get_type_byte_size(&type_die, cu);
+
+ return bsize;
+}
+
+static int get_type_byte_size(Dwarf_Die *die, struct cu *cu)
+{
+ int byte_size = 0;
+
+ Dwarf_Attribute attr;
+ if (dwarf_attr(die, DW_AT_abstract_origin, &attr)) {
+ Dwarf_Die origin;
+ if (dwarf_formref_die(&attr, &origin))
+ byte_size = __get_type_byte_size(&origin, cu);
+ } else {
+ byte_size = __get_type_byte_size(die, cu);
+ }
+ return byte_size;
+}
+
/* Get the first DW_OP_X (should be a register) from a parameter's DW_AT_location. */
static int parameter__peek_first_reg(Dwarf_Die *die)
{
@@ -1292,8 +1344,9 @@ static struct parameter *parameter__new(Dwarf_Die *die, struct cu *cu,
struct parameter *parm = tag__alloc(cu, sizeof(*parm));
if (parm != NULL) {
- bool has_const_value;
+ bool has_const_value, true_sig_enabled;
Dwarf_Attribute attr;
+ int reg_idx;
tag__init(&parm->tag, cu, die);
parm->name = attr_string(die, DW_AT_name, conf);
@@ -1303,8 +1356,10 @@ static struct parameter *parameter__new(Dwarf_Die *die, struct cu *cu,
if (!info->signature_changed) {
if (cu->producer_clang || param_idx >= cu->nr_register_params)
return parm;
- } else if (param_idx >= cu->nr_register_params) {
- return parm;
+ } else {
+ reg_idx = param_idx - info->skip_idx;
+ if (reg_idx >= cu->nr_register_params)
+ return parm;
}
/* Parameters which use DW_AT_abstract_origin to point at
@@ -1342,9 +1397,10 @@ static struct parameter *parameter__new(Dwarf_Die *die, struct cu *cu,
*/
has_const_value = dwarf_attr(die, DW_AT_const_value, &attr) != NULL;
parm->has_loc = dwarf_attr(die, DW_AT_location, &attr) != NULL;
+ true_sig_enabled = conf->true_signature && info->signature_changed;
if (parm->has_loc) {
- int expected_reg = cu->register_params[param_idx];
+ int expected_reg = cu->register_params[reg_idx];
int actual_reg = parameter__reg(&attr, expected_reg);
if (actual_reg < 0)
@@ -1357,8 +1413,35 @@ static struct parameter *parameter__new(Dwarf_Die *die, struct cu *cu,
* contents.
*/
parm->unexpected_reg = 1;
- } else if (has_const_value) {
+ } else if (has_const_value && !cu->producer_clang) {
+ parm->optimized = 1;
+ } else if (true_sig_enabled) {
+ int byte_size, num_regs, next_reg_idx;
+
+ if (param_idx + 1 < info->nr_params) {
+ int next_start = info->param_start_regs[param_idx + 1];
+ if (next_start >= 0) {
+ /* check whether we should preserve the argument or not */
+ byte_size = get_type_byte_size(die, cu);
+ /* byte_size 0 should not happen. */
+ if (!byte_size) {
+ parm->unexpected_reg = 1;
+ return parm;
+ }
+
+ num_regs = (byte_size + cu->addr_size - 1) / cu->addr_size;
+ next_reg_idx = reg_idx + num_regs;
+ if (next_reg_idx < cu->nr_register_params &&
+ next_start == cu->register_params[next_reg_idx]) {
+ if (byte_size > cu->addr_size)
+ info->skip_idx--;
+ return parm;
+ }
+ }
+ }
+
parm->optimized = 1;
+ info->skip_idx++;
}
}
--
2.52.0
next prev parent reply other threads:[~2026-03-26 1:32 UTC|newest]
Thread overview: 21+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-03-26 1:31 [PATCH dwarves v4 00/11] pahole: Encode true signatures in kernel BTF Yonghong Song
2026-03-26 1:31 ` [PATCH dwarves v4 01/11] dwarf_loader: Reduce parameter checking with clang DW_AT_calling_convention attr Yonghong Song
2026-03-30 8:31 ` Alan Maguire
2026-05-23 16:22 ` Yonghong Song
2026-03-26 1:31 ` [PATCH dwarves v4 02/11] dwarf_loader: Prescan all parameters with expected registers Yonghong Song
2026-03-26 1:31 ` Yonghong Song [this message]
2026-03-30 10:13 ` [PATCH dwarves v4 03/11] dwarf_loader: Handle signatures with dead arguments Alan Maguire
2026-05-23 16:28 ` Yonghong Song
2026-03-26 1:32 ` [PATCH dwarves v4 04/11] dwarf_loader: Refactor initial ret -1 to be macro PARM_DEFAULT_FAIL Yonghong Song
2026-03-26 1:32 ` [PATCH dwarves v4 05/11] dwarf_laoder: Handle locations with DW_OP_fbreg Yonghong Song
2026-03-26 1:32 ` [PATCH dwarves v4 06/11] dwarf_loader: Change exprlen checking condition in parameter__reg() Yonghong Song
2026-03-26 1:32 ` [PATCH dwarves v4 07/11] dwarf_loader: Detect optimized parameters with locations having constant values Yonghong Song
2026-03-26 1:32 ` [PATCH dwarves v4 08/11] dwarf_loader: Check whether two-reg parameter actually use two regs or not Yonghong Song
2026-03-26 1:32 ` [PATCH dwarves v4 09/11] dwarf_loader: Handle expression lists Yonghong Song
2026-03-31 8:04 ` Alan Maguire
2026-05-23 16:32 ` Yonghong Song
2026-03-26 1:33 ` [PATCH dwarves v4 10/11] btf_encoder: Handle optimized parameter properly Yonghong Song
2026-03-26 1:33 ` [PATCH dwarves v4 11/11] tests: Add a few clang true signature tests Yonghong Song
2026-03-27 16:02 ` [PATCH dwarves v4 00/11] pahole: Encode true signatures in kernel BTF Alan Maguire
2026-03-27 19:38 ` Yonghong Song
2026-03-30 9:56 ` Alan Maguire
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20260326013159.2904078-1-yonghong.song@linux.dev \
--to=yonghong.song@linux.dev \
--cc=alan.maguire@oracle.com \
--cc=andrii@kernel.org \
--cc=arnaldo.melo@gmail.com \
--cc=ast@kernel.org \
--cc=bpf@vger.kernel.org \
--cc=dwarves@vger.kernel.org \
--cc=kernel-team@fb.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.