class Itools::LinkMap

———————————LinkMap class———————————

Attributes

l_arch[RW]

包含的属性

l_dead_stripped_symbols[RW]

包含的属性

l_name[RW]

包含的属性

l_obj_files[RW]

包含的属性

l_path[RW]

包含的属性

l_sections[RW]

包含的属性

l_sym_map[RW]

包含的属性

l_symbols[RW]

包含的属性

Public Class Methods

new(fName) click to toggle source

初始化方法

# File lib/itools/link_map.rb, line 41
def initialize(fName)
   @l_name = fName
   @l_obj_files = []
   @l_symbols = []
   @l_sections = []
   @l_dead_stripped_symbols = []
end
parser(path_para) click to toggle source

对linkmap进行解析,然后输出结果

# File lib/itools/link_map.rb, line 155
def self.parser(path_para)
   start_time = Time.now.to_i    #程序开始执行时间(以毫秒为单位)
   # 获取link map file's name
   link_map_file_name = path_para
   puts "获取的文件路径为:#{link_map_file_name}"
   if link_map_file_name.nil?
      puts "请按照如下命令执行该脚本:"
      puts "\033[31mitools parse  **.txt \033[0m"
      puts "**指代Link Map File的名字,例如LinkMapApp-LinkMap-normal-x86_64.txt,parse后面为绝对路径"
      return
   end
   if File.exist?(link_map_file_name)
      puts "\033[32m获取LinkMap文件: #{link_map_file_name}成功,开始分析数据...\033[0m"
   else
      puts "\033[31m#{link_map_file_name}文件不存在,请重新输入文件 \033[0m"
      return
   end

   link_map = LinkMap.new(link_map_file_name)
   link_map.handle_map #处理文件为对象,然后继续后续操作
   link_map.handle_l_sym_map  #处理symbols为hashmap
   sizeResultArr = []

   link_map.l_obj_files.each do |obj|
      temp_file_name = obj.file_name.split("(")[0]

      last_file = sizeResultArr.last

      if last_file && temp_file_name.eql?(last_file.file_name)
         last_file.file_serial_numers << obj.serial_number
      else
         sz_obj = SizeResult.new
         sz_obj.file_name = temp_file_name
         sz_obj.file_serial_numers << obj.serial_number
         sizeResultArr << sz_obj
      end
   end
   data_analyze_time = Time.now.to_i
   puts "\033[32m数据分析完成,耗时#{data_analyze_time - start_time}秒。开始计算结果\033[0m"

   # 计算赋值size,此处耗时较长
   total_size = 0
   sizeResultArr.each do |obj|
      # 处理方法2
      obj.file_serial_numers.each do |s_number|
         begin
            link_map.l_sym_map[s_number].each do |symb|
               obj.size = obj.size + symb.s_size.hex
               total_size = total_size +symb.s_size.hex  #统计总大小
            end
         rescue => exception
         end
      end
      # 处理方法1 太过耗时
      # link_map.l_symbols.each do |symb|
      #     if obj.file_serial_numers.include?(symb.s_file_serial_number)
      #         obj.size = obj.size + symb.s_size.hex
      #     end
      # end
      # puts "正在计算#{obj.file_name}的大小..."
   end
   data_handle_time = Time.now.to_i  #处理数据时间
   puts "\033[32m数据处理完成,耗时#{data_handle_time - data_analyze_time}秒。开始对结果进行大小排序(从大到小)...\033[0m"
   # 按照从大到小排序
   sizeResultArr.sort_by!{|obj|[-obj.size]}
   sort_handle_time = Time.now.to_i  #排序耗时
   puts "\033[32m数据排序完成,耗时#{sort_handle_time - data_handle_time}秒。开始输出结果:\033[0m"
   puts "\033[32m--------------------------------\033[0m"

   # 判断文件是否存在
   save_file_path = SizeResult.getSaveFileName(path_para)
   if File.exist?(save_file_path)
      File.delete(save_file_path)
   end

   # 创建要保存数据的文件
   save_file = File.new(save_file_path,"w+")
   # 打印结果
   sizeResultArr.each do |obj|
      puts "#{obj.file_name}          " + SizeResult.handleSize(obj.size)
      save_file.puts("#{obj.file_name}          #{SizeResult.handleSize(obj.size)}(#{obj.size})")
   end
   save_file.puts("总大小为:#{SizeResult.handleSize(total_size)}")
   save_file.close
   puts "总大小为(仅供参考):#{SizeResult.handleSize(total_size)}"
   puts "\033[32m--------------------------------\033[0m"
   end_time = Time.now.to_i   #程序执行结束时间
   puts "分析结果已经保存为文件,位置为:\n\033[32m#{save_file_path}\033[0m"
   puts " "
   puts "\033[32m整个程序执行时间为:#{end_time - start_time}秒\033[0m"
