@@ -36,18 +36,10 @@ bool utils::elf::isELF(StringRef Buffer) {
36
36
}
37
37
}
38
38
39
- Expected<bool > utils::elf::checkMachine (StringRef Object, uint16_t EMachine) {
40
- assert (isELF (Object) && " Input is not an ELF!" );
41
-
42
- Expected<ELF64LEObjectFile> ElfOrErr =
43
- ELF64LEObjectFile::create (MemoryBufferRef (Object, /* Identifier=*/ " " ),
44
- /* InitContent=*/ false );
45
- if (!ElfOrErr)
46
- return ElfOrErr.takeError ();
47
-
48
- const auto Header = ElfOrErr->getELFFile ().getHeader ();
49
- if (Header.e_ident [EI_CLASS] != ELFCLASS64)
50
- return createError (" Only 64-bit ELF files are supported" );
39
+ template <class ELFT >
40
+ static Expected<bool >
41
+ checkMachineImpl (const object::ELFObjectFile<ELFT> &ELFObj, uint16_t EMachine) {
42
+ const auto Header = ELFObj.getELFFile ().getHeader ();
51
43
if (Header.e_type != ET_EXEC && Header.e_type != ET_DYN)
52
44
return createError (" Only executable ELF files are supported" );
53
45
@@ -71,6 +63,25 @@ Expected<bool> utils::elf::checkMachine(StringRef Object, uint16_t EMachine) {
71
63
return Header.e_machine == EMachine;
72
64
}
73
65
66
+ Expected<bool > utils::elf::checkMachine (StringRef Object, uint16_t EMachine) {
67
+ assert (isELF (Object) && " Input is not an ELF!" );
68
+
69
+ Expected<std::unique_ptr<ObjectFile>> ElfOrErr =
70
+ ObjectFile::createELFObjectFile (
71
+ MemoryBufferRef (Object, /* Identifier=*/ " " ),
72
+ /* InitContent=*/ false );
73
+ if (!ElfOrErr)
74
+ return ElfOrErr.takeError ();
75
+
76
+ if (const ELF64LEObjectFile *ELFObj =
77
+ dyn_cast<ELF64LEObjectFile>(&**ElfOrErr))
78
+ return checkMachineImpl (*ELFObj, EMachine);
79
+ if (const ELF64BEObjectFile *ELFObj =
80
+ dyn_cast<ELF64BEObjectFile>(&**ElfOrErr))
81
+ return checkMachineImpl (*ELFObj, EMachine);
82
+ return createError (" Only 64-bit ELF files are supported" );
83
+ }
84
+
74
85
template <class ELFT >
75
86
static Expected<const typename ELFT::Sym *>
76
87
getSymbolFromGnuHashTable (StringRef Name, const typename ELFT::GnuHash &HashTab,
@@ -138,9 +149,10 @@ getSymbolFromSysVHashTable(StringRef Name, const typename ELFT::Hash &HashTab,
138
149
}
139
150
140
151
template <class ELFT >
141
- static Expected<const typename ELFT::Sym *>
142
- getHashTableSymbol (const ELFFile<ELFT> &Elf, const typename ELFT::Shdr &Sec,
143
- StringRef Name) {
152
+ static Expected<std::optional<ELFSymbolRef>>
153
+ getHashTableSymbol (const ELFObjectFile<ELFT> &ELFObj,
154
+ const typename ELFT::Shdr &Sec, StringRef Name) {
155
+ const ELFFile<ELFT> &Elf = ELFObj.getELFFile ();
144
156
if (Sec.sh_type != ELF::SHT_HASH && Sec.sh_type != ELF::SHT_GNU_HASH)
145
157
return createError (
146
158
" invalid sh_type for hash table, expected SHT_HASH or SHT_GNU_HASH" );
@@ -179,7 +191,10 @@ getHashTableSymbol(const ELFFile<ELFT> &Elf, const typename ELFT::Shdr &Sec,
179
191
sizeof (typename ELFT::Word) * HashTab->nbuckets +
180
192
sizeof (typename ELFT::Word) * (SymTab.size () - HashTab->symndx ))
181
193
return createError (" section has invalid sh_size: " + Twine (Sec.sh_size ));
182
- return getSymbolFromGnuHashTable<ELFT>(Name, *HashTab, SymTab, StrTab);
194
+ auto Sym = getSymbolFromGnuHashTable<ELFT>(Name, *HashTab, SymTab, StrTab);
195
+ if (!Sym)
196
+ return Sym.takeError ();
197
+ return ELFObj.toSymbolRef (*SymTabOrErr, *Sym - &SymTab[0 ]);
183
198
}
184
199
185
200
// If this is a Sys-V hash table we verify its size and search the symbol
@@ -197,16 +212,20 @@ getHashTableSymbol(const ELFFile<ELFT> &Elf, const typename ELFT::Shdr &Sec,
197
212
sizeof (typename ELFT::Word) * HashTab->nchain )
198
213
return createError (" section has invalid sh_size: " + Twine (Sec.sh_size ));
199
214
200
- return getSymbolFromSysVHashTable<ELFT>(Name, *HashTab, SymTab, StrTab);
215
+ auto Sym = getSymbolFromSysVHashTable<ELFT>(Name, *HashTab, SymTab, StrTab);
216
+ if (!Sym)
217
+ return Sym.takeError ();
218
+ return ELFObj.toSymbolRef (*SymTabOrErr, *Sym - &SymTab[0 ]);
201
219
}
202
220
203
- return nullptr ;
221
+ return std::nullopt ;
204
222
}
205
223
206
224
template <class ELFT >
207
- static Expected<const typename ELFT::Sym *>
208
- getSymTableSymbol (const ELFFile<ELFT> &Elf, const typename ELFT::Shdr &Sec,
209
- StringRef Name) {
225
+ static Expected<std::optional<ELFSymbolRef>>
226
+ getSymTableSymbol (const ELFObjectFile<ELFT> &ELFObj,
227
+ const typename ELFT::Shdr &Sec, StringRef Name) {
228
+ const ELFFile<ELFT> &Elf = ELFObj.getELFFile ();
210
229
if (Sec.sh_type != ELF::SHT_SYMTAB && Sec.sh_type != ELF::SHT_DYNSYM)
211
230
return createError (
212
231
" invalid sh_type for hash table, expected SHT_SYMTAB or SHT_DYNSYM" );
@@ -226,13 +245,14 @@ getSymTableSymbol(const ELFFile<ELFT> &Elf, const typename ELFT::Shdr &Sec,
226
245
227
246
for (const typename ELFT::Sym &Sym : SymTab)
228
247
if (StrTab.drop_front (Sym.st_name ).data () == Name)
229
- return & Sym;
248
+ return ELFObj. toSymbolRef (&Sec, & Sym - &SymTab[ 0 ]) ;
230
249
231
- return nullptr ;
250
+ return std::nullopt ;
232
251
}
233
252
234
- Expected<const typename ELF64LE::Sym *>
235
- utils::elf::getSymbol (const ELFObjectFile<ELF64LE> &ELFObj, StringRef Name) {
253
+ template <class ELFT >
254
+ static Expected<std::optional<ELFSymbolRef>>
255
+ getSymbolImpl (const ELFObjectFile<ELFT> &ELFObj, StringRef Name) {
236
256
// First try to look up the symbol via the hash table.
237
257
for (ELFSectionRef Sec : ELFObj.sections ()) {
238
258
if (Sec.getType () != SHT_HASH && Sec.getType () != SHT_GNU_HASH)
@@ -241,8 +261,7 @@ utils::elf::getSymbol(const ELFObjectFile<ELF64LE> &ELFObj, StringRef Name) {
241
261
auto HashTabOrErr = ELFObj.getELFFile ().getSection (Sec.getIndex ());
242
262
if (!HashTabOrErr)
243
263
return HashTabOrErr.takeError ();
244
- return getHashTableSymbol<ELF64LE>(ELFObj.getELFFile (), **HashTabOrErr,
245
- Name);
264
+ return getHashTableSymbol<ELFT>(ELFObj, **HashTabOrErr, Name);
246
265
}
247
266
248
267
// If this is an executable file check the entire standard symbol table.
@@ -253,16 +272,31 @@ utils::elf::getSymbol(const ELFObjectFile<ELF64LE> &ELFObj, StringRef Name) {
253
272
auto SymTabOrErr = ELFObj.getELFFile ().getSection (Sec.getIndex ());
254
273
if (!SymTabOrErr)
255
274
return SymTabOrErr.takeError ();
256
- return getSymTableSymbol<ELF64LE >(ELFObj. getELFFile () , **SymTabOrErr, Name);
275
+ return getSymTableSymbol<ELFT >(ELFObj, **SymTabOrErr, Name);
257
276
}
258
277
259
- return nullptr ;
278
+ return std::nullopt ;
260
279
}
261
280
262
- Expected<const void *> utils::elf::getSymbolAddress (
263
- const object::ELFObjectFile<object::ELF64LE> &ELFObj,
264
- const object::ELF64LE::Sym &Symbol) {
265
- const ELFFile<ELF64LE> &ELFFile = ELFObj.getELFFile ();
281
+ Expected<std::optional<ELFSymbolRef>>
282
+ utils::elf::getSymbol (const ObjectFile &Obj, StringRef Name) {
283
+ if (const ELF64LEObjectFile *ELFObj = dyn_cast<ELF64LEObjectFile>(&Obj))
284
+ return getSymbolImpl (*ELFObj, Name);
285
+ if (const ELF64BEObjectFile *ELFObj = dyn_cast<ELF64BEObjectFile>(&Obj))
286
+ return getSymbolImpl (*ELFObj, Name);
287
+ return createError (" Only 64-bit ELF files are supported" );
288
+ }
289
+
290
+ template <class ELFT >
291
+ static Expected<const void *>
292
+ getSymbolAddressImpl (const ELFObjectFile<ELFT> &ELFObj,
293
+ const ELFSymbolRef &SymRef) {
294
+ const ELFFile<ELFT> &ELFFile = ELFObj.getELFFile ();
295
+
296
+ auto SymOrErr = ELFObj.getSymbol (SymRef.getRawDataRefImpl ());
297
+ if (!SymOrErr)
298
+ return SymOrErr.takeError ();
299
+ const auto &Symbol = **SymOrErr;
266
300
267
301
auto SecOrErr = ELFFile.getSection (Symbol.st_shndx );
268
302
if (!SecOrErr)
@@ -283,3 +317,13 @@ Expected<const void *> utils::elf::getSymbolAddress(
283
317
284
318
return ELFFile.base () + Offset;
285
319
}
320
+
321
+ Expected<const void *>
322
+ utils::elf::getSymbolAddress (const ELFSymbolRef &SymRef) {
323
+ const ObjectFile *Obj = SymRef.getObject ();
324
+ if (const ELF64LEObjectFile *ELFObj = dyn_cast<ELF64LEObjectFile>(Obj))
325
+ return getSymbolAddressImpl (*ELFObj, SymRef);
326
+ if (const ELF64BEObjectFile *ELFObj = dyn_cast<ELF64BEObjectFile>(Obj))
327
+ return getSymbolAddressImpl (*ELFObj, SymRef);
328
+ return createError (" Only 64-bit ELF files are supported" );
329
+ }
0 commit comments