776 lines
		
	
	
		
			27 KiB
		
	
	
	
		
			C++
		
	
	
	
			
		
		
	
	
			776 lines
		
	
	
		
			27 KiB
		
	
	
	
		
			C++
		
	
	
	
//===-- DWARFASTParserGo.cpp ---------------------------------*- C++ -*-===//
 | 
						|
//
 | 
						|
//                     The LLVM Compiler Infrastructure
 | 
						|
//
 | 
						|
// This file is distributed under the University of Illinois Open Source
 | 
						|
// License. See LICENSE.TXT for details.
 | 
						|
//
 | 
						|
//===----------------------------------------------------------------------===//
 | 
						|
 | 
						|
#include "DWARFASTParserGo.h"
 | 
						|
 | 
						|
#include "DWARFASTParserGo.h"
 | 
						|
#include "DWARFCompileUnit.h"
 | 
						|
#include "DWARFDIE.h"
 | 
						|
#include "DWARFDIECollection.h"
 | 
						|
#include "DWARFDebugInfo.h"
 | 
						|
#include "DWARFDeclContext.h"
 | 
						|
#include "DWARFDefines.h"
 | 
						|
#include "SymbolFileDWARF.h"
 | 
						|
#include "SymbolFileDWARFDebugMap.h"
 | 
						|
#include "UniqueDWARFASTType.h"
 | 
						|
 | 
						|
#include "clang/Basic/Specifiers.h"
 | 
						|
 | 
						|
#include "lldb/Core/Module.h"
 | 
						|
#include "lldb/Core/Value.h"
 | 
						|
#include "lldb/Symbol/CompileUnit.h"
 | 
						|
#include "lldb/Symbol/Function.h"
 | 
						|
#include "lldb/Symbol/ObjectFile.h"
 | 
						|
#include "lldb/Symbol/TypeList.h"
 | 
						|
 | 
						|
//#define ENABLE_DEBUG_PRINTF // COMMENT OUT THIS LINE PRIOR TO CHECKIN
 | 
						|
 | 
						|
#ifdef ENABLE_DEBUG_PRINTF
 | 
						|
#include <stdio.h>
 | 
						|
#define DEBUG_PRINTF(fmt, ...) printf(fmt, __VA_ARGS__)
 | 
						|
#else
 | 
						|
#define DEBUG_PRINTF(fmt, ...)
 | 
						|
#endif
 | 
						|
 | 
						|
#define DW_AT_go_kind 0x2900
 | 
						|
#define DW_AT_go_key 0x2901
 | 
						|
#define DW_AT_go_elem 0x2902
 | 
						|
 | 
						|
using namespace lldb;
 | 
						|
using namespace lldb_private;
 | 
						|
DWARFASTParserGo::DWARFASTParserGo(GoASTContext &ast) : m_ast(ast) {}
 | 
						|
 | 
						|
DWARFASTParserGo::~DWARFASTParserGo() {}
 | 
						|
 | 
						|
