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