]> git.proxmox.com Git - mirror_edk2.git/blame - BaseTools/Scripts/MemoryProfileSymbolGen.py
BaseTools: Clean up source files
[mirror_edk2.git] / BaseTools / Scripts / MemoryProfileSymbolGen.py
CommitLineData
1d9869f9
SZ
1##\r
2# Generate symbal for memory profile info.\r
3#\r
4# This tool depends on DIA2Dump.exe (VS) or nm (gcc) to parse debug entry.\r
5#\r
f7496d71 6# Copyright (c) 2016 - 2018, Intel Corporation. All rights reserved.<BR>\r
1d9869f9
SZ
7# This program and the accompanying materials are licensed and made available under\r
8# the terms and conditions of the BSD License that accompanies this distribution.\r
9# The full text of the license may be found at\r
10# http://opensource.org/licenses/bsd-license.php.\r
11#\r
12# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
13# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
14#\r
15##\r
16\r
72443dd2 17from __future__ import print_function\r
1d9869f9
SZ
18import os\r
19import re\r
20import sys\r
21from optparse import OptionParser\r
22\r
d84577e5 23versionNumber = "1.1"\r
f7496d71 24__copyright__ = "Copyright (c) 2016 - 2018, Intel Corporation. All rights reserved."\r
1d9869f9
SZ
25\r
26class Symbols:\r
27 def __init__(self):\r
28 self.listLineAddress = []\r
29 self.pdbName = ""\r
30 # Cache for function\r
31 self.functionName = ""\r
32 # Cache for line\r
33 self.sourceName = ""\r
34\r
35\r
36 def getSymbol (self, rva):\r
37 index = 0\r
38 lineName = 0\r
39 sourceName = "??"\r
40 while index + 1 < self.lineCount :\r
41 if self.listLineAddress[index][0] <= rva and self.listLineAddress[index + 1][0] > rva :\r
42 offset = rva - self.listLineAddress[index][0]\r
43 functionName = self.listLineAddress[index][1]\r
44 lineName = self.listLineAddress[index][2]\r
45 sourceName = self.listLineAddress[index][3]\r
46 if lineName == 0 :\r
47 return " (" + self.listLineAddress[index][1] + "() - " + ")"\r
48 else :\r
49 return " (" + self.listLineAddress[index][1] + "() - " + sourceName + ":" + str(lineName) + ")"\r
50 index += 1\r
51\r
52 return " (unknown)"\r
53\r
54 def parse_debug_file(self, driverName, pdbName):\r
55 if cmp (pdbName, "") == 0 :\r
56 return\r
57 self.pdbName = pdbName;\r
58\r
59 try:\r
60 nmCommand = "nm"\r
61 nmLineOption = "-l"\r
72443dd2 62 print("parsing (debug) - " + pdbName)\r
1d9869f9
SZ
63 os.system ('%s %s %s > nmDump.line.log' % (nmCommand, nmLineOption, pdbName))\r
64 except :\r
72443dd2 65 print('ERROR: nm command not available. Please verify PATH')\r
1d9869f9
SZ
66 return\r
67\r
68 #\r
69 # parse line\r
70 #\r
71 linefile = open("nmDump.line.log")\r
72 reportLines = linefile.readlines()\r
73 linefile.close()\r
74\r
f7496d71 75 # 000113ca T AllocatePool c:\home\edk-ii\MdePkg\Library\UefiMemoryAllocationLib\MemoryAllocationLib.c:399\r
d84577e5 76 patchLineFileMatchString = "([0-9a-fA-F]*)\s+[T|D|t|d]\s+(\w+)\s*((?:[a-zA-Z]:)?[\w+\-./_a-zA-Z0-9\\\\]*):?([0-9]*)"\r
1d9869f9
SZ
77\r
78 for reportLine in reportLines:\r
79 #print "check - " + reportLine\r
80 match = re.match(patchLineFileMatchString, reportLine)\r
81 if match is not None:\r
82 #print "match - " + reportLine[:-1]\r
83 #print "0 - " + match.group(0)\r
84 #print "1 - " + match.group(1)\r
85 #print "2 - " + match.group(2)\r
86 #print "3 - " + match.group(3)\r
87 #print "4 - " + match.group(4)\r
88\r
89 rva = int (match.group(1), 16)\r
90 functionName = match.group(2)\r
91 sourceName = match.group(3)\r
92 if cmp (match.group(4), "") != 0 :\r
93 lineName = int (match.group(4))\r
94 else :\r
95 lineName = 0\r
96 self.listLineAddress.append ([rva, functionName, lineName, sourceName])\r
97\r
98 self.lineCount = len (self.listLineAddress)\r
99\r
100 self.listLineAddress = sorted(self.listLineAddress, key=lambda symbolAddress:symbolAddress[0])\r
101\r
102 #for key in self.listLineAddress :\r
103 #print "rva - " + "%x"%(key[0]) + ", func - " + key[1] + ", line - " + str(key[2]) + ", source - " + key[3]\r
104\r
105 def parse_pdb_file(self, driverName, pdbName):\r
106 if cmp (pdbName, "") == 0 :\r
107 return\r
108 self.pdbName = pdbName;\r
109\r
110 try:\r
111 #DIA2DumpCommand = "\"C:\\Program Files (x86)\Microsoft Visual Studio 14.0\\DIA SDK\\Samples\\DIA2Dump\\x64\\Debug\\Dia2Dump.exe\""\r
112 DIA2DumpCommand = "Dia2Dump.exe"\r
113 #DIA2SymbolOption = "-p"\r
114 DIA2LinesOption = "-l"\r
72443dd2 115 print("parsing (pdb) - " + pdbName)\r
1d9869f9
SZ
116 #os.system ('%s %s %s > DIA2Dump.symbol.log' % (DIA2DumpCommand, DIA2SymbolOption, pdbName))\r
117 os.system ('%s %s %s > DIA2Dump.line.log' % (DIA2DumpCommand, DIA2LinesOption, pdbName))\r
118 except :\r
72443dd2 119 print('ERROR: DIA2Dump command not available. Please verify PATH')\r
1d9869f9
SZ
120 return\r
121\r
122 #\r
123 # parse line\r
124 #\r
125 linefile = open("DIA2Dump.line.log")\r
126 reportLines = linefile.readlines()\r
127 linefile.close()\r
128\r
129 # ** GetDebugPrintErrorLevel\r
f7496d71
LG
130 # line 32 at [0000C790][0001:0000B790], len = 0x3 c:\home\edk-ii\mdepkg\library\basedebugprinterrorlevellib\basedebugprinterrorlevellib.c (MD5: 687C0AE564079D35D56ED5D84A6164CC)\r
131 # line 36 at [0000C793][0001:0000B793], len = 0x5\r
132 # line 37 at [0000C798][0001:0000B798], len = 0x2\r
1d9869f9
SZ
133\r
134 patchLineFileMatchString = "\s+line ([0-9]+) at \[([0-9a-fA-F]{8})\]\[[0-9a-fA-F]{4}\:[0-9a-fA-F]{8}\], len = 0x[0-9a-fA-F]+\s*([\w+\-\:./_a-zA-Z0-9\\\\]*)\s*"\r
135 patchLineFileMatchStringFunc = "\*\*\s+(\w+)\s*"\r
136\r
137 for reportLine in reportLines:\r
138 #print "check line - " + reportLine\r
139 match = re.match(patchLineFileMatchString, reportLine)\r
140 if match is not None:\r
141 #print "match - " + reportLine[:-1]\r
142 #print "0 - " + match.group(0)\r
143 #print "1 - " + match.group(1)\r
144 #print "2 - " + match.group(2)\r
145 if cmp (match.group(3), "") != 0 :\r
146 self.sourceName = match.group(3)\r
147 sourceName = self.sourceName\r
148 functionName = self.functionName\r
149\r
150 rva = int (match.group(2), 16)\r
151 lineName = int (match.group(1))\r
152 self.listLineAddress.append ([rva, functionName, lineName, sourceName])\r
153 else :\r
154 match = re.match(patchLineFileMatchStringFunc, reportLine)\r
155 if match is not None:\r
156 self.functionName = match.group(1)\r
157\r
158 self.lineCount = len (self.listLineAddress)\r
159 self.listLineAddress = sorted(self.listLineAddress, key=lambda symbolAddress:symbolAddress[0])\r
160\r
161 #for key in self.listLineAddress :\r
162 #print "rva - " + "%x"%(key[0]) + ", func - " + key[1] + ", line - " + str(key[2]) + ", source - " + key[3]\r
163\r
164class SymbolsFile:\r
165 def __init__(self):\r
166 self.symbolsTable = {}\r
167\r
168symbolsFile = ""\r
169\r
170driverName = ""\r
171rvaName = ""\r
172symbolName = ""\r
173\r
174def getSymbolName(driverName, rva):\r
175 global symbolsFile\r
176\r
177 #print "driverName - " + driverName\r
178\r
179 try :\r
180 symbolList = symbolsFile.symbolsTable[driverName]\r
181 if symbolList is not None:\r
182 return symbolList.getSymbol (rva)\r
183 else:\r
184 return " (???)"\r
185 except Exception:\r
186 return " (???)"\r
187\r
188def processLine(newline):\r
189 global driverName\r
190 global rvaName\r
191\r
192 driverPrefixLen = len("Driver - ")\r
193 # get driver name\r
ccaa7754 194 if cmp(newline[0:driverPrefixLen], "Driver - ") == 0 :\r
1d9869f9
SZ
195 driverlineList = newline.split(" ")\r
196 driverName = driverlineList[2]\r
197 #print "Checking : ", driverName\r
198\r
199 # EDKII application output\r
200 pdbMatchString = "Driver - \w* \(Usage - 0x[0-9a-fA-F]+\) \(Pdb - ([:\-.\w\\\\/]*)\)\s*"\r
201 pdbName = ""\r
202 match = re.match(pdbMatchString, newline)\r
203 if match is not None:\r
204 #print "match - " + newline\r
205 #print "0 - " + match.group(0)\r
206 #print "1 - " + match.group(1)\r
207 pdbName = match.group(1)\r
208 #print "PDB - " + pdbName\r
209\r
210 symbolsFile.symbolsTable[driverName] = Symbols()\r
211\r
212 if cmp (pdbName[-3:], "pdb") == 0 :\r
213 symbolsFile.symbolsTable[driverName].parse_pdb_file (driverName, pdbName)\r
214 else :\r
215 symbolsFile.symbolsTable[driverName].parse_debug_file (driverName, pdbName)\r
216\r
ccaa7754 217 elif cmp(newline, "") == 0 :\r
1d9869f9
SZ
218 driverName = ""\r
219\r
220 # check entry line\r
221 if newline.find ("<==") != -1 :\r
222 entry_list = newline.split(" ")\r
223 rvaName = entry_list[4]\r
224 #print "rva : ", rvaName\r
225 symbolName = getSymbolName (driverName, int(rvaName, 16))\r
226 else :\r
227 rvaName = ""\r
228 symbolName = ""\r
229\r
ccaa7754 230 if cmp(rvaName, "") == 0 :\r
1d9869f9
SZ
231 return newline\r
232 else :\r
233 return newline + symbolName\r
234\r
235def myOptionParser():\r
236 usage = "%prog [--version] [-h] [--help] [-i inputfile [-o outputfile]]"\r
237 Parser = OptionParser(usage=usage, description=__copyright__, version="%prog " + str(versionNumber))\r
238 Parser.add_option("-i", "--inputfile", dest="inputfilename", type="string", help="The input memory profile info file output from MemoryProfileInfo application in MdeModulePkg")\r
239 Parser.add_option("-o", "--outputfile", dest="outputfilename", type="string", help="The output memory profile info file with symbol, MemoryProfileInfoSymbol.txt will be used if it is not specified")\r
240\r
241 (Options, args) = Parser.parse_args()\r
242 if Options.inputfilename is None:\r
243 Parser.error("no input file specified")\r
244 if Options.outputfilename is None:\r
245 Options.outputfilename = "MemoryProfileInfoSymbol.txt"\r
246 return Options\r
247\r
248def main():\r
249 global symbolsFile\r
250 global Options\r
251 Options = myOptionParser()\r
252\r
253 symbolsFile = SymbolsFile()\r
254\r
255 try :\r
256 file = open(Options.inputfilename)\r
257 except Exception:\r
72443dd2 258 print("fail to open " + Options.inputfilename)\r
1d9869f9
SZ
259 return 1\r
260 try :\r
261 newfile = open(Options.outputfilename, "w")\r
262 except Exception:\r
72443dd2 263 print("fail to open " + Options.outputfilename)\r
1d9869f9
SZ
264 return 1\r
265\r
266 try:\r
0d1f5b2b 267 while True:\r
1d9869f9
SZ
268 line = file.readline()\r
269 if not line:\r
270 break\r
271 newline = line[:-1]\r
272\r
273 newline = processLine(newline)\r
274\r
275 newfile.write(newline)\r
276 newfile.write("\n")\r
277 finally:\r
278 file.close()\r
279 newfile.close()\r
280\r
281if __name__ == '__main__':\r
282 sys.exit(main())\r