Skip to content

Commit

Permalink
libcextract: Add support for Weak symbols for kernel mode
Browse files Browse the repository at this point in the history
Until this point all symbols found in kernel mode (usually using Symvers
file), were strong (with externalized variables) or none (which copied
the symbols to the closure). Now clang-extract checks is the symbol is
present on vmlinux, meaning that the symbol is weak externalized,
meaning the the symbol will be always present.

Signed-off-by: Marcos Paulo de Souza <[email protected]>
  • Loading branch information
marcosps committed Aug 15, 2024
1 parent 272ac2e commit 55375f4
Show file tree
Hide file tree
Showing 5 changed files with 45 additions and 3 deletions.
6 changes: 6 additions & 0 deletions libcextract/InlineAnalysis.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -296,6 +296,12 @@ ExternalizationType InlineAnalysis::Needs_Externalization(const std::string &sym
{
if (Symv) {
const std::string &sym_mod = Symv->Get_Symbol_Module(sym);
/* If the symbol comes from vmlinux, then we should use Weak
* externalization, since the symbol is always present when loading the
* livepatch. */
if (sym_mod == "vmlinux")
return ExternalizationType::WEAK;

/*
* If the symbol exists on Symvers we can decide whether the symbol must be
* externalized or not, and not rely on ELF.
Expand Down
16 changes: 15 additions & 1 deletion libcextract/Passes.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -538,9 +538,23 @@ class IbtTailGeneratePass : public Pass
PassName = "IbtTailGeneratePass";
}

/* There are a few cases where we don't want IBT tail declarations to be
* defined:
* * If IBT is not enabled
* * If there are not externalized symbols
* * If all the externalized symbols are weak
*/
virtual bool Gate(PassManager::Context *ctx)
{
return ctx->Ibt && ctx->Externalize.size() > 0;
if (!ctx->Ibt || ctx->Externalize.size() == 0)
return false;

for (const ExternalizerLogEntry &entry : ctx->NamesLog) {
if (entry.Type == ExternalizationType::STRONG)
return true;
}

return false;
}

virtual bool Run_Pass(PassManager::Context *ctx)
Expand Down
7 changes: 6 additions & 1 deletion libcextract/SymbolExternalizer.hh
Original file line number Diff line number Diff line change
Expand Up @@ -101,8 +101,13 @@ struct SymbolUpdateStatus
}

/* For IBT, NewDecl and OldDecl are the same if the symbols is a function, so
don't replace text if the name didn't change. */
don't replace text if the name didn't change.
In the case of WEAK externalization NewDecl will also be empty, but in this
case we don't want a symbol rename. */
inline bool Needs_Sym_Rename(void) {
if (ExtType == ExternalizationType::WEAK)
return false;

if (NewDecl == nullptr)
return true;

Expand Down
3 changes: 2 additions & 1 deletion testsuite/linux/Modules.symvers
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
0x00000000 crc32c lib/libcrc32c EXPORT_SYMBOL
0x00000000 crc32c lib/libcrc32c EXPORT_SYMBOL
0x00000000 bpf_prog_put vmlinux EXPORT_SYMBOL_GPL
16 changes: 16 additions & 0 deletions testsuite/linux/weak-symbols.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
/* { dg-options "-DCE_EXTRACT_FUNCTIONS=f -DCE_SYMVERS_PATH=../testsuite/linux/Modules.symvers -DCE_RENAME_SYMBOLS -nostdinc -I../testsuite/linux -D__USE_IBT__ -D__KERNEL__" } */

int bpf_prog_put(void);

int bpf_prog_put(void)
{
return 42;
}

int f(void)
{
return bpf_prog_put();
}

/* { dg-final { scan-tree-dump "int bpf_prog_put\(void\);" } } */
/* { dg-final { scan-tree-dump-not "return 42;" } } */

0 comments on commit 55375f4

Please sign in to comment.