Skip to content

Commit

Permalink
Provide LLVMTypeWrapper trait
Browse files Browse the repository at this point in the history
Instead of keeping raw pointer fields (of types like `LLVMValueRef`,
`LLVMMetadataRef`) public and defining constructors with different
names, provide the `LLVMTypeWrapper` trait with `from_ptr()` and
`as_ptr()` methods.

This will allow to convert all safe wrappers from and to raw pointers
with one method, which is going to be helpful for building macros for
them.
  • Loading branch information
vadorovsky committed Nov 27, 2024
1 parent ccf6a2d commit 3f77c07
Show file tree
Hide file tree
Showing 6 changed files with 300 additions and 157 deletions.
8 changes: 6 additions & 2 deletions src/linker.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ use llvm_sys::{
use thiserror::Error;
use tracing::{debug, error, info, warn};

use crate::llvm;
use crate::llvm::{self, types::LLVMTypeError};

/// Linker error
#[derive(Debug, Error)]
Expand Down Expand Up @@ -77,6 +77,10 @@ pub enum LinkerError {
/// The input object file does not have embedded bitcode.
#[error("no bitcode section found in {0}")]
MissingBitcodeSection(PathBuf),

/// Interaction with an LLVM type failed.
#[error(transparent)]
LLVMType(#[from] LLVMTypeError),
}

/// BPF Cpu type
Expand Down Expand Up @@ -452,7 +456,7 @@ impl Linker {

if self.options.btf {
// if we want to emit BTF, we need to sanitize the debug information
llvm::DISanitizer::new(self.context, self.module).run(&self.options.export_symbols);
llvm::DISanitizer::new(self.context, self.module).run(&self.options.export_symbols)?;
} else {
// if we don't need BTF emission, we can strip DI
let ok = unsafe { llvm::strip_debug_info(self.module) };
Expand Down
38 changes: 24 additions & 14 deletions src/llvm/di.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,11 +10,14 @@ use gimli::{DW_TAG_pointer_type, DW_TAG_structure_type, DW_TAG_variant_part};
use llvm_sys::{core::*, debuginfo::*, prelude::*};
use tracing::{span, trace, warn, Level};

use super::types::{
di::DIType,
ir::{Function, MDNode, Metadata, Value},
use crate::llvm::{
iter::*,
types::{
di::{DISubprogram, DIType},
ir::{Function, MDNode, Metadata, Value},
LLVMTypeError, LLVMTypeWrapper,
},
};
use crate::llvm::{iter::*, types::di::DISubprogram};

// KSYM_NAME_LEN from linux kernel intentionally set
// to lower value found accross kernel versions to ensure
Expand Down Expand Up @@ -227,7 +230,7 @@ impl DISanitizer {
// An operand with no value is valid and means that the operand is
// not set
(v, Item::Operand { .. }) if v.is_null() => return,
(v, _) if !v.is_null() => Value::new(v),
(v, _) if !v.is_null() => Value::from_ptr(v).unwrap(),
// All other items should have values
(_, item) => panic!("{item:?} has no value"),
};
Expand Down Expand Up @@ -283,10 +286,13 @@ impl DISanitizer {
}
}

pub fn run(mut self, exported_symbols: &HashSet<Cow<'static, str>>) {
pub fn run(
mut self,
exported_symbols: &HashSet<Cow<'static, str>>,
) -> Result<(), LLVMTypeError> {
let module = self.module;

self.replace_operands = self.fix_subprogram_linkage(exported_symbols);
self.replace_operands = self.fix_subprogram_linkage(exported_symbols)?;

for value in module.globals_iter() {
self.visit_item(Item::GlobalVariable(value));
Expand All @@ -307,6 +313,8 @@ impl DISanitizer {
}

unsafe { LLVMDisposeDIBuilder(self.builder) };

Ok(())
}

// Make it so that only exported symbols (programs marked as #[no_mangle]) get BTF
Expand All @@ -325,14 +333,16 @@ impl DISanitizer {
fn fix_subprogram_linkage(
&mut self,
export_symbols: &HashSet<Cow<'static, str>>,
) -> HashMap<u64, LLVMMetadataRef> {
) -> Result<HashMap<u64, LLVMMetadataRef>, LLVMTypeError> {
let mut replace = HashMap::new();

for mut function in self
for function in self
.module
.functions_iter()
.map(|value| unsafe { Function::from_value_ref(value) })
.map(|value| Function::from_ptr(value))
{
let mut function = function?;

if export_symbols.contains(function.name()) {
continue;
}
Expand Down Expand Up @@ -370,7 +380,7 @@ impl DISanitizer {
// replace retained nodes manually below.
LLVMDIBuilderFinalizeSubprogram(self.builder, new_program);

DISubprogram::from_value_ref(LLVMMetadataAsValue(self.context, new_program))
DISubprogram::from_ptr(LLVMMetadataAsValue(self.context, new_program))?
};

// Point the function to the new subprogram.
Expand All @@ -396,13 +406,13 @@ impl DISanitizer {
unsafe { LLVMMDNodeInContext2(self.context, core::ptr::null_mut(), 0) };
subprogram.set_retained_nodes(empty_node);

let ret = replace.insert(subprogram.value_ref as u64, unsafe {
LLVMValueAsMetadata(new_program.value_ref)
let ret = replace.insert(subprogram.as_ptr() as u64, unsafe {
LLVMValueAsMetadata(new_program.as_ptr())
});
assert!(ret.is_none());
}

replace
Ok(replace)
}
}

Expand Down
2 changes: 1 addition & 1 deletion src/llvm/mod.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
mod di;
mod iter;
mod types;
pub mod types;

use std::{
borrow::Cow,
Expand Down
Loading

0 comments on commit 3f77c07

Please sign in to comment.