1 | //===-- NameToDIE.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 "NameToDIE.h" |
10 | #include "DWARFUnit.h" |
11 | #include "lldb/Core/DataFileCache.h" |
12 | #include "lldb/Symbol/ObjectFile.h" |
13 | #include "lldb/Utility/ConstString.h" |
14 | #include "lldb/Utility/DataEncoder.h" |
15 | #include "lldb/Utility/DataExtractor.h" |
16 | #include "lldb/Utility/RegularExpression.h" |
17 | #include "lldb/Utility/Stream.h" |
18 | #include "lldb/Utility/StreamString.h" |
19 | #include <optional> |
20 | |
21 | using namespace lldb; |
22 | using namespace lldb_private; |
23 | using namespace lldb_private::plugin::dwarf; |
24 | |
25 | void NameToDIE::Finalize() { |
26 | m_map.Sort(tc: std::less<DIERef>()); |
27 | m_map.SizeToFit(); |
28 | } |
29 | |
30 | void NameToDIE::Insert(ConstString name, const DIERef &die_ref) { |
31 | m_map.Append(unique_cstr: name, value: die_ref); |
32 | } |
33 | |
34 | bool NameToDIE::Find(ConstString name, |
35 | llvm::function_ref<bool(DIERef ref)> callback) const { |
36 | for (const auto &entry : m_map.equal_range(unique_cstr: name)) |
37 | if (!callback(entry.value)) |
38 | return false; |
39 | return true; |
40 | } |
41 | |
42 | bool NameToDIE::Find(const RegularExpression ®ex, |
43 | llvm::function_ref<bool(DIERef ref)> callback) const { |
44 | for (const auto &entry : m_map) |
45 | if (regex.Execute(string: entry.cstring.GetCString())) { |
46 | if (!callback(entry.value)) |
47 | return false; |
48 | } |
49 | return true; |
50 | } |
51 | |
52 | void NameToDIE::FindAllEntriesForUnit( |
53 | DWARFUnit &s_unit, llvm::function_ref<bool(DIERef ref)> callback) const { |
54 | const DWARFUnit &ns_unit = s_unit.GetNonSkeletonUnit(); |
55 | const uint32_t size = m_map.GetSize(); |
56 | for (uint32_t i = 0; i < size; ++i) { |
57 | const DIERef &die_ref = m_map.GetValueAtIndexUnchecked(idx: i); |
58 | if (ns_unit.GetSymbolFileDWARF().GetFileIndex() == die_ref.file_index() && |
59 | ns_unit.GetDebugSection() == die_ref.section() && |
60 | ns_unit.GetOffset() <= die_ref.die_offset() && |
61 | die_ref.die_offset() < ns_unit.GetNextUnitOffset()) { |
62 | if (!callback(die_ref)) |
63 | return; |
64 | } |
65 | } |
66 | } |
67 | |
68 | void NameToDIE::Dump(Stream *s) { |
69 | const uint32_t size = m_map.GetSize(); |
70 | for (uint32_t i = 0; i < size; ++i) { |
71 | s->Format(format: "{0} \"{1}\"\n" , args: m_map.GetValueAtIndexUnchecked(idx: i), |
72 | args: m_map.GetCStringAtIndexUnchecked(idx: i)); |
73 | } |
74 | } |
75 | |
76 | void NameToDIE::ForEach( |
77 | std::function<bool(ConstString name, const DIERef &die_ref)> const |
78 | &callback) const { |
79 | const uint32_t size = m_map.GetSize(); |
80 | for (uint32_t i = 0; i < size; ++i) { |
81 | if (!callback(m_map.GetCStringAtIndexUnchecked(idx: i), |
82 | m_map.GetValueAtIndexUnchecked(idx: i))) |
83 | break; |
84 | } |
85 | } |
86 | |
87 | void NameToDIE::Append(const NameToDIE &other) { |
88 | const uint32_t size = other.m_map.GetSize(); |
89 | for (uint32_t i = 0; i < size; ++i) { |
90 | m_map.Append(unique_cstr: other.m_map.GetCStringAtIndexUnchecked(idx: i), |
91 | value: other.m_map.GetValueAtIndexUnchecked(idx: i)); |
92 | } |
93 | } |
94 | |
95 | constexpr llvm::StringLiteral kIdentifierNameToDIE("N2DI" ); |
96 | |
97 | bool NameToDIE::(const DataExtractor &data, lldb::offset_t *offset_ptr, |
98 | const StringTableReader &strtab) { |
99 | m_map.Clear(); |
100 | llvm::StringRef identifier((const char *)data.GetData(offset_ptr, length: 4), 4); |
101 | if (identifier != kIdentifierNameToDIE) |
102 | return false; |
103 | const uint32_t count = data.GetU32(offset_ptr); |
104 | m_map.Reserve(n: count); |
105 | for (uint32_t i = 0; i < count; ++i) { |
106 | llvm::StringRef str(strtab.Get(offset: data.GetU32(offset_ptr))); |
107 | // No empty strings allowed in the name to DIE maps. |
108 | if (str.empty()) |
109 | return false; |
110 | if (std::optional<DIERef> die_ref = DIERef::Decode(data, offset_ptr)) |
111 | m_map.Append(unique_cstr: ConstString(str), value: *die_ref); |
112 | else |
113 | return false; |
114 | } |
115 | // We must sort the UniqueCStringMap after decoding it since it is a vector |
116 | // of UniqueCStringMap::Entry objects which contain a ConstString and type T. |
117 | // ConstString objects are sorted by "const char *" and then type T and |
118 | // the "const char *" are point values that will depend on the order in which |
119 | // ConstString objects are created and in which of the 256 string pools they |
120 | // are created in. So after we decode all of the entries, we must sort the |
121 | // name map to ensure name lookups succeed. If we encode and decode within |
122 | // the same process we wouldn't need to sort, so unit testing didn't catch |
123 | // this issue when first checked in. |
124 | m_map.Sort(tc: std::less<DIERef>()); |
125 | return true; |
126 | } |
127 | |
128 | void NameToDIE::Encode(DataEncoder &encoder, ConstStringTable &strtab) const { |
129 | encoder.AppendData(data: kIdentifierNameToDIE); |
130 | encoder.AppendU32(value: m_map.GetSize()); |
131 | for (const auto &entry : m_map) { |
132 | // Make sure there are no empty strings. |
133 | assert((bool)entry.cstring); |
134 | encoder.AppendU32(value: strtab.Add(s: entry.cstring)); |
135 | entry.value.Encode(encoder); |
136 | } |
137 | } |
138 | |
139 | bool NameToDIE::operator==(const NameToDIE &rhs) const { |
140 | const size_t size = m_map.GetSize(); |
141 | if (size != rhs.m_map.GetSize()) |
142 | return false; |
143 | for (size_t i = 0; i < size; ++i) { |
144 | if (m_map.GetCStringAtIndex(idx: i) != rhs.m_map.GetCStringAtIndex(idx: i)) |
145 | return false; |
146 | if (m_map.GetValueRefAtIndexUnchecked(idx: i) != |
147 | rhs.m_map.GetValueRefAtIndexUnchecked(idx: i)) |
148 | return false; |
149 | } |
150 | return true; |
151 | } |
152 | |