• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /* Copyright (C) 2007-2010 The Android Open Source Project
2 **
3 ** This software is licensed under the terms of the GNU General Public
4 ** License version 2, as published by the Free Software Foundation, and
5 ** may be copied, distributed, and modified under those terms.
6 **
7 ** This program is distributed in the hope that it will be useful,
8 ** but WITHOUT ANY WARRANTY; without even the implied warranty of
9 ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
10 ** GNU General Public License for more details.
11 */
12 
13 /*
14  * Contains implementation of ElfFile classes that encapsulate an ELF file.
15  */
16 
17 #include "string.h"
18 #include "elf_file.h"
19 #include "elf_alloc.h"
20 #include "dwarf_cu.h"
21 #include "dwarf_utils.h"
22 
23 #include <fcntl.h>
24 #ifndef O_BINARY
25 #define O_BINARY 0
26 #endif
27 
28 /* Tags to parse when collecting info about routines. */
29 static const Dwarf_Tag parse_rt_tags[] = {
30   DW_TAG_compile_unit,
31   DW_TAG_partial_unit,
32   DW_TAG_inlined_subroutine,
33   DW_TAG_subprogram,
34   0
35 };
36 static const DwarfParseContext parse_rt_context = { parse_rt_tags };
37 
38 //=============================================================================
39 // Base ElfFile implementation
40 //=============================================================================
41 
ElfFile()42 ElfFile::ElfFile()
43     : fixed_base_address_(0),
44       elf_handle_((MapFile*)-1),
45       elf_file_path_(NULL),
46       allocator_(NULL),
47       sec_table_(NULL),
48       sec_count_(0),
49       sec_entry_size_(0),
50       last_cu_(NULL),
51       cu_count_(0),
52       is_exec_(0) {
53 }
54 
~ElfFile()55 ElfFile::~ElfFile() {
56   DwarfCU* cu_to_del = last_cu_;
57   while (cu_to_del != NULL) {
58     DwarfCU* next_cu_to_del = cu_to_del->prev_cu_;
59     delete cu_to_del;
60     cu_to_del = next_cu_to_del;
61   }
62 
63   if (mapfile_is_valid(elf_handle_)) {
64     mapfile_close(elf_handle_);
65   }
66 
67   if (elf_file_path_ != NULL) {
68     delete[] elf_file_path_;
69   }
70 
71   if (sec_table_ != NULL) {
72     delete[] reinterpret_cast<Elf_Byte*>(sec_table_);
73   }
74 
75   /* Must be deleted last! */
76   if (allocator_ != NULL) {
77     delete allocator_;
78   }
79 }
80 
Create(const char * path)81 ElfFile* ElfFile::Create(const char* path) {
82   ElfFile* ret = NULL;
83   /* Allocate enough space on the stack to fit the largest ELF file header. */
84   Elf64_FHdr header;
85   const Elf_CommonHdr* elf_hdr = &header.common;
86 
87   assert(path != NULL && *path != '\0');
88   if (path == NULL || *path == '\0') {
89     _set_errno(EINVAL);
90     return NULL;
91   }
92 
93   /*
94    * Open ELF file, and read its header (the largest one possible).
95    */
96   MapFile* file_handle = mapfile_open(path, O_RDONLY | O_BINARY, 0);
97   if (!mapfile_is_valid(file_handle)) {
98     return NULL;
99   }
100   const ssize_t read_bytes = mapfile_read(file_handle, &header, sizeof(header));
101   mapfile_close(file_handle);
102   assert(read_bytes != -1 && read_bytes == sizeof(header));
103   if (read_bytes == -1 || read_bytes != sizeof(header)) {
104     if (read_bytes != -1) {
105       _set_errno(EINVAL);
106     }
107     return NULL;
108   }
109 
110   /* Lets see if this is an ELF file at all. */
111   if (memcmp(elf_hdr->e_ident, ELFMAG, SELFMAG) != 0) {
112     /* File is not an ELF file. */
113     _set_errno(ENOEXEC);
114     return NULL;
115   }
116 
117   /* Lets check ELF's "bitness". */
118   assert(elf_hdr->ei_info.ei_class == ELFCLASS32 ||
119          elf_hdr->ei_info.ei_class == ELFCLASS64);
120   if (elf_hdr->ei_info.ei_class != ELFCLASS32 &&
121       elf_hdr->ei_info.ei_class != ELFCLASS64) {
122     /* Neither 32, or 64-bit ELF file. Something wrong here. */
123     _set_errno(EBADF);
124     return NULL;
125   }
126 
127   /* Lets instantiate appropriate ElfFileImpl object for this ELF. */
128   if (elf_hdr->ei_info.ei_class == ELFCLASS32) {
129     ret = new ElfFileImpl<Elf32_Addr, Elf32_Off>;
130   } else {
131     ret = new ElfFileImpl<Elf64_Addr, Elf64_Off>;
132   }
133   assert(ret != NULL);
134   if (ret != NULL) {
135     if (!ret->initialize(elf_hdr, path)) {
136       delete ret;
137       ret = NULL;
138     }
139   } else {
140     _set_errno(ENOMEM);
141   }
142 
143   return ret;
144 }
145 
initialize(const Elf_CommonHdr * elf_hdr,const char * path)146 bool ElfFile::initialize(const Elf_CommonHdr* elf_hdr, const char* path) {
147   /* Must be created first! */
148   allocator_ = new ElfAllocator();
149   assert(allocator_ != NULL);
150   if (allocator_ == NULL) {
151     _set_errno(ENOMEM);
152     return false;
153   }
154 
155   /* Copy file path. */
156   size_t path_len = strlen(path) + 1;
157   elf_file_path_ = new char[path_len];
158   assert(elf_file_path_ != NULL);
159   if (elf_file_path_ == NULL) {
160     _set_errno(ENOMEM);
161     return false;
162   }
163   memcpy(elf_file_path_, path, path_len);
164 
165   /* Cache some basic ELF properties. */
166   is_ELF_64_ = elf_hdr->ei_info.ei_class == ELFCLASS64;
167   is_elf_big_endian_ = elf_hdr->ei_info.ei_data == ELFDATA2MSB;
168   same_endianness_ = is_elf_little_endian() == is_little_endian_cpu();
169   is_exec_ = elf_hdr->e_type == 2;
170 
171   /* Reopen file for further reads and mappings. */
172   elf_handle_ = mapfile_open(elf_file_path_, O_RDONLY | O_BINARY, 0);
173   return mapfile_is_valid(elf_handle_);
174 }
175 
get_pc_address_info(Elf_Xword address,Elf_AddressInfo * address_info)176 bool ElfFile::get_pc_address_info(Elf_Xword address,
177                                   Elf_AddressInfo* address_info) {
178   assert(address_info != NULL);
179   if (address_info == NULL) {
180     _set_errno(EINVAL);
181     return false;
182   }
183 
184   /* Collect routine information for all CUs in this file. */
185   if (parse_compilation_units(&parse_rt_context) == -1) {
186     return false;
187   }
188 
189   /* Iterate through the collected CUs looking for the one that
190    * contains the given address. */
191   address_info->inline_stack = NULL;
192   DwarfCU* cu = last_cu();
193   while (cu != NULL) {
194     /* Find a leaf DIE object in the current CU that contains the address. */
195     Dwarf_AddressInfo info;
196     info.die_obj = cu->get_leaf_die_for_address(address);
197     if (info.die_obj != NULL) {
198       /* Convert the address to a location inside source file. */
199       if (cu->get_pc_address_file_info(address, &info)) {
200           /* Copy location information to the returning structure. */
201           address_info->file_name = info.file_name;
202           address_info->dir_name = info.dir_name;
203           address_info->line_number = info.line_number;
204       } else {
205           address_info->file_name = NULL;
206           address_info->dir_name = NULL;
207           address_info->line_number = 0;
208       }
209 
210       /* Lets see if the DIE represents a routine (rather than
211        * a lexical block, for instance). */
212       Dwarf_Tag tag = info.die_obj->get_tag();
213       while (!dwarf_tag_is_routine(tag)) {
214         /* This is not a routine DIE. Lets loop trhough the parents of that
215          * DIE looking for the first routine DIE. */
216         info.die_obj = info.die_obj->parent_die();
217         if (info.die_obj == NULL) {
218           /* Reached compilation unit DIE. Can't go any further. */
219           address_info->routine_name = "<unknown>";
220           return true;
221         }
222         tag = info.die_obj->get_tag();
223       }
224 
225       /* Save name of the routine that contains the address. */
226       address_info->routine_name = info.die_obj->get_name();
227       if (address_info->routine_name == NULL) {
228         /* In some cases (minimum debugging info in the file) routine
229          * name may be not avaible. We, however, are obliged by API
230          * considerations to return something in this field. */
231           address_info->routine_name = "<unknown>";
232       }
233 
234       /* Lets see if address belongs to an inlined routine. */
235       if (tag != DW_TAG_inlined_subroutine) {
236         address_info->inline_stack = NULL;
237         return true;
238       }
239 
240       /*
241        * Address belongs to an inlined routine. Create inline stack.
242        */
243 
244       /* Allocate inline stack array big enough to fit all parent entries. */
245       address_info->inline_stack =
246         new Elf_InlineInfo[info.die_obj->get_level() + 1];
247       assert(address_info->inline_stack != NULL);
248       if (address_info->inline_stack == NULL) {
249         _set_errno(ENOMEM);
250         return false;
251       }
252       memset(address_info->inline_stack, 0,
253              sizeof(Elf_InlineInfo) * (info.die_obj->get_level() + 1));
254 
255       /* Reverse DIEs filling in inline stack entries for inline
256        * routine tags. */
257       int inl_index = 0;
258       do {
259         /* Save source file information. */
260         DIEAttrib file_desc;
261         if (info.die_obj->get_attrib(DW_AT_call_file, &file_desc)) {
262           const Dwarf_STMTL_FileDesc* desc =
263               cu->get_stmt_file_info(file_desc.value()->u32);
264           if (desc != NULL) {
265             address_info->inline_stack[inl_index].inlined_in_file =
266                 desc->file_name;
267             address_info->inline_stack[inl_index].inlined_in_file_dir =
268                 cu->get_stmt_dir_name(desc->get_dir_index());
269           }
270         }
271         if (address_info->inline_stack[inl_index].inlined_in_file == NULL) {
272           address_info->inline_stack[inl_index].inlined_in_file = "<unknown>";
273           address_info->inline_stack[inl_index].inlined_in_file_dir = NULL;
274         }
275 
276         /* Save source line information. */
277         if (info.die_obj->get_attrib(DW_AT_call_line, &file_desc)) {
278           address_info->inline_stack[inl_index].inlined_at_line = file_desc.value()->u32;
279         }
280 
281         /* Advance DIE to the parent routine, and save its name. */
282         info.die_obj = info.die_obj->parent_die();
283         assert(info.die_obj != NULL);
284         if (info.die_obj != NULL) {
285           tag = info.die_obj->get_tag();
286           while (!dwarf_tag_is_routine(tag)) {
287             info.die_obj = info.die_obj->parent_die();
288             if (info.die_obj == NULL) {
289               break;
290             }
291             tag = info.die_obj->get_tag();
292           }
293           if (info.die_obj != NULL) {
294             address_info->inline_stack[inl_index].routine_name =
295                 info.die_obj->get_name();
296           }
297         }
298         if (address_info->inline_stack[inl_index].routine_name == NULL) {
299           address_info->inline_stack[inl_index].routine_name = "<unknown>";
300         }
301 
302         /* Continue with the parent DIE. */
303         inl_index++;
304       } while (info.die_obj != NULL && tag == DW_TAG_inlined_subroutine);
305 
306       return true;
307     }
308     cu = cu->prev_cu();
309   }
310 
311   return false;
312 }
313 
free_pc_address_info(Elf_AddressInfo * address_info) const314 void ElfFile::free_pc_address_info(Elf_AddressInfo* address_info) const {
315   assert(address_info != NULL);
316   if (address_info != NULL && address_info->inline_stack != NULL) {
317     delete address_info->inline_stack;
318     address_info->inline_stack = NULL;
319   }
320 }
321 
322 //=============================================================================
323 // ElfFileImpl
324 //=============================================================================
325 
326 template <typename Elf_Addr, typename Elf_Off>
initialize(const Elf_CommonHdr * elf_hdr,const char * path)327 bool ElfFileImpl<Elf_Addr, Elf_Off>::initialize(const Elf_CommonHdr* elf_hdr,
328                                                 const char* path) {
329   /* Must be called first! */
330   if (!ElfFile::initialize(elf_hdr, path)) {
331     return false;
332   }
333 
334   /* Cache some header data, so later we can discard the header. */
335   const Elf_FHdr<Elf_Addr, Elf_Off>* header =
336       reinterpret_cast<const Elf_FHdr<Elf_Addr, Elf_Off>*>(elf_hdr);
337   sec_count_ = pull_val(header->e_shnum);
338   sec_entry_size_ = pull_val(header->e_shentsize);
339   fixed_base_address_ = pull_val(header->e_entry) & ~0xFFF;
340 
341   /* Cache section table (must have one!) */
342   const Elf_Off sec_table_off = pull_val(header->e_shoff);
343   assert(sec_table_off != 0 && sec_count_ != 0);
344   if (sec_table_off == 0 || sec_count_ == 0) {
345     _set_errno(EBADF);
346     return false;
347   }
348   const size_t sec_table_size = sec_count_ * sec_entry_size_;
349   sec_table_ = new Elf_Byte[sec_table_size];
350   assert(sec_table_ != NULL);
351   if (sec_table_ == NULL) {
352     _set_errno(ENOMEM);
353     return false;
354   }
355   if (mapfile_read_at(elf_handle_, sec_table_off, sec_table_,
356                       sec_table_size) < 0) {
357       return false;
358   }
359 
360   /* Map ELF's string section (must have one!). */
361   const Elf_Half str_sec_index = pull_val(header->e_shstrndx);
362   assert(str_sec_index != SHN_UNDEF);
363   if (str_sec_index == SHN_UNDEF) {
364     _set_errno(EBADF);
365     return false;
366   }
367   const Elf_SHdr<Elf_Addr, Elf_Off>* str_sec =
368       reinterpret_cast<const Elf_SHdr<Elf_Addr, Elf_Off>*>
369           (get_section_by_index(str_sec_index));
370   assert(str_sec != NULL);
371   if (str_sec == NULL) {
372     _set_errno(EBADF);
373     return false;
374   }
375   if (!string_section_.map(elf_handle_, pull_val(str_sec->sh_offset),
376                            pull_val(str_sec->sh_size))) {
377     return false;
378   }
379 
380   /* Lets determine DWARF format. According to the docs, DWARF is 64 bit, if
381    * first 4 bytes in the compilation unit header are set to 0xFFFFFFFF.
382    * .debug_info section of the ELF file begins with the first CU header. */
383   if (!map_section_by_name(".debug_info", &debug_info_)) {
384     _set_errno(EBADF);
385     return false;
386   }
387 
388   /* Note that we don't care about endianness here, since 0xFFFFFFFF is an
389    * endianness-independent value, so we don't have to pull_val here. */
390   is_DWARF_64_ =
391     *reinterpret_cast<const Elf_Word*>(debug_info_.data()) == 0xFFFFFFFF;
392 
393   return true;
394 }
395 
396 template <typename Elf_Addr, typename Elf_Off>
parse_compilation_units(const DwarfParseContext * parse_context)397 int ElfFileImpl<Elf_Addr, Elf_Off>::parse_compilation_units(
398     const DwarfParseContext* parse_context) {
399   /* Lets see if we already parsed the file. */
400   if (last_cu() != NULL) {
401     return cu_count_;
402   }
403 
404   /* Cache sections required for this parsing. */
405   if (!map_section_by_name(".debug_abbrev", &debug_abbrev_) ||
406       !map_section_by_name(".debug_ranges", &debug_ranges_) ||
407       !map_section_by_name(".debug_line", &debug_line_) ||
408       !map_section_by_name(".debug_str", &debug_str_)) {
409     _set_errno(EBADF);
410     return false;
411   }
412 
413   /* .debug_info section opens with the first CU header. */
414   const void* next_cu = debug_info_.data();
415 
416   /* Iterate through CUs until we reached the end of .debug_info section, or
417    * advanced to a CU with zero size, indicating the end of CU list for this
418    * file. */
419   while (is_valid_cu(next_cu)) {
420     /* Instatiate CU, depending on DWARF "bitness". */
421     DwarfCU* cu = DwarfCU::create_instance(this, next_cu);
422     if (cu == NULL) {
423       _set_errno(ENOMEM);
424       return -1;
425     }
426 
427     if (cu->parse(parse_context, &next_cu)) {
428       cu->set_prev_cu(last_cu_);
429       last_cu_ = cu;
430       cu_count_++;
431     } else {
432       delete cu;
433       return -1;
434     }
435   };
436 
437   return cu_count_;
438 }
439 
440 template <typename Elf_Addr, typename Elf_Off>
get_section_info_by_name(const char * name,Elf_Off * offset,Elf_Word * size)441 bool ElfFileImpl<Elf_Addr, Elf_Off>::get_section_info_by_name(const char* name,
442                                                               Elf_Off* offset,
443                                                               Elf_Word* size) {
444   const Elf_SHdr<Elf_Addr, Elf_Off>* cur_section =
445       reinterpret_cast<const Elf_SHdr<Elf_Addr, Elf_Off>*>(sec_table_);
446 
447   for (Elf_Half sec = 0; sec < sec_count_; sec++) {
448     const char* sec_name = get_str_sec_str(pull_val(cur_section->sh_name));
449     if (sec_name != NULL && strcmp(name, sec_name) == 0) {
450       *offset = pull_val(cur_section->sh_offset);
451       *size = pull_val(cur_section->sh_size);
452       return true;
453     }
454     cur_section = reinterpret_cast<const Elf_SHdr<Elf_Addr, Elf_Off>*>
455                                   (INC_CPTR(cur_section, sec_entry_size_));
456   }
457   _set_errno(EINVAL);
458   return false;
459 }
460 
461 template <typename Elf_Addr, typename Elf_Off>
map_section_by_name(const char * name,ElfMappedSection * section)462 bool ElfFileImpl<Elf_Addr, Elf_Off>::map_section_by_name(
463     const char* name,
464     ElfMappedSection* section) {
465   if (section->is_mapped()) {
466     return true;
467   }
468 
469   Elf_Off offset;
470   Elf_Word size;
471   if (!get_section_info_by_name(name, &offset, &size)) {
472     return false;
473   }
474 
475   return section->map(elf_handle_, offset, size);
476 }
477