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