Minor changes here and there.
[aesalon.git] / src / monitor / ElfParser.cpp
bloba9c34fd80c847feced3ba4e01fe6eee9b64686fe
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
8 */
10 #include <stdio.h>
11 #include <fcntl.h>
12 #include <elf.h>
13 #include <string.h>
14 #include <iostream>
15 #include <vector>
16 #include <sys/mman.h>
18 #include "monitor/ElfParser.h"
19 #include "util/PathSanitizer.h"
20 #include "util/StreamAsString.h"
21 #include "util/MessageSystem.h"
23 namespace Monitor {
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));
40 if(identValid()) {
41 if(m_elfType == ELF32) {
42 parseElf<ELF32_TYPES>();
44 else if(m_elfType == ELF64) {
45 parseElf<ELF64_TYPES>();
48 close(m_fd);
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 . . . */
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 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;
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 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