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