cmELF.cxx 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836
  1. /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
  2. file Copyright.txt or https://cmake.org/licensing for details. */
  3. #include "cmELF.h"
  4. #include <cstddef>
  5. #include <cstdint>
  6. #include <map>
  7. #include <memory>
  8. #include <sstream>
  9. #include <utility>
  10. #include <vector>
  11. #include <cm/memory>
  12. #include <cmext/algorithm>
  13. #include <cm3p/kwiml/abi.h>
  14. #include "cmsys/FStream.hxx"
  15. #include "cmelf/elf32.h"
  16. #include "cmelf/elf64.h"
  17. #include "cmelf/elf_common.h"
  18. // Low-level byte swapping implementation.
  19. template <size_t s>
  20. struct cmELFByteSwapSize
  21. {
  22. };
  23. static void cmELFByteSwap(char* data, cmELFByteSwapSize<2> /*unused*/)
  24. {
  25. char one_byte;
  26. one_byte = data[0];
  27. data[0] = data[1];
  28. data[1] = one_byte;
  29. }
  30. static void cmELFByteSwap(char* data, cmELFByteSwapSize<4> /*unused*/)
  31. {
  32. char one_byte;
  33. one_byte = data[0];
  34. data[0] = data[3];
  35. data[3] = one_byte;
  36. one_byte = data[1];
  37. data[1] = data[2];
  38. data[2] = one_byte;
  39. }
  40. static void cmELFByteSwap(char* data, cmELFByteSwapSize<8> /*unused*/)
  41. {
  42. char one_byte;
  43. one_byte = data[0];
  44. data[0] = data[7];
  45. data[7] = one_byte;
  46. one_byte = data[1];
  47. data[1] = data[6];
  48. data[6] = one_byte;
  49. one_byte = data[2];
  50. data[2] = data[5];
  51. data[5] = one_byte;
  52. one_byte = data[3];
  53. data[3] = data[4];
  54. data[4] = one_byte;
  55. }
  56. // Low-level byte swapping interface.
  57. template <typename T>
  58. void cmELFByteSwap(T& x)
  59. {
  60. cmELFByteSwap(reinterpret_cast<char*>(&x), cmELFByteSwapSize<sizeof(T)>());
  61. }
  62. class cmELFInternal
  63. {
  64. public:
  65. using StringEntry = cmELF::StringEntry;
  66. enum ByteOrderType
  67. {
  68. ByteOrderMSB,
  69. ByteOrderLSB
  70. };
  71. // Construct and take ownership of the file stream object.
  72. cmELFInternal(cmELF* external, std::unique_ptr<std::istream> fin,
  73. ByteOrderType order)
  74. : External(external)
  75. , Stream(std::move(fin))
  76. , ByteOrder(order)
  77. {
  78. // In most cases the processor-specific byte order will match that
  79. // of the target execution environment. If we choose wrong here
  80. // it is fixed when the header is read.
  81. #if KWIML_ABI_ENDIAN_ID == KWIML_ABI_ENDIAN_ID_LITTLE
  82. this->NeedSwap = (this->ByteOrder == ByteOrderMSB);
  83. #elif KWIML_ABI_ENDIAN_ID == KWIML_ABI_ENDIAN_ID_BIG
  84. this->NeedSwap = (this->ByteOrder == ByteOrderLSB);
  85. #else
  86. this->NeedSwap = false; // Final decision is at runtime anyway.
  87. #endif
  88. // We have not yet loaded the section info.
  89. this->DynamicSectionIndex = -1;
  90. }
  91. // Destruct and delete the file stream object.
  92. virtual ~cmELFInternal() = default;
  93. // Forward to the per-class implementation.
  94. virtual unsigned int GetNumberOfSections() const = 0;
  95. virtual unsigned long GetDynamicEntryPosition(int j) = 0;
  96. virtual cmELF::DynamicEntryList GetDynamicEntries() = 0;
  97. virtual std::vector<char> EncodeDynamicEntries(
  98. const cmELF::DynamicEntryList&) = 0;
  99. virtual StringEntry const* GetDynamicSectionString(unsigned int tag) = 0;
  100. virtual bool IsMips() const = 0;
  101. virtual void PrintInfo(std::ostream& os) const = 0;
  102. /** Returns true if the ELF file has a dynamic section **/
  103. bool HasDynamicSection() const { return this->DynamicSectionIndex >= 0; }
  104. // Lookup the SONAME in the DYNAMIC section.
  105. StringEntry const* GetSOName()
  106. {
  107. return this->GetDynamicSectionString(DT_SONAME);
  108. }
  109. // Lookup the RPATH in the DYNAMIC section.
  110. StringEntry const* GetRPath()
  111. {
  112. return this->GetDynamicSectionString(DT_RPATH);
  113. }
  114. // Lookup the RUNPATH in the DYNAMIC section.
  115. StringEntry const* GetRunPath()
  116. {
  117. return this->GetDynamicSectionString(DT_RUNPATH);
  118. }
  119. // Return the recorded ELF type.
  120. cmELF::FileType GetFileType() const { return this->ELFType; }
  121. // Return the recorded machine.
  122. std::uint16_t GetMachine() const { return this->Machine; }
  123. protected:
  124. // Data common to all ELF class implementations.
  125. // The external cmELF object.
  126. cmELF* External;
  127. // The stream from which to read.
  128. std::unique_ptr<std::istream> Stream;
  129. // The byte order of the ELF file.
  130. ByteOrderType ByteOrder;
  131. // The ELF file type.
  132. cmELF::FileType ELFType = cmELF::FileTypeInvalid;
  133. // The ELF architecture.
  134. std::uint16_t Machine;
  135. // Whether we need to byte-swap structures read from the stream.
  136. bool NeedSwap;
  137. // The section header index of the DYNAMIC section (-1 if none).
  138. int DynamicSectionIndex;
  139. // Helper methods for subclasses.
  140. void SetErrorMessage(const char* msg)
  141. {
  142. this->External->ErrorMessage = msg;
  143. this->ELFType = cmELF::FileTypeInvalid;
  144. }
  145. // Store string table entry states.
  146. std::map<unsigned int, StringEntry> DynamicSectionStrings;
  147. };
  148. // Configure the implementation template for 32-bit ELF files.
  149. struct cmELFTypes32
  150. {
  151. using ELF_Ehdr = Elf32_Ehdr;
  152. using ELF_Shdr = Elf32_Shdr;
  153. using ELF_Dyn = Elf32_Dyn;
  154. using ELF_Half = Elf32_Half;
  155. using tagtype = ::uint32_t;
  156. static const char* GetName() { return "32-bit"; }
  157. };
  158. // Configure the implementation template for 64-bit ELF files.
  159. struct cmELFTypes64
  160. {
  161. using ELF_Ehdr = Elf64_Ehdr;
  162. using ELF_Shdr = Elf64_Shdr;
  163. using ELF_Dyn = Elf64_Dyn;
  164. using ELF_Half = Elf64_Half;
  165. using tagtype = ::uint64_t;
  166. static const char* GetName() { return "64-bit"; }
  167. };
  168. // Parser implementation template.
  169. template <class Types>
  170. class cmELFInternalImpl : public cmELFInternal
  171. {
  172. public:
  173. // Copy the ELF file format types from our configuration parameter.
  174. using ELF_Ehdr = typename Types::ELF_Ehdr;
  175. using ELF_Shdr = typename Types::ELF_Shdr;
  176. using ELF_Dyn = typename Types::ELF_Dyn;
  177. using ELF_Half = typename Types::ELF_Half;
  178. using tagtype = typename Types::tagtype;
  179. // Construct with a stream and byte swap indicator.
  180. cmELFInternalImpl(cmELF* external, std::unique_ptr<std::istream> fin,
  181. ByteOrderType order);
  182. // Return the number of sections as specified by the ELF header.
  183. unsigned int GetNumberOfSections() const override
  184. {
  185. return static_cast<unsigned int>(this->ELFHeader.e_shnum +
  186. this->SectionHeaders[0].sh_size);
  187. }
  188. // Get the file position of a dynamic section entry.
  189. unsigned long GetDynamicEntryPosition(int j) override;
  190. cmELF::DynamicEntryList GetDynamicEntries() override;
  191. std::vector<char> EncodeDynamicEntries(
  192. const cmELF::DynamicEntryList&) override;
  193. // Lookup a string from the dynamic section with the given tag.
  194. StringEntry const* GetDynamicSectionString(unsigned int tag) override;
  195. bool IsMips() const override { return this->ELFHeader.e_machine == EM_MIPS; }
  196. // Print information about the ELF file.
  197. void PrintInfo(std::ostream& os) const override
  198. {
  199. os << "ELF " << Types::GetName();
  200. if (this->ByteOrder == ByteOrderMSB) {
  201. os << " MSB";
  202. } else if (this->ByteOrder == ByteOrderLSB) {
  203. os << " LSB";
  204. }
  205. switch (this->ELFType) {
  206. case cmELF::FileTypeInvalid:
  207. os << " invalid file";
  208. break;
  209. case cmELF::FileTypeRelocatableObject:
  210. os << " relocatable object";
  211. break;
  212. case cmELF::FileTypeExecutable:
  213. os << " executable";
  214. break;
  215. case cmELF::FileTypeSharedLibrary:
  216. os << " shared library";
  217. break;
  218. case cmELF::FileTypeCore:
  219. os << " core file";
  220. break;
  221. case cmELF::FileTypeSpecificOS:
  222. os << " os-specific type";
  223. break;
  224. case cmELF::FileTypeSpecificProc:
  225. os << " processor-specific type";
  226. break;
  227. }
  228. os << "\n";
  229. }
  230. private:
  231. static_assert(sizeof(ELF_Dyn().d_un.d_val) == sizeof(ELF_Dyn().d_un.d_ptr),
  232. "ByteSwap(ELF_Dyn) assumes d_val and d_ptr are the same size");
  233. void ByteSwap(ELF_Ehdr& elf_header)
  234. {
  235. cmELFByteSwap(elf_header.e_type);
  236. cmELFByteSwap(elf_header.e_machine);
  237. cmELFByteSwap(elf_header.e_version);
  238. cmELFByteSwap(elf_header.e_entry);
  239. cmELFByteSwap(elf_header.e_phoff);
  240. cmELFByteSwap(elf_header.e_shoff);
  241. cmELFByteSwap(elf_header.e_flags);
  242. cmELFByteSwap(elf_header.e_ehsize);
  243. cmELFByteSwap(elf_header.e_phentsize);
  244. cmELFByteSwap(elf_header.e_phnum);
  245. cmELFByteSwap(elf_header.e_shentsize);
  246. cmELFByteSwap(elf_header.e_shnum);
  247. cmELFByteSwap(elf_header.e_shstrndx);
  248. }
  249. void ByteSwap(ELF_Shdr& sec_header)
  250. {
  251. cmELFByteSwap(sec_header.sh_name);
  252. cmELFByteSwap(sec_header.sh_type);
  253. cmELFByteSwap(sec_header.sh_flags);
  254. cmELFByteSwap(sec_header.sh_addr);
  255. cmELFByteSwap(sec_header.sh_offset);
  256. cmELFByteSwap(sec_header.sh_size);
  257. cmELFByteSwap(sec_header.sh_link);
  258. cmELFByteSwap(sec_header.sh_info);
  259. cmELFByteSwap(sec_header.sh_addralign);
  260. cmELFByteSwap(sec_header.sh_entsize);
  261. }
  262. void ByteSwap(ELF_Dyn& dyn)
  263. {
  264. cmELFByteSwap(dyn.d_tag);
  265. cmELFByteSwap(dyn.d_un.d_val);
  266. }
  267. bool FileTypeValid(ELF_Half et)
  268. {
  269. unsigned int eti = static_cast<unsigned int>(et);
  270. if (eti == ET_NONE || eti == ET_REL || eti == ET_EXEC || eti == ET_DYN ||
  271. eti == ET_CORE) {
  272. return true;
  273. }
  274. if (eti >= ET_LOOS && eti <= ET_HIOS) {
  275. return true;
  276. }
  277. if (eti >= ET_LOPROC && eti <= ET_HIPROC) {
  278. return true;
  279. }
  280. return false;
  281. }
  282. bool Read(ELF_Ehdr& x)
  283. {
  284. // Read the header from the file.
  285. if (!this->Stream->read(reinterpret_cast<char*>(&x), sizeof(x))) {
  286. return false;
  287. }
  288. // The byte order of ELF header fields may not match that of the
  289. // processor-specific data. The header fields are ordered to
  290. // match the target execution environment, so we may need to
  291. // memorize the order of all platforms based on the e_machine
  292. // value. As a heuristic, if the type is invalid but its
  293. // swapped value is okay then flip our swap mode.
  294. ELF_Half et = x.e_type;
  295. if (this->NeedSwap) {
  296. cmELFByteSwap(et);
  297. }
  298. if (!this->FileTypeValid(et)) {
  299. cmELFByteSwap(et);
  300. if (this->FileTypeValid(et)) {
  301. // The previous byte order guess was wrong. Flip it.
  302. this->NeedSwap = !this->NeedSwap;
  303. }
  304. }
  305. // Fix the byte order of the header.
  306. if (this->NeedSwap) {
  307. this->ByteSwap(x);
  308. }
  309. return true;
  310. }
  311. bool Read(ELF_Shdr& x)
  312. {
  313. if (this->Stream->read(reinterpret_cast<char*>(&x), sizeof(x)) &&
  314. this->NeedSwap) {
  315. this->ByteSwap(x);
  316. }
  317. return !this->Stream->fail();
  318. }
  319. bool Read(ELF_Dyn& x)
  320. {
  321. if (this->Stream->read(reinterpret_cast<char*>(&x), sizeof(x)) &&
  322. this->NeedSwap) {
  323. this->ByteSwap(x);
  324. }
  325. return !this->Stream->fail();
  326. }
  327. bool LoadSectionHeader(unsigned int i)
  328. {
  329. // Read the section header from the file.
  330. this->Stream->seekg(this->ELFHeader.e_shoff +
  331. this->ELFHeader.e_shentsize * i);
  332. if (!this->Read(this->SectionHeaders[i])) {
  333. return false;
  334. }
  335. // Identify some important sections.
  336. if (this->SectionHeaders[i].sh_type == SHT_DYNAMIC) {
  337. this->DynamicSectionIndex = static_cast<int>(i);
  338. }
  339. return true;
  340. }
  341. bool LoadDynamicSection();
  342. // Store the main ELF header.
  343. ELF_Ehdr ELFHeader;
  344. // Store all the section headers.
  345. std::vector<ELF_Shdr> SectionHeaders;
  346. // Store all entries of the DYNAMIC section.
  347. std::vector<ELF_Dyn> DynamicSectionEntries;
  348. };
  349. template <class Types>
  350. cmELFInternalImpl<Types>::cmELFInternalImpl(cmELF* external,
  351. std::unique_ptr<std::istream> fin,
  352. ByteOrderType order)
  353. : cmELFInternal(external, std::move(fin), order)
  354. {
  355. // Read the main header.
  356. if (!this->Read(this->ELFHeader)) {
  357. this->SetErrorMessage("Failed to read main ELF header.");
  358. return;
  359. }
  360. // Determine the ELF file type.
  361. switch (this->ELFHeader.e_type) {
  362. case ET_NONE:
  363. this->SetErrorMessage("ELF file type is NONE.");
  364. return;
  365. case ET_REL:
  366. this->ELFType = cmELF::FileTypeRelocatableObject;
  367. break;
  368. case ET_EXEC:
  369. this->ELFType = cmELF::FileTypeExecutable;
  370. break;
  371. case ET_DYN:
  372. this->ELFType = cmELF::FileTypeSharedLibrary;
  373. break;
  374. case ET_CORE:
  375. this->ELFType = cmELF::FileTypeCore;
  376. break;
  377. default: {
  378. unsigned int eti = static_cast<unsigned int>(this->ELFHeader.e_type);
  379. if (eti >= ET_LOOS && eti <= ET_HIOS) {
  380. this->ELFType = cmELF::FileTypeSpecificOS;
  381. break;
  382. }
  383. if (eti >= ET_LOPROC && eti <= ET_HIPROC) {
  384. this->ELFType = cmELF::FileTypeSpecificProc;
  385. break;
  386. }
  387. std::ostringstream e;
  388. e << "Unknown ELF file type " << eti;
  389. this->SetErrorMessage(e.str().c_str());
  390. return;
  391. }
  392. }
  393. this->Machine = this->ELFHeader.e_machine;
  394. // Load the section headers.
  395. this->SectionHeaders.resize(
  396. this->ELFHeader.e_shnum == 0 ? 1 : this->ELFHeader.e_shnum);
  397. this->LoadSectionHeader(0);
  398. this->SectionHeaders.resize(this->GetNumberOfSections());
  399. for (unsigned int i = 1; i < this->GetNumberOfSections(); ++i) {
  400. if (!this->LoadSectionHeader(i)) {
  401. this->SetErrorMessage("Failed to load section headers.");
  402. return;
  403. }
  404. }
  405. }
  406. template <class Types>
  407. bool cmELFInternalImpl<Types>::LoadDynamicSection()
  408. {
  409. // If there is no dynamic section we are done.
  410. if (!this->HasDynamicSection()) {
  411. return false;
  412. }
  413. // If the section was already loaded we are done.
  414. if (!this->DynamicSectionEntries.empty()) {
  415. return true;
  416. }
  417. // If there are no entries we are done.
  418. ELF_Shdr const& sec = this->SectionHeaders[this->DynamicSectionIndex];
  419. if (sec.sh_entsize == 0) {
  420. return false;
  421. }
  422. // Allocate the dynamic section entries.
  423. int n = static_cast<int>(sec.sh_size / sec.sh_entsize);
  424. this->DynamicSectionEntries.resize(n);
  425. // Read each entry.
  426. for (int j = 0; j < n; ++j) {
  427. // Seek to the beginning of the section entry.
  428. this->Stream->seekg(sec.sh_offset + sec.sh_entsize * j);
  429. ELF_Dyn& dyn = this->DynamicSectionEntries[j];
  430. // Try reading the entry.
  431. if (!this->Read(dyn)) {
  432. this->SetErrorMessage("Error reading entry from DYNAMIC section.");
  433. this->DynamicSectionIndex = -1;
  434. return false;
  435. }
  436. }
  437. return true;
  438. }
  439. template <class Types>
  440. unsigned long cmELFInternalImpl<Types>::GetDynamicEntryPosition(int j)
  441. {
  442. if (!this->LoadDynamicSection()) {
  443. return 0;
  444. }
  445. if (j < 0 || j >= static_cast<int>(this->DynamicSectionEntries.size())) {
  446. return 0;
  447. }
  448. ELF_Shdr const& sec = this->SectionHeaders[this->DynamicSectionIndex];
  449. return sec.sh_offset + sec.sh_entsize * static_cast<unsigned long>(j);
  450. }
  451. template <class Types>
  452. cmELF::DynamicEntryList cmELFInternalImpl<Types>::GetDynamicEntries()
  453. {
  454. cmELF::DynamicEntryList result;
  455. // Ensure entries have been read from file
  456. if (!this->LoadDynamicSection()) {
  457. return result;
  458. }
  459. // Copy into public array
  460. result.reserve(this->DynamicSectionEntries.size());
  461. for (ELF_Dyn& dyn : this->DynamicSectionEntries) {
  462. result.emplace_back(dyn.d_tag, dyn.d_un.d_val);
  463. }
  464. return result;
  465. }
  466. template <class Types>
  467. std::vector<char> cmELFInternalImpl<Types>::EncodeDynamicEntries(
  468. const cmELF::DynamicEntryList& entries)
  469. {
  470. std::vector<char> result;
  471. result.reserve(sizeof(ELF_Dyn) * entries.size());
  472. for (auto const& entry : entries) {
  473. // Store the entry in an ELF_Dyn, byteswap it, then serialize to chars
  474. ELF_Dyn dyn;
  475. dyn.d_tag = static_cast<tagtype>(entry.first);
  476. dyn.d_un.d_val = static_cast<tagtype>(entry.second);
  477. if (this->NeedSwap) {
  478. this->ByteSwap(dyn);
  479. }
  480. char* pdyn = reinterpret_cast<char*>(&dyn);
  481. cm::append(result, pdyn, pdyn + sizeof(ELF_Dyn));
  482. }
  483. return result;
  484. }
  485. template <class Types>
  486. cmELF::StringEntry const* cmELFInternalImpl<Types>::GetDynamicSectionString(
  487. unsigned int tag)
  488. {
  489. // Short-circuit if already checked.
  490. auto dssi = this->DynamicSectionStrings.find(tag);
  491. if (dssi != this->DynamicSectionStrings.end()) {
  492. if (dssi->second.Position > 0) {
  493. return &dssi->second;
  494. }
  495. return nullptr;
  496. }
  497. // Create an entry for this tag. Assume it is missing until found.
  498. StringEntry& se = this->DynamicSectionStrings[tag];
  499. se.Position = 0;
  500. se.Size = 0;
  501. se.IndexInSection = -1;
  502. // Try reading the dynamic section.
  503. if (!this->LoadDynamicSection()) {
  504. return nullptr;
  505. }
  506. // Get the string table referenced by the DYNAMIC section.
  507. ELF_Shdr const& sec = this->SectionHeaders[this->DynamicSectionIndex];
  508. if (sec.sh_link >= this->SectionHeaders.size()) {
  509. this->SetErrorMessage("Section DYNAMIC has invalid string table index.");
  510. return nullptr;
  511. }
  512. ELF_Shdr const& strtab = this->SectionHeaders[sec.sh_link];
  513. // Look for the requested entry.
  514. for (auto di = this->DynamicSectionEntries.begin();
  515. di != this->DynamicSectionEntries.end(); ++di) {
  516. ELF_Dyn& dyn = *di;
  517. if (static_cast<tagtype>(dyn.d_tag) == static_cast<tagtype>(tag)) {
  518. // We found the tag requested.
  519. // Make sure the position given is within the string section.
  520. if (dyn.d_un.d_val >= strtab.sh_size) {
  521. this->SetErrorMessage("Section DYNAMIC references string beyond "
  522. "the end of its string section.");
  523. return nullptr;
  524. }
  525. // Seek to the position reported by the entry.
  526. unsigned long first = static_cast<unsigned long>(dyn.d_un.d_val);
  527. unsigned long last = first;
  528. unsigned long end = static_cast<unsigned long>(strtab.sh_size);
  529. this->Stream->seekg(strtab.sh_offset + first);
  530. // Read the string. It may be followed by more than one NULL
  531. // terminator. Count the total size of the region allocated to
  532. // the string. This assumes that the next string in the table
  533. // is non-empty, but the "chrpath" tool makes the same
  534. // assumption.
  535. bool terminated = false;
  536. char c;
  537. while (last != end && this->Stream->get(c) && !(terminated && c)) {
  538. ++last;
  539. if (c) {
  540. se.Value += c;
  541. } else {
  542. terminated = true;
  543. }
  544. }
  545. // Make sure the whole value was read.
  546. if (!(*this->Stream)) {
  547. if (tag == cmELF::TagRPath) {
  548. this->SetErrorMessage(
  549. "Dynamic section specifies unreadable DT_RPATH");
  550. } else if (tag == cmELF::TagRunPath) {
  551. this->SetErrorMessage(
  552. "Dynamic section specifies unreadable DT_RUNPATH");
  553. } else if (tag == cmELF::TagMipsRldMapRel) {
  554. this->SetErrorMessage(
  555. "Dynamic section specifies unreadable DT_MIPS_RLD_MAP_REL");
  556. } else {
  557. this->SetErrorMessage("Dynamic section specifies unreadable value"
  558. " for unexpected attribute");
  559. }
  560. se.Value = "";
  561. return nullptr;
  562. }
  563. // The value has been read successfully. Report it.
  564. se.Position = static_cast<unsigned long>(strtab.sh_offset + first);
  565. se.Size = last - first;
  566. se.IndexInSection =
  567. static_cast<int>(di - this->DynamicSectionEntries.begin());
  568. return &se;
  569. }
  570. }
  571. return nullptr;
  572. }
  573. //============================================================================
  574. // External class implementation.
  575. const long cmELF::TagRPath = DT_RPATH;
  576. const long cmELF::TagRunPath = DT_RUNPATH;
  577. const long cmELF::TagMipsRldMapRel = DT_MIPS_RLD_MAP_REL;
  578. cmELF::cmELF(const char* fname)
  579. {
  580. // Try to open the file.
  581. auto fin = cm::make_unique<cmsys::ifstream>(fname, std::ios::binary);
  582. // Quit now if the file could not be opened.
  583. if (!fin || !*fin) {
  584. this->ErrorMessage = "Error opening input file.";
  585. return;
  586. }
  587. // Read the ELF identification block.
  588. char ident[EI_NIDENT];
  589. if (!fin->read(ident, EI_NIDENT)) {
  590. this->ErrorMessage = "Error reading ELF identification.";
  591. return;
  592. }
  593. if (!fin->seekg(0)) {
  594. this->ErrorMessage = "Error seeking to beginning of file.";
  595. return;
  596. }
  597. // Verify the ELF identification.
  598. if (!(ident[EI_MAG0] == ELFMAG0 && ident[EI_MAG1] == ELFMAG1 &&
  599. ident[EI_MAG2] == ELFMAG2 && ident[EI_MAG3] == ELFMAG3)) {
  600. this->ErrorMessage = "File does not have a valid ELF identification.";
  601. return;
  602. }
  603. // Check the byte order in which the rest of the file is encoded.
  604. cmELFInternal::ByteOrderType order;
  605. if (ident[EI_DATA] == ELFDATA2LSB) {
  606. // File is LSB.
  607. order = cmELFInternal::ByteOrderLSB;
  608. } else if (ident[EI_DATA] == ELFDATA2MSB) {
  609. // File is MSB.
  610. order = cmELFInternal::ByteOrderMSB;
  611. } else {
  612. this->ErrorMessage = "ELF file is not LSB or MSB encoded.";
  613. return;
  614. }
  615. // Check the class of the file and construct the corresponding
  616. // parser implementation.
  617. if (ident[EI_CLASS] == ELFCLASS32) {
  618. // 32-bit ELF
  619. this->Internal = cm::make_unique<cmELFInternalImpl<cmELFTypes32>>(
  620. this, std::move(fin), order);
  621. } else if (ident[EI_CLASS] == ELFCLASS64) {
  622. // 64-bit ELF
  623. this->Internal = cm::make_unique<cmELFInternalImpl<cmELFTypes64>>(
  624. this, std::move(fin), order);
  625. } else {
  626. this->ErrorMessage = "ELF file class is not 32-bit or 64-bit.";
  627. return;
  628. }
  629. }
  630. cmELF::~cmELF() = default;
  631. bool cmELF::Valid() const
  632. {
  633. return this->Internal && this->Internal->GetFileType() != FileTypeInvalid;
  634. }
  635. cmELF::FileType cmELF::GetFileType() const
  636. {
  637. if (this->Valid()) {
  638. return this->Internal->GetFileType();
  639. }
  640. return FileTypeInvalid;
  641. }
  642. std::uint16_t cmELF::GetMachine() const
  643. {
  644. if (this->Valid()) {
  645. return this->Internal->GetMachine();
  646. }
  647. return 0;
  648. }
  649. unsigned int cmELF::GetNumberOfSections() const
  650. {
  651. if (this->Valid()) {
  652. return this->Internal->GetNumberOfSections();
  653. }
  654. return 0;
  655. }
  656. unsigned long cmELF::GetDynamicEntryPosition(int index) const
  657. {
  658. if (this->Valid()) {
  659. return this->Internal->GetDynamicEntryPosition(index);
  660. }
  661. return 0;
  662. }
  663. cmELF::DynamicEntryList cmELF::GetDynamicEntries() const
  664. {
  665. if (this->Valid()) {
  666. return this->Internal->GetDynamicEntries();
  667. }
  668. return cmELF::DynamicEntryList();
  669. }
  670. std::vector<char> cmELF::EncodeDynamicEntries(
  671. const cmELF::DynamicEntryList& dentries) const
  672. {
  673. if (this->Valid()) {
  674. return this->Internal->EncodeDynamicEntries(dentries);
  675. }
  676. return std::vector<char>();
  677. }
  678. bool cmELF::HasDynamicSection() const
  679. {
  680. return this->Valid() && this->Internal->HasDynamicSection();
  681. }
  682. bool cmELF::GetSOName(std::string& soname)
  683. {
  684. if (StringEntry const* se = this->GetSOName()) {
  685. soname = se->Value;
  686. return true;
  687. }
  688. return false;
  689. }
  690. cmELF::StringEntry const* cmELF::GetSOName()
  691. {
  692. if (this->Valid() &&
  693. this->Internal->GetFileType() == cmELF::FileTypeSharedLibrary) {
  694. return this->Internal->GetSOName();
  695. }
  696. return nullptr;
  697. }
  698. cmELF::StringEntry const* cmELF::GetRPath()
  699. {
  700. if (this->Valid() &&
  701. (this->Internal->GetFileType() == cmELF::FileTypeExecutable ||
  702. this->Internal->GetFileType() == cmELF::FileTypeSharedLibrary)) {
  703. return this->Internal->GetRPath();
  704. }
  705. return nullptr;
  706. }
  707. cmELF::StringEntry const* cmELF::GetRunPath()
  708. {
  709. if (this->Valid() &&
  710. (this->Internal->GetFileType() == cmELF::FileTypeExecutable ||
  711. this->Internal->GetFileType() == cmELF::FileTypeSharedLibrary)) {
  712. return this->Internal->GetRunPath();
  713. }
  714. return nullptr;
  715. }
  716. bool cmELF::IsMIPS() const
  717. {
  718. if (this->Valid()) {
  719. return this->Internal->IsMips();
  720. }
  721. return false;
  722. }
  723. void cmELF::PrintInfo(std::ostream& os) const
  724. {
  725. if (this->Valid()) {
  726. this->Internal->PrintInfo(os);
  727. } else {
  728. os << "Not a valid ELF file.\n";
  729. }
  730. }