]>
Commit | Line | Data |
---|---|---|
79e4f2a5 RN |
1 | #!/usr/bin/python\r |
2 | \r | |
3 | #\r | |
26cfe2c6 | 4 | # Copyright 2014 Apple Inc. All rights reserved.\r |
79e4f2a5 | 5 | #\r |
e3ba31da | 6 | # SPDX-License-Identifier: BSD-2-Clause-Patent\r |
79e4f2a5 RN |
7 | #\r |
8 | \r | |
9 | import lldb\r | |
10 | import os\r | |
11 | import uuid\r | |
12 | import string\r | |
13 | import commands\r | |
14 | import optparse\r | |
15 | import shlex\r | |
16 | \r | |
17 | guid_dict = {}\r | |
18 | \r | |
19 | \r | |
20 | def EFI_GUID_TypeSummary (valobj,internal_dict):\r | |
21 | """ Type summary for EFI GUID, print C Name if known\r | |
22 | """\r | |
23 | # typedef struct {\r | |
24 | # UINT32 Data1;\r | |
25 | # UINT16 Data2;\r | |
26 | # UINT16 Data3;\r | |
27 | # UINT8 Data4[8];\r | |
28 | # } EFI_GUID;\r | |
29 | SBError = lldb.SBError()\r | |
30 | \r | |
31 | data1_val = valobj.GetChildMemberWithName('Data1')\r | |
32 | data1 = data1_val.GetValueAsUnsigned(0)\r | |
33 | data2_val = valobj.GetChildMemberWithName('Data2')\r | |
34 | data2 = data2_val.GetValueAsUnsigned(0)\r | |
35 | data3_val = valobj.GetChildMemberWithName('Data3')\r | |
36 | data3 = data3_val.GetValueAsUnsigned(0)\r | |
37 | str = "%x-%x-%x-" % (data1, data2, data3)\r | |
38 | \r | |
39 | data4_val = valobj.GetChildMemberWithName('Data4')\r | |
40 | for i in range (data4_val.num_children):\r | |
41 | if i == 2:\r | |
42 | str +='-'\r | |
43 | str += "%02x" % data4_val.GetChildAtIndex(i).data.GetUnsignedInt8(SBError, 0)\r | |
44 | \r | |
45 | return guid_dict.get (str.upper(), '')\r | |
46 | \r | |
47 | \r | |
48 | \r | |
49 | EFI_STATUS_Dict = {\r | |
50 | (0x8000000000000000 | 1): "Load Error",\r | |
51 | (0x8000000000000000 | 2): "Invalid Parameter",\r | |
52 | (0x8000000000000000 | 3): "Unsupported",\r | |
53 | (0x8000000000000000 | 4): "Bad Buffer Size",\r | |
54 | (0x8000000000000000 | 5): "Buffer Too Small",\r | |
55 | (0x8000000000000000 | 6): "Not Ready",\r | |
56 | (0x8000000000000000 | 7): "Device Error",\r | |
57 | (0x8000000000000000 | 8): "Write Protected",\r | |
58 | (0x8000000000000000 | 9): "Out of Resources",\r | |
59 | (0x8000000000000000 | 10): "Volume Corrupt",\r | |
60 | (0x8000000000000000 | 11): "Volume Full",\r | |
61 | (0x8000000000000000 | 12): "No Media",\r | |
62 | (0x8000000000000000 | 13): "Media changed",\r | |
63 | (0x8000000000000000 | 14): "Not Found",\r | |
64 | (0x8000000000000000 | 15): "Access Denied",\r | |
65 | (0x8000000000000000 | 16): "No Response",\r | |
66 | (0x8000000000000000 | 17): "No mapping",\r | |
67 | (0x8000000000000000 | 18): "Time out",\r | |
68 | (0x8000000000000000 | 19): "Not started",\r | |
69 | (0x8000000000000000 | 20): "Already started",\r | |
70 | (0x8000000000000000 | 21): "Aborted",\r | |
71 | (0x8000000000000000 | 22): "ICMP Error",\r | |
72 | (0x8000000000000000 | 23): "TFTP Error",\r | |
73 | (0x8000000000000000 | 24): "Protocol Error",\r | |
74 | \r | |
75 | 0 : "Success",\r | |
76 | 1 : "Warning Unknown Glyph",\r | |
77 | 2 : "Warning Delete Failure",\r | |
78 | 3 : "Warning Write Failure",\r | |
79 | 4 : "Warning Buffer Too Small",\r | |
80 | \r | |
81 | (0x80000000 | 1): "Load Error",\r | |
82 | (0x80000000 | 2): "Invalid Parameter",\r | |
83 | (0x80000000 | 3): "Unsupported",\r | |
84 | (0x80000000 | 4): "Bad Buffer Size",\r | |
85 | (0x80000000 | 5): "Buffer Too Small",\r | |
86 | (0x80000000 | 6): "Not Ready",\r | |
87 | (0x80000000 | 7): "Device Error",\r | |
88 | (0x80000000 | 8): "Write Protected",\r | |
89 | (0x80000000 | 9): "Out of Resources",\r | |
90 | (0x80000000 | 10): "Volume Corrupt",\r | |
91 | (0x80000000 | 11): "Volume Full",\r | |
92 | (0x80000000 | 12): "No Media",\r | |
93 | (0x80000000 | 13): "Media changed",\r | |
94 | (0x80000000 | 14): "Not Found",\r | |
95 | (0x80000000 | 15): "Access Denied",\r | |
96 | (0x80000000 | 16): "No Response",\r | |
97 | (0x80000000 | 17): "No mapping",\r | |
98 | (0x80000000 | 18): "Time out",\r | |
99 | (0x80000000 | 19): "Not started",\r | |
100 | (0x80000000 | 20): "Already started",\r | |
101 | (0x80000000 | 21): "Aborted",\r | |
102 | (0x80000000 | 22): "ICMP Error",\r | |
103 | (0x80000000 | 23): "TFTP Error",\r | |
104 | (0x80000000 | 24): "Protocol Error",\r | |
105 | }\r | |
106 | \r | |
107 | def EFI_STATUS_TypeSummary (valobj,internal_dict):\r | |
108 | #\r | |
109 | # Return summary string for EFI_STATUS from dictionary\r | |
110 | #\r | |
111 | Status = valobj.GetValueAsUnsigned(0)\r | |
112 | return EFI_STATUS_Dict.get (Status, '')\r | |
113 | \r | |
114 | \r | |
115 | def EFI_TPL_TypeSummary (valobj,internal_dict):\r | |
116 | #\r | |
117 | # Return TPL values\r | |
118 | #\r | |
119 | \r | |
120 | if valobj.TypeIsPointerType():\r | |
121 | return ""\r | |
122 | \r | |
123 | Tpl = valobj.GetValueAsUnsigned(0)\r | |
124 | if Tpl < 4:\r | |
125 | Str = "%d" % Tpl\r | |
126 | elif Tpl == 6:\r | |
127 | Str = "TPL_DRIVER (Obsolete Concept in edk2)"\r | |
128 | elif Tpl < 8:\r | |
129 | Str = "TPL_APPLICATION"\r | |
130 | if Tpl - 4 > 0:\r | |
131 | Str += " + " + "%d" % (Tpl - 4)\r | |
132 | elif Tpl < 16:\r | |
133 | Str = "TPL_CALLBACK"\r | |
134 | if Tpl - 8 > 0:\r | |
135 | Str += " + " + "%d" % (Tpl - 4)\r | |
136 | elif Tpl < 31:\r | |
137 | Str = "TPL_NOTIFY"\r | |
138 | if Tpl - 16 > 0:\r | |
139 | Str += " + " + "%d" % (Tpl - 4)\r | |
140 | elif Tpl == 31:\r | |
141 | Str = "TPL_HIGH_LEVEL"\r | |
142 | else:\r | |
143 | Str = "Invalid TPL"\r | |
144 | \r | |
145 | return Str\r | |
146 | \r | |
147 | \r | |
148 | def CHAR16_TypeSummary (valobj,internal_dict):\r | |
149 | #\r | |
150 | # Display EFI CHAR16 'unsigned short' as string\r | |
151 | #\r | |
152 | SBError = lldb.SBError()\r | |
153 | Str = ''\r | |
154 | if valobj.TypeIsPointerType():\r | |
155 | if valobj.GetValueAsUnsigned () == 0:\r | |
156 | return "NULL"\r | |
157 | \r | |
158 | # CHAR16 * max string size 1024\r | |
159 | for i in range (1024):\r | |
160 | Char = valobj.GetPointeeData(i,1).GetUnsignedInt16(SBError, 0)\r | |
161 | if SBError.fail or Char == 0:\r | |
162 | break\r | |
163 | Str += unichr (Char)\r | |
164 | Str = 'L"' + Str + '"'\r | |
165 | return Str.encode ('utf-8', 'replace')\r | |
166 | \r | |
167 | if valobj.num_children == 0:\r | |
168 | # CHAR16\r | |
169 | if chr (valobj.unsigned) in string.printable:\r | |
170 | Str = "L'" + unichr (valobj.unsigned) + "'"\r | |
171 | return Str.encode ('utf-8', 'replace')\r | |
172 | else:\r | |
173 | # CHAR16 []\r | |
174 | for i in range (valobj.num_children):\r | |
175 | Char = valobj.GetChildAtIndex(i).data.GetUnsignedInt16(SBError, 0)\r | |
176 | if Char == 0:\r | |
177 | break\r | |
178 | Str += unichr (Char)\r | |
179 | Str = 'L"' + Str + '"'\r | |
180 | return Str.encode ('utf-8', 'replace')\r | |
181 | \r | |
182 | return Str\r | |
183 | \r | |
184 | def CHAR8_TypeSummary (valobj,internal_dict):\r | |
185 | #\r | |
186 | # Display EFI CHAR8 'signed char' as string\r | |
187 | # unichr() is used as a junk string can produce an error message like this:\r | |
188 | # UnicodeEncodeError: 'ascii' codec can't encode character u'\x90' in position 1: ordinal not in range(128)\r | |
189 | #\r | |
190 | SBError = lldb.SBError()\r | |
191 | Str = ''\r | |
192 | if valobj.TypeIsPointerType():\r | |
193 | if valobj.GetValueAsUnsigned () == 0:\r | |
194 | return "NULL"\r | |
195 | \r | |
196 | # CHAR8 * max string size 1024\r | |
197 | for i in range (1024):\r | |
198 | Char = valobj.GetPointeeData(i,1).GetUnsignedInt8(SBError, 0)\r | |
199 | if SBError.fail or Char == 0:\r | |
200 | break\r | |
201 | Str += unichr (Char)\r | |
202 | Str = '"' + Str + '"'\r | |
203 | return Str.encode ('utf-8', 'replace')\r | |
204 | \r | |
205 | if valobj.num_children == 0:\r | |
206 | # CHAR8\r | |
207 | if chr (valobj.unsigned) in string.printable:\r | |
208 | Str = '"' + unichr (valobj.unsigned) + '"'\r | |
209 | return Str.encode ('utf-8', 'replace')\r | |
210 | else:\r | |
211 | # CHAR8 []\r | |
212 | for i in range (valobj.num_children):\r | |
213 | Char = valobj.GetChildAtIndex(i).data.GetUnsignedInt8(SBError, 0)\r | |
214 | if Char == 0:\r | |
215 | break\r | |
216 | Str += unichr (Char)\r | |
217 | Str = '"' + Str + '"'\r | |
218 | return Str.encode ('utf-8', 'replace')\r | |
219 | \r | |
220 | return Str\r | |
221 | \r | |
222 | device_path_dict = {\r | |
223 | (0x01, 0x01): "PCI_DEVICE_PATH",\r | |
224 | (0x01, 0x02): "PCCARD_DEVICE_PATH",\r | |
225 | (0x01, 0x03): "MEMMAP_DEVICE_PATH",\r | |
226 | (0x01, 0x04): "VENDOR_DEVICE_PATH",\r | |
227 | (0x01, 0x05): "CONTROLLER_DEVICE_PATH",\r | |
228 | (0x02, 0x01): "ACPI_HID_DEVICE_PATH",\r | |
229 | (0x02, 0x02): "ACPI_EXTENDED_HID_DEVICE_PATH",\r | |
230 | (0x02, 0x03): "ACPI_ADR_DEVICE_PATH",\r | |
231 | (0x03, 0x01): "ATAPI_DEVICE_PATH",\r | |
232 | (0x03, 0x12): "SATA_DEVICE_PATH",\r | |
233 | (0x03, 0x02): "SCSI_DEVICE_PATH",\r | |
234 | (0x03, 0x03): "FIBRECHANNEL_DEVICE_PATH",\r | |
235 | (0x03, 0x04): "F1394_DEVICE_PATH",\r | |
236 | (0x03, 0x05): "USB_DEVICE_PATH",\r | |
237 | (0x03, 0x0f): "USB_CLASS_DEVICE_PATH",\r | |
238 | (0x03, 0x10): "FW_SBP2_UNIT_LUN_DEVICE_PATH",\r | |
239 | (0x03, 0x11): "DEVICE_LOGICAL_UNIT_DEVICE_PATH",\r | |
240 | (0x03, 0x06): "I2O_DEVICE_PATH",\r | |
241 | (0x03, 0x0b): "MAC_ADDR_DEVICE_PATH",\r | |
242 | (0x03, 0x0c): "IPv4_DEVICE_PATH",\r | |
243 | (0x03, 0x09): "INFINIBAND_DEVICE_PATH",\r | |
244 | (0x03, 0x0e): "UART_DEVICE_PATH",\r | |
245 | (0x03, 0x0a): "VENDOR_DEVICE_PATH",\r | |
246 | (0x03, 0x13): "ISCSI_DEVICE_PATH",\r | |
247 | (0x04, 0x01): "HARDDRIVE_DEVICE_PATH",\r | |
248 | (0x04, 0x02): "CDROM_DEVICE_PATH",\r | |
249 | (0x04, 0x03): "VENDOR_DEVICE_PATH",\r | |
250 | (0x04, 0x04): "FILEPATH_DEVICE_PATH",\r | |
251 | (0x04, 0x05): "MEDIA_PROTOCOL_DEVICE_PATH",\r | |
252 | (0x05, 0x01): "BBS_BBS_DEVICE_PATH",\r | |
253 | (0x7F, 0xFF): "EFI_DEVICE_PATH_PROTOCOL",\r | |
254 | (0xFF, 0xFF): "EFI_DEVICE_PATH_PROTOCOL",\r | |
255 | }\r | |
256 | \r | |
257 | def EFI_DEVICE_PATH_PROTOCOL_TypeSummary (valobj,internal_dict):\r | |
258 | #\r | |
259 | #\r | |
260 | #\r | |
261 | if valobj.TypeIsPointerType():\r | |
262 | # EFI_DEVICE_PATH_PROTOCOL *\r | |
263 | return ""\r | |
264 | \r | |
265 | Str = ""\r | |
266 | if valobj.num_children == 3:\r | |
267 | # EFI_DEVICE_PATH_PROTOCOL\r | |
268 | Type = valobj.GetChildMemberWithName('Type').unsigned\r | |
269 | SubType = valobj.GetChildMemberWithName('SubType').unsigned\r | |
270 | if (Type, SubType) in device_path_dict:\r | |
271 | TypeStr = device_path_dict[Type, SubType]\r | |
272 | else:\r | |
273 | TypeStr = ""\r | |
274 | \r | |
275 | LenLow = valobj.GetChildMemberWithName('Length').GetChildAtIndex(0).unsigned\r | |
276 | LenHigh = valobj.GetChildMemberWithName('Length').GetChildAtIndex(1).unsigned\r | |
277 | Len = LenLow + (LenHigh >> 8)\r | |
278 | \r | |
279 | Address = long ("%d" % valobj.addr)\r | |
280 | if (Address == lldb.LLDB_INVALID_ADDRESS):\r | |
26cfe2c6 | 281 | # Need to research this, it seems to be the nested struct case\r |
79e4f2a5 RN |
282 | ExprStr = ""\r |
283 | elif (Type & 0x7f == 0x7f):\r | |
284 | ExprStr = "End Device Path" if SubType == 0xff else "End This Instance"\r | |
285 | else:\r | |
286 | ExprStr = "expr *(%s *)0x%08x" % (TypeStr, Address)\r | |
287 | \r | |
288 | Str = " {\n"\r | |
289 | Str += " (UINT8) Type = 0x%02x // %s\n" % (Type, "END" if (Type & 0x7f == 0x7f) else "")\r | |
290 | Str += " (UINT8) SubType = 0x%02x // %s\n" % (SubType, ExprStr)\r | |
291 | Str += " (UINT8 [2]) Length = { // 0x%04x (%d) bytes\n" % (Len, Len)\r | |
292 | Str += " (UINT8) [0] = 0x%02x\n" % LenLow\r | |
293 | Str += " (UINT8) [1] = 0x%02x\n" % LenHigh\r | |
294 | Str += " }\n"\r | |
295 | if (Type & 0x7f == 0x7f) and (SubType == 0xff):\r | |
296 | pass\r | |
297 | elif ExprStr != "":\r | |
298 | NextNode = Address + Len\r | |
299 | Str += "// Next node 'expr *(EFI_DEVICE_PATH_PROTOCOL *)0x%08x'\n" % NextNode\r | |
300 | \r | |
301 | return Str\r | |
302 | \r | |
303 | \r | |
304 | \r | |
305 | def TypePrintFormating(debugger):\r | |
306 | #\r | |
26cfe2c6 | 307 | # Set the default print formatting for EFI types in lldb.\r |
79e4f2a5 RN |
308 | # seems lldb defaults to decimal.\r |
309 | #\r | |
310 | category = debugger.GetDefaultCategory()\r | |
311 | FormatBool = lldb.SBTypeFormat(lldb.eFormatBoolean)\r | |
312 | category.AddTypeFormat(lldb.SBTypeNameSpecifier("BOOLEAN"), FormatBool)\r | |
313 | \r | |
314 | FormatHex = lldb.SBTypeFormat(lldb.eFormatHex)\r | |
315 | category.AddTypeFormat(lldb.SBTypeNameSpecifier("UINT64"), FormatHex)\r | |
316 | category.AddTypeFormat(lldb.SBTypeNameSpecifier("INT64"), FormatHex)\r | |
317 | category.AddTypeFormat(lldb.SBTypeNameSpecifier("UINT32"), FormatHex)\r | |
318 | category.AddTypeFormat(lldb.SBTypeNameSpecifier("INT32"), FormatHex)\r | |
319 | category.AddTypeFormat(lldb.SBTypeNameSpecifier("UINT16"), FormatHex)\r | |
320 | category.AddTypeFormat(lldb.SBTypeNameSpecifier("INT16"), FormatHex)\r | |
321 | category.AddTypeFormat(lldb.SBTypeNameSpecifier("UINT8"), FormatHex)\r | |
322 | category.AddTypeFormat(lldb.SBTypeNameSpecifier("INT8"), FormatHex)\r | |
323 | category.AddTypeFormat(lldb.SBTypeNameSpecifier("UINTN"), FormatHex)\r | |
324 | category.AddTypeFormat(lldb.SBTypeNameSpecifier("INTN"), FormatHex)\r | |
325 | category.AddTypeFormat(lldb.SBTypeNameSpecifier("CHAR8"), FormatHex)\r | |
326 | category.AddTypeFormat(lldb.SBTypeNameSpecifier("CHAR16"), FormatHex)\r | |
327 | \r | |
328 | category.AddTypeFormat(lldb.SBTypeNameSpecifier("EFI_PHYSICAL_ADDRESS"), FormatHex)\r | |
329 | category.AddTypeFormat(lldb.SBTypeNameSpecifier("PHYSICAL_ADDRESS"), FormatHex)\r | |
330 | category.AddTypeFormat(lldb.SBTypeNameSpecifier("EFI_STATUS"), FormatHex)\r | |
331 | category.AddTypeFormat(lldb.SBTypeNameSpecifier("EFI_TPL"), FormatHex)\r | |
332 | category.AddTypeFormat(lldb.SBTypeNameSpecifier("EFI_LBA"), FormatHex)\r | |
333 | category.AddTypeFormat(lldb.SBTypeNameSpecifier("EFI_BOOT_MODE"), FormatHex)\r | |
334 | category.AddTypeFormat(lldb.SBTypeNameSpecifier("EFI_FV_FILETYPE"), FormatHex)\r | |
335 | \r | |
336 | #\r | |
337 | # Smart type printing for EFI\r | |
338 | #\r | |
339 | debugger.HandleCommand("type summary add EFI_GUID --python-function lldbefi.EFI_GUID_TypeSummary")\r | |
340 | debugger.HandleCommand("type summary add EFI_STATUS --python-function lldbefi.EFI_STATUS_TypeSummary")\r | |
341 | debugger.HandleCommand("type summary add EFI_TPL --python-function lldbefi.EFI_TPL_TypeSummary")\r | |
342 | debugger.HandleCommand("type summary add EFI_DEVICE_PATH_PROTOCOL --python-function lldbefi.EFI_DEVICE_PATH_PROTOCOL_TypeSummary")\r | |
343 | \r | |
344 | debugger.HandleCommand("type summary add CHAR16 --python-function lldbefi.CHAR16_TypeSummary")\r | |
345 | debugger.HandleCommand('type summary add --regex "CHAR16 \[[0-9]+\]" --python-function lldbefi.CHAR16_TypeSummary')\r | |
346 | debugger.HandleCommand("type summary add CHAR8 --python-function lldbefi.CHAR8_TypeSummary")\r | |
347 | debugger.HandleCommand('type summary add --regex "CHAR8 \[[0-9]+\]" --python-function lldbefi.CHAR8_TypeSummary')\r | |
348 | \r | |
32e55c9f AF |
349 | debugger.HandleCommand(\r |
350 | 'setting set frame-format "frame #${frame.index}: ${frame.pc}'\r | |
351 | '{ ${module.file.basename}{:${function.name}()${function.pc-offset}}}'\r | |
352 | '{ at ${line.file.fullpath}:${line.number}}\n"'\r | |
353 | )\r | |
79e4f2a5 RN |
354 | \r |
355 | gEmulatorBreakWorkaroundNeeded = True\r | |
356 | \r | |
357 | def LoadEmulatorEfiSymbols(frame, bp_loc , internal_dict):\r | |
358 | #\r | |
359 | # This is an lldb breakpoint script, and assumes the breakpoint is on a\r | |
360 | # function with the same prototype as SecGdbScriptBreak(). The\r | |
361 | # argument names are important as lldb looks them up.\r | |
362 | #\r | |
363 | # VOID\r | |
364 | # SecGdbScriptBreak (\r | |
365 | # char *FileName,\r | |
366 | # int FileNameLength,\r | |
367 | # long unsigned int LoadAddress,\r | |
368 | # int AddSymbolFlag\r | |
369 | # )\r | |
370 | # {\r | |
371 | # return;\r | |
372 | # }\r | |
373 | #\r | |
374 | # When the emulator loads a PE/COFF image, it calls the stub function with\r | |
375 | # the filename of the symbol file, the length of the FileName, the\r | |
376 | # load address and a flag to indicate if this is a load or unload operation\r | |
377 | #\r | |
378 | global gEmulatorBreakWorkaroundNeeded\r | |
379 | \r | |
380 | if gEmulatorBreakWorkaroundNeeded:\r | |
381 | # turn off lldb debug prints on SIGALRM (EFI timer tick)\r | |
382 | frame.thread.process.target.debugger.HandleCommand("process handle SIGALRM -n false")\r | |
383 | gEmulatorBreakWorkaroundNeeded = False\r | |
384 | \r | |
385 | # Convert C string to Python string\r | |
386 | Error = lldb.SBError()\r | |
387 | FileNamePtr = frame.FindVariable ("FileName").GetValueAsUnsigned()\r | |
388 | FileNameLen = frame.FindVariable ("FileNameLength").GetValueAsUnsigned()\r | |
32e55c9f | 389 | \r |
79e4f2a5 RN |
390 | FileName = frame.thread.process.ReadCStringFromMemory (FileNamePtr, FileNameLen, Error)\r |
391 | if not Error.Success():\r | |
392 | print "!ReadCStringFromMemory() did not find a %d byte C string at %x" % (FileNameLen, FileNamePtr)\r | |
26cfe2c6 | 393 | # make breakpoint command continue\r |
32e55c9f | 394 | return False\r |
79e4f2a5 RN |
395 | \r |
396 | debugger = frame.thread.process.target.debugger\r | |
397 | if frame.FindVariable ("AddSymbolFlag").GetValueAsUnsigned() == 1:\r | |
32e55c9f | 398 | LoadAddress = frame.FindVariable ("LoadAddress").GetValueAsUnsigned() - 0x240\r |
79e4f2a5 RN |
399 | \r |
400 | debugger.HandleCommand ("target modules add %s" % FileName)\r | |
401 | print "target modules load --slid 0x%x %s" % (LoadAddress, FileName)\r | |
402 | debugger.HandleCommand ("target modules load --slide 0x%x --file %s" % (LoadAddress, FileName))\r | |
403 | else:\r | |
404 | target = debugger.GetSelectedTarget()\r | |
405 | for SBModule in target.module_iter():\r | |
406 | ModuleName = SBModule.GetFileSpec().GetDirectory() + '/'\r | |
407 | ModuleName += SBModule.GetFileSpec().GetFilename()\r | |
408 | if FileName == ModuleName or FileName == SBModule.GetFileSpec().GetFilename():\r | |
409 | target.ClearModuleLoadAddress (SBModule)\r | |
410 | if not target.RemoveModule (SBModule):\r | |
411 | print "!lldb.target.RemoveModule (%s) FAILED" % SBModule\r | |
412 | \r | |
26cfe2c6 | 413 | # make breakpoint command continue\r |
32e55c9f | 414 | return False\r |
79e4f2a5 RN |
415 | \r |
416 | def GuidToCStructStr (guid, Name=False):\r | |
417 | #\r | |
26cfe2c6 | 418 | # Convert a 16-byte bytesarray (or bytearray compat object) to C guid string\r |
79e4f2a5 RN |
419 | # { 0xB402621F, 0xA940, 0x1E4A, { 0x86, 0x6B, 0x4D, 0xC9, 0x16, 0x2B, 0x34, 0x7C } }\r |
420 | #\r | |
421 | # Name=True means lookup name in GuidNameDict and us it if you find it\r | |
422 | #\r | |
423 | \r | |
424 | if not isinstance (guid, bytearray):\r | |
425 | # convert guid object to UUID, and UUID to bytearray\r | |
426 | Uuid = uuid.UUID(guid)\r | |
427 | guid = bytearray (Uuid.bytes_le)\r | |
428 | \r | |
429 | return "{ 0x%02.2X%02.2X%02.2X%02.2X, 0x%02.2X%02.2X, 0x%02.2X%02.2X, { 0x%02.2X, 0x%02.2X, 0x%02.2X, 0x%02.2X, 0x%02.2X, 0x%02.2X, 0x%02.2X, 0x%02.2X } }" % \\r | |
430 | (guid[3], guid[2], guid[1], guid[0], guid[5], guid[4], guid[7], guid[6], guid[8], guid[9], guid[10], guid[11], guid[12], guid[13], guid[14], guid[15])\r | |
431 | \r | |
432 | def ParseGuidString(GuidStr):\r | |
433 | #\r | |
434 | # Error check and convert C Guid init to string\r | |
435 | # ParseGuidString("49152E77-1ADA-4764-B7A2-7AFEFED95E8B")\r | |
436 | # ParseGuidString("{ 0xBA24B391, 0x73FD, 0xC54C, { 0x9E, 0xAF, 0x0C, 0xA7, 0x8A, 0x35, 0x46, 0xD1 } }")\r | |
437 | #\r | |
438 | \r | |
439 | if "{" in GuidStr :\r | |
440 | # convert C form "{ 0xBA24B391, 0x73FD, 0xC54C, { 0x9E, 0xAF, 0x0C, 0xA7, 0x8A, 0x35, 0x46, 0xD1 } }"\r | |
441 | # to string form BA24B391-73FD-C54C-9EAF-0CA78A3546D1\r | |
442 | # make a list of Hex numbers like: ['0xBA24B391', '0x73FD', '0xC54C', '0x9E', '0xAF', '0x0C', '0xA7', '0x8A', '0x35', '0x46', '0xD1']\r | |
443 | Hex = ''.join(x for x in GuidStr if x not in '{,}').split()\r | |
444 | Str = "%08X-%04X-%04X-%02.2X%02.2X-%02.2X%02.2X%02.2X%02.2X%02.2X%02.2X" % \\r | |
445 | (int(Hex[0], 0), int(Hex[1], 0), int(Hex[2], 0), int(Hex[3], 0), int(Hex[4], 0), \\r | |
446 | int(Hex[5], 0), int(Hex[6], 0), int(Hex[7], 0), int(Hex[8], 0), int(Hex[9], 0), int(Hex[10], 0))\r | |
447 | elif GuidStr.count('-') == 4:\r | |
448 | # validate "49152E77-1ADA-4764-B7A2-7AFEFED95E8B" form\r | |
449 | Check = "%s" % str(uuid.UUID(GuidStr)).upper()\r | |
450 | if GuidStr.upper() == Check:\r | |
451 | Str = GuidStr.upper()\r | |
452 | else:\r | |
453 | Ste = ""\r | |
454 | else:\r | |
455 | Str = ""\r | |
456 | \r | |
457 | return Str\r | |
458 | \r | |
459 | \r | |
460 | def create_guid_options():\r | |
461 | usage = "usage: %prog [data]"\r | |
462 | description='''lookup EFI_GUID by CName, C struct, or GUID string and print out all three.\r | |
463 | '''\r | |
464 | parser = optparse.OptionParser(description=description, prog='guid',usage=usage)\r | |
465 | return parser\r | |
466 | \r | |
467 | def efi_guid_command(debugger, command, result, dict):\r | |
468 | # Use the Shell Lexer to properly parse up command options just like a\r | |
469 | # shell would\r | |
470 | command_args = shlex.split(command)\r | |
471 | parser = create_guid_options()\r | |
472 | try:\r | |
473 | (options, args) = parser.parse_args(command_args)\r | |
474 | if len(args) >= 1:\r | |
475 | if args[0] == "{":\r | |
476 | # caller forgot to quote the string"\r | |
477 | # mark arg[0] a string containing all args[n]\r | |
478 | args[0] = ' '.join(args)\r | |
479 | GuidStr = ParseGuidString (args[0])\r | |
480 | if GuidStr == "":\r | |
481 | # return Key of GuidNameDict for value args[0]\r | |
482 | GuidStr = [Key for Key, Value in guid_dict.iteritems() if Value == args[0]][0]\r | |
483 | GuidStr = GuidStr.upper()\r | |
484 | except:\r | |
485 | # if you don't handle exceptions, passing an incorrect argument to the OptionParser will cause LLDB to exit\r | |
486 | # (courtesy of OptParse dealing with argument errors by throwing SystemExit)\r | |
487 | result.SetError ("option parsing failed")\r | |
488 | return\r | |
489 | \r | |
490 | \r | |
491 | if len(args) >= 1:\r | |
492 | if GuidStr in guid_dict:\r | |
493 | print "%s = %s" % (guid_dict[GuidStr], GuidStr)\r | |
494 | print "%s = %s" % (guid_dict[GuidStr], GuidToCStructStr (GuidStr))\r | |
495 | else:\r | |
496 | print GuidStr\r | |
497 | else:\r | |
498 | # dump entire dictionary\r | |
499 | width = max(len(v) for k,v in guid_dict.iteritems())\r | |
500 | for value in sorted(guid_dict, key=guid_dict.get):\r | |
501 | print '%-*s %s %s' % (width, guid_dict[value], value, GuidToCStructStr(value))\r | |
502 | \r | |
503 | return\r | |
504 | \r | |
505 | \r | |
506 | #\r | |
507 | ########## Code that runs when this script is imported into LLDB ###########\r | |
508 | #\r | |
509 | def __lldb_init_module (debugger, internal_dict):\r | |
510 | # This initializer is being run from LLDB in the embedded command interpreter\r | |
511 | # Make the options so we can generate the help text for the new LLDB\r | |
512 | # command line command prior to registering it with LLDB below\r | |
513 | \r | |
514 | global guid_dict\r | |
515 | \r | |
516 | # Source Guid.xref file if we can find it\r | |
517 | inputfile = os.getcwd()\r | |
518 | inputfile += os.sep + os.pardir + os.sep + 'FV' + os.sep + 'Guid.xref'\r | |
519 | with open(inputfile) as f:\r | |
520 | for line in f:\r | |
521 | data = line.split(' ')\r | |
522 | if len(data) >= 2:\r | |
523 | guid_dict[data[0].upper()] = data[1].strip('\n')\r | |
524 | \r | |
26cfe2c6 | 525 | # init EFI specific type formatters\r |
79e4f2a5 RN |
526 | TypePrintFormating (debugger)\r |
527 | \r | |
528 | \r | |
529 | # add guid command\r | |
530 | parser = create_guid_options()\r | |
531 | efi_guid_command.__doc__ = parser.format_help()\r | |
532 | debugger.HandleCommand('command script add -f lldbefi.efi_guid_command guid')\r | |
533 | \r | |
534 | \r | |
535 | Target = debugger.GetTargetAtIndex(0)\r | |
536 | if Target:\r | |
537 | Breakpoint = Target.BreakpointCreateByName('SecGdbScriptBreak')\r | |
538 | if Breakpoint.GetNumLocations() == 1:\r | |
539 | # Set the emulator breakpoints, if we are in the emulator\r | |
540 | debugger.HandleCommand("breakpoint command add -s python -F lldbefi.LoadEmulatorEfiSymbols {id}".format(id=Breakpoint.GetID()))\r | |
541 | print 'Type r to run emulator. SecLldbScriptBreak armed. EFI modules should now get source level debugging in the emulator.'\r |