cmELF.cxx 22 KB

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