Преглед изворни кода

fix: skip symbol parsing when there's no rodata

Claire xyz пре 1 месец
родитељ
комит
afcb54a2c7
4 измењених фајлова са 101 додато и 47 уклоњено
  1. 2 1
      .gitignore
  2. 0 2
      Cargo.lock
  3. 50 0
      src/bin/sbpf-link.rs
  4. 49 44
      src/byteparser.rs

+ 2 - 1
.gitignore

@@ -1,2 +1,3 @@
 /target
-.DS_Store
+.DS_Store
+Cargo.lock

+ 0 - 2
Cargo.lock

@@ -812,8 +812,6 @@ checksum = "28d3b2b1366ec20994f1fd18c3c594f05c5dd4bc44d8bb0c1c632c8d6829481f"
 [[package]]
 name = "sbpf-assembler"
 version = "0.1.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "502758dfa9f547723c407a9781ffb98d731275332a9a78e5a241cf440b50f980"
 dependencies = [
  "anyhow",
  "num-derive",

+ 50 - 0
src/bin/sbpf-link.rs

@@ -0,0 +1,50 @@
+use std::path::{Path, PathBuf};
+use std::fs;
+use clap::Parser;
+use sbpf_linker::link_program;
+
+/// Links an object file by reading it from the given path and processing its bytecode
+fn link_object_file<P: AsRef<Path>>(path: P) -> Result<Vec<u8>, String> {
+    // Read the object file into a byte array
+    let bytes = fs::read(path.as_ref())
+        .map_err(|e| format!("Failed to read object file: {}", e))?;
+    
+    // Call link_program on the bytes
+    link_program(&bytes)
+}
+
+#[derive(Debug, Parser)]
+#[command(
+    name = "sbpf-link",
+    version,
+    about = "Simple SBPF linker that processes object files directly"
+)]
+struct Args {
+    /// Input object file to link
+    #[clap(value_name = "INPUT")]
+    input: PathBuf,
+}
+
+fn main() -> Result<(), Box<dyn std::error::Error>> {
+    let args = Args::parse();
+
+    // Link the object file
+    println!("Linking: {}", args.input.display());
+    let linked_bytecode = link_object_file(&args.input)
+        .map_err(|e| format!("Failed to link object file: {}", e))?;
+
+    // Determine output path in same directory with .so extension
+    let parent = args.input.parent().unwrap_or_else(|| Path::new("."));
+    let stem = args.input.file_stem()
+        .and_then(|s| s.to_str())
+        .unwrap_or("output");
+    let output = parent.join(format!("{}.so", stem));
+
+    // Write the output
+    println!("Writing output to: {}", output.display());
+    std::fs::write(&output, &linked_bytecode)?;
+
+    println!("Successfully linked {} bytes", linked_bytecode.len());
+    Ok(())
+}
+

+ 49 - 44
src/byteparser.rs

