1 /* 2 3 Copyright (C) 2000, 2002 Silicon Graphics, Inc. All Rights Reserved. 4 5 This program is free software; you can redistribute it and/or modify it 6 under the terms of version 2.1 of the GNU Lesser General Public License 7 as published by the Free Software Foundation. 8 9 This program is distributed in the hope that it would be useful, but 10 WITHOUT ANY WARRANTY; without even the implied warranty of 11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 12 13 Further, this software is distributed without any warranty that it is 14 free of the rightful claim of any third person regarding infringement 15 or the like. Any license provided herein, whether implied or 16 otherwise, applies only to this software file. Patent licenses, if 17 any, provided herein do not apply to combinations of this program with 18 other software, or any other product whatsoever. 19 20 You should have received a copy of the GNU Lesser General Public 21 License along with this program; if not, write the Free Software 22 Foundation, Inc., 59 Temple Place - Suite 330, Boston MA 02111-1307, 23 USA. 24 25 Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pky, 26 Mountain View, CA 94043, or: 27 28 http://www.sgi.com 29 30 For further information regarding this notice, see: 31 32 http://oss.sgi.com/projects/GenInfo/NoticeExplan 33 34 */ 35 36 37 38 #include "config.h" 39 #include "dwarf_incl.h" 40 #include <stdio.h> 41 #include <limits.h> 42 #include "dwarf_macro.h" 43 44 45 #define LEFTPAREN '(' 46 #define RIGHTPAREN ')' 47 #define SPACE ' ' 48 49 /* 50 Given the dwarf macro string, return a pointer to 51 the value. Returns pointer to 0 byte at end of string 52 if no value found (meaning the value is the empty string). 53 54 Only understands well-formed dwarf macinfo strings. 55 */ 56 char * 57 dwarf_find_macro_value_start(char *str) 58 { 59 char *lcp; 60 int funclike = 0; 61 62 for (lcp = str; *lcp; ++lcp) { 63 switch (*lcp) { 64 case LEFTPAREN: 65 funclike = 1; 66 break; 67 case RIGHTPAREN: 68 /* lcp+1 must be a space, and following char is the value */ 69 return lcp + 2; 70 case SPACE: 71 /* we allow extraneous spaces inside macro parameter ** 72 list, just in case... This is not really needed. */ 73 if (!funclike) { 74 return lcp + 1; 75 } 76 break; 77 } 78 } 79 /* never found value: returns pointer to the 0 byte at end of 80 string */ 81 return lcp; 82 83 } 84 85 86 /* 87 Try to keep fileindex correct in every Macro_Details 88 record by tracking file starts and ends. 89 Uses high water mark: space reused, not freed. 90 Presumption is that this makes sense for most uses. 91 STARTERMAX is set so that the array need not be expanded for 92 most files: it is the initial include file depth. 93 */ 94 static Dwarf_Signed *st_base; 95 static long max; 96 static long next_to_use; 97 static int was_fault = 0; 98 99 #define STARTERMAX 10 100 static void 101 _dwarf_reset_index_stack(void) 102 { 103 next_to_use = 0; 104 was_fault = 0; 105 } 106 static int 107 _dwarf_mac_push_index(Dwarf_Debug dbg, Dwarf_Signed indx) 108 { 109 Dwarf_Signed *newbase; 110 111 if (next_to_use >= max) { 112 long new_size; 113 114 if (max == 0) { 115 max = STARTERMAX; 116 } 117 new_size = max * 2; 118 newbase = 119 _dwarf_get_alloc(dbg, DW_DLA_STRING, 120 new_size * sizeof(Dwarf_Signed)); 121 if (newbase == 0) { 122 /* just leave the old array in place */ 123 was_fault = 1; 124 return DW_DLV_ERROR; 125 } 126 memcpy(newbase, st_base, next_to_use * sizeof(Dwarf_Signed)); 127 dwarf_dealloc(dbg, st_base, DW_DLA_STRING); 128 st_base = newbase; 129 max = new_size; 130 } 131 st_base[next_to_use] = indx; 132 ++next_to_use; 133 return DW_DLV_OK; 134 } 135 static Dwarf_Signed 136 _dwarf_mac_pop_index(void) 137 { 138 if (was_fault) { 139 return -1; 140 } 141 if (next_to_use > 0) { 142 next_to_use--; 143 return (*(st_base + next_to_use)); 144 } 145 return -1; 146 } 147 148 /* starting at macro_offset in .debug_macinfo, 149 if maximum_count is 0, treat as if it is infinite. 150 get macro data up thru 151 maximum_count entries or the end of a compilation 152 unit's entries (whichever comes first). 153 */ 154 155 int 156 dwarf_get_macro_details(Dwarf_Debug dbg, 157 Dwarf_Off macro_offset, 158 Dwarf_Unsigned maximum_count, 159 Dwarf_Signed * entry_count, 160 Dwarf_Macro_Details ** details, 161 Dwarf_Error * error) 162 { 163 Dwarf_Small *macro_base; 164 Dwarf_Small *pnext; 165 Dwarf_Unsigned endloc; 166 unsigned char uc; 167 unsigned long depth; 168 169 int res; 170 171 /* count space used by strings */ 172 unsigned long str_space = 0; 173 int done = 0; 174 unsigned long space_needed; 175 unsigned long string_offset; 176 Dwarf_Small *return_data; 177 Dwarf_Small *pdata; 178 unsigned long final_count = 0; 179 Dwarf_Signed fileindex = -1; 180 Dwarf_Small *latest_str_loc; 181 182 unsigned long count; 183 unsigned long max_count = (unsigned long) maximum_count; 184 185 _dwarf_reset_index_stack(); 186 if (dbg == NULL) { 187 _dwarf_error(NULL, error, DW_DLE_DBG_NULL); 188 return (DW_DLV_ERROR); 189 } 190 191 res = 192 _dwarf_load_section(dbg, 193 dbg->de_debug_macinfo_index, 194 &dbg->de_debug_macinfo, 195 error); 196 if (res != DW_DLV_OK) { 197 return res; 198 } 199 200 macro_base = dbg->de_debug_macinfo; 201 if (macro_base == NULL) { 202 return (DW_DLV_NO_ENTRY); 203 } 204 if (macro_offset >= dbg->de_debug_macinfo_size) { 205 return (DW_DLV_NO_ENTRY); 206 } 207 208 pnext = macro_base + macro_offset; 209 if (maximum_count == 0) { 210 max_count = ULONG_MAX; 211 } 212 213 214 /* how many entries and how much space will they take? */ 215 216 endloc = (pnext - macro_base); 217 if (endloc >= dbg->de_debug_macinfo_size) { 218 if (endloc == dbg->de_debug_macinfo_size) { 219 /* normal: found last entry */ 220 return DW_DLV_NO_ENTRY; 221 } 222 _dwarf_error(dbg, error, DW_DLE_DEBUG_MACRO_LENGTH_BAD); 223 return (DW_DLV_ERROR); 224 } 225 for (count = 0; !done && count < max_count; ++count) { 226 unsigned long slen; 227 Dwarf_Word len; 228 229 uc = *pnext; 230 ++pnext; /* get past the type code */ 231 switch (uc) { 232 case DW_MACINFO_define: 233 case DW_MACINFO_undef: 234 /* line, string */ 235 case DW_MACINFO_vendor_ext: 236 /* number, string */ 237 (void) _dwarf_decode_u_leb128(pnext, &len); 238 239 pnext += len; 240 if (((pnext - macro_base)) >= dbg->de_debug_macinfo_size) { 241 _dwarf_error(dbg, error, 242 DW_DLE_DEBUG_MACRO_INCONSISTENT); 243 return (DW_DLV_ERROR); 244 } 245 slen = strlen((char *) pnext) + 1; 246 pnext += slen; 247 if (((pnext - macro_base)) >= dbg->de_debug_macinfo_size) { 248 _dwarf_error(dbg, error, 249 DW_DLE_DEBUG_MACRO_INCONSISTENT); 250 return (DW_DLV_ERROR); 251 } 252 str_space += slen; 253 break; 254 case DW_MACINFO_start_file: 255 /* line, file index */ 256 (void) _dwarf_decode_u_leb128(pnext, &len); 257 pnext += len; 258 if (((pnext - macro_base)) >= dbg->de_debug_macinfo_size) { 259 _dwarf_error(dbg, error, 260 DW_DLE_DEBUG_MACRO_INCONSISTENT); 261 return (DW_DLV_ERROR); 262 } 263 (void) _dwarf_decode_u_leb128(pnext, &len); 264 pnext += len; 265 if (((pnext - macro_base)) >= dbg->de_debug_macinfo_size) { 266 _dwarf_error(dbg, error, 267 DW_DLE_DEBUG_MACRO_INCONSISTENT); 268 return (DW_DLV_ERROR); 269 } 270 ++depth; 271 break; 272 273 case DW_MACINFO_end_file: 274 if (--depth == 0) { 275 done = 1; 276 } 277 break; /* no string or number here */ 278 case 0: 279 /* end of cu's entries */ 280 done = 1; 281 break; 282 default: 283 _dwarf_error(dbg, error, DW_DLE_DEBUG_MACRO_INCONSISTENT); 284 return (DW_DLV_ERROR); 285 /* bogus macinfo! */ 286 } 287 288 endloc = (pnext - macro_base); 289 if (endloc == dbg->de_debug_macinfo_size) { 290 done = 1; 291 } else if (endloc > dbg->de_debug_macinfo_size) { 292 _dwarf_error(dbg, error, DW_DLE_DEBUG_MACRO_LENGTH_BAD); 293 return (DW_DLV_ERROR); 294 } 295 } 296 if (count == 0) { 297 _dwarf_error(dbg, error, DW_DLE_DEBUG_MACRO_INTERNAL_ERR); 298 return (DW_DLV_ERROR); 299 } 300 301 /* we have 'count' array entries to allocate and str_space bytes of 302 string space to provide for. */ 303 304 string_offset = count * sizeof(Dwarf_Macro_Details); 305 306 /* extra 2 not really needed */ 307 space_needed = string_offset + str_space + 2; 308 return_data = pdata = 309 _dwarf_get_alloc(dbg, DW_DLA_STRING, space_needed); 310 latest_str_loc = pdata + string_offset; 311 if (pdata == 0) { 312 _dwarf_error(dbg, error, DW_DLE_DEBUG_MACRO_MALLOC_SPACE); 313 return (DW_DLV_ERROR); 314 } 315 pnext = macro_base + macro_offset; 316 317 done = 0; 318 319 for (final_count = 0; !done && final_count < count; ++final_count) { 320 unsigned long slen; 321 Dwarf_Word len; 322 Dwarf_Unsigned v1; 323 Dwarf_Macro_Details *pdmd = (Dwarf_Macro_Details *) (pdata + 324 final_count 325 * 326 sizeof 327 (Dwarf_Macro_Details)); 328 329 endloc = (pnext - macro_base); 330 if (endloc > dbg->de_debug_macinfo_size) { 331 _dwarf_error(dbg, error, DW_DLE_DEBUG_MACRO_LENGTH_BAD); 332 return (DW_DLV_ERROR); 333 } 334 uc = *pnext; 335 pdmd->dmd_offset = (pnext - macro_base); 336 pdmd->dmd_type = uc; 337 pdmd->dmd_fileindex = fileindex; 338 pdmd->dmd_lineno = 0; 339 pdmd->dmd_macro = 0; 340 ++pnext; /* get past the type code */ 341 switch (uc) { 342 case DW_MACINFO_define: 343 case DW_MACINFO_undef: 344 /* line, string */ 345 case DW_MACINFO_vendor_ext: 346 /* number, string */ 347 v1 = _dwarf_decode_u_leb128(pnext, &len); 348 pdmd->dmd_lineno = v1; 349 350 pnext += len; 351 if (((pnext - macro_base)) >= dbg->de_debug_macinfo_size) { 352 _dwarf_error(dbg, error, 353 DW_DLE_DEBUG_MACRO_INCONSISTENT); 354 return (DW_DLV_ERROR); 355 } 356 slen = strlen((char *) pnext) + 1; 357 strcpy((char *) latest_str_loc, (char *) pnext); 358 pdmd->dmd_macro = (char *) latest_str_loc; 359 latest_str_loc += slen; 360 pnext += slen; 361 if (((pnext - macro_base)) >= dbg->de_debug_macinfo_size) { 362 _dwarf_error(dbg, error, 363 DW_DLE_DEBUG_MACRO_INCONSISTENT); 364 return (DW_DLV_ERROR); 365 } 366 str_space += slen; 367 break; 368 case DW_MACINFO_start_file: 369 /* line, file index */ 370 v1 = _dwarf_decode_u_leb128(pnext, &len); 371 pdmd->dmd_lineno = v1; 372 pnext += len; 373 if (((pnext - macro_base)) >= dbg->de_debug_macinfo_size) { 374 _dwarf_error(dbg, error, 375 DW_DLE_DEBUG_MACRO_INCONSISTENT); 376 return (DW_DLV_ERROR); 377 } 378 v1 = _dwarf_decode_u_leb128(pnext, &len); 379 pdmd->dmd_fileindex = v1; 380 (void) _dwarf_mac_push_index(dbg, fileindex); 381 /* we ignore the error, we just let fileindex ** be -1 when 382 we pop this one */ 383 fileindex = v1; 384 pnext += len; 385 if (((pnext - macro_base)) >= dbg->de_debug_macinfo_size) { 386 _dwarf_error(dbg, error, 387 DW_DLE_DEBUG_MACRO_INCONSISTENT); 388 return (DW_DLV_ERROR); 389 } 390 break; 391 392 case DW_MACINFO_end_file: 393 fileindex = _dwarf_mac_pop_index(); 394 break; /* no string or number here */ 395 case 0: 396 /* end of cu's entries */ 397 done = 1; 398 break; 399 default: 400 _dwarf_error(dbg, error, DW_DLE_DEBUG_MACRO_INCONSISTENT); 401 return (DW_DLV_ERROR); 402 /* bogus macinfo! */ 403 } 404 } 405 *entry_count = count; 406 *details = (Dwarf_Macro_Details *) return_data; 407 408 return DW_DLV_OK; 409 } 410