end
parser_by_folder(args) click to toggle source

根据linkmap && folder计算占用 第一个参数为linkmap路径,第二个参数为要分析的项目文件夹

# File lib/itools/link_map.rb, line 249
def self.parser_by_folder(args)
   link_map_file_name = args[0]    #linkmap文件路径
   project_folder = args[1] #项目文件夹
   # 对参数进行校验
   if File::directory?(project_folder)
      puts "获取的项目目录路径为:#{project_folder}"
   else
      puts "\033[31m#{project_folder}文件夹不存在,请重新输入 \033[0m"
      return
   end
   if File.exist?(link_map_file_name)
      puts "获取的linkmap文件路径为:#{link_map_file_name}"
      puts "\033[32m获取LinkMap文件: #{link_map_file_name}成功,开始分析数据...\033[0m"
   else
      puts "\033[31m#{link_map_file_name}文件不存在,请重新输入 \033[0m"
      return
   end
   # 开始处理数据
   link_map = LinkMap.new(link_map_file_name)
   link_map.handle_map #处理文件为对象,然后继续后续操作
   link_map.handle_l_sym_map  #处理symbols为hashmap

   # 所有的文件
   link_map.l_obj_files
   # 所有的symbols
   link_map.l_symbols

   # 处理得到每个obj_file的大小
   link_map.l_obj_files.each do |obj|
      if link_map.l_sym_map[obj.serial_number]
         link_map.l_sym_map[obj.serial_number].each do |symb|
            obj.o_size = obj.o_size + symb.s_size.hex
         end
      end
   end
   # key为文件名,value为ojbect
   sort_by_obj_files_map = link_map.l_obj_files.group_by(&:o_name)
   # save_file_path = SizeResult.getSaveFileName(project_folder)
   # save_file = File.new(save_file_path,"w+")
   # sort_by_obj_files_map.keys.each do |sss|

   #    save_file.puts("#{sort_by_obj_files_map[sss][0].o_name}   #{sort_by_obj_files_map[sss][0].o_size}")
   # end
   # save_file.close
   # exit



   size_results = [] #盛放计算结果
   size_files = []
   space_index = 0
   puts "计算开始"
   traverse_dir(sort_by_obj_files_map,project_folder,size_results,size_files,space_index)
   size_results.reverse!
   # 存储为文件
   save_file_path = SizeResult.getSaveFileName(project_folder)
   if File.exist?(save_file_path)
      File.delete(save_file_path)
   end
   save_file = File.new(save_file_path,"w+")
   o_index = 2
   size_results.each do |o|
      result_str = "#{' ' * o.space_count}├── #{o.folder_name.split('/').last}    #{SizeResult.handleSize(o.size)}(#{o.size})"
      save_file.puts(result_str)
   end
   save_file.close
   puts "分析结果已经保存为文件,位置为:\n\033[32m#{save_file_path}\033[0m"
end
traverse_dir(sort_by_obj_files_map,file_path,results,size_files,space_index) click to toggle source
# File lib/itools/link_map.rb, line 317
def self.traverse_dir(sort_by_obj_files_map,file_path,results,size_files,space_index)
   s_result = SizeResult.new
   s_result.folder_name = file_path  
   space_index = space_index + 2 
   file_name_arr = [] #盛放计算过的类
   Find.find(file_path) do |file|
      # 不包含图片
      if File.file?(file) && !(File.extname(file) =~ /(png|gif|jpg|bmp|jpeg)/)
         file_name = File.basename(file,".*")
         if !file_name_arr.include?(file_name) && sort_by_obj_files_map[file_name] #没有已经计算过
            s_result.size = s_result.size + sort_by_obj_files_map[file_name][0].o_size
            file_name_arr << file_name
         end
      elsif File::directory?(file) && file != file_path
         traverse_dir(sort_by_obj_files_map,file,results,size_files,space_index)
      end
   end
   if s_result.size > 0 && !size_files.include?(s_result.folder_name)
      s_result.space_count = space_index
      results << s_result
      size_files << s_result.folder_name
   end