@@ -15,32 +15,33 @@ pub fn parse_bytecode(bytes: &[u8]) -> Result<ParseResult, String> {
     let mut ast = AST::new();
 
     let obj = File::parse(bytes).map_err(|e| e.to_string())?;
-
-    // only handle symbols in the .rodata section for now
-    let ro_section = obj.section_by_name(".rodata").unwrap();
     let mut rodata_table = HashMap::new();
-    let mut rodata_offset = 0;
-    for symbol in obj.symbols() {
-        if symbol.section_index() == Some(ro_section.index()) && symbol.size() > 0 {
-            let mut bytes = Vec::new();
-            for i in 0..symbol.size() {
-                bytes.push(ImmediateValue::Int(
-                    ro_section.data().unwrap()[(symbol.address() + i) as usize] as i64));
+    if let Some(ro_section) = obj.section_by_name(".rodata") {
+        // only handle symbols in the .rodata section for now
+        // let ro_section = ro_section.unwrap();
+        let mut rodata_offset = 0;
+        for symbol in obj.symbols() {
+            if symbol.section_index() == Some(ro_section.index()) && symbol.size() > 0 {
+                let mut bytes = Vec::new();
+                for i in 0..symbol.size() {
+                    bytes.push(ImmediateValue::Int(
+                        ro_section.data().unwrap()[(symbol.address() + i) as usize] as i64));
+                }
+                ast.rodata_nodes.push(ASTNode::ROData {
+                    rodata: ROData {
+                        name: symbol.name().unwrap().to_string(),
+                        args: vec![Token::Directive(String::from("byte"), 0..1) //
+                                , Token::VectorLiteral(bytes.clone(), 0..1)],
+                        span: 0..1,
+                    },
+                    offset: rodata_offset,
+                });
+                rodata_table.insert(symbol.address(), symbol.name().unwrap().to_string());
+                rodata_offset += symbol.size();
             }
-            ast.rodata_nodes.push(ASTNode::ROData {
-                rodata: ROData {
-                    name: symbol.name().unwrap().to_string(),
-                    args: vec![Token::Directive(String::from("byte"), 0..1) //
-                            , Token::VectorLiteral(bytes.clone(), 0..1)],
-                    span: 0..1,
-                },
-                offset: rodata_offset,
-            });
-            rodata_table.insert(symbol.address(), symbol.name().unwrap().to_string());
-            rodata_offset += symbol.size();
         }
+        ast.set_rodata_size(rodata_offset);
     }
-    ast.set_rodata_size(rodata_offset);
 
     for section in obj.sections() {
         if section.name() == Ok(".text") {
@@ -60,30 +61,34 @@ pub fn parse_bytecode(bytes: &[u8]) -> Result<ParseResult, String> {
                 offset += node_len;
             }
             
-            // handle relocations
-            for rel in section.relocations() {
-                // only handle relocations for symbols in the .rodata section for now
-                let symbol = match rel.1.target() {
-                    Symbol(sym) => Some(obj.symbol_by_index(sym).unwrap()), 
-                    _ => None
-                };
+            if let Some(ro_section) = obj.section_by_name(".rodata") {
+                // handle relocations
+                for rel in section.relocations() {
+                    // only handle relocations for symbols in the .rodata section for now
+                    let symbol = match rel.1.target() {
+                        Symbol(sym) => Some(obj.symbol_by_index(sym).unwrap()), 
+                        _ => None
+                    };
+                    println!("Symbol: {:?}", symbol);
                 
-                if symbol.unwrap().section_index() == Some(ro_section.index()) {
-                    // addend is not explicit in the relocation entry, but implicitly encoded
-                    // as the immediate value of the instruction
-                    let addend = //
-                        match ast.get_instruction_at_offset(rel.0 as u64).unwrap()
-                            .operands.last().unwrap().clone() {
-                                Token::ImmediateValue(ImmediateValue::Int(val), _) => val,
-                                _ => 0 
-                        };
+                    if symbol.unwrap().section_index() == Some(ro_section.index()) {
+                        println!("Relocation found");
+                        // addend is not explicit in the relocation entry, but implicitly encoded
+                        // as the immediate value of the instruction
+                        let addend = //
+                            match ast.get_instruction_at_offset(rel.0 as u64).unwrap()
+                                .operands.last().unwrap().clone() {
+                                    Token::ImmediateValue(ImmediateValue::Int(val), _) => val,
+                                    _ => 0 
+                            };
 
-                    // Replace the immediate value with the rodata label
-                    let ro_label = rodata_table.get(&(addend as u64)).unwrap();
-                    let ro_label_name = ro_label.clone();
-                    let node: &mut Instruction = ast.get_instruction_at_offset(rel.0 as u64).unwrap();
-                    let last_idx = node.operands.len() - 1;
-                    node.operands[last_idx] = Token::Identifier(ro_label_name, 0..1);
+                        // Replace the immediate value with the rodata label
+                        let ro_label = rodata_table.get(&(addend as u64)).unwrap();
+                        let ro_label_name = ro_label.clone();
+                        let node: &mut Instruction = ast.get_instruction_at_offset(rel.0 as u64).unwrap();
+                        let last_idx = node.operands.len() - 1;
+                        node.operands[last_idx] = Token::Identifier(ro_label_name, 0..1);
+                    }
                 }
             }
             ast.set_text_size(section.size());