Skip to content

Commit a3b7eaf

Browse files
Dont internalize extern definitions and add proper section info
1 parent 0758647 commit a3b7eaf

File tree

2 files changed

+71
-4
lines changed

2 files changed

+71
-4
lines changed

src/llvm/mod.rs

Lines changed: 28 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -16,10 +16,11 @@ use llvm_sys::{
1616
LLVMAttributeFunctionIndex, LLVMLinkage, LLVMVisibility,
1717
bit_reader::LLVMParseBitcodeInContext2,
1818
core::{
19-
LLVMCreateMemoryBufferWithMemoryRange, LLVMDisposeMemoryBuffer, LLVMDisposeMessage,
20-
LLVMGetEnumAttributeKindForName, LLVMGetMDString, LLVMGetModuleInlineAsm, LLVMGetTarget,
21-
LLVMGetValueName2, LLVMRemoveEnumAttributeAtIndex, LLVMSetLinkage, LLVMSetModuleInlineAsm2,
22-
LLVMSetVisibility,
19+
LLVMCountBasicBlocks, LLVMCreateMemoryBufferWithMemoryRange, LLVMDisposeMemoryBuffer,
20+
LLVMDisposeMessage, LLVMGetEnumAttributeKindForName, LLVMGetMDString,
21+
LLVMGetModuleInlineAsm, LLVMGetTarget, LLVMGetValueName2, LLVMIsAFunction,
22+
LLVMIsAGlobalVariable, LLVMIsDeclaration, LLVMRemoveEnumAttributeAtIndex, LLVMSetLinkage,
23+
LLVMSetModuleInlineAsm2, LLVMSetSection, LLVMSetVisibility,
2324
},
2425
error::{
2526
LLVMDisposeErrorMessage, LLVMGetErrorMessage, LLVMGetErrorTypeId, LLVMGetStringErrorTypeId,
@@ -41,6 +42,7 @@ use llvm_sys::{
4142
LLVMCreatePassBuilderOptions, LLVMDisposePassBuilderOptions, LLVMRunPasses,
4243
},
4344
};
45+
use log::info;
4446
use tracing::{debug, error};
4547
pub(crate) use types::{
4648
context::{InstalledDiagnosticHandler, LLVMContext},
@@ -261,6 +263,28 @@ pub(crate) fn internalize(
261263
export_symbols: &HashSet<Cow<'_, [u8]>>,
262264
) {
263265
if !name.starts_with(b"llvm.") && !export_symbols.contains(name) {
266+
if unsafe { !LLVMIsAFunction(value).is_null() } {
267+
let num_blocks = unsafe { LLVMCountBasicBlocks(value) };
268+
if num_blocks == 0 {
269+
unsafe { LLVMSetSection(value, c".ksyms".as_ptr()) };
270+
info!(
271+
"not internalizing undefined function {}",
272+
str::from_utf8(name).unwrap_or("<invalid utf8>")
273+
);
274+
return;
275+
}
276+
}
277+
if unsafe { !LLVMIsAGlobalVariable(value).is_null() } {
278+
if unsafe { LLVMIsDeclaration(value) != 0 } {
279+
unsafe { LLVMSetSection(value, c".ksyms".as_ptr()) };
280+
info!(
281+
"not internalizing undefined global variable {}",
282+
str::from_utf8(name).unwrap_or("<invalid utf8>")
283+
);
284+
return;
285+
}
286+
}
287+
264288
unsafe { LLVMSetLinkage(value, LLVMLinkage::LLVMInternalLinkage) };
265289
unsafe { LLVMSetVisibility(value, LLVMVisibility::LLVMDefaultVisibility) };
266290
}

tests/assembly/extern_linkage.rs

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
// assembly-output: bpf-linker
2+
// compile-flags: --crate-type cdylib -C link-arg=--emit=llvm-ir
3+
4+
#![no_std]
5+
6+
// aux-build: loop-panic-handler.rs
7+
extern crate loop_panic_handler;
8+
9+
// Extern declarations
10+
extern "C" {
11+
fn bpf_kfunc_call_test_acquire(arg: *mut u64) -> *mut u64;
12+
fn bpf_kfunc_call_test_release(arg: *mut u64);
13+
static bpf_prog_active: u32;
14+
static CONFIG_HZ: u64;
15+
}
16+
17+
#[no_mangle]
18+
#[link_section = "tc"]
19+
pub fn test_extern_symbols() -> u64 {
20+
unsafe {
21+
let mut val: u64 = 42;
22+
let ptr = bpf_kfunc_call_test_acquire(&mut val as *mut u64);
23+
bpf_kfunc_call_test_release(ptr);
24+
25+
let active = core::ptr::read_volatile(&bpf_prog_active);
26+
let hz = core::ptr::read_volatile(&CONFIG_HZ);
27+
active as u64 + hz
28+
}
29+
}
30+
31+
32+
// Verify extern variables: external, not internal
33+
// CHECK: @bpf_prog_active = external{{.*}}global i32{{.*}}section ".ksyms"
34+
// CHECK: @CONFIG_HZ = external{{.*}}global i64{{.*}}section ".ksyms"
35+
// CHECK-NOT: @bpf_prog_active = internal
36+
// CHECK-NOT: @CONFIG_HZ = internal
37+
// Verify extern functions preserve linkage/calling convention/function signature
38+
// CHECK: declare ptr @bpf_kfunc_call_test_acquire(ptr){{.*}}section ".ksyms"
39+
// CHECK: declare void @bpf_kfunc_call_test_release(ptr){{.*}}section ".ksyms"
40+
// CHECK-NOT: declare internal{{.*}}@bpf_kfunc_call_test_acquire unnamed_addr #0
41+
// CHECK-NOT: declare internal{{.*}}@bpf_kfunc_call_test_release unnamed_addr #0
42+
// CHECK-NOT: declare{{.*}}fastcc{{.*}}@bpf_kfunc_call_test_acquire unnamed_addr #0
43+
// CHECK-NOT: declare{{.*}}fastcc{{.*}}@bpf_kfunc_call_test_release unnamed_addr #0

0 commit comments

Comments
 (0)