[Lldb-commits] [lldb] r254294 - [RS] Support RenderScript struct allocations

Adrian McCarthy via lldb-commits lldb-commits at lists.llvm.org
Mon Nov 30 13:27:29 PST 2015


This revision seems to have created a hang on startup on Windows.  LLDB now
hangs during global static initialization on this line:

const ConstString
RenderScriptRuntime::Element::FallbackStructName("struct");

Perhaps its an initialization order problem?

Adrian.

On Mon, Nov 30, 2015 at 2:29 AM, Ewan Crawford via lldb-commits <
lldb-commits at lists.llvm.org> wrote:

> Author: ewancrawford
> Date: Mon Nov 30 04:29:49 2015
> New Revision: 254294
>
> URL: http://llvm.org/viewvc/llvm-project?rev=254294&view=rev
> Log:
> [RS] Support RenderScript struct allocations
>
> This patch adds functionality for dumping allocations of struct elements.
> This involves:
>
>     + Jitting the runtime for details on all the struct fields.
>
>     + Finding the name of the struct type by looking for a global variable
> of the same type, which will have been reflected back to the java host code.
>
>     + Using this struct type name to pass into expression evaluation for
> pretty printing the data for the dump command.
>
> Modified:
>
> lldb/trunk/source/Plugins/LanguageRuntime/RenderScript/RenderScriptRuntime/RenderScriptRuntime.cpp
>
> lldb/trunk/source/Plugins/LanguageRuntime/RenderScript/RenderScriptRuntime/RenderScriptRuntime.h
>
> Modified:
> lldb/trunk/source/Plugins/LanguageRuntime/RenderScript/RenderScriptRuntime/RenderScriptRuntime.cpp
> URL:
> http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/LanguageRuntime/RenderScript/RenderScriptRuntime/RenderScriptRuntime.cpp?rev=254294&r1=254293&r2=254294&view=diff
>
> ==============================================================================
> ---
> lldb/trunk/source/Plugins/LanguageRuntime/RenderScript/RenderScriptRuntime/RenderScriptRuntime.cpp
> (original)
> +++
> lldb/trunk/source/Plugins/LanguageRuntime/RenderScript/RenderScriptRuntime/RenderScriptRuntime.cpp
> Mon Nov 30 04:29:49 2015
> @@ -18,7 +18,9 @@
>  #include "lldb/Core/Error.h"
>  #include "lldb/Core/Log.h"
>  #include "lldb/Core/PluginManager.h"
> +#include "lldb/Core/ValueObjectVariable.h"
>  #include "lldb/Core/RegularExpression.h"
> +#include "lldb/DataFormatters/DumpValueObjectOptions.h"
>  #include "lldb/Host/StringConvert.h"
>  #include "lldb/Symbol/Symbol.h"
>  #include "lldb/Symbol/Type.h"
> @@ -133,42 +135,61 @@ struct RenderScriptRuntime::ScriptDetail
>      empirical_type<lldb::addr_t> script;
>  };
>
> +// This Element class represents the Element object in RS,
> +// defining the type associated with an Allocation.
> +struct RenderScriptRuntime::Element
> +{
> +    // Taken from rsDefines.h
> +    enum DataKind
> +    {
> +        RS_KIND_USER,
> +        RS_KIND_PIXEL_L = 7,
> +        RS_KIND_PIXEL_A,
> +        RS_KIND_PIXEL_LA,
> +        RS_KIND_PIXEL_RGB,
> +        RS_KIND_PIXEL_RGBA,
> +        RS_KIND_PIXEL_DEPTH,
> +        RS_KIND_PIXEL_YUV,
> +        RS_KIND_INVALID = 100
> +    };
> +
> +    // Taken from rsDefines.h
> +    enum DataType
> +    {
> +        RS_TYPE_NONE = 0,
> +        RS_TYPE_FLOAT_16,
> +        RS_TYPE_FLOAT_32,
> +        RS_TYPE_FLOAT_64,
> +        RS_TYPE_SIGNED_8,
> +        RS_TYPE_SIGNED_16,
> +        RS_TYPE_SIGNED_32,
> +        RS_TYPE_SIGNED_64,
> +        RS_TYPE_UNSIGNED_8,
> +        RS_TYPE_UNSIGNED_16,
> +        RS_TYPE_UNSIGNED_32,
> +        RS_TYPE_UNSIGNED_64,
> +        RS_TYPE_BOOLEAN
> +    };
> +
> +    std::vector<Element> children;                       // Child Element
> fields for structs
> +    empirical_type<lldb::addr_t> element_ptr;            // Pointer to
> the RS Element of the Type
> +    empirical_type<DataType> type;                       // Type of each
> data pointer stored by the allocation
> +    empirical_type<DataKind> type_kind;                  // Defines pixel
> type if Allocation is created from an image
> +    empirical_type<uint32_t> type_vec_size;              // Vector size
> of each data point, e.g '4' for uchar4
> +    empirical_type<uint32_t> field_count;                // Number of
> Subelements
> +    empirical_type<uint32_t> datum_size;                 // Size of a
> single Element with padding
> +    empirical_type<uint32_t> padding;                    // Number of
> padding bytes
> +    empirical_type<uint32_t> array_size;                 // Number of
> items in array, only needed for strucrs
> +    ConstString type_name;                               // Name of type,
> only needed for structs
> +
> +    static const ConstString FallbackStructName;         // Print this as
> the type name of a struct Element
> +                                                         // If we can't
> resolve the actual struct name
> +};
> +
>  // This AllocationDetails class collects data associated with a single
>  // allocation instance.
>  struct RenderScriptRuntime::AllocationDetails
>  {
> -   // Taken from rsDefines.h
> -   enum DataKind
> -   {
> -       RS_KIND_USER,
> -       RS_KIND_PIXEL_L = 7,
> -       RS_KIND_PIXEL_A,
> -       RS_KIND_PIXEL_LA,
> -       RS_KIND_PIXEL_RGB,
> -       RS_KIND_PIXEL_RGBA,
> -       RS_KIND_PIXEL_DEPTH,
> -       RS_KIND_PIXEL_YUV,
> -       RS_KIND_INVALID = 100
> -   };
> -
> -   // Taken from rsDefines.h
> -   enum DataType
> -   {
> -       RS_TYPE_NONE = 0,
> -       RS_TYPE_FLOAT_16,
> -       RS_TYPE_FLOAT_32,
> -       RS_TYPE_FLOAT_64,
> -       RS_TYPE_SIGNED_8,
> -       RS_TYPE_SIGNED_16,
> -       RS_TYPE_SIGNED_32,
> -       RS_TYPE_SIGNED_64,
> -       RS_TYPE_UNSIGNED_8,
> -       RS_TYPE_UNSIGNED_16,
> -       RS_TYPE_UNSIGNED_32,
> -       RS_TYPE_UNSIGNED_64,
> -       RS_TYPE_BOOLEAN
> -    };
> -
>      struct Dimension
>      {
>          uint32_t dim_1;
> @@ -214,14 +235,11 @@ struct RenderScriptRuntime::AllocationDe
>      // for commands to reference it.
>      const unsigned int id;
>
> -    empirical_type<DataType> type;            // Type of each data
> pointer stored by the allocation
> -    empirical_type<DataKind> type_kind;       // Defines pixel type if
> Allocation is created from an image
> -    empirical_type<uint32_t> type_vec_size;   // Vector size of each data
> point, e.g '4' for uchar4
> +    RenderScriptRuntime::Element element;     // Allocation Element type
>      empirical_type<Dimension> dimension;      // Dimensions of the
> Allocation
>      empirical_type<lldb::addr_t> address;     // Pointer to address of
> the RS Allocation
>      empirical_type<lldb::addr_t> data_ptr;    // Pointer to the data held
> by the Allocation
>      empirical_type<lldb::addr_t> type_ptr;    // Pointer to the RS Type
> of the Allocation
> -    empirical_type<lldb::addr_t> element_ptr; // Pointer to the RS
> Element of the Type
>      empirical_type<lldb::addr_t> context;     // Pointer to the RS
> Context of the Allocation
>      empirical_type<uint32_t> size;            // Size of the allocation
>      empirical_type<uint32_t> stride;          // Stride between rows of
> the allocation
> @@ -232,6 +250,8 @@ struct RenderScriptRuntime::AllocationDe
>      }
>  };
>
> +const ConstString
> RenderScriptRuntime::Element::FallbackStructName("struct");
> +
>  unsigned int RenderScriptRuntime::AllocationDetails::ID = 1;
>
>  const char* RenderScriptRuntime::AllocationDetails::RsDataKindToString[] =
> @@ -1099,7 +1119,11 @@ enum ExpressionStrings
>     eExprTypeElemPtr,
>     eExprElementType,
>     eExprElementKind,
> -   eExprElementVec
> +   eExprElementVec,
> +   eExprElementFieldCount,
> +   eExprSubelementsId,
> +   eExprSubelementsName,
> +   eExprSubelementsArrSize
>  };
>
>  // Format strings containing the expressions we may need to evaluate.
> @@ -1122,9 +1146,22 @@ const char runtimeExpressions[][256] =
>
>   // rsaElementGetNativeData(Context*, Element*, uint32_t* elemData,size)
>   // Pack mType; mKind; mNormalized; mVectorSize; NumSubElements into
> elemData
> - "uint32_t data[6]; (void*)rsaElementGetNativeData(0x%lx, 0x%lx, data,
> 5); data[0]", // Type
> - "uint32_t data[6]; (void*)rsaElementGetNativeData(0x%lx, 0x%lx, data,
> 5); data[1]", // Kind
> - "uint32_t data[6]; (void*)rsaElementGetNativeData(0x%lx, 0x%lx, data,
> 5); data[3]"  // Vector Size
> + "uint32_t data[5]; (void*)rsaElementGetNativeData(0x%lx, 0x%lx, data,
> 5); data[0]", // Type
> + "uint32_t data[5]; (void*)rsaElementGetNativeData(0x%lx, 0x%lx, data,
> 5); data[1]", // Kind
> + "uint32_t data[5]; (void*)rsaElementGetNativeData(0x%lx, 0x%lx, data,
> 5); data[3]", // Vector Size
> + "uint32_t data[5]; (void*)rsaElementGetNativeData(0x%lx, 0x%lx, data,
> 5); data[4]", // Field Count
> +
> +  // rsaElementGetSubElements(RsContext con, RsElement elem, uintptr_t
> *ids, const char **names,
> +  // size_t *arraySizes, uint32_t dataSize)
> +  // Needed for Allocations of structs to gather details about
> fields/Subelements
> + "void* ids[%u]; const char* names[%u]; size_t arr_size[%u];"
> + "(void*)rsaElementGetSubElements(0x%lx, 0x%lx, ids, names, arr_size,
> %u); ids[%u]",     // Element* of field
> +
> + "void* ids[%u]; const char* names[%u]; size_t arr_size[%u];"
> + "(void*)rsaElementGetSubElements(0x%lx, 0x%lx, ids, names, arr_size,
> %u); names[%u]",   // Name of field
> +
> + "void* ids[%u]; const char* names[%u]; size_t arr_size[%u];"
> + "(void*)rsaElementGetSubElements(0x%lx, 0x%lx, ids, names, arr_size,
> %u); arr_size[%u]" // Array size of field
>  };
>
>  // JITs the RS runtime for the internal data pointer of an allocation.
> @@ -1272,7 +1309,7 @@ RenderScriptRuntime::JITTypePacked(Alloc
>      allocation->dimension = dims;
>
>      addr_t elem_ptr = static_cast<lldb::addr_t>(results[3]);
> -    allocation->element_ptr = elem_ptr;
> +    allocation->element.element_ptr = elem_ptr;
>
>      if (log)
>          log->Printf("RenderScriptRuntime::JITTypePacked - dims (%u, %u,
> %u) Element*: 0x%" PRIx64,
> @@ -1282,23 +1319,23 @@ RenderScriptRuntime::JITTypePacked(Alloc
>  }
>
>  // JITs the RS runtime for information about the Element of an allocation
> -// Then sets type, type_vec_size, and type_kind members in Allocation
> with the result.
> +// Then sets type, type_vec_size, field_count and type_kind members in
> Element with the result.
>  // Returns true on success, false otherwise
>  bool
> -RenderScriptRuntime::JITElementPacked(AllocationDetails* allocation,
> StackFrame* frame_ptr)
> +RenderScriptRuntime::JITElementPacked(Element& elem, const lldb::addr_t
> context, StackFrame* frame_ptr)
>  {
>      Log* log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_LANGUAGE));
>
> -    if (!allocation->element_ptr.isValid() ||
> !allocation->context.isValid())
> +    if (!elem.element_ptr.isValid())
>      {
>          if (log)
>              log->Printf("RenderScriptRuntime::JITElementPacked - Failed
> to find allocation details");
>          return false;
>      }
>
> -    // We want 3 elements from packed data
> -    const unsigned int num_exprs = 3;
> -    assert(num_exprs == (eExprElementVec - eExprElementType + 1) &&
> "Invalid number of expressions");
> +    // We want 4 elements from packed data
> +    const unsigned int num_exprs = 4;
> +    assert(num_exprs == (eExprElementFieldCount - eExprElementType + 1)
> && "Invalid number of expressions");
>
>      const int max_expr_size = 512; // Max expression size
>      char buffer[num_exprs][max_expr_size];
> @@ -1306,11 +1343,11 @@ RenderScriptRuntime::JITElementPacked(Al
>
>      for (unsigned int i = 0; i < num_exprs; i++)
>      {
> -        int chars_written = snprintf(buffer[i], max_expr_size,
> runtimeExpressions[eExprElementType + i], *allocation->context.get(),
> *allocation->element_ptr.get());
> +        int chars_written = snprintf(buffer[i], max_expr_size,
> runtimeExpressions[eExprElementType + i], context, *elem.element_ptr.get());
>          if (chars_written < 0)
>          {
>              if (log)
> -                log->Printf("RenderScriptRuntime::JITDataPointer -
> Encoding error in snprintf()");
> +                log->Printf("RenderScriptRuntime::JITElementPacked -
> Encoding error in snprintf()");
>              return false;
>          }
>          else if (chars_written >= max_expr_size)
> @@ -1326,13 +1363,109 @@ RenderScriptRuntime::JITElementPacked(Al
>      }
>
>      // Assign results to allocation members
> -    allocation->type =
> static_cast<RenderScriptRuntime::AllocationDetails::DataType>(results[0]);
> -    allocation->type_kind =
> static_cast<RenderScriptRuntime::AllocationDetails::DataKind>(results[1]);
> -    allocation->type_vec_size = static_cast<uint32_t>(results[2]);
> +    elem.type =
> static_cast<RenderScriptRuntime::Element::DataType>(results[0]);
> +    elem.type_kind =
> static_cast<RenderScriptRuntime::Element::DataKind>(results[1]);
> +    elem.type_vec_size = static_cast<uint32_t>(results[2]);
> +    elem.field_count = static_cast<uint32_t>(results[3]);
>
>      if (log)
> -        log->Printf("RenderScriptRuntime::JITElementPacked - data type
> %u, pixel type %u, vector size %u",
> -                    *allocation->type.get(),
> *allocation->type_kind.get(), *allocation->type_vec_size.get());
> +        log->Printf("RenderScriptRuntime::JITElementPacked - data type
> %u, pixel type %u, vector size %u, field count %u",
> +                    *elem.type.get(), *elem.type_kind.get(),
> *elem.type_vec_size.get(), *elem.field_count.get());
> +
> +    // If this Element has subelements then JIT
> rsaElementGetSubElements() for details about its fields
> +    if (*elem.field_count.get() > 0 && !JITSubelements(elem, context,
> frame_ptr))
> +        return false;
> +
> +    return true;
> +}
> +
> +// JITs the RS runtime for information about the subelements/fields of a
> struct allocation
> +// This is necessary for infering the struct type so we can pretty print
> the allocation's contents.
> +// Returns true on success, false otherwise
> +bool
> +RenderScriptRuntime::JITSubelements(Element& elem, const lldb::addr_t
> context, StackFrame* frame_ptr)
> +{
> +    Log* log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_LANGUAGE));
> +
> +    if (!elem.element_ptr.isValid() || !elem.field_count.isValid())
> +    {
> +        if (log)
> +            log->Printf("RenderScriptRuntime::JITSubelements - Failed to
> find allocation details");
> +        return false;
> +    }
> +
> +    const short num_exprs = 3;
> +    assert(num_exprs == (eExprSubelementsArrSize - eExprSubelementsId +
> 1) && "Invalid number of expressions");
> +
> +    const int max_expr_size = 512; // Max expression size
> +    char expr_buffer[max_expr_size];
> +    uint64_t results;
> +
> +    // Iterate over struct fields.
> +    const uint32_t field_count = *elem.field_count.get();
> +    for (unsigned int field_index = 0; field_index < field_count;
> ++field_index)
> +    {
> +        Element child;
> +        for (unsigned int expr_index = 0; expr_index < num_exprs;
> ++expr_index)
> +        {
> +            int chars_written = snprintf(expr_buffer, max_expr_size,
> runtimeExpressions[eExprSubelementsId + expr_index],
> +                                         field_count, field_count,
> field_count,
> +                                         context,
> *elem.element_ptr.get(), field_count, field_index);
> +            if (chars_written < 0)
> +            {
> +                if (log)
> +                    log->Printf("RenderScriptRuntime::JITSubelements -
> Encoding error in snprintf()");
> +                return false;
> +            }
> +            else if (chars_written >= max_expr_size)
> +            {
> +                if (log)
> +                    log->Printf("RenderScriptRuntime::JITSubelements -
> Expression too long");
> +                return false;
> +            }
> +
> +            // Perform expression evaluation
> +            if (!EvalRSExpression(expr_buffer, frame_ptr, &results))
> +                return false;
> +
> +            if (log)
> +                log->Printf("RenderScriptRuntime::JITSubelements - Expr
> result 0x%" PRIx64, results);
> +
> +            switch(expr_index)
> +            {
> +                case 0: // Element* of child
> +                    child.element_ptr = static_cast<addr_t>(results);
> +                    break;
> +                case 1: // Name of child
> +                {
> +                    lldb::addr_t address = static_cast<addr_t>(results);
> +                    Error err;
> +                    std::string name;
> +                    GetProcess()->ReadCStringFromMemory(address, name,
> err);
> +                    if (!err.Fail())
> +                        child.type_name = ConstString(name);
> +                    else
> +                    {
> +                        if (log)
> +
> log->Printf("RenderScriptRuntime::JITSubelements - Warning: Couldn't read
> field name");
> +                    }
> +                    break;
> +                }
> +                case 2: // Array size of child
> +                    child.array_size = static_cast<uint32_t>(results);
> +                    break;
> +            }
> +        }
> +
> +        // We need to recursively JIT each Element field of the struct
> since
> +        // structs can be nested inside structs.
> +        if (!JITElementPacked(child, context, frame_ptr))
> +            return false;
> +        elem.children.push_back(child);
> +    }
> +
> +    // Try to infer the name of the struct type so we can pretty print
> the allocation contents.
> +    FindStructTypeName(elem, frame_ptr);
>
>      return true;
>  }
> @@ -1343,28 +1476,43 @@ RenderScriptRuntime::JITElementPacked(Al
>  // Using this offset minus the starting address we can calculate the size
> of the allocation.
>  // Returns true on success, false otherwise
>  bool
> -RenderScriptRuntime::JITAllocationSize(AllocationDetails* allocation,
> StackFrame* frame_ptr,
> -                                       const uint32_t elem_size)
> +RenderScriptRuntime::JITAllocationSize(AllocationDetails* allocation,
> StackFrame* frame_ptr)
>  {
>      Log* log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_LANGUAGE));
>
>      if (!allocation->address.isValid() || !allocation->dimension.isValid()
> -        || !allocation->data_ptr.isValid())
> +        || !allocation->data_ptr.isValid() ||
> !allocation->element.datum_size.isValid())
>      {
>          if (log)
>              log->Printf("RenderScriptRuntime::JITAllocationSize - Failed
> to find allocation details");
>          return false;
>      }
>
> -    const char* expr_cstr = runtimeExpressions[eExprGetOffsetPtr];
> -    const int max_expr_size = 512; // Max expression size
> -    char buffer[max_expr_size];
> -
>      // Find dimensions
>      unsigned int dim_x = allocation->dimension.get()->dim_1;
>      unsigned int dim_y = allocation->dimension.get()->dim_2;
>      unsigned int dim_z = allocation->dimension.get()->dim_3;
>
> +    // Our plan of jitting the last element address doesn't seem to work
> for struct Allocations
> +    // Instead try to infer the size ourselves without any inter element
> padding.
> +    if (allocation->element.children.size() > 0)
> +    {
> +        if (dim_x == 0) dim_x = 1;
> +        if (dim_y == 0) dim_y = 1;
> +        if (dim_z == 0) dim_z = 1;
> +
> +        allocation->size = dim_x * dim_y * dim_z *
> *allocation->element.datum_size.get();
> +
> +        if (log)
> +            log->Printf("RenderScriptRuntime::JITAllocationSize - Infered
> size of struct allocation %u", *allocation->size.get());
> +
> +        return true;
> +    }
> +
> +    const char* expr_cstr = runtimeExpressions[eExprGetOffsetPtr];
> +    const int max_expr_size = 512;
> +    char buffer[max_expr_size];
> +
>      // Calculate last element
>      dim_x = dim_x == 0 ? 0 : dim_x - 1;
>      dim_y = dim_y == 0 ? 0 : dim_y - 1;
> @@ -1391,7 +1539,7 @@ RenderScriptRuntime::JITAllocationSize(A
>
>      addr_t mem_ptr = static_cast<lldb::addr_t>(result);
>      // Find pointer to last element and add on size of an element
> -    allocation->size = static_cast<uint32_t>(mem_ptr -
> *allocation->data_ptr.get()) + elem_size;
> +    allocation->size = static_cast<uint32_t>(mem_ptr -
> *allocation->data_ptr.get()) + *allocation->element.datum_size.get();
>
>      return true;
>  }
> @@ -1457,31 +1605,140 @@ RenderScriptRuntime::RefreshAllocation(A
>          return false;
>
>      // rsaElementGetNativeData()
> -    if (!JITElementPacked(allocation, frame_ptr))
> +    if (!JITElementPacked(allocation->element,
> *allocation->context.get(), frame_ptr))
>          return false;
>
> +    // Sets the datum_size member in Element
> +    SetElementSize(allocation->element);
> +
>      // Use GetOffsetPointer() to infer size of the allocation
> -    const unsigned int element_size = GetElementSize(allocation);
> -    if (!JITAllocationSize(allocation, frame_ptr, element_size))
> +    if (!JITAllocationSize(allocation, frame_ptr))
>          return false;
>
>      return true;
>  }
>
> -// Returns the size of a single allocation element including padding.
> +// Function attempts to set the type_name member of the paramaterised
> Element object.
> +// This string should be the name of the struct type the Element
> represents.
> +// We need this string for pretty printing the Element to users.
> +void
> +RenderScriptRuntime::FindStructTypeName(Element& elem, StackFrame*
> frame_ptr)
> +{
> +    Log* log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_LANGUAGE));
> +
> +    if (!elem.type_name.IsEmpty()) // Name already set
> +        return;
> +    else
> +        elem.type_name = Element::FallbackStructName; // Default type
> name if we don't succeed
> +
> +    // Find all the global variables from the script rs modules
> +    VariableList variable_list;
> +    for (auto module_sp : m_rsmodules)
> +        module_sp->m_module->FindGlobalVariables(RegularExpression("."),
> true, UINT32_MAX, variable_list);
> +
> +    // Iterate over all the global variables looking for one with a
> matching type to the Element.
> +    // We make the assumption a match exists since there needs to be a
> global variable to reflect the
> +    // struct type back into java host code.
> +    for (uint32_t var_index = 0; var_index < variable_list.GetSize();
> ++var_index)
> +    {
> +        const VariableSP
> var_sp(variable_list.GetVariableAtIndex(var_index));
> +        if (!var_sp)
> +           continue;
> +
> +        ValueObjectSP valobj_sp = ValueObjectVariable::Create(frame_ptr,
> var_sp);
> +        if (!valobj_sp)
> +            continue;
> +
> +        // Find the number of variable fields.
> +        // If it has no fields, or more fields than our Element, then it
> can't be the struct we're looking for.
> +        // Don't check for equality since RS can add extra struct members
> for padding.
> +        size_t num_children = valobj_sp->GetNumChildren();
> +        if (num_children > elem.children.size() || num_children == 0)
> +            continue;
> +
> +        // Iterate over children looking for members with matching field
> names.
> +        // If all the field names match, this is likely the struct we
> want.
> +        //
> +        //   TODO: This could be made more robust by also checking
> children data sizes, or array size
> +        bool found = true;
> +        for (size_t child_index = 0; child_index < num_children;
> ++child_index)
> +        {
> +            ValueObjectSP child = valobj_sp->GetChildAtIndex(child_index,
> true);
> +            if (!child || (child->GetName() !=
> elem.children[child_index].type_name))
> +            {
> +                found = false;
> +                break;
> +            }
> +        }
> +
> +        // RS can add extra struct members for padding in the format
> '#rs_padding_[0-9]+'
> +        if (found && num_children < elem.children.size())
> +        {
> +            const unsigned int size_diff = elem.children.size() -
> num_children;
> +            if (log)
> +                log->Printf("RenderScriptRuntime::FindStructTypeName - %u
> padding struct entries", size_diff);
> +
> +            for (unsigned int padding_index = 0; padding_index <
> size_diff; ++padding_index)
> +            {
> +                const ConstString& name = elem.children[num_children +
> padding_index].type_name;
> +                if (strcmp(name.AsCString(), "#rs_padding") < 0)
> +                    found = false;
> +            }
> +        }
> +
> +        // We've found a global var with matching type
> +        if (found)
> +        {
> +            // Dereference since our Element type isn't a pointer.
> +            if (valobj_sp->IsPointerType())
> +            {
> +                Error err;
> +                ValueObjectSP deref_valobj = valobj_sp->Dereference(err);
> +                if (!err.Fail())
> +                    valobj_sp = deref_valobj;
> +            }
> +
> +            // Save name of variable in Element.
> +            elem.type_name = valobj_sp->GetTypeName();
> +            if (log)
> +                log->Printf("RenderScriptRuntime::FindStructTypeName -
> Element name set to %s", elem.type_name.AsCString());
> +
> +            return;
> +        }
> +    }
> +}
> +
> +// Function sets the datum_size member of Element. Representing the size
> of a single instance including padding.
>  // Assumes the relevant allocation information has already been jitted.
> -unsigned int
> -RenderScriptRuntime::GetElementSize(const AllocationDetails* allocation)
> +void
> +RenderScriptRuntime::SetElementSize(Element& elem)
>  {
> -    const AllocationDetails::DataType type = *allocation->type.get();
> -    assert(type >= AllocationDetails::RS_TYPE_NONE && type <=
> AllocationDetails::RS_TYPE_BOOLEAN
> +    Log* log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_LANGUAGE));
> +    const Element::DataType type = *elem.type.get();
> +    assert(type >= Element::RS_TYPE_NONE && type <=
> Element::RS_TYPE_BOOLEAN
>                                                     && "Invalid allocation
> type");
>
> -    const unsigned int vec_size = *allocation->type_vec_size.get();
> -    const unsigned int data_size = vec_size *
> AllocationDetails::RSTypeToFormat[type][eElementSize];
> +    const unsigned int vec_size = *elem.type_vec_size.get();
> +    unsigned int data_size = 0;
>      const unsigned int padding = vec_size == 3 ?
> AllocationDetails::RSTypeToFormat[type][eElementSize] : 0;
>
> -    return data_size + padding;
> +    // Element is of a struct type, calculate size recursively.
> +    if ((type == Element::RS_TYPE_NONE) && (elem.children.size() > 0))
> +    {
> +        for (Element& child : elem.children)
> +        {
> +            SetElementSize(child);
> +            const unsigned int array_size = child.array_size.isValid() ?
> *child.array_size.get() : 1;
> +            data_size += *child.datum_size.get() * array_size;
> +        }
> +    }
> +    else
> +        data_size = vec_size *
> AllocationDetails::RSTypeToFormat[type][eElementSize];
> +
> +    elem.padding = padding;
> +    elem.datum_size = data_size + padding;
> +    if (log)
> +        log->Printf("RenderScriptRuntime::SetElementSize - element size
> set to %u", data_size + padding);
>  }
>
>  // Given an allocation, this function copies the allocation contents from
> device into a buffer on the heap.
> @@ -1492,8 +1749,8 @@ RenderScriptRuntime::GetAllocationData(A
>      Log* log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_LANGUAGE));
>
>      // JIT all the allocation details
> -    if (!allocation->data_ptr.isValid() || !allocation->type.isValid() ||
> !allocation->type_vec_size.isValid()
> -        || !allocation->size.isValid())
> +    if (!allocation->data_ptr.isValid() ||
> !allocation->element.type.isValid()
> +        || !allocation->element.type_vec_size.isValid() ||
> !allocation->size.isValid())
>      {
>          if (log)
>              log->Printf("RenderScriptRuntime::GetAllocationData -
> Allocation details not calculated yet, jitting info");
> @@ -1506,7 +1763,7 @@ RenderScriptRuntime::GetAllocationData(A
>          }
>      }
>
> -    assert(allocation->data_ptr.isValid() && allocation->type.isValid()
> && allocation->type_vec_size.isValid()
> +    assert(allocation->data_ptr.isValid() &&
> allocation->element.type.isValid() &&
> allocation->element.type_vec_size.isValid()
>             && allocation->size.isValid() && "Allocation information not
> available");
>
>      // Allocate a buffer to copy data into
> @@ -1551,7 +1808,8 @@ RenderScriptRuntime::LoadAllocation(Stre
>          log->Printf("RenderScriptRuntime::LoadAllocation - Found
> allocation 0x%" PRIx64, *alloc->address.get());
>
>      // JIT all the allocation details
> -    if (!alloc->data_ptr.isValid() || !alloc->type.isValid() ||
> !alloc->type_vec_size.isValid() || !alloc->size.isValid())
> +    if (!alloc->data_ptr.isValid() || !alloc->element.type.isValid() ||
> !alloc->element.datum_size.isValid()
> +        || !alloc->element.type_vec_size.isValid() ||
> !alloc->size.isValid())
>      {
>          if (log)
>              log->Printf("RenderScriptRuntime::LoadAllocation - Allocation
> details not calculated yet, jitting info");
> @@ -1564,8 +1822,8 @@ RenderScriptRuntime::LoadAllocation(Stre
>          }
>      }
>
> -    assert(alloc->data_ptr.isValid() && alloc->type.isValid() &&
> alloc->type_vec_size.isValid() && alloc->size.isValid()
> -           && "Allocation information not available");
> +    assert(alloc->data_ptr.isValid() && alloc->element.type.isValid() &&
> alloc->element.type_vec_size.isValid()
> +           && alloc->size.isValid() &&
> alloc->element.datum_size.isValid() && "Allocation information not
> available");
>
>      // Check we can read from file
>      FileSpec file(filename, true);
> @@ -1598,16 +1856,15 @@ RenderScriptRuntime::LoadAllocation(Stre
>                      head->type, head->element_size);
>
>      // Check if the target allocation and file both have the same number
> of bytes for an Element
> -    const unsigned int elem_size = GetElementSize(alloc);
> -    if (elem_size != head->element_size)
> +    if (*alloc->element.datum_size.get() != head->element_size)
>      {
>          strm.Printf("Warning: Mismatched Element sizes - file %u bytes,
> allocation %u bytes",
> -                    head->element_size, elem_size);
> +                    head->element_size, *alloc->element.datum_size.get());
>          strm.EOL();
>      }
>
>      // Check if the target allocation and file both have the same
> integral type
> -    const unsigned int type = static_cast<unsigned
> int>(*alloc->type.get());
> +    const unsigned int type = static_cast<unsigned
> int>(*alloc->element.type.get());
>      if (type != head->type)
>      {
>          const char* file_type_cstr =
> AllocationDetails::RsDataTypeToString[head->type][0];
> @@ -1665,8 +1922,8 @@ RenderScriptRuntime::SaveAllocation(Stre
>          log->Printf("RenderScriptRuntime::SaveAllocation - Found
> allocation 0x%" PRIx64, *alloc->address.get());
>
>       // JIT all the allocation details
> -    if (!alloc->data_ptr.isValid() || !alloc->type.isValid() ||
> !alloc->type_vec_size.isValid()
> -        || !alloc->type_kind.isValid() || !alloc->dimension.isValid())
> +    if (!alloc->data_ptr.isValid() || !alloc->element.type.isValid() ||
> !alloc->element.type_vec_size.isValid()
> +        || !alloc->element.type_kind.isValid() ||
> !alloc->dimension.isValid())
>      {
>          if (log)
>              log->Printf("RenderScriptRuntime::SaveAllocation - Allocation
> details not calculated yet, jitting info");
> @@ -1679,8 +1936,8 @@ RenderScriptRuntime::SaveAllocation(Stre
>          }
>      }
>
> -    assert(alloc->data_ptr.isValid() && alloc->type.isValid() &&
> alloc->type_vec_size.isValid() && alloc->type_kind.isValid()
> -           && alloc->dimension.isValid() && "Allocation information not
> available");
> +    assert(alloc->data_ptr.isValid() && alloc->element.type.isValid() &&
> alloc->element.type_vec_size.isValid() && alloc->element.datum_size.get()
> +           && alloc->element.type_kind.isValid() &&
> alloc->dimension.isValid() && "Allocation information not available");
>
>      // Check we can create writable file
>      FileSpec file_spec(filename, true);
> @@ -1705,12 +1962,12 @@ RenderScriptRuntime::SaveAllocation(Stre
>      AllocationDetails::FileHeader head;
>      head.ident[0] = 'R'; head.ident[1] = 'S'; head.ident[2] = 'A';
> head.ident[3] = 'D';
>      head.hdr_size =
> static_cast<uint16_t>(sizeof(AllocationDetails::FileHeader));
> -    head.type = static_cast<uint16_t>(*alloc->type.get());
> -    head.kind = static_cast<uint32_t>(*alloc->type_kind.get());
> +    head.type = static_cast<uint16_t>(*alloc->element.type.get());
> +    head.kind = static_cast<uint32_t>(*alloc->element.type_kind.get());
>      head.dims[0] = static_cast<uint32_t>(alloc->dimension.get()->dim_1);
>      head.dims[1] = static_cast<uint32_t>(alloc->dimension.get()->dim_2);
>      head.dims[2] = static_cast<uint32_t>(alloc->dimension.get()->dim_3);
> -    head.element_size = static_cast<uint32_t>(GetElementSize(alloc));
> +    head.element_size =
> static_cast<uint32_t>(*alloc->element.datum_size.get());
>
>      // Write the file header
>      size_t num_bytes = sizeof(AllocationDetails::FileHeader);
> @@ -2080,8 +2337,8 @@ RenderScriptRuntime::DumpAllocation(Stre
>          log->Printf("RenderScriptRuntime::DumpAllocation - Found
> allocation 0x%" PRIx64, *alloc->address.get());
>
>      // Check we have information about the allocation, if not calculate it
> -    if (!alloc->data_ptr.isValid() || !alloc->type.isValid() ||
> -        !alloc->type_vec_size.isValid() || !alloc->dimension.isValid())
> +    if (!alloc->data_ptr.isValid() || !alloc->element.type.isValid() ||
> +        !alloc->element.type_vec_size.isValid() ||
> !alloc->dimension.isValid() || !alloc->element.datum_size.isValid())
>      {
>          if (log)
>              log->Printf("RenderScriptRuntime::DumpAllocation - Allocation
> details not calculated yet, jitting info");
> @@ -2096,22 +2353,19 @@ RenderScriptRuntime::DumpAllocation(Stre
>      }
>
>      // Establish format and size of each data element
> -    const unsigned int vec_size = *alloc->type_vec_size.get();
> -    const AllocationDetails::DataType type = *alloc->type.get();
> +    const unsigned int vec_size = *alloc->element.type_vec_size.get();
> +    const Element::DataType type = *alloc->element.type.get();
>
> -    assert(type >= AllocationDetails::RS_TYPE_NONE && type <=
> AllocationDetails::RS_TYPE_BOOLEAN
> +    assert(type >= Element::RS_TYPE_NONE && type <=
> Element::RS_TYPE_BOOLEAN
>                                                     && "Invalid allocation
> type");
>
>      lldb::Format format = vec_size == 1 ?
> static_cast<lldb::Format>(AllocationDetails::RSTypeToFormat[type][eFormatSingle])
>                                          :
> static_cast<lldb::Format>(AllocationDetails::RSTypeToFormat[type][eFormatVector]);
>
> -    const unsigned int data_size = vec_size *
> AllocationDetails::RSTypeToFormat[type][eElementSize];
> -    // Renderscript pads vector 3 elements to vector 4
> -    const unsigned int elem_padding = vec_size == 3 ?
> AllocationDetails::RSTypeToFormat[type][eElementSize] : 0;
> +    const unsigned int data_size = *alloc->element.datum_size.get();
>
>      if (log)
> -        log->Printf("RenderScriptRuntime::DumpAllocation - Element size
> %u bytes, element padding %u bytes",
> -                    data_size, elem_padding);
> +        log->Printf("RenderScriptRuntime::DumpAllocation - Element size
> %u bytes, including padding", data_size);
>
>      // Allocate a buffer to copy data into
>      std::shared_ptr<uint8_t> buffer = GetAllocationData(alloc, frame_ptr);
> @@ -2136,10 +2390,10 @@ RenderScriptRuntime::DumpAllocation(Stre
>          }
>      }
>      const unsigned int stride = *alloc->stride.get();
> -    const unsigned int size = *alloc->size.get(); //size of last element
> -
> +    const unsigned int size = *alloc->size.get(); // Size of whole
> allocation
> +    const unsigned int padding = alloc->element.padding.isValid() ?
> *alloc->element.padding.get() : 0;
>      if (log)
> -        log->Printf("RenderScriptRuntime::DumpAllocation - stride %u
> bytes, size %u bytes", stride, size);
> +        log->Printf("RenderScriptRuntime::DumpAllocation - stride %u
> bytes, size %u bytes, padding %u", stride, size, padding);
>
>      // Find dimensions used to index loops, so need to be non-zero
>      unsigned int dim_x = alloc->dimension.get()->dim_1;
> @@ -2173,8 +2427,41 @@ RenderScriptRuntime::DumpAllocation(Stre
>              for (unsigned int x = 0; x < dim_x; ++x)
>              {
>                  strm.Printf("\n(%u, %u, %u) = ", x, y, z);
> -                alloc_data.Dump(&strm, offset, format, data_size, 1, 1,
> LLDB_INVALID_ADDRESS, 0, 0);
> -                offset += data_size + elem_padding;
> +                if ((type == Element::RS_TYPE_NONE) &&
> (alloc->element.children.size() > 0) &&
> +                    (alloc->element.type_name !=
> Element::FallbackStructName))
> +                {
> +                    // Here we are dumping an Element of struct type.
> +                    // This is done using expression evaluation with the
> name of the struct type and pointer to element.
> +
> +                    // Don't print the name of the resulting expression,
> since this will be '$[0-9]+'
> +                    DumpValueObjectOptions expr_options;
> +                    expr_options.SetHideName(true);
> +
> +                    // Setup expression as derefrencing a pointer cast to
> element address.
> +                    const int max_expr_size = 512;
> +                    char expr_char_buffer[max_expr_size];
> +                    int chars_written = snprintf(expr_char_buffer,
> max_expr_size, "*(%s*) 0x%" PRIx64,
> +
> alloc->element.type_name.AsCString(), *alloc->data_ptr.get() + offset);
> +
> +                    if (chars_written < 0 || chars_written >=
> max_expr_size)
> +                    {
> +                        if (log)
> +
> log->Printf("RenderScriptRuntime::DumpAllocation- Error in snprintf()");
> +                        continue;
> +                    }
> +
> +                    // Evaluate expression
> +                    ValueObjectSP expr_result;
> +
> GetProcess()->GetTarget().EvaluateExpression(expr_char_buffer, frame_ptr,
> expr_result);
> +
> +                    // Print the results to our stream.
> +                    expr_result->Dump(strm, expr_options);
> +                }
> +                else
> +                {
> +                    alloc_data.Dump(&strm, offset, format, data_size -
> padding, 1, 1, LLDB_INVALID_ADDRESS, 0, 0);
> +                }
> +                offset += data_size;
>              }
>          }
>      }
> @@ -2234,27 +2521,29 @@ RenderScriptRuntime::ListAllocations(Str
>                                            alloc->dimension.get()->dim_3);
>
>          strm.Indent("Data Type: ");
> -        if (!alloc->type.isValid() || !alloc->type_vec_size.isValid())
> +        if (!alloc->element.type.isValid() ||
> !alloc->element.type_vec_size.isValid())
>              strm.Printf("unknown\n");
>          else
>          {
> -            const int vector_size = *alloc->type_vec_size.get();
> -            const AllocationDetails::DataType type = *alloc->type.get();
> +            const int vector_size = *alloc->element.type_vec_size.get();
> +            const Element::DataType type = *alloc->element.type.get();
>
> -            if (vector_size > 4 || vector_size < 1 ||
> -                type < AllocationDetails::RS_TYPE_NONE || type >
> AllocationDetails::RS_TYPE_BOOLEAN)
> +            if (!alloc->element.type_name.IsEmpty())
> +                strm.Printf("%s\n", alloc->element.type_name.AsCString());
> +            else if (vector_size > 4 || vector_size < 1 ||
> +                type < Element::RS_TYPE_NONE || type >
> Element::RS_TYPE_BOOLEAN)
>                  strm.Printf("invalid type\n");
>              else
>                  strm.Printf("%s\n",
> AllocationDetails::RsDataTypeToString[static_cast<unsigned
> int>(type)][vector_size-1]);
>          }
>
>          strm.Indent("Data Kind: ");
> -        if (!alloc->type_kind.isValid())
> +        if (!alloc->element.type_kind.isValid())
>              strm.Printf("unknown\n");
>          else
>          {
> -            const AllocationDetails::DataKind kind =
> *alloc->type_kind.get();
> -            if (kind < AllocationDetails::RS_KIND_USER || kind >
> AllocationDetails::RS_KIND_PIXEL_YUV)
> +            const Element::DataKind kind =
> *alloc->element.type_kind.get();
> +            if (kind < Element::RS_KIND_USER || kind >
> Element::RS_KIND_PIXEL_YUV)
>                  strm.Printf("invalid kind\n");
>              else
>                  strm.Printf("%s\n",
> AllocationDetails::RsDataKindToString[static_cast<unsigned int>(kind)]);
>
> Modified:
> lldb/trunk/source/Plugins/LanguageRuntime/RenderScript/RenderScriptRuntime/RenderScriptRuntime.h
> URL:
> http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/LanguageRuntime/RenderScript/RenderScriptRuntime/RenderScriptRuntime.h?rev=254294&r1=254293&r2=254294&view=diff
>
> ==============================================================================
> ---
> lldb/trunk/source/Plugins/LanguageRuntime/RenderScript/RenderScriptRuntime/RenderScriptRuntime.h
> (original)
> +++
> lldb/trunk/source/Plugins/LanguageRuntime/RenderScript/RenderScriptRuntime/RenderScriptRuntime.h
> Mon Nov 30 04:29:49 2015
> @@ -231,6 +231,7 @@ public:
>  protected:
>      struct ScriptDetails;
>      struct AllocationDetails;
> +    struct Element;
>
>      void InitSearchFilter(lldb::TargetSP target)
>      {
> @@ -311,8 +312,9 @@ private:
>
>      AllocationDetails* FindAllocByID(Stream &strm, const uint32_t
> alloc_id);
>      std::shared_ptr<uint8_t> GetAllocationData(AllocationDetails*
> allocation, StackFrame* frame_ptr);
> -    unsigned int GetElementSize(const AllocationDetails* allocation);
> +    void SetElementSize(Element& elem);
>      static bool GetFrameVarAsUnsigned(const lldb::StackFrameSP, const
> char* var_name, uint64_t& val);
> +    void FindStructTypeName(Element& elem, StackFrame* frame_ptr);
>
>      //
>      // Helper functions for jitting the runtime
> @@ -324,9 +326,11 @@ private:
>
>      bool JITTypePacked(AllocationDetails* allocation, StackFrame*
> frame_ptr);
>
> -    bool JITElementPacked(AllocationDetails* allocation, StackFrame*
> frame_ptr);
> +    bool JITElementPacked(Element& elem, const lldb::addr_t context,
> StackFrame* frame_ptr);
>
> -    bool JITAllocationSize(AllocationDetails* allocation, StackFrame*
> frame_ptr, const uint32_t elem_size);
> +    bool JITAllocationSize(AllocationDetails* allocation, StackFrame*
> frame_ptr);
> +
> +    bool JITSubelements(Element& elem, const lldb::addr_t context,
> StackFrame* frame_ptr);
>
>      bool JITAllocationStride(AllocationDetails* allocation, StackFrame*
> frame_ptr);
>
>
>
> _______________________________________________
> lldb-commits mailing list
> lldb-commits at lists.llvm.org
> http://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/lldb-commits/attachments/20151130/5657f5b6/attachment-0001.html>


More information about the lldb-commits mailing list