[lldb] Reduce intentation in SymbolFileDWARF::ParseVariableDIE
authorPavel Labath <pavel@labath.sk>
Thu, 27 Aug 2020 13:30:12 +0000 (15:30 +0200)
committerPavel Labath <pavel@labath.sk>
Fri, 28 Aug 2020 09:44:03 +0000 (11:44 +0200)
using early exits. NFC.

lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp

index 271821b..9f4556f 100644 (file)
@@ -3091,363 +3091,350 @@ VariableSP SymbolFileDWARF::ParseVariableDIE(const SymbolContext &sc,
   if (die.GetDWARF() != this)
     return die.GetDWARF()->ParseVariableDIE(sc, die, func_low_pc);
 
-  VariableSP var_sp;
   if (!die)
-    return var_sp;
+    return nullptr;
 
-  var_sp = GetDIEToVariable()[die.GetDIE()];
-  if (var_sp)
+  if (VariableSP var_sp = GetDIEToVariable()[die.GetDIE()])
     return var_sp; // Already been parsed!
 
   const dw_tag_t tag = die.Tag();
   ModuleSP module = GetObjectFile()->GetModule();
 
-  if ((tag == DW_TAG_variable) || (tag == DW_TAG_constant) ||
-      (tag == DW_TAG_formal_parameter && sc.function)) {
-    DWARFAttributes attributes;
-    const size_t num_attributes = die.GetAttributes(attributes);
-    DWARFDIE spec_die;
-    if (num_attributes > 0) {
-      const char *name = nullptr;
-      const char *mangled = nullptr;
-      Declaration decl;
-      DWARFFormValue type_die_form;
-      DWARFExpression location;
-      bool is_external = false;
-      bool is_artificial = false;
-      DWARFFormValue const_value_form, location_form;
-      Variable::RangeList scope_ranges;
-      // AccessType accessibility = eAccessNone;
-
-      for (size_t i = 0; i < num_attributes; ++i) {
-        dw_attr_t attr = attributes.AttributeAtIndex(i);
-        DWARFFormValue form_value;
-
-        if (attributes.ExtractFormValueAtIndex(i, form_value)) {
-          switch (attr) {
-          case DW_AT_decl_file:
-            decl.SetFile(sc.comp_unit->GetSupportFiles().GetFileSpecAtIndex(
-                form_value.Unsigned()));
-            break;
-          case DW_AT_decl_line:
-            decl.SetLine(form_value.Unsigned());
-            break;
-          case DW_AT_decl_column:
-            decl.SetColumn(form_value.Unsigned());
-            break;
-          case DW_AT_name:
-            name = form_value.AsCString();
-            break;
-          case DW_AT_linkage_name:
-          case DW_AT_MIPS_linkage_name:
-            mangled = form_value.AsCString();
-            break;
-          case DW_AT_type:
-            type_die_form = form_value;
-            break;
-          case DW_AT_external:
-            is_external = form_value.Boolean();
-            break;
-          case DW_AT_const_value:
-            const_value_form = form_value;
-            break;
-          case DW_AT_location:
-            location_form = form_value;
-            break;
-          case DW_AT_specification:
-            spec_die = form_value.Reference();
-            break;
-          case DW_AT_start_scope:
-            // TODO: Implement this.
-            break;
-          case DW_AT_artificial:
-            is_artificial = form_value.Boolean();
-            break;
-          case DW_AT_accessibility:
-            break; // accessibility =
-                   // DW_ACCESS_to_AccessType(form_value.Unsigned()); break;
-          case DW_AT_declaration:
-          case DW_AT_description:
-          case DW_AT_endianity:
-          case DW_AT_segment:
-          case DW_AT_visibility:
-          default:
-          case DW_AT_abstract_origin:
-          case DW_AT_sibling:
-            break;
-          }
-        }
-      }
+  if (tag != DW_TAG_variable && tag != DW_TAG_constant &&
+      (tag != DW_TAG_formal_parameter || !sc.function))
+    return nullptr;
 
-      // Prefer DW_AT_location over DW_AT_const_value. Both can be emitted e.g.
-      // for static constexpr member variables -- DW_AT_const_value will be
-      // present in the class declaration and DW_AT_location in the DIE defining
-      // the member.
-      bool location_is_const_value_data = false;
-      bool has_explicit_location = false;
-      bool use_type_size_for_value = false;
-      if (location_form.IsValid()) {
-        has_explicit_location = true;
-        if (DWARFFormValue::IsBlockForm(location_form.Form())) {
-          const DWARFDataExtractor &data = die.GetData();
-
-          uint32_t block_offset =
-              location_form.BlockData() - data.GetDataStart();
-          uint32_t block_length = location_form.Unsigned();
-          location = DWARFExpression(
-              module, DataExtractor(data, block_offset, block_length),
-              die.GetCU());
-        } else {
-          DataExtractor data = die.GetCU()->GetLocationData();
-          dw_offset_t offset = location_form.Unsigned();
-          if (location_form.Form() == DW_FORM_loclistx)
-            offset = die.GetCU()->GetLoclistOffset(offset).getValueOr(-1);
-          if (data.ValidOffset(offset)) {
-            data = DataExtractor(data, offset, data.GetByteSize() - offset);
-            location = DWARFExpression(module, data, die.GetCU());
-            assert(func_low_pc != LLDB_INVALID_ADDRESS);
-            location.SetLocationListAddresses(
-                location_form.GetUnit()->GetBaseAddress(), func_low_pc);
-          }
-        }
-      } else if (const_value_form.IsValid()) {
-        location_is_const_value_data = true;
-        // The constant value will be either a block, a data value or a
-        // string.
-        const DWARFDataExtractor &debug_info_data = die.GetData();
-        if (DWARFFormValue::IsBlockForm(const_value_form.Form())) {
-          // Retrieve the value as a block expression.
-          uint32_t block_offset =
-              const_value_form.BlockData() - debug_info_data.GetDataStart();
-          uint32_t block_length = const_value_form.Unsigned();
-          location = DWARFExpression(
-              module,
-              DataExtractor(debug_info_data, block_offset, block_length),
-              die.GetCU());
-        } else if (DWARFFormValue::IsDataForm(const_value_form.Form())) {
-          // Constant value size does not have to match the size of the
-          // variable. We will fetch the size of the type after we create
-          // it.
-          use_type_size_for_value = true;
-        } else if (const char *str = const_value_form.AsCString()) {
-          uint32_t string_length = strlen(str) + 1;
-          location = DWARFExpression(
-              module,
-              DataExtractor(str, string_length, die.GetCU()->GetByteOrder(),
-                            die.GetCU()->GetAddressByteSize()),
-              die.GetCU());
-        }
-      }
+  DWARFAttributes attributes;
+  const size_t num_attributes = die.GetAttributes(attributes);
+  DWARFDIE spec_die;
+  VariableSP var_sp;
+  const char *name = nullptr;
+  const char *mangled = nullptr;
+  Declaration decl;
+  DWARFFormValue type_die_form;
+  DWARFExpression location;
+  bool is_external = false;
+  bool is_artificial = false;
+  DWARFFormValue const_value_form, location_form;
+  Variable::RangeList scope_ranges;
+
+  for (size_t i = 0; i < num_attributes; ++i) {
+    dw_attr_t attr = attributes.AttributeAtIndex(i);
+    DWARFFormValue form_value;
+
+    if (!attributes.ExtractFormValueAtIndex(i, form_value))
+      continue;
+    switch (attr) {
+    case DW_AT_decl_file:
+      decl.SetFile(sc.comp_unit->GetSupportFiles().GetFileSpecAtIndex(
+          form_value.Unsigned()));
+      break;
+    case DW_AT_decl_line:
+      decl.SetLine(form_value.Unsigned());
+      break;
+    case DW_AT_decl_column:
+      decl.SetColumn(form_value.Unsigned());
+      break;
+    case DW_AT_name:
+      name = form_value.AsCString();
+      break;
+    case DW_AT_linkage_name:
+    case DW_AT_MIPS_linkage_name:
+      mangled = form_value.AsCString();
+      break;
+    case DW_AT_type:
+      type_die_form = form_value;
+      break;
+    case DW_AT_external:
+      is_external = form_value.Boolean();
+      break;
+    case DW_AT_const_value:
+      const_value_form = form_value;
+      break;
+    case DW_AT_location:
+      location_form = form_value;
+      break;
+    case DW_AT_specification:
+      spec_die = form_value.Reference();
+      break;
+    case DW_AT_start_scope:
+      // TODO: Implement this.
+      break;
+    case DW_AT_artificial:
+      is_artificial = form_value.Boolean();
+      break;
+    case DW_AT_declaration:
+    case DW_AT_description:
+    case DW_AT_endianity:
+    case DW_AT_segment:
+    case DW_AT_visibility:
+    default:
+    case DW_AT_abstract_origin:
+    case DW_AT_sibling:
+      break;
+    }
+  }
 
-      const DWARFDIE parent_context_die = GetDeclContextDIEContainingDIE(die);
-      const dw_tag_t parent_tag = die.GetParent().Tag();
-      bool is_static_member =
-          (parent_tag == DW_TAG_compile_unit ||
-           parent_tag == DW_TAG_partial_unit) &&
-          (parent_context_die.Tag() == DW_TAG_class_type ||
-           parent_context_die.Tag() == DW_TAG_structure_type);
-
-      ValueType scope = eValueTypeInvalid;
-
-      const DWARFDIE sc_parent_die = GetParentSymbolContextDIE(die);
-      SymbolContextScope *symbol_context_scope = nullptr;
-
-      bool has_explicit_mangled = mangled != nullptr;
-      if (!mangled) {
-        // LLDB relies on the mangled name (DW_TAG_linkage_name or
-        // DW_AT_MIPS_linkage_name) to generate fully qualified names
-        // of global variables with commands like "frame var j". For
-        // example, if j were an int variable holding a value 4 and
-        // declared in a namespace B which in turn is contained in a
-        // namespace A, the command "frame var j" returns
-        //   "(int) A::B::j = 4".
-        // If the compiler does not emit a linkage name, we should be
-        // able to generate a fully qualified name from the
-        // declaration context.
-        if ((parent_tag == DW_TAG_compile_unit ||
-             parent_tag == DW_TAG_partial_unit) &&
-            Language::LanguageIsCPlusPlus(GetLanguage(*die.GetCU())))
-          mangled = GetDWARFDeclContext(die)
-                        .GetQualifiedNameAsConstString()
-                        .GetCString();
+  // Prefer DW_AT_location over DW_AT_const_value. Both can be emitted e.g.
+  // for static constexpr member variables -- DW_AT_const_value will be
+  // present in the class declaration and DW_AT_location in the DIE defining
+  // the member.
+  bool location_is_const_value_data = false;
+  bool has_explicit_location = false;
+  bool use_type_size_for_value = false;
+  if (location_form.IsValid()) {
+    has_explicit_location = true;
+    if (DWARFFormValue::IsBlockForm(location_form.Form())) {
+      const DWARFDataExtractor &data = die.GetData();
+
+      uint32_t block_offset = location_form.BlockData() - data.GetDataStart();
+      uint32_t block_length = location_form.Unsigned();
+      location = DWARFExpression(
+          module, DataExtractor(data, block_offset, block_length), die.GetCU());
+    } else {
+      DataExtractor data = die.GetCU()->GetLocationData();
+      dw_offset_t offset = location_form.Unsigned();
+      if (location_form.Form() == DW_FORM_loclistx)
+        offset = die.GetCU()->GetLoclistOffset(offset).getValueOr(-1);
+      if (data.ValidOffset(offset)) {
+        data = DataExtractor(data, offset, data.GetByteSize() - offset);
+        location = DWARFExpression(module, data, die.GetCU());
+        assert(func_low_pc != LLDB_INVALID_ADDRESS);
+        location.SetLocationListAddresses(
+            location_form.GetUnit()->GetBaseAddress(), func_low_pc);
       }
+    }
+  } else if (const_value_form.IsValid()) {
+    location_is_const_value_data = true;
+    // The constant value will be either a block, a data value or a
+    // string.
+    const DWARFDataExtractor &debug_info_data = die.GetData();
+    if (DWARFFormValue::IsBlockForm(const_value_form.Form())) {
+      // Retrieve the value as a block expression.
+      uint32_t block_offset =
+          const_value_form.BlockData() - debug_info_data.GetDataStart();
+      uint32_t block_length = const_value_form.Unsigned();
+      location = DWARFExpression(
+          module, DataExtractor(debug_info_data, block_offset, block_length),
+          die.GetCU());
+    } else if (DWARFFormValue::IsDataForm(const_value_form.Form())) {
+      // Constant value size does not have to match the size of the
+      // variable. We will fetch the size of the type after we create
+      // it.
+      use_type_size_for_value = true;
+    } else if (const char *str = const_value_form.AsCString()) {
+      uint32_t string_length = strlen(str) + 1;
+      location = DWARFExpression(
+          module,
+          DataExtractor(str, string_length, die.GetCU()->GetByteOrder(),
+                        die.GetCU()->GetAddressByteSize()),
+          die.GetCU());
+    }
+  }
 
-      if (tag == DW_TAG_formal_parameter)
-        scope = eValueTypeVariableArgument;
-      else {
-        // DWARF doesn't specify if a DW_TAG_variable is a local, global
-        // or static variable, so we have to do a little digging:
-        // 1) DW_AT_linkage_name implies static lifetime (but may be missing)
-        // 2) An empty DW_AT_location is an (optimized-out) static lifetime var.
-        // 3) DW_AT_location containing a DW_OP_addr implies static lifetime.
-        // Clang likes to combine small global variables into the same symbol
-        // with locations like: DW_OP_addr(0x1000), DW_OP_constu(2), DW_OP_plus
-        // so we need to look through the whole expression.
-        bool is_static_lifetime =
-            has_explicit_mangled ||
-            (has_explicit_location && !location.IsValid());
-        // Check if the location has a DW_OP_addr with any address value...
-        lldb::addr_t location_DW_OP_addr = LLDB_INVALID_ADDRESS;
-        if (!location_is_const_value_data) {
-          bool op_error = false;
-          location_DW_OP_addr = location.GetLocation_DW_OP_addr(0, op_error);
-          if (op_error) {
-            StreamString strm;
-            location.DumpLocationForAddress(&strm, eDescriptionLevelFull, 0, 0,
-                                            nullptr);
-            GetObjectFile()->GetModule()->ReportError(
-                "0x%8.8x: %s has an invalid location: %s", die.GetOffset(),
-                die.GetTagAsCString(), strm.GetData());
-          }
-          if (location_DW_OP_addr != LLDB_INVALID_ADDRESS)
-            is_static_lifetime = true;
-        }
-        SymbolFileDWARFDebugMap *debug_map_symfile = GetDebugMapSymfile();
-        if (debug_map_symfile)
-          // Set the module of the expression to the linked module
-          // instead of the oject file so the relocated address can be
-          // found there.
-          location.SetModule(debug_map_symfile->GetObjectFile()->GetModule());
-
-        if (is_static_lifetime) {
-          if (is_external)
-            scope = eValueTypeVariableGlobal;
-          else
-            scope = eValueTypeVariableStatic;
-
-          if (debug_map_symfile) {
-            // When leaving the DWARF in the .o files on darwin, when we have a
-            // global variable that wasn't initialized, the .o file might not
-            // have allocated a virtual address for the global variable. In
-            // this case it will have created a symbol for the global variable
-            // that is undefined/data and external and the value will be the
-            // byte size of the variable. When we do the address map in
-            // SymbolFileDWARFDebugMap we rely on having an address, we need to
-            // do some magic here so we can get the correct address for our
-            // global variable. The address for all of these entries will be
-            // zero, and there will be an undefined symbol in this object file,
-            // and the executable will have a matching symbol with a good
-            // address. So here we dig up the correct address and replace it in
-            // the location for the variable, and set the variable's symbol
-            // context scope to be that of the main executable so the file
-            // address will resolve correctly.
-            bool linked_oso_file_addr = false;
-            if (is_external && location_DW_OP_addr == 0) {
-              // we have a possible uninitialized extern global
-              ConstString const_name(mangled ? mangled : name);
-              ObjectFile *debug_map_objfile =
-                  debug_map_symfile->GetObjectFile();
-              if (debug_map_objfile) {
-                Symtab *debug_map_symtab = debug_map_objfile->GetSymtab();
-                if (debug_map_symtab) {
-                  Symbol *exe_symbol =
-                      debug_map_symtab->FindFirstSymbolWithNameAndType(
-                          const_name, eSymbolTypeData, Symtab::eDebugYes,
-                          Symtab::eVisibilityExtern);
-                  if (exe_symbol) {
-                    if (exe_symbol->ValueIsAddress()) {
-                      const addr_t exe_file_addr =
-                          exe_symbol->GetAddressRef().GetFileAddress();
-                      if (exe_file_addr != LLDB_INVALID_ADDRESS) {
-                        if (location.Update_DW_OP_addr(exe_file_addr)) {
-                          linked_oso_file_addr = true;
-                          symbol_context_scope = exe_symbol;
-                        }
-                      }
+  const DWARFDIE parent_context_die = GetDeclContextDIEContainingDIE(die);
+  const dw_tag_t parent_tag = die.GetParent().Tag();
+  bool is_static_member = (parent_tag == DW_TAG_compile_unit ||
+                           parent_tag == DW_TAG_partial_unit) &&
+                          (parent_context_die.Tag() == DW_TAG_class_type ||
+                           parent_context_die.Tag() == DW_TAG_structure_type);
+
+  ValueType scope = eValueTypeInvalid;
+
+  const DWARFDIE sc_parent_die = GetParentSymbolContextDIE(die);
+  SymbolContextScope *symbol_context_scope = nullptr;
+
+  bool has_explicit_mangled = mangled != nullptr;
+  if (!mangled) {
+    // LLDB relies on the mangled name (DW_TAG_linkage_name or
+    // DW_AT_MIPS_linkage_name) to generate fully qualified names
+    // of global variables with commands like "frame var j". For
+    // example, if j were an int variable holding a value 4 and
+    // declared in a namespace B which in turn is contained in a
+    // namespace A, the command "frame var j" returns
+    //   "(int) A::B::j = 4".
+    // If the compiler does not emit a linkage name, we should be
+    // able to generate a fully qualified name from the
+    // declaration context.
+    if ((parent_tag == DW_TAG_compile_unit ||
+         parent_tag == DW_TAG_partial_unit) &&
+        Language::LanguageIsCPlusPlus(GetLanguage(*die.GetCU())))
+      mangled =
+          GetDWARFDeclContext(die).GetQualifiedNameAsConstString().GetCString();
+  }
+
+  if (tag == DW_TAG_formal_parameter)
+    scope = eValueTypeVariableArgument;
+  else {
+    // DWARF doesn't specify if a DW_TAG_variable is a local, global
+    // or static variable, so we have to do a little digging:
+    // 1) DW_AT_linkage_name implies static lifetime (but may be missing)
+    // 2) An empty DW_AT_location is an (optimized-out) static lifetime var.
+    // 3) DW_AT_location containing a DW_OP_addr implies static lifetime.
+    // Clang likes to combine small global variables into the same symbol
+    // with locations like: DW_OP_addr(0x1000), DW_OP_constu(2), DW_OP_plus
+    // so we need to look through the whole expression.
+    bool is_static_lifetime =
+        has_explicit_mangled || (has_explicit_location && !location.IsValid());
+    // Check if the location has a DW_OP_addr with any address value...
+    lldb::addr_t location_DW_OP_addr = LLDB_INVALID_ADDRESS;
+    if (!location_is_const_value_data) {
+      bool op_error = false;
+      location_DW_OP_addr = location.GetLocation_DW_OP_addr(0, op_error);
+      if (op_error) {
+        StreamString strm;
+        location.DumpLocationForAddress(&strm, eDescriptionLevelFull, 0, 0,
+                                        nullptr);
+        GetObjectFile()->GetModule()->ReportError(
+            "0x%8.8x: %s has an invalid location: %s", die.GetOffset(),
+            die.GetTagAsCString(), strm.GetData());
+      }
+      if (location_DW_OP_addr != LLDB_INVALID_ADDRESS)
+        is_static_lifetime = true;
+    }
+    SymbolFileDWARFDebugMap *debug_map_symfile = GetDebugMapSymfile();
+    if (debug_map_symfile)
+      // Set the module of the expression to the linked module
+      // instead of the oject file so the relocated address can be
+      // found there.
+      location.SetModule(debug_map_symfile->GetObjectFile()->GetModule());
+
+    if (is_static_lifetime) {
+      if (is_external)
+        scope = eValueTypeVariableGlobal;
+      else
+        scope = eValueTypeVariableStatic;
+
+      if (debug_map_symfile) {
+        // When leaving the DWARF in the .o files on darwin, when we have a
+        // global variable that wasn't initialized, the .o file might not
+        // have allocated a virtual address for the global variable. In
+        // this case it will have created a symbol for the global variable
+        // that is undefined/data and external and the value will be the
+        // byte size of the variable. When we do the address map in
+        // SymbolFileDWARFDebugMap we rely on having an address, we need to
+        // do some magic here so we can get the correct address for our
+        // global variable. The address for all of these entries will be
+        // zero, and there will be an undefined symbol in this object file,
+        // and the executable will have a matching symbol with a good
+        // address. So here we dig up the correct address and replace it in
+        // the location for the variable, and set the variable's symbol
+        // context scope to be that of the main executable so the file
+        // address will resolve correctly.
+        bool linked_oso_file_addr = false;
+        if (is_external && location_DW_OP_addr == 0) {
+          // we have a possible uninitialized extern global
+          ConstString const_name(mangled ? mangled : name);
+          ObjectFile *debug_map_objfile = debug_map_symfile->GetObjectFile();
+          if (debug_map_objfile) {
+            Symtab *debug_map_symtab = debug_map_objfile->GetSymtab();
+            if (debug_map_symtab) {
+              Symbol *exe_symbol =
+                  debug_map_symtab->FindFirstSymbolWithNameAndType(
+                      const_name, eSymbolTypeData, Symtab::eDebugYes,
+                      Symtab::eVisibilityExtern);
+              if (exe_symbol) {
+                if (exe_symbol->ValueIsAddress()) {
+                  const addr_t exe_file_addr =
+                      exe_symbol->GetAddressRef().GetFileAddress();
+                  if (exe_file_addr != LLDB_INVALID_ADDRESS) {
+                    if (location.Update_DW_OP_addr(exe_file_addr)) {
+                      linked_oso_file_addr = true;
+                      symbol_context_scope = exe_symbol;
                     }
                   }
                 }
               }
             }
-
-            if (!linked_oso_file_addr) {
-              // The DW_OP_addr is not zero, but it contains a .o file address
-              // which needs to be linked up correctly.
-              const lldb::addr_t exe_file_addr =
-                  debug_map_symfile->LinkOSOFileAddress(this,
-                                                        location_DW_OP_addr);
-              if (exe_file_addr != LLDB_INVALID_ADDRESS) {
-                // Update the file address for this variable
-                location.Update_DW_OP_addr(exe_file_addr);
-              } else {
-                // Variable didn't make it into the final executable
-                return var_sp;
-              }
-            }
           }
-        } else {
-          if (location_is_const_value_data &&
-              die.GetDIE()->IsGlobalOrStaticScopeVariable())
-            scope = eValueTypeVariableStatic;
-          else {
-            scope = eValueTypeVariableLocal;
-            if (debug_map_symfile) {
-              // We need to check for TLS addresses that we need to fixup
-              if (location.ContainsThreadLocalStorage()) {
-                location.LinkThreadLocalStorage(
-                    debug_map_symfile->GetObjectFile()->GetModule(),
-                    [this, debug_map_symfile](
-                        lldb::addr_t unlinked_file_addr) -> lldb::addr_t {
-                      return debug_map_symfile->LinkOSOFileAddress(
-                          this, unlinked_file_addr);
-                    });
-                scope = eValueTypeVariableThreadLocal;
-              }
-            }
+        }
+
+        if (!linked_oso_file_addr) {
+          // The DW_OP_addr is not zero, but it contains a .o file address
+          // which needs to be linked up correctly.
+          const lldb::addr_t exe_file_addr =
+              debug_map_symfile->LinkOSOFileAddress(this, location_DW_OP_addr);
+          if (exe_file_addr != LLDB_INVALID_ADDRESS) {
+            // Update the file address for this variable
+            location.Update_DW_OP_addr(exe_file_addr);
+          } else {
+            // Variable didn't make it into the final executable
+            return var_sp;
           }
         }
       }
-
-      if (symbol_context_scope == nullptr) {
-        switch (parent_tag) {
-        case DW_TAG_subprogram:
-        case DW_TAG_inlined_subroutine:
-        case DW_TAG_lexical_block:
-          if (sc.function) {
-            symbol_context_scope = sc.function->GetBlock(true).FindBlockByID(
-                sc_parent_die.GetID());
-            if (symbol_context_scope == nullptr)
-              symbol_context_scope = sc.function;
+    } else {
+      if (location_is_const_value_data &&
+          die.GetDIE()->IsGlobalOrStaticScopeVariable())
+        scope = eValueTypeVariableStatic;
+      else {
+        scope = eValueTypeVariableLocal;
+        if (debug_map_symfile) {
+          // We need to check for TLS addresses that we need to fixup
+          if (location.ContainsThreadLocalStorage()) {
+            location.LinkThreadLocalStorage(
+                debug_map_symfile->GetObjectFile()->GetModule(),
+                [this, debug_map_symfile](
+                    lldb::addr_t unlinked_file_addr) -> lldb::addr_t {
+                  return debug_map_symfile->LinkOSOFileAddress(
+                      this, unlinked_file_addr);
+                });
+            scope = eValueTypeVariableThreadLocal;
           }
-          break;
-
-        default:
-          symbol_context_scope = sc.comp_unit;
-          break;
         }
       }
+    }
+  }
 
-      if (symbol_context_scope) {
-        auto type_sp = std::make_shared<SymbolFileType>(
-            *this, GetUID(type_die_form.Reference()));
+  if (symbol_context_scope == nullptr) {
+    switch (parent_tag) {
+    case DW_TAG_subprogram:
+    case DW_TAG_inlined_subroutine:
+    case DW_TAG_lexical_block:
+      if (sc.function) {
+        symbol_context_scope =
+            sc.function->GetBlock(true).FindBlockByID(sc_parent_die.GetID());
+        if (symbol_context_scope == nullptr)
+          symbol_context_scope = sc.function;
+      }
+      break;
 
-        if (use_type_size_for_value && type_sp->GetType())
-          location.UpdateValue(
-              const_value_form.Unsigned(),
-              type_sp->GetType()->GetByteSize(nullptr).getValueOr(0),
-              die.GetCU()->GetAddressByteSize());
+    default:
+      symbol_context_scope = sc.comp_unit;
+      break;
+    }
+  }
 
-        var_sp = std::make_shared<Variable>(
-            die.GetID(), name, mangled, type_sp, scope, symbol_context_scope,
-            scope_ranges, &decl, location, is_external, is_artificial,
-            is_static_member);
+  if (symbol_context_scope) {
+    auto type_sp = std::make_shared<SymbolFileType>(
+        *this, GetUID(type_die_form.Reference()));
 
-        var_sp->SetLocationIsConstantValueData(location_is_const_value_data);
-      } else {
-        // Not ready to parse this variable yet. It might be a global or static
-        // variable that is in a function scope and the function in the symbol
-        // context wasn't filled in yet
-        return var_sp;
-      }
-    }
-    // Cache var_sp even if NULL (the variable was just a specification or was
-    // missing vital information to be able to be displayed in the debugger
-    // (missing location due to optimization, etc)) so we don't re-parse this
-    // DIE over and over later...
-    GetDIEToVariable()[die.GetDIE()] = var_sp;
-    if (spec_die)
-      GetDIEToVariable()[spec_die.GetDIE()] = var_sp;
+    if (use_type_size_for_value && type_sp->GetType())
+      location.UpdateValue(
+          const_value_form.Unsigned(),
+          type_sp->GetType()->GetByteSize(nullptr).getValueOr(0),
+          die.GetCU()->GetAddressByteSize());
+
+    var_sp = std::make_shared<Variable>(
+        die.GetID(), name, mangled, type_sp, scope, symbol_context_scope,
+        scope_ranges, &decl, location, is_external, is_artificial,
+        is_static_member);
+
+    var_sp->SetLocationIsConstantValueData(location_is_const_value_data);
+  } else {
+    // Not ready to parse this variable yet. It might be a global or static
+    // variable that is in a function scope and the function in the symbol
+    // context wasn't filled in yet
+    return var_sp;
   }
+  // Cache var_sp even if NULL (the variable was just a specification or was
+  // missing vital information to be able to be displayed in the debugger
+  // (missing location due to optimization, etc)) so we don't re-parse this
+  // DIE over and over later...
+  GetDIEToVariable()[die.GetDIE()] = var_sp;
+  if (spec_die)
+    GetDIEToVariable()[spec_die.GetDIE()] = var_sp;
+
   return var_sp;
 }