OLD | NEW |
| (Empty) |
1 // Copyright (c) 2010 The Chromium Authors. All rights reserved. | |
2 // Use of this source code is governed by a BSD-style license that can be | |
3 // found in the LICENSE file. | |
4 | |
5 #ifndef LIBRARY_H__ | |
6 #define LIBRARY_H__ | |
7 | |
8 #include <elf.h> | |
9 #include <functional> | |
10 #include <map> | |
11 #include <set> | |
12 #include <string> | |
13 #include <string.h> | |
14 #include <sys/mman.h> | |
15 | |
16 #include "maps.h" | |
17 | |
18 #if defined(__x86_64__) | |
19 typedef Elf64_Ehdr Elf_Ehdr; | |
20 typedef Elf64_Shdr Elf_Shdr; | |
21 typedef Elf64_Sym Elf_Sym; | |
22 typedef Elf64_Addr Elf_Addr; | |
23 #elif defined(__i386__) | |
24 typedef Elf32_Ehdr Elf_Ehdr; | |
25 typedef Elf32_Shdr Elf_Shdr; | |
26 typedef Elf32_Sym Elf_Sym; | |
27 typedef Elf32_Addr Elf_Addr; | |
28 #else | |
29 #error Unsupported target platform | |
30 #endif | |
31 | |
32 struct SyscallTable; | |
33 namespace playground { | |
34 | |
35 class Library { | |
36 friend class Maps; | |
37 public: | |
38 typedef Maps::string string; | |
39 | |
40 Library() : | |
41 valid_(false), | |
42 isVDSO_(false), | |
43 asr_offset_(0), | |
44 vsys_offset_(0), | |
45 maps_(0), | |
46 image_(0), | |
47 image_size_(0) { | |
48 } | |
49 | |
50 ~Library(); | |
51 | |
52 void setLibraryInfo(Maps* maps) { | |
53 if (!maps_) { | |
54 maps_ = maps; | |
55 } | |
56 } | |
57 | |
58 void addMemoryRange(void* start, void* stop, Elf_Addr offset, | |
59 int prot, int isVDSO) { | |
60 isVDSO_ = isVDSO; | |
61 RangeMap::const_iterator iter = memory_ranges_.find(offset); | |
62 if (iter != memory_ranges_.end()) { | |
63 // It is possible to have overlapping mappings. This is particularly | |
64 // likely to happen with very small programs or libraries. If it does | |
65 // happen, we really only care about the text segment. Look for a | |
66 // mapping that is mapped executable. | |
67 if ((prot & PROT_EXEC) == 0) { | |
68 return; | |
69 } | |
70 } | |
71 memory_ranges_.insert(std::make_pair(offset, Range(start, stop, prot))); | |
72 } | |
73 | |
74 char *get(Elf_Addr offset, char *buf, size_t len); | |
75 string get(Elf_Addr offset); | |
76 char *getOriginal(Elf_Addr offset, char *buf, size_t len); | |
77 string getOriginal(Elf_Addr offset); | |
78 | |
79 template<class T>T* get(Elf_Addr offset, T* t) { | |
80 if (!valid_) { | |
81 memset(t, 0, sizeof(T)); | |
82 return NULL; | |
83 } | |
84 return reinterpret_cast<T *>(get(offset, reinterpret_cast<char *>(t), | |
85 sizeof(T))); | |
86 } | |
87 | |
88 template<class T>T* getOriginal(Elf_Addr offset, T* t) { | |
89 if (!valid_) { | |
90 memset(t, 0, sizeof(T)); | |
91 return NULL; | |
92 } | |
93 return reinterpret_cast<T *>(getOriginal(offset, | |
94 reinterpret_cast<char *>(t), | |
95 sizeof(T))); | |
96 } | |
97 | |
98 template<class T>bool set(void *addr, T* value) { | |
99 if (!valid_) { | |
100 return false; | |
101 } | |
102 *reinterpret_cast<T *>(addr) = *value; | |
103 return true; | |
104 } | |
105 | |
106 template<class T>bool set(Elf_Addr offset, T* value) { | |
107 if (!valid_) { | |
108 return false; | |
109 } | |
110 RangeMap::const_iterator iter = memory_ranges_.lower_bound(offset); | |
111 if (iter == memory_ranges_.end()) { | |
112 return false; | |
113 } | |
114 offset -= iter->first; | |
115 if (offset > | |
116 reinterpret_cast<char *>(iter->second.stop) - | |
117 reinterpret_cast<char *>(iter->second.start) - | |
118 sizeof(T)) { | |
119 return false; | |
120 } | |
121 *reinterpret_cast<T *>( | |
122 reinterpret_cast<char *>(iter->second.start) + offset) = *value; | |
123 return true; | |
124 } | |
125 | |
126 bool parseElf(); | |
127 const Elf_Ehdr* getEhdr(); | |
128 const Elf_Shdr* getSection(const string& section); | |
129 int getSectionIndex(const string& section); | |
130 void makeWritable(bool state) const; | |
131 void patchSystemCalls(); | |
132 bool isVDSO() const { return isVDSO_; } | |
133 | |
134 protected: | |
135 bool parseSymbols(); | |
136 | |
137 private: | |
138 class GreaterThan : public std::binary_function<Elf_Addr, Elf_Addr, bool> { | |
139 // We create the RangeMap with a GreaterThan rather than the default | |
140 // comparator, as that allows us to use lower_bound() to find memory | |
141 // mappings. | |
142 public: | |
143 bool operator() (Elf_Addr s1, Elf_Addr s2) const { | |
144 return s1 > s2; | |
145 } | |
146 }; | |
147 | |
148 struct Range { | |
149 Range(void* start, void* stop, int prot) : | |
150 start(start), stop(stop), prot(prot) { } | |
151 void* start; | |
152 void* stop; | |
153 int prot; | |
154 }; | |
155 | |
156 typedef std::map<Elf_Addr, Range, GreaterThan, | |
157 SystemAllocator<std::pair<const Elf_Addr, | |
158 Range> > > RangeMap; | |
159 typedef std::map<string, std::pair<int, Elf_Shdr>, std::less<string>, | |
160 SystemAllocator<std::pair<const string, | |
161 std::pair<int, Elf_Shdr> > > > | |
162 SectionTable; | |
163 typedef std::map<string, Elf_Sym, std::less<string>, | |
164 SystemAllocator<std::pair<const string, | |
165 Elf_Sym> > > SymbolTable; | |
166 typedef std::map<string, Elf_Addr, std::less<string>, | |
167 SystemAllocator<std::pair<const string, | |
168 Elf_Addr> > > PltTable; | |
169 | |
170 char* getBytes(char* dst, const char* src, ssize_t len); | |
171 static bool isSafeInsn(unsigned short insn); | |
172 static int isSimpleSystemCall(char *start, char *end); | |
173 static char* getScratchSpace(const Maps* maps, char* near, int needed, | |
174 char** extraSpace, int* extraLength); | |
175 void patchSystemCallsInFunction(const Maps* maps, char *start, char *end, | |
176 char** extraSpace, int* extraLength); | |
177 int patchVSystemCalls(); | |
178 void patchVDSO(char** extraSpace, int* extraLength); | |
179 | |
180 RangeMap memory_ranges_; | |
181 bool valid_; | |
182 bool isVDSO_; | |
183 char* asr_offset_; | |
184 int vsys_offset_; | |
185 Maps* maps_; | |
186 Elf_Ehdr ehdr_; | |
187 SectionTable section_table_; | |
188 SymbolTable symbols_; | |
189 PltTable plt_entries_; | |
190 char* image_; | |
191 size_t image_size_; | |
192 static char* __kernel_vsyscall; | |
193 static char* __kernel_sigreturn; | |
194 static char* __kernel_rt_sigreturn; | |
195 }; | |
196 | |
197 } // namespace | |
198 | |
199 #endif // LIBRARY_H__ | |
OLD | NEW |