end

Public Instance Methods

get_arch(str) click to toggle source

get arch

# File lib/itools/link_map.rb, line 87
def get_arch(str)
   splitparam = str.split(" ")
   @l_arch = splitparam.last
end
get_o_name(str) click to toggle source

得到o_ame 有待优化,可以使用正则表达式处理TODO

# File lib/itools/link_map.rb, line 66
def get_o_name(str)
   temp_arr = str.split("(")
   if temp_arr.size > 1
      temp_arr[1].split(".o)")[0]
   else
      return temp_arr[0].split(".o")[0]
   end
end
get_path(str) click to toggle source

得到path

# File lib/itools/link_map.rb, line 49
def get_path(str)
   splitparam = str.split(" ")
   @l_path = splitparam.last
end
handle_l_sym_map() click to toggle source

处理symbols的数组,把symbols转换成hashmap

# File lib/itools/link_map.rb, line 116
def handle_l_sym_map
   @l_sym_map = @l_symbols.group_by(&:s_file_serial_number)
   if @l_sym_map.include?(-1)
      puts "移除无用元素"
      @l_sym_map.delete(-1)
   end
end
handle_map() click to toggle source

处理link map file

# File lib/itools/link_map.rb, line 124
def handle_map
   handle_method_name = ""
   File.read(@l_name).each_line do |line|
      if line[0] == "#"
         if line.include?("Path:")
            handle_method_name =  "get_path"
            puts "处理path..."
         elsif line.include?("Arch:")
            handle_method_name = "get_arch"
            puts "处理Arch..."
         elsif line.include?("Object files")
            handle_method_name = "handle_ojbect_files"
            puts "处理Object files..."
         elsif line.include?("Sections")
            handle_method_name = "handle_sections"
            puts "处理Sections..."
         elsif line.include?("Symbols:")   #symbols:和Dead Stripped Symbols处理一样
         #   这里不处理Dead Stripped Symbols
            if line.delete('#').strip.include?("Dead Stripped Symbols")
               puts "不处理处理#{line.delete('#').strip}..."
               break
            end
            puts "处理#{line.delete('#').strip}..."
            handle_method_name = "handle_symbols"
         end
      end
      self.send(handle_method_name, line)

   end
end
handle_ojbect_files(str) click to toggle source

处理object文件

# File lib/itools/link_map.rb, line 54
def handle_ojbect_files(str)
   tempSplit = str.split("]")
   if tempSplit.size > 1
      obj_file = ObjectFile.new
      obj_file.serial_number = tempSplit[0].delete("[").strip.to_i   #设置serial_number
      obj_file.file_path = tempSplit[1].strip
      obj_file.file_name = tempSplit[1].split("/").last.chomp
      obj_file.o_name = get_o_name(tempSplit[1].split("/").last.chomp)
      l_obj_files << obj_file
   end
end
handle_sections(str) click to toggle source

处理sections

# File lib/itools/link_map.rb, line 75
def handle_sections(str)
   sectionSplit = str.split(" ")
   if sectionSplit.size == 4
      section = Sections.new
      section.address = sectionSplit[0]
      section.size = sectionSplit[1]
      section.segment = sectionSplit[2]
      section.section = sectionSplit[3]
      l_sections << section
   end
end
handle_symbols(str) click to toggle source

处理Symbols

# File lib/itools/link_map.rb, line 92
def handle_symbols(str)
   # 字符编码产生的异常处理
   begin
      symbolsSplit = str.split("\t")
   rescue => exception
      return
   end
   if symbolsSplit.size > 2
      symbol = Symbols.new
      symbol.s_address = symbolsSplit[0]
      symbol.s_size = symbolsSplit[1]
      # 获取编号和名字
      serial_name_str = symbolsSplit[2]
      file_and_name_split = serial_name_str.split("]")
      if file_and_name_split.size > 1
         symbol.s_file_serial_number = file_and_name_split[0].delete("[").strip.to_i  #设置文件编号
         symbol.s_name = file_and_name_split[1]
      end

      l_symbols << symbol
   else
   end
end