BitFlip.py 22.3 KB
Newer Older
German Leon's avatar
German Leon committed
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
import random
import sys

import gdb
import re
import common_functions as cf  # All common functions will be at common_functions module
import common_parameters as cp  # All common parameters will be at common_parameters module

# from collections import deque

"""
BitFlip class
to implement the bit flip process.
The methods in this class will execute only inside a CUDA kernel
"""


class BitFlip:
    def __init__(self, **kwargs):
        # If kernel is not accessible it must return
        self.__bits_to_flip = kwargs.get('bits_to_flip')
        self.__fault_model = kwargs.get('fault_model')
        self.__logging = kwargs.get('logging')
        self.__injection_site = kwargs.get('injection_site')
German Leon's avatar
German Leon committed
25
        self.__maxregs=int(kwargs.get('max_regs'))
German Leon's avatar
German Leon committed
26
        self.fault_injected = False
German Leon's avatar
German Leon committed
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
        
    @staticmethod         
    def principiokernel(kernel):
       #Obtiene la direccion de comienzo de un kernel dado
       try:
         l=cf.execute_command(gdb=gdb, to_execute="print {}".format(kernel))
         inicio=l[0].split("}")[1].split("<")[0]
         return inicio
       except:
         l=BitFlip.principio2kernel(kernel)
         inicio=l.split(":")[0].split("<")[0]
         return inicio
    @staticmethod         
    def principio2kernel(kernel):
         #Obtiene la direccion de comienzo de un kernel dado de una forma mas lenta y mas segura
         l=BitFlip.disas(kernel)
         return(l[1])    
    @staticmethod         
    def lenkernel(kernel):
         #Obtiene la longitud (numero de instruccion) de un kernel
         l=BitFlip.disas(kernel)
         i= len(l) - 2
         while  ("NOP" in l[i]):
             i=i-1   
         fin=(l[i].split("<")[1])
         fin=(fin.split(">")[0])#.split("+")[1]
         return fin     
   
    @staticmethod
    def address_random(d):
      # Proporciona una direccion aleatorio, para realizar un breakpoint
      # De la informacion que tiene de los nkernel Principio y Tamano
      
      ky=random.choice(list(d.keys()))
      dir=random.randint(0, (d[ky]['Tamano']/16)-1)
      dir=d[ky]['Principio']+(dir*16)
      return (" *{} ".format(hex(dir)))  
    def readtraza(self,file):
       self.__traza=cf.load_config_file(file)
    def read_data_kernels(self,readtrace):
      #Leer la informacion de los kernels a trabajar
      conf =cf.load_config_file("tmpxxx/kernels.conf")
      lista= conf.get('Kernels', 'Nombres')
      if readtrace:
         self.readtraza(conf.get('DEFAULT',trace))
      datoskernels={}
      for i in lista.split(","):
        elem={}
        elem['Principio']=int(conf.get(i,'Principio'),16)
        #elem['Principio']=int(BitFlip.principiokernel(i),16)
        elem['Tamano']=int(conf.get(i,'Tamano'))
        datoskernels[i]=elem
      return datoskernels
    @staticmethod
    def update_data_kernels(dict):
      #Rellenar un diccionario con la direccion de comienzo.
      for i in dict:  
        dict[i]['Principio']=int(BitFlip.principiokernel(i),16)
German Leon's avatar
German Leon committed
85
86
87
88
89

    @staticmethod
    def __exception_str():
        exc_type, exc_obj, exc_tb = sys.exc_info()
        return "Exception type {} at line {}".format(exc_type, exc_tb.tb_lineno)
90
    @staticmethod
German Leon's avatar
German Leon committed
91
92
    def disas(kernel):
      #Desensamblando de un kernel 
93
94
      try:
        disassemble_array = cf.execute_command(gdb=gdb, to_execute="disassemble {}".format(kernel))
German Leon's avatar
German Leon committed
95
        
96
      except:
German Leon's avatar
German Leon committed
97
        #si no ha funcionado la forma general, es que solo habra uno y es el que es el activo.
98
        disassemble_array = cf.execute_command(gdb=gdb, to_execute="disassemble")
German Leon's avatar
German Leon committed
99
100
101
102
103
      return disassemble_array
    @staticmethod
    def numreg (kernel):
      #Calculo del numero de registro usados en un kernel 
      disassemble_array=BitFlip.disas(kernel)
