1 //===-- SBSection.cpp -------------------------------------------*- C++ -*-===//
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 "lldb/API/SBSection.h"
10 #include "SBReproducerPrivate.h"
11 #include "lldb/API/SBStream.h"
12 #include "lldb/API/SBTarget.h"
13 #include "lldb/Core/Module.h"
14 #include "lldb/Core/Section.h"
15 #include "lldb/Symbol/ObjectFile.h"
16 #include "lldb/Utility/DataBuffer.h"
17 #include "lldb/Utility/DataExtractor.h"
18 #include "lldb/Utility/StreamString.h"
19 
20 using namespace lldb;
21 using namespace lldb_private;
22 
23 SBSection::SBSection() : m_opaque_wp() {
24   LLDB_RECORD_CONSTRUCTOR_NO_ARGS(SBSection);
25 }
26 
27 SBSection::SBSection(const SBSection &rhs) : m_opaque_wp(rhs.m_opaque_wp) {
28   LLDB_RECORD_CONSTRUCTOR(SBSection, (const lldb::SBSection &), rhs);
29 }
30 
31 SBSection::SBSection(const lldb::SectionSP &section_sp)
32     : m_opaque_wp() // Don't init with section_sp otherwise this will throw if
33                     // section_sp doesn't contain a valid Section *
34 {
35   if (section_sp)
36     m_opaque_wp = section_sp;
37 }
38 
39 const SBSection &SBSection::operator=(const SBSection &rhs) {
40   LLDB_RECORD_METHOD(const lldb::SBSection &,
41                      SBSection, operator=,(const lldb::SBSection &), rhs);
42 
43   m_opaque_wp = rhs.m_opaque_wp;
44   return *this;
45 }
46 
47 SBSection::~SBSection() {}
48 
49 bool SBSection::IsValid() const {
50   LLDB_RECORD_METHOD_CONST_NO_ARGS(bool, SBSection, IsValid);
51 
52   SectionSP section_sp(GetSP());
53   return section_sp && section_sp->GetModule().get() != NULL;
54 }
55 
56 const char *SBSection::GetName() {
57   LLDB_RECORD_METHOD_NO_ARGS(const char *, SBSection, GetName);
58 
59   SectionSP section_sp(GetSP());
60   if (section_sp)
61     return section_sp->GetName().GetCString();
62   return NULL;
63 }
64 
65 lldb::SBSection SBSection::GetParent() {
66   LLDB_RECORD_METHOD_NO_ARGS(lldb::SBSection, SBSection, GetParent);
67 
68   lldb::SBSection sb_section;
69   SectionSP section_sp(GetSP());
70   if (section_sp) {
71     SectionSP parent_section_sp(section_sp->GetParent());
72     if (parent_section_sp)
73       sb_section.SetSP(parent_section_sp);
74   }
75   return LLDB_RECORD_RESULT(sb_section);
76 }
77 
78 lldb::SBSection SBSection::FindSubSection(const char *sect_name) {
79   LLDB_RECORD_METHOD(lldb::SBSection, SBSection, FindSubSection, (const char *),
80                      sect_name);
81 
82   lldb::SBSection sb_section;
83   if (sect_name) {
84     SectionSP section_sp(GetSP());
85     if (section_sp) {
86       ConstString const_sect_name(sect_name);
87       sb_section.SetSP(
88           section_sp->GetChildren().FindSectionByName(const_sect_name));
89     }
90   }
91   return LLDB_RECORD_RESULT(sb_section);
92 }
93 
94 size_t SBSection::GetNumSubSections() {
95   LLDB_RECORD_METHOD_NO_ARGS(size_t, SBSection, GetNumSubSections);
96 
97   SectionSP section_sp(GetSP());
98   if (section_sp)
99     return section_sp->GetChildren().GetSize();
100   return 0;
101 }
102 
103 lldb::SBSection SBSection::GetSubSectionAtIndex(size_t idx) {
104   LLDB_RECORD_METHOD(lldb::SBSection, SBSection, GetSubSectionAtIndex, (size_t),
105                      idx);
106 
107   lldb::SBSection sb_section;
108   SectionSP section_sp(GetSP());
109   if (section_sp)
110     sb_section.SetSP(section_sp->GetChildren().GetSectionAtIndex(idx));
111   return LLDB_RECORD_RESULT(sb_section);
112 }
113 
114 lldb::SectionSP SBSection::GetSP() const { return m_opaque_wp.lock(); }
115 
116 void SBSection::SetSP(const lldb::SectionSP &section_sp) {
117   m_opaque_wp = section_sp;
118 }
119 
120 lldb::addr_t SBSection::GetFileAddress() {
121   LLDB_RECORD_METHOD_NO_ARGS(lldb::addr_t, SBSection, GetFileAddress);
122 
123   lldb::addr_t file_addr = LLDB_INVALID_ADDRESS;
124   SectionSP section_sp(GetSP());
125   if (section_sp)
126     return section_sp->GetFileAddress();
127   return file_addr;
128 }
129 
130 lldb::addr_t SBSection::GetLoadAddress(lldb::SBTarget &sb_target) {
131   LLDB_RECORD_METHOD(lldb::addr_t, SBSection, GetLoadAddress,
132                      (lldb::SBTarget &), sb_target);
133 
134   TargetSP target_sp(sb_target.GetSP());
135   if (target_sp) {
136     SectionSP section_sp(GetSP());
137     if (section_sp)
138       return section_sp->GetLoadBaseAddress(target_sp.get());
139   }
140   return LLDB_INVALID_ADDRESS;
141 }
142 
143 lldb::addr_t SBSection::GetByteSize() {
144   LLDB_RECORD_METHOD_NO_ARGS(lldb::addr_t, SBSection, GetByteSize);
145 
146   SectionSP section_sp(GetSP());
147   if (section_sp)
148     return section_sp->GetByteSize();
149   return 0;
150 }
151 
152 uint64_t SBSection::GetFileOffset() {
153   LLDB_RECORD_METHOD_NO_ARGS(uint64_t, SBSection, GetFileOffset);
154 
155   SectionSP section_sp(GetSP());
156   if (section_sp) {
157     ModuleSP module_sp(section_sp->GetModule());
158     if (module_sp) {
159       ObjectFile *objfile = module_sp->GetObjectFile();
160       if (objfile)
161         return objfile->GetFileOffset() + section_sp->GetFileOffset();
162     }
163   }
164   return UINT64_MAX;
165 }
166 
167 uint64_t SBSection::GetFileByteSize() {
168   LLDB_RECORD_METHOD_NO_ARGS(uint64_t, SBSection, GetFileByteSize);
169 
170   SectionSP section_sp(GetSP());
171   if (section_sp)
172     return section_sp->GetFileSize();
173   return 0;
174 }
175 
176 SBData SBSection::GetSectionData() {
177   LLDB_RECORD_METHOD_NO_ARGS(lldb::SBData, SBSection, GetSectionData);
178 
179   return LLDB_RECORD_RESULT(GetSectionData(0, UINT64_MAX));
180 }
181 
182 SBData SBSection::GetSectionData(uint64_t offset, uint64_t size) {
183   LLDB_RECORD_METHOD(lldb::SBData, SBSection, GetSectionData,
184                      (uint64_t, uint64_t), offset, size);
185 
186   SBData sb_data;
187   SectionSP section_sp(GetSP());
188   if (section_sp) {
189     const uint64_t sect_file_size = section_sp->GetFileSize();
190     if (sect_file_size > 0) {
191       ModuleSP module_sp(section_sp->GetModule());
192       if (module_sp) {
193         ObjectFile *objfile = module_sp->GetObjectFile();
194         if (objfile) {
195           const uint64_t sect_file_offset =
196               objfile->GetFileOffset() + section_sp->GetFileOffset();
197           const uint64_t file_offset = sect_file_offset + offset;
198           uint64_t file_size = size;
199           if (file_size == UINT64_MAX) {
200             file_size = section_sp->GetByteSize();
201             if (file_size > offset)
202               file_size -= offset;
203             else
204               file_size = 0;
205           }
206           auto data_buffer_sp = FileSystem::Instance().CreateDataBuffer(
207               objfile->GetFileSpec().GetPath(), file_size, file_offset);
208           if (data_buffer_sp && data_buffer_sp->GetByteSize() > 0) {
209             DataExtractorSP data_extractor_sp(
210                 new DataExtractor(data_buffer_sp, objfile->GetByteOrder(),
211                                   objfile->GetAddressByteSize()));
212 
213             sb_data.SetOpaque(data_extractor_sp);
214           }
215         }
216       }
217     }
218   }
219   return LLDB_RECORD_RESULT(sb_data);
220 }
221 
222 SectionType SBSection::GetSectionType() {
223   LLDB_RECORD_METHOD_NO_ARGS(lldb::SectionType, SBSection, GetSectionType);
224 
225   SectionSP section_sp(GetSP());
226   if (section_sp.get())
227     return section_sp->GetType();
228   return eSectionTypeInvalid;
229 }
230 
231 uint32_t SBSection::GetPermissions() const {
232   LLDB_RECORD_METHOD_CONST_NO_ARGS(uint32_t, SBSection, GetPermissions);
233 
234   SectionSP section_sp(GetSP());
235   if (section_sp)
236     return section_sp->GetPermissions();
237   return 0;
238 }
239 
240 uint32_t SBSection::GetTargetByteSize() {
241   LLDB_RECORD_METHOD_NO_ARGS(uint32_t, SBSection, GetTargetByteSize);
242 
243   SectionSP section_sp(GetSP());
244   if (section_sp.get())
245     return section_sp->GetTargetByteSize();
246   return 0;
247 }
248 
249 bool SBSection::operator==(const SBSection &rhs) {
250   LLDB_RECORD_METHOD(bool, SBSection, operator==,(const lldb::SBSection &),
251                      rhs);
252 
253   SectionSP lhs_section_sp(GetSP());
254   SectionSP rhs_section_sp(rhs.GetSP());
255   if (lhs_section_sp && rhs_section_sp)
256     return lhs_section_sp == rhs_section_sp;
257   return false;
258 }
259 
260 bool SBSection::operator!=(const SBSection &rhs) {
261   LLDB_RECORD_METHOD(bool, SBSection, operator!=,(const lldb::SBSection &),
262                      rhs);
263 
264   SectionSP lhs_section_sp(GetSP());
265   SectionSP rhs_section_sp(rhs.GetSP());
266   return lhs_section_sp != rhs_section_sp;
267 }
268 
269 bool SBSection::GetDescription(SBStream &description) {
270   LLDB_RECORD_METHOD(bool, SBSection, GetDescription, (lldb::SBStream &),
271                      description);
272 
273   Stream &strm = description.ref();
274 
275   SectionSP section_sp(GetSP());
276   if (section_sp) {
277     const addr_t file_addr = section_sp->GetFileAddress();
278     strm.Printf("[0x%16.16" PRIx64 "-0x%16.16" PRIx64 ") ", file_addr,
279                 file_addr + section_sp->GetByteSize());
280     section_sp->DumpName(&strm);
281   } else {
282     strm.PutCString("No value");
283   }
284 
285   return true;
286 }
287