1 /** Aesalon, a tool to visualize program behaviour in real time.
2 Copyright (C) 2009-2011, Aesalon development team.
4 Aesalon is distributed under the terms of the GNU GPLv3. See
5 the included file LICENSE for more information.
7 @file src/monitor/ElfParser.cpp
18 #include "monitor/ElfParser.h"
19 #include "util/PathSanitizer.h"
20 #include "util/StreamAsString.h"
21 #include "util/MessageSystem.h"
25 ElfParser::ElfParser() {
29 ElfParser::~ElfParser() {
33 void ElfParser::parse(const std::string
&filename
, Processor
*processor
) {
34 m_processor
= processor
;
35 m_fd
= open(filename
.c_str(), O_RDONLY
);
37 m_fileSize
= lseek(m_fd
, 0, SEEK_END
);
38 m_file
= reinterpret_cast<uint8_t *>(mmap(NULL
, m_fileSize
, PROT_READ
, MAP_PRIVATE
, m_fd
, 0));
41 if(m_elfType
== ELF32
) {
42 parseElf
<ELF32_TYPES
>();
44 else if(m_elfType
== ELF64
) {
45 parseElf
<ELF64_TYPES
>();
49 munmap(m_file
, m_fileSize
);
52 bool ElfParser::identValid() {
53 if(m_fileSize
< EI_NIDENT
) return false;
54 unsigned char *ident
= reinterpret_cast<unsigned char *>(m_file
);
55 if(strncmp(ELFMAG
, (char *)ident
, SELFMAG
) != 0) return false;
57 /* By this point, it's probably valid. */
58 if(ident
[EI_CLASS
] == ELFCLASS32
) m_elfType
= ELF32
;
59 else if(ident
[EI_CLASS
] == ELFCLASS64
) m_elfType
= ELF64
;
60 /* But just in case . . . */
63 if(ident
[EI_DATA
] == ELFDATA2LSB
) m_encoding
= LSB_ENCODING
;
64 else if(ident
[EI_DATA
] == ELFDATA2MSB
) m_encoding
= MSB_ENCODING
;
65 /* Only know how to handle MSB and LSB encoding . . . */
68 /* If the execution has gotten this far, then it's a likely bet that
69 it's a valid ELF file.
74 template<typename ELFHeader
, typename SectionHeader
, typename SymbolHeader
>
75 void ElfParser::parseElf() {
76 if(m_encoding
!= LSB_ENCODING
) {
77 std::cout
<< "Don't know how to handle non-LSB encoding at the moment." << std::endl
;
81 lseek(m_fd
, 0, SEEK_SET
);
83 eheader
= reinterpret_cast<ELFHeader
*>(m_file
);
85 SectionHeader
*sections
= reinterpret_cast<SectionHeader
*>(m_file
+ eheader
->e_shoff
);
87 SectionHeader
*shstrSection
= sections
+ eheader
->e_shstrndx
;
88 const char *shstr
= reinterpret_cast<char *>(m_file
+ shstrSection
->sh_offset
);
90 SymbolHeader
*symtab
= NULL
;
92 const char *strtab
= NULL
;
93 SymbolHeader
*dynsym
= NULL
;
95 const char *dynstr
= NULL
;
97 for(int i
= 0; i
< eheader
->e_shnum
; i
++) {
98 SectionHeader
*section
= §ions
[i
];
99 if(!strcmp(".symtab", shstr
+ section
->sh_name
)) {
100 symtab
= reinterpret_cast<SymbolHeader
*>(m_file
+ section
->sh_offset
);
101 symtabSize
= section
->sh_size
/ sizeof(SymbolHeader
);
103 else if(!strcmp(".strtab", shstr
+ section
->sh_name
)) {
104 strtab
= reinterpret_cast<char *>(m_file
+ section
->sh_offset
);
106 else if(!strcmp(".dynsym", shstr
+ section
->sh_name
)) {
107 dynsym
= reinterpret_cast<SymbolHeader
*>(m_file
+ section
->sh_offset
);
108 dynsymSize
= section
->sh_size
/ sizeof(SymbolHeader
);
110 else if(!strcmp(".dynstr", shstr
+ section
->sh_name
)) {
111 dynstr
= reinterpret_cast<char *>(m_file
+ section
->sh_offset
);
115 parseSymbols
<SymbolHeader
>(symtab
, symtabSize
, strtab
);
116 parseSymbols
<SymbolHeader
>(dynsym
, dynsymSize
, dynstr
);
119 template<typename SymbolHeader
>
120 void ElfParser::parseSymbols(SymbolHeader
*symbols
, int symbolCount
, const char *stringTable
) {
121 for(int i
= 0; i
< symbolCount
; i
++) {
122 m_processor
->process(stringTable
+ symbols
[i
].st_name
, symbols
[i
].st_value
, symbols
[i
].st_size
);
126 } // namespace Monitor