# This implements the "diagnose-nsstring" command, usually installed in the debug session like
#   command script import lldb.diagnose
# it is used when NSString summary formatter fails to replicate the logic that went into LLDB making the
# decisions it did and  providing some useful context information that can
# be used for improving the formatter

import lldb


def read_memory(process, location, size):
    data = ""
    error = lldb.SBError()
    for x in range(0, size - 1):
        byte = process.ReadUnsignedFromMemory(x + location, 1, error)
        if error.fail:
            data = data + "err%s" % "" if x == size - 2 else ":"
        else:
            try:
                data = data + "0x%x" % byte
                if byte == 0:
                    data = data + "(\\0)"
                elif byte == 0xA:
                    data = data + "(\\a)"
                elif byte == 0xB:
                    data = data + "(\\b)"
                elif byte == 0xC:
                    data = data + "(\\c)"
                elif byte == "\n":
                    data = data + "(\\n)"
                else:
                    data = data + "(%s)" % chr(byte)
                if x < size - 2:
                    data = data + ":"
            except Exception as e:
                print(e)
    return data


def diagnose_nsstring_Command_Impl(debugger, command, exe_ctx, result, internal_dict):
    """
    A command to diagnose the LLDB NSString data formatter
    invoke as
    (lldb) diagnose-nsstring <expr returning NSString>
    e.g.
    (lldb) diagnose-nsstring @"Hello world"
    """
    target = exe_ctx.target
    process = exe_ctx.process
    frame = exe_ctx.thread
    if not target.IsValid() or not process.IsValid():
        return "unable to get target/process - cannot proceed"
    options = lldb.SBExpressionOptions()
    options.SetFetchDynamicValue()
    error = lldb.SBError()
    if frame.IsValid():
        nsstring = frame.EvaluateExpression(command, options)
    else:
        nsstring = target.EvaluateExpression(command, options)
    print(str(nsstring), file=result)
    nsstring_address = nsstring.GetValueAsUnsigned(0)
    if nsstring_address == 0:
        return "unable to obtain the string - cannot proceed"
    expression = "\
struct $__lldb__notInlineMutable {\
    char* buffer;\
    signed long length;\
    signed long capacity;\
    unsigned int hasGap:1;\
    unsigned int isFixedCapacity:1;\
    unsigned int isExternalMutable:1;\
    unsigned int capacityProvidedExternally:1;\n\
#if __LP64__\n\
    unsigned long desiredCapacity:60;\n\
#else\n\
    unsigned long desiredCapacity:28;\n\
#endif\n\
    void* contentsAllocator;\
};\
\
struct $__lldb__CFString {\
    void* _cfisa;\
    uint8_t _cfinfo[4];\
    uint32_t _rc;\
    union {\
        struct __inline1 {\
            signed long length;\
        } inline1;\
        struct __notInlineImmutable1 {\
            char* buffer;\
            signed long length;\
            void* contentsDeallocator;\
        } notInlineImmutable1;\
        struct __notInlineImmutable2 {\
            char* buffer;\
            void* contentsDeallocator;\
        } notInlineImmutable2;\
        struct $__lldb__notInlineMutable notInlineMutable;\
    } variants;\
};\
"

    expression = expression + "*(($__lldb__CFString*) %d)" % nsstring_address
    # print expression
    dumped = target.EvaluateExpression(expression, options)
    print(str(dumped), file=result)

    little_endian = target.byte_order == lldb.eByteOrderLittle
    ptr_size = target.addr_size

    info_bits = (
        dumped.GetChildMemberWithName("_cfinfo")
        .GetChildAtIndex(0 if little_endian else 3)
        .GetValueAsUnsigned(0)
    )
    is_mutable = (info_bits & 1) == 1
    is_inline = (info_bits & 0x60) == 0
    has_explicit_length = (info_bits & (1 | 4)) != 4
    is_unicode = (info_bits & 0x10) == 0x10
    is_special = (
        nsstring.GetDynamicValue(lldb.eDynamicCanRunTarget).GetTypeName()
        == "NSPathStore2"
    )
    has_null = (info_bits & 8) == 8

    print(
        "\nInfo=%d\nMutable=%s\nInline=%s\nExplicit=%s\nUnicode=%s\nSpecial=%s\nNull=%s\n"
        % (
            info_bits,
            "yes" if is_mutable else "no",
            "yes" if is_inline else "no",
            "yes" if has_explicit_length else "no",
            "yes" if is_unicode else "no",
            "yes" if is_special else "no",
            "yes" if has_null else "no",
        ),
        file=result,
    )

    explicit_length_offset = 0
    if not has_null and has_explicit_length and not is_special:
        explicit_length_offset = 2 * ptr_size
        if is_mutable and not is_inline:
            explicit_length_offset = explicit_length_offset + ptr_size
        elif is_inline:
            pass
        elif not is_inline and not is_mutable:
            explicit_length_offset = explicit_length_offset + ptr_size
        else:
            explicit_length_offset = 0

    if explicit_length_offset == 0:
        print("There is no explicit length marker - skipping this step\n", file=result)
    else:
        explicit_length_offset = nsstring_address + explicit_length_offset
        explicit_length = process.ReadUnsignedFromMemory(
            explicit_length_offset, 4, error
        )
        print(
            "Explicit length location is at 0x%x - read value is %d\n"
            % (explicit_length_offset, explicit_length),
            file=result,
        )

    if is_mutable:
        location = 2 * ptr_size + nsstring_address
        location = process.ReadPointerFromMemory(location, error)
    elif (
        is_inline
        and has_explicit_length
        and not is_unicode
        and not is_special
        and not is_mutable
    ):
        location = 3 * ptr_size + nsstring_address
    elif is_unicode:
        location = 2 * ptr_size + nsstring_address
        if is_inline:
            if not has_explicit_length:
                print(
                    "Unicode & Inline & !Explicit is a new combo - no formula for it",
                    file=result,
                )
            else:
                location += ptr_size
        else:
            location = process.ReadPointerFromMemory(location, error)
    elif is_special:
        location = nsstring_address + ptr_size + 4
    elif is_inline:
        location = 2 * ptr_size + nsstring_address
        if not has_explicit_length:
            location += 1
    else:
        location = 2 * ptr_size + nsstring_address
        location = process.ReadPointerFromMemory(location, error)
    print("Expected data location: 0x%x\n" % (location), file=result)
    print(
        "1K of data around location: %s\n" % read_memory(process, location, 1024),
        file=result,
    )
    print(
        "5K of data around string pointer: %s\n"
        % read_memory(process, nsstring_address, 1024 * 5),
        file=result,
    )


def __lldb_init_module(debugger, internal_dict):
    debugger.HandleCommand(
        "command script add -o -f %s.diagnose_nsstring_Command_Impl diagnose-nsstring"
        % __name__
    )
    print(
        'The "diagnose-nsstring" command has been installed, type "help diagnose-nsstring" for detailed help.'
    )