TypeSP DWARFASTParserGo::ParseTypeFromDWARF(
 | 
						|
    const lldb_private::SymbolContext &sc, const DWARFDIE &die,
 | 
						|
    lldb_private::Log *log, bool *type_is_new_ptr) {
 | 
						|
  TypeSP type_sp;
 | 
						|
 | 
						|
  if (type_is_new_ptr)
 | 
						|
    *type_is_new_ptr = false;
 | 
						|
 | 
						|
  if (die) {
 | 
						|
    SymbolFileDWARF *dwarf = die.GetDWARF();
 | 
						|
    if (log) {
 | 
						|
      dwarf->GetObjectFile()->GetModule()->LogMessage(
 | 
						|
          log, "DWARFASTParserGo::ParseTypeFromDWARF (die = 0x%8.8x) %s name = "
 | 
						|
               "'%s')",
 | 
						|
          die.GetOffset(), DW_TAG_value_to_name(die.Tag()), die.GetName());
 | 
						|
    }
 | 
						|
 | 
						|
    Type *type_ptr = dwarf->m_die_to_type.lookup(die.GetDIE());
 | 
						|
    TypeList *type_list = dwarf->GetTypeList();
 | 
						|
    if (type_ptr == NULL) {
 | 
						|
      if (type_is_new_ptr)
 | 
						|
        *type_is_new_ptr = true;
 | 
						|
 | 
						|
      const dw_tag_t tag = die.Tag();
 | 
						|
 | 
						|
      bool is_forward_declaration = false;
 | 
						|
      DWARFAttributes attributes;
 | 
						|
      const char *type_name_cstr = NULL;
 | 
						|
      ConstString type_name_const_str;
 | 
						|
      Type::ResolveState resolve_state = Type::eResolveStateUnresolved;
 | 
						|
      uint64_t byte_size = 0;
 | 
						|
      uint64_t go_kind = 0;
 | 
						|
      Declaration decl;
 | 
						|
 | 
						|
      Type::EncodingDataType encoding_data_type = Type::eEncodingIsUID;
 | 
						|
      CompilerType compiler_type;
 | 
						|
      DWARFFormValue form_value;
 | 
						|
 | 
						|
      dw_attr_t attr;
 | 
						|
 | 
						|
      switch (tag) {
 | 
						|
      case DW_TAG_base_type:
 | 
						|
      case DW_TAG_pointer_type:
 | 
						|
      case DW_TAG_typedef:
 | 
						|
      case DW_TAG_unspecified_type: {
 | 
						|
        // Set a bit that lets us know that we are currently parsing this
 | 
						|
        dwarf->m_die_to_type[die.GetDIE()] = DIE_IS_BEING_PARSED;
 | 
						|
 | 
						|
        const size_t num_attributes = die.GetAttributes(attributes);
 | 
						|
        lldb::user_id_t encoding_uid = LLDB_INVALID_UID;
 | 
						|
 | 
						|
        if (num_attributes > 0) {
 | 
						|
          uint32_t i;
 | 
						|
          for (i = 0; i < num_attributes; ++i) {
 | 
						|
            attr = attributes.AttributeAtIndex(i);
 | 
						|
            if (attributes.ExtractFormValueAtIndex(i, form_value)) {
 | 
						|
              switch (attr) {
 | 
						|
              case DW_AT_name:
 | 
						|
                type_name_cstr = form_value.AsCString();
 | 
						|
                if (type_name_cstr)
 | 
						|
                  type_name_const_str.SetCString(type_name_cstr);
 | 
						|
                break;
 | 
						|
              case DW_AT_byte_size:
 | 
						|
                byte_size = form_value.Unsigned();
 | 
						|
                break;
 | 
						|
              case DW_AT_encoding:
 | 
						|
                // = form_value.Unsigned();
 | 
						|
                break;
 | 
						|
              case DW_AT_type:
 | 
						|
                encoding_uid = form_value.Reference();
 | 
						|
                break;
 | 
						|
              case DW_AT_go_kind:
 | 
						|
                go_kind = form_value.Unsigned();
 | 
						|
                break;
 | 
						|
              default:
 | 
						|
                // Do we care about DW_AT_go_key or DW_AT_go_elem?
 | 
						|
                break;
 | 
						|
              }
 | 
						|
            }
 | 
						|
          }
 | 
						|
        }
 | 
						|
 | 
						|
        DEBUG_PRINTF("0x%8.8" PRIx64 ": %s (\"%s\") type => 0x%8.8lx\n",
 | 
						|
                     die.GetID(), DW_TAG_value_to_name(tag), type_name_cstr,
 | 
						|
                     encoding_uid);
 | 
						|
 | 
						|
        switch (tag) {
 | 
						|
        default:
 | 
						|
          break;
 | 
						|
 | 
						|
        case DW_TAG_unspecified_type:
 | 
						|
          resolve_state = Type::eResolveStateFull;
 | 
						|
          compiler_type = m_ast.CreateVoidType(type_name_const_str);
 | 
						|
          break;
 | 
						|
 | 
						|
        case DW_TAG_base_type:
 | 
						|
          resolve_state = Type::eResolveStateFull;
 | 
						|
          compiler_type =
 | 
						|
              m_ast.CreateBaseType(go_kind, type_name_const_str, byte_size);
 | 
						|
          break;
 | 
						|
 | 
						|
        case DW_TAG_pointer_type:
 | 
						|
          encoding_data_type = Type::eEncodingIsPointerUID;
 | 
						|
          break;
 | 
						|
        case DW_TAG_typedef:
 | 
						|
          encoding_data_type = Type::eEncodingIsTypedefUID;
 | 
						|
          CompilerType impl;
 | 
						|
          Type *type = dwarf->ResolveTypeUID(encoding_uid);
 | 
						|
          if (type) {
 | 
						|
            if (go_kind == 0 && type->GetName() == type_name_const_str) {
 | 
						|
              // Go emits extra typedefs as a forward declaration. Ignore these.
 | 
						|
              dwarf->m_die_to_type[die.GetDIE()] = type;
 | 
						|
              return type->shared_from_this();
 | 
						|
            }
 | 
						|
            impl = type->GetForwardCompilerType();
 | 
						|
            compiler_type =
 | 
						|
                m_ast.CreateTypedefType(go_kind, type_name_const_str, impl);
 | 
						|
          }
 | 
						|
          break;
 | 
						|
        }
 | 
						|
 | 
						|
        type_sp.reset(new Type(die.GetID(), dwarf, type_name_const_str,
 | 
						|
                               byte_size, NULL, encoding_uid,
 | 
						|
                               encoding_data_type, &decl, compiler_type,
 | 
						|
                               resolve_state));
 | 
						|
 | 
						|
        dwarf->m_die_to_type[die.GetDIE()] = type_sp.get();
 | 
						|
      } break;
 | 
						|
 | 
						|
      case DW_TAG_structure_type: {
 | 
						|
        // Set a bit that lets us know that we are currently parsing this
 | 
						|
        dwarf->m_die_to_type[die.GetDIE()] = DIE_IS_BEING_PARSED;
 | 
						|
        bool byte_size_valid = false;
 | 
						|
 | 
						|
        const size_t num_attributes = die.GetAttributes(attributes);
 | 
						|
        if (num_attributes > 0) {
 | 
						|
          uint32_t i;
 | 
						|
          for (i = 0; i < num_attributes; ++i) {
 | 
						|
            attr = attributes.AttributeAtIndex(i);
 | 
						|
            if (attributes.ExtractFormValueAtIndex(i, form_value)) {
 | 
						|
              switch (attr) {
 | 
						|
              case DW_AT_name:
 | 
						|
                type_name_cstr = form_value.AsCString();
 | 
						|
                type_name_const_str.SetCString(type_name_cstr);
 | 
						|
                break;
 | 
						|
 | 
						|
              case DW_AT_byte_size:
 | 
						|
                byte_size = form_value.Unsigned();
 | 
						|
                byte_size_valid = true;
 | 
						|
                break;
 | 
						|
 | 
						|
              case DW_AT_go_kind:
 | 
						|
                go_kind = form_value.Unsigned();
 | 
						|
                break;
 | 
						|
 | 
						|
              // TODO: Should we use SLICETYPE's DW_AT_go_elem?
 | 
						|
              default:
 | 
						|
                break;
 | 
						|
              }
 | 
						|
            }
 | 
						|
          }
 | 
						|
        }
 | 
						|
 | 
						|
        // TODO(ribrdb): Do we need this?
 | 
						|
 | 
						|
        // UniqueDWARFASTType is large, so don't create a local variables on the
 | 
						|
        // stack, put it on the heap. This function is often called recursively
 | 
						|
        // and clang isn't good and sharing the stack space for variables in
 | 
						|
        // different blocks.
 | 
						|
        std::unique_ptr<UniqueDWARFASTType> unique_ast_entry_ap(
 | 
						|
            new UniqueDWARFASTType());
 | 
						|
 | 
						|
        // Only try and unique the type if it has a name.
 | 
						|
        if (type_name_const_str &&
 | 
						|
            dwarf->GetUniqueDWARFASTTypeMap().Find(
 | 
						|
                type_name_const_str, die, decl,
 | 
						|
                byte_size_valid ? byte_size : -1, *unique_ast_entry_ap)) {
 | 
						|
          // We have already parsed this type or from another
 | 
						|
          // compile unit. GCC loves to use the "one definition
 | 
						|
          // rule" which can result in multiple definitions
 | 
						|
          // of the same class over and over in each compile
 | 
						|
          // unit.
 | 
						|
          type_sp = unique_ast_entry_ap->m_type_sp;
 | 
						|
          if (type_sp) {
 | 
						|
            dwarf->m_die_to_type[die.GetDIE()] = type_sp.get();
 | 
						|
            return type_sp;
 | 
						|
          }
 | 
						|
        }
 | 
						|
 | 
						|
        DEBUG_PRINTF("0x%8.8" PRIx64 ": %s (\"%s\")\n", die.GetID(),
 | 
						|
                     DW_TAG_value_to_name(tag), type_name_cstr);
 | 
						|
 | 
						|
        bool compiler_type_was_created = false;
 | 
						|
        compiler_type.SetCompilerType(
 | 
						|
            &m_ast,
 | 
						|
            dwarf->m_forward_decl_die_to_clang_type.lookup(die.GetDIE()));
 | 
						|
        if (!compiler_type) {
 | 
						|
          compiler_type_was_created = true;
 | 
						|
          compiler_type =
 | 
						|
              m_ast.CreateStructType(go_kind, type_name_const_str, byte_size);
 | 
						|
        }
 | 
						|
 | 
						|
        type_sp.reset(new Type(die.GetID(), dwarf, type_name_const_str,
 | 
						|
                               byte_size, NULL, LLDB_INVALID_UID,
 | 
						|
                               Type::eEncodingIsUID, &decl, compiler_type,
 | 
						|
                               Type::eResolveStateForward));
 | 
						|
 | 
						|
        // Add our type to the unique type map so we don't
 | 
						|
        // end up creating many copies of the same type over
 | 
						|
        // and over in the ASTContext for our module
 | 
						|
        unique_ast_entry_ap->m_type_sp = type_sp;
 | 
						|
        unique_ast_entry_ap->m_die = die;
 | 
						|
        unique_ast_entry_ap->m_declaration = decl;
 | 
						|
        unique_ast_entry_ap->m_byte_size = byte_size;
 | 
						|
        dwarf->GetUniqueDWARFASTTypeMap().Insert(type_name_const_str,
 | 
						|
                                                 *unique_ast_entry_ap);
 | 
						|
 | 
						|
        if (!is_forward_declaration) {
 | 
						|
          // Always start the definition for a class type so that
 | 
						|
          // if the class has child classes or types that require
 | 
						|
          // the class to be created for use as their decl contexts
 | 
						|
          // the class will be ready to accept these child definitions.
 | 
						|
          if (die.HasChildren() == false) {
 | 
						|
            // No children for this struct/union/class, lets finish it
 | 
						|
            m_ast.CompleteStructType(compiler_type);
 | 
						|
          } else if (compiler_type_was_created) {
 | 
						|
            // Leave this as a forward declaration until we need
 | 
						|
            // to know the details of the type. lldb_private::Type
 | 
						|
            // will automatically call the SymbolFile virtual function
 | 
						|
            // "SymbolFileDWARF::CompleteType(Type *)"
 | 
						|
            // When the definition needs to be defined.
 | 
						|
            dwarf->m_forward_decl_die_to_clang_type[die.GetDIE()] =
 | 
						|
                compiler_type.GetOpaqueQualType();
 | 
						|
            dwarf->m_forward_decl_clang_type_to_die[compiler_type
 | 
						|
                                                        .GetOpaqueQualType()] =
 | 
						|
                die.GetDIERef();
 | 
						|
            // SetHasExternalStorage (compiler_type.GetOpaqueQualType(), true);
 | 
						|
          }
 | 
						|
        }
 | 
						|
      } break;
 | 
						|
 | 
						|
      case DW_TAG_subprogram:
 | 
						|
      case DW_TAG_subroutine_type: {
 | 
						|
        // Set a bit that lets us know that we are currently parsing this
 | 
						|
        dwarf->m_die_to_type[die.GetDIE()] = DIE_IS_BEING_PARSED;
 | 
						|
 | 
						|
        bool is_variadic = false;
 | 
						|
        clang::StorageClass storage =
 | 
						|
            clang::SC_None; //, Extern, Static, PrivateExtern
 | 
						|
 | 
						|
        const size_t num_attributes = die.GetAttributes(attributes);
 | 
						|
        if (num_attributes > 0) {
 | 
						|
          uint32_t i;
 | 
						|
          for (i = 0; i < num_attributes; ++i) {
 | 
						|
            attr = attributes.AttributeAtIndex(i);
 | 
						|
            if (attributes.ExtractFormValueAtIndex(i, form_value)) {
 | 
						|
              switch (attr) {
 | 
						|
              case DW_AT_name:
 | 
						|
                type_name_cstr = form_value.AsCString();
 | 
						|
                type_name_const_str.SetCString(type_name_cstr);
 | 
						|
                break;
 | 
						|
 | 
						|
              case DW_AT_external:
 | 
						|
                if (form_value.Unsigned()) {
 | 
						|
                  if (storage == clang::SC_None)
 | 
						|
                    storage = clang::SC_Extern;
 | 
						|
                  else
 | 
						|
                    storage = clang::SC_PrivateExtern;
 | 
						|
                }
 | 
						|
                break;
 | 
						|
 | 
						|
              case DW_AT_high_pc:
 | 
						|
              case DW_AT_low_pc:
 | 
						|
                break;
 | 
						|
              }
 | 
						|
            }
 | 
						|
          }
 | 
						|
        }
 | 
						|
 | 
						|
        DEBUG_PRINTF("0x%8.8" PRIx64 ": %s (\"%s\")\n", die.GetID(),
 | 
						|
                     DW_TAG_value_to_name(tag), type_name_cstr);
 | 
						|
 | 
						|
        std::vector<CompilerType> function_param_types;
 | 
						|
 | 
						|
        // Parse the function children for the parameters
 | 
						|
 | 
						|
        if (die.HasChildren()) {
 | 
						|
          ParseChildParameters(sc, die, is_variadic, function_param_types);
 | 
						|
        }
 | 
						|
 | 
						|
        // compiler_type will get the function prototype clang type after this
 | 
						|
        // call
 | 
						|
        compiler_type = m_ast.CreateFunctionType(
 | 
						|
            type_name_const_str, function_param_types.data(),
 | 
						|
            function_param_types.size(), is_variadic);
 | 
						|
 | 
						|
        type_sp.reset(new Type(die.GetID(), dwarf, type_name_const_str, 0, NULL,
 | 
						|
                               LLDB_INVALID_UID, Type::eEncodingIsUID, &decl,
 | 
						|
                               compiler_type, Type::eResolveStateFull));
 | 
						|
        assert(type_sp.get());
 | 
						|
      } break;
 | 
						|
 | 
						|
      case DW_TAG_array_type: {
 | 
						|
        // Set a bit that lets us know that we are currently parsing this
 | 
						|
        dwarf->m_die_to_type[die.GetDIE()] = DIE_IS_BEING_PARSED;
 | 
						|
 | 
						|
        lldb::user_id_t type_die_offset = DW_INVALID_OFFSET;
 | 
						|
        int64_t first_index = 0;
 | 
						|
        uint32_t byte_stride = 0;
 | 
						|
        uint32_t bit_stride = 0;
 | 
						|
        const size_t num_attributes = die.GetAttributes(attributes);
 | 
						|
 | 
						|
        if (num_attributes > 0) {
 | 
						|
          uint32_t i;
 | 
						|
          for (i = 0; i < num_attributes; ++i) {
 | 
						|
            attr = attributes.AttributeAtIndex(i);
 | 
						|
            if (attributes.ExtractFormValueAtIndex(i, form_value)) {
 | 
						|
              switch (attr) {
 | 
						|
              case DW_AT_name:
 | 
						|
                type_name_cstr = form_value.AsCString();
 | 
						|
                type_name_const_str.SetCString(type_name_cstr);
 | 
						|
                break;
 | 
						|
 | 
						|
              case DW_AT_type:
 | 
						|
                type_die_offset = form_value.Reference();
 | 
						|
                break;
 | 
						|
              case DW_AT_byte_size:
 | 
						|
                break; // byte_size = form_value.Unsigned(); break;
 | 
						|
              case DW_AT_go_kind:
 | 
						|
                go_kind = form_value.Unsigned();
 | 
						|
                break;
 | 
						|
              default:
 | 
						|
                break;
 | 
						|
              }
 | 
						|
            }
 | 
						|
          }
 | 
						|
 | 
						|
          DEBUG_PRINTF("0x%8.8" PRIx64 ": %s (\"%s\")\n", die.GetID(),
 | 
						|
                       DW_TAG_value_to_name(tag), type_name_cstr);
 | 
						|
 | 
						|
          Type *element_type = dwarf->ResolveTypeUID(type_die_offset);
 | 
						|
 | 
						|
          if (element_type) {
 | 
						|
            std::vector<uint64_t> element_orders;
 | 
						|
            ParseChildArrayInfo(sc, die, first_index, element_orders,
 | 
						|
                                byte_stride, bit_stride);
 | 
						|
            if (byte_stride == 0)
 | 
						|
              byte_stride = element_type->GetByteSize();
 | 
						|
            CompilerType array_element_type =
 | 
						|
                element_type->GetForwardCompilerType();
 | 
						|
            if (element_orders.size() > 0) {
 | 
						|
              if (element_orders.size() > 1)
 | 
						|
                printf("golang: unsupported multi-dimensional array %s\n",
 | 
						|
                       type_name_cstr);
 | 
						|
              compiler_type = m_ast.CreateArrayType(
 | 
						|
                  type_name_const_str, array_element_type, element_orders[0]);
 | 
						|
            } else {
 | 
						|
              compiler_type = m_ast.CreateArrayType(type_name_const_str,
 | 
						|
                                                    array_element_type, 0);
 | 
						|
            }
 | 
						|
            type_sp.reset(new Type(die.GetID(), dwarf, type_name_const_str,
 | 
						|
                                   byte_stride, NULL, type_die_offset,
 | 
						|
                                   Type::eEncodingIsUID, &decl, compiler_type,
 | 
						|
                                   Type::eResolveStateFull));
 | 
						|
            type_sp->SetEncodingType(element_type);
 | 
						|
          }
 | 
						|
        }
 | 
						|
      } break;
 | 
						|
 | 
						|
      default:
 | 
						|
        dwarf->GetObjectFile()->GetModule()->ReportError(
 | 
						|
            "{0x%8.8x}: unhandled type tag 0x%4.4x (%s), "
 | 
						|
            "please file a bug and attach the file at the "
 | 
						|
            "start of this error message",
 | 
						|
            die.GetOffset(), tag, DW_TAG_value_to_name(tag));
 | 
						|
        break;
 | 
						|
      }
 | 
						|
 | 
						|
      if (type_sp.get()) {
 | 
						|
        DWARFDIE sc_parent_die =
 | 
						|
            SymbolFileDWARF::GetParentSymbolContextDIE(die);
 | 
						|
        dw_tag_t sc_parent_tag = sc_parent_die.Tag();
 | 
						|
 | 
						|
        SymbolContextScope *symbol_context_scope = NULL;
 | 
						|
        if (sc_parent_tag == DW_TAG_compile_unit) {
 | 
						|
          symbol_context_scope = sc.comp_unit;
 | 
						|
        } else if (sc.function != NULL && sc_parent_die) {
 | 
						|
          symbol_context_scope =
 | 
						|
              sc.function->GetBlock(true).FindBlockByID(sc_parent_die.GetID());
 | 
						|
          if (symbol_context_scope == NULL)
 | 
						|
            symbol_context_scope = sc.function;
 | 
						|
        }
 | 
						|
 | 
						|
        if (symbol_context_scope != NULL) {
 | 
						|
          type_sp->SetSymbolContextScope(symbol_context_scope);
 | 
						|
        }
 | 
						|
 | 
						|
        // We are ready to put this type into the uniqued list up at the module
 | 
						|
        // level
 | 
						|
        type_list->Insert(type_sp);
 | 
						|
 | 
						|
        dwarf->m_die_to_type[die.GetDIE()] = type_sp.get();
 | 
						|
      }
 | 
						|
    } else if (type_ptr != DIE_IS_BEING_PARSED) {
 | 
						|
      type_sp = type_ptr->shared_from_this();
 | 
						|
    }
 | 
						|
  }
 | 
						|
  return type_sp;
 | 
						|
}
 | 
						|
 | 
						|
