cmELF.cxx 24 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916
  1. /*============================================================================
  2. CMake - Cross Platform Makefile Generator
  3. Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
  4. Distributed under the OSI-approved BSD License (the "License");
  5. see accompanying file Copyright.txt for details.
  6. This software is distributed WITHOUT ANY WARRANTY; without even the
  7. implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  8. See the License for more information.
  9. ============================================================================*/
  10. #include "cmStandardIncludes.h" // to get CMAKE_USE_ELF_PARSER first
  11. #include "cmELF.h"
  12. #include <cm_auto_ptr.hxx>
  13. #include <cmsys/FStream.hxx>
  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. // Low-level byte swapping implementation.
  45. template <size_t s>
  46. struct cmELFByteSwapSize
  47. {
  48. };
  49. void cmELFByteSwap(char*, cmELFByteSwapSize<1> const&)
  50. {
  51. }
  52. void cmELFByteSwap(char* data, cmELFByteSwapSize<2> const&)
  53. {
  54. char one_byte;
  55. one_byte = data[0];
  56. data[0] = data[1];
  57. data[1] = one_byte;
  58. }
  59. void cmELFByteSwap(char* data, cmELFByteSwapSize<4> const&)
  60. {
  61. char one_byte;
  62. one_byte = data[0];
  63. data[0] = data[3];
  64. data[3] = one_byte;
  65. one_byte = data[1];
  66. data[1] = data[2];
  67. data[2] = one_byte;
  68. }
  69. void cmELFByteSwap(char* data, cmELFByteSwapSize<8> const&)
  70. {
  71. char one_byte;
  72. one_byte = data[0];
  73. data[0] = data[7];
  74. data[7] = one_byte;
  75. one_byte = data[1];
  76. data[1] = data[6];
  77. data[6] = one_byte;
  78. one_byte = data[2];
  79. data[2] = data[5];
  80. data[5] = one_byte;
  81. one_byte = data[3];
  82. data[3] = data[4];
  83. data[4] = one_byte;
  84. }
  85. // Low-level byte swapping interface.
  86. template <typename T>
  87. void cmELFByteSwap(T& x)
  88. {
  89. cmELFByteSwap(reinterpret_cast<char*>(&x), cmELFByteSwapSize<sizeof(T)>());
  90. }
  91. class cmELFInternal
  92. {
  93. public:
  94. typedef cmELF::StringEntry StringEntry;
  95. enum ByteOrderType
  96. {
  97. ByteOrderMSB,
  98. ByteOrderLSB
  99. };
  100. // Construct and take ownership of the file stream object.
  101. cmELFInternal(cmELF* external, CM_AUTO_PTR<cmsys::ifstream>& fin,
  102. ByteOrderType order)
  103. : External(external)
  104. , Stream(*fin.release())
  105. , ByteOrder(order)
  106. , ELFType(cmELF::FileTypeInvalid)
  107. {
  108. // In most cases the processor-specific byte order will match that
  109. // of the target execution environment. If we choose wrong here
  110. // it is fixed when the header is read.
  111. #if KWIML_ABI_ENDIAN_ID == KWIML_ABI_ENDIAN_ID_LITTLE
  112. this->NeedSwap = (this->ByteOrder == ByteOrderMSB);
  113. #elif KWIML_ABI_ENDIAN_ID == KWIML_ABI_ENDIAN_ID_BIG
  114. this->NeedSwap = (this->ByteOrder == ByteOrderLSB);
  115. #else
  116. this->NeedSwap = false; // Final decision is at runtime anyway.
  117. #endif
  118. // We have not yet loaded the section info.
  119. this->DynamicSectionIndex = -1;
  120. }
  121. // Destruct and delete the file stream object.
  122. virtual ~cmELFInternal() { delete &this->Stream; }
  123. // Forward to the per-class implementation.
  124. virtual unsigned int GetNumberOfSections() const = 0;
  125. virtual unsigned int GetDynamicEntryCount() = 0;
  126. virtual unsigned long GetDynamicEntryPosition(int j) = 0;
  127. virtual StringEntry const* GetDynamicSectionString(unsigned int tag) = 0;
  128. virtual void PrintInfo(std::ostream& os) const = 0;
  129. bool ReadBytes(unsigned long pos, unsigned long size, char* buf)
  130. {
  131. this->Stream.seekg(pos);
  132. this->Stream.read(buf, size);
  133. return !this->Stream.fail();
  134. }
  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. #if defined(DT_RUNPATH)
  149. return this->GetDynamicSectionString(DT_RUNPATH);
  150. #else
  151. return 0;
  152. #endif
  153. }
  154. // Return the recorded ELF type.
  155. cmELF::FileType GetFileType() const { return this->ELFType; }
  156. protected:
  157. // Data common to all ELF class implementations.
  158. // The external cmELF object.
  159. cmELF* External;
  160. // The stream from which to read.
  161. std::istream& Stream;
  162. // The byte order of the ELF file.
  163. ByteOrderType ByteOrder;
  164. // The ELF file type.
  165. cmELF::FileType ELFType;
  166. // Whether we need to byte-swap structures read from the stream.
  167. bool NeedSwap;
  168. // The section header index of the DYNAMIC section (-1 if none).
  169. int DynamicSectionIndex;
  170. // Helper methods for subclasses.
  171. void SetErrorMessage(const char* msg)
  172. {
  173. this->External->ErrorMessage = msg;
  174. this->ELFType = cmELF::FileTypeInvalid;
  175. }
  176. // Store string table entry states.
  177. std::map<unsigned int, StringEntry> DynamicSectionStrings;
  178. };
  179. // Configure the implementation template for 32-bit ELF files.
  180. struct cmELFTypes32
  181. {
  182. typedef Elf32_Ehdr ELF_Ehdr;
  183. typedef Elf32_Shdr ELF_Shdr;
  184. typedef Elf32_Dyn ELF_Dyn;
  185. typedef Elf32_Half ELF_Half;
  186. typedef KWIML_INT_uint32_t tagtype;
  187. static const char* GetName() { return "32-bit"; }
  188. };
  189. // Configure the implementation template for 64-bit ELF files.
  190. struct cmELFTypes64
  191. {
  192. typedef Elf64_Ehdr ELF_Ehdr;
  193. typedef Elf64_Shdr ELF_Shdr;
  194. typedef Elf64_Dyn ELF_Dyn;
  195. typedef Elf64_Half ELF_Half;
  196. typedef KWIML_INT_uint64_t tagtype;
  197. static const char* GetName() { return "64-bit"; }
  198. };
  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, CM_AUTO_PTR<cmsys::ifstream>& fin,
  212. ByteOrderType order);
  213. // Return the number of sections as specified by the ELF header.
  214. unsigned int GetNumberOfSections() const CM_OVERRIDE
  215. {
  216. return static_cast<unsigned int>(this->ELFHeader.e_shnum);
  217. }
  218. // Get the file position and size of a dynamic section entry.
  219. unsigned int GetDynamicEntryCount() CM_OVERRIDE;
  220. unsigned long GetDynamicEntryPosition(int j) CM_OVERRIDE;
  221. // Lookup a string from the dynamic section with the given tag.
  222. StringEntry const* GetDynamicSectionString(unsigned int tag) CM_OVERRIDE;
  223. // Print information about the ELF file.
  224. void PrintInfo(std::ostream& os) const CM_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. void ByteSwap(ELF_Ehdr& elf_header)
  259. {
  260. cmELFByteSwap(elf_header.e_type);
  261. cmELFByteSwap(elf_header.e_machine);
  262. cmELFByteSwap(elf_header.e_version);
  263. cmELFByteSwap(elf_header.e_entry);
  264. cmELFByteSwap(elf_header.e_phoff);
  265. cmELFByteSwap(elf_header.e_shoff);
  266. cmELFByteSwap(elf_header.e_flags);
  267. cmELFByteSwap(elf_header.e_ehsize);
  268. cmELFByteSwap(elf_header.e_phentsize);
  269. cmELFByteSwap(elf_header.e_phnum);
  270. cmELFByteSwap(elf_header.e_shentsize);
  271. cmELFByteSwap(elf_header.e_shnum);
  272. cmELFByteSwap(elf_header.e_shstrndx);
  273. }
  274. void ByteSwap(ELF_Shdr& sec_header)
  275. {
  276. cmELFByteSwap(sec_header.sh_name);
  277. cmELFByteSwap(sec_header.sh_type);
  278. cmELFByteSwap(sec_header.sh_flags);
  279. cmELFByteSwap(sec_header.sh_addr);
  280. cmELFByteSwap(sec_header.sh_offset);
  281. cmELFByteSwap(sec_header.sh_size);
  282. cmELFByteSwap(sec_header.sh_link);
  283. cmELFByteSwap(sec_header.sh_info);
  284. cmELFByteSwap(sec_header.sh_addralign);
  285. cmELFByteSwap(sec_header.sh_entsize);
  286. }
  287. void ByteSwap(ELF_Dyn& dyn)
  288. {
  289. cmELFByteSwap(dyn.d_tag);
  290. switch (dyn.d_tag) {
  291. case DT_NULL: /* dyn.d_un ignored */
  292. break;
  293. case DT_NEEDED:
  294. cmELFByteSwap(dyn.d_un.d_val);
  295. break;
  296. case DT_PLTRELSZ:
  297. cmELFByteSwap(dyn.d_un.d_val);
  298. break;
  299. case DT_PLTGOT:
  300. cmELFByteSwap(dyn.d_un.d_ptr);
  301. break;
  302. case DT_HASH:
  303. cmELFByteSwap(dyn.d_un.d_ptr);
  304. break;
  305. case DT_STRTAB:
  306. cmELFByteSwap(dyn.d_un.d_ptr);
  307. break;
  308. case DT_SYMTAB:
  309. cmELFByteSwap(dyn.d_un.d_ptr);
  310. break;
  311. case DT_RELA:
  312. cmELFByteSwap(dyn.d_un.d_ptr);
  313. break;
  314. case DT_RELASZ:
  315. cmELFByteSwap(dyn.d_un.d_val);
  316. break;
  317. case DT_RELAENT:
  318. cmELFByteSwap(dyn.d_un.d_val);
  319. break;
  320. case DT_STRSZ:
  321. cmELFByteSwap(dyn.d_un.d_val);
  322. break;
  323. case DT_SYMENT:
  324. cmELFByteSwap(dyn.d_un.d_val);
  325. break;
  326. case DT_INIT:
  327. cmELFByteSwap(dyn.d_un.d_ptr);
  328. break;
  329. case DT_FINI:
  330. cmELFByteSwap(dyn.d_un.d_ptr);
  331. break;
  332. case DT_SONAME:
  333. cmELFByteSwap(dyn.d_un.d_val);
  334. break;
  335. case DT_RPATH:
  336. cmELFByteSwap(dyn.d_un.d_val);
  337. break;
  338. case DT_SYMBOLIC: /* dyn.d_un ignored */
  339. break;
  340. case DT_REL:
  341. cmELFByteSwap(dyn.d_un.d_ptr);
  342. break;
  343. case DT_RELSZ:
  344. cmELFByteSwap(dyn.d_un.d_val);
  345. break;
  346. case DT_RELENT:
  347. cmELFByteSwap(dyn.d_un.d_val);
  348. break;
  349. case DT_PLTREL:
  350. cmELFByteSwap(dyn.d_un.d_val);
  351. break;
  352. case DT_DEBUG:
  353. cmELFByteSwap(dyn.d_un.d_ptr);
  354. break;
  355. case DT_TEXTREL: /* dyn.d_un ignored */
  356. break;
  357. case DT_JMPREL:
  358. cmELFByteSwap(dyn.d_un.d_ptr);
  359. break;
  360. #ifdef T_BIND_NOW
  361. case T_BIND_NOW: /* dyn.d_un ignored */
  362. break;
  363. #endif
  364. #ifdef DT_INIT_ARRAY
  365. case DT_INIT_ARRAY:
  366. cmELFByteSwap(dyn.d_un.d_ptr);
  367. break;
  368. #endif
  369. #ifdef DT_FINI_ARRAY
  370. case DT_FINI_ARRAY:
  371. cmELFByteSwap(dyn.d_un.d_ptr);
  372. break;
  373. #endif
  374. #ifdef DT_INIT_ARRAYSZ
  375. case DT_INIT_ARRAYSZ:
  376. cmELFByteSwap(dyn.d_un.d_val);
  377. break;
  378. #endif
  379. #ifdef DT_FINI_ARRAYSZ
  380. case DT_FINI_ARRAYSZ:
  381. cmELFByteSwap(dyn.d_un.d_val);
  382. break;
  383. #endif
  384. #ifdef DT_RUNPATH
  385. case DT_RUNPATH:
  386. cmELFByteSwap(dyn.d_un.d_val);
  387. break;
  388. #endif
  389. #ifdef DT_FLAGS
  390. case DT_FLAGS:
  391. cmELFByteSwap(dyn.d_un.d_val);
  392. break;
  393. #endif
  394. #ifdef DT_PREINIT_ARRAY
  395. case DT_PREINIT_ARRAY:
  396. cmELFByteSwap(dyn.d_un.d_ptr);
  397. break;
  398. #endif
  399. #ifdef DT_PREINIT_ARRAYSZ
  400. case DT_PREINIT_ARRAYSZ:
  401. cmELFByteSwap(dyn.d_un.d_val);
  402. break;
  403. #endif
  404. }
  405. }
  406. bool FileTypeValid(ELF_Half et)
  407. {
  408. unsigned int eti = static_cast<unsigned int>(et);
  409. if (eti == ET_NONE || eti == ET_REL || eti == ET_EXEC || eti == ET_DYN ||
  410. eti == ET_CORE) {
  411. return true;
  412. }
  413. #if defined(ET_LOOS) && defined(ET_HIOS)
  414. if (eti >= ET_LOOS && eti <= ET_HIOS) {
  415. return true;
  416. }
  417. #endif
  418. #if defined(ET_LOPROC) && defined(ET_HIPROC)
  419. if (eti >= ET_LOPROC && eti <= ET_HIPROC) {
  420. return true;
  421. }
  422. #endif
  423. return false;
  424. }
  425. bool Read(ELF_Ehdr& x)
  426. {
  427. // Read the header from the file.
  428. if (!this->Stream.read(reinterpret_cast<char*>(&x), sizeof(x))) {
  429. return false;
  430. }
  431. // The byte order of ELF header fields may not match that of the
  432. // processor-specific data. The header fields are ordered to
  433. // match the target execution environment, so we may need to
  434. // memorize the order of all platforms based on the e_machine
  435. // value. As a heuristic, if the type is invalid but its
  436. // swapped value is okay then flip our swap mode.
  437. ELF_Half et = x.e_type;
  438. if (this->NeedSwap) {
  439. cmELFByteSwap(et);
  440. }
  441. if (!this->FileTypeValid(et)) {
  442. cmELFByteSwap(et);
  443. if (this->FileTypeValid(et)) {
  444. // The previous byte order guess was wrong. Flip it.
  445. this->NeedSwap = !this->NeedSwap;
  446. }
  447. }
  448. // Fix the byte order of the header.
  449. if (this->NeedSwap) {
  450. ByteSwap(x);
  451. }
  452. return true;
  453. }
  454. bool Read(ELF_Shdr& x)
  455. {
  456. if (this->Stream.read(reinterpret_cast<char*>(&x), sizeof(x)) &&
  457. this->NeedSwap) {
  458. ByteSwap(x);
  459. }
  460. return !this->Stream.fail();
  461. }
  462. bool Read(ELF_Dyn& x)
  463. {
  464. if (this->Stream.read(reinterpret_cast<char*>(&x), sizeof(x)) &&
  465. this->NeedSwap) {
  466. ByteSwap(x);
  467. }
  468. return !this->Stream.fail();
  469. }
  470. bool LoadSectionHeader(ELF_Half i)
  471. {
  472. // Read the section header from the file.
  473. this->Stream.seekg(this->ELFHeader.e_shoff +
  474. this->ELFHeader.e_shentsize * i);
  475. if (!this->Read(this->SectionHeaders[i])) {
  476. return false;
  477. }
  478. // Identify some important sections.
  479. if (this->SectionHeaders[i].sh_type == SHT_DYNAMIC) {
  480. this->DynamicSectionIndex = i;
  481. }
  482. return true;
  483. }
  484. bool LoadDynamicSection();
  485. // Store the main ELF header.
  486. ELF_Ehdr ELFHeader;
  487. // Store all the section headers.
  488. std::vector<ELF_Shdr> SectionHeaders;
  489. // Store all entries of the DYNAMIC section.
  490. std::vector<ELF_Dyn> DynamicSectionEntries;
  491. };
  492. template <class Types>
  493. cmELFInternalImpl<Types>::cmELFInternalImpl(cmELF* external,
  494. CM_AUTO_PTR<cmsys::ifstream>& fin,
  495. ByteOrderType order)
  496. : cmELFInternal(external, fin, order)
  497. {
  498. // Read the main header.
  499. if (!this->Read(this->ELFHeader)) {
  500. this->SetErrorMessage("Failed to read main ELF header.");
  501. return;
  502. }
  503. // Determine the ELF file type.
  504. switch (this->ELFHeader.e_type) {
  505. case ET_NONE:
  506. this->SetErrorMessage("ELF file type is NONE.");
  507. return;
  508. case ET_REL:
  509. this->ELFType = cmELF::FileTypeRelocatableObject;
  510. break;
  511. case ET_EXEC:
  512. this->ELFType = cmELF::FileTypeExecutable;
  513. break;
  514. case ET_DYN:
  515. this->ELFType = cmELF::FileTypeSharedLibrary;
  516. break;
  517. case ET_CORE:
  518. this->ELFType = cmELF::FileTypeCore;
  519. break;
  520. default: {
  521. unsigned int eti = static_cast<unsigned int>(this->ELFHeader.e_type);
  522. #if defined(ET_LOOS) && defined(ET_HIOS)
  523. if (eti >= ET_LOOS && eti <= ET_HIOS) {
  524. this->ELFType = cmELF::FileTypeSpecificOS;
  525. break;
  526. }
  527. #endif
  528. #if defined(ET_LOPROC) && defined(ET_HIPROC)
  529. if (eti >= ET_LOPROC && eti <= ET_HIPROC) {
  530. this->ELFType = cmELF::FileTypeSpecificProc;
  531. break;
  532. }
  533. #endif
  534. std::ostringstream e;
  535. e << "Unknown ELF file type " << eti;
  536. this->SetErrorMessage(e.str().c_str());
  537. return;
  538. }
  539. }
  540. // Load the section headers.
  541. this->SectionHeaders.resize(this->ELFHeader.e_shnum);
  542. for (ELF_Half i = 0; i < this->ELFHeader.e_shnum; ++i) {
  543. if (!this->LoadSectionHeader(i)) {
  544. this->SetErrorMessage("Failed to load section headers.");
  545. return;
  546. }
  547. }
  548. }
  549. template <class Types>
  550. bool cmELFInternalImpl<Types>::LoadDynamicSection()
  551. {
  552. // If there is no dynamic section we are done.
  553. if (this->DynamicSectionIndex < 0) {
  554. return false;
  555. }
  556. // If the section was already loaded we are done.
  557. if (!this->DynamicSectionEntries.empty()) {
  558. return true;
  559. }
  560. // If there are no entries we are done.
  561. ELF_Shdr const& sec = this->SectionHeaders[this->DynamicSectionIndex];
  562. if (sec.sh_entsize == 0) {
  563. return false;
  564. }
  565. // Allocate the dynamic section entries.
  566. int n = static_cast<int>(sec.sh_size / sec.sh_entsize);
  567. this->DynamicSectionEntries.resize(n);
  568. // Read each entry.
  569. for (int j = 0; j < n; ++j) {
  570. // Seek to the beginning of the section entry.
  571. this->Stream.seekg(sec.sh_offset + sec.sh_entsize * j);
  572. ELF_Dyn& dyn = this->DynamicSectionEntries[j];
  573. // Try reading the entry.
  574. if (!this->Read(dyn)) {
  575. this->SetErrorMessage("Error reading entry from DYNAMIC section.");
  576. this->DynamicSectionIndex = -1;
  577. return false;
  578. }
  579. }
  580. return true;
  581. }
  582. template <class Types>
  583. unsigned int cmELFInternalImpl<Types>::GetDynamicEntryCount()
  584. {
  585. if (!this->LoadDynamicSection()) {
  586. return 0;
  587. }
  588. for (unsigned int i = 0; i < this->DynamicSectionEntries.size(); ++i) {
  589. if (this->DynamicSectionEntries[i].d_tag == DT_NULL) {
  590. return i;
  591. }
  592. }
  593. return static_cast<unsigned int>(this->DynamicSectionEntries.size());
  594. }
  595. template <class Types>
  596. unsigned long cmELFInternalImpl<Types>::GetDynamicEntryPosition(int j)
  597. {
  598. if (!this->LoadDynamicSection()) {
  599. return 0;
  600. }
  601. if (j < 0 || j >= static_cast<int>(this->DynamicSectionEntries.size())) {
  602. return 0;
  603. }
  604. ELF_Shdr const& sec = this->SectionHeaders[this->DynamicSectionIndex];
  605. return static_cast<unsigned long>(sec.sh_offset + sec.sh_entsize * j);
  606. }
  607. template <class Types>
  608. cmELF::StringEntry const* cmELFInternalImpl<Types>::GetDynamicSectionString(
  609. unsigned int tag)
  610. {
  611. // Short-circuit if already checked.
  612. std::map<unsigned int, StringEntry>::iterator dssi =
  613. this->DynamicSectionStrings.find(tag);
  614. if (dssi != this->DynamicSectionStrings.end()) {
  615. if (dssi->second.Position > 0) {
  616. return &dssi->second;
  617. }
  618. return CM_NULLPTR;
  619. }
  620. // Create an entry for this tag. Assume it is missing until found.
  621. StringEntry& se = this->DynamicSectionStrings[tag];
  622. se.Position = 0;
  623. se.Size = 0;
  624. se.IndexInSection = -1;
  625. // Try reading the dynamic section.
  626. if (!this->LoadDynamicSection()) {
  627. return CM_NULLPTR;
  628. }
  629. // Get the string table referenced by the DYNAMIC section.
  630. ELF_Shdr const& sec = this->SectionHeaders[this->DynamicSectionIndex];
  631. if (sec.sh_link >= this->SectionHeaders.size()) {
  632. this->SetErrorMessage("Section DYNAMIC has invalid string table index.");
  633. return CM_NULLPTR;
  634. }
  635. ELF_Shdr const& strtab = this->SectionHeaders[sec.sh_link];
  636. // Look for the requested entry.
  637. for (typename std::vector<ELF_Dyn>::iterator di =
  638. this->DynamicSectionEntries.begin();
  639. di != this->DynamicSectionEntries.end(); ++di) {
  640. ELF_Dyn& dyn = *di;
  641. if (static_cast<tagtype>(dyn.d_tag) == static_cast<tagtype>(tag)) {
  642. // We found the tag requested.
  643. // Make sure the position given is within the string section.
  644. if (dyn.d_un.d_val >= strtab.sh_size) {
  645. this->SetErrorMessage("Section DYNAMIC references string beyond "
  646. "the end of its string section.");
  647. return CM_NULLPTR;
  648. }
  649. // Seek to the position reported by the entry.
  650. unsigned long first = static_cast<unsigned long>(dyn.d_un.d_val);
  651. unsigned long last = first;
  652. unsigned long end = static_cast<unsigned long>(strtab.sh_size);
  653. this->Stream.seekg(strtab.sh_offset + first);
  654. // Read the string. It may be followed by more than one NULL
  655. // terminator. Count the total size of the region allocated to
  656. // the string. This assumes that the next string in the table
  657. // is non-empty, but the "chrpath" tool makes the same
  658. // assumption.
  659. bool terminated = false;
  660. char c;
  661. while (last != end && this->Stream.get(c) && !(terminated && c)) {
  662. ++last;
  663. if (c) {
  664. se.Value += c;
  665. } else {
  666. terminated = true;
  667. }
  668. }
  669. // Make sure the whole value was read.
  670. if (!this->Stream) {
  671. this->SetErrorMessage("Dynamic section specifies unreadable RPATH.");
  672. se.Value = "";
  673. return CM_NULLPTR;
  674. }
  675. // The value has been read successfully. Report it.
  676. se.Position = static_cast<unsigned long>(strtab.sh_offset + first);
  677. se.Size = last - first;
  678. se.IndexInSection =
  679. static_cast<int>(di - this->DynamicSectionEntries.begin());
  680. return &se;
  681. }
  682. }
  683. return CM_NULLPTR;
  684. }
  685. //============================================================================
  686. // External class implementation.
  687. cmELF::cmELF(const char* fname)
  688. : Internal(CM_NULLPTR)
  689. {
  690. // Try to open the file.
  691. CM_AUTO_PTR<cmsys::ifstream> fin(new cmsys::ifstream(fname));
  692. // Quit now if the file could not be opened.
  693. if (!fin.get() || !*fin) {
  694. this->ErrorMessage = "Error opening input file.";
  695. return;
  696. }
  697. // Read the ELF identification block.
  698. char ident[EI_NIDENT];
  699. if (!fin->read(ident, EI_NIDENT)) {
  700. this->ErrorMessage = "Error reading ELF identification.";
  701. return;
  702. }
  703. if (!fin->seekg(0)) {
  704. this->ErrorMessage = "Error seeking to beginning of file.";
  705. return;
  706. }
  707. // Verify the ELF identification.
  708. if (!(ident[EI_MAG0] == ELFMAG0 && ident[EI_MAG1] == ELFMAG1 &&
  709. ident[EI_MAG2] == ELFMAG2 && ident[EI_MAG3] == ELFMAG3)) {
  710. this->ErrorMessage = "File does not have a valid ELF identification.";
  711. return;
  712. }
  713. // Check the byte order in which the rest of the file is encoded.
  714. cmELFInternal::ByteOrderType order;
  715. if (ident[EI_DATA] == ELFDATA2LSB) {
  716. // File is LSB.
  717. order = cmELFInternal::ByteOrderLSB;
  718. } else if (ident[EI_DATA] == ELFDATA2MSB) {
  719. // File is MSB.
  720. order = cmELFInternal::ByteOrderMSB;
  721. } else {
  722. this->ErrorMessage = "ELF file is not LSB or MSB encoded.";
  723. return;
  724. }
  725. // Check the class of the file and construct the corresponding
  726. // parser implementation.
  727. if (ident[EI_CLASS] == ELFCLASS32) {
  728. // 32-bit ELF
  729. this->Internal = new cmELFInternalImpl<cmELFTypes32>(this, fin, order);
  730. } else if (ident[EI_CLASS] == ELFCLASS64) {
  731. // 64-bit ELF
  732. this->Internal = new cmELFInternalImpl<cmELFTypes64>(this, fin, order);
  733. } else {
  734. this->ErrorMessage = "ELF file class is not 32-bit or 64-bit.";
  735. return;
  736. }
  737. }
  738. cmELF::~cmELF()
  739. {
  740. delete this->Internal;
  741. }
  742. bool cmELF::Valid() const
  743. {
  744. return this->Internal && this->Internal->GetFileType() != FileTypeInvalid;
  745. }
  746. cmELF::FileType cmELF::GetFileType() const
  747. {
  748. if (this->Valid()) {
  749. return this->Internal->GetFileType();
  750. } else {
  751. return FileTypeInvalid;
  752. }
  753. }
  754. unsigned int cmELF::GetNumberOfSections() const
  755. {
  756. if (this->Valid()) {
  757. return this->Internal->GetNumberOfSections();
  758. } else {
  759. return 0;
  760. }
  761. }
  762. unsigned int cmELF::GetDynamicEntryCount() const
  763. {
  764. if (this->Valid()) {
  765. return this->Internal->GetDynamicEntryCount();
  766. } else {
  767. return 0;
  768. }
  769. }
  770. unsigned long cmELF::GetDynamicEntryPosition(int index) const
  771. {
  772. if (this->Valid()) {
  773. return this->Internal->GetDynamicEntryPosition(index);
  774. } else {
  775. return 0;
  776. }
  777. }
  778. bool cmELF::ReadBytes(unsigned long pos, unsigned long size, char* buf) const
  779. {
  780. if (this->Valid()) {
  781. return this->Internal->ReadBytes(pos, size, buf);
  782. } else {
  783. return false;
  784. }
  785. }
  786. bool cmELF::GetSOName(std::string& soname)
  787. {
  788. if (StringEntry const* se = this->GetSOName()) {
  789. soname = se->Value;
  790. return true;
  791. } else {
  792. return false;
  793. }
  794. }
  795. cmELF::StringEntry const* cmELF::GetSOName()
  796. {
  797. if (this->Valid() &&
  798. this->Internal->GetFileType() == cmELF::FileTypeSharedLibrary) {
  799. return this->Internal->GetSOName();
  800. } else {
  801. return CM_NULLPTR;
  802. }
  803. }
  804. cmELF::StringEntry const* cmELF::GetRPath()
  805. {
  806. if (this->Valid() &&
  807. (this->Internal->GetFileType() == cmELF::FileTypeExecutable ||
  808. this->Internal->GetFileType() == cmELF::FileTypeSharedLibrary)) {
  809. return this->Internal->GetRPath();
  810. } else {
  811. return CM_NULLPTR;
  812. }
  813. }
  814. cmELF::StringEntry const* cmELF::GetRunPath()
  815. {
  816. if (this->Valid() &&
  817. (this->Internal->GetFileType() == cmELF::FileTypeExecutable ||
  818. this->Internal->GetFileType() == cmELF::FileTypeSharedLibrary)) {
  819. return this->Internal->GetRunPath();
  820. } else {
  821. return CM_NULLPTR;
  822. }
  823. }
  824. void cmELF::PrintInfo(std::ostream& os) const
  825. {
  826. if (this->Valid()) {
  827. this->Internal->PrintInfo(os);
  828. } else {
  829. os << "Not a valid ELF file.\n";
  830. }
  831. }