1 /* 2 Copyright (C) 2016-2019 David Anderson. All Rights Reserved. 3 4 This program is free software; you can redistribute it and/or modify it 5 under the terms of version 2.1 of the GNU Lesser General Public License 6 as published by the Free Software Foundation. 7 8 This program is distributed in the hope that it would be useful, but 9 WITHOUT ANY WARRANTY; without even the implied warranty of 10 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 11 12 Further, this software is distributed without any warranty that it is 13 free of the rightful claim of any third person regarding infringement 14 or the like. Any license provided herein, whether implied or 15 otherwise, applies only to this software file. Patent licenses, if 16 any, provided herein do not apply to combinations of this program with 17 other software, or any other product whatsoever. 18 19 You should have received a copy of the GNU Lesser General Public 20 License along with this program; if not, write the Free Software 21 Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston MA 02110-1301, 22 USA. 23 24 */ 25 26 #include "config.h" 27 #include <stdio.h> 28 #ifdef HAVE_STDLIB_H 29 #include <stdlib.h> 30 #endif 31 #ifdef HAVE_MALLOC_H 32 /* Useful include for some Windows compilers. */ 33 #include <malloc.h> 34 #endif /* HAVE_MALLOC_H */ 35 #include "dwarf_incl.h" 36 #include "dwarf_alloc.h" 37 #include "dwarf_error.h" 38 #include "dwarf_util.h" 39 #include "dwarf_dsc.h" 40 41 #define FALSE 0 42 #define TRUE 1 43 44 /* When called with ary and *arraycount 0 45 this just counts the elements found. 46 Otherwise it records the values in ary and 47 recounts. The arraycount pointer must be 48 passed-in non-null always. */ 49 static int 50 get_dsc_leb_entries(Dwarf_Debug dbg, 51 Dwarf_Small * blockpointer, 52 Dwarf_Unsigned blocklen, 53 int dounsigned, 54 struct Dwarf_Dsc_Entry_s *ary, 55 size_t * arraycount, 56 Dwarf_Error * error) 57 { 58 Dwarf_Small *p = blockpointer; 59 Dwarf_Small *endp = blockpointer + blocklen; 60 size_t larraycount = 0; 61 size_t iarraycount = *arraycount; 62 63 if (!ary) { 64 if (iarraycount) { 65 /* Internal botch calling this static function. */ 66 _dwarf_error(dbg, error, DW_DLE_DISCR_ARRAY_ERROR); 67 return DW_DLV_ERROR; 68 } 69 } else { 70 if (!iarraycount) { 71 /* Internal botch calling this static function. */ 72 _dwarf_error(dbg, error, DW_DLE_DISCR_ARRAY_ERROR); 73 return DW_DLV_ERROR; 74 } 75 } 76 if (dounsigned) { 77 while (p < endp) { 78 Dwarf_Unsigned dsc = 0; 79 Dwarf_Unsigned low = 0; 80 Dwarf_Unsigned high = 0; 81 UNUSEDARG Dwarf_Unsigned leblen = 0; 82 83 if (ary && (larraycount >= iarraycount)) { 84 _dwarf_error(dbg, error, DW_DLE_DISCR_ARRAY_ERROR); 85 return DW_DLV_ERROR; 86 } 87 DECODE_LEB128_UWORD_LEN_CK(p,dsc, 88 leblen,dbg,error,endp); 89 if (!dsc) { 90 DECODE_LEB128_UWORD_LEN_CK(p,low, 91 leblen, dbg,error,endp); 92 } else { 93 DECODE_LEB128_UWORD_LEN_CK(p,low, 94 leblen, dbg,error,endp); 95 DECODE_LEB128_UWORD_LEN_CK(p,high, 96 leblen, dbg,error,endp); 97 } 98 if(ary) { 99 struct Dwarf_Dsc_Entry_s *arye = 100 ary+larraycount; 101 102 /* type reads the same as uleb and leb because 103 it is only zero or one. */ 104 arye->dsc_type = dsc; 105 arye->dsc_low_u = low; 106 arye->dsc_high_u = high; 107 } 108 larraycount++; 109 } 110 } else { 111 while (p < endp) { 112 Dwarf_Signed dsc = 0; 113 Dwarf_Signed low = 0; 114 Dwarf_Signed high = 0; 115 UNUSEDARG Dwarf_Unsigned leblen = 0; 116 117 if (ary && (larraycount >= iarraycount)) { 118 _dwarf_error(dbg, error, DW_DLE_DISCR_ARRAY_ERROR); 119 return DW_DLV_ERROR; 120 } 121 DECODE_LEB128_SWORD_LEN_CK(p,dsc, 122 leblen,dbg,error,endp); 123 if (!dsc) { 124 DECODE_LEB128_SWORD_LEN_CK(p,low, 125 leblen,dbg,error,endp); 126 } else { 127 DECODE_LEB128_SWORD_LEN_CK(p,low, 128 leblen,dbg,error,endp); 129 DECODE_LEB128_SWORD_LEN_CK(p,high, 130 leblen,dbg,error,endp); 131 } 132 if(ary) { 133 struct Dwarf_Dsc_Entry_s *arye = 134 ary+larraycount; 135 136 /* type reads the same as uleb and leb because 137 it is only zero or one. */ 138 arye->dsc_type = (Dwarf_Unsigned)dsc; 139 arye->dsc_low_s = low; 140 arye->dsc_high_s = high; 141 } 142 larraycount++; 143 } 144 } 145 if (ary) { 146 /* Just verify this recount matches original */ 147 if(iarraycount != larraycount) { 148 _dwarf_error(dbg, error, DW_DLE_DISCR_ARRAY_ERROR); 149 return DW_DLV_ERROR; 150 } 151 } else { 152 /* This matters for first call with 153 ary 0 and iarraycount 0 as we are generating the 154 count. */ 155 *arraycount = larraycount; 156 } 157 return DW_DLV_OK; 158 } 159 160 161 int dwarf_discr_list(Dwarf_Debug dbg, 162 Dwarf_Small * blockpointer, 163 Dwarf_Unsigned blocklen, 164 Dwarf_Dsc_Head * dsc_head_out, 165 Dwarf_Unsigned * dsc_array_length_out, 166 Dwarf_Error * error) 167 { 168 Dwarf_Dsc_Head h = 0; 169 int res = 0; 170 size_t arraycount = 0; 171 struct Dwarf_Dsc_Entry_s *ary = 0; 172 Dwarf_Small * dscblockp = 0; 173 Dwarf_Unsigned dscblocklen = 0; 174 175 if (!dbg){ 176 _dwarf_error(NULL, error, DW_DLE_DBG_NULL); \ 177 return DW_DLV_ERROR; 178 } 179 if (blocklen == 0) { 180 return DW_DLV_NO_ENTRY; 181 } 182 dscblockp = (Dwarf_Small *)calloc(blocklen,sizeof(Dwarf_Small)); 183 if(!dscblockp) { 184 _dwarf_error(dbg, error, DW_DLE_ALLOC_FAIL); 185 return DW_DLV_ERROR; 186 } 187 dscblocklen = blocklen; 188 memcpy(dscblockp,blockpointer,blocklen); 189 190 res = get_dsc_leb_entries(dbg,dscblockp,dscblocklen, 191 /* TRUE or FALSE here is not important, the arraycount 192 returned to us will be identical either way. */ 193 FALSE, 0, &arraycount,error); 194 if (res != DW_DLV_OK) { 195 free(dscblockp); 196 return res; 197 } 198 199 h = (Dwarf_Dsc_Head)_dwarf_get_alloc(dbg,DW_DLA_DSC_HEAD,1); 200 if(!h) { 201 free(dscblockp); 202 _dwarf_error(dbg, error, DW_DLE_ALLOC_FAIL); 203 return DW_DLV_ERROR; 204 } 205 206 h->dsh_block = dscblockp; 207 h->dsh_block_len = dscblocklen; 208 h->dsh_debug = dbg; 209 /* Now the destructor for h will deal with block malloc space. */ 210 211 ary = (struct Dwarf_Dsc_Entry_s *)calloc(arraycount, 212 sizeof(struct Dwarf_Dsc_Entry_s)); 213 if(!ary) { 214 dwarf_dealloc(dbg,h,DW_DLA_DSC_HEAD); 215 _dwarf_error(dbg, error, DW_DLE_ALLOC_FAIL); 216 return DW_DLV_ERROR; 217 } 218 h->dsh_count = arraycount; 219 h->dsh_array = ary; 220 h->dsh_set_unsigned = 0; 221 h->dsh_set_signed = 0; 222 223 *dsc_head_out = h; 224 *dsc_array_length_out = arraycount; 225 return DW_DLV_OK; 226 } 227 228 /* NEW September 2016. Allows easy access to DW_AT_discr_list 229 entry. Callers must know which is the appropriate 230 one of the following two interfaces, though both 231 will work. */ 232 int dwarf_discr_entry_u(Dwarf_Dsc_Head dsh , 233 Dwarf_Unsigned entrynum, 234 Dwarf_Half * out_type, 235 Dwarf_Unsigned * out_discr_low, 236 Dwarf_Unsigned * out_discr_high, 237 UNUSEDARG Dwarf_Error * error) 238 { 239 struct Dwarf_Dsc_Entry_s *dse = 0; 240 241 if (entrynum >= dsh->dsh_count) { 242 return DW_DLV_NO_ENTRY; 243 } 244 if (!dsh->dsh_set_unsigned) { 245 int res =0; 246 int dounsigned = 1; 247 size_t count = dsh->dsh_count; 248 249 res = get_dsc_leb_entries(dsh->dsh_debug, 250 dsh->dsh_block, 251 dsh->dsh_block_len, 252 dounsigned, 253 dsh->dsh_array, 254 &count, 255 error); 256 if (res != DW_DLV_OK) { 257 return res; 258 } 259 dsh->dsh_set_unsigned = TRUE; 260 } 261 if (!dsh->dsh_array) { 262 _dwarf_error(dsh->dsh_debug, error, DW_DLE_DISCR_ARRAY_ERROR); 263 return DW_DLV_ERROR; 264 } 265 dse = dsh->dsh_array + entrynum; 266 *out_type = dse->dsc_type; 267 *out_discr_low = dse->dsc_low_u; 268 *out_discr_high = dse->dsc_high_u; 269 return DW_DLV_OK; 270 } 271 272 /* NEW September 2016. Allows easy access to DW_AT_discr_list 273 entry. */ 274 int dwarf_discr_entry_s(Dwarf_Dsc_Head dsh, 275 Dwarf_Unsigned entrynum, 276 Dwarf_Half * out_type, 277 Dwarf_Signed * out_discr_low, 278 Dwarf_Signed * out_discr_high, 279 UNUSEDARG Dwarf_Error * error) 280 { 281 struct Dwarf_Dsc_Entry_s *dse = 0; 282 283 if (entrynum >= dsh->dsh_count) { 284 return DW_DLV_NO_ENTRY; 285 } 286 if (!dsh->dsh_set_signed) { 287 int res =0; 288 int dounsigned = 0; 289 size_t count = dsh->dsh_count; 290 291 res = get_dsc_leb_entries(dsh->dsh_debug, 292 dsh->dsh_block, 293 dsh->dsh_block_len, 294 dounsigned, 295 dsh->dsh_array, 296 &count, 297 error); 298 if (res != DW_DLV_OK) { 299 return res; 300 } 301 dsh->dsh_set_signed = TRUE; 302 } 303 if (!dsh->dsh_array) { 304 _dwarf_error(dsh->dsh_debug, error, DW_DLE_DISCR_ARRAY_ERROR); 305 return DW_DLV_ERROR; 306 } 307 dse = dsh->dsh_array + entrynum; 308 *out_type = dse->dsc_type; 309 *out_discr_low = dse->dsc_low_s; 310 *out_discr_high = dse->dsc_high_s; 311 return DW_DLV_OK; 312 } 313 314 void 315 _dwarf_dsc_destructor(void *m) 316 { 317 Dwarf_Dsc_Head h = (Dwarf_Dsc_Head) m; 318 319 free(h->dsh_array); 320 h->dsh_array = 0; 321 free(h->dsh_block); 322 h->dsh_block = 0; 323 h->dsh_count = 0; 324 } 325