| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108 |
- use sbpf_assembler::ast::AST;
- use sbpf_assembler::astnode::{ASTNode, ROData};
- use sbpf_assembler::instruction::Instruction;
- use sbpf_assembler::lexer::{ImmediateValue, Token};
- use sbpf_assembler::opcode::Opcode;
- use sbpf_assembler::parser::ParseResult;
- use object::RelocationTarget::Symbol;
- use object::{File, Object, ObjectSection, ObjectSymbol};
- use std::collections::HashMap;
- use crate::SbpfLinkerError;
- pub fn parse_bytecode(bytes: &[u8]) -> Result<ParseResult, SbpfLinkerError> {
- let mut ast = AST::new();
- let obj = File::parse(bytes)?;
- let mut rodata_table = HashMap::new();
- if let Some(ro_section) = obj.section_by_name(".rodata") {
- // only handle symbols in the .rodata section for now
- 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.set_rodata_size(rodata_offset);
- }
- for section in obj.sections() {
- if section.name() == Ok(".text") {
- // parse text section and build instruction nodes
- // lddw takes 16 bytes, other instructions take 8 bytes
- let mut offset = 0;
- while offset < section.data().unwrap().len() {
- let node_len = match Opcode::from_u8(section.data().unwrap()[offset]) {
- Some(Opcode::Lddw) => 16,
- _ => 8,
- };
- let node = §ion.data().unwrap()[offset..offset + node_len];
- ast.nodes.push(ASTNode::Instruction {
- instruction: Instruction::from_bytes(node).unwrap(),
- offset: offset as u64,
- });
- offset += node_len;
- }
- 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()) {
- 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)
- .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).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());
- }
- }
- ast.build_program()
- .map_err(|errors| SbpfLinkerError::BuildProgramError { errors })
- }
|