cmELF.cxx 25 KB

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