cmELF.cxx 26 KB

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