size_t DWARFASTParserGo::ParseChildParameters(
 | 
						|
    const SymbolContext &sc,
 | 
						|
 | 
						|
    const DWARFDIE &parent_die, bool &is_variadic,
 | 
						|
    std::vector<CompilerType> &function_param_types) {
 | 
						|
  if (!parent_die)
 | 
						|
    return 0;
 | 
						|
 | 
						|
  size_t arg_idx = 0;
 | 
						|
  for (DWARFDIE die = parent_die.GetFirstChild(); die.IsValid();
 | 
						|
       die = die.GetSibling()) {
 | 
						|
 | 
						|
    dw_tag_t tag = die.Tag();
 | 
						|
    switch (tag) {
 | 
						|
    case DW_TAG_formal_parameter: {
 | 
						|
      DWARFAttributes attributes;
 | 
						|
      const size_t num_attributes = die.GetAttributes(attributes);
 | 
						|
      if (num_attributes > 0) {
 | 
						|
        Declaration decl;
 | 
						|
        DWARFFormValue param_type_die_offset;
 | 
						|
 | 
						|
        uint32_t i;
 | 
						|
        for (i = 0; i < num_attributes; ++i) {
 | 
						|
          const dw_attr_t attr = attributes.AttributeAtIndex(i);
 | 
						|
          DWARFFormValue form_value;
 | 
						|
          if (attributes.ExtractFormValueAtIndex(i, form_value)) {
 | 
						|
            switch (attr) {
 | 
						|
            case DW_AT_name:
 | 
						|
              // = form_value.AsCString();
 | 
						|
              break;
 | 
						|
            case DW_AT_type:
 | 
						|
              param_type_die_offset = form_value;
 | 
						|
              break;
 | 
						|
            case DW_AT_location:
 | 
						|
            //                          if (form_value.BlockData())
 | 
						|
            //                          {
 | 
						|
            //                              const DWARFDataExtractor&
 | 
						|
            //                              debug_info_data =
 | 
						|
            //                              debug_info();
 | 
						|
            //                              uint32_t block_length =
 | 
						|
            //                              form_value.Unsigned();
 | 
						|
            //                              DWARFDataExtractor
 | 
						|
            //                              location(debug_info_data,
 | 
						|
            //                              form_value.BlockData() -
 | 
						|
            //                              debug_info_data.GetDataStart(),
 | 
						|
            //                              block_length);
 | 
						|
            //                          }
 | 
						|
            //                          else
 | 
						|
            //                          {
 | 
						|
            //                          }
 | 
						|
            //                          break;
 | 
						|
            default:
 | 
						|
              break;
 | 
						|
            }
 | 
						|
          }
 | 
						|
        }
 | 
						|
 | 
						|
        Type *type = parent_die.ResolveTypeUID(DIERef(param_type_die_offset));
 | 
						|
        if (type) {
 | 
						|
          function_param_types.push_back(type->GetForwardCompilerType());
 | 
						|
        }
 | 
						|
      }
 | 
						|
      arg_idx++;
 | 
						|
    } break;
 | 
						|
 | 
						|
    case DW_TAG_unspecified_parameters:
 | 
						|
      is_variadic = true;
 | 
						|
      break;
 | 
						|
 | 
						|
    default:
 | 
						|
      break;
 | 
						|
    }
 | 
						|
  }
 | 
						|
  return arg_idx;
 | 
						|
}
 | 
						|
 | 
						|