104
105
106
107
108
      listareg=set()
      listaregdst=set()
      listaregcond=set()
      for i in range(0, len(disassemble_array) - 1):
        line = disassemble_array[i]
German Leon's avatar
German Leon committed
109
        #m=re.match(r".*:\t(\S+) .*",line)#Para que es m
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
        todacadena="ASSM_LINE:{}".format(line)
        lista=re.findall(r"R(\d+)", line)
        if (len(lista) > 0):   	
           listareg.update(lista)
        lista=re.findall(r" P(\d+)", line)
        if (len(lista) > 0): 
           listaregcond.update(lista)

      print ("Registros Visibles ({})".format(len(listareg)))
      print (listareg)
      print ("Registros destino ({})".format(len(listaregdst)))
      print (listaregdst)
      print ("Registros condicionales ({})".format(len(listaregcond)))
      print (listaregcond)
      return (listareg)
German Leon's avatar
German Leon committed
125
126
127
    """
    TODO: Describe the method
    """
German Leon's avatar
German Leon committed
128
129
130
131
132
133
134
135
136
137
138
139
140
    @staticmethod
    def kernelnow():
      #Obtiene el kernel enfocado,
      str=gdb.execute(" info cuda kernels",to_string=True)
      str=str.splitlines()
      index=str[0].find("Invocation")
      for i in range(1, len(str) ):
          if "* " in str[i] :
             ret=(str[i][index:]).split("(")[0]
      return ret     
      
 

German Leon's avatar
German Leon committed
141
    def asmline(self):
German Leon's avatar
German Leon committed
142
      #Leo la instruccion en ensamblador a ejecutar.
German Leon's avatar
German Leon committed
143
144
145
146
      linea=cf.execute_command(gdb=gdb, to_execute="x/1i $pc")
      self.__logging.info("ASSM_LINE:{}".format(linea[0]))
      return linea
      
German Leon's avatar
German Leon committed
147
148
149
150
151
152
153
    
    def asmline2(self):
      #Difiere de asmline donde visualiza la informacion
      linea=cf.execute_command(gdb=gdb, to_execute="x/1i $pc")
      print("ASSM_LINE:{}".format(linea[0]))
      return linea

German Leon's avatar
German Leon committed
154
    def reg_asmline( self):
German Leon's avatar
German Leon committed
155
      #Obtengo los registros de la instruccion a ejecutar y los devuelvo una lista
German Leon's avatar
German Leon committed
156
157
158
159
160
      linea= self.asmline()
      lista=re.findall(r"R(\d+)", linea[0])
      setlista=set()
      setlista.update(lista)
      return setlista
German Leon's avatar
German Leon committed
161
    def LoadValuesRegsInst(self):  
German Leon's avatar
German Leon committed
162
163
164
165
166
167
      lista=self.reg_asmline()
      listareg=[" R{} ".format(x) for x in lista]
      strlistareg="info registers " 
      for x in listareg:
        strlistareg+=x;
      self.__stringregs=strlistareg
German Leon's avatar
German Leon committed
168
169
170
171
172
173
174
175
176
177
178
    def ValueRegsInst (self):
       valores= cf.execute_command(gdb=gdb, to_execute=self.__stringregs)
       return valores
      
    def regmod (self):
      lista=self.reg_asmline()
      while len(lista) == 0: #Habria que poner un limite. 
        #Busco una instruccion que referiencia algun registro 
        self.__logging.info("INSTRUCTION WITHOUT DESTINATION REGISTER")              
        self.nextinstr()
      self.LoadValuesRegsInst()
German Leon's avatar
German Leon committed
179
      #Obtengo el valor de los registro referenciados
German Leon's avatar
German Leon committed
180
      return self.ValueRegsInst()
German Leon's avatar
German Leon committed
181
    def nextinstr(self):
German Leon's avatar
German Leon committed
182
183
184
         
          x=cf.execute_command(gdb=gdb, to_execute="nexti") 
         
German Leon's avatar
German Leon committed
185
    def dictreg(self,valores):
German Leon's avatar
German Leon committed
186
187
      
      #Almaceno en un dictionario los valores de los registros obtenido de un info registers
