From: Thierry Treyer via B4 Relay <devnull+ttreyer.meta.com@kernel.org>
To: dwarves@vger.kernel.org, bpf@vger.kernel.org
Cc: Thierry Treyer <ttreyer@meta.com>,
acme@kernel.org, ast@kernel.org, yhs@meta.com,
andrii@kernel.org, ihor.solodrai@linux.dev,
songliubraving@meta.com, alan.maguire@oracle.com,
mykolal@meta.com
Subject: [PATCH RFC 1/3] dwarf_loader: Add parameters list to inlined expansion
Date: Wed, 16 Apr 2025 19:20:35 +0000 [thread overview]
Message-ID: <20250416-btf_inline-v1-1-e4bd2f8adae5@meta.com> (raw)
In-Reply-To: <20250416-btf_inline-v1-0-e4bd2f8adae5@meta.com>
From: Thierry Treyer <ttreyer@meta.com>
The parameters of inlined expansions are stored in the lexblock tag
list, making it difficult to iterate over the parameters of a given
inlined expansion.
Add a list of parameters to 'struct inline_expansion', so the parameters
are stored in their expansion instead of the lexblock.
Add location to 'struct parameter', so their location expression can be
referenced when consuming the DWARF.
Parameters with a constant value have their value stored in the location
too: 'location.expr' is set to NULL and 'location.exprlen' is set to the
constant's value.
Signed-off-by: Thierry Treyer <ttreyer@meta.com>
---
dwarf_loader.c | 167 ++++++++++++++++++++++++++++++++++-----------------------
dwarves.c | 26 +++++++++
dwarves.h | 6 +++
3 files changed, 132 insertions(+), 67 deletions(-)
diff --git a/dwarf_loader.c b/dwarf_loader.c
index 84122d04e42cab53c5598ae62b750a43e187e11d..24ac9afceb3793c165d3e92cfdfaf27ab67fd4d6 100644
--- a/dwarf_loader.c
+++ b/dwarf_loader.c
@@ -1297,6 +1297,8 @@ static struct parameter *parameter__new(Dwarf_Die *die, struct cu *cu,
parm->has_loc = dwarf_attr(die, DW_AT_location, &attr) != NULL;
if (parm->has_loc) {
+ attr_location(die, &parm->location.expr, &parm->location.exprlen);
+
int expected_reg = cu->register_params[param_idx];
int actual_reg = parameter__reg(&attr, expected_reg);
@@ -1312,6 +1314,8 @@ static struct parameter *parameter__new(Dwarf_Die *die, struct cu *cu,
parm->unexpected_reg = 1;
} else if (has_const_value) {
parm->optimized = 1;
+ parm->location.expr = NULL;
+ parm->location.exprlen = attr_numeric(die, DW_AT_const_value);
}
}
@@ -1374,6 +1378,8 @@ static struct inline_expansion *inline_expansion__new(Dwarf_Die *die, struct cu
dwarf_tag__set_attr_type(dtag, type, die, DW_AT_abstract_origin);
exp->ip.addr = 0;
exp->high_pc = 0;
+ exp->nr_parms = 0;
+ INIT_LIST_HEAD(&exp->parms);
if (!cu->has_addr_info)
goto out;
@@ -1794,6 +1800,7 @@ static struct tag *die__create_new_string_type(Dwarf_Die *die, struct cu *cu)
static struct tag *die__create_new_parameter(Dwarf_Die *die,
struct ftype *ftype,
struct lexblock *lexblock,
+ struct inline_expansion *exp,
struct cu *cu, struct conf_load *conf,
int param_idx)
{
@@ -1808,15 +1815,16 @@ static struct tag *die__create_new_parameter(Dwarf_Die *die,
if (add_child_llvm_annotations(die, param_idx, conf, &(tag__function(&ftype->tag)->annots)))
return NULL;
}
+ } else if (exp != NULL) {
+ /*
+ * Inline expansion stores the parameters in a list to emit
+ * .BTF_inline parameter location.
+ */
+ inline_expansion__add_parameter(exp, parm);
} else {
/*
- * DW_TAG_formal_parameters on a non DW_TAG_subprogram nor
- * DW_TAG_subroutine_type tag happens sometimes, likely due to
- * compiler optimizing away a inline expansion (at least this
- * was observed in some cases, such as in the Linux kernel
- * current_kernel_time function circa 2.6.20-rc5), keep it in
- * the lexblock tag list because it can be referenced as an
- * DW_AT_abstract_origin in another DW_TAG_formal_parameter.
+ * Keep it in the lexblock tag list because it can be referenced
+ * as an DW_AT_abstract_origin in another DW_TAG_formal_parameter.
*/
lexblock__add_tag(lexblock, &parm->tag);
}
@@ -1884,7 +1892,7 @@ static struct tag *die__create_new_subroutine_type(Dwarf_Die *die,
tag__print_not_supported(die);
continue;
case DW_TAG_formal_parameter:
- tag = die__create_new_parameter(die, ftype, NULL, cu, conf, -1);
+ tag = die__create_new_parameter(die, ftype, NULL, NULL, cu, conf, -1);
break;
case DW_TAG_unspecified_parameters:
ftype->unspec_parms = 1;
@@ -2136,10 +2144,13 @@ static struct tag *die__create_new_inline_expansion(Dwarf_Die *die,
struct lexblock *lexblock,
struct cu *cu, struct conf_load *conf);
-static int die__process_inline_expansion(Dwarf_Die *die, struct lexblock *lexblock, struct cu *cu, struct conf_load *conf)
+static int die__process_inline_expansion(Dwarf_Die *die,
+ struct inline_expansion *exp, struct lexblock *lexblock,
+ struct cu *cu, struct conf_load *conf)
{
Dwarf_Die child;
struct tag *tag;
+ int parm_idx = 0;
if (!dwarf_haschildren(die) || dwarf_child(die, &child) != 0)
return 0;
@@ -2179,6 +2190,7 @@ static int die__process_inline_expansion(Dwarf_Die *die, struct lexblock *lexblo
*
* cu__tag_not_handled(cu, die);
*/
+ tag = die__create_new_parameter(die, NULL, lexblock, exp, cu, conf, parm_idx++);
continue;
case DW_TAG_inlined_subroutine:
tag = die__create_new_inline_expansion(die, lexblock, cu, conf);
@@ -2230,7 +2242,7 @@ static struct tag *die__create_new_inline_expansion(Dwarf_Die *die,
if (exp == NULL)
return NULL;
- if (die__process_inline_expansion(die, lexblock, cu, conf) != 0) {
+ if (die__process_inline_expansion(die, exp, lexblock, cu, conf) != 0) {
tag__free(&exp->ip.tag, cu);
return NULL;
}
@@ -2315,7 +2327,7 @@ static int die__process_function(Dwarf_Die *die, struct ftype *ftype,
continue;
}
case DW_TAG_formal_parameter:
- tag = die__create_new_parameter(die, ftype, lexblock, cu, conf, param_idx++);
+ tag = die__create_new_parameter(die, ftype, lexblock, NULL, cu, conf, param_idx++);
break;
case DW_TAG_variable:
tag = die__create_new_variable(die, cu, conf, 0);
@@ -2607,54 +2619,87 @@ static void __tag__print_abstract_origin_not_found(struct tag *tag,
#define tag__print_abstract_origin_not_found(tag) \
__tag__print_abstract_origin_not_found(tag, __func__, __LINE__)
+static void parameter__recode_dwarf_type(struct parameter *parm, struct cu *cu)
+{
+ struct dwarf_cu *dcu = cu->priv;
+ struct dwarf_tag *dparm = tag__dwarf(&parm->tag);
+
+ if (dparm->type == 0) {
+ if (dparm->abstract_origin == 0) {
+ /* Function without parameters */
+ parm->tag.type = 0;
+ return;
+ }
+ // FIXME: Should this use find_type_by_ref instead?
+ struct dwarf_tag *dtype = dwarf_cu__find_tag_by_ref(dcu, dparm, abstract_origin);
+ if (dtype == NULL) {
+ tag__print_abstract_origin_not_found(&parm->tag);
+ return;
+ }
+ struct parameter *oparm = tag__parameter(dtag__tag(dtype));
+ parm->name = oparm->name;
+ parm->tag.type = dtag__tag(dtype)->type;
+ /* Share location information between parameter and abstract origin;
+ * if neither have location, we will mark the parameter as optimized out.
+ * Also share info regarding unexpected register use for parameters.
+ */
+ if (parm->has_loc)
+ oparm->has_loc = parm->has_loc;
+
+ if (parm->optimized)
+ oparm->optimized = parm->optimized;
+ if (parm->unexpected_reg)
+ oparm->unexpected_reg = parm->unexpected_reg;
+ return;
+ }
+
+ struct dwarf_tag *dtype = dwarf_cu__find_type_by_ref(dcu, dparm, type);
+ if (dtype == NULL) {
+ tag__print_type_not_found(&parm->tag);
+ return;
+ }
+ parm->tag.type = dtype->small_id;
+}
+
static void ftype__recode_dwarf_types(struct tag *tag, struct cu *cu)
{
struct parameter *pos;
- struct dwarf_cu *dcu = cu->priv;
struct ftype *type = tag__ftype(tag);
- ftype__for_each_parameter(type, pos) {
- struct dwarf_tag *dpos = tag__dwarf(&pos->tag);
- struct parameter *opos;
- struct dwarf_tag *dtype;
-
- if (dpos->type == 0) {
- if (dpos->abstract_origin == 0) {
- /* Function without parameters */
- pos->tag.type = 0;
- continue;
- }
- dtype = dwarf_cu__find_tag_by_ref(dcu, dpos, abstract_origin);
- if (dtype == NULL) {
- tag__print_abstract_origin_not_found(&pos->tag);
- continue;
- }
- opos = tag__parameter(dtag__tag(dtype));
- pos->name = opos->name;
- pos->tag.type = dtag__tag(dtype)->type;
- /* share location information between parameter and
- * abstract origin; if neither have location, we will
- * mark the parameter as optimized out. Also share
- * info regarding unexpected register use for
- * parameters.
- */
- if (pos->has_loc)
- opos->has_loc = pos->has_loc;
+ ftype__for_each_parameter(type, pos)
+ parameter__recode_dwarf_type(pos, cu);
+}
- if (pos->optimized)
- opos->optimized = pos->optimized;
- if (pos->unexpected_reg)
- opos->unexpected_reg = pos->unexpected_reg;
- continue;
- }
+static void inline_expansion__recode_dwarf_types(struct tag *tag, struct cu *cu)
+{
+ struct dwarf_cu *dcu = cu->priv;
+ struct dwarf_tag *dtag = tag__dwarf(tag);
- dtype = dwarf_cu__find_type_by_ref(dcu, dpos, type);
- if (dtype == NULL) {
- tag__print_type_not_found(&pos->tag);
- continue;
- }
- pos->tag.type = dtype->small_id;
+ /* DW_TAG_inlined_subroutine is an special case as dwarf_tag->id is
+ * in fact an abtract origin, i.e. must be looked up in the tags_table,
+ * not in the types_table.
+ */
+ struct dwarf_tag *ftype = NULL;
+ if (dtag->type != 0)
+ ftype = dwarf_cu__find_tag_by_ref(dcu, dtag, type);
+ else
+ ftype = dwarf_cu__find_tag_by_ref(dcu, dtag, abstract_origin);
+ if (ftype == NULL) {
+ if (dtag->type != 0)
+ tag__print_type_not_found(tag);
+ else
+ tag__print_abstract_origin_not_found(tag);
+ return;
}
+
+ // TODO: Is ftype a prototype or a function?
+ ftype__recode_dwarf_types(dtag__tag(ftype), cu);
+
+ struct tag *pos;
+ struct inline_expansion *exp = tag__inline_expansion(tag);
+ list_for_each_entry(pos, &exp->parms, node)
+ parameter__recode_dwarf_type(tag__parameter(pos), cu);
+ exp->ip.tag.type = ftype->small_id;
}
static void lexblock__recode_dwarf_types(struct lexblock *tag, struct cu *cu)
@@ -2671,18 +2716,7 @@ static void lexblock__recode_dwarf_types(struct lexblock *tag, struct cu *cu)
lexblock__recode_dwarf_types(tag__lexblock(pos), cu);
continue;
case DW_TAG_inlined_subroutine:
- if (dpos->type != 0)
- dtype = dwarf_cu__find_tag_by_ref(dcu, dpos, type);
- else
- dtype = dwarf_cu__find_tag_by_ref(dcu, dpos, abstract_origin);
- if (dtype == NULL) {
- if (dpos->type != 0)
- tag__print_type_not_found(pos);
- else
- tag__print_abstract_origin_not_found(pos);
- continue;
- }
- ftype__recode_dwarf_types(dtag__tag(dtype), cu);
+ inline_expansion__recode_dwarf_types(pos, cu);
continue;
case DW_TAG_formal_parameter:
@@ -2862,12 +2896,11 @@ static int tag__recode_dwarf_type(struct tag *tag, struct cu *cu)
case DW_TAG_namespace:
return namespace__recode_dwarf_types(tag, cu);
- /* Damn, DW_TAG_inlined_subroutine is an special case
- as dwarf_tag->id is in fact an abtract origin, i.e. must be
- looked up in the tags_table, not in the types_table.
- The others also point to routines, so are in tags_table */
case DW_TAG_inlined_subroutine:
+ inline_expansion__recode_dwarf_types(tag, cu);
+ return 0;
case DW_TAG_imported_module:
+ /* Modules point to routines, so are in tags_table */
dtype = dwarf_cu__find_tag_by_ref(cu->priv, dtag, type);
goto check_type;
/* Can be for both types and non types */
diff --git a/dwarves.c b/dwarves.c
index ef93239d26827711e23b405dd113986867d18507..2232ee713d57a92a700be56be7b7e1128741e24a 100644
--- a/dwarves.c
+++ b/dwarves.c
@@ -203,6 +203,20 @@ void formal_parameter_pack__delete(struct formal_parameter_pack *pack, struct cu
cu__tag_free(cu, &pack->tag);
}
+static void parameter__delete(struct parameter *parm, struct cu *cu);
+
+static void inline_expansion__delete(struct inline_expansion *exp, struct cu *cu)
+{
+ if (exp == NULL)
+ return;
+
+ struct tag *parm, *n;
+ list_for_each_entry_safe_reverse(parm, n, &exp->parms, node) {
+ list_del_init(&parm->node);
+ parameter__delete(tag__parameter(parm), cu);
+ }
+}
+
void tag__delete(struct tag *tag, struct cu *cu)
{
if (tag == NULL)
@@ -225,6 +239,8 @@ void tag__delete(struct tag *tag, struct cu *cu)
ftype__delete(tag__ftype(tag), cu); break;
case DW_TAG_subprogram:
function__delete(tag__function(tag), cu); break;
+ case DW_TAG_inlined_subroutine:
+ inline_expansion__delete(tag__inline_expansion(tag), cu); break;
case DW_TAG_lexical_block:
lexblock__delete(tag__lexblock(tag), cu); break;
case DW_TAG_GNU_template_parameter_pack:
@@ -1514,6 +1530,12 @@ void formal_parameter_pack__add(struct formal_parameter_pack *pack, struct param
list_add_tail(¶m->tag.node, &pack->params);
}
+void inline_expansion__add_parameter(struct inline_expansion *exp, struct parameter *parm)
+{
+ ++exp->nr_parms;
+ list_add_tail(&parm->tag.node, &exp->parms);
+}
+
void lexblock__add_tag(struct lexblock *block, struct tag *tag)
{
list_add_tail(&tag->node, &block->tags);
@@ -2116,6 +2138,10 @@ static int list__for_all_tags(struct list_head *list, struct cu *cu,
if (list__for_all_tags(&tag__lexblock(pos)->tags,
cu, iterator, cookie))
return 1;
+ } else if (pos->tag == DW_TAG_inlined_subroutine) {
+ if (list__for_all_tags(&tag__inline_expansion(pos)->parms,
+ cu, iterator, cookie))
+ return 1;
}
if (iterator(pos, cu, cookie))
diff --git a/dwarves.h b/dwarves.h
index 8234e1a09128c667a2a516dccb6d7c6a194f8c5b..38efd6a6e2b0b0e5a571a8d12bbec33502509d8b 100644
--- a/dwarves.h
+++ b/dwarves.h
@@ -811,6 +811,8 @@ struct inline_expansion {
struct ip_tag ip;
size_t size;
uint64_t high_pc;
+ struct list_head parms;
+ uint16_t nr_parms;
};
static inline struct inline_expansion *
@@ -819,6 +821,9 @@ static inline struct inline_expansion *
return (struct inline_expansion *)tag;
}
+struct parameter;
+void inline_expansion__add_parameter(struct inline_expansion *exp, struct parameter *parm);
+
struct label {
struct ip_tag ip;
const char *name;
@@ -929,6 +934,7 @@ size_t lexblock__fprintf(const struct lexblock *lexblock, const struct cu *cu,
struct parameter {
struct tag tag;
const char *name;
+ struct location location;
uint8_t optimized:1;
uint8_t unexpected_reg:1;
uint8_t has_loc:1;
--
2.47.1
WARNING: multiple messages have this Message-ID (diff)
From: Thierry Treyer <ttreyer@meta.com>
To: dwarves@vger.kernel.org, bpf@vger.kernel.org
Cc: Thierry Treyer <ttreyer@meta.com>,
acme@kernel.org, ast@kernel.org, yhs@meta.com,
andrii@kernel.org, ihor.solodrai@linux.dev,
songliubraving@meta.com, alan.maguire@oracle.com,
mykolal@meta.com
Subject: [PATCH RFC 1/3] dwarf_loader: Add parameters list to inlined expansion
Date: Wed, 16 Apr 2025 19:20:35 +0000 [thread overview]
Message-ID: <20250416-btf_inline-v1-1-e4bd2f8adae5@meta.com> (raw)
In-Reply-To: <20250416-btf_inline-v1-0-e4bd2f8adae5@meta.com>
The parameters of inlined expansions are stored in the lexblock tag
list, making it difficult to iterate over the parameters of a given
inlined expansion.
Add a list of parameters to 'struct inline_expansion', so the parameters
are stored in their expansion instead of the lexblock.
Add location to 'struct parameter', so their location expression can be
referenced when consuming the DWARF.
Parameters with a constant value have their value stored in the location
too: 'location.expr' is set to NULL and 'location.exprlen' is set to the
constant's value.
Signed-off-by: Thierry Treyer <ttreyer@meta.com>
---
dwarf_loader.c | 167 ++++++++++++++++++++++++++++++++++-----------------------
dwarves.c | 26 +++++++++
dwarves.h | 6 +++
3 files changed, 132 insertions(+), 67 deletions(-)
diff --git a/dwarf_loader.c b/dwarf_loader.c
index 84122d04e42cab53c5598ae62b750a43e187e11d..24ac9afceb3793c165d3e92cfdfaf27ab67fd4d6 100644
--- a/dwarf_loader.c
+++ b/dwarf_loader.c
@@ -1297,6 +1297,8 @@ static struct parameter *parameter__new(Dwarf_Die *die, struct cu *cu,
parm->has_loc = dwarf_attr(die, DW_AT_location, &attr) != NULL;
if (parm->has_loc) {
+ attr_location(die, &parm->location.expr, &parm->location.exprlen);
+
int expected_reg = cu->register_params[param_idx];
int actual_reg = parameter__reg(&attr, expected_reg);
@@ -1312,6 +1314,8 @@ static struct parameter *parameter__new(Dwarf_Die *die, struct cu *cu,
parm->unexpected_reg = 1;
} else if (has_const_value) {
parm->optimized = 1;
+ parm->location.expr = NULL;
+ parm->location.exprlen = attr_numeric(die, DW_AT_const_value);
}
}
@@ -1374,6 +1378,8 @@ static struct inline_expansion *inline_expansion__new(Dwarf_Die *die, struct cu
dwarf_tag__set_attr_type(dtag, type, die, DW_AT_abstract_origin);
exp->ip.addr = 0;
exp->high_pc = 0;
+ exp->nr_parms = 0;
+ INIT_LIST_HEAD(&exp->parms);
if (!cu->has_addr_info)
goto out;
@@ -1794,6 +1800,7 @@ static struct tag *die__create_new_string_type(Dwarf_Die *die, struct cu *cu)
static struct tag *die__create_new_parameter(Dwarf_Die *die,
struct ftype *ftype,
struct lexblock *lexblock,
+ struct inline_expansion *exp,
struct cu *cu, struct conf_load *conf,
int param_idx)
{
@@ -1808,15 +1815,16 @@ static struct tag *die__create_new_parameter(Dwarf_Die *die,
if (add_child_llvm_annotations(die, param_idx, conf, &(tag__function(&ftype->tag)->annots)))
return NULL;
}
+ } else if (exp != NULL) {
+ /*
+ * Inline expansion stores the parameters in a list to emit
+ * .BTF_inline parameter location.
+ */
+ inline_expansion__add_parameter(exp, parm);
} else {
/*
- * DW_TAG_formal_parameters on a non DW_TAG_subprogram nor
- * DW_TAG_subroutine_type tag happens sometimes, likely due to
- * compiler optimizing away a inline expansion (at least this
- * was observed in some cases, such as in the Linux kernel
- * current_kernel_time function circa 2.6.20-rc5), keep it in
- * the lexblock tag list because it can be referenced as an
- * DW_AT_abstract_origin in another DW_TAG_formal_parameter.
+ * Keep it in the lexblock tag list because it can be referenced
+ * as an DW_AT_abstract_origin in another DW_TAG_formal_parameter.
*/
lexblock__add_tag(lexblock, &parm->tag);
}
@@ -1884,7 +1892,7 @@ static struct tag *die__create_new_subroutine_type(Dwarf_Die *die,
tag__print_not_supported(die);
continue;
case DW_TAG_formal_parameter:
- tag = die__create_new_parameter(die, ftype, NULL, cu, conf, -1);
+ tag = die__create_new_parameter(die, ftype, NULL, NULL, cu, conf, -1);
break;
case DW_TAG_unspecified_parameters:
ftype->unspec_parms = 1;
@@ -2136,10 +2144,13 @@ static struct tag *die__create_new_inline_expansion(Dwarf_Die *die,
struct lexblock *lexblock,
struct cu *cu, struct conf_load *conf);
-static int die__process_inline_expansion(Dwarf_Die *die, struct lexblock *lexblock, struct cu *cu, struct conf_load *conf)
+static int die__process_inline_expansion(Dwarf_Die *die,
+ struct inline_expansion *exp, struct lexblock *lexblock,
+ struct cu *cu, struct conf_load *conf)
{
Dwarf_Die child;
struct tag *tag;
+ int parm_idx = 0;
if (!dwarf_haschildren(die) || dwarf_child(die, &child) != 0)
return 0;
@@ -2179,6 +2190,7 @@ static int die__process_inline_expansion(Dwarf_Die *die, struct lexblock *lexblo
*
* cu__tag_not_handled(cu, die);
*/
+ tag = die__create_new_parameter(die, NULL, lexblock, exp, cu, conf, parm_idx++);
continue;
case DW_TAG_inlined_subroutine:
tag = die__create_new_inline_expansion(die, lexblock, cu, conf);
@@ -2230,7 +2242,7 @@ static struct tag *die__create_new_inline_expansion(Dwarf_Die *die,
if (exp == NULL)
return NULL;
- if (die__process_inline_expansion(die, lexblock, cu, conf) != 0) {
+ if (die__process_inline_expansion(die, exp, lexblock, cu, conf) != 0) {
tag__free(&exp->ip.tag, cu);
return NULL;
}
@@ -2315,7 +2327,7 @@ static int die__process_function(Dwarf_Die *die, struct ftype *ftype,
continue;
}
case DW_TAG_formal_parameter:
- tag = die__create_new_parameter(die, ftype, lexblock, cu, conf, param_idx++);
+ tag = die__create_new_parameter(die, ftype, lexblock, NULL, cu, conf, param_idx++);
break;
case DW_TAG_variable:
tag = die__create_new_variable(die, cu, conf, 0);
@@ -2607,54 +2619,87 @@ static void __tag__print_abstract_origin_not_found(struct tag *tag,
#define tag__print_abstract_origin_not_found(tag) \
__tag__print_abstract_origin_not_found(tag, __func__, __LINE__)
+static void parameter__recode_dwarf_type(struct parameter *parm, struct cu *cu)
+{
+ struct dwarf_cu *dcu = cu->priv;
+ struct dwarf_tag *dparm = tag__dwarf(&parm->tag);
+
+ if (dparm->type == 0) {
+ if (dparm->abstract_origin == 0) {
+ /* Function without parameters */
+ parm->tag.type = 0;
+ return;
+ }
+ // FIXME: Should this use find_type_by_ref instead?
+ struct dwarf_tag *dtype = dwarf_cu__find_tag_by_ref(dcu, dparm, abstract_origin);
+ if (dtype == NULL) {
+ tag__print_abstract_origin_not_found(&parm->tag);
+ return;
+ }
+ struct parameter *oparm = tag__parameter(dtag__tag(dtype));
+ parm->name = oparm->name;
+ parm->tag.type = dtag__tag(dtype)->type;
+ /* Share location information between parameter and abstract origin;
+ * if neither have location, we will mark the parameter as optimized out.
+ * Also share info regarding unexpected register use for parameters.
+ */
+ if (parm->has_loc)
+ oparm->has_loc = parm->has_loc;
+
+ if (parm->optimized)
+ oparm->optimized = parm->optimized;
+ if (parm->unexpected_reg)
+ oparm->unexpected_reg = parm->unexpected_reg;
+ return;
+ }
+
+ struct dwarf_tag *dtype = dwarf_cu__find_type_by_ref(dcu, dparm, type);
+ if (dtype == NULL) {
+ tag__print_type_not_found(&parm->tag);
+ return;
+ }
+ parm->tag.type = dtype->small_id;
+}
+
static void ftype__recode_dwarf_types(struct tag *tag, struct cu *cu)
{
struct parameter *pos;
- struct dwarf_cu *dcu = cu->priv;
struct ftype *type = tag__ftype(tag);
- ftype__for_each_parameter(type, pos) {
- struct dwarf_tag *dpos = tag__dwarf(&pos->tag);
- struct parameter *opos;
- struct dwarf_tag *dtype;
-
- if (dpos->type == 0) {
- if (dpos->abstract_origin == 0) {
- /* Function without parameters */
- pos->tag.type = 0;
- continue;
- }
- dtype = dwarf_cu__find_tag_by_ref(dcu, dpos, abstract_origin);
- if (dtype == NULL) {
- tag__print_abstract_origin_not_found(&pos->tag);
- continue;
- }
- opos = tag__parameter(dtag__tag(dtype));
- pos->name = opos->name;
- pos->tag.type = dtag__tag(dtype)->type;
- /* share location information between parameter and
- * abstract origin; if neither have location, we will
- * mark the parameter as optimized out. Also share
- * info regarding unexpected register use for
- * parameters.
- */
- if (pos->has_loc)
- opos->has_loc = pos->has_loc;
+ ftype__for_each_parameter(type, pos)
+ parameter__recode_dwarf_type(pos, cu);
+}
- if (pos->optimized)
- opos->optimized = pos->optimized;
- if (pos->unexpected_reg)
- opos->unexpected_reg = pos->unexpected_reg;
- continue;
- }
+static void inline_expansion__recode_dwarf_types(struct tag *tag, struct cu *cu)
+{
+ struct dwarf_cu *dcu = cu->priv;
+ struct dwarf_tag *dtag = tag__dwarf(tag);
- dtype = dwarf_cu__find_type_by_ref(dcu, dpos, type);
- if (dtype == NULL) {
- tag__print_type_not_found(&pos->tag);
- continue;
- }
- pos->tag.type = dtype->small_id;
+ /* DW_TAG_inlined_subroutine is an special case as dwarf_tag->id is
+ * in fact an abtract origin, i.e. must be looked up in the tags_table,
+ * not in the types_table.
+ */
+ struct dwarf_tag *ftype = NULL;
+ if (dtag->type != 0)
+ ftype = dwarf_cu__find_tag_by_ref(dcu, dtag, type);
+ else
+ ftype = dwarf_cu__find_tag_by_ref(dcu, dtag, abstract_origin);
+ if (ftype == NULL) {
+ if (dtag->type != 0)
+ tag__print_type_not_found(tag);
+ else
+ tag__print_abstract_origin_not_found(tag);
+ return;
}
+
+ // TODO: Is ftype a prototype or a function?
+ ftype__recode_dwarf_types(dtag__tag(ftype), cu);
+
+ struct tag *pos;
+ struct inline_expansion *exp = tag__inline_expansion(tag);
+ list_for_each_entry(pos, &exp->parms, node)
+ parameter__recode_dwarf_type(tag__parameter(pos), cu);
+ exp->ip.tag.type = ftype->small_id;
}
static void lexblock__recode_dwarf_types(struct lexblock *tag, struct cu *cu)
@@ -2671,18 +2716,7 @@ static void lexblock__recode_dwarf_types(struct lexblock *tag, struct cu *cu)
lexblock__recode_dwarf_types(tag__lexblock(pos), cu);
continue;
case DW_TAG_inlined_subroutine:
- if (dpos->type != 0)
- dtype = dwarf_cu__find_tag_by_ref(dcu, dpos, type);
- else
- dtype = dwarf_cu__find_tag_by_ref(dcu, dpos, abstract_origin);
- if (dtype == NULL) {
- if (dpos->type != 0)
- tag__print_type_not_found(pos);
- else
- tag__print_abstract_origin_not_found(pos);
- continue;
- }
- ftype__recode_dwarf_types(dtag__tag(dtype), cu);
+ inline_expansion__recode_dwarf_types(pos, cu);
continue;
case DW_TAG_formal_parameter:
@@ -2862,12 +2896,11 @@ static int tag__recode_dwarf_type(struct tag *tag, struct cu *cu)
case DW_TAG_namespace:
return namespace__recode_dwarf_types(tag, cu);
- /* Damn, DW_TAG_inlined_subroutine is an special case
- as dwarf_tag->id is in fact an abtract origin, i.e. must be
- looked up in the tags_table, not in the types_table.
- The others also point to routines, so are in tags_table */
case DW_TAG_inlined_subroutine:
+ inline_expansion__recode_dwarf_types(tag, cu);
+ return 0;
case DW_TAG_imported_module:
+ /* Modules point to routines, so are in tags_table */
dtype = dwarf_cu__find_tag_by_ref(cu->priv, dtag, type);
goto check_type;
/* Can be for both types and non types */
diff --git a/dwarves.c b/dwarves.c
index ef93239d26827711e23b405dd113986867d18507..2232ee713d57a92a700be56be7b7e1128741e24a 100644
--- a/dwarves.c
+++ b/dwarves.c
@@ -203,6 +203,20 @@ void formal_parameter_pack__delete(struct formal_parameter_pack *pack, struct cu
cu__tag_free(cu, &pack->tag);
}
+static void parameter__delete(struct parameter *parm, struct cu *cu);
+
+static void inline_expansion__delete(struct inline_expansion *exp, struct cu *cu)
+{
+ if (exp == NULL)
+ return;
+
+ struct tag *parm, *n;
+ list_for_each_entry_safe_reverse(parm, n, &exp->parms, node) {
+ list_del_init(&parm->node);
+ parameter__delete(tag__parameter(parm), cu);
+ }
+}
+
void tag__delete(struct tag *tag, struct cu *cu)
{
if (tag == NULL)
@@ -225,6 +239,8 @@ void tag__delete(struct tag *tag, struct cu *cu)
ftype__delete(tag__ftype(tag), cu); break;
case DW_TAG_subprogram:
function__delete(tag__function(tag), cu); break;
+ case DW_TAG_inlined_subroutine:
+ inline_expansion__delete(tag__inline_expansion(tag), cu); break;
case DW_TAG_lexical_block:
lexblock__delete(tag__lexblock(tag), cu); break;
case DW_TAG_GNU_template_parameter_pack:
@@ -1514,6 +1530,12 @@ void formal_parameter_pack__add(struct formal_parameter_pack *pack, struct param
list_add_tail(¶m->tag.node, &pack->params);
}
+void inline_expansion__add_parameter(struct inline_expansion *exp, struct parameter *parm)
+{
+ ++exp->nr_parms;
+ list_add_tail(&parm->tag.node, &exp->parms);
+}
+
void lexblock__add_tag(struct lexblock *block, struct tag *tag)
{
list_add_tail(&tag->node, &block->tags);
@@ -2116,6 +2138,10 @@ static int list__for_all_tags(struct list_head *list, struct cu *cu,
if (list__for_all_tags(&tag__lexblock(pos)->tags,
cu, iterator, cookie))
return 1;
+ } else if (pos->tag == DW_TAG_inlined_subroutine) {
+ if (list__for_all_tags(&tag__inline_expansion(pos)->parms,
+ cu, iterator, cookie))
+ return 1;
}
if (iterator(pos, cu, cookie))
diff --git a/dwarves.h b/dwarves.h
index 8234e1a09128c667a2a516dccb6d7c6a194f8c5b..38efd6a6e2b0b0e5a571a8d12bbec33502509d8b 100644
--- a/dwarves.h
+++ b/dwarves.h
@@ -811,6 +811,8 @@ struct inline_expansion {
struct ip_tag ip;
size_t size;
uint64_t high_pc;
+ struct list_head parms;
+ uint16_t nr_parms;
};
static inline struct inline_expansion *
@@ -819,6 +821,9 @@ static inline struct inline_expansion *
return (struct inline_expansion *)tag;
}
+struct parameter;
+void inline_expansion__add_parameter(struct inline_expansion *exp, struct parameter *parm);
+
struct label {
struct ip_tag ip;
const char *name;
@@ -929,6 +934,7 @@ size_t lexblock__fprintf(const struct lexblock *lexblock, const struct cu *cu,
struct parameter {
struct tag tag;
const char *name;
+ struct location location;
uint8_t optimized:1;
uint8_t unexpected_reg:1;
uint8_t has_loc:1;
--
2.47.1
next prev parent reply other threads:[~2025-04-16 19:21 UTC|newest]
Thread overview: 25+ messages / expand[flat|nested] mbox.gz Atom feed top
2025-04-16 19:20 [PATCH RFC 0/3] list inline expansions in .BTF.inline Thierry Treyer via B4 Relay
2025-04-16 19:20 ` Thierry Treyer
2025-04-16 19:20 ` Thierry Treyer via B4 Relay [this message]
2025-04-16 19:20 ` [PATCH RFC 1/3] dwarf_loader: Add parameters list to inlined expansion Thierry Treyer
2025-04-16 19:20 ` [PATCH RFC 2/3] dwarf_loader: Add name to inline expansion Thierry Treyer via B4 Relay
2025-04-16 19:20 ` Thierry Treyer
2025-04-16 19:20 ` [PATCH RFC 3/3] inline_encoder: Introduce inline encoder to emit BTF.inline Thierry Treyer via B4 Relay
2025-04-16 19:20 ` Thierry Treyer
2025-04-25 18:40 ` [PATCH RFC 0/3] list inline expansions in .BTF.inline Daniel Xu
2025-04-28 20:51 ` Alexei Starovoitov
2025-04-29 19:14 ` Thierry Treyer
2025-04-29 23:58 ` Alexei Starovoitov
2025-04-30 15:25 ` Alan Maguire
2025-05-01 19:38 ` Thierry Treyer
2025-05-02 8:31 ` Alan Maguire
2025-05-19 12:02 ` Alan Maguire
2025-05-22 17:56 ` Thierry Treyer
2025-05-22 20:03 ` Andrii Nakryiko
2025-05-22 20:16 ` Eduard Zingerman
2025-05-23 18:57 ` Thierry Treyer
2025-05-26 14:30 ` Alan Maguire
2025-05-27 21:41 ` Andrii Nakryiko
2025-05-28 10:14 ` Alan Maguire
2025-05-23 17:33 ` Alexei Starovoitov
2025-05-23 18:35 ` Thierry Treyer
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=20250416-btf_inline-v1-1-e4bd2f8adae5@meta.com \
--to=devnull+ttreyer.meta.com@kernel.org \
--cc=acme@kernel.org \
--cc=alan.maguire@oracle.com \
--cc=andrii@kernel.org \
--cc=ast@kernel.org \
--cc=bpf@vger.kernel.org \
--cc=dwarves@vger.kernel.org \
--cc=ihor.solodrai@linux.dev \
--cc=mykolal@meta.com \
--cc=songliubraving@meta.com \
--cc=ttreyer@meta.com \
--cc=yhs@meta.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.