Skip to content

Basic Clang PGO support #1231

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 4 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 13 additions & 2 deletions kpatch-build/create-diff-object.c
Original file line number Diff line number Diff line change
Expand Up @@ -454,6 +454,14 @@ static bool rela_equal(struct rela *rela1, struct rela *rela2)
!strcmp(rela2->sym->name, ".altinstr_aux"))
return true;

/*
* __llvm_prf_cnts is used by clang PGO to store counters. Ignore
* these to void unnecessary "changed function".
*/
if (!strcmp(rela1->sym->name, "__llvm_prf_cnts") &&
!strcmp(rela2->sym->name, "__llvm_prf_cnts"))
return true;

/*
* With -mcmodel=large on ppc64le, GCC might generate entries in the .toc
* section for relocation symbol references. The .toc offsets may change
Expand Down Expand Up @@ -986,6 +994,8 @@ static void kpatch_correlate_section(struct section *sec_orig,
kpatch_correlate_symbol(sec_orig->sym, sec_patched->sym);
}

static char *kpatch_section_function_name(struct section *sec);

static void kpatch_correlate_sections(struct list_head *seclist_orig,
struct list_head *seclist_patched)
{
Expand All @@ -995,8 +1005,9 @@ static void kpatch_correlate_sections(struct list_head *seclist_orig,
if (sec_orig->twin)
continue;
list_for_each_entry(sec_patched, seclist_patched, list) {
if (kpatch_mangled_strcmp(sec_orig->name, sec_patched->name) ||
sec_patched->twin)
if (sec_patched->twin ||
kpatch_mangled_strcmp(kpatch_section_function_name(sec_orig),
kpatch_section_function_name(sec_patched)))
continue;

if (is_special_static(is_rela_section(sec_orig) ?
Expand Down
20 changes: 19 additions & 1 deletion kpatch-build/kpatch-build
Original file line number Diff line number Diff line change
Expand Up @@ -677,9 +677,10 @@ usage() {
echo " --skip-cleanup Skip post-build cleanup" >&2
echo " --skip-compiler-check Skip compiler version matching check" >&2
echo " (not recommended)" >&2
echo " -p, --profile-data specify profile data for PGO (clang only)" >&2
}

options="$(getopt -o ha:r:s:c:v:j:t:n:o:dR -l "help,archversion:,sourcerpm:,sourcedir:,config:,vmlinux:,jobs:,target:,name:,output:,oot-module:,oot-module-src:,debug,skip-gcc-check,skip-compiler-check,skip-cleanup,non-replace" -- "$@")" || die "getopt failed"
options="$(getopt -o ha:r:s:c:v:j:t:n:o:dRp: -l "help,archversion:,sourcerpm:,sourcedir:,config:,vmlinux:,jobs:,target:,name:,output:,oot-module:,oot-module-src:,debug,skip-gcc-check,skip-compiler-check,skip-cleanup,non-replace,profile-data" -- "$@")" || die "getopt failed"

eval set -- "$options"

Expand Down Expand Up @@ -761,6 +762,10 @@ while [[ $# -gt 0 ]]; do
echo "WARNING: Skipping compiler version matching check (not recommended)"
SKIPCOMPILERCHECK=1
;;
-p|--profile-data)
PROFILE_DATA="$(readlink -f "$2")"
shift
;;
*)
[[ "$1" = "--" ]] && shift && continue
[[ ! -f "$1" ]] && die "patch file '$1' not found"
Expand Down Expand Up @@ -1056,6 +1061,16 @@ fi

if [[ -n "$CONFIG_CC_IS_CLANG" ]]; then
echo "WARNING: Clang support is experimental"
if [[ -z "$PROFILE_DATA" ]] && [[ -n "$CONFIG_PGO_CLANG" ]]; then
die "Please specify profile-data for CONFIG_PGO_CLANG"
fi
if [[ -n "$PROFILE_DATA" ]] && [[ -z "$CONFIG_PGO_CLANG" ]]; then
echo "WARNING profile-data specified w/o CONFIG_PGO_CLANG, ignore it"
fi
else
if [[ -n "$PROFILE_DATA" ]]; then
die "Only supports profile-data with Clang"
fi
fi

if [[ "$SKIPCOMPILERCHECK" -eq 0 ]]; then
Expand Down Expand Up @@ -1107,6 +1122,9 @@ declare -a MAKEVARS
if [[ -n "$CONFIG_CC_IS_CLANG" ]]; then
MAKEVARS+=("CC=${KPATCH_CC_PREFIX}${CLANG}")
MAKEVARS+=("HOSTCC=clang")
if [[ -n "$CONFIG_PGO_CLANG" ]]; then
MAKEVARS+=("LLVM=1 CFLAGS_PGO_CLANG=-fprofile-use=$PROFILE_DATA")
fi
else
MAKEVARS+=("CC=${KPATCH_CC_PREFIX}${GCC}")
fi
Expand Down
26 changes: 19 additions & 7 deletions kpatch-build/lookup.c
Original file line number Diff line number Diff line change
Expand Up @@ -91,11 +91,13 @@ static bool maybe_discarded_sym(const char *name)
}

static bool locals_match(struct lookup_table *table, int idx,
struct symbol *file_sym, struct list_head *sym_list)
struct symbol *file_sym, struct list_head *sym_list,
int match_pct)
{
struct symbol *sym;
struct object_symbol *table_sym;
int i, found;
int match_cnt = 0, mismatch_cnt = 0;

i = idx + 1;
for_each_obj_symbol_continue(i, table_sym, table) {
Expand All @@ -121,10 +123,18 @@ static bool locals_match(struct lookup_table *table, int idx,
}
}

if (!found)
return false;
if (found)
match_cnt++;
else
mismatch_cnt++;
}

if (match_cnt * 100 < (match_cnt + mismatch_cnt) * match_pct)
return false;

match_cnt = 0;
mismatch_cnt = 0;

sym = file_sym;
list_for_each_entry_continue(sym, sym_list, list) {
if (sym->type == STT_FILE)
Expand Down Expand Up @@ -157,11 +167,13 @@ static bool locals_match(struct lookup_table *table, int idx,
}
}

if (!found)
return false;
if (found)
match_cnt++;
else
mismatch_cnt++;
}

return true;
return match_cnt * 100 >= (match_cnt + mismatch_cnt) * match_pct;
}

static void find_local_syms(struct lookup_table *table, struct symbol *file_sym,
Expand All @@ -176,7 +188,7 @@ static void find_local_syms(struct lookup_table *table, struct symbol *file_sym,
continue;
if (strcmp(file_sym->name, sym->name))
continue;
if (!locals_match(table, i, file_sym, sym_list))
if (!locals_match(table, i, file_sym, sym_list, 90 /* match_pct */))
continue;
if (lookup_table_file_sym)
ERROR("found duplicate matches for %s local symbols in %s symbol table",
Expand Down