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