29 #include <string.h> |
29 #include <string.h> |
30 #include <stdio.h> |
30 #include <stdio.h> |
31 #include <limits.h> |
31 #include <limits.h> |
32 #include <new> |
32 #include <new> |
33 |
33 |
|
34 #include "logging/log.hpp" |
34 #include "memory/allocation.inline.hpp" |
35 #include "memory/allocation.inline.hpp" |
|
36 #include "memory/resourceArea.hpp" |
35 #include "utilities/decoder.hpp" |
37 #include "utilities/decoder.hpp" |
36 #include "utilities/elfFile.hpp" |
38 #include "utilities/elfFile.hpp" |
37 #include "utilities/elfFuncDescTable.hpp" |
39 #include "utilities/elfFuncDescTable.hpp" |
38 #include "utilities/elfStringTable.hpp" |
40 #include "utilities/elfStringTable.hpp" |
39 #include "utilities/elfSymbolTable.hpp" |
41 #include "utilities/elfSymbolTable.hpp" |
40 |
42 #include "utilities/ostream.hpp" |
41 |
43 |
42 ElfFile::ElfFile(const char* filepath) { |
44 // For test only, disable elf section cache and force to read from file directly. |
|
45 bool ElfFile::_do_not_cache_elf_section = false; |
|
46 |
|
47 ElfSection::ElfSection(FILE* fd, const Elf_Shdr& hdr) : _section_data(NULL) { |
|
48 _stat = load_section(fd, hdr); |
|
49 } |
|
50 |
|
51 ElfSection::~ElfSection() { |
|
52 if (_section_data != NULL) { |
|
53 os::free(_section_data); |
|
54 } |
|
55 } |
|
56 |
|
57 NullDecoder::decoder_status ElfSection::load_section(FILE* const fd, const Elf_Shdr& shdr) { |
|
58 memcpy((void*)&_section_hdr, (const void*)&shdr, sizeof(shdr)); |
|
59 |
|
60 if (ElfFile::_do_not_cache_elf_section) { |
|
61 log_debug(decoder)("Elf section cache is disabled"); |
|
62 return NullDecoder::no_error; |
|
63 } |
|
64 |
|
65 _section_data = os::malloc(shdr.sh_size, mtInternal); |
|
66 // No enough memory for caching. It is okay, we can try to read from |
|
67 // file instead. |
|
68 if (_section_data == NULL) return NullDecoder::no_error; |
|
69 |
|
70 MarkedFileReader mfd(fd); |
|
71 if (mfd.has_mark() && |
|
72 mfd.set_position(shdr.sh_offset) && |
|
73 mfd.read(_section_data, shdr.sh_size)) { |
|
74 return NullDecoder::no_error; |
|
75 } else { |
|
76 os::free(_section_data); |
|
77 _section_data = NULL; |
|
78 return NullDecoder::file_invalid; |
|
79 } |
|
80 } |
|
81 |
|
82 bool FileReader::read(void* buf, size_t size) { |
|
83 assert(buf != NULL, "no buffer"); |
|
84 assert(size > 0, "no space"); |
|
85 return fread(buf, size, 1, _fd) == 1; |
|
86 } |
|
87 |
|
88 int FileReader::read_buffer(void* buf, size_t size) { |
|
89 assert(buf != NULL, "no buffer"); |
|
90 assert(size > 0, "no space"); |
|
91 return fread(buf, 1, size, _fd); |
|
92 } |
|
93 |
|
94 bool FileReader::set_position(long offset) { |
|
95 return fseek(_fd, offset, SEEK_SET) == 0; |
|
96 } |
|
97 |
|
98 MarkedFileReader::MarkedFileReader(FILE* fd) : FileReader(fd) { |
|
99 _marked_pos = ftell(fd); |
|
100 } |
|
101 |
|
102 MarkedFileReader::~MarkedFileReader() { |
|
103 if (_marked_pos != -1) { |
|
104 set_position(_marked_pos); |
|
105 } |
|
106 } |
|
107 |
|
108 ElfFile::ElfFile(const char* filepath) : |
|
109 _string_tables(NULL), _symbol_tables(NULL), _funcDesc_table(NULL), |
|
110 _next(NULL), _status(NullDecoder::no_error), |
|
111 _shdr_string_table(NULL), _file(NULL), _filepath(NULL) { |
|
112 memset(&_elfHdr, 0, sizeof(_elfHdr)); |
|
113 |
|
114 int len = strlen(filepath) + 1; |
|
115 _filepath = (char*)os::malloc(len * sizeof(char), mtInternal); |
|
116 if (_filepath == NULL) { |
|
117 _status = NullDecoder::out_of_memory; |
|
118 return; |
|
119 } |
|
120 strcpy(_filepath, filepath); |
|
121 |
|
122 _status = parse_elf(filepath); |
|
123 |
|
124 // we no longer need section header string table |
|
125 if (_shdr_string_table != NULL) { |
|
126 delete _shdr_string_table; |
|
127 _shdr_string_table = NULL; |
|
128 } |
|
129 } |
|
130 |
|
131 ElfFile::~ElfFile() { |
|
132 if (_shdr_string_table != NULL) { |
|
133 delete _shdr_string_table; |
|
134 } |
|
135 |
|
136 cleanup_tables(); |
|
137 |
|
138 if (_file != NULL) { |
|
139 fclose(_file); |
|
140 } |
|
141 |
|
142 if (_filepath != NULL) { |
|
143 os::free((void*)_filepath); |
|
144 } |
|
145 |
|
146 if (_next != NULL) { |
|
147 delete _next; |
|
148 } |
|
149 } |
|
150 |
|
151 void ElfFile::cleanup_tables() { |
|
152 if (_string_tables != NULL) { |
|
153 delete _string_tables; |
|
154 _string_tables = NULL; |
|
155 } |
|
156 |
|
157 if (_symbol_tables != NULL) { |
|
158 delete _symbol_tables; |
|
159 _symbol_tables = NULL; |
|
160 } |
|
161 |
|
162 if (_funcDesc_table != NULL) { |
|
163 delete _funcDesc_table; |
|
164 _funcDesc_table = NULL; |
|
165 } |
|
166 } |
|
167 |
|
168 NullDecoder::decoder_status ElfFile::parse_elf(const char* filepath) { |
43 assert(filepath, "null file path"); |
169 assert(filepath, "null file path"); |
44 memset(&m_elfHdr, 0, sizeof(m_elfHdr)); |
170 |
45 m_string_tables = NULL; |
171 _file = fopen(filepath, "r"); |
46 m_symbol_tables = NULL; |
172 if (_file != NULL) { |
47 m_funcDesc_table = NULL; |
173 return load_tables(); |
48 m_next = NULL; |
|
49 m_status = NullDecoder::no_error; |
|
50 |
|
51 int len = strlen(filepath) + 1; |
|
52 m_filepath = (const char*)os::malloc(len * sizeof(char), mtInternal); |
|
53 if (m_filepath != NULL) { |
|
54 strcpy((char*)m_filepath, filepath); |
|
55 m_file = fopen(filepath, "r"); |
|
56 if (m_file != NULL) { |
|
57 load_tables(); |
|
58 } else { |
|
59 m_status = NullDecoder::file_not_found; |
|
60 } |
|
61 } else { |
174 } else { |
62 m_status = NullDecoder::out_of_memory; |
175 return NullDecoder::file_not_found; |
63 } |
176 } |
64 } |
177 } |
65 |
|
66 ElfFile::~ElfFile() { |
|
67 if (m_string_tables != NULL) { |
|
68 delete m_string_tables; |
|
69 } |
|
70 |
|
71 if (m_symbol_tables != NULL) { |
|
72 delete m_symbol_tables; |
|
73 } |
|
74 |
|
75 if (m_file != NULL) { |
|
76 fclose(m_file); |
|
77 } |
|
78 |
|
79 if (m_filepath != NULL) { |
|
80 os::free((void*)m_filepath); |
|
81 } |
|
82 |
|
83 if (m_next != NULL) { |
|
84 delete m_next; |
|
85 } |
|
86 }; |
|
87 |
|
88 |
178 |
89 //Check elf header to ensure the file is valid. |
179 //Check elf header to ensure the file is valid. |
90 bool ElfFile::is_elf_file(Elf_Ehdr& hdr) { |
180 bool ElfFile::is_elf_file(Elf_Ehdr& hdr) { |
91 return (ELFMAG0 == hdr.e_ident[EI_MAG0] && |
181 return (ELFMAG0 == hdr.e_ident[EI_MAG0] && |
92 ELFMAG1 == hdr.e_ident[EI_MAG1] && |
182 ELFMAG1 == hdr.e_ident[EI_MAG1] && |
94 ELFMAG3 == hdr.e_ident[EI_MAG3] && |
184 ELFMAG3 == hdr.e_ident[EI_MAG3] && |
95 ELFCLASSNONE != hdr.e_ident[EI_CLASS] && |
185 ELFCLASSNONE != hdr.e_ident[EI_CLASS] && |
96 ELFDATANONE != hdr.e_ident[EI_DATA]); |
186 ELFDATANONE != hdr.e_ident[EI_DATA]); |
97 } |
187 } |
98 |
188 |
99 bool ElfFile::load_tables() { |
189 NullDecoder::decoder_status ElfFile::load_tables() { |
100 assert(m_file, "file not open"); |
190 assert(_file, "file not open"); |
101 assert(!NullDecoder::is_error(m_status), "already in error"); |
191 assert(!NullDecoder::is_error(_status), "already in error"); |
102 |
192 |
|
193 FileReader freader(fd()); |
103 // read elf file header |
194 // read elf file header |
104 if (fread(&m_elfHdr, sizeof(m_elfHdr), 1, m_file) != 1) { |
195 if (!freader.read(&_elfHdr, sizeof(_elfHdr))) { |
105 m_status = NullDecoder::file_invalid; |
196 return NullDecoder::file_invalid; |
106 return false; |
197 } |
107 } |
198 |
108 |
199 // Check signature |
109 if (!is_elf_file(m_elfHdr)) { |
200 if (!is_elf_file(_elfHdr)) { |
110 m_status = NullDecoder::file_invalid; |
201 return NullDecoder::file_invalid; |
111 return false; |
|
112 } |
202 } |
113 |
203 |
114 // walk elf file's section headers, and load string tables |
204 // walk elf file's section headers, and load string tables |
115 Elf_Shdr shdr; |
205 Elf_Shdr shdr; |
116 if (!fseek(m_file, m_elfHdr.e_shoff, SEEK_SET)) { |
206 if (!freader.set_position(_elfHdr.e_shoff)) { |
117 if (NullDecoder::is_error(m_status)) return false; |
207 return NullDecoder::file_invalid; |
118 |
208 } |
119 for (int index = 0; index < m_elfHdr.e_shnum; index ++) { |
209 |
120 if (fread((void*)&shdr, sizeof(Elf_Shdr), 1, m_file) != 1) { |
210 for (int index = 0; index < _elfHdr.e_shnum; index ++) { |
121 m_status = NullDecoder::file_invalid; |
211 if (!freader.read(&shdr, sizeof(shdr))) { |
122 return false; |
212 return NullDecoder::file_invalid; |
|
213 } |
|
214 |
|
215 if (shdr.sh_type == SHT_STRTAB) { |
|
216 // string tables |
|
217 ElfStringTable* table = new (std::nothrow) ElfStringTable(fd(), shdr, index); |
|
218 if (table == NULL) { |
|
219 return NullDecoder::out_of_memory; |
123 } |
220 } |
124 if (shdr.sh_type == SHT_STRTAB) { |
221 if (index == _elfHdr.e_shstrndx) { |
125 // string tables |
222 assert(_shdr_string_table == NULL, "Only set once"); |
126 ElfStringTable* table = new (std::nothrow) ElfStringTable(m_file, shdr, index); |
223 _shdr_string_table = table; |
127 if (table == NULL) { |
224 } else { |
128 m_status = NullDecoder::out_of_memory; |
|
129 return false; |
|
130 } |
|
131 add_string_table(table); |
225 add_string_table(table); |
132 } else if (shdr.sh_type == SHT_SYMTAB || shdr.sh_type == SHT_DYNSYM) { |
|
133 // symbol tables |
|
134 ElfSymbolTable* table = new (std::nothrow) ElfSymbolTable(m_file, shdr); |
|
135 if (table == NULL) { |
|
136 m_status = NullDecoder::out_of_memory; |
|
137 return false; |
|
138 } |
|
139 add_symbol_table(table); |
|
140 } |
226 } |
141 } |
227 } else if (shdr.sh_type == SHT_SYMTAB || shdr.sh_type == SHT_DYNSYM) { |
142 |
228 // symbol tables |
|
229 ElfSymbolTable* table = new (std::nothrow) ElfSymbolTable(fd(), shdr); |
|
230 if (table == NULL) { |
|
231 return NullDecoder::out_of_memory; |
|
232 } |
|
233 add_symbol_table(table); |
|
234 } |
|
235 } |
143 #if defined(PPC64) && !defined(ABI_ELFv2) |
236 #if defined(PPC64) && !defined(ABI_ELFv2) |
144 // Now read the .opd section wich contains the PPC64 function descriptor table. |
237 // Now read the .opd section wich contains the PPC64 function descriptor table. |
145 // The .opd section is only available on PPC64 (see for example: |
238 // The .opd section is only available on PPC64 (see for example: |
146 // http://refspecs.linuxfoundation.org/LSB_3.1.1/LSB-Core-PPC64/LSB-Core-PPC64/specialsections.html) |
239 // http://refspecs.linuxfoundation.org/LSB_3.1.1/LSB-Core-PPC64/LSB-Core-PPC64/specialsections.html) |
147 // so this code should do no harm on other platforms but because of performance reasons we only |
240 // so this code should do no harm on other platforms but because of performance reasons we only |
148 // execute it on PPC64 platforms. |
241 // execute it on PPC64 platforms. |
149 // Notice that we can only find the .opd section after we have successfully read in the string |
242 // Notice that we can only find the .opd section after we have successfully read in the string |
150 // tables in the previous loop, because we need to query the name of each section which is |
243 // tables in the previous loop, because we need to query the name of each section which is |
151 // contained in one of the string tables (i.e. the one with the index m_elfHdr.e_shstrndx). |
244 // contained in one of the string tables (i.e. the one with the index m_elfHdr.e_shstrndx). |
152 |
245 |
153 // Reset the file pointer |
246 // Reset the file pointer |
154 if (fseek(m_file, m_elfHdr.e_shoff, SEEK_SET)) { |
247 int sect_index = section_by_name(".opd", shdr); |
155 m_status = NullDecoder::file_invalid; |
248 |
156 return false; |
249 if (sect_index == -1) { |
157 } |
250 return NullDecoder::file_invalid; |
158 for (int index = 0; index < m_elfHdr.e_shnum; index ++) { |
251 } |
159 if (fread((void*)&shdr, sizeof(Elf_Shdr), 1, m_file) != 1) { |
252 |
160 m_status = NullDecoder::file_invalid; |
253 _funcDesc_table = new (std::nothrow) ElfFuncDescTable(_file, shdr, sect_index); |
161 return false; |
254 if (_funcDesc_table == NULL) { |
|
255 return NullDecoder::out_of_memory; |
|
256 } |
|
257 #endif |
|
258 return NullDecoder::no_error; |
|
259 } |
|
260 |
|
261 int ElfFile::section_by_name(const char* name, Elf_Shdr& hdr) { |
|
262 assert(name != NULL, "No section name"); |
|
263 size_t len = strlen(name) + 1; |
|
264 ResourceMark rm; |
|
265 char* buf = NEW_RESOURCE_ARRAY(char, len); |
|
266 if (buf == NULL) { |
|
267 return -1; |
|
268 } |
|
269 |
|
270 assert(_shdr_string_table != NULL, "Section header string table should be loaded"); |
|
271 ElfStringTable* const table = _shdr_string_table; |
|
272 MarkedFileReader mfd(fd()); |
|
273 if (!mfd.has_mark() || !mfd.set_position(_elfHdr.e_shoff)) return -1; |
|
274 |
|
275 int sect_index = -1; |
|
276 for (int index = 0; index < _elfHdr.e_shnum; index ++) { |
|
277 if (!mfd.read((void*)&hdr, sizeof(hdr))) { |
|
278 break; |
|
279 } |
|
280 if (table->string_at(hdr.sh_name, buf, len)) { |
|
281 if (strncmp(buf, name, len) == 0) { |
|
282 sect_index = index; |
|
283 break; |
162 } |
284 } |
163 if (m_elfHdr.e_shstrndx != SHN_UNDEF && shdr.sh_type == SHT_PROGBITS) { |
285 } |
164 ElfStringTable* string_table = get_string_table(m_elfHdr.e_shstrndx); |
286 } |
165 if (string_table == NULL) { |
287 return sect_index; |
166 m_status = NullDecoder::file_invalid; |
|
167 return false; |
|
168 } |
|
169 char buf[8]; // '8' is enough because we only want to read ".opd" |
|
170 if (string_table->string_at(shdr.sh_name, buf, sizeof(buf)) && !strncmp(".opd", buf, 4)) { |
|
171 m_funcDesc_table = new (std::nothrow) ElfFuncDescTable(m_file, shdr, index); |
|
172 if (m_funcDesc_table == NULL) { |
|
173 m_status = NullDecoder::out_of_memory; |
|
174 return false; |
|
175 } |
|
176 break; |
|
177 } |
|
178 } |
|
179 } |
|
180 #endif |
|
181 |
|
182 } |
|
183 return true; |
|
184 } |
288 } |
185 |
289 |
186 bool ElfFile::decode(address addr, char* buf, int buflen, int* offset) { |
290 bool ElfFile::decode(address addr, char* buf, int buflen, int* offset) { |
187 // something already went wrong, just give up |
291 // something already went wrong, just give up |
188 if (NullDecoder::is_error(m_status)) { |
292 if (NullDecoder::is_error(_status)) { |
189 return false; |
293 return false; |
190 } |
294 } |
191 ElfSymbolTable* symbol_table = m_symbol_tables; |
295 |
192 int string_table_index; |
296 int string_table_index; |
193 int pos_in_string_table; |
297 int pos_in_string_table; |
194 int off = INT_MAX; |
298 int off = INT_MAX; |
195 bool found_symbol = false; |
299 bool found_symbol = false; |
|
300 ElfSymbolTable* symbol_table = _symbol_tables; |
|
301 |
196 while (symbol_table != NULL) { |
302 while (symbol_table != NULL) { |
197 if (symbol_table->lookup(addr, &string_table_index, &pos_in_string_table, &off, m_funcDesc_table)) { |
303 if (symbol_table->lookup(addr, &string_table_index, &pos_in_string_table, &off, _funcDesc_table)) { |
198 found_symbol = true; |
304 found_symbol = true; |
199 break; |
305 break; |
200 } |
306 } |
201 symbol_table = symbol_table->m_next; |
307 symbol_table = symbol_table->next(); |
202 } |
308 } |
203 if (!found_symbol) return false; |
309 if (!found_symbol) { |
|
310 return false; |
|
311 } |
204 |
312 |
205 ElfStringTable* string_table = get_string_table(string_table_index); |
313 ElfStringTable* string_table = get_string_table(string_table_index); |
206 |
314 |
207 if (string_table == NULL) { |
315 if (string_table == NULL) { |
208 m_status = NullDecoder::file_invalid; |
316 _status = NullDecoder::file_invalid; |
209 return false; |
317 return false; |
210 } |
318 } |
211 if (offset) *offset = off; |
319 if (offset) *offset = off; |
212 |
320 |
213 return string_table->string_at(pos_in_string_table, buf, buflen); |
321 return string_table->string_at(pos_in_string_table, buf, buflen); |
214 } |
322 } |
215 |
323 |
216 |
|
217 void ElfFile::add_symbol_table(ElfSymbolTable* table) { |
324 void ElfFile::add_symbol_table(ElfSymbolTable* table) { |
218 if (m_symbol_tables == NULL) { |
325 if (_symbol_tables == NULL) { |
219 m_symbol_tables = table; |
326 _symbol_tables = table; |
220 } else { |
327 } else { |
221 table->m_next = m_symbol_tables; |
328 table->set_next(_symbol_tables); |
222 m_symbol_tables = table; |
329 _symbol_tables = table; |
223 } |
330 } |
224 } |
331 } |
225 |
332 |
226 void ElfFile::add_string_table(ElfStringTable* table) { |
333 void ElfFile::add_string_table(ElfStringTable* table) { |
227 if (m_string_tables == NULL) { |
334 if (_string_tables == NULL) { |
228 m_string_tables = table; |
335 _string_tables = table; |
229 } else { |
336 } else { |
230 table->m_next = m_string_tables; |
337 table->set_next(_string_tables); |
231 m_string_tables = table; |
338 _string_tables = table; |
232 } |
339 } |
233 } |
340 } |
234 |
341 |
235 ElfStringTable* ElfFile::get_string_table(int index) { |
342 ElfStringTable* ElfFile::get_string_table(int index) { |
236 ElfStringTable* p = m_string_tables; |
343 ElfStringTable* p = _string_tables; |
237 while (p != NULL) { |
344 while (p != NULL) { |
238 if (p->index() == index) return p; |
345 if (p->index() == index) return p; |
239 p = p->m_next; |
346 p = p->next(); |
240 } |
347 } |
241 return NULL; |
348 return NULL; |
242 } |
349 } |
243 |
350 |
244 #ifdef LINUX |
|
245 bool ElfFile::specifies_noexecstack(const char* filepath) { |
|
246 // Returns true if the elf file is marked NOT to require an executable stack, |
|
247 // or if the file could not be opened. |
|
248 // Returns false if the elf file requires an executable stack, the stack flag |
|
249 // is not set at all, or if the file can not be read. |
|
250 if (filepath == NULL) return true; |
|
251 |
|
252 FILE* file = fopen(filepath, "r"); |
|
253 if (file == NULL) return true; |
|
254 |
|
255 // AARCH64 defaults to noexecstack. All others default to execstack. |
|
256 #ifdef AARCH64 |
|
257 bool result = true; |
|
258 #else |
|
259 bool result = false; |
|
260 #endif |
|
261 |
|
262 // Read file header |
|
263 Elf_Ehdr head; |
|
264 if (fread(&head, sizeof(Elf_Ehdr), 1, file) == 1 && |
|
265 is_elf_file(head) && |
|
266 fseek(file, head.e_phoff, SEEK_SET) == 0) { |
|
267 |
|
268 // Read program header table |
|
269 Elf_Phdr phdr; |
|
270 for (int index = 0; index < head.e_phnum; index ++) { |
|
271 if (fread((void*)&phdr, sizeof(Elf_Phdr), 1, file) != 1) { |
|
272 result = false; |
|
273 break; |
|
274 } |
|
275 if (phdr.p_type == PT_GNU_STACK) { |
|
276 result = (phdr.p_flags == (PF_R | PF_W)); |
|
277 break; |
|
278 } |
|
279 } |
|
280 } |
|
281 fclose(file); |
|
282 return result; |
|
283 } |
|
284 #endif // LINUX |
|
285 |
|
286 #endif // !_WINDOWS && !__APPLE__ |
351 #endif // !_WINDOWS && !__APPLE__ |