2 Aesalon, a tool to visualize a program's behaviour at run-time.
3 Copyright (C) 2010, Aesalon Development Team.
5 Aesalon is distributed under the terms of the GNU GPLv3. For more
6 licensing information, see the file LICENSE included with the distribution.
8 @file monitor/src/analyzer/ElfAnalyzer.cpp
20 #include "analyzer/ElfAnalyzer.h"
21 #include "config/ConcreteVault.h"
22 #include "common/PathSanitizer.h"
23 #include "common/StreamAsString.h"
28 ElfAnalyzer::ElfAnalyzer(std::string filename
) : ExecutableAnalyzer(filename
), m_vault(NULL
) {
29 filename
= Common::PathSanitizer::sanitize(filename
);
30 m_fd
= open(filename
.c_str(), O_RDONLY
);
32 m_fileSize
= lseek(m_fd
, 0, SEEK_END
);
33 m_file
= reinterpret_cast<uint8_t *>(mmap(NULL
, m_fileSize
, PROT_READ
, MAP_PRIVATE
, m_fd
, 0));
36 m_vault
= new Config::ConcreteVault();
37 if(m_elfType
== ELF32
) {
38 parseElf
<ELF32_TYPES
>();
40 else if(m_elfType
== ELF64
) {
41 parseElf
<ELF64_TYPES
>();
45 munmap(m_file
, m_fileSize
);
48 ElfAnalyzer::~ElfAnalyzer() {
52 bool ElfAnalyzer::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 ElfAnalyzer::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 ElfAnalyzer::parseSymbols(SymbolHeader
*symbols
, int symbolCount
, const char *stringTable
) {
121 for(int i
= 0; i
< symbolCount
; i
++) {
122 /*std::cout << "Parsing symbol \"" << stringTable + symbols[i].st_name << "\" . . .\n";*/
124 Common::StreamAsString() << "\"" << stringTable
+ symbols
[i
].st_name
<< "\":value",
125 Common::StreamAsString() << symbols
[i
].st_value
);
127 Common::StreamAsString() << "\"" << stringTable
+ symbols
[i
].st_name
<< "\":size",
128 Common::StreamAsString() << symbols
[i
].st_size
);
132 } // namespace Analyzer
133 } // namespace Monitor