llvm.org GIT mirror llvm / c8a55a6
Object/Archive: Add symbol table iteration. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@143561 91177308-0d34-0410-b5e6-96231b3b80d8 Michael J. Spencer 8 years ago
2 changed file(s) with 118 addition(s) and 10 deletion(s). Raw diff Collapse all Expand all
4949 class child_iterator {
5050 Child child;
5151 public:
52 child_iterator() : child(Child(0, StringRef())) {}
5253 child_iterator(const Child &c) : child(c) {}
5354 const Child* operator->() const {
5455 return &child;
6869 }
6970 };
7071
72 class Symbol {
73 const Archive *Parent;
74 uint32_t SymbolIndex;
75 uint32_t StringIndex; // Extra index to the string.
76
77 public:
78 bool operator ==(const Symbol &other) const {
79 return (Parent == other.Parent) && (SymbolIndex == other.SymbolIndex);
80 }
81
82 Symbol(const Archive *p, uint32_t symi, uint32_t stri)
83 : Parent(p)
84 , SymbolIndex(symi)
85 , StringIndex(stri) {}
86 error_code getName(StringRef &Result) const;
87 error_code getMember(child_iterator &Result) const;
88 Symbol getNext() const;
89 };
90
91 class symbol_iterator {
92 Symbol symbol;
93 public:
94 symbol_iterator(const Symbol &s) : symbol(s) {}
95 const Symbol *operator->() const {
96 return &symbol;
97 }
98
99 bool operator==(const symbol_iterator &other) const {
100 return symbol == other.symbol;
101 }
102
103 bool operator!=(const symbol_iterator &other) const {
104 return !(*this == other);
105 }
106
107 symbol_iterator& operator++() { // Preincrement
108 symbol = symbol.getNext();
109 return *this;
110 }
111 };
112
71113 Archive(MemoryBuffer *source, error_code &ec);
72114
73115 child_iterator begin_children(bool skip_internal = true) const;
74116 child_iterator end_children() const;
117
118 symbol_iterator begin_symbols() const;
119 symbol_iterator end_symbols() const;
75120
76121 // Cast methods.
77122 static inline bool classof(Archive const *v) { return true; }
80125 }
81126
82127 private:
128 child_iterator SymbolTable;
83129 child_iterator StringTable;
84130 };
85131
1212
1313 #include "llvm/Object/Archive.h"
1414 #include "llvm/ADT/APInt.h"
15 #include "llvm/Support/Endian.h"
1516 #include "llvm/Support/MemoryBuffer.h"
1617
1718 using namespace llvm;
170171 }
171172
172173 Archive::Archive(MemoryBuffer *source, error_code &ec)
173 : Binary(Binary::isArchive, source)
174 , StringTable(Child(this, StringRef(0, 0))) {
174 : Binary(Binary::isArchive, source) {
175175 // Check for sufficient magic.
176176 if (!source || source->getBufferSize()
177177 < (8 + sizeof(ArchiveMemberHeader) + 2) // Smallest archive.
180180 return;
181181 }
182182
183 // Get the string table. It's the 3rd member.
184 child_iterator StrTable = begin_children(false);
183 // Get the special members.
184 child_iterator i = begin_children(false);
185185 child_iterator e = end_children();
186 for (int i = 0; StrTable != e && i < 2; ++StrTable, ++i) {}
187
188 // Check to see if there were 3 members, or the 3rd member wasn't named "//".
189 StringRef name;
190 if (StrTable != e && !StrTable->getName(name) && name == "//")
191 StringTable = StrTable;
186
187 if (i != e) ++i; // Nobody cares about the first member.
188 if (i != e) {
189 SymbolTable = i;
190 ++i;
191 }
192 if (i != e) {
193 StringTable = i;
194 }
192195
193196 ec = object_error::success;
194197 }
207210 Archive::child_iterator Archive::end_children() const {
208211 return Child(this, StringRef(0, 0));
209212 }
213
214 error_code Archive::Symbol::getName(StringRef &Result) const {
215 Result =
216 StringRef(Parent->SymbolTable->getBuffer()->getBufferStart() + StringIndex);
217 return object_error::success;
218 }
219
220 error_code Archive::Symbol::getMember(child_iterator &Result) const {
221 const char *buf = Parent->SymbolTable->getBuffer()->getBufferStart();
222 uint32_t member_count = *reinterpret_cast(buf);
223 const char *offsets = buf + 4;
224 buf += 4 + (member_count * 4); // Skip offsets.
225 uint32_t symbol_count = *reinterpret_cast(buf);
226 const char *indicies = buf + 4;
227
228 uint16_t offsetindex =
229 *(reinterpret_cast(indicies)
230 + SymbolIndex);
231
232 uint32_t offset = *(reinterpret_cast(offsets)
233 + (offsetindex - 1));
234
235 const char *Loc = Parent->getData().begin() + offset;
236 size_t Size = sizeof(ArchiveMemberHeader) +
237 ToHeader(Loc)->getSize();
238 Result = Child(Parent, StringRef(Loc, Size));
239
240 return object_error::success;
241 }
242
243 Archive::Symbol Archive::Symbol::getNext() const {
244 Symbol t(*this);
245 const char *buf = Parent->SymbolTable->getBuffer()->getBufferStart();
246 buf += t.StringIndex;
247 while (*buf++); // Go to one past next null.
248 t.StringIndex = buf - Parent->SymbolTable->getBuffer()->getBufferStart();
249 ++t.SymbolIndex;
250 return t;
251 }
252
253 Archive::symbol_iterator Archive::begin_symbols() const {
254 const char *buf = SymbolTable->getBuffer()->getBufferStart();
255 uint32_t member_count = *reinterpret_cast(buf);
256 buf += 4 + (member_count * 4); // Skip offsets.
257 uint32_t symbol_count = *reinterpret_cast(buf);
258 buf += 4 + (symbol_count * 2); // Skip indices.
259 uint32_t string_start_offset =
260 buf - SymbolTable->getBuffer()->getBufferStart();
261 return symbol_iterator(Symbol(this, 0, string_start_offset));
262 }
263
264 Archive::symbol_iterator Archive::end_symbols() const {
265 const char *buf = SymbolTable->getBuffer()->getBufferStart();
266 uint32_t member_count = *reinterpret_cast(buf);
267 buf += 4 + (member_count * 4); // Skip offsets.
268 uint32_t symbol_count = *reinterpret_cast(buf);
269 return symbol_iterator(
270 Symbol(this, symbol_count, 0));
271 }