German Leon's avatar
German Leon committed
188
189
190
191
192
      regs={}
      for x in valores:
        m = re.match(r".*R(\d+).*0x([0-9a-fA-F]+).*", x)
        if m:
          regs[m.group(1)]=m.group(2)
German Leon's avatar
German Leon committed
193
        
German Leon's avatar
German Leon committed
194
195
      return regs    
    def cmpregdst (self,valores,regs):
German Leon's avatar
German Leon committed
196
197
     regdst=set()
     for x in valores:
German Leon's avatar
German Leon committed
198
199
200
201
202
203
        m = re.match(r".*R(\d+).*0x([0-9a-fA-F]+).*", x)
        if m:
          #print("El registro {} tiene {} y tenia{}".format(m.group(1),m.group(2),regs[m.group(1)]))
          if (regs[m.group(1)]!=m.group(2)):
            #print("Diferente")
            regdst.add(m.group(1))  
German Leon's avatar
German Leon committed
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
     return regdst
    def mypcis(self):
        #Obtiene el pc relativo
        valores= cf.execute_command(gdb=gdb, to_execute="info registers pc")
        pc=int((valores[0].split("+")[1]).split(">")[0])       
        return pc
    def RegDstInst(self,despl):
        #Obtiene registro destino de la instruccion -despl
        linea=cf.execute_command(gdb=gdb, to_execute="x/1i $pc-"+str(despl))
        rd=re.findall(r"R(\d+)",linea[0])
        if (len(rd) >0):
           rd=rd [0]
        return  rd
    def isfininstruction(self):
        linea=cf.execute_command(gdb=gdb, to_execute="x/1i $pc")
        lista=linea[0].find("EXIT")
        return (lista!=-1)
    def regdst(self):
        #Regsitro modificados en la ejecuccion de una instrucciones. varios si no hace referencia
        # a ningun registro.
German Leon's avatar
German Leon committed
224
        regs=self.dictreg(self.regmod())
German Leon's avatar
German Leon committed
225
226
227
        self.nextinstr()
        self.LoadValuesRegsInst()
        valores=self.ValueRegsInst()
German Leon's avatar
German Leon committed
228
        r=self.cmpregdst(valores,regs)
German Leon's avatar
German Leon committed
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
        self.__logging.info ("Registros Modificados: {}".format(r))
    def CalculateRegDestInst(self,despl):
       r=self.RegDstInst(despl)  
       if cp.HIGHPRECISION:
          if (len(r)>0):
             print ("=========HP+++++++++++++================")
             valores=self.ValueRegsInst()
             print ("Valores:...{}".format(valores))
             r=self.cmpregdst(valores,self.__regs)
             
             if (len(r)>0):
                r=r.pop()
                print ("Registros modificados:...{}".format(r))
             self.__regs=self.dictreg(valores)
             print ("Regs:...{}".format(self.__regs))
    
           
       return r  
          
    def analisis(self,kernels):
      gdb.execute("set cuda break_on_launch none")
      for kernel in kernels:
        self.asmline2()
        #self.__logging.raw("Kernel {}".format(kernel))
        #gdb.execute()
        gdb.execute("delete breakpoints")
        str=gdb.execute("break "+kernel,to_string=True)
        #self.__logging.raw("====".format(str))
        gdb.execute("c")
        self.asmline2()
        self.__logging.raw("["+kernel+"]\n")
        pcold=0

        dict={}
        fin=self.isfininstruction()
        rold=self.RegDstInst(0) 
        print("Rold={}".format(rold))
        pcold=self.mypcis()
        self.LoadValuesRegsInst()
        self.__regs=self.dictreg(self.ValueRegsInst())
        print ("Regs:...{}".format(self.__regs))
        self.nextinstr()
        #Y si la primera instruccion no tiene argumentos?
        i=0
        while not fin:
         # regs=self.dictreg(self.regmod()) # Igual solo tendriamos que mirar el regfdst de la instruccion      
         # r=self.cmpregdst(valores,regs)
          pc=self.mypcis()
          print("====")
          self.asmline2()
          #r=self.RegDstInst(16) #
          r=self.CalculateRegDestInst(16)
          if (pc!=pcold+16) or (len(r)==0) :
              if not (pc in dict):
                 print("Rold={}".format(rold))
                 a={rold:1}
                 dict[pc]={rold:1}
              else: 
                 if not (rold in dict[pc] ):
                     (dict[pc]) [rold]=1
                 else:
                     a=(dict[pc])[rold]
                     (dict[pc]) [rold]=a+1  
              print ("++++Instruccion cuyo pc {} tiene estos valores {}".format(pc,dict[pc]))          
              if (pc!=pcold+16):     
                print ("++++Ruptura de secuencia desde {}".format(pcold)) 
              else:
                print("++++Sin operandos la instruccion anterior")
          else:           
              rold=r
              print("Registro {}".format(r))
          pcold=pc   
          self.nextinstr()
          
          fin= self.isfininstruction()
          
          
          
          i=i+1
         
        for k in dict:
           print("Clave: {} {} ".format(k,type(k)))
           #cad= str(key)+ "="
        for key in dict:   
      
           cad="{} =".format(key)
           sep=" "
           for key2 in dict[key]:
             #cad=cad+sep+str(key2)+ "x"+str(( dict[key]) [key2])
             cad="{}{}{}x{}".format(cad,sep,key2,(dict[key]) [key2])
             sep=","
           self.__logging.raw(cad+"\n")  
      

