cmELF.cxx 23 KB

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