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