2020
2121class OTBNProgram :
2222 def __init__ (self , symbols : Dict [str , int ], insns : Dict [int , int ],
23- data : Dict [int , int ]):
23+ data : Dict [int , int ], nop_subfuncs : List [ str ] ):
2424 self .symbols = symbols # label -> PC
25- self .data = data # addr -> data (32b word)
25+ self .data = data # addr -> data (32b word)
26+
27+ # Get start PCs for function symbols that we want to ignore
28+ nop_starts = [symbols [name ] for name in nop_subfuncs if name in symbols ]
29+ nop_ranges = []
30+
31+ # Build NOP ranges by scanning until JALR
32+ for start_pc in nop_starts :
33+ pc = start_pc
34+ while pc in insns :
35+ opcode = insns [pc ]
36+ mnem = INSNS_FILE .mnem_for_word (opcode )
37+ if mnem is None :
38+ raise ValueError (f"Invalid instruction at PC { pc :#x} " )
39+ insn = INSNS_FILE .mnemonic_to_insn [mnem ]
40+
41+ # Stop after at the JALR instruction
42+ if mnem == "jalr" :
43+ nop_ranges .append ((start_pc , pc ))
44+ break
45+
46+ pc += 4
47+ else :
48+ # In case we never find a ret
49+ raise RuntimeError (
50+ f"Did not find 'JALR' for function starting at { start_pc :#x} "
51+ )
2652
2753 self .insns = {}
2854 for pc , opcode in insns .items ():
29- mnem = INSNS_FILE .mnem_for_word (opcode )
30- if mnem is None :
31- raise ValueError (
32- 'No legal decoding for mnemonic: {}' .format (mnem ))
33- insn = INSNS_FILE .mnemonic_to_insn [mnem ]
34- assert insn .encoding is not None
35- enc_vals = insn .encoding .extract_operands (opcode )
55+ # Check if PC lies within one of the NOP ranges
56+ in_nop_region = any (
57+ start <= pc < end for start , end in nop_ranges
58+ )
59+
60+ if in_nop_region :
61+ # Replace instruction that belong to a ignored routine with a NOP
62+ insn = INSNS_FILE .mnemonic_to_insn ["addi" ]
63+ enc_vals = {'imm' : 0 , 'grs1' : 0 , 'grd' : 0 }
64+ else :
65+ # Normal decode
66+ mnem = INSNS_FILE .mnem_for_word (opcode )
67+ if mnem is None :
68+ raise ValueError (
69+ 'No legal decoding for mnemonic: {}' .format (mnem ))
70+ insn = INSNS_FILE .mnemonic_to_insn [mnem ]
71+ assert insn .encoding is not None
72+ enc_vals = insn .encoding .extract_operands (opcode )
73+
3674 op_vals = insn .enc_vals_to_op_vals (pc , enc_vals )
3775 self .insns [pc ] = (insn , op_vals )
3876
@@ -69,7 +107,7 @@ def _decode_mem(base_addr: int, data: bytes) -> Dict[int, int]:
69107 for offset , int_val in enumerate (struct .iter_unpack ('<I' , data ))}
70108
71109
72- def decode_elf (path : str ) -> OTBNProgram :
110+ def decode_elf (path : str , nop_subfuncs : List [ str ] ) -> OTBNProgram :
73111 '''Read ELF file at path and decode contents into an OTBNProgram instance
74112
75113 Returns the OTBNProgram instance representing the program in the ELF file.
@@ -79,4 +117,4 @@ def decode_elf(path: str) -> OTBNProgram:
79117 insns = _decode_mem (0 , imem_bytes )
80118 data = _decode_mem (0 , dmem_bytes )
81119
82- return OTBNProgram (symbols , insns , data )
120+ return OTBNProgram (symbols , insns , data , nop_subfuncs )
0 commit comments