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