byteparser.rs 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108
  1. use sbpf_assembler::ast::AST;
  2. use sbpf_assembler::astnode::{ASTNode, ROData};
  3. use sbpf_assembler::instruction::Instruction;
  4. use sbpf_assembler::lexer::{ImmediateValue, Token};
  5. use sbpf_assembler::opcode::Opcode;
  6. use sbpf_assembler::parser::ParseResult;
  7. use object::RelocationTarget::Symbol;
  8. use object::{File, Object, ObjectSection, ObjectSymbol};
  9. use std::collections::HashMap;
  10. use crate::SbpfLinkerError;
  11. pub fn parse_bytecode(bytes: &[u8]) -> Result<ParseResult, SbpfLinkerError> {
  12. let mut ast = AST::new();
  13. let obj = File::parse(bytes)?;
  14. let mut rodata_table = HashMap::new();
  15. if let Some(ro_section) = obj.section_by_name(".rodata") {
  16. // only handle symbols in the .rodata section for now
  17. let mut rodata_offset = 0;
  18. for symbol in obj.symbols() {
  19. if symbol.section_index() == Some(ro_section.index()) && symbol.size() > 0 {
  20. let mut bytes = Vec::new();
  21. for i in 0..symbol.size() {
  22. bytes.push(ImmediateValue::Int(
  23. ro_section.data().unwrap()[(symbol.address() + i) as usize] as i64,
  24. ));
  25. }
  26. ast.rodata_nodes.push(ASTNode::ROData {
  27. rodata: ROData {
  28. name: symbol.name().unwrap().to_string(),
  29. args: vec![
  30. Token::Directive(String::from("byte"), 0..1), //
  31. Token::VectorLiteral(bytes.clone(), 0..1),
  32. ],
  33. span: 0..1,
  34. },
  35. offset: rodata_offset,
  36. });
  37. rodata_table.insert(symbol.address(), symbol.name().unwrap().to_string());
  38. rodata_offset += symbol.size();
  39. }
  40. }
  41. ast.set_rodata_size(rodata_offset);
  42. }
  43. for section in obj.sections() {
  44. if section.name() == Ok(".text") {
  45. // parse text section and build instruction nodes
  46. // lddw takes 16 bytes, other instructions take 8 bytes
  47. let mut offset = 0;
  48. while offset < section.data().unwrap().len() {
  49. let node_len = match Opcode::from_u8(section.data().unwrap()[offset]) {
  50. Some(Opcode::Lddw) => 16,
  51. _ => 8,
  52. };
  53. let node = &section.data().unwrap()[offset..offset + node_len];
  54. ast.nodes.push(ASTNode::Instruction {
  55. instruction: Instruction::from_bytes(node).unwrap(),
  56. offset: offset as u64,
  57. });
  58. offset += node_len;
  59. }
  60. if let Some(ro_section) = obj.section_by_name(".rodata") {
  61. // handle relocations
  62. for rel in section.relocations() {
  63. // only handle relocations for symbols in the .rodata section for now
  64. let symbol = match rel.1.target() {
  65. Symbol(sym) => Some(obj.symbol_by_index(sym).unwrap()),
  66. _ => None,
  67. };
  68. println!("Symbol: {:?}", symbol);
  69. if symbol.unwrap().section_index() == Some(ro_section.index()) {
  70. println!("Relocation found");
  71. // addend is not explicit in the relocation entry, but implicitly encoded
  72. // as the immediate value of the instruction
  73. let addend = match ast
  74. .get_instruction_at_offset(rel.0)
  75. .unwrap()
  76. .operands
  77. .last()
  78. .unwrap()
  79. .clone()
  80. {
  81. Token::ImmediateValue(ImmediateValue::Int(val), _) => val,
  82. _ => 0,
  83. };
  84. // Replace the immediate value with the rodata label
  85. let ro_label = rodata_table.get(&(addend as u64)).unwrap();
  86. let ro_label_name = ro_label.clone();
  87. let node: &mut Instruction = ast.get_instruction_at_offset(rel.0).unwrap();
  88. let last_idx = node.operands.len() - 1;
  89. node.operands[last_idx] = Token::Identifier(ro_label_name, 0..1);
  90. }
  91. }
  92. }
  93. ast.set_text_size(section.size());
  94. }
  95. }
  96. ast.build_program()
  97. .map_err(|errors| SbpfLinkerError::BuildProgramError { errors })
  98. }