def set_inlineblocklocation(loc, block): """ Set location for code block :param loc: location object :param block: list of instructions """ return [set_loc(block[0], loc)] + \ map(lambda i: set_loc(i, Types.Loc('', loc.loc_addr, loc.loc_visible)), block[1:])
def add_func_label(self, ufuncs, instrs): """ Insert function labels :param ufuncs: function list :param instrs: instruction list :return: instruction list with function declarations """ i = 0 j = 0 while True: if i == len(ufuncs) or j == len(instrs): break hf = ufuncs[i] hi = instrs[j] iloc = get_loc(hi) if hf.func_begin_addr == iloc.loc_addr and hf.func_name not in iloc.loc_label: lab = '\n' + hf.func_name + ' : ' if ELF_utils.elf_arm(): lab = '\n.thumb_func' + lab iloc.loc_label = lab + iloc.loc_label instrs[j] = set_loc(hi, iloc) i += 1 j -= 1 elif hf.func_begin_addr < iloc.loc_addr: i += 1 j += 1 return instrs
def translate_it_block(block): """ Translate IT block using normal branches :param block: instruction list of IT block :return: instruction list with normal branches """ itloc = get_loc(block[0]) res = [ Types.DoubleInstr( ('b' + block[0][1], Types.Label('.LIT_%X.T' % itloc.loc_addr), itloc, False)) ] branches = {'t': [], 'e': []} for i in xrange(1, len(block[0][0])): op = block[i][0].split('.') op[0] = op[0][:-2] instr = type(block[i])(('.'.join(op), ) + block[i][1:]) branches[block[0][0][i]].append(instr) endloc = get_loc(block[-1]) branches['e'].append( Types.DoubleInstr(('b', Types.Label( ('.LIT_%X.E' % itloc.loc_addr)), endloc, False))) branches['t'][0][-2].loc_label += '.LIT_%X.T: ' % itloc.loc_addr res += branches['e'] + branches['t'] res.append( set_loc( block[-1], Types.Loc('.LIT_%X.E: ' % itloc.loc_addr, endloc.loc_addr, True))) return res
def get_returnenc(curr_instr, popcookie=False): """ Get code block for return address encryption :param curr_instr: return instruction :param popcookie: True if also frame cookie must be removed :return: return encryption instruction list """ pre = list(framecookietail) if popcookie else [] loc = get_loc(curr_instr) if curr_instr[0].upper().startswith('POP'): # pop {...,pc} i = map(str.upper, curr_instr[1]).index('PC') rlist = curr_instr[1][:i] + ('lr', ) + curr_instr[1][i + 1:] pre.insert( 0, Types.DoubleInstr( (curr_instr[0], Types.RegList(rlist), None, False))) curr_instr = Types.DoubleInstr( ('bx', Types.RegClass('lr'), None, False)) elif curr_instr[0].upper().startswith( 'LDR') and curr_instr[1].upper() == 'PC': # ldr pc, [sp], #4 pre.insert( 0, type(curr_instr)((curr_instr[0], Types.RegClass('lr')) + curr_instr[2:])) curr_instr = Types.DoubleInstr( ('bx', Types.RegClass('lr'), None, False)) return set_inlineblocklocation(loc, pre + returnenc) + \ [set_loc(curr_instr, Types.Loc('', loc.loc_addr, loc.loc_visible))]
def unify_loc(self, instrs): last_label = '' for i in xrange(len(instrs)): lo = get_loc(instrs[i]) if lo.loc_label != '' and lo.loc_label == last_label: instrs[i] = set_loc(instrs[i], Types.Loc('', lo.loc_addr, True)) else: last_label = lo.loc_label return instrs
def get_returnenc(curr_instr, popcookie=False): """ Get code block for return address encryption :param curr_instr: return instruction :param popcookie: True if also frame cookie must be removed :return: return encryption instruction list """ loc = get_loc(curr_instr) return set_inlineblocklocation(loc, framecookietail + returnenc if popcookie else returnenc) + \ [set_loc(curr_instr, Types.Loc('', loc.loc_addr, loc.loc_visible))]
def get_framecookiecheck(curr_instr, funcID): """ Get code block for frame cookie check :param curr_instr: indirect branch instruction :param funcID: generated function ID :return: frame cookie check instruction list """ loc = get_loc(curr_instr) tmp = list(framecookiecheck) tmp[3][2] = Types.Normal(funcID) tmp[3] = Types.TripleInstr(tmp[3]) return set_inlineblocklocation(loc, tmp) + \ [set_loc(curr_instr, Types.Loc('', loc.loc_addr, loc.loc_visible))]
def get_framecookiehead(curr_instr, funcID): """ Get function header code block for frame cookie insertion :param curr_instr: function entry instruction :param funcID: generated function ID :return: frame cookie insertion instruction list """ loc = get_loc(curr_instr) tmp = list(framecookiehead) tmp[5][2] = Types.Normal(funcID) tmp[5] = Types.TripleInstr(tmp[5]) return set_inlineblocklocation(loc, returnenc + tmp) + \ [set_loc(curr_instr, Types.Loc('', loc.loc_addr, loc.loc_visible))]
def alignvldrARM(self, instrs): """ Insert alignment compiler instruction for vldr targets (ARM) :param instrs: instruction list """ self.ARMvldrtargets = sorted(set(self.ARMvldrtargets)) i = 0 j = 0 while True: if i == len(instrs) or j == len(self.ARMvldrtargets): break loc = get_loc(instrs[i]) if loc.loc_addr == self.ARMvldrtargets[j]: loc.loc_label = '\n.align 2' + loc.loc_label instrs[i] = set_loc(instrs[i], loc) j += 1 elif loc.loc_addr > self.ARMvldrtargets[j]: j += 1 i -= 2 i += 1 return instrs
def add_bblock_label(self, bbl, instrs): bbl1 = sorted( bbl, lambda b1, b2: b1.bblock_begin_loc.loc_addr - b2. bblock_begin_loc.loc_addr) i = 0 j = 0 while True: if i == len(instrs) and j < len(bbl1): raise Exception('failed to add block label') if j == len(bbl1): break hi = instrs[i] hb = bbl1[j] iloc = get_loc(hi) bloc = hb.bblock_begin_loc if bloc.loc_addr == iloc.loc_addr: iloc = Types.Loc(hb.bblock_name + ': ' + iloc.loc_label, iloc.loc_addr, iloc.loc_visible) instrs[i] = set_loc(instrs[i], iloc) j += 1 i += 1 return instrs
def get_instr_list(self): """ Get instruction list """ return map(lambda e: set_loc(e[0], e[1]), zip(self.instr_list, self.locs))