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 implementations of classes defined for a variety of DWARF objects. 15 */ 16 17 #include <stdio.h> 18 #define __STDC_FORMAT_MACROS 1 19 #include <inttypes.h> 20 #include "dwarf_die.h" 21 #include "dwarf_cu.h" 22 #include "dwarf_utils.h" 23 #include "elf_file.h" 24 25 DIEObject::~DIEObject() { 26 /* Delete all children of this object. */ 27 DIEObject* to_del = last_child(); 28 while (to_del != NULL) { 29 DIEObject* next = to_del->prev_sibling(); 30 delete to_del; 31 to_del = next; 32 } 33 } 34 35 ElfFile* DIEObject::elf_file() const { 36 return parent_cu()->elf_file(); 37 } 38 39 Dwarf_Tag DIEObject::get_tag() const { 40 Dwarf_Tag tag; 41 return advance(NULL, &tag) != NULL ? tag : 0; 42 } 43 44 const char* DIEObject::get_name() const { 45 DIEAttrib die_attr; 46 /* Start with the obvious. */ 47 if (get_attrib(DW_AT_name, &die_attr)) { 48 return die_attr.value()->str; 49 } 50 51 /* Lets see if there is a reference to the abstract origin, or specification, 52 * and use its name as the name for this DIE. */ 53 if (get_attrib(DW_AT_abstract_origin, &die_attr) || 54 get_attrib(DW_AT_specification, &die_attr)) { 55 DIEObject* org_die_obj = 56 parent_cu()->get_referenced_die_object(die_attr.value()->u32); 57 if (org_die_obj != NULL) { 58 return org_die_obj->get_name(); 59 } 60 } 61 62 /* Lets see if there is a reference to the type DIE, and use 63 * its name as the name for this DIE. */ 64 if (get_attrib(DW_AT_type, &die_attr)) { 65 DIEObject* org_die_obj = 66 parent_cu()->get_referenced_die_object(die_attr.value()->u32); 67 if (org_die_obj != NULL) { 68 return org_die_obj->get_name(); 69 } 70 } 71 72 /* Can't figure the name for this DIE. */ 73 return NULL; 74 } 75 76 bool DIEObject::get_attrib(Dwarf_At at_id, DIEAttrib* attr) const { 77 const Dwarf_Abbr_AT* at_abbr; 78 79 /* Advance to DIE attributes. */ 80 const Elf_Byte* die_attr = advance(&at_abbr, NULL); 81 if (die_attr == NULL) { 82 _set_errno(EINVAL); 83 return false; 84 } 85 86 /* Loop through all DIE attributes, looking for the one that's being 87 * requested. */ 88 while (!at_abbr->is_separator()) { 89 at_abbr = at_abbr->process(&attr->at_, &attr->form_); 90 die_attr = parent_cu()->process_attrib(die_attr, attr->form_, &attr->value_); 91 if (at_id == attr->at()) { 92 return true; 93 } 94 } 95 96 _set_errno(EINVAL); 97 98 return false; 99 } 100 101 DIEObject* DIEObject::get_leaf_for_address(Elf_Xword address) { 102 const bool contains = parent_cu()->is_CU_address_64() ? 103 contains_address<Elf_Xword>(address) : 104 contains_address<Elf_Word>(address); 105 if (!contains && !is_cu_die()) { 106 /* For CU DIEs address range may be zero size, even though its child DIEs 107 * occupie some address space. So, if CU DIE's address range doesn't 108 * contain the given address, we still want to go and check the children. 109 */ 110 _set_errno(EINVAL); 111 return NULL; 112 } 113 114 /* This DIE contains given address (or may contain it, if this is a CU DIE). 115 * Lets iterate through child DIEs to find the leaf (last DIE) that contains 116 * this address. */ 117 DIEObject* child = last_child(); 118 while (child != NULL) { 119 DIEObject* leaf = child->get_leaf_for_address(address); 120 if (leaf != NULL) { 121 return leaf; 122 } 123 child = child->prev_sibling(); 124 } 125 /* No child DIE contains this address. This DIE is the leaf. */ 126 return contains || !is_cu_die() ? this : NULL; 127 } 128 129 template <typename AddrType> 130 bool DIEObject::contains_address(Elf_Xword address) { 131 DIEAttrib die_ranges; 132 /* DIE can contain either list of ranges (f.i. DIEs that represent a routine 133 * that is inlined in multiple places will contain list of address ranges 134 * where that routine is inlined), or a pair "low PC, and high PC" describing 135 * contiguos address space where routine has been placed by compiler. */ 136 if (get_attrib(DW_AT_ranges, &die_ranges)) { 137 /* Iterate through this DIE's ranges list, looking for the one that 138 * contains the given address. */ 139 AddrType low; 140 AddrType high; 141 Elf_Word range_off = die_ranges.value()->u32; 142 while (elf_file()->get_range(range_off, &low, &high) && 143 (low != 0 || high != 0)) { 144 if (address >= low && address < high) { 145 return true; 146 } 147 range_off += sizeof(AddrType) * 2; 148 } 149 return false; 150 } else { 151 /* This DIE doesn't have ranges. Lets see if it has low_pc and high_pc 152 * attributes. */ 153 DIEAttrib low_pc; 154 DIEAttrib high_pc; 155 if (!get_attrib(DW_AT_low_pc, &low_pc) || 156 !get_attrib(DW_AT_high_pc, &high_pc) || 157 address < low_pc.value()->u64 || 158 address >= high_pc.value()->u64) { 159 return false; 160 } 161 return true; 162 } 163 } 164 165 DIEObject* DIEObject::find_die_object(const Dwarf_DIE* die_to_find) { 166 if (die_to_find == die()) { 167 return this; 168 } 169 170 /* First we will iterate through the list of children, since chances to 171 * find requested DIE decrease as we go deeper into DIE tree. */ 172 DIEObject* iter = last_child(); 173 while (iter != NULL) { 174 if (iter->die() == die_to_find) { 175 return iter; 176 } 177 iter = iter->prev_sibling(); 178 }; 179 180 /* DIE has not been found among the children. Lets go deeper now. */ 181 iter = last_child(); 182 while (iter != NULL) { 183 DIEObject* ret = iter->find_die_object(die_to_find); 184 if (ret != NULL) { 185 return ret; 186 } 187 iter = iter->prev_sibling(); 188 } 189 190 _set_errno(EINVAL); 191 return NULL; 192 } 193 194 void DIEObject::dump(bool only_this) const { 195 const Dwarf_Abbr_AT* at_abbr; 196 Dwarf_Tag tag; 197 198 const Elf_Byte* die_attr = advance(&at_abbr, &tag); 199 if (die_attr != NULL) { 200 printf("\n********** DIE[%p(%04X)] %s: %s **********\n", 201 die_, parent_cu()->get_die_reference(die_), dwarf_tag_name(tag), 202 get_name()); 203 204 /* Dump this DIE attributes. */ 205 while (!at_abbr->is_separator()) { 206 DIEAttrib attr; 207 at_abbr = at_abbr->process(&attr.at_, &attr.form_); 208 die_attr = parent_cu()->process_attrib(die_attr, attr.form(), &attr.value_); 209 dump_attrib(attr.at(), attr.form(), attr.value()); 210 if (attr.at() == DW_AT_ranges) { 211 /* Dump all ranges for this DIE. */ 212 Elf_Word off = attr.value()->u32; 213 if (parent_cu()->is_CU_address_64()) { 214 Elf_Xword low, high; 215 while (elf_file()->get_range<Elf_Xword>(off, &low, &high) && 216 (low != 0 || high != 0)) { 217 printf(" %08" PRIX64 " - %08" PRIX64 "\n", 218 low, high); 219 off += 16; 220 } 221 } else { 222 Elf_Word low, high; 223 while (elf_file()->get_range<Elf_Word>(off, &low, &high) && 224 (low != 0 || high != 0)) { 225 printf(" %08X - %08X\n", 226 low, high); 227 off += 8; 228 } 229 } 230 } 231 } 232 } 233 234 if (only_this) { 235 if (parent_die_ != NULL && !parent_die_->is_cu_die()) { 236 printf("\n-----------> CHILD OF:\n"); 237 parent_die_->dump(true); 238 } 239 } else { 240 /* Dump this DIE's children. */ 241 if (last_child() != NULL) { 242 last_child()->dump(false); 243 } 244 245 /* Dump this DIE's siblings. */ 246 if (prev_sibling() != NULL) { 247 prev_sibling()->dump(false); 248 } 249 } 250 } 251 252 const Elf_Byte* DIEObject::advance(const Dwarf_Abbr_AT** at_abbr, 253 Dwarf_Tag* tag) const { 254 Dwarf_AbbrNum abbr_num; 255 Dwarf_Tag die_tag; 256 257 const Elf_Byte* die_attr = die()->process(&abbr_num); 258 const Dwarf_Abbr_DIE* abbr = parent_cu()->get_die_abbr(abbr_num); 259 if (abbr == NULL) { 260 return NULL; 261 } 262 263 const Dwarf_Abbr_AT* attrib_abbr = abbr->process(NULL, &die_tag); 264 if (at_abbr != NULL) { 265 *at_abbr = attrib_abbr; 266 } 267 if (tag != NULL) { 268 *tag = die_tag; 269 } 270 return die_attr; 271 } 272