German Leon's avatar
German Leon committed
323
       
German Leon's avatar
German Leon committed
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
    def LastRegDest(self):
        #Obtiene el ultimo registro destino modificado, se consulta la traza
        # si el pc no esta en la traza, es que la anterior instruccion indica
        # el ultimo registro destino.
        kernel=self.kernelnow()
        pc=str(self.mypcis())
        traza=self.__traza
        self.__logging.info("kernel {} pc {} pcespeciales{} \n".format(kernel,pc,traza.options(kernel)))
        
        if (pc in traza.options(kernel)):
          self.__logging.info("Si es especial {}".format(traza.get(kernel,pc)))
          a= (traza.get(kernel,pc)).split(",")
          ac=0
          self.__logging.info(" Valor {}".format(a))
          for x in a:
            ac=ac+int(x.split("x")[1])
          self.__logging.info("Total {}".format(ac))  
          rd=0
          iac=(random.randint(0, ac-1))
          self.__logging.info("Elegido {}".format(iac))  
          for x in a:
            t=x.split("x")
            if (int(t[1]) >=iac):
                   rd=t[0]
                   break
            else:
               iac=iac-int(t[1])            
          #print("Registro Destino es {}".format(rd))
        else:          
         rd=self.RegDstInst(16)
         self.__logging.info("Es normal {}".format(rd))
        self.__logging.info("Registro es {}".format(rd)) 
        return rd    
    def  __inst_generic_injector(self):
  
        r=self.regdst()    
German Leon's avatar
German Leon committed
360
361
362
        while (len(r) ==0):
             self.__logging.info("INSTRUCTION WITHOUT OPERANDS")
             gdb.execute("nexti")
German Leon's avatar
German Leon committed
363
364
             r=self.regdst()
             
German Leon's avatar
German Leon committed
365
366
367
                    
        self.__register="R{}".format(r.pop())
        self.__logging.info("SELECTED_REGISTER:{}".format(self.__register))
German Leon's avatar
German Leon committed
368
        
German Leon's avatar
German Leon committed
369
370
371
372
        
                # __rf_generic_injector will set fault_injected attribute
        self.__rf_generic_injector()
     
German Leon's avatar
German Leon committed
373
374
375
376
377
378
379
380
381
    def single_event(self):
        # fault_injected attribute will be set by the methods that perform fault injection
        # Focusing the thread. If focus succeed, otherwise not
        if self.__thread_focus():
            # Do the fault injection magic

            # Register File mode
            if cp.RF == self.__injection_site:
                # Select the register before the injection
German Leon's avatar
German Leon committed
382
                #self.__logging.info("select-register")
German Leon's avatar
German Leon committed
383
384
                self.__select_register()
                # RF is the default mode of injection
German Leon's avatar
German Leon committed
385
                #self.__logging.info("rf-genera")
German Leon's avatar
German Leon committed
386
                self.__rf_generic_injector()
German Leon's avatar
German Leon committed
387
                #self.__logging.info("rf-genera-fin")
German Leon's avatar
German Leon committed
388
389
            # Instruction Output mode
            elif cp.INST_OUT == self.__injection_site:
