cmELF.cxx 25 KB

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