1 /*- 2 * Copyright (c) 2009 Kai Wang 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * 14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24 * SUCH DAMAGE. 25 */ 26 27 #include "_libdwarf.h" 28 29 ELFTC_VCSID("$Id: dwarf_loclist.c 2074 2011-10-27 03:34:33Z jkoshy $"); 30 31 int 32 dwarf_loclist_n(Dwarf_Attribute at, Dwarf_Locdesc ***llbuf, 33 Dwarf_Signed *listlen, Dwarf_Error *error) 34 { 35 Dwarf_Loclist ll; 36 Dwarf_Debug dbg; 37 int ret; 38 39 dbg = at != NULL ? at->at_die->die_dbg : NULL; 40 41 if (at == NULL || llbuf == NULL || listlen == NULL) { 42 DWARF_SET_ERROR(dbg, error, DW_DLE_ARGUMENT); 43 return (DW_DLV_ERROR); 44 } 45 46 switch (at->at_attrib) { 47 case DW_AT_location: 48 case DW_AT_string_length: 49 case DW_AT_return_addr: 50 case DW_AT_data_member_location: 51 case DW_AT_frame_base: 52 case DW_AT_segment: 53 case DW_AT_static_link: 54 case DW_AT_use_location: 55 case DW_AT_vtable_elem_location: 56 switch (at->at_form) { 57 case DW_FORM_data4: 58 case DW_FORM_data8: 59 /* 60 * DW_FORM_data[48] can not be used as section offset 61 * since DWARF4. For DWARF[23], the application needs 62 * to determine if DW_FORM_data[48] is representing 63 * a constant or a section offset. 64 */ 65 if (at->at_die->die_cu->cu_version >= 4) { 66 DWARF_SET_ERROR(dbg, error, DW_DLE_NO_ENTRY); 67 return (DW_DLV_NO_ENTRY); 68 } 69 /* FALLTHROUGH */ 70 case DW_FORM_sec_offset: 71 ret = _dwarf_loclist_find(dbg, at->at_die->die_cu, 72 at->u[0].u64, &ll, error); 73 if (ret == DW_DLE_NO_ENTRY) { 74 DWARF_SET_ERROR(dbg, error, ret); 75 return (DW_DLV_NO_ENTRY); 76 } 77 if (ret != DW_DLE_NONE) 78 return (DW_DLV_ERROR); 79 *llbuf = ll->ll_ldlist; 80 *listlen = ll->ll_ldlen; 81 return (DW_DLV_OK); 82 case DW_FORM_block: 83 case DW_FORM_block1: 84 case DW_FORM_block2: 85 case DW_FORM_block4: 86 if (at->at_ld == NULL) { 87 ret = _dwarf_loc_add(at->at_die, at, error); 88 if (ret != DW_DLE_NONE) 89 return (DW_DLV_ERROR); 90 } 91 *llbuf = &at->at_ld; 92 *listlen = 1; 93 return (DW_DLV_OK); 94 default: 95 /* Malformed Attr? */ 96 DWARF_SET_ERROR(dbg, error, DW_DLE_ATTR_FORM_BAD); 97 return (DW_DLV_NO_ENTRY); 98 } 99 default: 100 /* Wrong attr supplied. */ 101 DWARF_SET_ERROR(dbg, error, DW_DLE_ARGUMENT); 102 return (DW_DLV_ERROR); 103 } 104 } 105 106 int 107 dwarf_loclist(Dwarf_Attribute at, Dwarf_Locdesc **llbuf, 108 Dwarf_Signed *listlen, Dwarf_Error *error) 109 { 110 Dwarf_Loclist ll; 111 Dwarf_Debug dbg; 112 int ret; 113 114 dbg = at != NULL ? at->at_die->die_dbg : NULL; 115 116 if (at == NULL || llbuf == NULL || listlen == NULL) { 117 DWARF_SET_ERROR(dbg, error, DW_DLE_ARGUMENT); 118 return (DW_DLV_ERROR); 119 } 120 121 switch (at->at_attrib) { 122 case DW_AT_location: 123 case DW_AT_string_length: 124 case DW_AT_return_addr: 125 case DW_AT_data_member_location: 126 case DW_AT_frame_base: 127 case DW_AT_segment: 128 case DW_AT_static_link: 129 case DW_AT_use_location: 130 case DW_AT_vtable_elem_location: 131 switch (at->at_form) { 132 case DW_FORM_data4: 133 case DW_FORM_data8: 134 /* 135 * DW_FORM_data[48] can not be used as section offset 136 * since DWARF4. For DWARF[23], the application needs 137 * to determine if DW_FORM_data[48] is representing 138 * a constant or a section offset. 139 */ 140 if (at->at_die->die_cu->cu_version >= 4) { 141 printf("called cu_version >= 4\n"); 142 DWARF_SET_ERROR(dbg, error, DW_DLE_NO_ENTRY); 143 return (DW_DLV_NO_ENTRY); 144 } 145 /* FALLTHROUGH */ 146 case DW_FORM_sec_offset: 147 ret = _dwarf_loclist_find(at->at_die->die_dbg, 148 at->at_die->die_cu, at->u[0].u64, &ll, error); 149 if (ret == DW_DLE_NO_ENTRY) { 150 DWARF_SET_ERROR(dbg, error, DW_DLV_NO_ENTRY); 151 return (DW_DLV_NO_ENTRY); 152 } 153 if (ret != DW_DLE_NONE) 154 return (DW_DLV_ERROR); 155 *llbuf = ll->ll_ldlist[0]; 156 *listlen = 1; 157 return (DW_DLV_OK); 158 case DW_FORM_block: 159 case DW_FORM_block1: 160 case DW_FORM_block2: 161 case DW_FORM_block4: 162 if (at->at_ld == NULL) { 163 ret = _dwarf_loc_add(at->at_die, at, error); 164 if (ret != DW_DLE_NONE) 165 return (DW_DLV_ERROR); 166 } 167 *llbuf = at->at_ld; 168 *listlen = 1; 169 return (DW_DLV_OK); 170 default: 171 DWARF_SET_ERROR(dbg, error, DW_DLE_ATTR_FORM_BAD); 172 return (DW_DLV_ERROR); 173 } 174 default: 175 /* Wrong attr supplied. */ 176 DWARF_SET_ERROR(dbg, error, DW_DLE_ARGUMENT); 177 return (DW_DLV_ERROR); 178 } 179 } 180 181 int 182 dwarf_get_loclist_entry(Dwarf_Debug dbg, Dwarf_Unsigned offset, 183 Dwarf_Addr *hipc, Dwarf_Addr *lopc, Dwarf_Ptr *data, 184 Dwarf_Unsigned *entry_len, Dwarf_Unsigned *next_entry, 185 Dwarf_Error *error) 186 { 187 Dwarf_Loclist ll, next_ll; 188 Dwarf_Locdesc *ld; 189 Dwarf_Section *ds; 190 int i, ret; 191 192 if (dbg == NULL || hipc == NULL || lopc == NULL || data == NULL || 193 entry_len == NULL || next_entry == NULL) { 194 DWARF_SET_ERROR(dbg, error, DW_DLE_ARGUMENT); 195 return (DW_DLV_ERROR); 196 } 197 198 ret = _dwarf_loclist_find(dbg, STAILQ_FIRST(&dbg->dbg_cu), offset, &ll, 199 error); 200 if (ret == DW_DLE_NO_ENTRY) { 201 DWARF_SET_ERROR(dbg, error, DW_DLV_NO_ENTRY); 202 return (DW_DLV_NO_ENTRY); 203 } else if (ret != DW_DLE_NONE) 204 return (DW_DLV_ERROR); 205 206 *hipc = *lopc = 0; 207 for (i = 0; i < ll->ll_ldlen; i++) { 208 ld = ll->ll_ldlist[i]; 209 if (i == 0) { 210 *hipc = ld->ld_hipc; 211 *lopc = ld->ld_lopc; 212 } else { 213 if (ld->ld_lopc < *lopc) 214 *lopc = ld->ld_lopc; 215 if (ld->ld_hipc > *hipc) 216 *hipc = ld->ld_hipc; 217 } 218 } 219 220 ds = _dwarf_find_section(dbg, ".debug_loc"); 221 assert(ds != NULL); 222 *data = (uint8_t *) ds->ds_data + ll->ll_offset; 223 *entry_len = ll->ll_length; 224 225 next_ll = TAILQ_NEXT(ll, ll_next); 226 if (next_ll != NULL) 227 *next_entry = next_ll->ll_offset; 228 else 229 *next_entry = ds->ds_size; 230 231 return (DW_DLV_OK); 232 } 233 234 int 235 dwarf_loclist_from_expr(Dwarf_Debug dbg, Dwarf_Ptr bytes_in, 236 Dwarf_Unsigned bytes_len, Dwarf_Locdesc **llbuf, Dwarf_Signed *listlen, 237 Dwarf_Error *error) 238 { 239 Dwarf_Locdesc *ld; 240 int ret; 241 242 if (dbg == NULL || bytes_in == NULL || bytes_len == 0 || 243 llbuf == NULL || listlen == NULL) { 244 DWARF_SET_ERROR(dbg, error, DW_DLE_ARGUMENT); 245 return (DW_DLV_ERROR); 246 } 247 248 ret = _dwarf_loc_fill_locexpr(dbg, &ld, bytes_in, bytes_len, 249 dbg->dbg_pointer_size, error); 250 if (ret != DW_DLE_NONE) 251 return (DW_DLV_ERROR); 252 253 *llbuf = ld; 254 *listlen = 1; 255 256 return (DW_DLV_OK); 257 } 258 259 int 260 dwarf_loclist_from_expr_a(Dwarf_Debug dbg, Dwarf_Ptr bytes_in, 261 Dwarf_Unsigned bytes_len, Dwarf_Half addr_size, Dwarf_Locdesc **llbuf, 262 Dwarf_Signed *listlen, Dwarf_Error *error) 263 { 264 Dwarf_Locdesc *ld; 265 int ret; 266 267 if (dbg == NULL || bytes_in == NULL || bytes_len == 0 || 268 llbuf == NULL || listlen == NULL) { 269 DWARF_SET_ERROR(dbg, error, DW_DLE_ARGUMENT); 270 return (DW_DLV_ERROR); 271 } 272 273 if (addr_size != 4 && addr_size != 8) { 274 DWARF_SET_ERROR(dbg, error, DW_DLE_ARGUMENT); 275 return (DW_DLV_ERROR); 276 } 277 278 ret = _dwarf_loc_fill_locexpr(dbg, &ld, bytes_in, bytes_len, addr_size, 279 error); 280 if (ret != DW_DLE_NONE) 281 return (DW_DLV_ERROR); 282 283 *llbuf = ld; 284 *listlen = 1; 285 286 return (DW_DLV_OK); 287 } 288