* [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 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.