def move_up_offset(self, inpath, outpath): # {{{ t1 = timer() retcode = 0 self.p('\nMoving up section offset after QShrink operation...') shutil.copyfile(inpath, outpath) elf = elfFileClass.elfFile(inpath) # TODO: add check for existence of target sections. elf.moveupElfOffsetSectionByName(".dynamicReclaim") elf.moveupElfOffsetSectionByName("QSR_STRING") elf.writeOutELF(outpath) if retcode != 0: self.p('Failed moving up offset') # self.p('stdout: %s' % stdout) # self.p('stderr: %s' % stderr) # else: self.log('Passed moving up offset') # self.log('stdout: %s' % stdout) # self.log('stderr: %s' % stderr) t2 = timer() t_diff = t2 - t1 self.p(' Move up offset execution time: %s' % t_str(t_diff)) return retcode
def __init__(self, elf_path, hexagon_path=None): # {{{ self.dummy_segment = None # get_image_and_pad_size may change this self.hex_path = hexagon_path self.elf = elfFileClass.elfFile(elf_path) self.symtab = self.get_reduced_symbol_table() self.sizes = [i[2] for i in self.size_template] self.sz_idx = dict([(i[1], j) for j, i in enumerate(self.size_template)])
def qshrink(self, inpath, outpath): # {{{ t1 = timer() sh_table = list(elfFileClass.elfFile(inpath).sectionHeaderTable) retcode = 0 if 'QSR_STRING' in [i.sh_nameStr for i in sh_table]: # qshrink section exists, run qshrink self.p('\nRunning QShrink') qspath = pj(self.mypspath, 'qshrink') qs_build_path = os.path.abspath( os.path.join( self.buildpath, 'build', 'myps', 'qshrink', ) ) retcode, stdout, stderr = self.call([ self.python, '-O', pj(qspath, 'Qshrink20.py'), inpath, '--image_end_from_elfheader', ''.join(['--output=', outpath]), ''.join(['--hashfile=', pj(qspath, 'msg_hash.txt')]), ''.join(['--qdbFile=', self.qdbpath]), ''.join(['--buildOutputPath=', qs_build_path])]) if retcode != 0: self.p('QShrink failed. Logs below:') self.p('stdout: %s' % stdout) self.p('stderr: %s' % stderr) else: self.log('QShrink logs:') self.log('stdout: %s' % stdout) self.log('stderr: %s' % stderr) else: self.p(' Skipping QShrink: no QSR_STRING section found') t2 = timer() t_diff = t2 - t1 self.p(' QShrink execution time: %s' % t_str(t_diff)) return retcode
def main(): #{{{{ print "Running Dynamic Reclaiming post-linking processing..." elf_handle = elfFileClass.elfFile(sys.argv[1]) Dict = {} #NameList = getSectionName(elf_handle, ".dynamicReclaim.*") #print(NameList) print print "-> Searching Dynamic Reclaiming section..." sh_src = elf_handle.getSectionByName(".dynamicReclaim") if sh_src == const.RC_ERROR: #{ print " " * 3 + "-> ! No Dynamic Reclaiming segment found, quit execution." elf_handle.writeOutELF(sys.argv[2]) sys.exit() #} Dict["old_dynrec_base_address"] = sh_src.sh_addr elf_handle.moveupSectionByName(".dynamicReclaim") sh_src = elf_handle.getSectionByName(".dynamicReclaim") Dict["dynrec_base_address"] = sh_src.sh_addr Dict["dynrec_section_size"] = sh_src.sh_size Dict["image_vend"] = (sh_src.sh_addr + sh_src.sh_size + 4096) & (~4095) #========================================= # updated to remove dupllicates from list. #========================================= elf = elf_handle symtab = elf.getSectionByName(".symtab") strtab = elf.getSectionByName(".strtab") print print "-> Getting Dynamic Reclaiming linker symbols..." symbols = elfFileClass.Elf32_SymGenerator(symtab, strtab) #SymbolList = getLinkerVars(elf, "__dynrec_.*_rfc_.*", symtab, strtab, symbols) SymbolList = getLinkerVars(elf, "__dynrec_.*", symtab, strtab, symbols) if len(SymbolList) == 0: #{ print " " * 3 + "-> ! No dynrec symbols found <==> feature disabled, quit execution." elf_handle.updateSymbolValuesByDict(Dict) elf_handle.writeOutELF(sys.argv[2]) sys.exit() #} dynrecSymbol_text_start_preorder_list = [] dynrecSymbol_new_client_list = [] dynrecSymbol_text_start_list = [] for symbol in SymbolList: #} if re.match(".*dynrec_text_start.*rfc_.*", symbol.st_nameStr, flags=0) != None: #{ print " "*3\ + "-> %-30s:" %"Found RFC symbol"\ + "\tS:\t%-40s, " %symbol.st_nameStr\ + "\t\tV:\t%-15s. " %str(hex(symbol.st_value)) dynrecSymbol_text_start_preorder_list.append(symbol) #} elif re.match(".*dynrec_.*_wtr_4905.*", symbol.st_nameStr, flags=0) != None: #{ print " "*3\ + "-> %-30s:" %"Found new client symbol"\ + "\tS:\t%-40s, " %symbol.st_nameStr\ + "\t\tV:\t%-15s. " %str(hex(symbol.st_value)) dynrecSymbol_new_client_list.append(symbol) #} #} dynrecAddrTableSize = len(dynrecSymbol_text_start_preorder_list) if dynrecAddrTableSize == 0: #{ print " " * 3 + "-> ! No dynrec RFC text starts symbols found, skip rest of RFC symbol processing." print "-> Starting new client symbol processing..." #} else: #{ print print "-> Continuing with RFC symbol processing..." print " " * 3 + "-> Sorting RFC symbols based on virtual address..." dynrecSymbol_text_start_preorder_list = sorted( dynrecSymbol_text_start_preorder_list, key=lambda x: x.st_value, reverse=False) print " " * 3 + "-> Sorted text_start RFC linker symbols: " for k in range(0, len(dynrecSymbol_text_start_preorder_list)): #{ print " " * 6 + "\tS:\t%-40s" % dynrecSymbol_text_start_preorder_list[ k].st_nameStr #} print print "-> Getting \'text_end_\', \'data_start_\', and \'data_end_\' RFC symbols..." dynrecSymbol_text_end_preorder_list = [] dynredSymbol_data_start_preorder_list = [] dynredSymbol_data_end_preorder_list = [] for j in range(0, dynrecAddrTableSize): #{ symbolTextStart = dynrecSymbol_text_start_preorder_list[ j].st_nameStr symbolTextEnd = symbolTextStart.replace("_start_", "_end_") symbolDataStart = symbolTextStart.replace("_text_", "_data_") symbolDataEnd = symbolDataStart.replace("_start_", "_end_") for symbol in SymbolList: #{ if symbolTextEnd == symbol.st_nameStr: #{ dynrecSymbol_text_end_preorder_list.append(symbol) #} elif symbolDataStart == symbol.st_nameStr: #{ dynredSymbol_data_start_preorder_list.append(symbol) #} elif symbolDataEnd == symbol.st_nameStr: #{ dynredSymbol_data_end_preorder_list.append(symbol) #} else: #{ continue #} print " "*3\ + "-> Found Symbol:"\ + "\tS:\t%-40s, " %symbol.st_nameStr\ + "\t\tV:\t%-15s. " %str(hex(symbol.st_value)) #} #} print print "-> All RFC linker symbols are found, continuing to sort..." if len(dynrecSymbol_text_end_preorder_list) != dynrecAddrTableSize or \ len(dynredSymbol_data_start_preorder_list) != dynrecAddrTableSize or \ len(dynredSymbol_data_end_preorder_list) != dynrecAddrTableSize: #{ print " " * 3 + "-> ! Missing addr symbols for text ends, data starts or data ends, quit execution." elf_handle.updateSymbolValuesByDict(Dict) elf_handle.writeOutELF(sys.argv[2]) sys.exit() #} print " " * 3 + "-> Printing pre-order list entries:" for x in range(0, dynrecAddrTableSize): #{ print " "*6\ + "\tS:\t%-40s," %dynrecSymbol_text_start_preorder_list[x].st_nameStr\ + "\t\tV:\t%-15s." %str(hex(dynrecSymbol_text_start_preorder_list[x].st_value)) print " "*6\ + "\tS:\t%-40s," %dynrecSymbol_text_end_preorder_list[x].st_nameStr\ + "\t\tV:\t%-15s." %str(hex(dynrecSymbol_text_end_preorder_list[x].st_value)) print " "*6\ + "\tS:\t%-40s," %dynredSymbol_data_start_preorder_list[x].st_nameStr\ + "\t\tV:\t%-15s." %str(hex(dynredSymbol_data_start_preorder_list[x].st_value)) print " "*6\ + "\tS:\t%-40s," %dynredSymbol_data_end_preorder_list[x].st_nameStr\ + "\t\tV:\t%-15s." %str(hex(dynredSymbol_data_end_preorder_list[x].st_value)) #} print print "-> Done printing pre-order list symbols, continuing to remove symbols of empty RFC modules..." # moving dynrecSymbol_text_start_list[] definition out of if branch # to avoid post-link error when feature is checked in but disabled. #dynrecSymbol_text_start_list = [] dynrecSymbol_text_end_list = [] dynredSymbol_data_start_list = [] dynredSymbol_data_end_list = [] print " " * 3 + "-> Removing empty modules..." print " " * 6 + "-> Found non-empty RFC modules:" for j in range(0, dynrecAddrTableSize): #{{ symbol_va_start_text = dynrecSymbol_text_start_preorder_list[j] symbol_va_end_text = dynrecSymbol_text_end_preorder_list[j] symbol_va_start_data = dynredSymbol_data_start_preorder_list[j] symbol_va_end_data = dynredSymbol_data_end_preorder_list[j] if (symbol_va_start_text.st_value < symbol_va_end_text.st_value and symbol_va_start_data.st_value < symbol_va_end_data.st_value): #{ print " " * 9 + "-> %d" % j print " "*12\ + "\tS:\t%-40s," %symbol_va_start_text.st_nameStr\ + "\t\tV:\t%-15s." %str(hex(symbol_va_start_text.st_value)) print " "*12\ + "\tS:\t%-40s," %symbol_va_end_text.st_nameStr\ + "\t\tV:\t%-15s." %str(hex(symbol_va_end_text.st_value)) print " "*12\ + "\tS:\t%-40s," %symbol_va_start_data.st_nameStr\ + "\t\tV:\t%-15s." %str(hex(symbol_va_start_data.st_value)) print " "*12\ + "\tS:\t%-40s," %symbol_va_end_data.st_nameStr\ + "\t\tV:\t%-15s." %str(hex(symbol_va_end_data.st_value)) dynrecSymbol_text_start_list.append(symbol_va_start_text) dynrecSymbol_text_end_list.append(symbol_va_end_text) dynredSymbol_data_start_list.append(symbol_va_start_data) dynredSymbol_data_end_list.append(symbol_va_end_data) #} #}} print " " * 3 + "-> Removed empty modules..." print print "-> Continuing to add linker symbols for new clients..." #} # start dynrec new client symbol processing. print " " * 3 + "-> Adding new client symbols to \'dynrec_linker_var_arr[]\'..." dynrecSymbol_new_client_list_size = len(dynrecSymbol_new_client_list) if dynrecSymbol_new_client_list_size == 0: #{ print " " * 6 + "-> ! No dynrec new client symbols found, skip processing." print #} else: #{ for j in range(0, len(dynrecSymbol_new_client_list)): #{ sym_data_start = dynrecSymbol_new_client_list[j].st_nameStr if (sym_data_start.find("__dynrec_data_start_") != -1): #{ dynredSymbol_data_start_list.append( dynrecSymbol_new_client_list[j]) print " "*9\ + "-> Adding %d:" %j\ + "\tS:\t%-40s," %sym_data_start\ + "\t\tV:\t%-15s." %str(hex(dynrecSymbol_new_client_list[j].st_value)) sym_data_end = sym_data_start.replace("_start_", "_end_") sym_text_start = sym_data_start.replace("_data_", "_text_") sym_text_end = sym_text_start.replace("_start_", "_end_") for symbol in dynrecSymbol_new_client_list: #{ if symbol.st_nameStr == sym_data_end: #{ dynredSymbol_data_end_list.append(symbol) #} elif symbol.st_nameStr == sym_text_start: #{ dynrecSymbol_text_start_list.append(symbol) #} elif symbol.st_nameStr == sym_text_end: #{ dynrecSymbol_text_end_list.append(symbol) #} else: #{ continue #} print " "*9\ + "-> Adding %d:" %j\ + "\tS:\t%-40s," %symbol.st_nameStr\ + "\t\tV:\t%-15s." %str(hex(symbol.st_value)) #} #} #} print " " * 6 + "-> Added new client modules." print #} print "-> Checking Dynamic Reclaiming symbols collected so far..." if (len(dynrecSymbol_text_start_list) == 0): #{{ print " " * 3 + "-> ! No module to be dynamic reclaimed, quit execution." elf_handle.updateSymbolValuesByDict(Dict) elf_handle.writeOutELF(sys.argv[2]) sys.exit() #}} if (dynrecSymbol_text_start_list[0].st_nameStr.find("_preload") != -1): #{{ print " " * 3 + "-> Processing symbols of first RFC module for veneer issue workaround..." dynrecSymbol_text_start_list[ 0].st_nameStr = dynrecSymbol_text_start_list[0].st_nameStr.rstrip( "_preload") dynrecSymbol_text_end_list[0].st_nameStr = dynrecSymbol_text_end_list[ 0].st_nameStr.rstrip("_preload") dynredSymbol_data_start_list[ 0].st_nameStr = dynredSymbol_data_start_list[0].st_nameStr.rstrip( "_preload") dynredSymbol_data_end_list[0].st_nameStr = dynredSymbol_data_end_list[ 0].st_nameStr.rstrip("_preload") print " " * 3 + "-> Done stripping first preloaded card back to original name..." #}} else: #{{ print " " * 3 + "-> Did not find \"_preload\" pattern in first card, maybe it's empty." #}} print #============================================================================================================ print "-> Continuing to update dynrec_linker_var_arr[] in symbol table..." Dict["dynrec_numentries"] = len(dynrecSymbol_text_start_list) print " " * 3 + "-> Collected %d" % len( dynrecSymbol_text_start_list) + " modules in total." elf_handle.updateSymbolValuesByDict(Dict) dynrec_linker_var_arr = elf_handle.getSymbolByName("dynrec_linker_var_arr") if (dynrec_linker_var_arr == const.RC_ERROR): #{ print " " * 3 + "-> ! Cannot find \'dynrec_linker_var_arr[]\', please check source code correctness, quit execution." elf_handle.updateSymbolValuesByDict(Dict) elf_handle.writeOutELF(sys.argv[2]) sys.exit() #} api_called = elf_handle.getSymbolByName("mcfg_dynrec_load") if (api_called == const.RC_ERROR): #{ print " " * 3 + "-> ! CDynrec feature is enabled but mcfg_dynrec_* API has not been called, please check source code correctness, quit execution." elf_handle.updateSymbolValuesByDict(Dict) elf_handle.writeOutELF(sys.argv[2]) sys.exit() #} data_ptr = dynrec_linker_var_arr.st_value val = readDataByAddress(elf_handle, data_ptr + 1, 1) print " " * 3 + "-> Adding following entries to \'dynrec_linker_var_arr[]\':" print print " "*6\ + "%5s: " %"index"\ + "\t" + "%10s:" %"client_id"\ + "\t" + "%20s:" %"is_module_loaded"\ + "\t" + "%20s:" %"str_id[]"\ + "\t" + "%20s:" %"is_client_reclaimed"\ + "\t" + "%15s:" %"text_begin"\ + "\t" + "%15s:" %"text_end"\ + "\t" + "%15s:" %"data_begin"\ + "\t" + "%15s:" %"data_end" client_dict = {'rfc': 1, 'wtr_4905': 2, 'rfc_internal': 3} for i in range(0, len(dynrecSymbol_text_start_list)): #{ curr_entry = dynrecSymbol_text_start_list[i] curr_entry_name = curr_entry.st_nameStr curr_entry_addr = curr_entry.st_value curr_entry_generic_val = 0 marker = re.sub('__dynrec_text_start_', '', curr_entry_name, count=1) client_id = 0 for j in client_dict.keys(): #{ if marker.find(j) != -1: #{ client_id = client_dict[j] # MCFG_DYNREC_CLIENT_RFC marker = marker.rstrip("_") break #} #} if client_id > 3 or client_id < 1: #{ print " " * 6 + "-> ! Invalid str_id[]: %-15s, skip to next." % marker continue #} if setDataByAddress( elf_handle, data_ptr, 1, client_id) == const.RC_ERROR: # data_ptr -> 'client_id' #{ print " " * 6 + "-> ! Failed to set symbol: %-40s\t, skip to next." % curr_entry_name continue #} data_ptr = data_ptr + 1 # data_ptr -> 'is_module_loaded' setDataByAddress(elf_handle, data_ptr, 1, 0) data_ptr = data_ptr + 1 # data_ptr -> str_id[] str_ptr = data_ptr for char in marker: #{ setDataByAddress(elf_handle, str_ptr, 1, ord(char)) str_ptr = str_ptr + 1 #} data_ptr = data_ptr + 50 # data_ptr -> 'is_client_reclaimed' setDataByAddress(elf_handle, data_ptr, 4, 0) data_ptr = data_ptr + 4 # data_ptr -> text_address_begin setDataByAddress(elf_handle, data_ptr, 4, dynrecSymbol_text_start_list[i].st_value) data_ptr = data_ptr + 4 # data_ptr -> text_address_end setDataByAddress(elf_handle, data_ptr, 4, dynrecSymbol_text_end_list[i].st_value) data_ptr = data_ptr + 4 # data_ptr -> rodata_data_address_begin setDataByAddress(elf_handle, data_ptr, 4, dynredSymbol_data_start_list[i].st_value) data_ptr = data_ptr + 4 # data_ptr -> rodata_data_address_end setDataByAddress(elf_handle, data_ptr, 4, dynredSymbol_data_end_list[i].st_value) data_ptr = data_ptr + 4 # data_ptr -> starting address of next entry. print " "*6\ + "%5d:" %i\ + "\t" + "%10d " %client_id\ + "\t" + "%20s " %curr_entry_generic_val\ + "\t" + "%20s " %marker\ + "\t" + "%20s " %curr_entry_generic_val\ + "\t" + "%15s " %str(hex(dynrecSymbol_text_start_list[i].st_value))\ + "\t" + "%15s " %str(hex(dynrecSymbol_text_end_list[i].st_value))\ + "\t" + "%15s " %str(hex(dynredSymbol_data_start_list[i].st_value))\ + "\t" + "%15s " %str(hex(dynredSymbol_data_end_list[i].st_value)) #} print print "-> Done updating \'dynrec_linker_var_arr[]\', continuing to update ELF file..." elf_handle.writeOutELF(sys.argv[2]) print print "-> Done Dynamic Reclaiming post-linking process, finish." print return 0
def fix_physpool_size(input_elf, dummy_segment_size): # {{{ script_dir = os.path.split( inspect.getframeinfo(inspect.currentframe()).filename)[0] # cwd() is supposedly modem_proc/build/ms # could also be launched from our master location elfmanip_paths = (('..', 'myps', 'elfManipulator', 'include'), ('..', 'elfManipulator', 'include')) for elfmanip_path in elfmanip_paths: sys.path.insert(0, os.path.join(*[script_dir] + list(elfmanip_path))) import elfFileClass import elfConstants elf = elfFileClass.elfFile(input_elf) symtab = elf.getSectionByName('.symtab') strtab = elf.getSectionByName('.strtab') found_pool_configs = False ph = elf.programHeaderTable[-1] print 'Last program segment information:' print ' Starting address : 0x%08x' % ph.p_paddr print ' Size : 0x%08x' % ph.p_memsz print ' Alignment : 0x%08x' % ph.p_align dummy_seg = { 'start': (ph.p_paddr + ph.p_memsz + ph.p_align - 1) & ~(ph.p_align - 1), 'size': dummy_segment_size, 'align': 0x100000 } print 'Dummy segment information:' print ' Starting address : 0x%08x' % dummy_seg['start'] print ' Unaligned size : 0x%08x' % dummy_seg['size'] # get image start, assume it's the smallest non-zero paddr image_start = sorted( [i.p_paddr for i in elf.programHeaderTable if i.p_paddr > 0])[0] physpool = {'size_old': dummy_seg['start'] - image_start} physpool['end_aligned'] = (elf.programHeaderTable[0].p_paddr + physpool['size_old'] + dummy_seg['size'] + dummy_seg['align'] - 0x1) & ~(dummy_seg['align'] - 0x1) physpool['size_new'] = physpool['end_aligned'] - \ elf.programHeaderTable[0].p_paddr print 'Default physical pool information:' print ' Unadjusted size : 0x%08x' % physpool['size_old'] print ' Aligned adjusted size : 0x%08x' % physpool['size_new'] print ' Aligned ending address : 0x%08x' % physpool['end_aligned'] if physpool['size_new'] > physpool['size_old']: raise Exception('Adjusted size cannot be greater than unadjusted size') if (symtab != elfConstants.RC_ERROR and strtab != elfConstants.RC_ERROR): for symbol in elfFileClass.Elf32_SymGenerator(symtab, strtab): if symbol.st_nameStr == 'pool_configs': found_pool_configs = True # For executable files, st_value holds a virtual address sect_offset = symbol.st_value - \ elf.sectionHeaderTable[symbol.st_shndx].sh_addr # struct definition of pool_configs # modem_proc/core/kernel/config/build/mba/qdsp6/.../qurt_config.c#286 s = struct.Struct('<32c' + 'II' * 16) entry_size = s.size found_default_physpool = False for struct_offset in xrange(0, symbol.st_size, entry_size): unpacked_data = list( s.unpack(elf.sectionHeaderTable[symbol.st_shndx]. contents[sect_offset + struct_offset:sect_offset + struct_offset + entry_size])) pool_entry_name = ''.join( unpacked_data[0:32]).rstrip('\x00') pool_entry_addr_pairs = unpacked_data[32:] if pool_entry_name == 'DEFAULT_PHYSPOOL': found_default_physpool = True for i in xrange(0, len(pool_entry_addr_pairs), 2): # the first pair holds the (start, size) tuple pool_entry_addr_pairs[i + 1] = physpool['size_new'] break # roll it all back into the ELF unpacked_data[32:] = pool_entry_addr_pairs packed_data = s.pack(*unpacked_data) elf.sectionHeaderTable[ symbol.st_shndx].contents = ''.join([ elf.sectionHeaderTable[ symbol.st_shndx].contents[:sect_offset], packed_data, elf.sectionHeaderTable[symbol.st_shndx]. contents[sect_offset + len(packed_data):] ]) elf.writeOutELF(input_elf) print 'Successfully wrote new DEFAULT_PHYSPOOL size 0x%08x' % \ physpool['size_new'] return if not found_default_physpool: print 'Error: Could not find DEFAULT_PHYSPOOL within pool_configs' sys.exit(2) if not found_pool_configs: print 'Error: Could not find symbol pool_configs to update' sys.exit(2) else: print 'Error: Missing .symtab and/or .strtab section' sys.exit(2)