On Wed, Aug 27, 2014 at 9:50 AM, Andrew Fish <[email protected]> wrote:
>
> On Aug 26, 2014, at 11:17 PM, Jordan Justen <[email protected]> wrote:
>
> On Tue, Aug 26, 2014 at 9:34 PM, Andrew Fish <[email protected]> wrote:
>
> EmulatorPkg:Host: Port emulator to Xcode5
>
> Xcode5 retired gdb, so this patch adds support for using, and loading
> symbols in, lldb.
>
>
> Cool, but I don't think the subject is right:
> -EmulatorPkg:Host: Port emulator to Xcode5
> +EmulatorPkg Unix Host: Add LLDB support
>
> Well Xcode 5 does not support gdb, and only supports lldb.

Right. I just think the lldb support should be the focus, and Xcode 5
could be mentioned in the main commit message body as one motivation.

-Jordan

> I don't see XCODE5 in the patch. Seems fine to mention in the commit
> message that Xcode5 is the motivation for adding the LLDB support.
>
> Is the new SecGdbScriptBreak call going to cause EmulatorPkg to break
> on each run? Why is that needed?
>
>
> It pushes control to the lldb Python script. Loading symbols dynamically
> allows the setting of breakpoints prior to loading the module. Loading the
> symbols will resolve the breakpoint and activate it.
> The files written by the emulator are not used by lldb. I should probably
> just move the call to SecGdbScriptBreak() out of the if PCD construct that
> defines how the files get written.
>
> Since the breakpoint script is just doing a few reads from the stack it is
> very fast. The emulator runs about the same speed if you load symbols or
> not.
>
> What's the "+ 1" change in the call to SecGdbScriptBreak?
>
>
> StrSize vs. StrLen. So it was a bug. Lldb was only getting Module.dl and not
> Module.dll.
>
> I think the X stuff could be a separate commit from the LLDB part.
>
>
> OK
>
> -Jordan
>
> The lldb script also supports dumping out the build generated guid database
> and it prints guids out with thier Cname if available. lldbefi.py also
> contains some EFI specific type formatters.
>
> Unix/Host/X11IncludeHack is a symbolic link that is need to add the path for
> X11, since it is now an external package.
> X11IncludeHack is a symbolic link to /opt/X11/include
>
> To get X11 to work on a Mac you now have to install XQuartz:
> http://xquartz.macosforge.org
>
> To fully work the -combine needs to be removed from the
> *_XCODE32_X64_CC_FLAGS in BaseTools/Conf/tools_def.template, this will be a
> separate commit.
>
> ---
> EmulatorPkg/Unix/Host/Host.c         |   5 +-
> EmulatorPkg/Unix/Host/Host.inf       |   2 +-
> EmulatorPkg/Unix/Host/X11IncludeHack |   1 +
> EmulatorPkg/Unix/lldbefi.py          | 540
> +++++++++++++++++++++++++++++++++++
> EmulatorPkg/Unix/lldbinit            |   3 +
> 5 files changed, 549 insertions(+), 2 deletions(-)
> create mode 120000 EmulatorPkg/Unix/Host/X11IncludeHack
> create mode 100755 EmulatorPkg/Unix/lldbefi.py
> create mode 100644 EmulatorPkg/Unix/lldbinit
>
> diff --git a/EmulatorPkg/Unix/Host/Host.c b/EmulatorPkg/Unix/Host/Host.c
> index 7eecbce..480bc54 100644
> --- a/EmulatorPkg/Unix/Host/Host.c
> +++ b/EmulatorPkg/Unix/Host/Host.c
> @@ -1161,6 +1161,9 @@ GdbScriptAddImage (
>           SymbolsAddr
>           );
>         fclose (GdbTempFile);
> +
> +        // for lldb call the stub function too
> +        SecGdbScriptBreak (ImageContext->PdbPointer, strlen
> (ImageContext->PdbPointer) + 1, (long unsigned
> int)(ImageContext->ImageAddress + ImageContext->SizeOfHeaders), 1);
>       } else {
>         ASSERT (FALSE);
>       }
> @@ -1179,7 +1182,7 @@ GdbScriptAddImage (
>         // Target for gdb breakpoint in a script that uses
> gGdbWorkingFileName to set a breakpoint.
>         // Hey what can you say scripting in gdb is not that great....
>         //
> -        SecGdbScriptBreak (ImageContext->PdbPointer, strlen
> (ImageContext->PdbPointer), (long unsigned int)(ImageContext->ImageAddress +
> ImageContext->SizeOfHeaders), 1);
> +        SecGdbScriptBreak (ImageContext->PdbPointer, strlen
> (ImageContext->PdbPointer) + 1, (long unsigned
> int)(ImageContext->ImageAddress + ImageContext->SizeOfHeaders), 1);
>       } else {
>         ASSERT (FALSE);
>       }
> diff --git a/EmulatorPkg/Unix/Host/Host.inf b/EmulatorPkg/Unix/Host/Host.inf
> index dee2e0d..f8a4e99 100644
> --- a/EmulatorPkg/Unix/Host/Host.inf
> +++ b/EmulatorPkg/Unix/Host/Host.inf
> @@ -145,4 +145,4 @@
>    XCODE:*_*_X64_DLINK_PATH == gcc
>    XCODE:*_*_X64_DLINK_FLAGS == -o $(BIN_DIR)/Host -L/usr/X11R6/lib -lXext
> -lX11 -framework Carbon
>    XCODE:*_*_X64_ASM_FLAGS == -g
> -
> +   XCODE:*_*_X64_CC_FLAGS = -include $(DEST_DIR_DEBUG)/AutoGen.h
> -I$(WORKSPACE)/EmulatorPkg/Unix/Host/X11IncludeHack
> diff --git a/EmulatorPkg/Unix/Host/X11IncludeHack
> b/EmulatorPkg/Unix/Host/X11IncludeHack
> new file mode 120000
> index 0000000..f7ab103
> --- /dev/null
> +++ b/EmulatorPkg/Unix/Host/X11IncludeHack
> @@ -0,0 +1 @@
> +/opt/X11/include
> \ No newline at end of file
> diff --git a/EmulatorPkg/Unix/lldbefi.py b/EmulatorPkg/Unix/lldbefi.py
> new file mode 100755
> index 0000000..64549ce
> --- /dev/null
> +++ b/EmulatorPkg/Unix/lldbefi.py
> @@ -0,0 +1,540 @@
> +#!/usr/bin/python
> +
> +#
> +#  Copyright 2014 Apple Inc. All righes reserved.
> +#
> +#  This program and the accompanying materials
> +#  are licensed and made available under the terms and conditions of the
> BSD License
> +#  which accompanies this distribution. The full text of the license may be
> found at
> +#  http://opensource.org/licenses/bsd-license.php.
> +#  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
> +#  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR
> IMPLIED.
> +#
> +
> +import lldb
> +import os
> +import uuid
> +import string
> +import commands
> +import optparse
> +import shlex
> +
> +guid_dict = {}
> +
> +
> +def EFI_GUID_TypeSummary (valobj,internal_dict):
> +    """ Type summary for EFI GUID, print C Name if known
> +    """
> +    # typedef struct {
> +    #   UINT32  Data1;
> +    #   UINT16  Data2;
> +    #   UINT16  Data3;
> +    #   UINT8   Data4[8];
> +    # } EFI_GUID;
> +    SBError = lldb.SBError()
> +
> +    data1_val = valobj.GetChildMemberWithName('Data1')
> +    data1 = data1_val.GetValueAsUnsigned(0)
> +    data2_val = valobj.GetChildMemberWithName('Data2')
> +    data2 = data2_val.GetValueAsUnsigned(0)
> +    data3_val = valobj.GetChildMemberWithName('Data3')
> +    data3 = data3_val.GetValueAsUnsigned(0)
> +    str = "%x-%x-%x-" % (data1, data2, data3)
> +
> +    data4_val = valobj.GetChildMemberWithName('Data4')
> +    for i in range (data4_val.num_children):
> +        if i == 2:
> +            str +='-'
> +        str += "%02x" %
> data4_val.GetChildAtIndex(i).data.GetUnsignedInt8(SBError, 0)
> +
> +    return guid_dict.get (str.upper(), '')
> +
> +
> +
> +EFI_STATUS_Dict = {
> +    (0x8000000000000000 |  1): "Load Error",
> +    (0x8000000000000000 |  2): "Invalid Parameter",
> +    (0x8000000000000000 |  3): "Unsupported",
> +    (0x8000000000000000 |  4): "Bad Buffer Size",
> +    (0x8000000000000000 |  5): "Buffer Too Small",
> +    (0x8000000000000000 |  6): "Not Ready",
> +    (0x8000000000000000 |  7): "Device Error",
> +    (0x8000000000000000 |  8): "Write Protected",
> +    (0x8000000000000000 |  9): "Out of Resources",
> +    (0x8000000000000000 | 10): "Volume Corrupt",
> +    (0x8000000000000000 | 11): "Volume Full",
> +    (0x8000000000000000 | 12): "No Media",
> +    (0x8000000000000000 | 13): "Media changed",
> +    (0x8000000000000000 | 14): "Not Found",
> +    (0x8000000000000000 | 15): "Access Denied",
> +    (0x8000000000000000 | 16): "No Response",
> +    (0x8000000000000000 | 17): "No mapping",
> +    (0x8000000000000000 | 18): "Time out",
> +    (0x8000000000000000 | 19): "Not started",
> +    (0x8000000000000000 | 20): "Already started",
> +    (0x8000000000000000 | 21): "Aborted",
> +    (0x8000000000000000 | 22): "ICMP Error",
> +    (0x8000000000000000 | 23): "TFTP Error",
> +    (0x8000000000000000 | 24): "Protocol Error",
> +
> +                          0 : "Success",
> +                          1 : "Warning Unknown Glyph",
> +                          2 : "Warning Delete Failure",
> +                          3 : "Warning Write Failure",
> +                          4 : "Warning Buffer Too Small",
> +
> +    (0x80000000         |  1): "Load Error",
> +    (0x80000000         |  2): "Invalid Parameter",
> +    (0x80000000         |  3): "Unsupported",
> +    (0x80000000         |  4): "Bad Buffer Size",
> +    (0x80000000         |  5): "Buffer Too Small",
> +    (0x80000000         |  6): "Not Ready",
> +    (0x80000000         |  7): "Device Error",
> +    (0x80000000         |  8): "Write Protected",
> +    (0x80000000         |  9): "Out of Resources",
> +    (0x80000000         | 10): "Volume Corrupt",
> +    (0x80000000         | 11): "Volume Full",
> +    (0x80000000         | 12): "No Media",
> +    (0x80000000         | 13): "Media changed",
> +    (0x80000000         | 14): "Not Found",
> +    (0x80000000         | 15): "Access Denied",
> +    (0x80000000         | 16): "No Response",
> +    (0x80000000         | 17): "No mapping",
> +    (0x80000000         | 18): "Time out",
> +    (0x80000000         | 19): "Not started",
> +    (0x80000000         | 20): "Already started",
> +    (0x80000000         | 21): "Aborted",
> +    (0x80000000         | 22): "ICMP Error",
> +    (0x80000000         | 23): "TFTP Error",
> +    (0x80000000         | 24): "Protocol Error",
> +}
> +
> +def EFI_STATUS_TypeSummary (valobj,internal_dict):
> +  #
> +  # Return summary string for EFI_STATUS from dictionary
> +  #
> +  Status = valobj.GetValueAsUnsigned(0)
> +  return EFI_STATUS_Dict.get (Status, '')
> +
> +
> +def EFI_TPL_TypeSummary (valobj,internal_dict):
> +  #
> +  # Return TPL values
> +  #
> +
> +  if valobj.TypeIsPointerType():
> +    return ""
> +
> +  Tpl = valobj.GetValueAsUnsigned(0)
> +  if   Tpl < 4:
> +    Str = "%d" % Tpl
> +  elif Tpl == 6:
> +    Str = "TPL_DRIVER (Obsolete Concept in edk2)"
> +  elif Tpl < 8:
> +    Str = "TPL_APPLICATION"
> +    if Tpl - 4 > 0:
> +      Str += " + " + "%d" % (Tpl - 4)
> +  elif Tpl < 16:
> +    Str = "TPL_CALLBACK"
> +    if Tpl - 8 > 0:
> +      Str += " + " + "%d" % (Tpl - 4)
> +  elif Tpl < 31:
> +    Str = "TPL_NOTIFY"
> +    if Tpl - 16 > 0:
> +      Str += " + " + "%d" % (Tpl - 4)
> +  elif Tpl == 31:
> +    Str = "TPL_HIGH_LEVEL"
> +  else:
> +    Str = "Invalid TPL"
> +
> +  return Str
> +
> +
> +def CHAR16_TypeSummary (valobj,internal_dict):
> +  #
> +  # Display EFI CHAR16 'unsigned short' as string
> +  #
> +  SBError = lldb.SBError()
> +  Str = ''
> +  if valobj.TypeIsPointerType():
> +    if valobj.GetValueAsUnsigned () == 0:
> +      return "NULL"
> +
> +    # CHAR16 *   max string size 1024
> +    for i in range (1024):
> +      Char = valobj.GetPointeeData(i,1).GetUnsignedInt16(SBError, 0)
> +      if SBError.fail or Char == 0:
> +        break
> +      Str += unichr (Char)
> +    Str = 'L"' + Str + '"'
> +    return Str.encode ('utf-8', 'replace')
> +
> +  if valobj.num_children == 0:
> +    # CHAR16
> +    if chr (valobj.unsigned) in string.printable:
> +      Str = "L'" + unichr (valobj.unsigned) + "'"
> +      return Str.encode ('utf-8', 'replace')
> +  else:
> +    # CHAR16 []
> +    for i in range (valobj.num_children):
> +      Char = valobj.GetChildAtIndex(i).data.GetUnsignedInt16(SBError, 0)
> +      if Char == 0:
> +        break
> +      Str += unichr (Char)
> +    Str = 'L"' + Str + '"'
> +    return Str.encode ('utf-8', 'replace')
> +
> +  return Str
> +
> +def CHAR8_TypeSummary (valobj,internal_dict):
> +  #
> +  # Display EFI CHAR8 'signed char' as string
> +  # unichr() is used as a junk string can produce an error message like
> this:
> +  # UnicodeEncodeError: 'ascii' codec can't encode character u'\x90' in
> position 1: ordinal not in range(128)
> +  #
> +  SBError = lldb.SBError()
> +  Str = ''
> +  if valobj.TypeIsPointerType():
> +    if valobj.GetValueAsUnsigned () == 0:
> +      return "NULL"
> +
> +    # CHAR8 *   max string size 1024
> +    for i in range (1024):
> +      Char = valobj.GetPointeeData(i,1).GetUnsignedInt8(SBError, 0)
> +      if SBError.fail or Char == 0:
> +        break
> +      Str += unichr (Char)
> +    Str = '"' + Str + '"'
> +    return Str.encode ('utf-8', 'replace')
> +
> +  if valobj.num_children == 0:
> +    # CHAR8
> +    if chr (valobj.unsigned) in string.printable:
> +      Str = '"' + unichr (valobj.unsigned)  + '"'
> +      return Str.encode ('utf-8', 'replace')
> +  else:
> +    # CHAR8 []
> +    for i in range (valobj.num_children):
> +      Char = valobj.GetChildAtIndex(i).data.GetUnsignedInt8(SBError, 0)
> +      if Char == 0:
> +        break
> +      Str += unichr (Char)
> +    Str = '"' + Str + '"'
> +    return Str.encode ('utf-8', 'replace')
> +
> +  return Str
> +
> +device_path_dict = {
> +  (0x01, 0x01): "PCI_DEVICE_PATH",
> +  (0x01, 0x02): "PCCARD_DEVICE_PATH",
> +  (0x01, 0x03): "MEMMAP_DEVICE_PATH",
> +  (0x01, 0x04): "VENDOR_DEVICE_PATH",
> +  (0x01, 0x05): "CONTROLLER_DEVICE_PATH",
> +  (0x02, 0x01): "ACPI_HID_DEVICE_PATH",
> +  (0x02, 0x02): "ACPI_EXTENDED_HID_DEVICE_PATH",
> +  (0x02, 0x03): "ACPI_ADR_DEVICE_PATH",
> +  (0x03, 0x01): "ATAPI_DEVICE_PATH",
> +  (0x03, 0x12): "SATA_DEVICE_PATH",
> +  (0x03, 0x02): "SCSI_DEVICE_PATH",
> +  (0x03, 0x03): "FIBRECHANNEL_DEVICE_PATH",
> +  (0x03, 0x04): "F1394_DEVICE_PATH",
> +  (0x03, 0x05): "USB_DEVICE_PATH",
> +  (0x03, 0x0f): "USB_CLASS_DEVICE_PATH",
> +  (0x03, 0x10): "FW_SBP2_UNIT_LUN_DEVICE_PATH",
> +  (0x03, 0x11): "DEVICE_LOGICAL_UNIT_DEVICE_PATH",
> +  (0x03, 0x06): "I2O_DEVICE_PATH",
> +  (0x03, 0x0b): "MAC_ADDR_DEVICE_PATH",
> +  (0x03, 0x0c): "IPv4_DEVICE_PATH",
> +  (0x03, 0x09): "INFINIBAND_DEVICE_PATH",
> +  (0x03, 0x0e): "UART_DEVICE_PATH",
> +  (0x03, 0x0a): "VENDOR_DEVICE_PATH",
> +  (0x03, 0x13): "ISCSI_DEVICE_PATH",
> +  (0x04, 0x01): "HARDDRIVE_DEVICE_PATH",
> +  (0x04, 0x02): "CDROM_DEVICE_PATH",
> +  (0x04, 0x03): "VENDOR_DEVICE_PATH",
> +  (0x04, 0x04): "FILEPATH_DEVICE_PATH",
> +  (0x04, 0x05): "MEDIA_PROTOCOL_DEVICE_PATH",
> +  (0x05, 0x01): "BBS_BBS_DEVICE_PATH",
> +  (0x7F, 0xFF): "EFI_DEVICE_PATH_PROTOCOL",
> +  (0xFF, 0xFF): "EFI_DEVICE_PATH_PROTOCOL",
> +}
> +
> +def EFI_DEVICE_PATH_PROTOCOL_TypeSummary (valobj,internal_dict):
> +  #
> +  #
> +  #
> +  if valobj.TypeIsPointerType():
> +    # EFI_DEVICE_PATH_PROTOCOL *
> +    return ""
> +
> +  Str = ""
> +  if valobj.num_children == 3:
> +    # EFI_DEVICE_PATH_PROTOCOL
> +    Type    = valobj.GetChildMemberWithName('Type').unsigned
> +    SubType = valobj.GetChildMemberWithName('SubType').unsigned
> +    if (Type, SubType) in device_path_dict:
> +      TypeStr = device_path_dict[Type, SubType]
> +    else:
> +      TypeStr = ""
> +
> +    LenLow  =
> valobj.GetChildMemberWithName('Length').GetChildAtIndex(0).unsigned
> +    LenHigh =
> valobj.GetChildMemberWithName('Length').GetChildAtIndex(1).unsigned
> +    Len = LenLow + (LenHigh >> 8)
> +
> +    Address = long ("%d" % valobj.addr)
> +    if (Address == lldb.LLDB_INVALID_ADDRESS):
> +      # Need to reserach this, it seems to be the nested struct case
> +      ExprStr = ""
> +    elif (Type & 0x7f == 0x7f):
> +      ExprStr = "End Device Path" if SubType == 0xff else "End This
> Instance"
> +    else:
> +      ExprStr = "expr *(%s *)0x%08x" % (TypeStr, Address)
> +
> +    Str =  " {\n"
> +    Str += "   (UINT8) Type    = 0x%02x // %s\n" % (Type, "END" if (Type &
> 0x7f == 0x7f) else "")
> +    Str += "   (UINT8) SubType = 0x%02x // %s\n" % (SubType, ExprStr)
> +    Str += "   (UINT8 [2]) Length = { // 0x%04x (%d) bytes\n" % (Len, Len)
> +    Str += "     (UINT8) [0] = 0x%02x\n" % LenLow
> +    Str += "     (UINT8) [1] = 0x%02x\n" % LenHigh
> +    Str +=  "   }\n"
> +    if (Type & 0x7f == 0x7f) and (SubType == 0xff):
> +      pass
> +    elif ExprStr != "":
> +      NextNode = Address + Len
> +      Str += "// Next node 'expr *(EFI_DEVICE_PATH_PROTOCOL *)0x%08x'\n" %
> NextNode
> +
> +  return Str
> +
> +
> +
> +def TypePrintFormating(debugger):
> +    #
> +    # Set the default print formating for EFI types in lldb.
> +    # seems lldb defaults to decimal.
> +    #
> +    category = debugger.GetDefaultCategory()
> +    FormatBool = lldb.SBTypeFormat(lldb.eFormatBoolean)
> +    category.AddTypeFormat(lldb.SBTypeNameSpecifier("BOOLEAN"), FormatBool)
> +
> +    FormatHex  = lldb.SBTypeFormat(lldb.eFormatHex)
> +    category.AddTypeFormat(lldb.SBTypeNameSpecifier("UINT64"), FormatHex)
> +    category.AddTypeFormat(lldb.SBTypeNameSpecifier("INT64"), FormatHex)
> +    category.AddTypeFormat(lldb.SBTypeNameSpecifier("UINT32"), FormatHex)
> +    category.AddTypeFormat(lldb.SBTypeNameSpecifier("INT32"), FormatHex)
> +    category.AddTypeFormat(lldb.SBTypeNameSpecifier("UINT16"), FormatHex)
> +    category.AddTypeFormat(lldb.SBTypeNameSpecifier("INT16"), FormatHex)
> +    category.AddTypeFormat(lldb.SBTypeNameSpecifier("UINT8"), FormatHex)
> +    category.AddTypeFormat(lldb.SBTypeNameSpecifier("INT8"), FormatHex)
> +    category.AddTypeFormat(lldb.SBTypeNameSpecifier("UINTN"), FormatHex)
> +    category.AddTypeFormat(lldb.SBTypeNameSpecifier("INTN"), FormatHex)
> +    category.AddTypeFormat(lldb.SBTypeNameSpecifier("CHAR8"), FormatHex)
> +    category.AddTypeFormat(lldb.SBTypeNameSpecifier("CHAR16"), FormatHex)
> +
> +
> category.AddTypeFormat(lldb.SBTypeNameSpecifier("EFI_PHYSICAL_ADDRESS"),
> FormatHex)
> +    category.AddTypeFormat(lldb.SBTypeNameSpecifier("PHYSICAL_ADDRESS"),
> FormatHex)
> +    category.AddTypeFormat(lldb.SBTypeNameSpecifier("EFI_STATUS"),
> FormatHex)
> +    category.AddTypeFormat(lldb.SBTypeNameSpecifier("EFI_TPL"), FormatHex)
> +    category.AddTypeFormat(lldb.SBTypeNameSpecifier("EFI_LBA"), FormatHex)
> +    category.AddTypeFormat(lldb.SBTypeNameSpecifier("EFI_BOOT_MODE"),
> FormatHex)
> +    category.AddTypeFormat(lldb.SBTypeNameSpecifier("EFI_FV_FILETYPE"),
> FormatHex)
> +
> +    #
> +    # Smart type printing for EFI
> +    #
> +    debugger.HandleCommand("type summary add EFI_GUID --python-function
> lldbefi.EFI_GUID_TypeSummary")
> +    debugger.HandleCommand("type summary add EFI_STATUS --python-function
> lldbefi.EFI_STATUS_TypeSummary")
> +    debugger.HandleCommand("type summary add EFI_TPL --python-function
> lldbefi.EFI_TPL_TypeSummary")
> +    debugger.HandleCommand("type summary add EFI_DEVICE_PATH_PROTOCOL
> --python-function lldbefi.EFI_DEVICE_PATH_PROTOCOL_TypeSummary")
> +
> +    debugger.HandleCommand("type summary add CHAR16 --python-function
> lldbefi.CHAR16_TypeSummary")
> +    debugger.HandleCommand('type summary add --regex "CHAR16 \[[0-9]+\]"
> --python-function lldbefi.CHAR16_TypeSummary')
> +    debugger.HandleCommand("type summary add CHAR8 --python-function
> lldbefi.CHAR8_TypeSummary")
> +    debugger.HandleCommand('type summary add --regex "CHAR8 \[[0-9]+\]"
> --python-function lldbefi.CHAR8_TypeSummary')
> +
> +
> +gEmulatorBreakWorkaroundNeeded = True
> +
> +def LoadEmulatorEfiSymbols(frame, bp_loc , internal_dict):
> +    #
> +    # This is an lldb breakpoint script, and assumes the breakpoint is on a
> +    # function with the same prototype as SecGdbScriptBreak(). The
> +    # argument names are important as lldb looks them up.
> +    #
> +    # VOID
> +    # SecGdbScriptBreak (
> +    #   char                *FileName,
> +    #   int                 FileNameLength,
> +    #   long unsigned int   LoadAddress,
> +    #   int                 AddSymbolFlag
> +    #   )
> +    # {
> +    #   return;
> +    # }
> +    #
> +    # When the emulator loads a PE/COFF image, it calls the stub function
> with
> +    # the filename of the symbol file, the length of the FileName, the
> +    # load address and a flag to indicate if this is a load or unload
> operation
> +    #
> +    global gEmulatorBreakWorkaroundNeeded
> +
> +    if gEmulatorBreakWorkaroundNeeded:
> +        # turn off lldb debug prints on SIGALRM (EFI timer tick)
> +        frame.thread.process.target.debugger.HandleCommand("process handle
> SIGALRM -n false")
> +        gEmulatorBreakWorkaroundNeeded = False
> +
> +    # Convert C string to Python string
> +    Error = lldb.SBError()
> +    FileNamePtr = frame.FindVariable ("FileName").GetValueAsUnsigned()
> +    FileNameLen = frame.FindVariable
> ("FileNameLength").GetValueAsUnsigned()
> +    FileName = frame.thread.process.ReadCStringFromMemory (FileNamePtr,
> FileNameLen, Error)
> +    if not Error.Success():
> +        print "!ReadCStringFromMemory() did not find a %d byte C string at
> %x" % (FileNameLen, FileNamePtr)
> +        # make breakpoint command contiue
> +        frame.GetThread().GetProcess().Continue()
> +
> +    debugger = frame.thread.process.target.debugger
> +    if frame.FindVariable ("AddSymbolFlag").GetValueAsUnsigned() == 1:
> +        LoadAddress = frame.FindVariable
> ("LoadAddress").GetValueAsUnsigned()
> +
> +        debugger.HandleCommand ("target modules add  %s" % FileName)
> +        print "target modules load --slid 0x%x %s" % (LoadAddress,
> FileName)
> +        debugger.HandleCommand ("target modules load --slide 0x%x --file
> %s" % (LoadAddress, FileName))
> +    else:
> +        target = debugger.GetSelectedTarget()
> +        for SBModule in target.module_iter():
> +            ModuleName  = SBModule.GetFileSpec().GetDirectory() + '/'
> +            ModuleName += SBModule.GetFileSpec().GetFilename()
> +            if FileName == ModuleName or FileName ==
> SBModule.GetFileSpec().GetFilename():
> +                target.ClearModuleLoadAddress (SBModule)
> +                if not target.RemoveModule (SBModule):
> +                    print "!lldb.target.RemoveModule (%s) FAILED" %
> SBModule
> +
> +    # make breakpoint command contiue
> +    frame.thread.process.Continue()
> +
> +def GuidToCStructStr (guid, Name=False):
> +  #
> +  # Convert a 16-byte bytesarry (or bytearray compat object) to C guid
> string
> +  # { 0xB402621F, 0xA940, 0x1E4A, { 0x86, 0x6B, 0x4D, 0xC9, 0x16, 0x2B,
> 0x34, 0x7C } }
> +  #
> +  # Name=True means lookup name in GuidNameDict and us it if you find it
> +  #
> +
> +  if not isinstance (guid, bytearray):
> +    # convert guid object to UUID, and UUID to bytearray
> +    Uuid = uuid.UUID(guid)
> +    guid = bytearray (Uuid.bytes_le)
> +
> +  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 } }" % \
> +         (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])
> +
> +def ParseGuidString(GuidStr):
> +  #
> +  # Error check and convert C Guid init to string
> +  # ParseGuidString("49152E77-1ADA-4764-B7A2-7AFEFED95E8B")
> +  # ParseGuidString("{ 0xBA24B391, 0x73FD, 0xC54C, { 0x9E, 0xAF, 0x0C,
> 0xA7, 0x8A, 0x35, 0x46, 0xD1 } }")
> +  #
> +
> +  if "{" in GuidStr
> :
> +    # convert C form "{ 0xBA24B391, 0x73FD, 0xC54C, { 0x9E, 0xAF, 0x0C,
> 0xA7, 0x8A, 0x35, 0x46, 0xD1 } }"
> +    # to string form BA24B391-73FD-C54C-9EAF-0CA78A3546D1
> +    # make a list of Hex numbers like: ['0xBA24B391', '0x73FD', '0xC54C',
> '0x9E', '0xAF', '0x0C', '0xA7', '0x8A', '0x35', '0x46', '0xD1']
> +    Hex = ''.join(x for x in GuidStr if x not in '{,}').split()
> +    Str =
> "%08X-%04X-%04X-%02.2X%02.2X-%02.2X%02.2X%02.2X%02.2X%02.2X%02.2X" % \
> +          (int(Hex[0], 0), int(Hex[1], 0), int(Hex[2], 0), int(Hex[3], 0),
> int(Hex[4], 0), \
> +           int(Hex[5], 0), int(Hex[6], 0), int(Hex[7], 0), int(Hex[8], 0),
> int(Hex[9], 0), int(Hex[10], 0))
> +  elif GuidStr.count('-') == 4:
> +    # validate "49152E77-1ADA-4764-B7A2-7AFEFED95E8B" form
> +    Check = "%s" % str(uuid.UUID(GuidStr)).upper()
> +    if GuidStr.upper() == Check:
> +      Str = GuidStr.upper()
> +    else:
> +      Ste = ""
> +  else:
> +    Str = ""
> +
> +  return Str
> +
> +
> +def create_guid_options():
> +    usage = "usage: %prog [data]"
> +    description='''lookup EFI_GUID by CName, C struct, or GUID string and
> print out all three.
> +    '''
> +    parser = optparse.OptionParser(description=description,
> prog='guid',usage=usage)
> +    return parser
> +
> +def efi_guid_command(debugger, command, result, dict):
> +    # Use the Shell Lexer to properly parse up command options just like a
> +    # shell would
> +    command_args = shlex.split(command)
> +    parser = create_guid_options()
> +    try:
> +        (options, args) = parser.parse_args(command_args)
> +        if len(args) >= 1:
> +          if args[0] == "{":
> +              # caller forgot to quote the string"
> +              # mark arg[0] a string containing all args[n]
> +              args[0] = ' '.join(args)
> +          GuidStr = ParseGuidString (args[0])
> +          if GuidStr == "":
> +              # return Key of GuidNameDict for value args[0]
> +              GuidStr = [Key for Key, Value in guid_dict.iteritems() if
> Value == args[0]][0]
> +          GuidStr = GuidStr.upper()
> +    except:
> +        # if you don't handle exceptions, passing an incorrect argument to
> the OptionParser will cause LLDB to exit
> +        # (courtesy of OptParse dealing with argument errors by throwing
> SystemExit)
> +        result.SetError ("option parsing failed")
> +        return
> +
> +
> +    if len(args) >= 1:
> +        if GuidStr in guid_dict:
> +            print "%s = %s" % (guid_dict[GuidStr], GuidStr)
> +            print "%s = %s" % (guid_dict[GuidStr], GuidToCStructStr
> (GuidStr))
> +        else:
> +            print GuidStr
> +    else:
> +        # dump entire dictionary
> +        width = max(len(v) for k,v in guid_dict.iteritems())
> +        for value in sorted(guid_dict, key=guid_dict.get):
> +            print '%-*s %s %s' % (width, guid_dict[value], value,
> GuidToCStructStr(value))
> +
> +    return
> +
> +
> +#
> +########## Code that runs when this script is imported into LLDB
> ###########
> +#
> +def __lldb_init_module (debugger, internal_dict):
> +    # This initializer is being run from LLDB in the embedded command
> interpreter
> +    # Make the options so we can generate the help text for the new LLDB
> +    # command line command prior to registering it with LLDB below
> +
> +    global guid_dict
> +
> +    # Source Guid.xref file if we can find it
> +    inputfile = os.getcwd()
> +    inputfile += os.sep + os.pardir + os.sep + 'FV' + os.sep + 'Guid.xref'
> +    with open(inputfile) as f:
> +        for line in f:
> +            data = line.split(' ')
> +            if len(data) >= 2:
> +                guid_dict[data[0].upper()] = data[1].strip('\n')
> +
> +    # init EFI specific type formaters
> +    TypePrintFormating (debugger)
> +
> +
> +    # add guid command
> +    parser = create_guid_options()
> +    efi_guid_command.__doc__ = parser.format_help()
> +    debugger.HandleCommand('command script add -f lldbefi.efi_guid_command
> guid')
> +
> +
> +    Target = debugger.GetTargetAtIndex(0)
> +    if Target:
> +        Breakpoint = Target.BreakpointCreateByName('SecGdbScriptBreak')
> +        if Breakpoint.GetNumLocations() == 1:
> +            # Set the emulator breakpoints, if we are in the emulator
> +            debugger.HandleCommand("breakpoint command add -s python -F
> lldbefi.LoadEmulatorEfiSymbols {id}".format(id=Breakpoint.GetID()))
> +            print 'Type r to run emulator. SecLldbScriptBreak armed. EFI
> modules should now get source level debugging in the emulator.'
> diff --git a/EmulatorPkg/Unix/lldbinit b/EmulatorPkg/Unix/lldbinit
> new file mode 100644
> index 0000000..16b34e3
> --- /dev/null
> +++ b/EmulatorPkg/Unix/lldbinit
> @@ -0,0 +1,3 @@
> +setting set frame-format "frame #${frame.index}: ${frame.pc}{
> ${module.file.basename}{:${function.name}()${function.pc-offset}}}{ at
> ${line.file.fullpath}:${line.number}}\n"
> +command script import lldbefi.py
> +run
> --
> 1.8.5.2 (Apple Git-48)
>
>
> ------------------------------------------------------------------------------
> Slashdot TV.
> Video for Nerds.  Stuff that matters.
> http://tv.slashdot.org/
> _______________________________________________
> edk2-devel mailing list
> [email protected]
> https://lists.sourceforge.net/lists/listinfo/edk2-devel
>
>
> ------------------------------------------------------------------------------
> Slashdot TV.
> Video for Nerds.  Stuff that matters.
> http://tv.slashdot.org/
> _______________________________________________
> edk2-devel mailing list
> [email protected]
> https://lists.sourceforge.net/lists/listinfo/edk2-devel
>
>
>
> ------------------------------------------------------------------------------
> Slashdot TV.
> Video for Nerds.  Stuff that matters.
> http://tv.slashdot.org/
> _______________________________________________
> edk2-devel mailing list
> [email protected]
> https://lists.sourceforge.net/lists/listinfo/edk2-devel
>

------------------------------------------------------------------------------
Slashdot TV.  
Video for Nerds.  Stuff that matters.
http://tv.slashdot.org/
_______________________________________________
edk2-devel mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/edk2-devel

Reply via email to