German Leon's avatar
German Leon committed
390
391
392
393
394
               self.__inst_generic_injector()()
            elif cp.INST_OUT_ORI == self.__injection_site:
               self.__inst_generic_injector_old()
            elif cp.INST_V1 == self.__injection_site:   
                self.__inst_generic_injector_preliminar()
German Leon's avatar
German Leon committed
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
            # Instruction Address mode
            elif cp.INST_ADD == self.__injection_site:
                self.__logging.exception("INST_ADD NOT IMPLEMENTED YET")
                self.__logging.exception(self.__exception_str())
                self.fault_injected = False

            # Test fault injection result
            self.__logging.info("Fault Injection " + ("Successful" if self.fault_injected else "Went Wrong"))

    """
    Selects a valid thread for a specific
    kernel
    return the coordinates for the block
    and the thread
    """

    def __thread_focus(self):
        try:
            # Selecting the block, it must be a valid block
            blocks = cf.execute_command(gdb=gdb, to_execute="info cuda blocks")
            # empty lists are always false
            while blocks:
                chosen_block = random.choice(blocks)
                # remove it from the options
                blocks.remove(chosen_block)

                m = re.match(r".*\(.*\).*\((\d+),(\d+),(\d+)\).*", chosen_block)
                # Try to focus
                if m:
                    change_focus_block_cmd = "cuda block {},{},{}".format(m.group(1), m.group(2), m.group(3))
                    block_focus = cf.execute_command(gdb=gdb, to_execute=change_focus_block_cmd)
                    # empty lists are always false
                    if block_focus:
                        # Thread focus return information
                        self.__logging.info("CUDA_BLOCK_FOCUS:{}".format(block_focus))
                        # No need to continue to seek
                        break

            # Selecting the thread
            threads = cf.execute_command(gdb=gdb, to_execute="info cuda threads")
            while threads:
                chosen_thread = random.choice(threads)
                # remove it from the options
                threads.remove(chosen_thread)

                m = re.match(r".*\(.*\).*\(.*\).*\(.*\).*\((\d+),(\d+),(\d+)\).*", chosen_thread)
                # Try to focus
                if m:
                    change_focus_thread_cmd = "cuda thread {},{},{}".format(m.group(1), m.group(2), m.group(3))
                    thread_focus = cf.execute_command(gdb=gdb, to_execute=change_focus_thread_cmd)

                    # empty lists are always false
                    if thread_focus:
                        # Thread focus return information
                        self.__logging.info("CUDA_THREAD_FOCUS:{}".format(thread_focus))
                        # No need to continue to seek
                        break

        except Exception as err:
            err_str = str(err)
            self.__logging.exception("CUDA_FOCUS_CANNOT_BE_REQUESTED, ERROR:" + err_str)

            # No need to continue if no active kernel
            if err_str == cp.FOCUS_ERROR_STRING:
                return False

        # If we are inside the kernel return true
        return True

    """
    Flip a bit or multiple bits based on a fault model
    """

    def __rf_generic_injector(self):
        try:
            # get register content
German Leon's avatar
German Leon committed
471
            self.asmline()
