1 //===-- DWARFContext.cpp --------------------------------------------------===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 
9 #include "DWARFContext.h"
10 
11 #include "lldb/Core/Section.h"
12 #include <optional>
13 
14 using namespace lldb;
15 using namespace lldb_private;
16 using namespace lldb_private::plugin::dwarf;
17 
LoadSection(SectionList * section_list,SectionType section_type)18 static DWARFDataExtractor LoadSection(SectionList *section_list,
19                                       SectionType section_type) {
20   if (!section_list)
21     return DWARFDataExtractor();
22 
23   auto section_sp = section_list->FindSectionByType(section_type, true);
24   if (!section_sp)
25     return DWARFDataExtractor();
26 
27   DWARFDataExtractor data;
28   section_sp->GetSectionData(data);
29   return data;
30 }
31 
32 const DWARFDataExtractor &
LoadOrGetSection(std::optional<SectionType> main_section_type,std::optional<SectionType> dwo_section_type,SectionData & data)33 DWARFContext::LoadOrGetSection(std::optional<SectionType> main_section_type,
34                                std::optional<SectionType> dwo_section_type,
35                                SectionData &data) {
36   llvm::call_once(data.flag, [&] {
37     if (dwo_section_type && isDwo())
38       data.data = LoadSection(m_dwo_section_list, *dwo_section_type);
39     else if (main_section_type)
40       data.data = LoadSection(m_main_section_list, *main_section_type);
41   });
42   return data.data;
43 }
44 
getOrLoadCuIndexData()45 const DWARFDataExtractor &DWARFContext::getOrLoadCuIndexData() {
46   return LoadOrGetSection(std::nullopt, eSectionTypeDWARFDebugCuIndex,
47                           m_data_debug_cu_index);
48 }
49 
getOrLoadTuIndexData()50 const DWARFDataExtractor &DWARFContext::getOrLoadTuIndexData() {
51   return LoadOrGetSection(std::nullopt, eSectionTypeDWARFDebugTuIndex,
52                           m_data_debug_tu_index);
53 }
54 
getOrLoadAbbrevData()55 const DWARFDataExtractor &DWARFContext::getOrLoadAbbrevData() {
56   return LoadOrGetSection(eSectionTypeDWARFDebugAbbrev,
57                           eSectionTypeDWARFDebugAbbrevDwo, m_data_debug_abbrev);
58 }
59 
getOrLoadArangesData()60 const DWARFDataExtractor &DWARFContext::getOrLoadArangesData() {
61   return LoadOrGetSection(eSectionTypeDWARFDebugAranges, std::nullopt,
62                           m_data_debug_aranges);
63 }
64 
getOrLoadAddrData()65 const DWARFDataExtractor &DWARFContext::getOrLoadAddrData() {
66   return LoadOrGetSection(eSectionTypeDWARFDebugAddr, std::nullopt,
67                           m_data_debug_addr);
68 }
69 
getOrLoadDebugInfoData()70 const DWARFDataExtractor &DWARFContext::getOrLoadDebugInfoData() {
71   return LoadOrGetSection(eSectionTypeDWARFDebugInfo,
72                           eSectionTypeDWARFDebugInfoDwo, m_data_debug_info);
73 }
74 
getOrLoadLineData()75 const DWARFDataExtractor &DWARFContext::getOrLoadLineData() {
76   return LoadOrGetSection(eSectionTypeDWARFDebugLine, std::nullopt,
77                           m_data_debug_line);
78 }
79 
getOrLoadLineStrData()80 const DWARFDataExtractor &DWARFContext::getOrLoadLineStrData() {
81   return LoadOrGetSection(eSectionTypeDWARFDebugLineStr, std::nullopt,
82                           m_data_debug_line_str);
83 }
84 
getOrLoadLocData()85 const DWARFDataExtractor &DWARFContext::getOrLoadLocData() {
86   return LoadOrGetSection(eSectionTypeDWARFDebugLoc,
87                           eSectionTypeDWARFDebugLocDwo, m_data_debug_loc);
88 }
89 
getOrLoadLocListsData()90 const DWARFDataExtractor &DWARFContext::getOrLoadLocListsData() {
91   return LoadOrGetSection(eSectionTypeDWARFDebugLocLists,
92                           eSectionTypeDWARFDebugLocListsDwo,
93                           m_data_debug_loclists);
94 }
95 
getOrLoadMacroData()96 const DWARFDataExtractor &DWARFContext::getOrLoadMacroData() {
97   return LoadOrGetSection(eSectionTypeDWARFDebugMacro, std::nullopt,
98                           m_data_debug_macro);
99 }
100 
getOrLoadRangesData()101 const DWARFDataExtractor &DWARFContext::getOrLoadRangesData() {
102   return LoadOrGetSection(eSectionTypeDWARFDebugRanges, std::nullopt,
103                           m_data_debug_ranges);
104 }
105 
getOrLoadRngListsData()106 const DWARFDataExtractor &DWARFContext::getOrLoadRngListsData() {
107   return LoadOrGetSection(eSectionTypeDWARFDebugRngLists,
108                           eSectionTypeDWARFDebugRngListsDwo,
109                           m_data_debug_rnglists);
110 }
111 
getOrLoadStrData()112 const DWARFDataExtractor &DWARFContext::getOrLoadStrData() {
113   return LoadOrGetSection(eSectionTypeDWARFDebugStr,
114                           eSectionTypeDWARFDebugStrDwo, m_data_debug_str);
115 }
116 
getOrLoadStrOffsetsData()117 const DWARFDataExtractor &DWARFContext::getOrLoadStrOffsetsData() {
118   return LoadOrGetSection(eSectionTypeDWARFDebugStrOffsets,
119                           eSectionTypeDWARFDebugStrOffsetsDwo,
120                           m_data_debug_str_offsets);
121 }
122 
getOrLoadDebugTypesData()123 const DWARFDataExtractor &DWARFContext::getOrLoadDebugTypesData() {
124   return LoadOrGetSection(eSectionTypeDWARFDebugTypes,
125                           eSectionTypeDWARFDebugTypesDwo, m_data_debug_types);
126 }
127 
GetAsLLVM()128 llvm::DWARFContext &DWARFContext::GetAsLLVM() {
129   if (!m_llvm_context) {
130     llvm::StringMap<std::unique_ptr<llvm::MemoryBuffer>> section_map;
131     uint8_t addr_size = 0;
132     auto AddSection = [&](llvm::StringRef name, DWARFDataExtractor data) {
133       // Set the address size the first time we see it.
134       if (addr_size == 0)
135         addr_size = data.GetAddressByteSize();
136 
137       section_map.try_emplace(
138           name, llvm::MemoryBuffer::getMemBuffer(toStringRef(data.GetData()),
139                                                  name, false));
140     };
141 
142     AddSection("debug_line_str", getOrLoadLineStrData());
143     AddSection("debug_cu_index", getOrLoadCuIndexData());
144     AddSection("debug_tu_index", getOrLoadTuIndexData());
145     if (isDwo()) {
146       AddSection("debug_info.dwo", getOrLoadDebugInfoData());
147       AddSection("debug_types.dwo", getOrLoadDebugTypesData());
148     }
149     m_llvm_context = llvm::DWARFContext::create(section_map, addr_size);
150   }
151   return *m_llvm_context;
152 }
153