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 }
184 ELFMAG3 == hdr.e_ident[EI_MAG3] &&
185 ELFCLASSNONE != hdr.e_ident[EI_CLASS] &&
186 ELFDATANONE != hdr.e_ident[EI_DATA]);
187 }
188
189 NullDecoder::decoder_status ElfFile::load_tables() {
190 assert(_file, "file not open");
191 assert(!NullDecoder::is_error(_status), "already in error");
192
193 FileReader freader(fd());
194 // read elf file header
195 if (!freader.read(&_elfHdr, sizeof(_elfHdr))) {
196 return NullDecoder::file_invalid;
197 }
198
199 // Check signature
200 if (!is_elf_file(_elfHdr)) {
201 return NullDecoder::file_invalid;
202 }
203
204 // walk elf file's section headers, and load string tables
205 Elf_Shdr shdr;
206 if (!freader.set_position(_elfHdr.e_shoff)) {
207 return NullDecoder::file_invalid;
208 }
209
210 for (int index = 0; index < _elfHdr.e_shnum; index ++) {
211 if (!freader.read(&shdr, sizeof(shdr))) {
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;
220 }
221 if (index == _elfHdr.e_shstrndx) {
222 assert(_shdr_string_table == NULL, "Only set once");
223 _shdr_string_table = table;
224 } else {
225 add_string_table(table);
226 }
227 } else if (shdr.sh_type == SHT_SYMTAB || shdr.sh_type == SHT_DYNSYM) {
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 }
236 #if defined(PPC64) && !defined(ABI_ELFv2)
237 // Now read the .opd section wich contains the PPC64 function descriptor table.
238 // The .opd section is only available on PPC64 (see for example:
239 // http://refspecs.linuxfoundation.org/LSB_3.1.1/LSB-Core-PPC64/LSB-Core-PPC64/specialsections.html)
240 // so this code should do no harm on other platforms but because of performance reasons we only
241 // execute it on PPC64 platforms.
242 // Notice that we can only find the .opd section after we have successfully read in the string
243 // tables in the previous loop, because we need to query the name of each section which is
244 // contained in one of the string tables (i.e. the one with the index m_elfHdr.e_shstrndx).
245
246 // Reset the file pointer
247 int sect_index = section_by_name(".opd", shdr);
248
249 if (sect_index == -1) {
250 return NullDecoder::file_invalid;
251 }
252
253 _funcDesc_table = new (std::nothrow) ElfFuncDescTable(_file, shdr, sect_index);
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;
284 }
285 }
286 }
287 return sect_index;
288 }
289
290 bool ElfFile::decode(address addr, char* buf, int buflen, int* offset) {
291 // something already went wrong, just give up
292 if (NullDecoder::is_error(_status)) {
293 return false;
294 }
295
296 int string_table_index;
297 int pos_in_string_table;
298 int off = INT_MAX;
299 bool found_symbol = false;
300 ElfSymbolTable* symbol_table = _symbol_tables;
301
302 while (symbol_table != NULL) {
303 if (symbol_table->lookup(addr, &string_table_index, &pos_in_string_table, &off, _funcDesc_table)) {
304 found_symbol = true;
305 break;
306 }
307 symbol_table = symbol_table->next();
308 }
309 if (!found_symbol) {
310 return false;
|
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, bool load_debug_info) :
109 _string_tables(NULL), _symbol_tables(NULL), _funcDesc_table(NULL),
110 _next(NULL), _status(NullDecoder::no_error), _debuginfo(NULL),
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 // See if we should try to load external debug info
125 if (_status == NullDecoder::no_debug_symbols && load_debug_info) {
126 log_debug(decoder)("No debug symbols in %s, trying external debuginfo", _filepath);
127 _debuginfo = load_debuginfo();
128 }
129
130 if (NullDecoder::is_error(_status)) {
131 // Not be able to decode, cleanup
132 cleanup_tables();
133 } else {
134 log_debug(decoder)("%s contains debug symbols", _filepath);
135 // No longer need section header string table, which is not used for decoding
136 if (_shdr_string_table != NULL) {
137 delete _shdr_string_table;
138 _shdr_string_table = NULL;
139 }
140 }
141 }
142
143 ElfFile::~ElfFile() {
144 if (_shdr_string_table != NULL) {
145 delete _shdr_string_table;
146 }
147
148 cleanup_tables();
149
150 if (_file != NULL) {
151 fclose(_file);
152 }
153
154 if (_filepath != NULL) {
155 os::free((void*)_filepath);
156 }
157
158 if (_next != NULL) {
159 delete _next;
160 }
196 ELFMAG3 == hdr.e_ident[EI_MAG3] &&
197 ELFCLASSNONE != hdr.e_ident[EI_CLASS] &&
198 ELFDATANONE != hdr.e_ident[EI_DATA]);
199 }
200
201 NullDecoder::decoder_status ElfFile::load_tables() {
202 assert(_file, "file not open");
203 assert(!NullDecoder::is_error(_status), "already in error");
204
205 FileReader freader(fd());
206 // read elf file header
207 if (!freader.read(&_elfHdr, sizeof(_elfHdr))) {
208 return NullDecoder::file_invalid;
209 }
210
211 // Check signature
212 if (!is_elf_file(_elfHdr)) {
213 return NullDecoder::file_invalid;
214 }
215
216 // test if the file contains debug symbols
217 NullDecoder::decoder_status stat = NullDecoder::no_debug_symbols;
218
219 // walk elf file's section headers, and load string tables
220 Elf_Shdr shdr;
221 if (!freader.set_position(_elfHdr.e_shoff)) {
222 return NullDecoder::file_invalid;
223 }
224
225 for (int index = 0; index < _elfHdr.e_shnum; index ++) {
226 if (!freader.read(&shdr, sizeof(shdr))) {
227 return NullDecoder::file_invalid;
228 }
229
230 if (shdr.sh_type == SHT_STRTAB) {
231 // string tables
232 ElfStringTable* table = new (std::nothrow) ElfStringTable(fd(), shdr, index);
233 if (table == NULL) {
234 return NullDecoder::out_of_memory;
235 }
236 if (index == _elfHdr.e_shstrndx) {
237 assert(_shdr_string_table == NULL, "Only set once");
238 _shdr_string_table = table;
239 } else {
240 add_string_table(table);
241 }
242 } else if (shdr.sh_type == SHT_SYMTAB || shdr.sh_type == SHT_DYNSYM) {
243 // symbol tables
244 ElfSymbolTable* table = new (std::nothrow) ElfSymbolTable(fd(), shdr);
245 if (table == NULL) {
246 return NullDecoder::out_of_memory;
247 }
248 // see if we have debug symbols
249 if (shdr.sh_type == SHT_SYMTAB) {
250 stat = NullDecoder::no_error;
251 }
252 add_symbol_table(table);
253 }
254 }
255 #if defined(PPC64) && !defined(ABI_ELFv2)
256 // Now read the .opd section wich contains the PPC64 function descriptor table.
257 // The .opd section is only available on PPC64 (see for example:
258 // http://refspecs.linuxfoundation.org/LSB_3.1.1/LSB-Core-PPC64/LSB-Core-PPC64/specialsections.html)
259 // so this code should do no harm on other platforms but because of performance reasons we only
260 // execute it on PPC64 platforms.
261 // Notice that we can only find the .opd section after we have successfully read in the string
262 // tables in the previous loop, because we need to query the name of each section which is
263 // contained in one of the string tables (i.e. the one with the index m_elfHdr.e_shstrndx).
264
265 // Reset the file pointer
266 int sect_index = section_by_name(".opd", shdr);
267
268 if (sect_index == -1) {
269 return NullDecoder::file_invalid;
270 }
271
272 _funcDesc_table = new (std::nothrow) ElfFuncDescTable(_file, shdr, sect_index);
273 if (_funcDesc_table == NULL) {
274 return NullDecoder::out_of_memory;
275 }
276 #endif
277 return stat;
278 }
279
280 int ElfFile::section_by_name(const char* name, Elf_Shdr& hdr) {
281 assert(name != NULL, "No section name");
282 size_t len = strlen(name) + 1;
283 ResourceMark rm;
284 char* buf = NEW_RESOURCE_ARRAY(char, len);
285 if (buf == NULL) {
286 return -1;
287 }
288
289 assert(_shdr_string_table != NULL, "Section header string table should be loaded");
290 ElfStringTable* const table = _shdr_string_table;
291 MarkedFileReader mfd(fd());
292 if (!mfd.has_mark() || !mfd.set_position(_elfHdr.e_shoff)) return -1;
293
294 int sect_index = -1;
295 for (int index = 0; index < _elfHdr.e_shnum; index ++) {
296 if (!mfd.read((void*)&hdr, sizeof(hdr))) {
297 break;
298 }
299 if (table->string_at(hdr.sh_name, buf, len)) {
300 if (strncmp(buf, name, len) == 0) {
301 sect_index = index;
302 break;
303 }
304 }
305 }
306 return sect_index;
307 }
308
309 bool ElfFile::decode(address addr, char* buf, int buflen, int* offset) {
310 if (_debuginfo != NULL) {
311 return _debuginfo->decode(addr, buf, buflen, offset);
312 } else {
313 return decode_impl(addr, buf, buflen, offset);
314 }
315 }
316
317 bool ElfFile::decode_impl(address addr, char* buf, int buflen, int* offset) {
318 // something already went wrong, just give up
319 if (NullDecoder::is_error(_status)) {
320 return false;
321 }
322
323 int string_table_index;
324 int pos_in_string_table;
325 int off = INT_MAX;
326 bool found_symbol = false;
327 ElfSymbolTable* symbol_table = _symbol_tables;
328
329 while (symbol_table != NULL) {
330 if (symbol_table->lookup(addr, &string_table_index, &pos_in_string_table, &off, _funcDesc_table)) {
331 found_symbol = true;
332 break;
333 }
334 symbol_table = symbol_table->next();
335 }
336 if (!found_symbol) {
337 return false;
|