German Leon's avatar
German Leon committed
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
            reg_cmd = cf.execute_command(gdb, "p/t ${}".format(self.__register))
            m = re.match(r'\$(\d+)[ ]*=[ ]*(\S+).*', reg_cmd[0])

            reg_content_old = str(m.group(2))
            # Make sure that binary value will have max size register
            reg_content_full_bits = str(
                '0' * (cp.SINGLE_MAX_SIZE_REGISTER - len(reg_content_old))) + reg_content_old

            reg_content_new = ''

            # Single or double bit flip or Least significant bits
            if self.__fault_model in [cp.FLIP_SINGLE_BIT, cp.FLIP_TWO_BITS, cp.LEAST_16_BITS, cp.LEAST_8_BITS]:
                # single bit flip or Double bit flip
                reg_content_new = reg_content_full_bits
                for bit_to_flip in self.__bits_to_flip:
                    reg_content_new = self.__flip_a_bit(int(bit_to_flip), reg_content_new)
                reg_content_new = hex(int(reg_content_new, 2))

            # Random value or Zero value
            elif self.__fault_model == cp.RANDOM_VALUE or self.__fault_model == cp.ZERO_VALUE:
                # random value is stored at bits_to_flip[0]
                reg_content_new = self.__bits_to_flip[0]

            # send the new value to gdb
            flip_command = "set ${} = {}".format(self.__register, reg_content_new)
            reg_cmd_flipped = cf.execute_command(gdb, flip_command)

            # ['$2 = 100000000111111111111111']
            modify_output = cf.execute_command(gdb, "p/t ${}".format(self.__register))[0]

            # With string split it is easier to crash
            reg_modified = re.match(r"(.*)=(.*)", modify_output).group(2).strip()

            # Return the fault confirmation
            self.fault_injected = reg_content_old != reg_modified

            # Log the register only if the fault was injected, reduce unnecessary file write
            if self.fault_injected:
                # LOGGING
                self.__logging.info("SELECTED_REGISTER:{}".format(self.__register))
                # Logging info result extracted from register
                self.__logging.info("old_value:{}".format(reg_content_old))
                # Also logging the new value
                self.__logging.info("new_value:{}".format(reg_modified))

                # Log if something was printed
                # empty list is always false
                if reg_cmd_flipped:
                    self.__logging.info("flip command return:{}".format(reg_cmd_flipped))

        except Exception as err:
            self.__logging.exception("fault_injection_python_exception: {}".format(err))
            self.__logging.exception(self.__exception_str())
            self.fault_injected = False

    """
    Flip only a bit in a register content
    """

    @staticmethod
    def __flip_a_bit(bit_to_flip, reg_content):
        return reg_content[:bit_to_flip] + ('0' if reg_content[bit_to_flip] == '1' else '1') + reg_content[
                                                                                               bit_to_flip + 1:]

    """
    Runtime select register
    """

    def __select_register(self):
        # Start on 1 to consider R0
leon@uji.es's avatar
leon@uji.es committed
542
        #max_num_register = 
German Leon's avatar
German Leon committed
543
        # registers_list.popleft()
leon@uji.es's avatar
leon@uji.es committed
544
545
546
547
        #registers_list = cf.execute_command(gdb=gdb, to_execute="info registers")
        #for line in registers_list:
        #    m = re.match(r".*R.*0x([0-9a-fA-F]+).*", line)
        #    if m and m.group(1) != '0':
German Leon's avatar
German Leon committed
548
                #self.__logging.info ("LIne salida:{}".format(m.group(1))
leon@uji.es's avatar
leon@uji.es committed
549
        #         max_num_register += 1
German Leon's avatar
German Leon committed
550
                #self.__logging.info("LIne entrada {}--max{}".format(line,max_num_register))
German Leon's avatar
German Leon committed
551
552
553
        #self.__logging.info("MAX_NUM_REGISTER:{}".format(self.__maxregs))        
        self.__register = "R{}".format(random.randint(0, (self.__maxregs)-1))
       
German Leon's avatar
German Leon committed
554
555
556
    """
    Instruction injector    
    """
German Leon's avatar
German Leon committed
557
558
559
560
    def __inst_generic_injector_preliminar(self):
        self.__register="R{}".format(self.LastRegDest())
        self.__logging.info("SELECTED_REGISTER:{}".format(self.__register))
        self.__rf_generic_injector()
German Leon's avatar
German Leon committed
561
    def __inst_generic_injector_old(self):
German Leon's avatar
German Leon committed
562
563
564
565
        disassemble_array = cf.execute_command(gdb=gdb, to_execute="disassemble")
        # Search the line to inject
        # -1 will use the next instruction after program counter
        for i in range(0, len(disassemble_array) - 1):
German Leon's avatar
German Leon committed
566
            next_line = disassemble_array[i] # He modifico i+1 por i
German Leon's avatar
German Leon committed
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583

            # => defines where the program counter is
            # There is an instruction on this line
            # then inject in the output register
            if "=>" in disassemble_array[i] and re.match(r".*:\t(\S+) .*", next_line):
                # If it gets the PC + 1 then I must inject in the input of the next instruction
                # Which is the most right register (-1 index)
                self.__register = "R{}".format(re.findall(r"R(\d+)", next_line)[-1])
                self.__logging.info("SELECTED_REGISTER:{}".format(self.__register))
                self.__logging.info("ASSM_LINE:{}".format(next_line))

                # __rf_generic_injector will set fault_injected attribute
                self.__rf_generic_injector()
                break  # avoid execute the else
        else:
            self.__logging.exception("SEARCH_FOR_PC_INDICATOR_FAILED")
            self.fault_injected = False