* [PATCH v4 dwarves 0/2] fixes for memory optimized BTF
@ 2024-09-30 8:17 Alan Maguire
2024-09-30 8:17 ` [PATCH v4 dwarves 1/2] btf_encoder: fix strncpy issues, other issues identified in code review Alan Maguire
` (2 more replies)
0 siblings, 3 replies; 5+ messages in thread
From: Alan Maguire @ 2024-09-30 8:17 UTC (permalink / raw)
To: acme
Cc: dwarves, eddyz87, olsajiri, shung-hsi.yu, jirislaby, sedat.dilek,
w, Alan Maguire
This series is identical in effect to [1], it is simply applied
on top of the "next" branch which now includes v2 of the series.
Patch 1 fixes issues identified in code review around use of
func->state, strncpy issues.
Patch 2 speeds up the btf_functions.sh test by reducing the
number of greps/pipes, shaving ~1 minute off execution time.
[1] https://lore.kernel.org/dwarves/20240925091734.1943742-1-alan.maguire@oracle.com/
Changes since v2:
- fixed checks of func->state since it is always non-NULL and removed
now-unneeded fields from dwarves.h; added assertions that either
ELF or DWARF data is present for func encoding (Jiri, patch 1)
- fixed strncpy() issues, improved equality comparions between types
(Eduard, patch 1)
- reworked btf_functions test to minimize overheads (patch 2)
Changes since RFC:
- fixed free issues (Jiri, patch 1)
- embed func state into struct elf_function as each function
has state, and we can use the stack for state comparison
avoiding the cost of additional allocations (patch 1)
- fix an intermittent coredump that resulted from using
btf__str_by_offset() string in adding function prototype;
needing more space could sometimes result in strset memory
movement which would in turn invalidate the char * string,
so copy it to a char array for param name/tag value encoding
(patch 1)
- improve logging of decision to skip functions so that we can
gather that info more easily for testing in patch 3
- added new option to pfunct to show all instances of a function
prototype and - if no function is specified - use the stealer
to dump out all prototypes more rapidly to aid quicker testing
- added test covering BTF function generation, checking that
DWARF/BTF are consistent and that for skipped functions the
skip rationale was valid (Jiri, patch 3)
Alan Maguire (2):
btf_encoder: fix strncpy issues, other issues identified in code
review
tests: improve btf_functions.sh by reducing greps/pipes
btf_encoder.c | 68 ++++++++++++++++++++++++++++--------------
tests/btf_functions.sh | 22 +++++---------
2 files changed, 54 insertions(+), 36 deletions(-)
--
2.43.5
^ permalink raw reply [flat|nested] 5+ messages in thread
* [PATCH v4 dwarves 1/2] btf_encoder: fix strncpy issues, other issues identified in code review
2024-09-30 8:17 [PATCH v4 dwarves 0/2] fixes for memory optimized BTF Alan Maguire
@ 2024-09-30 8:17 ` Alan Maguire
2024-09-30 8:17 ` [PATCH v4 dwarves 2/2] tests: improve btf_functions.sh by reducing greps/pipes Alan Maguire
2024-09-30 11:20 ` [PATCH v4 dwarves 0/2] fixes for memory optimized BTF Jiri Olsa
2 siblings, 0 replies; 5+ messages in thread
From: Alan Maguire @ 2024-09-30 8:17 UTC (permalink / raw)
To: acme
Cc: dwarves, eddyz87, olsajiri, shung-hsi.yu, jirislaby, sedat.dilek,
w, Alan Maguire
- fixed checks of func->state since it is always non-NULL and removed
now-unneeded fields from dwarves.h; added assertions that either
ELF or DWARF data is present for func encoding (Jiri)
- fixed strncpy() issues, improved equality comparions between types
(Eduard)
Signed-off-by: Alan Maguire <alan.maguire@oracle.com>
---
btf_encoder.c | 68 ++++++++++++++++++++++++++++++++++-----------------
1 file changed, 46 insertions(+), 22 deletions(-)
diff --git a/btf_encoder.c b/btf_encoder.c
index d535b90..92dc5c4 100644
--- a/btf_encoder.c
+++ b/btf_encoder.c
@@ -28,6 +28,7 @@
#include <unistd.h>
+#include <assert.h>
#include <errno.h>
#include <stdint.h>
#include <search.h> /* for tsearch(), tfind() and tdestroy() */
@@ -692,7 +693,8 @@ static int32_t btf_encoder__tag_type(struct btf_encoder *encoder, uint32_t tag_t
return encoder->type_id_off + tag_type;
}
-static int32_t btf_encoder__add_func_proto(struct btf_encoder *encoder, struct ftype *ftype, struct elf_function *func)
+static int32_t btf_encoder__add_func_proto(struct btf_encoder *encoder, struct ftype *ftype,
+ struct elf_function *func)
{
struct btf *btf = encoder->btf;
const struct btf_type *t;
@@ -701,16 +703,22 @@ static int32_t btf_encoder__add_func_proto(struct btf_encoder *encoder, struct f
int32_t id, type_id;
char tmp_name[KSYM_NAME_LEN];
const char *name;
- struct btf_encoder_func_state *state = &func->state;
+ struct btf_encoder_func_state *state;
+
+ assert(ftype != NULL || func != NULL);
/* add btf_type for func_proto */
if (ftype) {
nr_params = ftype->nr_parms + (ftype->unspec_parms ? 1 : 0);
type_id = btf_encoder__tag_type(encoder, ftype->tag.type);
- } else {
+ } else if (func) {
+ state = &func->state;
nr_params = state->nr_parms;
type_id = state->ret_type_id;
+ } else {
+ return 0;
}
+
id = btf__add_func_proto(btf, type_id);
if (id > 0) {
t = btf__type_by_id(btf, id);
@@ -730,25 +738,29 @@ static int32_t btf_encoder__add_func_proto(struct btf_encoder *encoder, struct f
type_id = param->tag.type == 0 ? 0 : encoder->type_id_off + param->tag.type;
++param_idx;
- if (btf_encoder__add_func_param(encoder, name, type_id, param_idx == nr_params))
+ if (btf_encoder__add_func_param(encoder, name, type_id,
+ param_idx == nr_params))
return -1;
}
++param_idx;
if (ftype->unspec_parms)
- if (btf_encoder__add_func_param(encoder, NULL, 0, param_idx == nr_params))
+ if (btf_encoder__add_func_param(encoder, NULL, 0,
+ param_idx == nr_params))
return -1;
} else {
for (param_idx = 0; param_idx < nr_params; param_idx++) {
struct btf_encoder_func_parm *p = &state->parms[param_idx];
+
name = btf__name_by_offset(btf, p->name_off);
/* adding BTF data may result in a move of the
* name string memory, so make a temporary copy.
*/
- strncpy(tmp_name, name, sizeof(tmp_name));
+ strncpy(tmp_name, name, sizeof(tmp_name) - 1);
- if (btf_encoder__add_func_param(encoder, tmp_name, p->type_id, param_idx == nr_params))
+ if (btf_encoder__add_func_param(encoder, tmp_name, p->type_id,
+ param_idx == nr_params))
return -1;
}
}
@@ -950,10 +962,17 @@ static bool types__match(struct btf_encoder *encoder,
return false;
}
- switch (btf_kind(t1)) {
+ switch (k1) {
case BTF_KIND_INT:
+ if (t1->size != t2->size)
+ return false;
+ if (*(__u32 *)(t1 + 1) != *(__u32 *)(t2 + 1))
+ return false;
+ return names__match(btf1, t1, btf2, t2);
case BTF_KIND_FLOAT:
- case BTF_KIND_FWD:
+ if (t1->size != t2->size)
+ return false;
+ return names__match(btf1, t1, btf2, t2);
case BTF_KIND_TYPEDEF:
case BTF_KIND_STRUCT:
case BTF_KIND_UNION:
@@ -1009,9 +1028,6 @@ static bool funcs__match(struct btf_encoder *encoder, struct elf_function *func,
{
uint8_t i;
- if (!s1->initialized || !s2->initialized)
- return true;
-
if (s1->nr_parms != s2->nr_parms) {
btf_encoder__log_func_skip(encoder, func,
"param count mismatch; %d params != %d params\n",
@@ -1081,7 +1097,8 @@ static int32_t btf_encoder__save_func(struct btf_encoder *encoder, struct functi
goto out;
}
state.parms[param_idx].name_off = str_off;
- state.parms[param_idx].type_id = param->tag.type == 0 ? 0 : encoder->type_id_off + param->tag.type;
+ state.parms[param_idx].type_id = param->tag.type == 0 ? 0 :
+ encoder->type_id_off + param->tag.type;
param_idx++;
}
if (ftype->unspec_parms)
@@ -1139,7 +1156,8 @@ out:
return err;
}
-static int32_t btf_encoder__add_func(struct btf_encoder *encoder, struct function *fn, struct elf_function *func)
+static int32_t btf_encoder__add_func(struct btf_encoder *encoder, struct function *fn,
+ struct elf_function *func)
{
int btf_fnproto_id, btf_fn_id, tag_type_id = 0;
int16_t component_idx = -1;
@@ -1147,19 +1165,23 @@ static int32_t btf_encoder__add_func(struct btf_encoder *encoder, struct functio
const char *value;
char tmp_value[KSYM_NAME_LEN];
+ assert(fn != NULL || func != NULL);
+
btf_fnproto_id = btf_encoder__add_func_proto(encoder, fn ? &fn->proto : NULL, func);
name = func->alias ?: func->name;
if (btf_fnproto_id >= 0)
- btf_fn_id = btf_encoder__add_ref_type(encoder, BTF_KIND_FUNC, btf_fnproto_id, name, false);
+ btf_fn_id = btf_encoder__add_ref_type(encoder, BTF_KIND_FUNC, btf_fnproto_id,
+ name, false);
if (btf_fnproto_id < 0 || btf_fn_id < 0) {
- printf("error: failed to encode function '%s': invalid %s\n", name, btf_fnproto_id < 0 ? "proto" : "func");
+ printf("error: failed to encode function '%s': invalid %s\n",
+ name, btf_fnproto_id < 0 ? "proto" : "func");
return -1;
}
if (!fn) {
struct btf_encoder_func_state *state = &func->state;
uint16_t idx;
- if (!state || state->nr_annots == 0)
+ if (state->nr_annots == 0)
return 0;
for (idx = 0; idx < state->nr_annots; idx++) {
@@ -1169,10 +1191,11 @@ static int32_t btf_encoder__add_func(struct btf_encoder *encoder, struct functio
/* adding BTF data may result in a mode of the
* value string memory, so make a temporary copy.
*/
- strncpy(tmp_value, value, sizeof(tmp_value));
+ strncpy(tmp_value, value, sizeof(tmp_value) - 1);
component_idx = a->component_idx;
- tag_type_id = btf_encoder__add_decl_tag(encoder, tmp_value, btf_fn_id, component_idx);
+ tag_type_id = btf_encoder__add_decl_tag(encoder, tmp_value,
+ btf_fn_id, component_idx);
if (tag_type_id < 0)
break;
}
@@ -1190,7 +1213,8 @@ static int32_t btf_encoder__add_func(struct btf_encoder *encoder, struct functio
}
}
if (tag_type_id < 0) {
- fprintf(stderr, "error: failed to encode tag '%s' to func %s with component_idx %d\n",
+ fprintf(stderr,
+ "error: failed to encode tag '%s' to func %s with component_idx %d\n",
value, name, component_idx);
return -1;
}
@@ -1207,7 +1231,7 @@ static int btf_encoder__add_saved_funcs(struct btf_encoder *encoder)
struct btf_encoder_func_state *state = &func->state;
struct btf_encoder *other_encoder = NULL;
- if (!state || !state->initialized || state->processed)
+ if (!state->initialized || state->processed)
continue;
/* merge optimized-out status across encoders; since each
* encoder has the same elf symbol table we can use the
@@ -1223,7 +1247,7 @@ static int btf_encoder__add_saved_funcs(struct btf_encoder *encoder)
other_func = &other_encoder->functions.entries[i];
other_state = &other_func->state;
- if (!other_state)
+ if (!other_state->initialized)
continue;
optimized = state->optimized_parms | other_state->optimized_parms;
unexpected = state->unexpected_reg | other_state->unexpected_reg;
--
2.43.5
^ permalink raw reply related [flat|nested] 5+ messages in thread
* [PATCH v4 dwarves 2/2] tests: improve btf_functions.sh by reducing greps/pipes
2024-09-30 8:17 [PATCH v4 dwarves 0/2] fixes for memory optimized BTF Alan Maguire
2024-09-30 8:17 ` [PATCH v4 dwarves 1/2] btf_encoder: fix strncpy issues, other issues identified in code review Alan Maguire
@ 2024-09-30 8:17 ` Alan Maguire
2024-09-30 11:20 ` [PATCH v4 dwarves 0/2] fixes for memory optimized BTF Jiri Olsa
2 siblings, 0 replies; 5+ messages in thread
From: Alan Maguire @ 2024-09-30 8:17 UTC (permalink / raw)
To: acme
Cc: dwarves, eddyz87, olsajiri, shung-hsi.yu, jirislaby, sedat.dilek,
w, Alan Maguire
Reduce number of greps/pipes to minimize overhead of test; in my
measurements this shaves ~1min off test run time to be approximately
4 minutes.
Signed-off-by: Alan Maguire <alan.maguire@oracle.com>
---
tests/btf_functions.sh | 22 ++++++++--------------
1 file changed, 8 insertions(+), 14 deletions(-)
diff --git a/tests/btf_functions.sh b/tests/btf_functions.sh
index 4a60a18..b8645cc 100755
--- a/tests/btf_functions.sh
+++ b/tests/btf_functions.sh
@@ -47,7 +47,8 @@ trap cleanup EXIT
test -n "$VERBOSE" && printf "Encoding..."
-pahole --btf_features=default --btf_encode_detached=$outdir/vmlinux.btf --verbose $vmlinux |grep "skipping BTF encoding of function" > ${outdir}/skipped_fns
+pahole --btf_features=default --btf_encode_detached=$outdir/vmlinux.btf --verbose $vmlinux |\
+ grep "skipping BTF encoding of function" > ${outdir}/skipped_fns
test -n "$VERBOSE" && printf "done.\n"
@@ -57,7 +58,7 @@ funcs=$(pfunct --format_path=btf $outdir/vmlinux.btf |sort)
# all functions from DWARF; some inline functions are not inlined so include them too
pfunct --all --no_parm_names --format_path=dwarf $vmlinux | \
- awk '{ print $0}'|sort|uniq > $outdir/dwarf.funcs
+ sort|uniq > $outdir/dwarf.funcs
# all functions from BTF (removing bpf_kfunc prefix where found)
pfunct --all --no_parm_names --format_path=btf $outdir/vmlinux.btf |\
awk '{ gsub("^bpf_kfunc ",""); print $0}'|sort|uniq > $outdir/btf.funcs
@@ -66,14 +67,12 @@ exact=0
inline=0
const_insensitive=0
-for f in $funcs ; do
- btf=$(grep " $f(" $outdir/btf.funcs)
+while IFS= read -r btf ; do
# look for non-inline match first
- dwarf=$(grep " $f(" $outdir/dwarf.funcs | grep -Ev "^inline ")
+ dwarf=$(grep -F "$btf" $outdir/dwarf.funcs)
if [[ "$btf" != "$dwarf" ]]; then
# function might be declared inline in DWARF.
- inline_dwarf=$(grep " $f(" $outdir/dwarf.funcs |grep "^inline ")
- if [[ "inline $btf" != "$inline_dwarf" ]]; then
+ if [[ "inline $btf" != "$dwarf" ]]; then
# some functions have multiple instances in DWARF where one has
# const param(s) and another does not (see errpos()). We do not
# mark these functions inconsistent as though they technically
@@ -83,7 +82,7 @@ for f in $funcs ; do
if [[ "$dwarf_noconst" =~ "$btf_noconst" ]]; then
const_insensitive=$((const_insensitive+1))
else
- echo "ERROR: mismatch for '$f()' : BTF '$btf' not found; DWARF '$dwarf'"
+ echo "ERROR: mismatch : BTF '$btf' not found; DWARF '$dwarf'"
fail
fi
else
@@ -92,7 +91,7 @@ for f in $funcs ; do
else
exact=$((exact+1))
fi
-done
+done < $outdir/btf.funcs
echo "Matched $exact functions exactly."
echo "Matched $inline functions with inlines."
@@ -133,8 +132,6 @@ for r in $return_mismatches ; do
grep " $r(" $outdir/dwarf.funcs | \
awk -v FN=$r '{i = index($0, FN); if (i>0) print substr($0, 0, i-1) }' \
| uniq > ${outdir}/retvals.$r
- test -n "$VERBOSE" && echo "'${r}()' has return values:"
- test -n "$VERBOSE" && cat ${outdir}/retvals.$r
cnt=$(wc -l ${outdir}/retvals.$r | awk '{ print $1 }')
if [[ $cnt -lt 2 ]]; then
echo "ERROR: '${r}()' has only one return value; it should not be reported as having incompatible return values"
@@ -159,14 +156,11 @@ for p in $param_mismatches ; do
skipmsg=$(awk -v FN=$p '{ if ($1 == FN) print $0 }' $outdir/skipped_fns)
altname=$(echo $skipmsg | awk '{ i=index($2,")"); print substr($2,2,i-2); }')
if [[ "$altname" != "$p" ]]; then
- test -n "$VERBOSE" && echo "skipping optimized function $p ($altname); pfunct may not reflect late optimizations."
optimized=$((optimized+1))
continue
fi
# Ensure there are multiple instances with incompatible params
grep " $p(" $outdir/dwarf.funcs | uniq > ${outdir}/protos.$p
- test -n "$VERBOSE" && echo "'${p}()' has prototypes:"
- test -n "$VERBOSE" && cat ${outdir}/protos.$p
cnt=$(wc -l ${outdir}/protos.$p | awk '{ print $1 }')
if [[ $cnt -lt 2 ]]; then
# function may be inlined in multiple sites with different protos
--
2.43.5
^ permalink raw reply related [flat|nested] 5+ messages in thread
* Re: [PATCH v4 dwarves 0/2] fixes for memory optimized BTF
2024-09-30 8:17 [PATCH v4 dwarves 0/2] fixes for memory optimized BTF Alan Maguire
2024-09-30 8:17 ` [PATCH v4 dwarves 1/2] btf_encoder: fix strncpy issues, other issues identified in code review Alan Maguire
2024-09-30 8:17 ` [PATCH v4 dwarves 2/2] tests: improve btf_functions.sh by reducing greps/pipes Alan Maguire
@ 2024-09-30 11:20 ` Jiri Olsa
2024-09-30 14:34 ` Arnaldo Carvalho de Melo
2 siblings, 1 reply; 5+ messages in thread
From: Jiri Olsa @ 2024-09-30 11:20 UTC (permalink / raw)
To: Alan Maguire
Cc: acme, dwarves, eddyz87, olsajiri, shung-hsi.yu, jirislaby,
sedat.dilek, w
On Mon, Sep 30, 2024 at 09:17:23AM +0100, Alan Maguire wrote:
> This series is identical in effect to [1], it is simply applied
> on top of the "next" branch which now includes v2 of the series.
>
> Patch 1 fixes issues identified in code review around use of
> func->state, strncpy issues.
>
> Patch 2 speeds up the btf_functions.sh test by reducing the
> number of greps/pipes, shaving ~1 minute off execution time.
>
> [1] https://lore.kernel.org/dwarves/20240925091734.1943742-1-alan.maguire@oracle.com/
>
> Changes since v2:
>
> - fixed checks of func->state since it is always non-NULL and removed
> now-unneeded fields from dwarves.h; added assertions that either
> ELF or DWARF data is present for func encoding (Jiri, patch 1)
lgtm
Acked-by: Jiri Olsa <jolsa@kernel.org>
jirka
> - fixed strncpy() issues, improved equality comparions between types
> (Eduard, patch 1)
> - reworked btf_functions test to minimize overheads (patch 2)
>
> Changes since RFC:
>
> - fixed free issues (Jiri, patch 1)
> - embed func state into struct elf_function as each function
> has state, and we can use the stack for state comparison
> avoiding the cost of additional allocations (patch 1)
> - fix an intermittent coredump that resulted from using
> btf__str_by_offset() string in adding function prototype;
> needing more space could sometimes result in strset memory
> movement which would in turn invalidate the char * string,
> so copy it to a char array for param name/tag value encoding
> (patch 1)
> - improve logging of decision to skip functions so that we can
> gather that info more easily for testing in patch 3
> - added new option to pfunct to show all instances of a function
> prototype and - if no function is specified - use the stealer
> to dump out all prototypes more rapidly to aid quicker testing
> - added test covering BTF function generation, checking that
> DWARF/BTF are consistent and that for skipped functions the
> skip rationale was valid (Jiri, patch 3)
>
> Alan Maguire (2):
> btf_encoder: fix strncpy issues, other issues identified in code
> review
> tests: improve btf_functions.sh by reducing greps/pipes
>
> btf_encoder.c | 68 ++++++++++++++++++++++++++++--------------
> tests/btf_functions.sh | 22 +++++---------
> 2 files changed, 54 insertions(+), 36 deletions(-)
>
> --
> 2.43.5
>
^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: [PATCH v4 dwarves 0/2] fixes for memory optimized BTF
2024-09-30 11:20 ` [PATCH v4 dwarves 0/2] fixes for memory optimized BTF Jiri Olsa
@ 2024-09-30 14:34 ` Arnaldo Carvalho de Melo
0 siblings, 0 replies; 5+ messages in thread
From: Arnaldo Carvalho de Melo @ 2024-09-30 14:34 UTC (permalink / raw)
To: Jiri Olsa
Cc: Alan Maguire, dwarves, eddyz87, shung-hsi.yu, jirislaby,
sedat.dilek, w
On Mon, Sep 30, 2024 at 01:20:11PM +0200, Jiri Olsa wrote:
> On Mon, Sep 30, 2024 at 09:17:23AM +0100, Alan Maguire wrote:
> > This series is identical in effect to [1], it is simply applied
> > on top of the "next" branch which now includes v2 of the series.
> >
> > Patch 1 fixes issues identified in code review around use of
> > func->state, strncpy issues.
> >
> > Patch 2 speeds up the btf_functions.sh test by reducing the
> > number of greps/pipes, shaving ~1 minute off execution time.
> >
> > [1] https://lore.kernel.org/dwarves/20240925091734.1943742-1-alan.maguire@oracle.com/
> >
> > Changes since v2:
> >
> > - fixed checks of func->state since it is always non-NULL and removed
> > now-unneeded fields from dwarves.h; added assertions that either
> > ELF or DWARF data is present for func encoding (Jiri, patch 1)
>
> lgtm
>
> Acked-by: Jiri Olsa <jolsa@kernel.org>
Thanks, applied to next,
- Arnaldo
^ permalink raw reply [flat|nested] 5+ messages in thread
end of thread, other threads:[~2024-09-30 14:34 UTC | newest]
Thread overview: 5+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2024-09-30 8:17 [PATCH v4 dwarves 0/2] fixes for memory optimized BTF Alan Maguire
2024-09-30 8:17 ` [PATCH v4 dwarves 1/2] btf_encoder: fix strncpy issues, other issues identified in code review Alan Maguire
2024-09-30 8:17 ` [PATCH v4 dwarves 2/2] tests: improve btf_functions.sh by reducing greps/pipes Alan Maguire
2024-09-30 11:20 ` [PATCH v4 dwarves 0/2] fixes for memory optimized BTF Jiri Olsa
2024-09-30 14:34 ` Arnaldo Carvalho de Melo
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox