├── linkMapInfo.txt ├── README.md ├── linkMapStatistic.py └── linkMap.py /linkMapInfo.txt: -------------------------------------------------------------------------------- 1 | total:all 2 | someThingBeginWithA:a 3 | someThingBeginWithB:ba,be,bc 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # LinkMap-Analyse 2 | a python code for Analyse .linkmap file; 3 | get .xlxs for the size you want know. 4 | before you use, comfirm you had install xlsxwriter. 5 | put the info you want know in the linkMapInfo.txt and run .py; 6 | -------------------------------------------------------------------------------- /linkMapStatistic.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | #coding:utf-8 3 | #这个脚本是为了统计 分析出来的linkMap的文件大小 的总和 4 | # 5 | import os,sys,shutil 6 | import xlsxwriter # xlsxwriter 用户生成xlsx文件 7 | from string import Template 8 | 9 | 10 | class sizeFile: 11 | #定义基本属性 12 | moduleName = '' 13 | lastSize = 0 14 | currentSize = 0 15 | #定义构造方法 16 | def __init__(self,n,s,d): 17 | self.moduleName = n 18 | self.lastSize = s 19 | self.currentSize = d 20 | 21 | def show(self): 22 | print("moduleName: %s lastSize: %d currentSize: %d" %(self.moduleName,self.lastSize,self.currentSize)) 23 | 24 | 25 | class sizeMapReader(object): 26 | 27 | def __init__(self, sizemapdir): 28 | super(sizeMapReader, self).__init__() 29 | self.sizemapdir=sizemapdir 30 | 31 | #read objs From linkmapdir 32 | def readObjectFrom(self): 33 | f=open(self.sizemapdir, "r") 34 | arr = [] 35 | for line in f: 36 | if line.find("moduleName:")!=-1 and line.find("lastSize:")!=-1 and line.find("currentSize:")!=-1: 37 | tempStr = line.replace('moduleName:',' ') 38 | tempStr = tempStr.replace('lastSize:',' ') 39 | tempStr = tempStr.replace('currentSize:',' ') 40 | print tempStr 41 | objInfo=tempStr.split(',') 42 | if len(objInfo)==3: 43 | singleFile = sizeFile(objInfo[0],int(objInfo[1]),int(objInfo[2])) 44 | arr.append(singleFile) 45 | f.close 46 | return arr 47 | 48 | def formatSize(kybeSize): 49 | return float('%.2f'%(float(kybeSize) / 1024)) 50 | 51 | if __name__=='__main__': 52 | if len(sys.argv) < 2: 53 | print 'Not enough Params' 54 | sys.exit(0) 55 | 56 | oldDir = sys.argv[1] 57 | newDir = sys.argv[2] 58 | 59 | if oldDir.count('arm64') > 0 and newDir.count('-armv7') > 0: 60 | arm64Dir = oldDir 61 | armv7Dir = newDir 62 | elif newDir.count('arm64') > 0 and oldDir.count('-armv7') > 0: 63 | arm64Dir = newDir 64 | armv7Dir = oldDir 65 | else: 66 | print 'Params error' 67 | sys.exit(0) 68 | 69 | arm64SizeReader = sizeMapReader(arm64Dir) 70 | armv7SizeReader = sizeMapReader(armv7Dir) 71 | arm64Arr = arm64SizeReader.readObjectFrom() 72 | armv7Arr = armv7SizeReader.readObjectFrom() 73 | 74 | dirName = os.path.split(os.path.realpath(__file__))[0] + '/LinkMapOutPut/' + 'linkMapSize.xlsx' 75 | workbook = xlsxwriter.Workbook(dirName) 76 | worksheet = workbook.add_worksheet() 77 | 78 | worksheet.set_column('A:A',13) #设定列的宽度为60像素 79 | worksheet.set_column('B:B',13) 80 | worksheet.set_column('C:C',13) 81 | worksheet.set_column('D:D',13) 82 | worksheet.set_column('E:E',13) 83 | 84 | currentRow = 0 85 | worksheet.write(currentRow, 0, 'Name') 86 | worksheet.write(currentRow, 1, 'lastTotalSize') 87 | worksheet.write(currentRow, 2, 'currentTotalSize') 88 | worksheet.write(currentRow, 3, 'change') 89 | 90 | format_title_add = workbook.add_format() #定义format_title格式对象 91 | format_title_add.set_border(1) #定义format_title对象单元格边框加粗(1像素)的格式 92 | #format_title_add.set_bg_color('#ef7175') #定义format_title对象单元格背景颜色为'#cccccc'的格式 93 | 94 | for obj64 in arm64Arr : 95 | obj64.show() 96 | for objv7 in armv7Arr : 97 | if objv7.moduleName == obj64.moduleName: 98 | currentRow = currentRow + 1 99 | worksheet.write(currentRow, 0, obj64.moduleName, format_title_add) 100 | worksheet.write_number(currentRow, 1, formatSize(obj64.lastSize + objv7.lastSize), format_title_add) 101 | worksheet.write_number(currentRow, 2, formatSize(obj64.currentSize + objv7.currentSize), format_title_add) 102 | worksheet.write_number(currentRow, 3, formatSize(int(obj64.currentSize + objv7.currentSize) - int(obj64.lastSize + objv7.lastSize)), format_title_add) 103 | print("moduleName: %s lastSize: %d currentSize: %d hasChanged: %d ." %(obj64.moduleName, formatSize(obj64.lastSize + objv7.lastSize), formatSize(obj64.currentSize + objv7.currentSize), formatSize(int(obj64.currentSize + objv7.currentSize) - int(obj64.lastSize + objv7.lastSize)) )) 104 | workbook.close() 105 | 106 | 107 | 108 | -------------------------------------------------------------------------------- /linkMap.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | #coding:utf-8 3 | 4 | #这个脚本是为了分析linkMap的文件大小 5 | #代码参考 https://github.com/sumx/LinkMapReader 6 | # 7 | 8 | import os,sys,shutil 9 | import xlsxwriter # xlsxwriter 用户生成xlsx文件 10 | from string import Template 11 | 12 | class linkFile: 13 | #定义基本属性 14 | name = '' 15 | size = 0 16 | diff = 0 17 | #定义构造方法 18 | def __init__(self,n,s,d): 19 | self.name = n 20 | self.size = s 21 | self.diff = d 22 | 23 | def show(self): 24 | print("name: %s size: %d diff: %d" %(self.name,self.size,self.diff)) 25 | 26 | class SymbolReader(object): 27 | 28 | def __init__(self, linkmapdir): 29 | super(SymbolReader, self).__init__() 30 | self.linkmapdir=linkmapdir 31 | 32 | #read objs From linkmapdir 33 | def readObjectFrom(self): 34 | f=open(self.linkmapdir, "r") 35 | shouldSkip=True 36 | dic={} 37 | for line in f: 38 | if line.find("Object files:")!=-1 and shouldSkip: 39 | shouldSkip=False 40 | continue 41 | else: 42 | if line.find("# Sections:")!=-1: 43 | break 44 | else: 45 | objInfo=line.split(']') 46 | if len(objInfo)==2: 47 | index=objInfo[0]+']' 48 | name=objInfo[1] 49 | dic[index.strip()]=name.strip() 50 | f.close 51 | return dic 52 | 53 | #read linkmapdir 54 | def readSymbolsInfoFrom(self): 55 | f=open(self.linkmapdir, "r") 56 | shouldSkip=0 57 | dic={} 58 | for line in f: 59 | if line.find("# Address Size File Name")!=-1 and shouldSkip==0: 60 | shouldSkip=1 61 | continue 62 | else: 63 | if shouldSkip==1: 64 | symbolInfo=line.split(" ") 65 | if len(symbolInfo)==3: 66 | offset=symbolInfo[0].strip() 67 | symbolSize=symbolInfo[1].strip() 68 | leftStr=symbolInfo[2] 69 | indexAndSymbolName=leftStr.split('] ') 70 | if len(indexAndSymbolName) >= 2: 71 | index=indexAndSymbolName[0]+"]".strip() 72 | symbolName=indexAndSymbolName[1].strip() 73 | if index in dic: 74 | dic[index].append({"Address":offset,"size":symbolSize,"index":index,"name":symbolName}) 75 | else: 76 | dic[index]=[]; 77 | dic[index].append({"Address":offset,"size":symbolSize,"index":index,"name":symbolName}) 78 | f.close 79 | return dic 80 | 81 | def generateSymbolSize(self,item): 82 | sum=0 83 | for sinfo in item: 84 | sum=sum+int(sinfo["size"],16) 85 | return sum 86 | 87 | def generateObjSizeDetail(self): 88 | objs=self.readObjectFrom() 89 | symbols=self.readSymbolsInfoFrom() 90 | tsum=0 91 | tempArr = [] 92 | for key in sorted(symbols.keys()): 93 | item=symbols[key] 94 | tsum=tsum+self.generateSymbolSize(item) 95 | sum=0 96 | for sinfo in item: 97 | sum=sum+int(sinfo["size"],16) 98 | objNameSplited=objs[key].split(os.sep) 99 | linkfile = linkFile(objNameSplited[len(objNameSplited)-1], sum, 0) 100 | tempArr.append(linkfile) 101 | print "linkMap analyze has Done!" 102 | return tempArr 103 | 104 | def analyzeLinkMap(dir): 105 | if os.path.isfile(dir) == True: 106 | reader=SymbolReader(dir) 107 | fileArr = reader.generateObjSizeDetail() 108 | return fileArr 109 | else: 110 | print "should config linkmap path" 111 | sys.exit(0) 112 | 113 | #排序用的方法 114 | def sizeSort(a,b): 115 | if isinstance(a, linkFile) and isinstance(b, linkFile): 116 | if int(a.size) < int(b.size): 117 | return 1 118 | if int(a.size) > int(b.size): 119 | return -1 120 | return 0 121 | 122 | def diffSort(a,b): 123 | if isinstance(a, linkFile) and isinstance(b, linkFile): 124 | if int(a.diff) < int(b.diff): 125 | return 1 126 | if int(a.diff) > int(b.diff): 127 | return -1 128 | return 0 129 | 130 | 131 | #数组去重 132 | def deplicateArr(oldArr): 133 | newArr = [] 134 | for oldId in oldArr: 135 | if oldId not in newArr: 136 | if isinstance(oldId, linkFile): 137 | isContain = False 138 | for newId in newArr: 139 | if isinstance(newId, linkFile): 140 | if oldId.name == newId.name and oldId.size == newId.size: 141 | isContain = True 142 | if not isContain: 143 | newArr.append(oldId) 144 | return newArr 145 | 146 | 147 | #分析并输出两次迭代的变化 148 | def diffArray(oldArr,newArr,dirName,moduleName): 149 | 150 | workbook = xlsxwriter.Workbook(dirName) 151 | worksheet = workbook.add_worksheet() 152 | 153 | worksheet.set_column('A:A',60) #设定列的宽度为60像素 154 | worksheet.set_column('B:B',10) 155 | worksheet.set_column('C:C',10) 156 | 157 | currentRow = 0 158 | title = '' 159 | worksheet.write(currentRow, 0, 'Name') 160 | worksheet.write(currentRow, 1, 'Size') 161 | worksheet.write(currentRow, 2, 'Diff') 162 | 163 | #用来取差集 来找出新增/删除 的文件 164 | oldCommonArr = [] 165 | newCommonArr = [] 166 | 167 | sortArr = [] #用来排序用的数组 168 | tempArr = [] #没去重的数组 169 | for oldFile in oldArr: 170 | for newFile in newArr: 171 | if oldFile.name == newFile.name: 172 | oldCommonArr.append(oldFile) 173 | newCommonArr.append(newFile) 174 | commonfile = linkFile(newFile.name, newFile.size, newFile.size - oldFile.size) 175 | tempArr.append(commonfile) 176 | 177 | sortArr = deplicateArr(tempArr) 178 | oldCommonArr = deplicateArr(oldCommonArr) 179 | newCommonArr = deplicateArr(newCommonArr) 180 | 181 | totalOldSize = 0 182 | totalNewSize = 0 183 | for oldFile in oldArr: 184 | totalOldSize += int(oldFile.size) 185 | 186 | for newFile in newArr: 187 | totalNewSize += int(newFile.size) 188 | 189 | format_title_add = workbook.add_format() #定义format_title格式对象 190 | format_title_add.set_border(1) #定义format_title对象单元格边框加粗(1像素)的格式 191 | format_title_add.set_bg_color('#ef7175') #定义format_title对象单元格背景颜色为'#cccccc'的格式 192 | 193 | format_title_del = workbook.add_format() #定义format_title格式对象 194 | format_title_del.set_border(1) #定义format_title对象单元格边框加粗(1像素)的格式 195 | format_title_del.set_bg_color('#23b6e7') #定义format_title对象单元格背景颜色为'#cccccc'的格式 196 | 197 | format_title_topTen = workbook.add_format() #定义format_title格式对象 198 | format_title_topTen.set_border(1) #定义format_title对象单元格边框加粗(1像素)的格式 199 | format_title_topTen.set_bg_color('#fea976') #定义format_title对象单元格背景颜色为'#cccccc'的格式 200 | 201 | format_title_change = workbook.add_format() #定义format_title格式对象 202 | format_title_change.set_border(1) #定义format_title对象单元格边框加粗(1像素)的格式 203 | format_title_change.set_bg_color('#cff7d5') #定义format_title对象单元格背景颜色为'#cccccc'的格式 204 | 205 | currentRow = currentRow + 2 206 | title = 'old totalSize is ' + str(totalOldSize ) + ' new totalSize is ' + str(totalNewSize) + ' has Changed ' + str(totalNewSize - totalOldSize) 207 | print("%s: 上次迭代大小为%.2fkb ,此次迭代大小为%.2fkb, 变化了%2.fkb" %(dirName, totalOldSize / 1024, totalNewSize / 1024 , (totalNewSize - totalOldSize) / 1024) ) 208 | resultStr = 'moduleName:' + moduleName + ',lastSize:' + str(totalOldSize / 1024) + ',currentSize:' + str(totalNewSize / 1024) 209 | worksheet.write(currentRow, 0, title) 210 | 211 | # 新增的文件 212 | addArr = list(set(newArr).difference(set(newCommonArr))) # newrr中有而newCommonArr中没有的 213 | 214 | currentRow = currentRow + 2 215 | title = 'Add total ' + str(len(addArr)) + ' files' 216 | worksheet.write(currentRow, 0, title) 217 | for addFile in addArr: 218 | currentRow = currentRow + 1 219 | worksheet.write(currentRow, 0, str(addFile.name),format_title_add) 220 | worksheet.write_number(currentRow, 1, int(addFile.size),format_title_add) 221 | worksheet.write_number(currentRow, 2, int(addFile.size),format_title_add) 222 | 223 | # 被删除的文件 224 | delArr = list(set(oldArr).difference(set(oldCommonArr))) # oldArr中有而oldCommonArr中没有的 225 | 226 | currentRow = currentRow + 2 227 | title = 'delete total ' + str(len(delArr)) + ' files' 228 | worksheet.write(currentRow, 0, title) 229 | 230 | for delFile in delArr: 231 | currentRow = currentRow + 1 232 | worksheet.write(currentRow, 0, delFile.name,format_title_del) 233 | worksheet.write_number(currentRow, 1, int(delFile.size),format_title_del) 234 | worksheet.write_number(currentRow, 2, 0 - int(delFile.size),format_title_del) 235 | 236 | if len(sortArr) > 10 : 237 | #按大小排序 238 | currentRow = currentRow + 2 239 | worksheet.write(currentRow, 0, "the Size Top10") 240 | sortArr.sort(cmp = sizeSort) 241 | 242 | for x in xrange(1,10): 243 | item = sortArr[x] 244 | currentRow = currentRow + 1 245 | worksheet.write(currentRow, 0, item.name, format_title_topTen) 246 | worksheet.write_number(currentRow, 1, int(item.size), format_title_topTen) 247 | worksheet.write_number(currentRow, 2, int(item.diff), format_title_topTen) 248 | 249 | #按变化排序 250 | currentRow = currentRow + 2 251 | worksheet.write(currentRow, 0, "the Change Top10") 252 | sortArr.sort(cmp = diffSort) 253 | 254 | for x in xrange(1,10): 255 | item = sortArr[x] 256 | currentRow = currentRow + 1 257 | worksheet.write(currentRow, 0, item.name, format_title_topTen) 258 | worksheet.write_number(currentRow, 1, int(item.size), format_title_topTen) 259 | worksheet.write_number(currentRow, 2, int(item.diff), format_title_topTen) 260 | 261 | currentRow = currentRow + 2 262 | title = 'all the ' + str(len(sortArr)) + ' Change files' 263 | worksheet.write(currentRow, 0, title) 264 | 265 | for row_date in sortArr: 266 | currentRow = currentRow + 1 267 | worksheet.write(currentRow, 0, row_date.name, format_title_change) 268 | worksheet.write_number(currentRow, 1, int(row_date.size), format_title_change) 269 | worksheet.write_number(currentRow, 2, int(row_date.diff), format_title_change) 270 | 271 | #print dirName + 'Excel is ok!' 272 | workbook.close() 273 | return resultStr 274 | 275 | 276 | def getTheArr(arr, startStrArr): 277 | theArr = [] 278 | for file in arr : 279 | for startStr in startStrArr : 280 | fileName = str(file.name) 281 | if fileName.count(startStr) > 0: 282 | theArr.append(file) 283 | 284 | return theArr 285 | 286 | def getTheReport(oldArr, newArr, startStrArr, fileName, moduleName): 287 | oldAirArr = getTheArr(oldArr, startStrArr) 288 | newAirArr = getTheArr(newArr, startStrArr) 289 | fileName = os.path.split(os.path.realpath(__file__))[0] + '/LinkMapOutPut/' + fileName #脚本所在位置的目录 290 | resultStr = diffArray(oldAirArr, newAirArr, fileName, moduleName) 291 | return resultStr 292 | 293 | if __name__=='__main__': 294 | if len(sys.argv) < 2: 295 | print 'Not enough Params' 296 | sys.exit(0) 297 | 298 | 299 | oldDir = sys.argv[1] 300 | newDir = sys.argv[2] 301 | 302 | if not os.path.isfile(newDir) : 303 | print 'No valid new File' 304 | sys.exit(0) 305 | 306 | cpuTypeSTr = '' 307 | if newDir.count('arm64') > 0: 308 | cpuTypeSTr = '-arm64' 309 | elif newDir.count('-armv7') > 0: 310 | cpuTypeSTr = '-armv7' 311 | else: 312 | pass 313 | 314 | if not os.path.isfile(oldDir): 315 | print 'No valid old File' 316 | if os.path.isfile(newDir) : 317 | # shutil.move(newDir,'' + cpuTypeSTr + '.txt') #将新的linkMap文件放入旧的中,替换掉(用来自动化执行) 318 | print 'had moved New Dir 2 Old Dir' 319 | sys.exit(0) 320 | 321 | oldArr = analyzeLinkMap(oldDir) 322 | newArr = analyzeLinkMap(newDir) 323 | resultStrArr = [] 324 | 325 | infoTxt = open(os.path.split(os.path.realpath(__file__))[0] + '/linkMapInfo.txt','rw') 326 | for line in infoTxt.readlines(): 327 | print line 328 | infoArr = line.split(':') 329 | if len(infoArr) >= 2: 330 | print infoArr 331 | nameStr = infoArr[0] 332 | startStrArr = [''] 333 | startStr = infoArr[1] 334 | startStr = startStr.strip('\n') 335 | if startStr == 'all': 336 | startStrArr = [''] 337 | elif ',' in startStr: 338 | startStrArr = startStr.split(',') 339 | else: 340 | startStrArr = [startStr] 341 | 342 | resultStrArr.append(getTheReport(oldArr, newArr, startStrArr, nameStr + cpuTypeSTr + '.xlsx', nameStr)) 343 | 344 | f = open(os.path.split(os.path.realpath(__file__))[0] + '/LinkMapOutPut/' + cpuTypeSTr + '.txt','w') 345 | for resultStr in resultStrArr: 346 | print resultStr 347 | f.write(resultStr + '\n') 348 | f.close 349 | 350 | #shutil.move(newDir, oldDir) #将新的linkMap文件放入旧的中,替换掉(用来自动化执行) 351 | #print 'had moved New Dir 2 old Dir' 352 | --------------------------------------------------------------------------------