-
Notifications
You must be signed in to change notification settings - Fork 305
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
kpatch-build: support CONFIG_LTO_CLANG_THIN #1325
Conversation
kpatch-build/create-diff-object.c
Outdated
* such as: | ||
* __initstub__kmod_syscall__728_5326_bpf_syscall_sysctl_init7 | ||
* while the original function is very similar, like: | ||
* __initstub__kmod_syscall__728_5324_bpf_syscall_sysctl_init7 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm a bit confused here, are they "weird new functions" or is it the same function with a slight rename?
If the latter, it sounds like maybe kpatch_mangled_strcmp() should be updated to recognize this renaming pattern. That way the functions get correlated correctly.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I played with kpatch_mangled_strcmp() a little bit, but didn't solve all the problem. Let me dig more into it.
sed -i "s/--thinlto-cache-dir=\$(extmod_prefix).thinlto-cache/--lto-obj-path=vmlinux.o.thinlto.o/g" "$KERNEL_SRCDIR"/Makefile | ||
|
||
cp -f "$KERNEL_SRCDIR/scripts/Makefile.build" "$TEMPDIR/Makefile.build" || die | ||
sed -i "s/\$(ld_flags)/\$(ld_flags) --lto-obj-path=\[email protected]/g" "$KERNEL_SRCDIR"/scripts/Makefile.build |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
These changes to Makefile and Makefile.build need short comments describing what they're doing and why
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah, updating kpatch_mangled_strcmp() solves the problem.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Bump
kpatch-build/kpatch-build
Outdated
@@ -1107,6 +1142,7 @@ declare -a MAKEVARS | |||
if [[ -n "$CONFIG_CC_IS_CLANG" ]]; then | |||
MAKEVARS+=("CC=${KPATCH_CC_PREFIX}${CLANG}") | |||
MAKEVARS+=("HOSTCC=clang") | |||
MAKEVARS+=("LLVM=1") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is only a one-line change but it has a big impact and belongs in a separate commit with proper justification. Also I wonder how it interacts with the CONFIG_LD_IS_LLD check.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It appears to me that I need to pass in LLVM=1 to the make command. Otherwise, the make will fail. I have the same change for PGO support.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It is possible for the user to specify CC=clang and LD=ld.lld separately. And LLVM=1 will enable a set of utilities. From llvm.rst:
LLVM has substitutes for GNU binutils utilities. They can be enabled individually.
The full list of supported make variables::
make CC=clang LD=ld.lld AR=llvm-ar NM=llvm-nm STRIP=llvm-strip \
OBJCOPY=llvm-objcopy OBJDUMP=llvm-objdump READELF=llvm-readelf \
HOSTCC=clang HOSTCXX=clang++ HOSTAR=llvm-ar HOSTLD=ld.lld
To simplify the above command, Kbuild supports the ``LLVM`` variable::
make LLVM=1
I changed the code to use CONFIG_AS_IS_LLVM to detect the use of LLVM=1. I think this should cover most use cases.
DIFF_OBJS="$TEMPDIR/thinlto_objs" | ||
else | ||
DIFF_OBJS="$TEMPDIR/changed_objs" | ||
fi |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why does lto need its own special file name?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Initially, I thought we may still use changed_objs for something else. But I think we didn't use it at the moment.
OTOH, "changed_objs" is not accurate for thin LTO, as not all these files are changed.
kpatch-build/create-diff-object.c
Outdated
*/ | ||
if (!strncmp(childobj, "vmlinux.o", 9) && | ||
!strncmp(sec->name, ".init.text", 10)) | ||
sec->ignore = 1; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Also this (or whatever the change eventually is) should probably be in its own commit.
It is common for the user to use LLVM=1 to enable all LLVM untilities. Use CONFIG_AS_IS_LLVM to detect such cases, and add LLVM=1 to MAKEVARS. Signed-off-by: Song Liu <[email protected]>
4c955d2
to
cb87482
Compare
@jpoimboe Does this version look reasonable? |
# Detech such case with CONFIG_AS_IS_LLVM flag. | ||
if [[ -n "$CONFIG_AS_IS_LLVM" ]]; then | ||
MAKEVARS+=("LLVM=1") | ||
fi |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This still doesn't seem quite right, but maybe nobody will notice ;-)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah, I couldn't think of a better test for LLVM=1.
|
||
return *s1 == *s2; | ||
} | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm not sure how this works. To match strcmp() semantics it needs to return 0 if they match.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Here's a simplified version (untested)
static int __kpatch_skip_digits_strcmp(char *s1, char *s2)
{
while (*s1 == *s2) {
if (!*s1)
return 0;
s1++;
s2++;
while (isdigit(*s1))
s1++;
while (isdigit(*s2))
s2++;
}
return 1;
}
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hmm.. I am also confused with 1/0 return value. Let me double check..
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Here's a simplified version (untested)
static int __kpatch_skip_digits_strcmp(char *s1, char *s2) { while (*s1 == *s2) { if (!*s1) return 0; s1++; s2++; while (isdigit(*s1)) s1++; while (isdigit(*s2)) s2++; } return 1; }
This is really clean. Thanks!
kpatch-build/kpatch-build
Outdated
|
||
# With LTO, many GLOBAL symbols are converted to LOCAL in vmlinux, | ||
# which confuses the klp reloc logic. Require vmlinux.o for LTO. | ||
[[ -e "$VMLINUX" ]] || die "For kernel with CONFIG_LTO_CLANG, please supply vmlinux.o via -v|--vmlinux option." |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
At this point I think we already know "$VMLINUX" exists so maybe we can skip this first check.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Will remove.
sed -i "s/--thinlto-cache-dir=\$(extmod_prefix).thinlto-cache/--lto-obj-path=vmlinux.o.thinlto.o/g" "$KERNEL_SRCDIR"/Makefile | ||
|
||
cp -f "$KERNEL_SRCDIR/scripts/Makefile.build" "$TEMPDIR/Makefile.build" || die | ||
sed -i "s/\$(ld_flags)/\$(ld_flags) --lto-obj-path=\[email protected]/g" "$KERNEL_SRCDIR"/scripts/Makefile.build |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Bump
find_kobj "$i" | ||
else | ||
KOBJFILE=${i/.o.thinlto.o*/} | ||
fi |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Bump
kpatch-build/kpatch-build
Outdated
KOBJFILE_PATH="${TEMPDIR}/module/$KOBJFILE.ko" | ||
SYMTAB="${KOBJFILE_PATH}.symtab" | ||
SYMVERS_FILE="$BUILDDIR/Module.symvers" | ||
fi |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Bump
The kernel use a special __initcall_stub() with CONFIG_LTO_CLANG to avoid name collisions. Handle it in kpatch_mangled_strcmp() by ignoring all digits for symbols start with __initstub__kmod_syscall__. Signed-off-by: Song Liu <[email protected]>
Support CONFIG_LTO_CLANG_THIN with ld.lld --lto-obj-path option. With CONFIG_LTO_CLANG_THIN, .o files are LLVM IR binary, so CDO doesn't work on .o file. To solve this issue, we CDO the thinlto files generated by the --lto-obj-path option. Clang LTO generates the thinlto files after cross file inline, so they are good candidates for CDO. See [1] for more discussions about this. To achieve this, we need: 1. kpatch-build to update kernel Makefile(s) so it generates thinlto files; 2. kpatch-build and kpatch-cc to save the thinlto file properly; 3. kpatch-build to feed these thinlto files to CDO; 4. The user need to supply vmlinux.o, from which we generate the symtab file. We need this because GLOBAL symbols may be marked as LOCAL in LTO vmlinux; [1] dynup#1320 Signed-off-by: Song Liu <[email protected]>
cb87482
to
a8c651f
Compare
@jpoimboe Could you please share your comments on the latest version? Thanks in advance! |
I tried out the patches against a 6.2 kernel and got the following errors:
The cause for the errors is the new CONFIG_CALL_DEPTH_TRACKING feature which enables CONFIG_PREFIX_SYMBOLS, which relies on objtool to create a The problem is that objtool didn't run on the vmlinux.o.thinlto.o* objects. Objtool has become an integral part of the x86 toolchain and removing it from patch module objects could create all kinds of surprises. So I'm thinking this approach may not work and we may have to add vmlinux.o support to CDO after all. |
Hmm... This does sound like a big problem. :(
How should we enable CDOing vmlinux.o? @jpoimboe IIRC, you plan to work on this soon? |
I could certainly do it, though I'm probably not free for at least a few weeks. |
At the moment, I am hoping this version will work for our 5.19 based kernel. If it doesn't work, we would probably need CDOing vmlinux.o soon.. |
If you rely on the ORC unwinder, static calls or return thunks then it may have problems... |
Hmm... we do use most of these. Let me see how bad it would be.. Maybe we can run objtool on these thinlto files before CDOing? |
Yes, maybe (but to be clear I'd rather avoid this type of Makefile hacking for kpatch upstream) |
Agreed. CDOing vmlinux.o is a much cleaner approach. We already use some non-upstream kpatch commits for PGO. If this hack works for short term, we will do the same. |
I am testing this change that run objtool on thinlto files: liu-song-6@1203c9f . I understand we don't want this in upstream, but just in case someone would like to test/use it before we can CDO vmlinux.o. |
This PR has been open for 60 days with no activity and no assignee. It will be closed in 7 days unless a comment is added. |
This PR was closed because it was inactive for 7 days after being marked stale. |
Support CONFIG_LTO_CLANG_THIN with ld.lld --lto-obj-path option.
With CONFIG_LTO_CLANG_THIN, .o files are LLVM IR binary, so CDO doesn't work on .o file. To solve this issue, we CDO the thinlto files generated by the --lto-obj-path option. Clang LTO generates the thinlto files after cross file inline, so they are good candidates for CDO. See [1] for more discussions about this.
To achieve this, we need:
[1] #1320
Signed-off-by: Song Liu [email protected]