diff options
Diffstat (limited to 'poky/meta/recipes-kernel/perf')
-rw-r--r-- | poky/meta/recipes-kernel/perf/perf.bb | 57 | ||||
-rwxr-xr-x | poky/meta/recipes-kernel/perf/perf/sort-pmuevents.py | 93 |
2 files changed, 149 insertions, 1 deletions
diff --git a/poky/meta/recipes-kernel/perf/perf.bb b/poky/meta/recipes-kernel/perf/perf.bb index 5faf22a26..b4683720a 100644 --- a/poky/meta/recipes-kernel/perf/perf.bb +++ b/poky/meta/recipes-kernel/perf/perf.bb @@ -32,6 +32,7 @@ PACKAGECONFIG[coresight] = "CORESIGHT=1,,opencsd" # libunwind is not yet ported for some architectures PACKAGECONFIG_remove_arc = "libunwind" PACKAGECONFIG_remove_riscv64 = "libunwind" +PACKAGECONFIG_remove_riscv32 = "libunwind" DEPENDS = " \ virtual/${MLPREFIX}libc \ @@ -81,6 +82,7 @@ EXTRA_OEMAKE = '\ AR="${AR}" \ LD="${LD}" \ EXTRA_CFLAGS="-ldw" \ + YFLAGS='-y --file-prefix-map=${WORKDIR}=/usr/src/debug/${PN}/${EXTENDPE}${PV}-${PR}' \ EXTRA_LDFLAGS="${PERF_EXTRA_LDFLAGS}" \ perfexecdir=${libexecdir} \ NO_GTK2=1 \ @@ -214,6 +216,51 @@ do_configure_prepend () { ${S}/tools/build/Makefile.build fi + # start reproducibility substitutions + if [ -e "${S}/tools/perf/Makefile.config" ]; then + # The following line in the Makefle: + # override PYTHON := $(call get-executable-or-default,PYTHON,$(PYTHON_AUTO)) + # "PYTHON" / "PYTHON_AUTO" have the full path as part of the variable. We've + # ensure that the environment is setup and we do not need the full path to be + # captured, since the symbol gets built into the executable, making it not + # reproducible. + sed -i -e 's,$(call get-executable-or-default\,PYTHON\,$(PYTHON_AUTO)),$(notdir $(call get-executable-or-default\,PYTHON\,$(PYTHON_AUTO))),g' \ + ${S}/tools/perf/Makefile.config + + # The following line: + # srcdir_SQ = $(patsubst %tools/perf,tools/perf,$(subst ','\'',$(srcdir))), + # Captures the full src path of perf, which of course makes it not + # reproducible. We really only need the relative location 'tools/perf', so we + # change the Makefile line to remove everything before 'tools/perf' + sed -i -e "s%srcdir_SQ = \$(subst ','\\\'',\$(srcdir))%srcdir_SQ = \$(patsubst \%tools/perf,tools/perf,\$(subst ','\\\'',\$(srcdir)))%g" \ + ${S}/tools/perf/Makefile.config + fi + if [ -e "${S}/tools/perf/tests/Build" ]; then + # OUTPUT is the full path, we have python on the path so we remove it from the + # definition. This is captured in the perf binary, so breaks reproducibility + sed -i -e 's,PYTHONPATH="BUILD_STR($(OUTPUT)python)",PYTHONPATH="BUILD_STR(python)",g' \ + ${S}/tools/perf/tests/Build + fi + if [ -e "${S}/tools/perf/util/Build" ]; then + # To avoid bison generating #ifdefs that have captured paths, we make sure + # all the calls have YFLAGS, which contains prefix mapping information. + sed -i -e 's,$(BISON),$(BISON) $(YFLAGS),g' ${S}/tools/perf/util/Build + fi + if [ -e "${S}/scripts/Makefile.host" ]; then + # To avoid yacc (bison) generating #ifdefs that have captured paths, we make sure + # all the calls have YFLAGS, which contains prefix mapping information. + sed -i -e 's,$(YACC),$(YACC) $(YFLAGS),g' ${S}/scripts/Makefile.host + fi + if [ -e "${S}/tools/perf/pmu-events/Build" ]; then + target='$(OUTPUT)pmu-events/pmu-events.c $(V)' + replacement1='$(OUTPUT)pmu-events/pmu-events.c $(V)\n' + replacement2='\t$(srctree)/sort-pmuevents.py $(OUTPUT)pmu-events/pmu-events.c $(OUTPUT)pmu-events/pmu-events.c.new\n' + replacement3='\tcp $(OUTPUT)pmu-events/pmu-events.c.new $(OUTPUT)pmu-events/pmu-events.c' + sed -i -e "s,$target,$replacement1$replacement2$replacement3,g" \ + "${S}/tools/perf/pmu-events/Build" + fi + # end reproducibility substitutions + # We need to ensure the --sysroot option in CC is preserved if [ -e "${S}/tools/perf/Makefile.perf" ]; then sed -i 's,CC = $(CROSS_COMPILE)gcc,#CC,' ${S}/tools/perf/Makefile.perf @@ -254,6 +301,14 @@ do_configure_prepend () { # so we copy it from the sysroot unistd.h to the perf unistd.h install -D -m0644 ${STAGING_INCDIR}/asm-generic/unistd.h ${S}/tools/include/uapi/asm-generic/unistd.h install -D -m0644 ${STAGING_INCDIR}/asm-generic/unistd.h ${S}/include/uapi/asm-generic/unistd.h + + # the fetcher is inhibited by the 'inherit kernelsrc', so we do a quick check and + # copy for a helper script we need + for p in $(echo ${FILESPATH} | tr ':' '\n'); do + if [ -e $p/sort-pmuevents.py ]; then + cp $p/sort-pmuevents.py ${S} + fi + done } python do_package_prepend() { @@ -269,7 +324,7 @@ RDEPENDS_${PN} += "elfutils bash" RDEPENDS_${PN}-archive =+ "bash" RDEPENDS_${PN}-python =+ "bash python3 python3-modules ${@bb.utils.contains('PACKAGECONFIG', 'audit', 'audit-python3', '', d)}" RDEPENDS_${PN}-perl =+ "bash perl perl-modules" -RDEPENDS_${PN}-tests =+ "python3" +RDEPENDS_${PN}-tests =+ "python3 bash" RSUGGESTS_SCRIPTING = "${@bb.utils.contains('PACKAGECONFIG', 'scripting', '${PN}-perl ${PN}-python', '',d)}" RSUGGESTS_${PN} += "${PN}-archive ${PN}-tests ${RSUGGESTS_SCRIPTING}" diff --git a/poky/meta/recipes-kernel/perf/perf/sort-pmuevents.py b/poky/meta/recipes-kernel/perf/perf/sort-pmuevents.py new file mode 100755 index 000000000..5ddf0f144 --- /dev/null +++ b/poky/meta/recipes-kernel/perf/perf/sort-pmuevents.py @@ -0,0 +1,93 @@ +#!/usr/bin/env python3 + +# perf pmu-events sorting tool +# +# Copyright (C) 2021 Bruce Ashfield +# +# SPDX-License-Identifier: MIT +# + +import sys +import os +import re +from collections import OrderedDict + +if len(sys.argv) < 2: + print( "[ERROR]: input and output pmu files missing" ) + sys.exit(1) + +if len(sys.argv) < 3: + print( "[ERROR]: output pmu file missing" ) + sys.exit(1) + +infile = sys.argv[1] +outfile = sys.argv[2] + +if not os.path.exists(infile): + print( "ERROR. input file does not exist: %s" % infile ) + sys.exit(1) + +if os.path.exists(outfile): + print( "WARNING. output file will be overwritten: %s" % infile ) + +with open(infile, 'r') as file: + data = file.read() + +preamble_regex = re.compile( '^(.*?)^struct', re.MULTILINE | re.DOTALL ) + +preamble = re.search( preamble_regex, data ) +struct_block_regex = re.compile( '^struct.*?(\w+) (.*?)\[\] = {(.*?)^};', re.MULTILINE | re.DOTALL ) +field_regex = re.compile( '{.*?},', re.MULTILINE | re.DOTALL ) +cpuid_regex = re.compile( '\.cpuid = (.*?),', re.MULTILINE | re.DOTALL ) +name_regex = re.compile( '\.name = (.*?),', re.MULTILINE | re.DOTALL ) + +# create a dictionary structure to store all the structs, their +# types and then their fields. +entry_dict = {} +for struct in re.findall( struct_block_regex, data ): + # print( "struct: %s %s" % (struct[0],struct[1]) ) + entry_dict[struct[1]] = {} + entry_dict[struct[1]]['type'] = struct[0] + entry_dict[struct[1]]['fields'] = {} + for entry in re.findall( field_regex, struct[2] ): + #print( " entry: %s" % entry ) + cpuid = re.search( cpuid_regex, entry ) + if cpuid: + #print( " cpuid found: %s" % cpuid.group(1) ) + entry_dict[struct[1]]['fields'][cpuid.group(1)] = entry + + name = re.search( name_regex, entry ) + if name: + #print( " name found: %s" % name.group(1) ) + entry_dict[struct[1]]['fields'][name.group(1)] = entry + + +# created ordered dictionaries from the captured values. These are ordered by +# a sorted() iteration of the keys. We don't care about the order we read +# things, just the sorted order. Hency why we couldn't create these during +# reading. +# +# yes, there's a more concise way to do this, but our nested dictionaries of +# fields make it complex enough that it becomes unreadable. +entry_dict_sorted = OrderedDict() +for i in sorted(entry_dict.keys()): + entry_dict_sorted[i] = {} + entry_dict_sorted[i]['type'] = entry_dict[i]['type'] + entry_dict_sorted[i]['fields'] = {} + for f in sorted(entry_dict[i]['fields'].keys()): + entry_dict_sorted[i]['fields'][f] = entry_dict[i]['fields'][f] + +# dump the sorted elements to the outfile +outf = open( outfile, 'w' ) + +print( preamble.group(1) ) +outf.write( preamble.group(1) ) +for d in entry_dict_sorted: + outf.write( "struct %s %s[] = {\n" % (entry_dict_sorted[d]['type'],d) ) + for f in entry_dict_sorted[d]['fields']: + outf.write( entry_dict_sorted[d]['fields'][f] + '\n' ) + + outf.write( "};\n" ) + +outf.close() + |