@@ -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,27 @@ 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
+ // Little-endian 64-bit
77
+ if (const ELF64LEObjectFile *ELFObj =
78
+ dyn_cast<ELF64LEObjectFile>(&**ElfOrErr))
79
+ return checkMachineImpl (*ELFObj, EMachine);
80
+ // Big-endian 64-bit
81
+ if (const ELF64BEObjectFile *ELFObj =
82
+ dyn_cast<ELF64BEObjectFile>(&**ElfOrErr))
83
+ return checkMachineImpl (*ELFObj, EMachine);
84
+ return createError (" Only 64-bit ELF files are supported" );
85
+ }
86
+
74
87
template <class ELFT >
75
88
static Expected<const typename ELFT::Sym *>
76
89
getSymbolFromGnuHashTable (StringRef Name, const typename ELFT::GnuHash &HashTab,
@@ -231,8 +244,9 @@ getSymTableSymbol(const ELFFile<ELFT> &Elf, const typename ELFT::Shdr &Sec,
231
244
return nullptr ;
232
245
}
233
246
234
- Expected<const typename ELF64LE::Sym *>
235
- utils::elf::getSymbol (const ELFObjectFile<ELF64LE> &ELFObj, StringRef Name) {
247
+ template <class ELFT >
248
+ static Expected<const typename ELFT::Sym *>
249
+ getSymbol (const ELFObjectFile<ELFT> &ELFObj, StringRef Name) {
236
250
// First try to look up the symbol via the hash table.
237
251
for (ELFSectionRef Sec : ELFObj.sections ()) {
238
252
if (Sec.getType () != SHT_HASH && Sec.getType () != SHT_GNU_HASH)
@@ -241,8 +255,7 @@ utils::elf::getSymbol(const ELFObjectFile<ELF64LE> &ELFObj, StringRef Name) {
241
255
auto HashTabOrErr = ELFObj.getELFFile ().getSection (Sec.getIndex ());
242
256
if (!HashTabOrErr)
243
257
return HashTabOrErr.takeError ();
244
- return getHashTableSymbol<ELF64LE>(ELFObj.getELFFile (), **HashTabOrErr,
245
- Name);
258
+ return getHashTableSymbol<ELFT>(ELFObj.getELFFile (), **HashTabOrErr, Name);
246
259
}
247
260
248
261
// If this is an executable file check the entire standard symbol table.
@@ -253,16 +266,17 @@ utils::elf::getSymbol(const ELFObjectFile<ELF64LE> &ELFObj, StringRef Name) {
253
266
auto SymTabOrErr = ELFObj.getELFFile ().getSection (Sec.getIndex ());
254
267
if (!SymTabOrErr)
255
268
return SymTabOrErr.takeError ();
256
- return getSymTableSymbol<ELF64LE >(ELFObj.getELFFile (), **SymTabOrErr, Name);
269
+ return getSymTableSymbol<ELFT >(ELFObj.getELFFile (), **SymTabOrErr, Name);
257
270
}
258
271
259
272
return nullptr ;
260
273
}
261
274
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 ();
275
+ template <class ELFT >
276
+ static Expected<const void *>
277
+ getSymbolAddress (const object::ELFObjectFile<ELFT> &ELFObj,
278
+ const typename ELFT::Sym &Symbol) {
279
+ const ELFFile<ELFT> &ELFFile = ELFObj.getELFFile ();
266
280
267
281
auto SecOrErr = ELFFile.getSection (Symbol.st_shndx );
268
282
if (!SecOrErr)
@@ -283,3 +297,45 @@ Expected<const void *> utils::elf::getSymbolAddress(
283
297
284
298
return ELFFile.base () + Offset;
285
299
}
300
+
301
+ template <class ELFT >
302
+ static Expected<StringRef>
303
+ findSymbolInImageImpl (const object::ELFObjectFile<ELFT> &ELFObj,
304
+ StringRef Name) {
305
+ // Search for the symbol by name.
306
+ auto SymOrErr = getSymbol (ELFObj, Name);
307
+ if (!SymOrErr)
308
+ return SymOrErr.takeError ();
309
+ // If symbol not found, return an empty StringRef.
310
+ if (!*SymOrErr)
311
+ return StringRef ();
312
+
313
+ // Retrieve the symbol address within the object's memory image.
314
+ auto AddrOrErr = getSymbolAddress (ELFObj, **SymOrErr);
315
+ if (!AddrOrErr)
316
+ return AddrOrErr.takeError ();
317
+
318
+ // Return a StringRef covering the symbol's data, based on
319
+ // its address and size.
320
+ return StringRef (static_cast <const char *>(*AddrOrErr), (*SymOrErr)->st_size );
321
+ }
322
+
323
+ Expected<StringRef> utils::elf::findSymbolInImage (MemoryBufferRef Obj,
324
+ StringRef Name) {
325
+ assert (isELF (Obj.getBuffer ()) && " Input is not an ELF!" );
326
+
327
+ Expected<std::unique_ptr<ObjectFile>> ElfOrErr =
328
+ ObjectFile::createELFObjectFile (Obj, /* InitContent=*/ false );
329
+ if (!ElfOrErr)
330
+ return ElfOrErr.takeError ();
331
+
332
+ // Little-endian 64-bit
333
+ if (const ELF64LEObjectFile *ELFObj =
334
+ dyn_cast<ELF64LEObjectFile>(&**ElfOrErr))
335
+ return findSymbolInImageImpl (*ELFObj, Name);
336
+ // Big-endian 64-bit
337
+ if (const ELF64BEObjectFile *ELFObj =
338
+ dyn_cast<ELF64BEObjectFile>(&**ElfOrErr))
339
+ return findSymbolInImageImpl (*ELFObj, Name);
340
+ return createError (" Only 64-bit ELF files are supported" );
341
+ }
0 commit comments