Instead of finding libelf on host system like this:
https://github.com/ClangBuiltLinux/linux/blob/0e698dfa282211e414076f9dc7e83c1c288314fd/Makefile#L1018
we could include (a subset of) libelf with the kernel. This will allow UNWINDER_ORC to be enabled regardless of the availability of libelf on the host system. Right now it's disabled even if libelf is available unless clang is built with CLANG_DEFAULT_LINKER=lld: https://github.com/ClangBuiltLinux/linux/issues/479#issuecomment-492460731.
libelf comes from elfutils which is a big project and has certain incompatibilities with clang (e.g. using nested functions, a gnu-specific extension not supported by clang). So my suggestion is to extract only the necessary functions from libelf and bundle it with the kernel. The libraries of elfutils project are dual licensed under GPLv2+/LGPLv3+.
One could also use a different, more portable libelf implementation to make it easier to port the subset to the kernel, there's a libelf version that has been dead forever that works, or one present in elftoolchain.
I guess a useful start would be checking what functions from libelf are needed in the kernel.
There is another implement of libelf from BSD:
https://sourceforge.net/p/elftoolchain/wiki/Home/
https://wiki.freebsd.org/LibElf
It don't have GNU extensions and works fine when compiling Linux with clang.
However, this project uses BSD make, so the Makefile needs to be rewritten to GNU style.
https://fossies.org/linux/misc/old/libelf-0.8.13.tar.gz This is the dead libelf I was referring to, I think it's GPL2 or LGPL2? So licensing-wise probably easier to integrate than the elftoolchain version? And it works with clang unlike the elfutils version. So maybe the relevant subset could be pulled from this, and then the newer libelf features the kernel uses that it doesn't support like ELF_C_READ_MMAP could be added to it? It would also be convenient because there wouldn't be any need to worry about merging upstream changes because it gets no development.
elftoolchain will stop working with kernel 5.8, because the kernel started using gelf_getsymshndx(), with a 2nd parameter that is NULL (it is sometimes set to non-NULL if a condition is true), and elfutils' libelf works with a NULL 2nd parameter, but elftoolchain's libelf does not, so for it to continue working, elftoolchain's gelf_getsymshndx() needs to be changed to support NULL as the 2nd parameter.
elftoolchain will stop working with kernel 5.8, because the kernel started using gelf_getsymshndx(), with a 2nd parameter that is NULL (it is sometimes set to non-NULL if a condition is true), and elfutils' libelf works with a NULL 2nd parameter, but elftoolchain's libelf does not, so for it to continue working, elftoolchain's gelf_getsymshndx() needs to be changed to support NULL as the 2nd parameter.
This has been fixed upstream
Most helpful comment
There is another implement of libelf from BSD:
https://sourceforge.net/p/elftoolchain/wiki/Home/
https://wiki.freebsd.org/LibElf
It don't have GNU extensions and works fine when compiling Linux with clang.
However, this project uses BSD make, so the Makefile needs to be rewritten to GNU style.