void DWARFASTParserGo::ParseChildArrayInfo(
 | 
						|
    const SymbolContext &sc, const DWARFDIE &parent_die, int64_t &first_index,
 | 
						|
    std::vector<uint64_t> &element_orders, uint32_t &byte_stride,
 | 
						|
    uint32_t &bit_stride) {
 | 
						|
  if (!parent_die)
 | 
						|
    return;
 | 
						|
 | 
						|
  for (DWARFDIE die = parent_die.GetFirstChild(); die.IsValid();
 | 
						|
       die = die.GetSibling()) {
 | 
						|
    const dw_tag_t tag = die.Tag();
 | 
						|
    switch (tag) {
 | 
						|
    case DW_TAG_subrange_type: {
 | 
						|
      DWARFAttributes attributes;
 | 
						|
      const size_t num_child_attributes = die.GetAttributes(attributes);
 | 
						|
      if (num_child_attributes > 0) {
 | 
						|
        uint64_t num_elements = 0;
 | 
						|
        uint32_t i;
 | 
						|
        for (i = 0; i < num_child_attributes; ++i) {
 | 
						|
          const dw_attr_t attr = attributes.AttributeAtIndex(i);
 | 
						|
          DWARFFormValue form_value;
 | 
						|
          if (attributes.ExtractFormValueAtIndex(i, form_value)) {
 | 
						|
            switch (attr) {
 | 
						|
            case DW_AT_count:
 | 
						|
              num_elements = form_value.Unsigned();
 | 
						|
              break;
 | 
						|
 | 
						|
            default:
 | 
						|
            case DW_AT_type:
 | 
						|
              break;
 | 
						|
            }
 | 
						|
          }
 | 
						|
        }
 | 
						|
 | 
						|
        element_orders.push_back(num_elements);
 | 
						|
      }
 | 
						|
    } break;
 | 
						|
    }
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
bool DWARFASTParserGo::CompleteTypeFromDWARF(const DWARFDIE &die,
 | 
						|
                                             lldb_private::Type *type,
 | 
						|
                                             CompilerType &compiler_type) {
 | 
						|
  if (!die)
 | 
						|
    return false;
 | 
						|
 | 
						|
  const dw_tag_t tag = die.Tag();
 | 
						|
 | 
						|
  SymbolFileDWARF *dwarf = die.GetDWARF();
 | 
						|
  Log *log =
 | 
						|
      nullptr; // (LogChannelDWARF::GetLogIfAny(DWARF_LOG_DEBUG_INFO|DWARF_LOG_TYPE_COMPLETION));
 | 
						|
  if (log)
 | 
						|
    dwarf->GetObjectFile()->GetModule()->LogMessageVerboseBacktrace(
 | 
						|
        log, "0x%8.8" PRIx64 ": %s '%s' resolving forward declaration...",
 | 
						|
        die.GetID(), DW_TAG_value_to_name(tag), type->GetName().AsCString());
 | 
						|
  assert(compiler_type);
 | 
						|
  DWARFAttributes attributes;
 | 
						|
 | 
						|
  switch (tag) {
 | 
						|
  case DW_TAG_structure_type: {
 | 
						|
    {
 | 
						|
      if (die.HasChildren()) {
 | 
						|
        SymbolContext sc(die.GetLLDBCompileUnit());
 | 
						|
 | 
						|
        ParseChildMembers(sc, die, compiler_type);
 | 
						|
      }
 | 
						|
    }
 | 
						|
    m_ast.CompleteStructType(compiler_type);
 | 
						|
    return (bool)compiler_type;
 | 
						|
  }
 | 
						|
 | 
						|
  default:
 | 
						|
    assert(false && "not a forward go type decl!");
 | 
						|
    break;
 | 
						|
  }
 | 
						|
 | 
						|
  return false;
 | 
						|
}
 | 
						|
 | 
						|
size_t DWARFASTParserGo::ParseChildMembers(const SymbolContext &sc,
 | 
						|
                                           const DWARFDIE &parent_die,
 | 
						|
                                           CompilerType &class_compiler_type) {
 | 
						|
  size_t count = 0;
 | 
						|
  uint32_t member_idx = 0;
 | 
						|
 | 
						|
  ModuleSP module_sp = parent_die.GetDWARF()->GetObjectFile()->GetModule();
 | 
						|
  GoASTContext *ast =
 | 
						|
      llvm::dyn_cast_or_null<GoASTContext>(class_compiler_type.GetTypeSystem());
 | 
						|
  if (ast == nullptr)
 | 
						|
    return 0;
 | 
						|
 | 
						|
  for (DWARFDIE die = parent_die.GetFirstChild(); die.IsValid();
 | 
						|
       die = die.GetSibling()) {
 | 
						|
    dw_tag_t tag = die.Tag();
 | 
						|
 | 
						|
    switch (tag) {
 | 
						|
    case DW_TAG_member: {
 | 
						|
      DWARFAttributes attributes;
 | 
						|
      const size_t num_attributes = die.GetAttributes(attributes);
 | 
						|
      if (num_attributes > 0) {
 | 
						|
        Declaration decl;
 | 
						|
        const char *name = NULL;
 | 
						|
 | 
						|
        DWARFFormValue encoding_uid;
 | 
						|
        uint32_t member_byte_offset = UINT32_MAX;
 | 
						|
        uint32_t i;
 | 
						|
        for (i = 0; i < num_attributes; ++i) {
 | 
						|
          const dw_attr_t attr = attributes.AttributeAtIndex(i);
 | 
						|
          DWARFFormValue form_value;
 | 
						|
          if (attributes.ExtractFormValueAtIndex(i, form_value)) {
 | 
						|
            switch (attr) {
 | 
						|
            case DW_AT_name:
 | 
						|
              name = form_value.AsCString();
 | 
						|
              break;
 | 
						|
            case DW_AT_type:
 | 
						|
              encoding_uid = form_value;
 | 
						|
              break;
 | 
						|
            case DW_AT_data_member_location:
 | 
						|
              if (form_value.BlockData()) {
 | 
						|
                Value initialValue(0);
 | 
						|
                Value memberOffset(0);
 | 
						|
                const DWARFDataExtractor &debug_info_data =
 | 
						|
                    die.GetDWARF()->get_debug_info_data();
 | 
						|
                uint32_t block_length = form_value.Unsigned();
 | 
						|
                uint32_t block_offset =
 | 
						|
                    form_value.BlockData() - debug_info_data.GetDataStart();
 | 
						|
                if (DWARFExpression::Evaluate(
 | 
						|
                        NULL, // ExecutionContext *
 | 
						|
                        NULL, // ClangExpressionVariableList *
 | 
						|
                        NULL, // ClangExpressionDeclMap *
 | 
						|
                        NULL, // RegisterContext *
 | 
						|
                        module_sp, debug_info_data, die.GetCU(), block_offset,
 | 
						|
                        block_length, eRegisterKindDWARF, &initialValue, NULL,
 | 
						|
                        memberOffset, NULL)) {
 | 
						|
                  member_byte_offset = memberOffset.ResolveValue(NULL).UInt();
 | 
						|
                }
 | 
						|
              } else {
 | 
						|
                // With DWARF 3 and later, if the value is an integer constant,
 | 
						|
                // this form value is the offset in bytes from the beginning
 | 
						|
                // of the containing entity.
 | 
						|
                member_byte_offset = form_value.Unsigned();
 | 
						|
              }
 | 
						|
              break;
 | 
						|
 | 
						|
            default:
 | 
						|
              break;
 | 
						|
            }
 | 
						|
          }
 | 
						|
        }
 | 
						|
 | 
						|
        Type *member_type = die.ResolveTypeUID(DIERef(encoding_uid));
 | 
						|
        if (member_type) {
 | 
						|
          CompilerType member_go_type = member_type->GetFullCompilerType();
 | 
						|
          ConstString name_const_str(name);
 | 
						|
          m_ast.AddFieldToStruct(class_compiler_type, name_const_str,
 | 
						|
                                 member_go_type, member_byte_offset);
 | 
						|
        }
 | 
						|
      }
 | 
						|
      ++member_idx;
 | 
						|
    } break;
 | 
						|
 | 
						|
    default:
 | 
						|
      break;
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  return count;
 | 
						|
}
 | 
						|
 | 
						|
Function *DWARFASTParserGo::ParseFunctionFromDWARF(const SymbolContext &sc,
 | 
						|
                                                   const DWARFDIE &die) {
 | 
						|
  DWARFRangeList func_ranges;
 | 
						|
  const char *name = NULL;
 | 
						|
  const char *mangled = NULL;
 | 
						|
  int decl_file = 0;
 | 
						|
  int decl_line = 0;
 | 
						|
  int decl_column = 0;
 | 
						|
  int call_file = 0;
 | 
						|
  int call_line = 0;
 | 
						|
  int call_column = 0;
 | 
						|
  DWARFExpression frame_base(die.GetCU());
 | 
						|
 | 
						|
  assert(die.Tag() == DW_TAG_subprogram);
 | 
						|
 | 
						|
  if (die.Tag() != DW_TAG_subprogram)
 | 
						|
    return NULL;
 | 
						|
 | 
						|
  if (die.GetDIENamesAndRanges(name, mangled, func_ranges, decl_file, decl_line,
 | 
						|
                               decl_column, call_file, call_line, call_column,
 | 
						|
                               &frame_base)) {
 | 
						|
    // Union of all ranges in the function DIE (if the function is
 | 
						|
    // discontiguous)
 | 
						|
    AddressRange func_range;
 | 
						|
    lldb::addr_t lowest_func_addr = func_ranges.GetMinRangeBase(0);
 | 
						|
    lldb::addr_t highest_func_addr = func_ranges.GetMaxRangeEnd(0);
 | 
						|
    if (lowest_func_addr != LLDB_INVALID_ADDRESS &&
 | 
						|
        lowest_func_addr <= highest_func_addr) {
 | 
						|
      ModuleSP module_sp(die.GetModule());
 | 
						|
      func_range.GetBaseAddress().ResolveAddressUsingFileSections(
 | 
						|
          lowest_func_addr, module_sp->GetSectionList());
 | 
						|
      if (func_range.GetBaseAddress().IsValid())
 | 
						|
        func_range.SetByteSize(highest_func_addr - lowest_func_addr);
 | 
						|
    }
 | 
						|
 | 
						|
    if (func_range.GetBaseAddress().IsValid()) {
 | 
						|
      Mangled func_name;
 | 
						|
      func_name.SetValue(ConstString(name), false);
 | 
						|
 | 
						|
      FunctionSP func_sp;
 | 
						|
      std::unique_ptr<Declaration> decl_ap;
 | 
						|
      if (decl_file != 0 || decl_line != 0 || decl_column != 0)
 | 
						|
        decl_ap.reset(new Declaration(
 | 
						|
            sc.comp_unit->GetSupportFiles().GetFileSpecAtIndex(decl_file),
 | 
						|
            decl_line, decl_column));
 | 
						|
 | 
						|
      SymbolFileDWARF *dwarf = die.GetDWARF();
 | 
						|
      // Supply the type _only_ if it has already been parsed
 | 
						|
      Type *func_type = dwarf->m_die_to_type.lookup(die.GetDIE());
 | 
						|
 | 
						|
      assert(func_type == NULL || func_type != DIE_IS_BEING_PARSED);
 | 
						|
 | 
						|
      if (dwarf->FixupAddress(func_range.GetBaseAddress())) {
 | 
						|
        const user_id_t func_user_id = die.GetID();
 | 
						|
        func_sp.reset(new Function(sc.comp_unit,
 | 
						|
                                   func_user_id, // UserID is the DIE offset
 | 
						|
                                   func_user_id, func_name, func_type,
 | 
						|
                                   func_range)); // first address range
 | 
						|
 | 
						|
        if (func_sp.get() != NULL) {
 | 
						|
          if (frame_base.IsValid())
 | 
						|
            func_sp->GetFrameBaseExpression() = frame_base;
 | 
						|
          sc.comp_unit->AddFunction(func_sp);
 | 
						|
          return func_sp.get();
 | 
						|
        }
 | 
						|
      }
 | 
						|
    }
 | 
						|
  }
 | 
						|
  return NULL;
 | 
						|
}
 |