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