|
1 /* This Source Code Form is subject to the terms of the Mozilla Public |
|
2 * License, v. 2.0. If a copy of the MPL was not distributed with this |
|
3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ |
|
4 |
|
5 #include <string> |
|
6 #include <fstream> |
|
7 #include <errno.h> |
|
8 #include <fcntl.h> |
|
9 #include <stdlib.h> |
|
10 #include <stdio.h> |
|
11 #include <unistd.h> |
|
12 #include <sys/stat.h> |
|
13 |
|
14 #include "elf_symbol_table.h" |
|
15 #include "elf_utils.h" |
|
16 |
|
17 int |
|
18 elf_symbol_table::init(const char *name) |
|
19 { |
|
20 // Open the file readonly. |
|
21 m_fd = open(name, O_RDONLY); |
|
22 if (m_fd < 0) { |
|
23 perror(name); |
|
24 return m_fd; |
|
25 } |
|
26 |
|
27 // Get its size. |
|
28 struct stat statbuf; |
|
29 if (fstat(m_fd, &statbuf) < 0) { |
|
30 perror(name); |
|
31 return -1; |
|
32 } |
|
33 |
|
34 m_size = statbuf.st_size; |
|
35 |
|
36 // Memory map it. |
|
37 m_mapping = mmap(0, m_size, PROT_READ, MAP_SHARED, m_fd, 0); |
|
38 if (m_mapping == MAP_FAILED) { |
|
39 perror(name); |
|
40 return -1; |
|
41 } |
|
42 |
|
43 // Make sure it's an ELF header. |
|
44 const Elf32_Ehdr *ehdr = reinterpret_cast<const Elf32_Ehdr *>(m_mapping); |
|
45 if (elf_verify_header(ehdr) < 0) |
|
46 return -1; |
|
47 |
|
48 const char *mapping = reinterpret_cast<const char *>(m_mapping); |
|
49 |
|
50 // Find the section headers |
|
51 const Elf32_Shdr *shdrs |
|
52 = reinterpret_cast<const Elf32_Shdr *>(mapping + ehdr->e_shoff); |
|
53 |
|
54 // find the section header string table, .shstrtab |
|
55 const Elf32_Shdr *shstrtabsh = shdrs + ehdr->e_shstrndx; |
|
56 const char *shstrtab = mapping + shstrtabsh->sh_offset; |
|
57 |
|
58 // parse the sections we care about |
|
59 int shndx = 0; |
|
60 const Elf32_Shdr *shlimit = shdrs + ehdr->e_shnum; |
|
61 for (const Elf32_Shdr *shdr = shdrs; shdr < shlimit; ++shdr, ++shndx) { |
|
62 basic_string<char> name(shstrtab + shdr->sh_name); |
|
63 if (name == ".symtab") { |
|
64 m_symbols = reinterpret_cast<const Elf32_Sym *>(mapping + shdr->sh_offset); |
|
65 m_nsymbols = shdr->sh_size / sizeof(Elf32_Sym); |
|
66 } |
|
67 else if (name == ".strtab") { |
|
68 m_strtab = mapping + shdr->sh_offset; |
|
69 } |
|
70 else if (name == ".text") { |
|
71 m_text_shndx = shndx; |
|
72 } |
|
73 } |
|
74 |
|
75 // Parse the symbol table |
|
76 const Elf32_Sym *limit = m_symbols + m_nsymbols; |
|
77 for (const Elf32_Sym *sym = m_symbols; sym < limit; ++sym) { |
|
78 if (is_function(sym)) { |
|
79 #ifdef DEBUG |
|
80 hex(cout); |
|
81 cout << sym->st_value << endl; |
|
82 #endif |
|
83 m_rsymtab.put(sym->st_value, sym->st_value + sym->st_size, sym); |
|
84 } |
|
85 } |
|
86 |
|
87 return 0; |
|
88 } |
|
89 |
|
90 int |
|
91 elf_symbol_table::finish() |
|
92 { |
|
93 if (m_mapping != MAP_FAILED) { |
|
94 munmap(m_mapping, m_size); |
|
95 m_mapping = MAP_FAILED; |
|
96 } |
|
97 |
|
98 if (m_fd >= 0) { |
|
99 close(m_fd); |
|
100 m_fd = -1; |
|
101 } |
|
102 |
|
103 return 0; |
|
104 } |
|
105 |
|
106 const Elf32_Sym * |
|
107 elf_symbol_table::lookup(unsigned int addr) const |
|
108 { |
|
109 rsymtab_t::const_iterator result = m_rsymtab.get(addr); |
|
110 return result != m_rsymtab.end() ? reinterpret_cast<const Elf32_Sym *>(*result) : 0; |
|
111 } |
|
112 |
|
113 const char * |
|
114 elf_symbol_table::get_symbol_name(const Elf32_Sym *sym) const |
|
115 { |
|
116 return m_strtab + sym->st_name; |
|
117 } |