cmELF.cxx 25 KB

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