1) Cmake support for PPC64LE builds
[dyninst.git] / elf / src / Elf_X.C
1 /*
2  * See the dyninst/COPYRIGHT file for copyright information.
3  * 
4  * We provide the Paradyn Tools (below described as "Paradyn")
5  * on an AS IS basis, and do not warrant its validity or performance.
6  * We reserve the right to update, modify, or discontinue this
7  * software at any time.  We shall have no obligation to supply such
8  * updates or modifications or any other form of support to you.
9  * 
10  * By your use of Paradyn, you understand and agree that we (or any
11  * other person or entity with proprietary rights in Paradyn) are
12  * under no obligation to provide either maintenance services,
13  * update services, notices of latent defects, or correction of
14  * defects for Paradyn.
15  * 
16  * This library is free software; you can redistribute it and/or
17  * modify it under the terms of the GNU Lesser General Public
18  * License as published by the Free Software Foundation; either
19  * version 2.1 of the License, or (at your option) any later version.
20  * 
21  * This library is distributed in the hope that it will be useful,
22  * but WITHOUT ANY WARRANTY; without even the implied warranty of
23  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
24  * Lesser General Public License for more details.
25  * 
26  * You should have received a copy of the GNU Lesser General Public
27  * License along with this library; if not, write to the Free Software
28  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
29  */
30
31 #include <sys/mman.h>
32 #include <sys/types.h>
33 #include <sys/stat.h>
34 #include <fcntl.h>
35 #include <unistd.h>
36 #include <libgen.h>
37
38 #include <boost/crc.hpp>
39 #include <boost/assign/list_of.hpp>
40 #include <boost/assign/std/set.hpp>
41 #include <boost/assign/std/vector.hpp>
42
43 #include "common/src/headers.h"
44 #include "Elf_X.h"
45 #include <iostream>
46 #include <iomanip>
47 #include <sstream>
48
49 using namespace std;
50 using boost::crc_32_type;
51 using namespace boost::assign;
52
53 using namespace Dyninst;
54
55 #define DEBUGLINK_NAME ".gnu_debuglink"
56 #define BUILD_ID_NAME ".note.gnu.build-id"
57
58 template class std::map<std::pair<std::string, int> , Elf_X*>;
59 template class std::map<std::pair<std::string, char*> , Elf_X*>;
60 template class std::vector<Elf_X_Shdr>;
61 template class std::vector<Elf_X_Phdr>;
62
63 map<pair<string, int>, Elf_X *> Elf_X::elf_x_by_fd;
64 map<pair<string, char *>, Elf_X *> Elf_X::elf_x_by_ptr;
65
66 #define APPEND(X) X ## 1
67 #define APPEND2(X) APPEND(X)
68 #define LIBELF_TEST APPEND2(_LIBELF_H)
69 #if (LIBELF_TEST == 11)
70 #define USES_ELFUTILS
71 #endif
72
73 Elf_X *Elf_X::newElf_X(int input, Elf_Cmd cmd, Elf_X *ref, string name)
74 {
75 #if defined(USES_ELFUTILS)
76    //If using libelf via elfutils from RedHat
77    if (cmd == ELF_C_READ) {
78       cmd = ELF_C_READ_MMAP;
79    }
80 #endif
81    if (name.empty()) {
82       return new Elf_X(input, cmd, ref);
83    }
84    auto i = elf_x_by_fd.find(make_pair(name, input));
85    if (i != elf_x_by_fd.end()) {
86      Elf_X *ret = i->second;
87      ret->ref_count++;
88      return ret;
89    }
90    Elf_X *ret = new Elf_X(input, cmd, ref);
91    ret->filename = name;
92    elf_x_by_fd.insert(make_pair(make_pair(name, input), ret));
93    return ret;
94 }
95
96 Elf_X *Elf_X::newElf_X(char *mem_image, size_t mem_size, string name)
97 {
98    if (name.empty()) {
99       return new Elf_X(mem_image, mem_size);
100    }
101    auto i = elf_x_by_ptr.find(make_pair(name, mem_image));
102    if (i != elf_x_by_ptr.end()) {
103      Elf_X *ret = i->second;
104      
105      ret->ref_count++;
106      return ret;
107    }
108    Elf_X *ret = new Elf_X(mem_image, mem_size);
109    ret->filename = name;
110    elf_x_by_ptr.insert(make_pair(make_pair(name, mem_image), ret));
111    return ret;
112 }
113
114 // ------------------------------------------------------------------------
115 // Class Elf_X simulates the Elf(32|64)_Ehdr structure.
116 // Also works for ELF archives. 
117 Elf_X::Elf_X()
118     : elf(NULL), ehdr32(NULL), ehdr64(NULL), phdr32(NULL), phdr64(NULL),
119       filedes(-1), is64(false), isArchive(false), ref_count(1),
120       cached_debug_buffer(NULL), cached_debug_size(0), cached_debug(false)
121 { }
122
123 Elf_X::Elf_X(int input, Elf_Cmd cmd, Elf_X *ref)
124     : elf(NULL), ehdr32(NULL), ehdr64(NULL), phdr32(NULL), phdr64(NULL),
125       filedes(input), is64(false), isArchive(false), ref_count(1),
126       cached_debug_buffer(NULL), cached_debug_size(0), cached_debug(false)
127 {
128     if (elf_version(EV_CURRENT) == EV_NONE) {
129        return;
130     }
131     elf_errno(); // Reset elf_errno to zero.
132     if (ref)
133        elf = elf_begin(input, cmd, ref->e_elfp());
134     else {
135        elf = elf_begin(input, cmd, NULL);
136     }
137     if (elf) {
138        if (elf_kind(elf) == ELF_K_ELF) {
139           char *identp = elf_getident(elf, NULL);
140           is64 = (identp && identp[EI_CLASS] == ELFCLASS64);
141           isBigEndian = (identp && identp[EI_DATA] == ELFDATA2MSB);
142        }
143        else if(elf_kind(elf) == ELF_K_AR) {
144           char *identp = elf_getident(elf, NULL);
145           is64 = (identp && identp[EI_CLASS] == ELFCLASS64);
146           isArchive = true;
147        }
148        
149        if (!is64)  ehdr32 = elf32_getehdr(elf);
150        else       ehdr64 = elf64_getehdr(elf);
151        
152        if (!is64) phdr32 = elf32_getphdr(elf);
153        else       phdr64 = elf64_getphdr(elf);
154     }
155
156     if (elf_kind(elf) == ELF_K_ELF) {
157        size_t phdrnum = e_phnum();
158        size_t shdrnum = e_shnum();
159        shdrs.resize(shdrnum);
160        phdrs.resize(phdrnum);
161     }
162 }
163
164 unsigned short Elf_X::e_endian() const {
165     return isBigEndian;
166 }
167
168
169 Elf_X::Elf_X(char *mem_image, size_t mem_size)
170     : elf(NULL), ehdr32(NULL), ehdr64(NULL), phdr32(NULL), phdr64(NULL),
171       filedes(-1), is64(false), isArchive(false), ref_count(1),
172       cached_debug_buffer(NULL), cached_debug_size(0), cached_debug(false)
173 {
174     if (elf_version(EV_CURRENT) == EV_NONE) {
175        return;
176     }
177
178     elf_errno(); // Reset elf_errno to zero.
179     elf = elf_memory(mem_image, mem_size);
180     
181     int err;
182     if ( (err = elf_errno()) != 0) {
183        //const char *msg = elf_errmsg(err);
184     }
185     
186     if (elf) {
187        if (elf_kind(elf) == ELF_K_ELF) {
188           char *identp = elf_getident(elf, NULL);
189           is64 = (identp && identp[EI_CLASS] == ELFCLASS64);
190        }
191        
192        if (!is64) ehdr32 = elf32_getehdr(elf);
193        else       ehdr64 = elf64_getehdr(elf);
194        
195        if (!is64) phdr32 = elf32_getphdr(elf);
196        else       phdr64 = elf64_getphdr(elf);
197     }
198
199     if (elf_kind(elf) == ELF_K_ELF) {
200        size_t phdrnum = e_phnum();
201        size_t shdrnum = e_shnum();
202        shdrs.resize(shdrnum);
203        phdrs.resize(phdrnum);
204     }
205 }
206
207 void Elf_X::end()
208 {
209    if (ref_count > 1) {
210       ref_count--;
211       return;
212    }
213    /*
214      Stop cleaning Elf_X.  Leads to constant remapping of file.
215    if (elf) {
216       elf_end(elf);
217       elf = NULL;
218       ehdr32 = NULL;
219       ehdr64 = NULL;
220       phdr32 = NULL;
221       phdr64 = NULL;
222    }
223    delete this;*/
224 }
225
226 Elf_X::~Elf_X()
227 {
228   // Unfortunately, we have to be slow here
229   for (auto iter = elf_x_by_fd.begin(); iter != elf_x_by_fd.end(); ++iter) {
230     if (iter->second == this) {
231       elf_x_by_fd.erase(iter);
232       return;
233     }
234   }
235
236   for (auto iter = elf_x_by_ptr.begin(); iter != elf_x_by_ptr.end(); ++iter) {
237     if (iter->second == this) {
238       elf_x_by_ptr.erase(iter);
239       return;
240     }
241   }
242 }
243
244 // Read Interface
245 Elf *Elf_X::e_elfp() const
246 {
247     return elf;
248 }
249
250 unsigned char *Elf_X::e_ident() const
251 {
252     return (!is64 ?
253             static_cast<unsigned char*>(ehdr32->e_ident) :
254             static_cast<unsigned char*>(ehdr64->e_ident));
255 }
256
257 unsigned short Elf_X::e_type() const
258 {
259     return (!is64 ?
260             static_cast<unsigned short>(ehdr32->e_type) :
261             static_cast<unsigned short>(ehdr64->e_type));
262 }
263
264 unsigned short Elf_X::e_machine() const
265 {
266     return (!is64 ?
267             static_cast<unsigned short>(ehdr32->e_machine) :
268             static_cast<unsigned short>(ehdr64->e_machine));
269 }
270
271 unsigned long Elf_X::e_version() const
272 {
273     return (!is64 ?
274             static_cast<unsigned long>(ehdr32->e_version) :
275             static_cast<unsigned long>(ehdr64->e_version));
276 }
277
278 unsigned long Elf_X::e_entry() const
279 {
280     return (!is64 ?
281             static_cast<unsigned long>(ehdr32->e_entry) :
282             static_cast<unsigned long>(ehdr64->e_entry));
283 }
284
285 unsigned long Elf_X::e_phoff() const
286 {
287     return (!is64 ?
288             static_cast<unsigned long>(ehdr32->e_phoff) :
289             static_cast<unsigned long>(ehdr64->e_phoff));
290 }
291
292 unsigned long Elf_X::e_shoff() const
293 {
294     return (!is64 ?
295             static_cast<unsigned long>(ehdr32->e_shoff) :
296             static_cast<unsigned long>(ehdr64->e_shoff));
297 }
298
299 unsigned long Elf_X::e_flags() const
300 {
301     return (!is64 ?
302             static_cast<unsigned long>(ehdr32->e_flags) :
303             static_cast<unsigned long>(ehdr64->e_flags));
304 }
305
306 unsigned short Elf_X::e_ehsize() const
307 {
308     return (!is64 ?
309             static_cast<unsigned short>(ehdr32->e_ehsize) :
310             static_cast<unsigned short>(ehdr64->e_ehsize));
311 }
312
313 unsigned short Elf_X::e_phentsize() const {
314     return (!is64 ?
315             static_cast<unsigned short>(ehdr32->e_phentsize) :
316             static_cast<unsigned short>(ehdr64->e_phentsize));
317 }
318
319 unsigned short Elf_X::e_phnum() const
320 {
321     return (!is64 ?
322             static_cast<unsigned short>(ehdr32->e_phnum) :
323             static_cast<unsigned short>(ehdr64->e_phnum));
324 }
325
326 unsigned short Elf_X::e_shentsize() const
327 {
328     return (!is64 ?
329             static_cast<unsigned short>(ehdr32->e_shentsize) :
330             static_cast<unsigned short>(ehdr64->e_shentsize));
331 }
332
333 unsigned short Elf_X::e_shnum() const
334 {
335     return (!is64 ?
336             static_cast<unsigned short>(ehdr32->e_shnum) :
337             static_cast<unsigned short>(ehdr64->e_shnum));
338 }
339
340 unsigned short Elf_X::e_shstrndx() const
341 {
342     return (!is64 ?
343             static_cast<unsigned short>(ehdr32->e_shstrndx) :
344             static_cast<unsigned short>(ehdr64->e_shstrndx));
345 }
346
347 const char *Elf_X::e_rawfile(size_t &nbytes) const
348 {
349     return elf_rawfile(elf, &nbytes);
350 }
351
352 Elf_X *Elf_X::e_next(Elf_X *ref)
353 {
354     if (!isArchive)
355         return NULL;
356     Elf_Cmd cmd = elf_next(ref->e_elfp());
357     return Elf_X::newElf_X(filedes, cmd, this);
358 }
359
360 Elf_X *Elf_X::e_rand(unsigned offset)
361 {
362     if (!isArchive)
363         return NULL;
364     elf_rand(elf, offset);
365     return Elf_X::newElf_X(filedes, ELF_C_READ, this);
366 }
367
368 // Write Interface
369 void Elf_X::e_ident(unsigned char *input)
370 {
371     if (!is64) P_memcpy(ehdr32->e_ident, input, EI_NIDENT);
372     else       P_memcpy(ehdr64->e_ident, input, EI_NIDENT);
373 }
374
375 void Elf_X::e_type(unsigned short input)
376 {
377     if (!is64) ehdr32->e_type = input;
378     else       ehdr64->e_type = input;
379 }
380
381 void Elf_X::e_machine(unsigned short input)
382 {
383     if (!is64) ehdr32->e_machine = input;
384     else       ehdr64->e_machine = input;
385 }
386
387 void Elf_X::e_version(unsigned long input)
388 {
389     if (!is64) ehdr32->e_version = input;
390     else       ehdr64->e_version = input;
391 }
392
393 void Elf_X::e_entry(unsigned long input)
394 {
395     if (!is64) ehdr32->e_entry = input;
396     else       ehdr64->e_entry = input;
397 }
398
399 void Elf_X::e_phoff(unsigned long input)
400 {
401     if (!is64) ehdr32->e_phoff = input;
402     else       ehdr64->e_phoff = input;
403 }
404
405 void Elf_X::e_shoff(unsigned long input)
406 {
407     if (!is64) ehdr32->e_shoff = input;
408     else       ehdr64->e_shoff = input;
409 }
410
411 void Elf_X::e_flags(unsigned long input)
412 {
413     if (!is64) ehdr32->e_flags = input;
414     else       ehdr64->e_flags = input;
415 }
416
417 void Elf_X::e_ehsize(unsigned short input)
418 {
419     if (!is64) ehdr32->e_ehsize = input;
420     else       ehdr64->e_ehsize = input;
421 }
422
423 void Elf_X::e_phentsize(unsigned short input)
424 {
425     if (!is64) ehdr32->e_phentsize = input;
426     else       ehdr64->e_phentsize = input;
427 }
428
429 void Elf_X::e_phnum(unsigned short input)
430 {
431     if (!is64) ehdr32->e_phnum = input;
432     else       ehdr64->e_phnum = input;
433 }
434
435 void Elf_X::e_shentsize(unsigned short input)
436 {
437     if (!is64) ehdr32->e_shentsize = input;
438     else       ehdr64->e_shentsize = input;
439 }
440
441 void Elf_X::e_shnum(unsigned short input)
442 {
443     if (!is64) ehdr32->e_shnum = input;
444     else       ehdr64->e_shnum = input;
445 }
446
447 void Elf_X::e_shstrndx(unsigned short input)
448 {
449     if (!is64) ehdr32->e_shstrndx = input;
450     else       ehdr64->e_shstrndx = input;
451 }
452
453 // Data Interface
454 bool Elf_X::isValid() const
455 {
456     return (ehdr32 || ehdr64);
457 }
458
459 int Elf_X::wordSize() const
460 {
461     return (!is64 ? 4 : 8);
462 }
463
464 Elf_X_Phdr &Elf_X::get_phdr(unsigned int i)
465 {
466    if (is64 && !phdrs[i].phdr64) {
467       phdrs[i] = Elf_X_Phdr(is64, phdr64 + i);
468    }
469    else if (!is64 && !phdrs[i].phdr32) {
470       phdrs[i] = Elf_X_Phdr(is64, phdr32 + i);
471    }
472    return phdrs[i];
473 }
474
475 Elf_X_Shdr &Elf_X::get_shdr(unsigned int i)
476 {
477    if (!shdrs[i]._elf) {
478       Elf_Scn *scn = elf_getscn(elf, i);
479       shdrs[i] = Elf_X_Shdr(is64, scn);
480       shdrs[i]._elf = this;
481    }
482    return shdrs[i];
483 }
484
485 // ------------------------------------------------------------------------
486 // Class Elf_X_Phdr simulates the Elf(32|64)_Phdr structure.
487 Elf_X_Phdr::Elf_X_Phdr()
488     : phdr32(NULL), phdr64(NULL), is64(false)
489 { }
490
491 Elf_X_Phdr::Elf_X_Phdr(bool is64_, void *input)
492     : phdr32(NULL), phdr64(NULL), is64(is64_)
493 {
494     if (input) {
495         if (!is64) phdr32 = (Elf32_Phdr *)input;
496         else       phdr64 = (Elf64_Phdr *)input;
497     }
498 }
499
500 // Read Interface
501 unsigned long Elf_X_Phdr::p_type() const
502 {
503     return (!is64 ?
504             static_cast<unsigned long>(phdr32->p_type) :
505             static_cast<unsigned long>(phdr64->p_type));
506 }
507
508 unsigned long Elf_X_Phdr::p_offset() const
509 {
510     return (!is64 ?
511             static_cast<unsigned long>(phdr32->p_offset) :
512             static_cast<unsigned long>(phdr64->p_offset));
513 }
514
515 unsigned long Elf_X_Phdr::p_vaddr() const
516 {
517     return (!is64 ?
518             static_cast<unsigned long>(phdr32->p_vaddr) :
519             static_cast<unsigned long>(phdr64->p_vaddr));
520 }
521
522 unsigned long Elf_X_Phdr::p_paddr() const
523 {
524     return (!is64 ?
525             static_cast<unsigned long>(phdr32->p_paddr) :
526             static_cast<unsigned long>(phdr64->p_paddr));
527 }
528
529 unsigned long Elf_X_Phdr::p_filesz() const
530 {
531     return (!is64 ?
532             static_cast<unsigned long>(phdr32->p_filesz) :
533             static_cast<unsigned long>(phdr64->p_filesz));
534 }
535
536 unsigned long Elf_X_Phdr::p_memsz() const
537 {
538     return (!is64 ?
539             static_cast<unsigned long>(phdr32->p_memsz) :
540             static_cast<unsigned long>(phdr64->p_memsz));
541 }
542
543 unsigned long Elf_X_Phdr::p_flags() const
544 {
545     return (!is64 ?
546             static_cast<unsigned long>(phdr32->p_flags) :
547             static_cast<unsigned long>(phdr64->p_flags));
548 }
549
550 unsigned long Elf_X_Phdr::p_align() const
551 {
552     return (!is64 ?
553             static_cast<unsigned long>(phdr32->p_align) :
554             static_cast<unsigned long>(phdr64->p_align));
555 }
556
557 // Write Interface
558 void Elf_X_Phdr::p_type(unsigned long input)
559 {
560     if (!is64) phdr32->p_type = input;
561     else       phdr64->p_type = input;
562 }
563
564 void Elf_X_Phdr::p_offset(unsigned long input)
565 {
566     if (!is64) phdr32->p_offset = input;
567     else       phdr64->p_offset = input;
568 }
569
570 void Elf_X_Phdr::p_vaddr(unsigned long input)
571 {
572     if (!is64) phdr32->p_vaddr = input;
573     else       phdr64->p_vaddr = input;
574 }
575
576 void Elf_X_Phdr::p_paddr(unsigned long input)
577 {
578     if (!is64) phdr32->p_paddr = input;
579     else       phdr64->p_paddr = input;
580 }
581
582 void Elf_X_Phdr::p_filesz(unsigned long input)
583 {
584     if (!is64) phdr32->p_filesz = input;
585     else       phdr64->p_filesz = input;
586 }
587
588 void Elf_X_Phdr::p_memsz(unsigned long input)
589 {
590     if (!is64) phdr32->p_memsz = input;
591     else       phdr64->p_memsz = input;
592 }
593
594 void Elf_X_Phdr::p_flags(unsigned long input)
595 {
596     if (!is64) phdr32->p_flags = input;
597     else       phdr64->p_flags = input;
598 }
599
600 void Elf_X_Phdr::p_align(unsigned long input)
601 {
602     if (!is64) phdr32->p_align = input;
603     else       phdr64->p_align = input;
604 }
605
606 bool Elf_X_Phdr::isValid() const
607 {
608     return (phdr32 || phdr64);
609 }
610
611 // ------------------------------------------------------------------------
612 // Class Elf_X_Shdr simulates the Elf(32|64)_Shdr structure.
613 Elf_X_Shdr::Elf_X_Shdr()
614     : scn(NULL), data(NULL), shdr32(NULL), shdr64(NULL), is64(false),
615       fromDebugFile(false), _elf(NULL)
616 { }
617
618 Elf_X_Shdr::Elf_X_Shdr(bool is64_, Elf_Scn *input)
619     : scn(input), data(NULL), shdr32(NULL), shdr64(NULL), is64(is64_),
620       fromDebugFile(false), _elf(NULL)
621 {
622     if (input) {
623         first_data();
624         if (!is64) shdr32 = elf32_getshdr(scn);
625         else       shdr64 = elf64_getshdr(scn);
626     }
627 }
628
629 // Read Interface
630 unsigned long Elf_X_Shdr::sh_name() const
631 {
632     return (!is64 ?
633             static_cast<unsigned long>(shdr32->sh_name) :
634             static_cast<unsigned long>(shdr64->sh_name));
635 }
636
637 unsigned long Elf_X_Shdr::sh_type() const
638 {
639     return (!is64 ?
640             static_cast<unsigned long>(shdr32->sh_type) :
641             static_cast<unsigned long>(shdr64->sh_type));
642 }
643
644 unsigned long Elf_X_Shdr::sh_flags() const
645 {
646     return (!is64 ?
647             static_cast<unsigned long>(shdr32->sh_flags) :
648             static_cast<unsigned long>(shdr64->sh_flags));
649 }
650
651 unsigned long Elf_X_Shdr::sh_addr() const
652 {
653 #if defined(os_vxworks)
654     assert(_elf);
655     if (_elf->e_type() == ET_REL) {
656         // VxWorks relocatable object files (kernel modules) don't have
657         // the address filled out.  Return the disk offset instead.
658         return (!is64 ?
659                 static_cast<unsigned long>(shdr32->sh_offset) :
660                 static_cast<unsigned long>(shdr64->sh_offset));
661     }
662 #endif
663
664     return (!is64 ?
665             static_cast<unsigned long>(shdr32->sh_addr) :
666             static_cast<unsigned long>(shdr64->sh_addr));
667 }
668
669 unsigned long Elf_X_Shdr::sh_offset() const
670 {
671     return (!is64 ?
672             static_cast<unsigned long>(shdr32->sh_offset) :
673             static_cast<unsigned long>(shdr64->sh_offset));
674 }
675
676 unsigned long Elf_X_Shdr::sh_size() const
677 {
678     return (!is64 ?
679             static_cast<unsigned long>(shdr32->sh_size) :
680             static_cast<unsigned long>(shdr64->sh_size));
681 }
682
683 unsigned long Elf_X_Shdr::sh_link() const
684 {
685     return (!is64 ?
686             shdr32->sh_link :
687             shdr64->sh_link);
688 }
689
690 unsigned long Elf_X_Shdr::sh_info() const
691 {
692     return (!is64 ?
693             static_cast<unsigned long>(shdr32->sh_info) :
694             static_cast<unsigned long>(shdr64->sh_info));
695 }
696
697 unsigned long Elf_X_Shdr::sh_addralign() const
698 {
699     return (!is64 ?
700             static_cast<unsigned long>(shdr32->sh_addralign) :
701             static_cast<unsigned long>(shdr64->sh_addralign));
702 }
703
704 unsigned long Elf_X_Shdr::sh_entsize() const
705 {
706     return (!is64 ?
707             static_cast<unsigned long>(shdr32->sh_entsize) :
708             static_cast<unsigned long>(shdr64->sh_entsize));
709 }
710
711 bool Elf_X_Shdr::isFromDebugFile() const
712 {
713     return fromDebugFile;
714 }
715
716 // Write Interface
717 void Elf_X_Shdr::sh_name(unsigned long input)
718 {
719     if (!is64) shdr32->sh_name = input;
720     else       shdr64->sh_name = input;
721 }
722
723 void Elf_X_Shdr::sh_type(unsigned long input)
724 {
725     if (!is64) shdr32->sh_type = input;
726     else       shdr64->sh_type = input;
727 }
728
729 void Elf_X_Shdr::sh_flags(unsigned long input)
730 {
731     if (!is64) shdr32->sh_flags = input;
732     else       shdr64->sh_flags = input;
733 }
734
735 void Elf_X_Shdr::sh_addr(unsigned long input)
736 {
737     if (!is64) shdr32->sh_addr = input;
738     else       shdr64->sh_addr = input;
739 }
740
741 void Elf_X_Shdr::sh_offset(unsigned long input)
742 {
743     if (!is64) shdr32->sh_offset = input;
744     else       shdr64->sh_offset = input;
745 }
746
747 void Elf_X_Shdr::sh_size(unsigned long input)
748 {
749     if (!is64) shdr32->sh_size = input;
750     else       shdr64->sh_size = input;
751 }
752
753 void Elf_X_Shdr::sh_link(unsigned long input)
754 {
755     if (!is64) shdr32->sh_link = input;
756     else       shdr64->sh_link = input;
757 }
758
759 void Elf_X_Shdr::sh_info(unsigned long input)
760 {
761     if (!is64) shdr32->sh_info = input;
762     else       shdr64->sh_info = input;
763 }
764
765 void Elf_X_Shdr::sh_addralign(unsigned long input)
766 {
767     if (!is64) shdr32->sh_addralign = input;
768     else       shdr64->sh_addralign = input;
769 }
770
771 void Elf_X_Shdr::sh_entsize(unsigned long input)
772 {
773     if (!is64) shdr32->sh_entsize = input;
774     else       shdr64->sh_entsize = input;
775 }
776
777 void Elf_X_Shdr::setDebugFile(bool b)
778 {
779     fromDebugFile = b;
780 }
781
782 // Section Data Interface
783 Elf_X_Data Elf_X_Shdr::get_data() const
784 {
785     return Elf_X_Data(is64, data);
786 }
787
788 // For Sections with Multiple Data Sections
789 void Elf_X_Shdr::first_data()
790 {
791     data = elf_getdata(scn, NULL);
792 }
793
794 bool Elf_X_Shdr::next_data()
795 {
796     Elf_Data *nextData = elf_getdata(scn, data);
797     if (nextData) data = nextData;
798     return nextData;
799 }
800
801 bool Elf_X_Shdr::isValid() const
802 {
803     return (shdr32 || shdr64);
804 }
805
806 unsigned Elf_X_Shdr::wordSize() const
807 {
808     return is64 ? 8 : 4;
809 }
810
811 Elf_Scn *Elf_X_Shdr::getScn() const
812 {
813     return scn;
814 }
815
816 Elf_X_Nhdr Elf_X_Shdr::get_note() const
817 {
818     if (sh_type() != SHT_NOTE)
819         return Elf_X_Nhdr();
820     return Elf_X_Nhdr(data, 0);
821 }
822
823 // ------------------------------------------------------------------------
824 // Class Elf_X_Data simulates the Elf_Data structure.
825 Elf_X_Data::Elf_X_Data()
826     : data(NULL), is64(false)
827 { }
828
829 Elf_X_Data::Elf_X_Data(bool is64_, Elf_Data *input)
830     : data(input), is64(is64_)
831 { }
832
833 // Read Interface
834 void *Elf_X_Data::d_buf() const
835 {
836     return data->d_buf;
837 }
838
839 Elf_Type Elf_X_Data::d_type() const
840 {
841     return data->d_type;
842 }
843
844 unsigned int Elf_X_Data::d_version() const
845 {
846     return data->d_version;
847 }
848
849 size_t Elf_X_Data::d_size() const
850 {
851     return data->d_size;
852 }
853
854 off_t Elf_X_Data::d_off() const
855 {
856     return (off_t) data->d_off;
857 }
858
859 size_t Elf_X_Data::d_align() const
860 {
861     return data->d_align;
862 }
863
864 // Write Interface
865 void Elf_X_Data::d_buf(void *input)
866 {
867     data->d_buf = input;
868 }
869
870 void Elf_X_Data::d_type(Elf_Type input)
871 {
872     data->d_type = input;
873 }
874
875 void Elf_X_Data::d_version(unsigned int input)
876 {
877     data->d_version = input;
878 }
879
880 void Elf_X_Data::d_size(unsigned int input)
881 {
882     data->d_size = input;
883 }
884
885 void Elf_X_Data::d_off(signed int input)
886 {
887     data->d_off = input;
888 }
889
890 void Elf_X_Data::d_align(unsigned int input)
891 {
892     data->d_align = input;
893 }
894
895 // Data Interface
896 const char *Elf_X_Data::get_string() const
897 {
898     return (const char *)data->d_buf;
899 }
900
901 Elf_X_Dyn Elf_X_Data::get_dyn()
902 {
903     return Elf_X_Dyn(is64, data);
904 }
905
906 Elf_X_Versym Elf_X_Data::get_versyms()
907 {
908     return Elf_X_Versym(is64, data);
909 }
910
911 Elf_X_Verneed *Elf_X_Data::get_verNeedSym()
912 {
913     return new Elf_X_Verneed(is64, data->d_buf);
914 }
915
916 Elf_X_Verdef *Elf_X_Data::get_verDefSym()
917 {
918     return new Elf_X_Verdef(is64, data->d_buf);
919 }
920
921 Elf_X_Rel Elf_X_Data::get_rel()
922 {
923     return Elf_X_Rel(is64, data);
924 }
925
926 Elf_X_Rela Elf_X_Data::get_rela()
927 {
928     return Elf_X_Rela(is64, data);
929 }
930
931 Elf_X_Sym Elf_X_Data::get_sym()
932 {
933     return Elf_X_Sym(is64, data);
934 }
935
936 bool Elf_X_Data::isValid() const
937 {
938     return data;
939 }
940
941 // ------------------------------------------------------------------------
942 // Class Elf_X_Versym simulates the SHT_GNU_versym structure.
943 Elf_X_Versym::Elf_X_Versym()
944     : data(NULL), versym32(NULL), versym64(NULL), is64(false)
945 { }
946
947 Elf_X_Versym::Elf_X_Versym(bool is64_, Elf_Data *input)
948     : data(input), versym32(NULL), versym64(NULL), is64(is64_)
949 {
950     if (input) {
951         if (!is64) versym32 = (Elf32_Half *)data->d_buf;
952         else       versym64 = (Elf64_Half *)data->d_buf;
953     }
954 }
955
956 // Read Interface
957 unsigned long Elf_X_Versym::get(int i) const
958 {
959     return (!is64 ? versym32[i]
960                   : versym64[i]);
961 }
962
963 // Meta-Info Interface
964 unsigned long Elf_X_Versym::count() const
965 {
966     return (data->d_size / (!is64 ? sizeof(Elf32_Half)
967                                   : sizeof(Elf64_Half) ));
968 }
969
970 bool Elf_X_Versym::isValid() const
971 {
972     return (versym32 || versym64);
973 }
974
975 // ------------------------------------------------------------------------
976 // Class Elf_X_Verdaux simulates the Elf(32|64)_Verdaux structure.
977 Elf_X_Verdaux::Elf_X_Verdaux()
978     : data(NULL), verdaux32(NULL), verdaux64(NULL), is64(false)
979 { }
980
981 Elf_X_Verdaux::Elf_X_Verdaux(bool is64_, void *input)
982     : data(input), verdaux32(NULL), verdaux64(NULL), is64(is64_)
983 {
984     if (input) {
985         if (!is64) verdaux32 = (Elf32_Verdaux *)data;
986         else       verdaux64 = (Elf64_Verdaux *)data;
987     }
988 }
989
990 // Read Interface
991 unsigned long Elf_X_Verdaux::vda_name() const
992 {
993     return (!is64 ? verdaux32->vda_name
994                   : verdaux64->vda_name);
995 }
996
997 unsigned long Elf_X_Verdaux::vda_next() const
998 {
999     return (!is64 ? verdaux32->vda_next
1000                   : verdaux64->vda_next);
1001 }
1002
1003 Elf_X_Verdaux *Elf_X_Verdaux::get_next() const
1004 {
1005     if (vda_next() == 0)
1006         return NULL;
1007     return new Elf_X_Verdaux(is64, (char *)data+vda_next());
1008 }
1009
1010 // Meta-Info Interface
1011 bool Elf_X_Verdaux::isValid() const
1012 {
1013     return (verdaux32 || verdaux64);
1014 }
1015
1016 // ------------------------------------------------------------------------
1017 // Class Elf_X_Verdef simulates the Elf(32|64)_Verdef structure.
1018 Elf_X_Verdef::Elf_X_Verdef()
1019     : data(NULL), verdef32(NULL), verdef64(NULL), is64(false)
1020 { }
1021
1022 Elf_X_Verdef::Elf_X_Verdef(bool is64_, void *input)
1023     : data(input), verdef32(NULL), verdef64(NULL), is64(is64_)
1024 {
1025     if (input) {
1026         if (!is64) verdef32 = (Elf32_Verdef *)data;
1027         else       verdef64 = (Elf64_Verdef *)data;
1028     }
1029 }
1030
1031 // Read Interface
1032 unsigned long Elf_X_Verdef::vd_version() const
1033 {
1034     return (!is64 ? verdef32->vd_version
1035                   : verdef64->vd_version);
1036 }
1037
1038 unsigned long Elf_X_Verdef::vd_flags() const
1039 {
1040     return (!is64 ? verdef32->vd_flags
1041                   : verdef64->vd_flags);
1042 }
1043
1044 unsigned long Elf_X_Verdef::vd_ndx() const
1045 {
1046     return (!is64 ? verdef32->vd_ndx
1047                   : verdef64->vd_ndx);
1048 }
1049
1050 unsigned long Elf_X_Verdef::vd_cnt() const
1051 {
1052     return (!is64 ? verdef32->vd_cnt
1053                   : verdef64->vd_cnt);
1054 }
1055
1056 unsigned long Elf_X_Verdef::vd_hash() const
1057 {
1058     return (!is64 ? verdef32->vd_hash
1059                   : verdef64->vd_hash);
1060 }
1061
1062 unsigned long Elf_X_Verdef::vd_aux() const
1063 {
1064     return (!is64 ? verdef32->vd_aux
1065                   : verdef64->vd_aux);
1066 }
1067
1068 unsigned long Elf_X_Verdef::vd_next() const
1069 {
1070     return (!is64 ? verdef32->vd_next
1071                   : verdef64->vd_next);
1072 }
1073
1074 Elf_X_Verdaux *Elf_X_Verdef::get_aux() const
1075 {
1076     if (vd_cnt() == 0)
1077         return NULL;
1078     return new Elf_X_Verdaux(is64, (char *)data+vd_aux());
1079 }
1080
1081 Elf_X_Verdef *Elf_X_Verdef::get_next() const
1082 {
1083     if (vd_next() == 0)
1084         return NULL;
1085     return new Elf_X_Verdef(is64, (char *)data+vd_next());
1086 }
1087
1088 // Meta-Info Interface
1089 bool Elf_X_Verdef::isValid() const
1090 {
1091     return (verdef32 || verdef64);
1092 }
1093
1094 // ------------------------------------------------------------------------
1095 // Class Elf_X_Vernaux simulates the Elf(32|64)_Vernaux structure.
1096 Elf_X_Vernaux::Elf_X_Vernaux()
1097     : data(NULL), vernaux32(NULL), vernaux64(NULL), is64(false)
1098 { }
1099
1100 Elf_X_Vernaux::Elf_X_Vernaux(bool is64_, void *input)
1101     : data(input), vernaux32(NULL), vernaux64(NULL), is64(is64_)
1102 {
1103     if (input) {
1104         if (!is64) vernaux32 = (Elf32_Vernaux *)data;
1105         else       vernaux64 = (Elf64_Vernaux *)data;
1106     }
1107 }
1108
1109 // Read Interface
1110 unsigned long Elf_X_Vernaux::vna_hash() const
1111 {
1112     return (!is64 ? vernaux32->vna_hash
1113                   : vernaux64->vna_hash);
1114 }
1115
1116 unsigned long Elf_X_Vernaux::vna_flags() const
1117 {
1118     return (!is64 ? vernaux32->vna_flags
1119                   : vernaux64->vna_flags);
1120 }
1121
1122 unsigned long Elf_X_Vernaux::vna_other() const
1123 {
1124     return (!is64 ? vernaux32->vna_other
1125                   : vernaux64->vna_other);
1126 }
1127
1128 unsigned long Elf_X_Vernaux::vna_name() const
1129 {
1130     return (!is64 ? vernaux32->vna_name
1131                   : vernaux64->vna_name);
1132 }
1133
1134 unsigned long Elf_X_Vernaux::vna_next() const
1135 {
1136     return (!is64 ? vernaux32->vna_next
1137                   : vernaux64->vna_next);
1138 }
1139
1140 Elf_X_Vernaux *Elf_X_Vernaux::get_next() const
1141 {
1142     if (vna_next() == 0)
1143         return NULL;
1144     return new Elf_X_Vernaux(is64, (char *)data+vna_next());
1145 }
1146
1147 // Meta-Info Interface
1148 bool Elf_X_Vernaux::isValid() const
1149 {
1150     return (vernaux32 || vernaux64);
1151 }
1152
1153 // ------------------------------------------------------------------------
1154 // Class Elf_X_Verneed simulates the Elf(32|64)_Verneed structure.
1155 Elf_X_Verneed::Elf_X_Verneed()
1156     : data(NULL), verneed32(NULL), verneed64(NULL), is64(false)
1157 { }
1158
1159 Elf_X_Verneed::Elf_X_Verneed(bool is64_, void *input)
1160     : data(input), verneed32(NULL), verneed64(NULL), is64(is64_)
1161 {
1162     if (input) {
1163         if (!is64) verneed32 = (Elf32_Verneed *)data;
1164         else       verneed64 = (Elf64_Verneed *)data;
1165     }
1166 }
1167
1168 // Read Interface
1169 unsigned long Elf_X_Verneed::vn_version() const
1170 {
1171     return (!is64 ? verneed32->vn_version
1172                   : verneed64->vn_version);
1173 }
1174
1175 unsigned long Elf_X_Verneed::vn_cnt() const
1176 {
1177     return (!is64 ? verneed32->vn_cnt
1178             : verneed64->vn_cnt);
1179 }
1180
1181 unsigned long Elf_X_Verneed::vn_file() const
1182 {
1183     return (!is64 ? verneed32->vn_file
1184                   : verneed64->vn_file);
1185 }
1186
1187 unsigned long Elf_X_Verneed::vn_aux() const
1188 {
1189     return (!is64 ? verneed32->vn_aux
1190                   : verneed64->vn_aux);
1191 }
1192
1193 unsigned long Elf_X_Verneed::vn_next() const
1194 {
1195     return (!is64 ? verneed32->vn_next
1196             : verneed64->vn_next);
1197 }
1198
1199 Elf_X_Vernaux *Elf_X_Verneed::get_aux() const
1200 {
1201     if (vn_cnt() == 0)
1202         return NULL;
1203     return new Elf_X_Vernaux(is64, (char *)data+vn_aux());
1204 }
1205
1206 Elf_X_Verneed *Elf_X_Verneed::get_next() const
1207 {
1208     if (vn_next() == 0)
1209         return NULL;
1210     return new Elf_X_Verneed(is64, (char *)data+vn_next());
1211 }
1212
1213 // Meta-Info Interface
1214 bool Elf_X_Verneed::isValid() const
1215 {
1216     return (verneed32 || verneed64);
1217 }
1218
1219
1220 // ------------------------------------------------------------------------
1221 // Class Elf_X_Sym simulates the Elf(32|64)_Sym structure.
1222 Elf_X_Sym::Elf_X_Sym()
1223     : data(NULL), sym32(NULL), sym64(NULL), is64(false)
1224 { }
1225
1226 Elf_X_Sym::Elf_X_Sym(bool is64_, Elf_Data *input)
1227     : data(input), sym32(NULL), sym64(NULL), is64(is64_)
1228 {
1229     if (input) {
1230         if (!is64) sym32 = (Elf32_Sym *)data->d_buf;
1231         else       sym64 = (Elf64_Sym *)data->d_buf;
1232     }
1233 }
1234
1235 // Read Interface
1236 unsigned long Elf_X_Sym::st_name(int i) const
1237 {
1238     return (!is64 ?
1239             static_cast<unsigned long>(sym32[i].st_name) :
1240             static_cast<unsigned long>(sym64[i].st_name));
1241 }
1242
1243 unsigned long Elf_X_Sym::st_value(int i) const
1244 {
1245     return (!is64 ?
1246             static_cast<unsigned long>(sym32[i].st_value) :
1247             static_cast<unsigned long>(sym64[i].st_value));
1248 }
1249
1250 unsigned long Elf_X_Sym::st_size(int i) const
1251 {
1252     return (!is64 ?
1253             static_cast<unsigned long>(sym32[i].st_size) :
1254             static_cast<unsigned long>(sym64[i].st_size));
1255 }
1256
1257 unsigned char Elf_X_Sym::st_info(int i) const
1258 {
1259     return (!is64 ?
1260             sym32[i].st_info :
1261             sym64[i].st_info);
1262 }
1263
1264 unsigned char Elf_X_Sym::st_other(int i) const
1265 {
1266     return (!is64 ?
1267             sym32[i].st_other :
1268             sym64[i].st_other);
1269 }
1270
1271 unsigned short Elf_X_Sym::st_shndx(int i) const
1272 {
1273     return (!is64 ?
1274             sym32[i].st_shndx :
1275             sym64[i].st_shndx);
1276 }
1277
1278 unsigned char Elf_X_Sym::ST_BIND(int i) const
1279 {
1280     return (!is64 ?
1281             static_cast<unsigned char>(ELF32_ST_BIND(sym32[i].st_info)) :
1282             static_cast<unsigned char>(ELF64_ST_BIND(sym64[i].st_info)));
1283 }
1284
1285 unsigned char Elf_X_Sym::ST_TYPE(int i) const
1286 {
1287     return (!is64 ?
1288             static_cast<unsigned char>(ELF32_ST_TYPE(sym32[i].st_info)) :
1289             static_cast<unsigned char>(ELF64_ST_TYPE(sym64[i].st_info)));
1290 }
1291
1292 unsigned char Elf_X_Sym::ST_VISIBILITY(int i) const
1293 {
1294     return (!is64 ?
1295             static_cast<unsigned char>(ELF32_ST_VISIBILITY(sym32[i].st_other)) :
1296             static_cast<unsigned char>(ELF64_ST_VISIBILITY(sym64[i].st_other)));
1297 }
1298
1299 void *Elf_X_Sym::st_symptr(int i) const
1300 {
1301     return (!is64 ?
1302             (void *)(sym32 + i) :
1303             (void *)(sym64 + i));
1304 }
1305
1306 unsigned Elf_X_Sym::st_entsize() const
1307 {
1308     return (is64 ?
1309             sizeof(Elf64_Sym) :
1310             sizeof(Elf32_Sym));
1311 }
1312
1313 // Write Interface
1314 void Elf_X_Sym::st_name(int i, unsigned long input)
1315 {
1316     if (!is64) sym32[i].st_name = input;
1317     else       sym64[i].st_name = input;
1318 }
1319
1320 void Elf_X_Sym::st_value(int i, unsigned long input)
1321 {
1322     if (!is64) sym32[i].st_value = input;
1323     else       sym64[i].st_value = input;
1324 }
1325
1326 void Elf_X_Sym::st_size(int i, unsigned long input)
1327 {
1328     if (!is64) sym32[i].st_size = input;
1329     else       sym64[i].st_size = input;
1330 }
1331
1332 void Elf_X_Sym::st_info(int i, unsigned char input)
1333 {
1334     if (!is64) sym32[i].st_info = input;
1335     else       sym64[i].st_info = input;
1336 }
1337
1338 void Elf_X_Sym::st_other(int i, unsigned char input)
1339 {
1340     if (!is64) sym32[i].st_other = input;
1341     else       sym64[i].st_other = input;
1342 }
1343
1344 void Elf_X_Sym::st_shndx(int i, unsigned short input)
1345 {
1346     if (!is64) sym32[i].st_shndx = input;
1347     else       sym64[i].st_shndx = input;
1348 }
1349
1350 // Meta-Info Interface
1351 unsigned long Elf_X_Sym::count() const
1352 {
1353     return (data->d_size / (!is64 ? sizeof(Elf32_Sym)
1354                                   : sizeof(Elf64_Sym)));
1355 }
1356
1357 bool Elf_X_Sym::isValid() const
1358 {
1359     return sym32 || sym64;
1360 }
1361
1362 // ------------------------------------------------------------------------
1363 // Class Elf_X_Rel simulates the Elf(32|64)_Rel structure.
1364 Elf_X_Rel::Elf_X_Rel()
1365     : data(NULL), rel32(NULL), rel64(NULL), is64(false)
1366 { }
1367
1368 Elf_X_Rel::Elf_X_Rel(bool is64_, Elf_Data *input)
1369     : data(input), rel32(NULL), rel64(NULL), is64(is64_)
1370 {
1371     if (input) {
1372         if (!is64) 
1373             rel32 = (Elf32_Rel *)data->d_buf;
1374         else       
1375             rel64 = (Elf64_Rel *)data->d_buf;
1376     }
1377 }
1378
1379 // Read Interface
1380 unsigned long Elf_X_Rel::r_offset(int i) const
1381 {
1382     return (!is64 ?
1383             static_cast<unsigned long>(rel32[i].r_offset) :
1384             static_cast<unsigned long>(rel64[i].r_offset));
1385 }
1386
1387 unsigned long Elf_X_Rel::r_info(int i) const
1388 {
1389     return (!is64 ?
1390             static_cast<unsigned long>(rel32[i].r_info) :
1391             static_cast<unsigned long>(rel64[i].r_info));
1392 }
1393
1394 unsigned long Elf_X_Rel::R_SYM(int i) const
1395 {
1396     return (!is64 ?
1397             static_cast<unsigned long>(ELF32_R_SYM(rel32[i].r_info)) :
1398             static_cast<unsigned long>(ELF64_R_SYM(rel64[i].r_info)));
1399 }
1400
1401 unsigned long Elf_X_Rel::R_TYPE(int i) const
1402 {
1403     return (!is64 ?
1404             static_cast<unsigned long>(ELF32_R_TYPE(rel32[i].r_info)) :
1405             static_cast<unsigned long>(ELF64_R_TYPE(rel64[i].r_info)));
1406 };
1407
1408 // Write Interface
1409 void Elf_X_Rel::r_offset(int i, unsigned long input)
1410 {
1411     if (!is64)
1412         rel32[i].r_offset = input;
1413     else
1414         rel64[i].r_offset = input;
1415 }
1416
1417 void Elf_X_Rel::r_info(int i, unsigned long input)
1418 {
1419     if (!is64)
1420         rel32[i].r_info = input;
1421     else
1422         rel64[i].r_info = input;
1423 }
1424
1425 // Meta-Info Interface
1426 unsigned long Elf_X_Rel::count() const
1427 {
1428     return (data->d_size / (!is64 ? sizeof(Elf32_Rel)
1429                                   : sizeof(Elf64_Rel)) );
1430 }
1431
1432 bool Elf_X_Rel::isValid() const
1433 {
1434     return (rel32 || rel64);
1435 }
1436
1437 // ------------------------------------------------------------------------
1438 // Class Elf_X_Rela simulates the Elf(32|64)_Rela structure.
1439 Elf_X_Rela::Elf_X_Rela()
1440     : data(NULL), rela32(NULL), rela64(NULL), is64(false)
1441 { }
1442
1443 Elf_X_Rela::Elf_X_Rela(bool is64_, Elf_Data *input)
1444     : data(input), rela32(NULL), rela64(NULL), is64(is64_)
1445 {
1446     if (input) {
1447         if (!is64) 
1448             rela32 = (Elf32_Rela *)data->d_buf;
1449         else       
1450             rela64 = (Elf64_Rela *)data->d_buf;
1451     }
1452 }
1453
1454 // Read Interface
1455 unsigned long Elf_X_Rela::r_offset(int i) const
1456 {
1457     return (!is64 ?
1458             static_cast<unsigned long>(rela32[i].r_offset) :
1459             static_cast<unsigned long>(rela64[i].r_offset));
1460 }
1461
1462 unsigned long Elf_X_Rela::r_info(int i) const
1463 {
1464     return (!is64 ?
1465             static_cast<unsigned long>(rela32[i].r_info) :
1466             static_cast<unsigned long>(rela64[i].r_info));
1467 }
1468
1469 signed long Elf_X_Rela::r_addend(int i) const
1470 {
1471     return (!is64 ?
1472             static_cast<signed long>(rela32[i].r_addend) :
1473             static_cast<signed long>(rela64[i].r_addend));
1474 }
1475
1476 unsigned long Elf_X_Rela::R_SYM(int i) const
1477 {
1478     return (!is64 ?
1479             static_cast<unsigned long>(ELF32_R_SYM(rela32[i].r_info)) :
1480             static_cast<unsigned long>(ELF64_R_SYM(rela64[i].r_info)));
1481 }
1482
1483 unsigned long Elf_X_Rela::R_TYPE(int i) const
1484 {
1485     return (!is64 ?
1486             static_cast<unsigned long>(ELF32_R_TYPE(rela32[i].r_info)) :
1487             static_cast<unsigned long>(ELF64_R_TYPE(rela64[i].r_info)));
1488 }
1489
1490 // Write Interface
1491 void Elf_X_Rela::r_offset(int i, unsigned long input)
1492 {
1493     if (!is64)
1494         rela32[i].r_offset = input;
1495     else
1496         rela64[i].r_offset = input;
1497 }
1498
1499 void Elf_X_Rela::r_info(int i, unsigned long input)
1500 {
1501     if (!is64)
1502         rela32[i].r_info = input;
1503     else
1504         rela64[i].r_info = input;
1505 }
1506
1507 void Elf_X_Rela::r_addend(int i, signed long input)
1508 {
1509     if (!is64)
1510         rela32[i].r_addend = input;
1511     else
1512         rela64[i].r_addend = input;
1513 }
1514
1515 // Meta-Info Interface
1516 unsigned long Elf_X_Rela::count() const
1517 {
1518     return (data->d_size / (!is64 ? sizeof(Elf32_Rela)
1519                                   : sizeof(Elf64_Rela)));
1520 }
1521
1522 bool Elf_X_Rela::isValid() const
1523 {
1524     return (rela32 || rela64);
1525 }
1526
1527
1528 // ------------------------------------------------------------------------
1529 // Class Elf_X_Dyn simulates the Elf(32|64)_Dyn structure.
1530 Elf_X_Dyn::Elf_X_Dyn()
1531     : data(NULL), dyn32(NULL), dyn64(NULL), is64(false)
1532 { }
1533
1534 Elf_X_Dyn::Elf_X_Dyn(bool is64_, Elf_Data *input)
1535     : data(input), dyn32(NULL), dyn64(NULL), is64(is64_)
1536 {
1537     if (input) {
1538         if (!is64) dyn32 = (Elf32_Dyn *)data->d_buf;
1539         else       dyn64 = (Elf64_Dyn *)data->d_buf;
1540     }
1541 }
1542
1543 // Read Interface
1544 signed long Elf_X_Dyn::d_tag(int i) const
1545
1546     return (!is64 ?
1547             static_cast<signed long>(dyn32[i].d_tag) :
1548             static_cast<signed long>(dyn64[i].d_tag));
1549 }
1550
1551 unsigned long Elf_X_Dyn::d_val(int i) const
1552 {
1553     return (!is64 ?
1554             static_cast<unsigned long>(dyn32[i].d_un.d_val) :
1555             static_cast<unsigned long>(dyn64[i].d_un.d_val));
1556 }
1557
1558 unsigned long Elf_X_Dyn::d_ptr(int i) const
1559 {
1560     return (!is64 ?
1561             static_cast<unsigned long>(dyn32[i].d_un.d_ptr) :
1562             static_cast<unsigned long>(dyn64[i].d_un.d_ptr));
1563 }
1564
1565 // Write Interface
1566 void Elf_X_Dyn::d_tag(int i, signed long input)
1567 {
1568     if (!is64) dyn32[i].d_tag = input;
1569     else       dyn64[i].d_tag = input;
1570 }
1571
1572 void Elf_X_Dyn::d_val(int i, unsigned long input)
1573 {
1574     if (!is64) dyn32[i].d_un.d_val = input;
1575     else       dyn64[i].d_un.d_val = input;
1576 }
1577
1578 void Elf_X_Dyn::d_ptr(int i, unsigned long input)
1579 {
1580     if (!is64) dyn32[i].d_un.d_ptr = input;
1581     else       dyn64[i].d_un.d_ptr = input;
1582 }
1583
1584 // Meta-Info Interface
1585 unsigned long Elf_X_Dyn::count() const
1586 {
1587     return (data->d_size / (!is64 ? sizeof(Elf32_Dyn)
1588                                   : sizeof(Elf64_Dyn) ));
1589 }
1590
1591 bool Elf_X_Dyn::isValid() const
1592 {
1593     return (dyn32 || dyn64);
1594 }
1595
1596 static bool loadDebugFileFromDisk(string name, char* &output_buffer, unsigned long &output_buffer_size)
1597 {
1598    struct stat fileStat;
1599    int result = stat(name.c_str(), &fileStat);
1600    if (result == -1)
1601       return false;
1602    if (S_ISDIR(fileStat.st_mode))
1603       return false;
1604    int fd = open(name.c_str(), O_RDONLY);
1605    if (fd == -1)
1606       return false;
1607
1608    char *buffer = (char *) mmap(NULL, fileStat.st_size, PROT_READ, MAP_SHARED, fd, 0);
1609    close(fd);
1610    if (!buffer)
1611       return false;
1612
1613    output_buffer = buffer;
1614    output_buffer_size = fileStat.st_size;
1615
1616    return true;
1617 }
1618
1619 // The standard procedure to look for a separate debug information file
1620 // is as follows:
1621 // 1. Lookup build_id from .note.gnu.build-id section and debug-file-name and
1622 //    crc from .gnu_debuglink section of the original binary.
1623 // 2. Look for the following files:
1624 //        /usr/lib/debug/.build-id/<path-obtained-using-build-id>.debug
1625 //        <debug-file-name> in <directory-of-executable>
1626 //        <debug-file-name> in <directory-of-executable>/.debug
1627 //        <debug-file-name> in /usr/lib/debug/<directory-of-executable>
1628 // Reference: http://sourceware.org/gdb/current/onlinedocs/gdb_16.html#SEC157
1629 bool Elf_X::findDebugFile(std::string origfilename, string &output_name, char* &output_buffer, unsigned long &output_buffer_size)
1630 {
1631    if (cached_debug) {
1632       output_buffer = cached_debug_buffer;
1633       output_buffer_size = cached_debug_size;
1634       output_name = cached_debug_name;
1635       return (output_buffer != NULL);
1636    }
1637    cached_debug = true;
1638
1639    uint16_t shnames_idx = e_shstrndx();
1640    Elf_X_Shdr shnames_hdr = get_shdr(shnames_idx);
1641    if (!shnames_hdr.isValid())
1642       return false;
1643    const char *shnames = (const char *) shnames_hdr.get_data().d_buf();
1644    
1645   string debugFileFromDebugLink, debugFileFromBuildID;
1646   unsigned debugFileCrc = 0;
1647
1648   for(int i = 0; i < e_shnum(); i++) {
1649      Elf_X_Shdr scn = get_shdr(i);
1650      if (!scn.isValid()) { // section is malformed
1651         continue;
1652      }
1653
1654      const char *name = &shnames[scn.sh_name()];
1655      if(strcmp(name, DEBUGLINK_NAME) == 0) {
1656         Elf_X_Data data = scn.get_data();
1657         debugFileFromDebugLink = (char *) data.d_buf();
1658         void *crcLocation = ((char *) data.d_buf() + data.d_size() - 4);
1659         debugFileCrc = *(unsigned *) crcLocation;
1660      }
1661      else if (scn.sh_type() == SHT_NOTE) {
1662         // Look for a build-id note in this section.  It is usually a note by
1663         // itself in section .note.gnu.build-id, but not necessarily so.
1664         for (Elf_X_Nhdr note = scn.get_note();
1665               note.isValid(); note = note.next()) {
1666            if (note.n_type() == 3 // NT_GNU_BUILD_ID
1667                  && note.n_namesz() == sizeof("GNU")
1668                  && strcmp(note.get_name(), "GNU") == 0
1669                  && note.n_descsz() >= 2) {
1670               // This is a raw build-id, now convert it to hex
1671               const unsigned char *desc = (const unsigned char *)note.get_desc();
1672               stringstream buildid_path;
1673               buildid_path << "/usr/lib/debug/.build-id/"
1674                  << hex << setfill('0') << setw(2) << (unsigned)desc[0] << '/';
1675               for (unsigned long j = 1; j < note.n_descsz(); ++j)
1676                  buildid_path << (unsigned)desc[j];
1677               buildid_path << ".debug";
1678               debugFileFromBuildID = buildid_path.str();
1679               break;
1680            }
1681         }
1682      }
1683   }
1684
1685   if (!debugFileFromBuildID.empty()) {
1686      bool result = loadDebugFileFromDisk(debugFileFromBuildID, output_buffer, output_buffer_size);
1687      if (result) {
1688         output_name = debugFileFromBuildID;
1689         cached_debug_buffer = output_buffer;
1690         cached_debug_size = output_buffer_size;
1691         cached_debug_name = output_name;
1692         return true;
1693      }
1694   }
1695
1696   if (debugFileFromDebugLink.empty())
1697      return false;
1698
1699   char *mfPathNameCopy = strdup(origfilename.c_str());
1700   string objectFileDirName = dirname(mfPathNameCopy);
1701
1702   vector<string> fnames = list_of
1703     (objectFileDirName + "/" + debugFileFromDebugLink)
1704     (objectFileDirName + "/.debug/" + debugFileFromDebugLink)
1705     ("/usr/lib/debug/" + objectFileDirName + "/" + debugFileFromDebugLink);
1706
1707   free(mfPathNameCopy);
1708
1709   for(unsigned i = 0; i < fnames.size(); i++) {
1710      bool result = loadDebugFileFromDisk(fnames[i], output_buffer, output_buffer_size);
1711      if (!result)
1712         continue;
1713     
1714     boost::crc_32_type crcComputer;
1715     crcComputer.process_bytes(output_buffer, output_buffer_size);
1716     if(crcComputer.checksum() != debugFileCrc) {
1717        munmap(output_buffer, output_buffer_size);
1718        continue;
1719     }
1720
1721     output_name = fnames[i];
1722     cached_debug_buffer = output_buffer;
1723     cached_debug_size = output_buffer_size;
1724     cached_debug_name = output_name;
1725     return true;
1726   }
1727
1728   return false;
1729 }
1730
1731 // ------------------------------------------------------------------------
1732 // Class Elf_X_Nhdr simulates the Elf(32|64)_Nhdr structure.
1733 Elf_X_Nhdr::Elf_X_Nhdr()
1734     : data(NULL), nhdr(NULL)
1735 { }
1736
1737 Elf_X_Nhdr::Elf_X_Nhdr(Elf_Data *data_, size_t offset)
1738     : data(data_), nhdr(NULL)
1739 {
1740     // 32|64 are actually the same, which simplifies things
1741     assert(sizeof(Elf32_Nhdr) == sizeof(Elf64_Nhdr));
1742
1743     if (data && offset < data->d_size) {
1744         size_t size = data->d_size - offset;
1745         if (sizeof(*nhdr) <= size) {
1746             size -= sizeof(*nhdr);
1747             nhdr = (Elf32_Nhdr *)((char *)data->d_buf + offset);
1748             if (n_namesz() > size || n_descsz() > size - n_namesz())
1749                 nhdr = NULL;
1750         }
1751     }
1752     if (!nhdr)
1753         data = NULL;
1754 }
1755
1756 // Read Interface
1757 unsigned long Elf_X_Nhdr::n_namesz() const
1758 {
1759     return isValid() ? nhdr->n_namesz : 0;
1760 }
1761
1762 unsigned long Elf_X_Nhdr::n_descsz() const
1763 {
1764     return isValid() ? nhdr->n_descsz : 0;
1765 }
1766
1767 unsigned long Elf_X_Nhdr::n_type() const
1768 {
1769     return isValid() ? nhdr->n_type : 0;
1770 }
1771
1772 bool Elf_X_Nhdr::isValid() const
1773 {
1774     return (data && nhdr);
1775 }
1776
1777 const char* Elf_X_Nhdr::get_name() const
1778 {
1779     return isValid() ? (char *)nhdr + sizeof(*nhdr) : NULL;
1780 }
1781
1782 const void* Elf_X_Nhdr::get_desc() const
1783 {
1784     return isValid() ? get_name() + n_namesz() : NULL;
1785 }
1786
1787 Elf_X_Nhdr Elf_X_Nhdr::next() const
1788 {
1789     if (!isValid())
1790         return Elf_X_Nhdr();
1791
1792     size_t offset = (const char *)get_desc() + n_descsz() - (char *)data->d_buf;
1793     return Elf_X_Nhdr(data, offset);
1794 }