| File: | src/gnu/usr.bin/binutils-2.17/binutils/rdcoff.c |
| Warning: | line 437, column 12 Assigned value is garbage or undefined |
Press '?' to see keyboard shortcuts
Keyboard shortcuts:
| 1 | /* stabs.c -- Parse COFF debugging information | |||
| 2 | Copyright 1996, 1999, 2000, 2002, 2003 Free Software Foundation, Inc. | |||
| 3 | Written by Ian Lance Taylor <ian@cygnus.com>. | |||
| 4 | ||||
| 5 | This file is part of GNU Binutils. | |||
| 6 | ||||
| 7 | This program is free software; you can redistribute it and/or modify | |||
| 8 | it under the terms of the GNU General Public License as published by | |||
| 9 | the Free Software Foundation; either version 2 of the License, or | |||
| 10 | (at your option) any later version. | |||
| 11 | ||||
| 12 | This program is distributed in the hope that it will be useful, | |||
| 13 | but WITHOUT ANY WARRANTY; without even the implied warranty of | |||
| 14 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||
| 15 | GNU General Public License for more details. | |||
| 16 | ||||
| 17 | You should have received a copy of the GNU General Public License | |||
| 18 | along with this program; if not, write to the Free Software | |||
| 19 | Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA | |||
| 20 | 02110-1301, USA. */ | |||
| 21 | ||||
| 22 | /* This file contains code which parses COFF debugging information. */ | |||
| 23 | ||||
| 24 | #include "bfd.h" | |||
| 25 | #include "coff/internal.h" | |||
| 26 | #include "bucomm.h" | |||
| 27 | #include "libiberty.h" | |||
| 28 | #include "debug.h" | |||
| 29 | #include "budbg.h" | |||
| 30 | ||||
| 31 | /* FIXME: We should not need this BFD internal file. We need it for | |||
| 32 | the N_BTMASK, etc., values. */ | |||
| 33 | #include "libcoff.h" | |||
| 34 | ||||
| 35 | /* These macros extract the right mask and shifts for this BFD. They | |||
| 36 | assume that there is a local variable named ABFD. This is so that | |||
| 37 | macros like ISFCN and DECREF, from coff/internal.h, will work | |||
| 38 | without modification. */ | |||
| 39 | #define N_BTMASK(((abfd)->tdata.coff_obj_data)->local_n_btmask) (coff_data (abfd)((abfd)->tdata.coff_obj_data)->local_n_btmask) | |||
| 40 | #define N_BTSHFT(((abfd)->tdata.coff_obj_data)->local_n_btshft) (coff_data (abfd)((abfd)->tdata.coff_obj_data)->local_n_btshft) | |||
| 41 | #define N_TMASK(((abfd)->tdata.coff_obj_data)->local_n_tmask) (coff_data (abfd)((abfd)->tdata.coff_obj_data)->local_n_tmask) | |||
| 42 | #define N_TSHIFT(((abfd)->tdata.coff_obj_data)->local_n_tshift) (coff_data (abfd)((abfd)->tdata.coff_obj_data)->local_n_tshift) | |||
| 43 | ||||
| 44 | /* This structure is used to hold the symbols, as well as the current | |||
| 45 | location within the symbols. */ | |||
| 46 | ||||
| 47 | struct coff_symbols | |||
| 48 | { | |||
| 49 | /* The symbols. */ | |||
| 50 | asymbol **syms; | |||
| 51 | /* The number of symbols. */ | |||
| 52 | long symcount; | |||
| 53 | /* The index of the current symbol. */ | |||
| 54 | long symno; | |||
| 55 | /* The index of the current symbol in the COFF symbol table (where | |||
| 56 | each auxent counts as a symbol). */ | |||
| 57 | long coff_symno; | |||
| 58 | }; | |||
| 59 | ||||
| 60 | /* The largest basic type we are prepared to handle. */ | |||
| 61 | ||||
| 62 | #define T_MAX(16) (T_LNGDBL16) | |||
| 63 | ||||
| 64 | /* This structure is used to hold slots. */ | |||
| 65 | ||||
| 66 | struct coff_slots | |||
| 67 | { | |||
| 68 | /* Next set of slots. */ | |||
| 69 | struct coff_slots *next; | |||
| 70 | /* Slots. */ | |||
| 71 | #define COFF_SLOTS(16) (16) | |||
| 72 | debug_type slots[COFF_SLOTS(16)]; | |||
| 73 | }; | |||
| 74 | ||||
| 75 | /* This structure is used to map symbol indices to types. */ | |||
| 76 | ||||
| 77 | struct coff_types | |||
| 78 | { | |||
| 79 | /* Slots. */ | |||
| 80 | struct coff_slots *slots; | |||
| 81 | /* Basic types. */ | |||
| 82 | debug_type basic[T_MAX(16) + 1]; | |||
| 83 | }; | |||
| 84 | ||||
| 85 | static debug_type *coff_get_slot (struct coff_types *, int); | |||
| 86 | static debug_type parse_coff_type | |||
| 87 | (bfd *, struct coff_symbols *, struct coff_types *, long, int, | |||
| 88 | union internal_auxent *, bfd_boolean, void *); | |||
| 89 | static debug_type parse_coff_base_type | |||
| 90 | (bfd *, struct coff_symbols *, struct coff_types *, long, int, | |||
| 91 | union internal_auxent *, void *); | |||
| 92 | static debug_type parse_coff_struct_type | |||
| 93 | (bfd *, struct coff_symbols *, struct coff_types *, int, | |||
| 94 | union internal_auxent *, void *); | |||
| 95 | static debug_type parse_coff_enum_type | |||
| 96 | (bfd *, struct coff_symbols *, struct coff_types *, | |||
| 97 | union internal_auxent *, void *); | |||
| 98 | static bfd_boolean parse_coff_symbol | |||
| 99 | (bfd *, struct coff_types *, asymbol *, long, struct internal_syment *, | |||
| 100 | void *, debug_type, bfd_boolean); | |||
| 101 | static bfd_boolean external_coff_symbol_p (int sym_class); | |||
| 102 | ||||
| 103 | /* Return the slot for a type. */ | |||
| 104 | ||||
| 105 | static debug_type * | |||
| 106 | coff_get_slot (struct coff_types *types, int indx) | |||
| 107 | { | |||
| 108 | struct coff_slots **pps; | |||
| 109 | ||||
| 110 | pps = &types->slots; | |||
| 111 | ||||
| 112 | while (indx >= COFF_SLOTS(16)) | |||
| 113 | { | |||
| 114 | if (*pps == NULL((void*)0)) | |||
| 115 | { | |||
| 116 | *pps = (struct coff_slots *) xmalloc (sizeof **pps); | |||
| 117 | memset (*pps, 0, sizeof **pps); | |||
| 118 | } | |||
| 119 | pps = &(*pps)->next; | |||
| 120 | indx -= COFF_SLOTS(16); | |||
| 121 | } | |||
| 122 | ||||
| 123 | if (*pps == NULL((void*)0)) | |||
| 124 | { | |||
| 125 | *pps = (struct coff_slots *) xmalloc (sizeof **pps); | |||
| 126 | memset (*pps, 0, sizeof **pps); | |||
| 127 | } | |||
| 128 | ||||
| 129 | return (*pps)->slots + indx; | |||
| 130 | } | |||
| 131 | ||||
| 132 | /* Parse a COFF type code in NTYPE. */ | |||
| 133 | ||||
| 134 | static debug_type | |||
| 135 | parse_coff_type (bfd *abfd, struct coff_symbols *symbols, | |||
| 136 | struct coff_types *types, long coff_symno, int ntype, | |||
| 137 | union internal_auxent *pauxent, bfd_boolean useaux, | |||
| 138 | void *dhandle) | |||
| 139 | { | |||
| 140 | debug_type type; | |||
| 141 | ||||
| 142 | if ((ntype & ~N_BTMASK(((abfd)->tdata.coff_obj_data)->local_n_btmask)) != 0) | |||
| 143 | { | |||
| 144 | int newtype; | |||
| 145 | ||||
| 146 | newtype = DECREF (ntype)((((ntype) >> (((abfd)->tdata.coff_obj_data)->local_n_tshift )) & ~ (((abfd)->tdata.coff_obj_data)->local_n_btmask )) | ((ntype) & (((abfd)->tdata.coff_obj_data)->local_n_btmask ))); | |||
| 147 | ||||
| 148 | if (ISPTR (ntype)(((unsigned long) (ntype) & (((abfd)->tdata.coff_obj_data )->local_n_tmask)) == ((unsigned long) (1) << (((abfd )->tdata.coff_obj_data)->local_n_btshft)))) | |||
| 149 | { | |||
| 150 | type = parse_coff_type (abfd, symbols, types, coff_symno, newtype, | |||
| 151 | pauxent, useaux, dhandle); | |||
| 152 | type = debug_make_pointer_type (dhandle, type); | |||
| 153 | } | |||
| 154 | else if (ISFCN (ntype)(((unsigned long) (ntype) & (((abfd)->tdata.coff_obj_data )->local_n_tmask)) == ((unsigned long) (2) << (((abfd )->tdata.coff_obj_data)->local_n_btshft)))) | |||
| 155 | { | |||
| 156 | type = parse_coff_type (abfd, symbols, types, coff_symno, newtype, | |||
| 157 | pauxent, useaux, dhandle); | |||
| 158 | type = debug_make_function_type (dhandle, type, (debug_type *) NULL((void*)0), | |||
| 159 | FALSE0); | |||
| 160 | } | |||
| 161 | else if (ISARY (ntype)(((unsigned long) (ntype) & (((abfd)->tdata.coff_obj_data )->local_n_tmask)) == ((unsigned long) (3) << (((abfd )->tdata.coff_obj_data)->local_n_btshft)))) | |||
| 162 | { | |||
| 163 | int n; | |||
| 164 | ||||
| 165 | if (pauxent == NULL((void*)0)) | |||
| 166 | n = 0; | |||
| 167 | else | |||
| 168 | { | |||
| 169 | unsigned short *dim; | |||
| 170 | int i; | |||
| 171 | ||||
| 172 | /* FIXME: If pauxent->x_sym.x_tagndx.l == 0, gdb sets | |||
| 173 | the c_naux field of the syment to 0. */ | |||
| 174 | ||||
| 175 | /* Move the dimensions down, so that the next array | |||
| 176 | picks up the next one. */ | |||
| 177 | dim = pauxent->x_sym.x_fcnary.x_ary.x_dimen; | |||
| 178 | n = dim[0]; | |||
| 179 | for (i = 0; *dim != 0 && i < DIMNUM4 - 1; i++, dim++) | |||
| 180 | *dim = *(dim + 1); | |||
| 181 | *dim = 0; | |||
| 182 | } | |||
| 183 | ||||
| 184 | type = parse_coff_type (abfd, symbols, types, coff_symno, newtype, | |||
| 185 | pauxent, FALSE0, dhandle); | |||
| 186 | type = debug_make_array_type (dhandle, type, | |||
| 187 | parse_coff_base_type (abfd, symbols, | |||
| 188 | types, | |||
| 189 | coff_symno, | |||
| 190 | T_INT4, | |||
| 191 | NULL((void*)0), dhandle), | |||
| 192 | 0, n - 1, FALSE0); | |||
| 193 | } | |||
| 194 | else | |||
| 195 | { | |||
| 196 | non_fatal (_("parse_coff_type: Bad type code 0x%x")("parse_coff_type: Bad type code 0x%x"), ntype); | |||
| 197 | return DEBUG_TYPE_NULL((debug_type) ((void*)0)); | |||
| 198 | } | |||
| 199 | ||||
| 200 | return type; | |||
| 201 | } | |||
| 202 | ||||
| 203 | if (pauxent != NULL((void*)0) && pauxent->x_sym.x_tagndx.l > 0) | |||
| 204 | { | |||
| 205 | debug_type *slot; | |||
| 206 | ||||
| 207 | /* This is a reference to an existing type. FIXME: gdb checks | |||
| 208 | that the class is not C_STRTAG, nor C_UNTAG, nor C_ENTAG. */ | |||
| 209 | slot = coff_get_slot (types, pauxent->x_sym.x_tagndx.l); | |||
| 210 | if (*slot != DEBUG_TYPE_NULL((debug_type) ((void*)0))) | |||
| 211 | return *slot; | |||
| 212 | else | |||
| 213 | return debug_make_indirect_type (dhandle, slot, (const char *) NULL((void*)0)); | |||
| 214 | } | |||
| 215 | ||||
| 216 | /* If the aux entry has already been used for something, useaux will | |||
| 217 | have been set to false, indicating that parse_coff_base_type | |||
| 218 | should not use it. We need to do it this way, rather than simply | |||
| 219 | passing pauxent as NULL, because we need to be able handle | |||
| 220 | multiple array dimensions while still discarding pauxent after | |||
| 221 | having handled all of them. */ | |||
| 222 | if (! useaux) | |||
| 223 | pauxent = NULL((void*)0); | |||
| 224 | ||||
| 225 | return parse_coff_base_type (abfd, symbols, types, coff_symno, ntype, | |||
| 226 | pauxent, dhandle); | |||
| 227 | } | |||
| 228 | ||||
| 229 | /* Parse a basic COFF type in NTYPE. */ | |||
| 230 | ||||
| 231 | static debug_type | |||
| 232 | parse_coff_base_type (bfd *abfd, struct coff_symbols *symbols, | |||
| 233 | struct coff_types *types, long coff_symno, int ntype, | |||
| 234 | union internal_auxent *pauxent, void *dhandle) | |||
| 235 | { | |||
| 236 | debug_type ret; | |||
| 237 | bfd_boolean set_basic; | |||
| 238 | const char *name; | |||
| 239 | debug_type *slot; | |||
| 240 | ||||
| 241 | if (ntype >= 0 | |||
| 242 | && ntype <= T_MAX(16) | |||
| 243 | && types->basic[ntype] != DEBUG_TYPE_NULL((debug_type) ((void*)0))) | |||
| 244 | return types->basic[ntype]; | |||
| 245 | ||||
| 246 | set_basic = TRUE1; | |||
| 247 | name = NULL((void*)0); | |||
| 248 | ||||
| 249 | switch (ntype) | |||
| 250 | { | |||
| 251 | default: | |||
| 252 | ret = debug_make_void_type (dhandle); | |||
| 253 | break; | |||
| 254 | ||||
| 255 | case T_NULL0: | |||
| 256 | case T_VOID1: | |||
| 257 | ret = debug_make_void_type (dhandle); | |||
| 258 | name = "void"; | |||
| 259 | break; | |||
| 260 | ||||
| 261 | case T_CHAR2: | |||
| 262 | ret = debug_make_int_type (dhandle, 1, FALSE0); | |||
| 263 | name = "char"; | |||
| 264 | break; | |||
| 265 | ||||
| 266 | case T_SHORT3: | |||
| 267 | ret = debug_make_int_type (dhandle, 2, FALSE0); | |||
| 268 | name = "short"; | |||
| 269 | break; | |||
| 270 | ||||
| 271 | case T_INT4: | |||
| 272 | /* FIXME: Perhaps the size should depend upon the architecture. */ | |||
| 273 | ret = debug_make_int_type (dhandle, 4, FALSE0); | |||
| 274 | name = "int"; | |||
| 275 | break; | |||
| 276 | ||||
| 277 | case T_LONG5: | |||
| 278 | ret = debug_make_int_type (dhandle, 4, FALSE0); | |||
| 279 | name = "long"; | |||
| 280 | break; | |||
| 281 | ||||
| 282 | case T_FLOAT6: | |||
| 283 | ret = debug_make_float_type (dhandle, 4); | |||
| 284 | name = "float"; | |||
| 285 | break; | |||
| 286 | ||||
| 287 | case T_DOUBLE7: | |||
| 288 | ret = debug_make_float_type (dhandle, 8); | |||
| 289 | name = "double"; | |||
| 290 | break; | |||
| 291 | ||||
| 292 | case T_LNGDBL16: | |||
| 293 | ret = debug_make_float_type (dhandle, 12); | |||
| 294 | name = "long double"; | |||
| 295 | break; | |||
| 296 | ||||
| 297 | case T_UCHAR12: | |||
| 298 | ret = debug_make_int_type (dhandle, 1, TRUE1); | |||
| 299 | name = "unsigned char"; | |||
| 300 | break; | |||
| 301 | ||||
| 302 | case T_USHORT13: | |||
| 303 | ret = debug_make_int_type (dhandle, 2, TRUE1); | |||
| 304 | name = "unsigned short"; | |||
| 305 | break; | |||
| 306 | ||||
| 307 | case T_UINT14: | |||
| 308 | ret = debug_make_int_type (dhandle, 4, TRUE1); | |||
| 309 | name = "unsigned int"; | |||
| 310 | break; | |||
| 311 | ||||
| 312 | case T_ULONG15: | |||
| 313 | ret = debug_make_int_type (dhandle, 4, TRUE1); | |||
| 314 | name = "unsigned long"; | |||
| 315 | break; | |||
| 316 | ||||
| 317 | case T_STRUCT8: | |||
| 318 | if (pauxent == NULL((void*)0)) | |||
| 319 | ret = debug_make_struct_type (dhandle, TRUE1, 0, | |||
| 320 | (debug_field *) NULL((void*)0)); | |||
| 321 | else | |||
| 322 | ret = parse_coff_struct_type (abfd, symbols, types, ntype, pauxent, | |||
| 323 | dhandle); | |||
| 324 | ||||
| 325 | slot = coff_get_slot (types, coff_symno); | |||
| 326 | *slot = ret; | |||
| 327 | ||||
| 328 | set_basic = FALSE0; | |||
| 329 | break; | |||
| 330 | ||||
| 331 | case T_UNION9: | |||
| 332 | if (pauxent == NULL((void*)0)) | |||
| 333 | ret = debug_make_struct_type (dhandle, FALSE0, 0, (debug_field *) NULL((void*)0)); | |||
| 334 | else | |||
| 335 | ret = parse_coff_struct_type (abfd, symbols, types, ntype, pauxent, | |||
| 336 | dhandle); | |||
| 337 | ||||
| 338 | slot = coff_get_slot (types, coff_symno); | |||
| 339 | *slot = ret; | |||
| 340 | ||||
| 341 | set_basic = FALSE0; | |||
| 342 | break; | |||
| 343 | ||||
| 344 | case T_ENUM10: | |||
| 345 | if (pauxent == NULL((void*)0)) | |||
| 346 | ret = debug_make_enum_type (dhandle, (const char **) NULL((void*)0), | |||
| 347 | (bfd_signed_vma *) NULL((void*)0)); | |||
| 348 | else | |||
| 349 | ret = parse_coff_enum_type (abfd, symbols, types, pauxent, dhandle); | |||
| 350 | ||||
| 351 | slot = coff_get_slot (types, coff_symno); | |||
| 352 | *slot = ret; | |||
| 353 | ||||
| 354 | set_basic = FALSE0; | |||
| 355 | break; | |||
| 356 | } | |||
| 357 | ||||
| 358 | if (name != NULL((void*)0)) | |||
| 359 | ret = debug_name_type (dhandle, name, ret); | |||
| 360 | ||||
| 361 | if (set_basic | |||
| 362 | && ntype >= 0 | |||
| 363 | && ntype <= T_MAX(16)) | |||
| 364 | types->basic[ntype] = ret; | |||
| 365 | ||||
| 366 | return ret; | |||
| 367 | } | |||
| 368 | ||||
| 369 | /* Parse a struct type. */ | |||
| 370 | ||||
| 371 | static debug_type | |||
| 372 | parse_coff_struct_type (bfd *abfd, struct coff_symbols *symbols, | |||
| 373 | struct coff_types *types, int ntype, | |||
| 374 | union internal_auxent *pauxent, void *dhandle) | |||
| 375 | { | |||
| 376 | long symend; | |||
| 377 | int alloc; | |||
| 378 | debug_field *fields; | |||
| 379 | int count; | |||
| 380 | bfd_boolean done; | |||
| 381 | ||||
| 382 | symend = pauxent->x_sym.x_fcnary.x_fcn.x_endndx.l; | |||
| 383 | ||||
| 384 | alloc = 10; | |||
| 385 | fields = (debug_field *) xmalloc (alloc * sizeof *fields); | |||
| 386 | count = 0; | |||
| 387 | ||||
| 388 | done = FALSE0; | |||
| 389 | while (! done |
0.1 | 'done' is 0 |
1 | Assuming 'symend' is > field 'coff_symno' |
9 | Assigned value is garbage or undefined |