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 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 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 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 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 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 314 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> 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> 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> 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> 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