def_locate_file(self,filename):ifos.path.isfile(filename):returnfilenameifself._source_rootisNone:returnNonefilename=filename.strip("/\\")path_keys=re.split("[/\\\\]",filename)foriinrange(len(path_keys)):maybe_path=os.path.join(self._source_root,*path_keys[i:])ifos.path.isfile(maybe_path):returnmaybe_pathreturnNonedef_open_file(self,name,cache=None):ifcacheisNone:cache={}ifnameincache:returncache[name]local_name=self._locate_file(name)iflocal_nameisNone:l.warning("Could not find a local copy of %s",name)cache[name]=NonereturnNonewithopen(local_name,encoding=self._encoding)asfp:line_data=fp.readlines()cache[name]=line_datareturnline_datadef_compute_function_ranges(self,cache=None):ifcacheisNone:cache={}obj=self.project.loader.find_object_containing(self.function.addr)ifobjisNone:l.warning("No object contains function %s",self.function.name)return[]ifself.function.addrnotinobj.addr_to_line:l.info("No line data for function %s",self.function.name)return[]lines=SortedList()forblockinself.function.blocks:forinsninblock.instruction_addrs:ifinsninobj.addr_to_line:lines.update((*filename_line,insn)forfilename_lineinobj.addr_to_line[insn])ranges=[]forfilename,line,_inlines:ifany(r[0]==filenameandr[1]<=line<=r[2]forrinranges):continuefile_lines=self._open_file(filename,cache=cache)iffile_linesisNone:continueifline-1>=len(file_lines)orline-1<0:# a non-existent line number is specified. skip this recordl.warning("Line number %d does not exist in file %s. It might be the wrong source code file.",line,filename)continuerange_start=linerange_end=line# find the first { on the line# find the matching }# scan backwards for any lines that aren't blank and don't have {}; on them# scan forwards for any lines continued via \col=file_lines[range_start-1].find("{")ifcol!=-1:col+=1stack=1whilerange_end-1<len(file_lines):whilecol<len(file_lines[range_end-1]):ch=file_lines[range_end-1][col]ifch=="{":stack+=1elifch=="}":stack-=1ifstack==0:breakcol+=1else:col=0range_end+=1continuebreakmaybe_prev_line=range_start-1whilemaybe_prev_line>=0:linedata=file_lines[maybe_prev_line-1].strip()iflinedataandnotany(cinlinedataforcin"{};"):range_start=maybe_prev_linemaybe_prev_line-=1else:breakwhilerange_end-1<len(file_lines)-1:linedata=file_lines[range_end-1].strip()iflinedata.endswith("\\"):range_end+=1else:breakifany(r[0]==filenameand(r[1]<=range_start<=r[2]orrange_start<=r[1]<=range_end)forrinranges):l.error("Detected line ranges are overlapping?")ranges.append((filename,range_start,range_end))returnrangesdef_compute_line_to_addr(self,ranges):result={}forfilename,range_start,range_endinranges:forlineinrange(range_start,range_end+1):result[(filename,line)]=Noneobj=self.project.loader.find_object_containing(self.function.addr)ifobjisNone:l.error("There is a function whose address does not correspond to any loaded object")return{}foraddr,filename_lineinobj.addr_to_line.items():iffilename_lineinresult:result[filename_line]=addrreturnresult