Started implementing various things.
[aesalon.git] / monitor / src / analyzer / ElfAnalyzer.cpp
blobc50e999c8b75872e07169b966f3d73c6a2dfdb46
1 /**
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
12 #include <stdio.h>
13 #include <fcntl.h>
14 #include <elf.h>
15 #include <string.h>
16 #include <iostream>
17 #include <vector>
18 #include <sys/mman.h>
20 #include "analyzer/ElfAnalyzer.h"
21 #include "config/ConcreteVault.h"
22 #include "common/PathSanitizer.h"
23 #include "common/StreamAsString.h"
25 namespace Monitor {
26 namespace Analyzer {
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));
35 if(identValid()) {
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>();
44 close(m_fd);
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 . . . */
61 else return false;
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 . . . */
66 else return false;
68 /* If the execution has gotten this far, then it's a likely bet that
69 it's a valid ELF file.
71 return true;
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;
78 return;
81 lseek(m_fd, 0, SEEK_SET);
82 ELFHeader *eheader;
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;
91 int symtabSize = 0;
92 const char *strtab = NULL;
93 SymbolHeader *dynsym = NULL;
94 int dynsymSize = 0;
95 const char *dynstr = NULL;
97 for(int i = 0; i < eheader->e_shnum; i ++) {
98 SectionHeader *section = &sections[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";*/
123 m_vault->set(
124 Common::StreamAsString() << "\"" << stringTable + symbols[i].st_name << "\":value",
125 Common::StreamAsString() << symbols[i].st_value);
126 m_vault->set(
127 Common::StreamAsString() << "\"" << stringTable + symbols[i].st_name << "\":size",
128 Common::StreamAsString() << symbols[i].st_size);
132 } // namespace Analyzer
133 } // namespace Monitor