| 1 | diff -Nruw bfd/Makefile.am bfd/Makefile.am |
| 2 | --- bfd/Makefile.am 2009-10-16 17:17:44.000000000 +0530 |
| 3 | +++ bfd/Makefile.am 2010-02-11 10:59:11.320193800 +0530 |
| 4 | @@ -228,6 +228,8 @@ |
| 5 | coff-apollo.lo \ |
| 6 | coff-arm.lo \ |
| 7 | coff-aux.lo \ |
| 8 | + coff-avr.lo \ |
| 9 | + coff-ext-avr.lo \ |
| 10 | coff-go32.lo \ |
| 11 | coff-h8300.lo \ |
| 12 | coff-h8500.lo \ |
| 13 | @@ -411,6 +413,8 @@ |
| 14 | coff-apollo.c \ |
| 15 | coff-arm.c \ |
| 16 | coff-aux.c \ |
| 17 | + coff-avr.c \ |
| 18 | + coff-ext-avr.c \ |
| 19 | coff-go32.c \ |
| 20 | coff-h8300.c \ |
| 21 | coff-h8500.c \ |
| 22 | diff -Nruw bfd/Makefile.in bfd/Makefile.in |
| 23 | --- bfd/Makefile.in 2009-10-16 17:17:48.000000000 +0530 |
| 24 | +++ bfd/Makefile.in 2010-02-11 11:13:52.698455300 +0530 |
| 25 | @@ -524,6 +524,8 @@ |
| 26 | coff-apollo.lo \ |
| 27 | coff-arm.lo \ |
| 28 | coff-aux.lo \ |
| 29 | + coff-avr.lo \ |
| 30 | + coff-ext-avr.lo \ |
| 31 | coff-go32.lo \ |
| 32 | coff-h8300.lo \ |
| 33 | coff-h8500.lo \ |
| 34 | @@ -707,6 +709,8 @@ |
| 35 | coff-apollo.c \ |
| 36 | coff-arm.c \ |
| 37 | coff-aux.c \ |
| 38 | + coff-avr.c \ |
| 39 | + coff-ext-avr.c \ |
| 40 | coff-go32.c \ |
| 41 | coff-h8300.c \ |
| 42 | coff-h8500.c \ |
| 43 | diff -Nruw bfd/coff-avr.c bfd/coff-avr.c |
| 44 | --- bfd/coff-avr.c 1970-01-01 05:30:00.000000000 +0530 |
| 45 | +++ bfd/coff-avr.c 2010-02-10 17:35:58.222099600 +0530 |
| 46 | @@ -0,0 +1,613 @@ |
| 47 | +/* BFD back-end for Atmel AVR COFF files. |
| 48 | + Copyright 1990, 1991, 1992, 1993, 1994, 1995, 1999, 2000, 2001, 2003 |
| 49 | + Free Software Foundation, Inc. |
| 50 | + Created mostly by substituting "avr" for "i860" in coff-i860.c |
| 51 | + |
| 52 | +This file is part of BFD, the Binary File Descriptor library. |
| 53 | + |
| 54 | +This program is free software; you can redistribute it and/or modify |
| 55 | +it under the terms of the GNU General Public License as published by |
| 56 | +the Free Software Foundation; either version 2 of the License, or |
| 57 | +(at your option) any later version. |
| 58 | + |
| 59 | +This program is distributed in the hope that it will be useful, |
| 60 | +but WITHOUT ANY WARRANTY; without even the implied warranty of |
| 61 | +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| 62 | +GNU General Public License for more details. |
| 63 | + |
| 64 | +You should have received a copy of the GNU General Public License |
| 65 | +along with this program; if not, write to the Free Software |
| 66 | +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ |
| 67 | + |
| 68 | +#include "bfd.h" |
| 69 | +#include "sysdep.h" |
| 70 | +#include "libbfd.h" |
| 71 | + |
| 72 | +#include "coff/avr.h" |
| 73 | + |
| 74 | +#include "coff/internal.h" |
| 75 | + |
| 76 | +#include "libcoff.h" |
| 77 | + |
| 78 | +static bfd_reloc_status_type coff_avr_reloc |
| 79 | + PARAMS ((bfd *, arelent *, asymbol *, PTR, asection *, bfd *, char **)); |
| 80 | +static reloc_howto_type *coff_avr_rtype_to_howto |
| 81 | + PARAMS ((bfd *, asection *, struct internal_reloc *, |
| 82 | + struct coff_link_hash_entry *, struct internal_syment *, |
| 83 | + bfd_vma *)); |
| 84 | +static const bfd_target * coff_avr_object_p PARAMS ((bfd *)); |
| 85 | + |
| 86 | +#define COFF_DEFAULT_SECTION_ALIGNMENT_POWER (2) |
| 87 | +/* The page size is a guess based on ELF. */ |
| 88 | + |
| 89 | +#define COFF_PAGE_SIZE 0x1000 |
| 90 | + |
| 91 | +/* For some reason when using avr COFF the value stored in the .text |
| 92 | + section for a reference to a common symbol is the value itself plus |
| 93 | + any desired offset. Ian Taylor, Cygnus Support. */ |
| 94 | + |
| 95 | +/* If we are producing relocateable output, we need to do some |
| 96 | + adjustments to the object file that are not done by the |
| 97 | + bfd_perform_relocation function. This function is called by every |
| 98 | + reloc type to make any required adjustments. */ |
| 99 | + |
| 100 | +static bfd_reloc_status_type |
| 101 | +coff_avr_reloc (abfd, reloc_entry, symbol, data, input_section, output_bfd, |
| 102 | + error_message) |
| 103 | + bfd *abfd; |
| 104 | + arelent *reloc_entry; |
| 105 | + asymbol *symbol; |
| 106 | + PTR data; |
| 107 | + asection *input_section ATTRIBUTE_UNUSED; |
| 108 | + bfd *output_bfd; |
| 109 | + char **error_message ATTRIBUTE_UNUSED; |
| 110 | +{ |
| 111 | + symvalue diff; |
| 112 | + |
| 113 | + if (output_bfd == (bfd *) NULL) |
| 114 | + return bfd_reloc_continue; |
| 115 | + |
| 116 | + if (bfd_is_com_section (symbol->section)) |
| 117 | + { |
| 118 | + /* We are relocating a common symbol. The current value in the |
| 119 | + object file is ORIG + OFFSET, where ORIG is the value of the |
| 120 | + common symbol as seen by the object file when it was compiled |
| 121 | + (this may be zero if the symbol was undefined) and OFFSET is |
| 122 | + the offset into the common symbol (normally zero, but may be |
| 123 | + non-zero when referring to a field in a common structure). |
| 124 | + ORIG is the negative of reloc_entry->addend, which is set by |
| 125 | + the CALC_ADDEND macro below. We want to replace the value in |
| 126 | + the object file with NEW + OFFSET, where NEW is the value of |
| 127 | + the common symbol which we are going to put in the final |
| 128 | + object file. NEW is symbol->value. */ |
| 129 | + diff = symbol->value + reloc_entry->addend; |
| 130 | + } |
| 131 | + else |
| 132 | + { |
| 133 | + /* For some reason bfd_perform_relocation always effectively |
| 134 | + ignores the addend for a COFF target when producing |
| 135 | + relocateable output. This seems to be always wrong for 860 |
| 136 | + COFF, so we handle the addend here instead. */ |
| 137 | + diff = reloc_entry->addend; |
| 138 | + } |
| 139 | + |
| 140 | +#define DOIT(x) \ |
| 141 | + x = ((x & ~howto->dst_mask) | (((x & howto->src_mask) + diff) & howto->dst_mask)) |
| 142 | + |
| 143 | + if (diff != 0) |
| 144 | + { |
| 145 | + reloc_howto_type *howto = reloc_entry->howto; |
| 146 | + unsigned char *addr = (unsigned char *) data + reloc_entry->address; |
| 147 | + |
| 148 | + switch (howto->size) |
| 149 | + { |
| 150 | + case 0: |
| 151 | + { |
| 152 | + char x = bfd_get_8 (abfd, addr); |
| 153 | + DOIT (x); |
| 154 | + bfd_put_8 (abfd, x, addr); |
| 155 | + } |
| 156 | + break; |
| 157 | + |
| 158 | + case 1: |
| 159 | + { |
| 160 | + short x = bfd_get_16 (abfd, addr); |
| 161 | + DOIT (x); |
| 162 | + bfd_put_16 (abfd, (bfd_vma) x, addr); |
| 163 | + } |
| 164 | + break; |
| 165 | + |
| 166 | + case 2: |
| 167 | + { |
| 168 | + long x = bfd_get_32 (abfd, addr); |
| 169 | + DOIT (x); |
| 170 | + bfd_put_32 (abfd, (bfd_vma) x, addr); |
| 171 | + } |
| 172 | + break; |
| 173 | + |
| 174 | + default: |
| 175 | + abort (); |
| 176 | + } |
| 177 | + } |
| 178 | + |
| 179 | + /* Now let bfd_perform_relocation finish everything up. */ |
| 180 | + return bfd_reloc_continue; |
| 181 | +} |
| 182 | + |
| 183 | +#ifndef PCRELOFFSET |
| 184 | +#define PCRELOFFSET FALSE |
| 185 | +#endif |
| 186 | + |
| 187 | +static reloc_howto_type howto_table[] = |
| 188 | +{ |
| 189 | + EMPTY_HOWTO (0), |
| 190 | + EMPTY_HOWTO (1), |
| 191 | + EMPTY_HOWTO (2), |
| 192 | + EMPTY_HOWTO (3), |
| 193 | + EMPTY_HOWTO (4), |
| 194 | + EMPTY_HOWTO (5), |
| 195 | + HOWTO (R_DIR32, /* type */ |
| 196 | + 0, /* rightshift */ |
| 197 | + 2, /* size (0 = byte, 1 = short, 2 = long) */ |
| 198 | + 32, /* bitsize */ |
| 199 | + FALSE, /* pc_relative */ |
| 200 | + 0, /* bitpos */ |
| 201 | + complain_overflow_bitfield, /* complain_on_overflow */ |
| 202 | + coff_avr_reloc, /* special_function */ |
| 203 | + "dir32", /* name */ |
| 204 | + TRUE, /* partial_inplace */ |
| 205 | + 0xffffffff, /* src_mask */ |
| 206 | + 0xffffffff, /* dst_mask */ |
| 207 | + TRUE), /* pcrel_offset */ |
| 208 | + /* {7}, */ |
| 209 | + HOWTO (R_IMAGEBASE, /* type */ |
| 210 | + 0, /* rightshift */ |
| 211 | + 2, /* size (0 = byte, 1 = short, 2 = long) */ |
| 212 | + 32, /* bitsize */ |
| 213 | + FALSE, /* pc_relative */ |
| 214 | + 0, /* bitpos */ |
| 215 | + complain_overflow_bitfield, /* complain_on_overflow */ |
| 216 | + coff_avr_reloc, /* special_function */ |
| 217 | + "rva32", /* name */ |
| 218 | + TRUE, /* partial_inplace */ |
| 219 | + 0xffffffff, /* src_mask */ |
| 220 | + 0xffffffff, /* dst_mask */ |
| 221 | + FALSE), /* pcrel_offset */ |
| 222 | + EMPTY_HOWTO (010), |
| 223 | + EMPTY_HOWTO (011), |
| 224 | + EMPTY_HOWTO (012), |
| 225 | + EMPTY_HOWTO (013), |
| 226 | + EMPTY_HOWTO (014), |
| 227 | + EMPTY_HOWTO (015), |
| 228 | + EMPTY_HOWTO (016), |
| 229 | + HOWTO (R_RELBYTE, /* type */ |
| 230 | + 0, /* rightshift */ |
| 231 | + 0, /* size (0 = byte, 1 = short, 2 = long) */ |
| 232 | + 8, /* bitsize */ |
| 233 | + FALSE, /* pc_relative */ |
| 234 | + 0, /* bitpos */ |
| 235 | + complain_overflow_bitfield, /* complain_on_overflow */ |
| 236 | + coff_avr_reloc, /* special_function */ |
| 237 | + "8", /* name */ |
| 238 | + TRUE, /* partial_inplace */ |
| 239 | + 0x000000ff, /* src_mask */ |
| 240 | + 0x000000ff, /* dst_mask */ |
| 241 | + PCRELOFFSET), /* pcrel_offset */ |
| 242 | + HOWTO (R_RELWORD, /* type */ |
| 243 | + 0, /* rightshift */ |
| 244 | + 1, /* size (0 = byte, 1 = short, 2 = long) */ |
| 245 | + 16, /* bitsize */ |
| 246 | + FALSE, /* pc_relative */ |
| 247 | + 0, /* bitpos */ |
| 248 | + complain_overflow_bitfield, /* complain_on_overflow */ |
| 249 | + coff_avr_reloc, /* special_function */ |
| 250 | + "16", /* name */ |
| 251 | + TRUE, /* partial_inplace */ |
| 252 | + 0x0000ffff, /* src_mask */ |
| 253 | + 0x0000ffff, /* dst_mask */ |
| 254 | + PCRELOFFSET), /* pcrel_offset */ |
| 255 | + HOWTO (R_RELLONG, /* type */ |
| 256 | + 0, /* rightshift */ |
| 257 | + 2, /* size (0 = byte, 1 = short, 2 = long) */ |
| 258 | + 32, /* bitsize */ |
| 259 | + FALSE, /* pc_relative */ |
| 260 | + 0, /* bitpos */ |
| 261 | + complain_overflow_bitfield, /* complain_on_overflow */ |
| 262 | + coff_avr_reloc, /* special_function */ |
| 263 | + "32", /* name */ |
| 264 | + TRUE, /* partial_inplace */ |
| 265 | + 0xffffffff, /* src_mask */ |
| 266 | + 0xffffffff, /* dst_mask */ |
| 267 | + PCRELOFFSET), /* pcrel_offset */ |
| 268 | + HOWTO (R_PCRBYTE, /* type */ |
| 269 | + 0, /* rightshift */ |
| 270 | + 0, /* size (0 = byte, 1 = short, 2 = long) */ |
| 271 | + 8, /* bitsize */ |
| 272 | + TRUE, /* pc_relative */ |
| 273 | + 0, /* bitpos */ |
| 274 | + complain_overflow_signed, /* complain_on_overflow */ |
| 275 | + coff_avr_reloc, /* special_function */ |
| 276 | + "DISP8", /* name */ |
| 277 | + TRUE, /* partial_inplace */ |
| 278 | + 0x000000ff, /* src_mask */ |
| 279 | + 0x000000ff, /* dst_mask */ |
| 280 | + PCRELOFFSET), /* pcrel_offset */ |
| 281 | + HOWTO (R_PCRWORD, /* type */ |
| 282 | + 0, /* rightshift */ |
| 283 | + 1, /* size (0 = byte, 1 = short, 2 = long) */ |
| 284 | + 16, /* bitsize */ |
| 285 | + TRUE, /* pc_relative */ |
| 286 | + 0, /* bitpos */ |
| 287 | + complain_overflow_signed, /* complain_on_overflow */ |
| 288 | + coff_avr_reloc, /* special_function */ |
| 289 | + "DISP16", /* name */ |
| 290 | + TRUE, /* partial_inplace */ |
| 291 | + 0x0000ffff, /* src_mask */ |
| 292 | + 0x0000ffff, /* dst_mask */ |
| 293 | + PCRELOFFSET), /* pcrel_offset */ |
| 294 | + HOWTO (R_PCRLONG, /* type */ |
| 295 | + 0, /* rightshift */ |
| 296 | + 2, /* size (0 = byte, 1 = short, 2 = long) */ |
| 297 | + 32, /* bitsize */ |
| 298 | + TRUE, /* pc_relative */ |
| 299 | + 0, /* bitpos */ |
| 300 | + complain_overflow_signed, /* complain_on_overflow */ |
| 301 | + coff_avr_reloc, /* special_function */ |
| 302 | + "DISP32", /* name */ |
| 303 | + TRUE, /* partial_inplace */ |
| 304 | + 0xffffffff, /* src_mask */ |
| 305 | + 0xffffffff, /* dst_mask */ |
| 306 | + PCRELOFFSET) /* pcrel_offset */ |
| 307 | +}; |
| 308 | + |
| 309 | +/* Turn a howto into a reloc nunmber */ |
| 310 | + |
| 311 | +#define SELECT_RELOC(x,howto) { x.r_type = howto->type; } |
| 312 | +#define BADMAG(x) AVRBADMAG(x) |
| 313 | +#define AVR 1 /* Customize coffcode.h */ |
| 314 | + |
| 315 | +#define RTYPE2HOWTO(cache_ptr, dst) \ |
| 316 | + (cache_ptr)->howto = howto_table + (dst)->r_type; |
| 317 | + |
| 318 | +/* For AVR COFF a STYP_NOLOAD | STYP_BSS section is part of a shared |
| 319 | + library. On some other COFF targets STYP_BSS is normally |
| 320 | + STYP_NOLOAD. */ |
| 321 | +#define BSS_NOLOAD_IS_SHARED_LIBRARY |
| 322 | + |
| 323 | +/* Compute the addend of a reloc. If the reloc is to a common symbol, |
| 324 | + the object file contains the value of the common symbol. By the |
| 325 | + time this is called, the linker may be using a different symbol |
| 326 | + from a different object file with a different value. Therefore, we |
| 327 | + hack wildly to locate the original symbol from this file so that we |
| 328 | + can make the correct adjustment. This macro sets coffsym to the |
| 329 | + symbol from the original file, and uses it to set the addend value |
| 330 | + correctly. If this is not a common symbol, the usual addend |
| 331 | + calculation is done, except that an additional tweak is needed for |
| 332 | + PC relative relocs. |
| 333 | + FIXME: This macro refers to symbols and asect; these are from the |
| 334 | + calling function, not the macro arguments. */ |
| 335 | + |
| 336 | +#define CALC_ADDEND(abfd, ptr, reloc, cache_ptr) \ |
| 337 | + { \ |
| 338 | + coff_symbol_type *coffsym = (coff_symbol_type *) NULL; \ |
| 339 | + if (ptr && bfd_asymbol_bfd (ptr) != abfd) \ |
| 340 | + coffsym = (obj_symbols (abfd) \ |
| 341 | + + (cache_ptr->sym_ptr_ptr - symbols)); \ |
| 342 | + else if (ptr) \ |
| 343 | + coffsym = coff_symbol_from (abfd, ptr); \ |
| 344 | + if (coffsym != (coff_symbol_type *) NULL \ |
| 345 | + && coffsym->native->u.syment.n_scnum == 0) \ |
| 346 | + cache_ptr->addend = - coffsym->native->u.syment.n_value; \ |
| 347 | + else if (ptr && bfd_asymbol_bfd (ptr) == abfd \ |
| 348 | + && ptr->section != (asection *) NULL) \ |
| 349 | + cache_ptr->addend = - (ptr->section->vma + ptr->value); \ |
| 350 | + else \ |
| 351 | + cache_ptr->addend = 0; \ |
| 352 | + if (ptr && howto_table[reloc.r_type].pc_relative) \ |
| 353 | + cache_ptr->addend += asect->vma; \ |
| 354 | + } |
| 355 | + |
| 356 | +/* We use the special COFF backend linker. */ |
| 357 | +#define coff_relocate_section _bfd_coff_generic_relocate_section |
| 358 | + |
| 359 | +static reloc_howto_type * |
| 360 | +coff_avr_rtype_to_howto (abfd, sec, rel, h, sym, addendp) |
| 361 | + bfd *abfd ATTRIBUTE_UNUSED; |
| 362 | + asection *sec; |
| 363 | + struct internal_reloc *rel; |
| 364 | + struct coff_link_hash_entry *h; |
| 365 | + struct internal_syment *sym; |
| 366 | + bfd_vma *addendp; |
| 367 | +{ |
| 368 | + |
| 369 | + reloc_howto_type *howto; |
| 370 | + |
| 371 | + howto = howto_table + rel->r_type; |
| 372 | + |
| 373 | + if (howto->pc_relative) |
| 374 | + *addendp += sec->vma; |
| 375 | + |
| 376 | + if (sym != NULL && sym->n_scnum == 0 && sym->n_value != 0) |
| 377 | + { |
| 378 | + /* This is a common symbol. The section contents include the |
| 379 | + size (sym->n_value) as an addend. The relocate_section |
| 380 | + function will be adding in the final value of the symbol. We |
| 381 | + need to subtract out the current size in order to get the |
| 382 | + correct result. */ |
| 383 | + |
| 384 | + BFD_ASSERT (h != NULL); |
| 385 | + |
| 386 | + /* I think we *do* want to bypass this. If we don't, I have seen some data |
| 387 | + parameters get the wrong relcation address. If I link two versions |
| 388 | + with and without this section bypassed and then do a binary comparison, |
| 389 | + the addresses which are different can be looked up in the map. The |
| 390 | + case in which this section has been bypassed has addresses which correspond |
| 391 | + to values I can find in the map. */ |
| 392 | + *addendp -= sym->n_value; |
| 393 | + } |
| 394 | + |
| 395 | + /* If the output symbol is common (in which case this must be a |
| 396 | + relocateable link), we need to add in the final size of the |
| 397 | + common symbol. */ |
| 398 | + if (h != NULL && h->root.type == bfd_link_hash_common) |
| 399 | + *addendp += h->root.u.c.size; |
| 400 | + |
| 401 | + return howto; |
| 402 | +} |
| 403 | + |
| 404 | +#define coff_rtype_to_howto coff_avr_rtype_to_howto |
| 405 | + |
| 406 | +#ifndef bfd_pe_print_pdata |
| 407 | +#define bfd_pe_print_pdata NULL |
| 408 | +#endif |
| 409 | + |
| 410 | +#include "coffcode.h" |
| 411 | + |
| 412 | +static const bfd_target * |
| 413 | +coff_avr_object_p(a) |
| 414 | + bfd *a; |
| 415 | +{ |
| 416 | + return coff_object_p (a); |
| 417 | +} |
| 418 | + |
| 419 | +/* Handle all the abominations of AVR COFF: |
| 420 | + |
| 421 | + Generic COFF always uses the D1 slot to indicate the "most |
| 422 | + important" derived type, and the D2...Dn slots for decreasing |
| 423 | + importance. E. g., a function symbol will always have its DT_FCN |
| 424 | + element in D1, an array its DT_ARY (its first DT_ARY in a |
| 425 | + multi-dimensional array). In contrast, AVR COFF expects this most |
| 426 | + important derived type specifier in the upmost Dn slot that is |
| 427 | + allocated at all (i. e. that is != 0). |
| 428 | + |
| 429 | + Generic COFF says that "Any symbol that satisfies more than one |
| 430 | + condition [... for AUX entries] should have a union format in its |
| 431 | + auxiliary entry." AVR COFF uses sepearate AUX entries for multiple |
| 432 | + derived types, and in some cases (like the ISFCN one), even puts |
| 433 | + the most important one into the last allocated AUX entry. We |
| 434 | + join/split them here at the border as well. Note that when |
| 435 | + generating AUX entries (where we need to split them), the n_numaux |
| 436 | + field must already have been set up properly (e. g. in |
| 437 | + binutils/wrcoff.c) since the entry renumbering and pointerization |
| 438 | + would not work otherwise. Thus, we only split the information into |
| 439 | + multiple records if n_numaux > 1. For similar reasons, we keep |
| 440 | + n_numaux > 1 on input to keep the appropriate AUX entries |
| 441 | + allocated, so a symbol can be reconstructed if it is being passed |
| 442 | + through one of the GNU tools. |
| 443 | + |
| 444 | + Note that this adjustment is called after the symbol itself has |
| 445 | + been swapped in, but before the AUX entries are swapped in. This |
| 446 | + is the only hook available that could swap (or merge) AUX entries |
| 447 | + at all, so we have to operate on the external AUX entries still. */ |
| 448 | + |
| 449 | +void |
| 450 | +avr_coff_adjust_sym_in_post (abfd, ext, in) |
| 451 | + bfd *abfd; |
| 452 | + PTR ext; |
| 453 | + PTR in; |
| 454 | +{ |
| 455 | + struct internal_syment *dst = (struct internal_syment *)in; |
| 456 | + unsigned short dt, bt, ndt; |
| 457 | + dt = dst->n_type & ~N_BTMASK; |
| 458 | + bt = BTYPE (dst->n_type); |
| 459 | + |
| 460 | + /* Some AVR COFF producers seem to violate the COFF specs, and |
| 461 | + produce symbols for tag names that have the C_FOO filled in |
| 462 | + properly, but T_NULL as the base type value. Patch up here, |
| 463 | + since some of our generic COFF tools (in particular |
| 464 | + binutils/rdcoff.c) rely on the correct data. */ |
| 465 | + if (bt == T_NULL) |
| 466 | + switch (dst->n_sclass) |
| 467 | + { |
| 468 | + case C_STRTAG: |
| 469 | + bt = T_STRUCT; |
| 470 | + break; |
| 471 | + |
| 472 | + case C_UNTAG: |
| 473 | + bt = T_UNION; |
| 474 | + break; |
| 475 | + |
| 476 | + case C_ENTAG: |
| 477 | + bt = T_ENUM; |
| 478 | + break; |
| 479 | + } |
| 480 | + |
| 481 | + /* Swap the derived type slots. */ |
| 482 | + if (dt != 0) |
| 483 | + { |
| 484 | + ndt = 0; |
| 485 | + while (dt != 0) |
| 486 | + { |
| 487 | + ndt = (ndt << N_TSHIFT) | (dt & (N_TMASK >> N_BTSHFT)); |
| 488 | + dt >>= N_TSHIFT; |
| 489 | + } |
| 490 | + dst->n_type = (ndt << N_BTSHFT) | bt; |
| 491 | + } |
| 492 | + else |
| 493 | + dst->n_type = bt; |
| 494 | + |
| 495 | + /* If the derived type is function, and there is more than one AUX |
| 496 | + entry, swap the first and the last AUX entry, so the most |
| 497 | + interesting one will become the first. |
| 498 | + |
| 499 | + If the fundamental type is a tagged type (struct/union/enum), try |
| 500 | + to find the AUX entry describing the tagged type (the one that |
| 501 | + has x_sym.x_tagndx filled in), and merge the tag index into the |
| 502 | + first AUX entry. Depending on the actual input file, there might |
| 503 | + be further DT_PTR entries which we just ignore, since we could |
| 504 | + not handle that information anyway. */ |
| 505 | + if (dst->n_numaux > 1 && dst->n_sclass != C_FILE) |
| 506 | + { |
| 507 | + AUXENT caux, *auxp1, *auxp2; |
| 508 | + size_t symesz; |
| 509 | + unsigned int i; |
| 510 | + |
| 511 | + symesz = bfd_coff_symesz (abfd); |
| 512 | + i = dst->n_numaux; |
| 513 | + |
| 514 | + auxp1 = (AUXENT *)((char *)ext + symesz); |
| 515 | + auxp2 = (AUXENT *)((char *)ext + i * symesz); |
| 516 | + |
| 517 | + if (ISFCN (dst->n_type) |
| 518 | + || (ISPTR(dst->n_type) |
| 519 | + && (bt == T_STRUCT || bt == T_UNION || bt == T_ENUM))) |
| 520 | + { |
| 521 | + caux = *auxp2; |
| 522 | + *auxp2 = *auxp1; |
| 523 | + *auxp1 = caux; |
| 524 | + } |
| 525 | + else |
| 526 | + caux = *auxp1; |
| 527 | + |
| 528 | + if ((ISFCN (dst->n_type) || ISARY (dst->n_type)) |
| 529 | + && (bt == T_STRUCT || bt == T_UNION || bt == T_ENUM)) |
| 530 | + { |
| 531 | + while (i > 1) |
| 532 | + { |
| 533 | + auxp2 = (AUXENT *)((char *)ext + i * symesz); |
| 534 | + |
| 535 | + if (auxp2->x_sym.x_tagndx[0] != 0 || auxp2->x_sym.x_tagndx[1] != 0 |
| 536 | + || auxp2->x_sym.x_tagndx[2] != 0 || auxp2->x_sym.x_tagndx[3] != 0) |
| 537 | + { |
| 538 | + memcpy (caux.x_sym.x_tagndx, auxp2->x_sym.x_tagndx, |
| 539 | + 4 * sizeof (char)); |
| 540 | + break; |
| 541 | + } |
| 542 | + i--; |
| 543 | + } |
| 544 | + if (i > 1) |
| 545 | + *auxp1 = caux; |
| 546 | + } |
| 547 | + } |
| 548 | +} |
| 549 | + |
| 550 | +/* When exporting an AVR COFF file, just undo all that has been done |
| 551 | + above. Again, we are called after the symbol itself has been |
| 552 | + swapped out, but before the AUX entries are being written. |
| 553 | + Unfortunately, we are only given a pointer to the symbol itself, so |
| 554 | + we have to derive the pointer to the respective aux entries from |
| 555 | + that address, which is a bit clumsy. */ |
| 556 | +void |
| 557 | +avr_coff_adjust_sym_out_post (abfd, in, ext) |
| 558 | + bfd *abfd; |
| 559 | + PTR in; |
| 560 | + PTR ext; |
| 561 | +{ |
| 562 | + struct internal_syment *src = (struct internal_syment *)(in); |
| 563 | + struct external_syment *dst = (struct external_syment *)(ext); |
| 564 | + unsigned short dt, bt, ndt; |
| 565 | + |
| 566 | + dt = src->n_type & ~N_BTMASK; |
| 567 | + bt = BTYPE (src->n_type); |
| 568 | + |
| 569 | + if (dt != 0) |
| 570 | + { |
| 571 | + ndt = 0; |
| 572 | + while (dt != 0) |
| 573 | + { |
| 574 | + ndt = (ndt << N_TSHIFT) | (dt & (N_TMASK >> N_BTSHFT)); |
| 575 | + dt >>= N_TSHIFT; |
| 576 | + } |
| 577 | + H_PUT_16 (abfd, (ndt << N_BTSHFT) | bt, dst->e_type); |
| 578 | + } |
| 579 | + |
| 580 | + if (src->n_numaux > 1 && src->n_sclass != C_FILE) |
| 581 | + { |
| 582 | + combined_entry_type *srce, *dste; |
| 583 | + char *hackp; |
| 584 | + unsigned int i; |
| 585 | + |
| 586 | + /* Recover the original combinend_entry_type *. */ |
| 587 | + hackp = (char *)in; |
| 588 | + hackp -= offsetof(combined_entry_type, u.syment); |
| 589 | + srce = (combined_entry_type *)hackp; |
| 590 | + srce++; |
| 591 | + |
| 592 | + /* We simply duplicate the first AUX entry as many times as |
| 593 | + needed. Since COFF itself normally uses just a single AUX |
| 594 | + entry for all the information, this will work -- each COFF |
| 595 | + consumer will then just pick the fields it is particularly |
| 596 | + interested in. This would not work for the AVR COFF specific |
| 597 | + DT_PTR AUX entries, but we don't support them anyway. */ |
| 598 | + for (i = 1; i < src->n_numaux; i++) |
| 599 | + { |
| 600 | + dste = srce + i; |
| 601 | + *dste = *srce; |
| 602 | + } |
| 603 | + } |
| 604 | +} |
| 605 | + |
| 606 | +const bfd_target |
| 607 | +#ifdef TARGET_SYM |
| 608 | + TARGET_SYM = |
| 609 | +#else |
| 610 | + avrcoff_vec = |
| 611 | +#endif |
| 612 | +{ |
| 613 | +#ifdef TARGET_NAME |
| 614 | + TARGET_NAME, |
| 615 | +#else |
| 616 | + "coff-avr", /* name */ |
| 617 | +#endif |
| 618 | + bfd_target_coff_flavour, |
| 619 | + BFD_ENDIAN_LITTLE, /* data byte order is little */ |
| 620 | + BFD_ENDIAN_LITTLE, /* header byte order is little */ |
| 621 | + |
| 622 | + (HAS_RELOC | EXEC_P | /* object flags */ |
| 623 | + HAS_LINENO | HAS_DEBUG | |
| 624 | + HAS_SYMS | HAS_LOCALS | WP_TEXT), |
| 625 | + |
| 626 | + (SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD | SEC_RELOC), /* section flags */ |
| 627 | + 0, /* leading char */ |
| 628 | + '/', /* ar_pad_char */ |
| 629 | + 15, /* ar_max_namelen */ |
| 630 | + |
| 631 | + bfd_getl64, bfd_getl_signed_64, bfd_putl64, |
| 632 | + bfd_getl32, bfd_getl_signed_32, bfd_putl32, |
| 633 | + bfd_getl16, bfd_getl_signed_16, bfd_putl16, /* data */ |
| 634 | + bfd_getl64, bfd_getl_signed_64, bfd_putl64, |
| 635 | + bfd_getl32, bfd_getl_signed_32, bfd_putl32, |
| 636 | + bfd_getl16, bfd_getl_signed_16, bfd_putl16, /* hdrs */ |
| 637 | + |
| 638 | +/* Note that we allow an object file to be treated as a core file as well. */ |
| 639 | + {_bfd_dummy_target, coff_avr_object_p, /* bfd_check_format */ |
| 640 | + bfd_generic_archive_p, coff_avr_object_p}, |
| 641 | + {bfd_false, coff_mkobject, _bfd_generic_mkarchive, /* bfd_set_format */ |
| 642 | + bfd_false}, |
| 643 | + {bfd_false, coff_write_object_contents, /* bfd_write_contents */ |
| 644 | + _bfd_write_archive_contents, bfd_false}, |
| 645 | + |
| 646 | + BFD_JUMP_TABLE_GENERIC (coff), |
| 647 | + BFD_JUMP_TABLE_COPY (coff), |
| 648 | + BFD_JUMP_TABLE_CORE (_bfd_nocore), |
| 649 | + BFD_JUMP_TABLE_ARCHIVE (_bfd_archive_coff), |
| 650 | + BFD_JUMP_TABLE_SYMBOLS (coff), |
| 651 | + BFD_JUMP_TABLE_RELOCS (coff), |
| 652 | + BFD_JUMP_TABLE_WRITE (coff), |
| 653 | + BFD_JUMP_TABLE_LINK (coff), |
| 654 | + BFD_JUMP_TABLE_DYNAMIC (_bfd_nodynamic), |
| 655 | + |
| 656 | + NULL, |
| 657 | + |
| 658 | + COFF_SWAP_TABLE |
| 659 | +}; |
| 660 | diff -Nruw bfd/coff-ext-avr.c bfd/coff-ext-avr.c |
| 661 | --- bfd/coff-ext-avr.c 1970-01-01 05:30:00.000000000 +0530 |
| 662 | +++ bfd/coff-ext-avr.c 2010-02-10 17:35:58.222099600 +0530 |
| 663 | @@ -0,0 +1,428 @@ |
| 664 | +/* BFD back-end for Atmel AVR "extended" COFF files. |
| 665 | + Copyright 1990, 1991, 1992, 1993, 1994, 1995, 1999, 2000, 2001, 2003 |
| 666 | + Free Software Foundation, Inc. |
| 667 | + This is mostly the same as avr-coff, except of the presence of the |
| 668 | + COFF optional header. |
| 669 | + |
| 670 | +This file is part of BFD, the Binary File Descriptor library. |
| 671 | + |
| 672 | +This program is free software; you can redistribute it and/or modify |
| 673 | +it under the terms of the GNU General Public License as published by |
| 674 | +the Free Software Foundation; either version 2 of the License, or |
| 675 | +(at your option) any later version. |
| 676 | + |
| 677 | +This program is distributed in the hope that it will be useful, |
| 678 | +but WITHOUT ANY WARRANTY; without even the implied warranty of |
| 679 | +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| 680 | +GNU General Public License for more details. |
| 681 | + |
| 682 | +You should have received a copy of the GNU General Public License |
| 683 | +along with this program; if not, write to the Free Software |
| 684 | +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ |
| 685 | + |
| 686 | +#include "bfd.h" |
| 687 | +#include "sysdep.h" |
| 688 | +#include "libbfd.h" |
| 689 | + |
| 690 | +#define AVR_EXT_COFF 1 |
| 691 | +#include "coff/avr.h" |
| 692 | + |
| 693 | +#include "coff/internal.h" |
| 694 | + |
| 695 | +#include "libcoff.h" |
| 696 | + |
| 697 | +static bfd_reloc_status_type coff_ext_avr_reloc |
| 698 | + PARAMS ((bfd *, arelent *, asymbol *, PTR, asection *, bfd *, char **)); |
| 699 | +static reloc_howto_type *coff_ext_avr_rtype_to_howto |
| 700 | + PARAMS ((bfd *, asection *, struct internal_reloc *, |
| 701 | + struct coff_link_hash_entry *, struct internal_syment *, |
| 702 | + bfd_vma *)); |
| 703 | +static const bfd_target * coff_ext_avr_object_p PARAMS ((bfd *)); |
| 704 | + |
| 705 | +#define COFF_DEFAULT_SECTION_ALIGNMENT_POWER (2) |
| 706 | +/* The page size is a guess based on ELF. */ |
| 707 | + |
| 708 | +#define COFF_PAGE_SIZE 0x1000 |
| 709 | + |
| 710 | +/* For some reason when using avr COFF the value stored in the .text |
| 711 | + section for a reference to a common symbol is the value itself plus |
| 712 | + any desired offset. Ian Taylor, Cygnus Support. */ |
| 713 | + |
| 714 | +/* If we are producing relocateable output, we need to do some |
| 715 | + adjustments to the object file that are not done by the |
| 716 | + bfd_perform_relocation function. This function is called by every |
| 717 | + reloc type to make any required adjustments. */ |
| 718 | + |
| 719 | +static bfd_reloc_status_type |
| 720 | +coff_ext_avr_reloc (abfd, reloc_entry, symbol, data, input_section, output_bfd, |
| 721 | + error_message) |
| 722 | + bfd *abfd; |
| 723 | + arelent *reloc_entry; |
| 724 | + asymbol *symbol; |
| 725 | + PTR data; |
| 726 | + asection *input_section ATTRIBUTE_UNUSED; |
| 727 | + bfd *output_bfd; |
| 728 | + char **error_message ATTRIBUTE_UNUSED; |
| 729 | +{ |
| 730 | + symvalue diff; |
| 731 | + |
| 732 | + if (output_bfd == (bfd *) NULL) |
| 733 | + return bfd_reloc_continue; |
| 734 | + |
| 735 | + if (bfd_is_com_section (symbol->section)) |
| 736 | + { |
| 737 | + /* We are relocating a common symbol. The current value in the |
| 738 | + object file is ORIG + OFFSET, where ORIG is the value of the |
| 739 | + common symbol as seen by the object file when it was compiled |
| 740 | + (this may be zero if the symbol was undefined) and OFFSET is |
| 741 | + the offset into the common symbol (normally zero, but may be |
| 742 | + non-zero when referring to a field in a common structure). |
| 743 | + ORIG is the negative of reloc_entry->addend, which is set by |
| 744 | + the CALC_ADDEND macro below. We want to replace the value in |
| 745 | + the object file with NEW + OFFSET, where NEW is the value of |
| 746 | + the common symbol which we are going to put in the final |
| 747 | + object file. NEW is symbol->value. */ |
| 748 | + diff = symbol->value + reloc_entry->addend; |
| 749 | + } |
| 750 | + else |
| 751 | + { |
| 752 | + /* For some reason bfd_perform_relocation always effectively |
| 753 | + ignores the addend for a COFF target when producing |
| 754 | + relocateable output. This seems to be always wrong for 860 |
| 755 | + COFF, so we handle the addend here instead. */ |
| 756 | + diff = reloc_entry->addend; |
| 757 | + } |
| 758 | + |
| 759 | +#define DOIT(x) \ |
| 760 | + x = ((x & ~howto->dst_mask) | (((x & howto->src_mask) + diff) & howto->dst_mask)) |
| 761 | + |
| 762 | + if (diff != 0) |
| 763 | + { |
| 764 | + reloc_howto_type *howto = reloc_entry->howto; |
| 765 | + unsigned char *addr = (unsigned char *) data + reloc_entry->address; |
| 766 | + |
| 767 | + switch (howto->size) |
| 768 | + { |
| 769 | + case 0: |
| 770 | + { |
| 771 | + char x = bfd_get_8 (abfd, addr); |
| 772 | + DOIT (x); |
| 773 | + bfd_put_8 (abfd, x, addr); |
| 774 | + } |
| 775 | + break; |
| 776 | + |
| 777 | + case 1: |
| 778 | + { |
| 779 | + short x = bfd_get_16 (abfd, addr); |
| 780 | + DOIT (x); |
| 781 | + bfd_put_16 (abfd, (bfd_vma) x, addr); |
| 782 | + } |
| 783 | + break; |
| 784 | + |
| 785 | + case 2: |
| 786 | + { |
| 787 | + long x = bfd_get_32 (abfd, addr); |
| 788 | + DOIT (x); |
| 789 | + bfd_put_32 (abfd, (bfd_vma) x, addr); |
| 790 | + } |
| 791 | + break; |
| 792 | + |
| 793 | + default: |
| 794 | + abort (); |
| 795 | + } |
| 796 | + } |
| 797 | + |
| 798 | + /* Now let bfd_perform_relocation finish everything up. */ |
| 799 | + return bfd_reloc_continue; |
| 800 | +} |
| 801 | + |
| 802 | +#ifndef PCRELOFFSET |
| 803 | +#define PCRELOFFSET FALSE |
| 804 | +#endif |
| 805 | + |
| 806 | +static reloc_howto_type howto_table[] = |
| 807 | +{ |
| 808 | + EMPTY_HOWTO (0), |
| 809 | + EMPTY_HOWTO (1), |
| 810 | + EMPTY_HOWTO (2), |
| 811 | + EMPTY_HOWTO (3), |
| 812 | + EMPTY_HOWTO (4), |
| 813 | + EMPTY_HOWTO (5), |
| 814 | + HOWTO (R_DIR32, /* type */ |
| 815 | + 0, /* rightshift */ |
| 816 | + 2, /* size (0 = byte, 1 = short, 2 = long) */ |
| 817 | + 32, /* bitsize */ |
| 818 | + FALSE, /* pc_relative */ |
| 819 | + 0, /* bitpos */ |
| 820 | + complain_overflow_bitfield, /* complain_on_overflow */ |
| 821 | + coff_ext_avr_reloc, /* special_function */ |
| 822 | + "dir32", /* name */ |
| 823 | + TRUE, /* partial_inplace */ |
| 824 | + 0xffffffff, /* src_mask */ |
| 825 | + 0xffffffff, /* dst_mask */ |
| 826 | + TRUE), /* pcrel_offset */ |
| 827 | + /* {7}, */ |
| 828 | + HOWTO (R_IMAGEBASE, /* type */ |
| 829 | + 0, /* rightshift */ |
| 830 | + 2, /* size (0 = byte, 1 = short, 2 = long) */ |
| 831 | + 32, /* bitsize */ |
| 832 | + FALSE, /* pc_relative */ |
| 833 | + 0, /* bitpos */ |
| 834 | + complain_overflow_bitfield, /* complain_on_overflow */ |
| 835 | + coff_ext_avr_reloc, /* special_function */ |
| 836 | + "rva32", /* name */ |
| 837 | + TRUE, /* partial_inplace */ |
| 838 | + 0xffffffff, /* src_mask */ |
| 839 | + 0xffffffff, /* dst_mask */ |
| 840 | + FALSE), /* pcrel_offset */ |
| 841 | + EMPTY_HOWTO (010), |
| 842 | + EMPTY_HOWTO (011), |
| 843 | + EMPTY_HOWTO (012), |
| 844 | + EMPTY_HOWTO (013), |
| 845 | + EMPTY_HOWTO (014), |
| 846 | + EMPTY_HOWTO (015), |
| 847 | + EMPTY_HOWTO (016), |
| 848 | + HOWTO (R_RELBYTE, /* type */ |
| 849 | + 0, /* rightshift */ |
| 850 | + 0, /* size (0 = byte, 1 = short, 2 = long) */ |
| 851 | + 8, /* bitsize */ |
| 852 | + FALSE, /* pc_relative */ |
| 853 | + 0, /* bitpos */ |
| 854 | + complain_overflow_bitfield, /* complain_on_overflow */ |
| 855 | + coff_ext_avr_reloc, /* special_function */ |
| 856 | + "8", /* name */ |
| 857 | + TRUE, /* partial_inplace */ |
| 858 | + 0x000000ff, /* src_mask */ |
| 859 | + 0x000000ff, /* dst_mask */ |
| 860 | + PCRELOFFSET), /* pcrel_offset */ |
| 861 | + HOWTO (R_RELWORD, /* type */ |
| 862 | + 0, /* rightshift */ |
| 863 | + 1, /* size (0 = byte, 1 = short, 2 = long) */ |
| 864 | + 16, /* bitsize */ |
| 865 | + FALSE, /* pc_relative */ |
| 866 | + 0, /* bitpos */ |
| 867 | + complain_overflow_bitfield, /* complain_on_overflow */ |
| 868 | + coff_ext_avr_reloc, /* special_function */ |
| 869 | + "16", /* name */ |
| 870 | + TRUE, /* partial_inplace */ |
| 871 | + 0x0000ffff, /* src_mask */ |
| 872 | + 0x0000ffff, /* dst_mask */ |
| 873 | + PCRELOFFSET), /* pcrel_offset */ |
| 874 | + HOWTO (R_RELLONG, /* type */ |
| 875 | + 0, /* rightshift */ |
| 876 | + 2, /* size (0 = byte, 1 = short, 2 = long) */ |
| 877 | + 32, /* bitsize */ |
| 878 | + FALSE, /* pc_relative */ |
| 879 | + 0, /* bitpos */ |
| 880 | + complain_overflow_bitfield, /* complain_on_overflow */ |
| 881 | + coff_ext_avr_reloc, /* special_function */ |
| 882 | + "32", /* name */ |
| 883 | + TRUE, /* partial_inplace */ |
| 884 | + 0xffffffff, /* src_mask */ |
| 885 | + 0xffffffff, /* dst_mask */ |
| 886 | + PCRELOFFSET), /* pcrel_offset */ |
| 887 | + HOWTO (R_PCRBYTE, /* type */ |
| 888 | + 0, /* rightshift */ |
| 889 | + 0, /* size (0 = byte, 1 = short, 2 = long) */ |
| 890 | + 8, /* bitsize */ |
| 891 | + TRUE, /* pc_relative */ |
| 892 | + 0, /* bitpos */ |
| 893 | + complain_overflow_signed, /* complain_on_overflow */ |
| 894 | + coff_ext_avr_reloc, /* special_function */ |
| 895 | + "DISP8", /* name */ |
| 896 | + TRUE, /* partial_inplace */ |
| 897 | + 0x000000ff, /* src_mask */ |
| 898 | + 0x000000ff, /* dst_mask */ |
| 899 | + PCRELOFFSET), /* pcrel_offset */ |
| 900 | + HOWTO (R_PCRWORD, /* type */ |
| 901 | + 0, /* rightshift */ |
| 902 | + 1, /* size (0 = byte, 1 = short, 2 = long) */ |
| 903 | + 16, /* bitsize */ |
| 904 | + TRUE, /* pc_relative */ |
| 905 | + 0, /* bitpos */ |
| 906 | + complain_overflow_signed, /* complain_on_overflow */ |
| 907 | + coff_ext_avr_reloc, /* special_function */ |
| 908 | + "DISP16", /* name */ |
| 909 | + TRUE, /* partial_inplace */ |
| 910 | + 0x0000ffff, /* src_mask */ |
| 911 | + 0x0000ffff, /* dst_mask */ |
| 912 | + PCRELOFFSET), /* pcrel_offset */ |
| 913 | + HOWTO (R_PCRLONG, /* type */ |
| 914 | + 0, /* rightshift */ |
| 915 | + 2, /* size (0 = byte, 1 = short, 2 = long) */ |
| 916 | + 32, /* bitsize */ |
| 917 | + TRUE, /* pc_relative */ |
| 918 | + 0, /* bitpos */ |
| 919 | + complain_overflow_signed, /* complain_on_overflow */ |
| 920 | + coff_ext_avr_reloc, /* special_function */ |
| 921 | + "DISP32", /* name */ |
| 922 | + TRUE, /* partial_inplace */ |
| 923 | + 0xffffffff, /* src_mask */ |
| 924 | + 0xffffffff, /* dst_mask */ |
| 925 | + PCRELOFFSET) /* pcrel_offset */ |
| 926 | +}; |
| 927 | + |
| 928 | +/* Turn a howto into a reloc nunmber */ |
| 929 | + |
| 930 | +#define SELECT_RELOC(x,howto) { x.r_type = howto->type; } |
| 931 | +#define BADMAG(x) AVRBADMAG(x) |
| 932 | +#define AVR 1 /* Customize coffcode.h */ |
| 933 | + |
| 934 | +#define RTYPE2HOWTO(cache_ptr, dst) \ |
| 935 | + (cache_ptr)->howto = howto_table + (dst)->r_type; |
| 936 | + |
| 937 | +/* For AVR COFF a STYP_NOLOAD | STYP_BSS section is part of a shared |
| 938 | + library. On some other COFF targets STYP_BSS is normally |
| 939 | + STYP_NOLOAD. */ |
| 940 | +#define BSS_NOLOAD_IS_SHARED_LIBRARY |
| 941 | + |
| 942 | +/* Compute the addend of a reloc. If the reloc is to a common symbol, |
| 943 | + the object file contains the value of the common symbol. By the |
| 944 | + time this is called, the linker may be using a different symbol |
| 945 | + from a different object file with a different value. Therefore, we |
| 946 | + hack wildly to locate the original symbol from this file so that we |
| 947 | + can make the correct adjustment. This macro sets coffsym to the |
| 948 | + symbol from the original file, and uses it to set the addend value |
| 949 | + correctly. If this is not a common symbol, the usual addend |
| 950 | + calculation is done, except that an additional tweak is needed for |
| 951 | + PC relative relocs. |
| 952 | + FIXME: This macro refers to symbols and asect; these are from the |
| 953 | + calling function, not the macro arguments. */ |
| 954 | + |
| 955 | +#define CALC_ADDEND(abfd, ptr, reloc, cache_ptr) \ |
| 956 | + { \ |
| 957 | + coff_symbol_type *coffsym = (coff_symbol_type *) NULL; \ |
| 958 | + if (ptr && bfd_asymbol_bfd (ptr) != abfd) \ |
| 959 | + coffsym = (obj_symbols (abfd) \ |
| 960 | + + (cache_ptr->sym_ptr_ptr - symbols)); \ |
| 961 | + else if (ptr) \ |
| 962 | + coffsym = coff_symbol_from (abfd, ptr); \ |
| 963 | + if (coffsym != (coff_symbol_type *) NULL \ |
| 964 | + && coffsym->native->u.syment.n_scnum == 0) \ |
| 965 | + cache_ptr->addend = - coffsym->native->u.syment.n_value; \ |
| 966 | + else if (ptr && bfd_asymbol_bfd (ptr) == abfd \ |
| 967 | + && ptr->section != (asection *) NULL) \ |
| 968 | + cache_ptr->addend = - (ptr->section->vma + ptr->value); \ |
| 969 | + else \ |
| 970 | + cache_ptr->addend = 0; \ |
| 971 | + if (ptr && howto_table[reloc.r_type].pc_relative) \ |
| 972 | + cache_ptr->addend += asect->vma; \ |
| 973 | + } |
| 974 | + |
| 975 | +/* We use the special COFF backend linker. */ |
| 976 | +#define coff_relocate_section _bfd_coff_generic_relocate_section |
| 977 | + |
| 978 | +static reloc_howto_type * |
| 979 | +coff_ext_avr_rtype_to_howto (abfd, sec, rel, h, sym, addendp) |
| 980 | + bfd *abfd ATTRIBUTE_UNUSED; |
| 981 | + asection *sec; |
| 982 | + struct internal_reloc *rel; |
| 983 | + struct coff_link_hash_entry *h; |
| 984 | + struct internal_syment *sym; |
| 985 | + bfd_vma *addendp; |
| 986 | +{ |
| 987 | + |
| 988 | + reloc_howto_type *howto; |
| 989 | + |
| 990 | + howto = howto_table + rel->r_type; |
| 991 | + |
| 992 | + if (howto->pc_relative) |
| 993 | + *addendp += sec->vma; |
| 994 | + |
| 995 | + if (sym != NULL && sym->n_scnum == 0 && sym->n_value != 0) |
| 996 | + { |
| 997 | + /* This is a common symbol. The section contents include the |
| 998 | + size (sym->n_value) as an addend. The relocate_section |
| 999 | + function will be adding in the final value of the symbol. We |
| 1000 | + need to subtract out the current size in order to get the |
| 1001 | + correct result. */ |
| 1002 | + |
| 1003 | + BFD_ASSERT (h != NULL); |
| 1004 | + |
| 1005 | + /* I think we *do* want to bypass this. If we don't, I have seen some data |
| 1006 | + parameters get the wrong relcation address. If I link two versions |
| 1007 | + with and without this section bypassed and then do a binary comparison, |
| 1008 | + the addresses which are different can be looked up in the map. The |
| 1009 | + case in which this section has been bypassed has addresses which correspond |
| 1010 | + to values I can find in the map. */ |
| 1011 | + *addendp -= sym->n_value; |
| 1012 | + } |
| 1013 | + |
| 1014 | + /* If the output symbol is common (in which case this must be a |
| 1015 | + relocateable link), we need to add in the final size of the |
| 1016 | + common symbol. */ |
| 1017 | + if (h != NULL && h->root.type == bfd_link_hash_common) |
| 1018 | + *addendp += h->root.u.c.size; |
| 1019 | + |
| 1020 | + return howto; |
| 1021 | +} |
| 1022 | + |
| 1023 | +#define coff_rtype_to_howto coff_ext_avr_rtype_to_howto |
| 1024 | + |
| 1025 | +#ifndef bfd_pe_print_pdata |
| 1026 | +#define bfd_pe_print_pdata NULL |
| 1027 | +#endif |
| 1028 | + |
| 1029 | +#include "coffcode.h" |
| 1030 | + |
| 1031 | +static const bfd_target * |
| 1032 | +coff_ext_avr_object_p(a) |
| 1033 | + bfd *a; |
| 1034 | +{ |
| 1035 | + return coff_object_p (a); |
| 1036 | +} |
| 1037 | + |
| 1038 | +const bfd_target |
| 1039 | +#ifdef TARGET_SYM |
| 1040 | + TARGET_SYM = |
| 1041 | +#else |
| 1042 | + avrextcoff_vec = |
| 1043 | +#endif |
| 1044 | +{ |
| 1045 | +#ifdef TARGET_NAME |
| 1046 | + TARGET_NAME, |
| 1047 | +#else |
| 1048 | + "coff-ext-avr", /* name */ |
| 1049 | +#endif |
| 1050 | + bfd_target_coff_flavour, |
| 1051 | + BFD_ENDIAN_LITTLE, /* data byte order is little */ |
| 1052 | + BFD_ENDIAN_LITTLE, /* header byte order is little */ |
| 1053 | + |
| 1054 | + (HAS_RELOC | EXEC_P | /* object flags */ |
| 1055 | + HAS_LINENO | HAS_DEBUG | |
| 1056 | + HAS_SYMS | HAS_LOCALS | WP_TEXT), |
| 1057 | + |
| 1058 | + (SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD | SEC_RELOC), /* section flags */ |
| 1059 | + 0, /* leading char */ |
| 1060 | + '/', /* ar_pad_char */ |
| 1061 | + 15, /* ar_max_namelen */ |
| 1062 | + |
| 1063 | + bfd_getl64, bfd_getl_signed_64, bfd_putl64, |
| 1064 | + bfd_getl32, bfd_getl_signed_32, bfd_putl32, |
| 1065 | + bfd_getl16, bfd_getl_signed_16, bfd_putl16, /* data */ |
| 1066 | + bfd_getl64, bfd_getl_signed_64, bfd_putl64, |
| 1067 | + bfd_getl32, bfd_getl_signed_32, bfd_putl32, |
| 1068 | + bfd_getl16, bfd_getl_signed_16, bfd_putl16, /* hdrs */ |
| 1069 | + |
| 1070 | +/* Note that we allow an object file to be treated as a core file as well. */ |
| 1071 | + {_bfd_dummy_target, coff_ext_avr_object_p, /* bfd_check_format */ |
| 1072 | + bfd_generic_archive_p, coff_ext_avr_object_p}, |
| 1073 | + {bfd_false, coff_mkobject, _bfd_generic_mkarchive, /* bfd_set_format */ |
| 1074 | + bfd_false}, |
| 1075 | + {bfd_false, coff_write_object_contents, /* bfd_write_contents */ |
| 1076 | + _bfd_write_archive_contents, bfd_false}, |
| 1077 | + |
| 1078 | + BFD_JUMP_TABLE_GENERIC (coff), |
| 1079 | + BFD_JUMP_TABLE_COPY (coff), |
| 1080 | + BFD_JUMP_TABLE_CORE (_bfd_nocore), |
| 1081 | + BFD_JUMP_TABLE_ARCHIVE (_bfd_archive_coff), |
| 1082 | + BFD_JUMP_TABLE_SYMBOLS (coff), |
| 1083 | + BFD_JUMP_TABLE_RELOCS (coff), |
| 1084 | + BFD_JUMP_TABLE_WRITE (coff), |
| 1085 | + BFD_JUMP_TABLE_LINK (coff), |
| 1086 | + BFD_JUMP_TABLE_DYNAMIC (_bfd_nodynamic), |
| 1087 | + |
| 1088 | + NULL, |
| 1089 | + |
| 1090 | + COFF_SWAP_TABLE |
| 1091 | +}; |
| 1092 | diff -Nruw bfd/coffcode.h bfd/coffcode.h |
| 1093 | --- bfd/coffcode.h 2009-09-10 17:17:12.000000000 +0530 |
| 1094 | +++ bfd/coffcode.h 2010-02-10 17:35:58.253349600 +0530 |
| 1095 | @@ -1,3 +1,4 @@ |
| 1096 | + |
| 1097 | /* Support for the generic parts of most COFF variants, for BFD. |
| 1098 | Copyright 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, |
| 1099 | 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 |
| 1100 | @@ -1910,6 +1911,17 @@ |
| 1101 | coff->relocbase = 0; |
| 1102 | coff->local_toc_sym_map = 0; |
| 1103 | |
| 1104 | + /* These members communicate important constants about the symbol |
| 1105 | + table to GDB's symbol-reading code. These `constants' |
| 1106 | + unfortunately vary among coff implementations... */ |
| 1107 | + coff->local_n_btmask = N_BTMASK; |
| 1108 | + coff->local_n_btshft = N_BTSHFT; |
| 1109 | + coff->local_n_tmask = N_TMASK; |
| 1110 | + coff->local_n_tshift = N_TSHIFT; |
| 1111 | + coff->local_symesz = bfd_coff_symesz (abfd); |
| 1112 | + coff->local_auxesz = bfd_coff_auxesz (abfd); |
| 1113 | + coff->local_linesz = bfd_coff_linesz (abfd); |
| 1114 | + |
| 1115 | /* make_abs_section(abfd);*/ |
| 1116 | |
| 1117 | return TRUE; |
| 1118 | @@ -1934,17 +1946,6 @@ |
| 1119 | |
| 1120 | coff->sym_filepos = internal_f->f_symptr; |
| 1121 | |
| 1122 | - /* These members communicate important constants about the symbol |
| 1123 | - table to GDB's symbol-reading code. These `constants' |
| 1124 | - unfortunately vary among coff implementations... */ |
| 1125 | - coff->local_n_btmask = N_BTMASK; |
| 1126 | - coff->local_n_btshft = N_BTSHFT; |
| 1127 | - coff->local_n_tmask = N_TMASK; |
| 1128 | - coff->local_n_tshift = N_TSHIFT; |
| 1129 | - coff->local_symesz = bfd_coff_symesz (abfd); |
| 1130 | - coff->local_auxesz = bfd_coff_auxesz (abfd); |
| 1131 | - coff->local_linesz = bfd_coff_linesz (abfd); |
| 1132 | - |
| 1133 | coff->timestamp = internal_f->f_timdat; |
| 1134 | |
| 1135 | obj_raw_syment_count (abfd) = |
| 1136 | @@ -2076,6 +2077,11 @@ |
| 1137 | } |
| 1138 | break; |
| 1139 | #endif |
| 1140 | +#ifdef AVRMAGIC |
| 1141 | + case AVRMAGIC: |
| 1142 | + arch = bfd_arch_avr; |
| 1143 | + break; |
| 1144 | +#endif |
| 1145 | #ifdef MC68MAGIC |
| 1146 | case MC68MAGIC: |
| 1147 | case M68MAGIC: |
| 1148 | @@ -2871,6 +2877,13 @@ |
| 1149 | return TRUE; |
| 1150 | #endif |
| 1151 | |
| 1152 | +#ifdef AVRMAGIC |
| 1153 | + case bfd_arch_avr: |
| 1154 | + *magicp = AVRMAGIC; |
| 1155 | + return TRUE; |
| 1156 | + break; |
| 1157 | +#endif |
| 1158 | + |
| 1159 | #ifdef PPCMAGIC |
| 1160 | case bfd_arch_powerpc: |
| 1161 | *magicp = PPCMAGIC; |
| 1162 | @@ -3698,6 +3711,11 @@ |
| 1163 | section.s_page = 0; |
| 1164 | #endif |
| 1165 | |
| 1166 | +#ifdef AVR |
| 1167 | + /* AVR uses s_paddr the way GNU uses s_vaddr, and effectively |
| 1168 | + ignores s_vaddr. */ |
| 1169 | + section.s_paddr = current->vma; |
| 1170 | +#endif |
| 1171 | #ifdef COFF_WITH_PE |
| 1172 | section.s_paddr = 0; |
| 1173 | #endif |
| 1174 | @@ -4042,6 +4060,17 @@ |
| 1175 | internal_a.magic = ZMAGIC; |
| 1176 | #endif |
| 1177 | |
| 1178 | +#ifdef AVR |
| 1179 | + /* a.out is a dummy for non-extended COFF */ |
| 1180 | + internal_a.magic = AVRAOUTMAGIC; |
| 1181 | + /* Upper nibble of f_flags must be set for historical reasons. |
| 1182 | + The upper byte remains blank on coff-avr, so undo the F_AR32WR |
| 1183 | + setting performed above. */ |
| 1184 | + internal_f.f_flags |= F_JUNK; |
| 1185 | + internal_f.f_flags &= ~F_UNUSED; |
| 1186 | +#define __A_MAGIC_SET__ |
| 1187 | +#endif /* AVR */ |
| 1188 | + |
| 1189 | #if defined(PPC_PE) |
| 1190 | #define __A_MAGIC_SET__ |
| 1191 | internal_a.magic = IMAGE_NT_OPTIONAL_HDR_MAGIC; |
| 1192 | @@ -4109,8 +4138,16 @@ |
| 1193 | #endif |
| 1194 | } |
| 1195 | |
| 1196 | +#ifdef AVR_EXT_COFF |
| 1197 | + /* Note that we do not set F_PTRINFO because the GNU toolchain |
| 1198 | + doesn't provide any information about the target of a pointer, |
| 1199 | + so we cannot derive which section our pointer target would be |
| 1200 | + in. */ |
| 1201 | + internal_a.vstamp = F_FULLPATHS | F_STRUCTINFO; |
| 1202 | +#else |
| 1203 | /* FIXME: Does anybody ever set this to another value? */ |
| 1204 | internal_a.vstamp = 0; |
| 1205 | +#endif |
| 1206 | |
| 1207 | /* Now should write relocs, strings, syms. */ |
| 1208 | obj_sym_filepos (abfd) = sym_base; |
| 1209 | @@ -4668,6 +4705,10 @@ |
| 1210 | /* In PE, 0x69 (105) denotes a weak external symbol. */ |
| 1211 | case C_NT_WEAK: |
| 1212 | #endif |
| 1213 | +#ifdef AVR |
| 1214 | + /* Some AVR COFF compilers handle EXTDEF like EXT. */ |
| 1215 | + case C_EXTDEF: /* external definition */ |
| 1216 | +#endif |
| 1217 | switch (coff_classify_symbol (abfd, &src->u.syment)) |
| 1218 | { |
| 1219 | case COFF_SYMBOL_GLOBAL: |
| 1220 | @@ -4891,7 +4932,9 @@ |
| 1221 | && src->u.syment.n_scnum == 0) |
| 1222 | break; |
| 1223 | /* Fall through. */ |
| 1224 | +#if !defined(AVR) |
| 1225 | case C_EXTDEF: /* External definition. */ |
| 1226 | +#endif |
| 1227 | case C_ULABEL: /* Undefined label. */ |
| 1228 | case C_USTATIC: /* Undefined static. */ |
| 1229 | #ifndef COFF_WITH_PE |
| 1230 | diff -Nruw bfd/coffgen.c bfd/coffgen.c |
| 1231 | --- bfd/coffgen.c 2009-09-10 17:17:12.000000000 +0530 |
| 1232 | +++ bfd/coffgen.c 2010-02-11 11:20:28.795092600 +0530 |
| 1233 | @@ -699,6 +699,20 @@ |
| 1234 | if (last_file != NULL) |
| 1235 | last_file->n_value = native_index; |
| 1236 | last_file = &(s->u.syment); |
| 1237 | + if (bfd_get_arch (bfd_ptr) == bfd_arch_avr |
| 1238 | + && bfd_coff_long_filenames (bfd_ptr) |
| 1239 | + && s->u.syment.n_numaux > 0) |
| 1240 | + { |
| 1241 | + /* AVR COFF records long filenames in successive aux |
| 1242 | + records. Adjust the number of aux records |
| 1243 | + required here, so the renumbering will account |
| 1244 | + for them. */ |
| 1245 | + unsigned int filnmlen = bfd_coff_filnmlen (bfd_ptr); |
| 1246 | + unsigned int namelen = strlen (coff_symbol_ptr->symbol.name); |
| 1247 | + unsigned int n = (namelen + filnmlen - 1) / filnmlen; |
| 1248 | + |
| 1249 | + s->u.syment.n_numaux = n > NAUXENTS? NAUXENTS: n; |
| 1250 | + } |
| 1251 | } |
| 1252 | else |
| 1253 | /* Modify the symbol values according to their section and |
| 1254 | @@ -827,6 +841,20 @@ |
| 1255 | { |
| 1256 | if (name_length <= filnmlen) |
| 1257 | strncpy (auxent->x_file.x_fname, name, filnmlen); |
| 1258 | + else if (bfd_get_arch (abfd) == bfd_arch_avr) |
| 1259 | + { |
| 1260 | + /* AVR COFF records long filenames in successive aux records. */ |
| 1261 | + int i = 1; |
| 1262 | + while (name_length > filnmlen && i < NAUXENTS) |
| 1263 | + { |
| 1264 | + strncpy (auxent->x_file.x_fname, name, filnmlen); |
| 1265 | + name += filnmlen; |
| 1266 | + name_length -= filnmlen; |
| 1267 | + i++; |
| 1268 | + auxent = &(native + i)->u.auxent; |
| 1269 | + } |
| 1270 | + strncpy (auxent->x_file.x_fname, name, filnmlen); |
| 1271 | + } |
| 1272 | else |
| 1273 | { |
| 1274 | auxent->x_file.x_n.x_offset = *string_size_p + STRING_SIZE_SIZE; |
| 1275 | @@ -1272,6 +1300,10 @@ |
| 1276 | if (bfd_bwrite (".file", (bfd_size_type) 6, abfd) != 6) |
| 1277 | return FALSE; |
| 1278 | } |
| 1279 | + if (bfd_get_arch (abfd) == bfd_arch_avr) |
| 1280 | + /* AVR COFF handles long file names in aux records. */ |
| 1281 | + maxlen = name_length; |
| 1282 | + else |
| 1283 | maxlen = bfd_coff_filnmlen (abfd); |
| 1284 | } |
| 1285 | else |
| 1286 | @@ -1710,14 +1742,27 @@ |
| 1287 | { |
| 1288 | /* Ordinary short filename, put into memory anyway. The |
| 1289 | Microsoft PE tools sometimes store a filename in |
| 1290 | - multiple AUX entries. */ |
| 1291 | + multiple AUX entries. |
| 1292 | + AVR COFF does it that way, too. */ |
| 1293 | if (internal_ptr->u.syment.n_numaux > 1 |
| 1294 | - && coff_data (abfd)->pe) |
| 1295 | - internal_ptr->u.syment._n._n_n._n_offset = |
| 1296 | - ((bfd_hostptr_t) |
| 1297 | - copy_name (abfd, |
| 1298 | - (internal_ptr + 1)->u.auxent.x_file.x_fname, |
| 1299 | - internal_ptr->u.syment.n_numaux * symesz)); |
| 1300 | + && (coff_data (abfd)->pe |
| 1301 | + || (bfd_get_arch (abfd) == bfd_arch_avr))) |
| 1302 | + { |
| 1303 | + char *b; |
| 1304 | + unsigned int i; |
| 1305 | + |
| 1306 | + /* We allocate enough storage to fit the contents of |
| 1307 | + this many aux records, and simply append a \0. |
| 1308 | + This ensures the string will always be |
| 1309 | + terminated, even in the case where it just fit |
| 1310 | + into the aux records. */ |
| 1311 | + b = (char *) bfd_alloc (abfd, |
| 1312 | + internal_ptr->u.syment.n_numaux * FILNMLEN + 1); |
| 1313 | + internal_ptr->u.syment._n._n_n._n_offset = (bfd_hostptr_t) b; |
| 1314 | + b[internal_ptr->u.syment.n_numaux * FILNMLEN] = '\0'; |
| 1315 | + for (i = 0; i < internal_ptr->u.syment.n_numaux; i++, b += FILNMLEN) |
| 1316 | + memcpy (b, (internal_ptr + i + 1)->u.auxent.x_file.x_fname, FILNMLEN); |
| 1317 | + } |
| 1318 | else |
| 1319 | internal_ptr->u.syment._n._n_n._n_offset = |
| 1320 | ((bfd_hostptr_t) |
| 1321 | @@ -1823,9 +1868,9 @@ |
| 1322 | |
| 1323 | if (new_symbol == NULL) |
| 1324 | return NULL; |
| 1325 | - /* @@ The 10 is a guess at a plausible maximum number of aux entries |
| 1326 | + /* @@ The NAUXENTS is a guess at a plausible maximum number of aux entries |
| 1327 | (but shouldn't be a constant). */ |
| 1328 | - amt = sizeof (combined_entry_type) * 10; |
| 1329 | + amt = sizeof (combined_entry_type) * (NAUXENTS + 1); |
| 1330 | new_symbol->native = (combined_entry_type *) bfd_zalloc (abfd, amt); |
| 1331 | if (!new_symbol->native) |
| 1332 | return NULL; |
| 1333 | diff -Nruw bfd/coffswap.h bfd/coffswap.h |
| 1334 | --- bfd/coffswap.h 2009-09-07 13:45:15.000000000 +0530 |
| 1335 | +++ bfd/coffswap.h 2010-02-11 11:24:25.908936000 +0530 |
| 1336 | @@ -383,7 +383,11 @@ |
| 1337 | void * ext1, |
| 1338 | int type, |
| 1339 | int in_class, |
| 1340 | - int indx, |
| 1341 | + int indx |
| 1342 | +#if defined(AVR) && __GNUC__ |
| 1343 | + __attribute__((unused)) |
| 1344 | +#endif |
| 1345 | + , |
| 1346 | int numaux, |
| 1347 | void * in1) |
| 1348 | { |
| 1349 | @@ -409,9 +413,13 @@ |
| 1350 | #else |
| 1351 | if (numaux > 1) |
| 1352 | { |
| 1353 | +#if defined(AVR) |
| 1354 | + memcpy (in->x_file.x_fname, ext->x_file.x_fname, sizeof (AUXENT)); |
| 1355 | +#else |
| 1356 | if (indx == 0) |
| 1357 | memcpy (in->x_file.x_fname, ext->x_file.x_fname, |
| 1358 | numaux * sizeof (AUXENT)); |
| 1359 | +#endif |
| 1360 | } |
| 1361 | else |
| 1362 | memcpy (in->x_file.x_fname, ext->x_file.x_fname, FILNMLEN); |
| 1363 | diff -Nruw bfd/config.bfd bfd/config.bfd |
| 1364 | --- bfd/config.bfd 2009-08-06 23:08:00.000000000 +0530 |
| 1365 | +++ bfd/config.bfd 2010-02-10 17:35:58.300224600 +0530 |
| 1366 | @@ -339,6 +339,7 @@ |
| 1367 | |
| 1368 | avr-*-*) |
| 1369 | targ_defvec=bfd_elf32_avr_vec |
| 1370 | + targ_selvecs="bfd_elf32_avr_vec avrcoff_vec avrextcoff_vec" |
| 1371 | ;; |
| 1372 | |
| 1373 | bfin-*-*) |
| 1374 | diff -Nruw bfd/configure bfd/configure |
| 1375 | --- bfd/configure 2009-10-16 17:17:47.000000000 +0530 |
| 1376 | +++ bfd/configure 2010-02-10 17:35:58.331474600 +0530 |
| 1377 | @@ -14782,6 +14782,8 @@ |
| 1378 | armpe_little_vec) tb="$tb pe-arm.lo peigen.lo cofflink.lo " ;; |
| 1379 | armpei_big_vec) tb="$tb pei-arm.lo peigen.lo cofflink.lo " ;; |
| 1380 | armpei_little_vec) tb="$tb pei-arm.lo peigen.lo cofflink.lo " ;; |
| 1381 | + avrcoff_vec) tb="$tb coff-avr.lo cofflink.lo " ;; |
| 1382 | + avrextcoff_vec) tb="$tb coff-ext-avr.lo cofflink.lo " ;; |
| 1383 | b_out_vec_big_host) tb="$tb bout.lo aout32.lo" ;; |
| 1384 | b_out_vec_little_host) tb="$tb bout.lo aout32.lo" ;; |
| 1385 | bfd_pei_ia64_vec) tb="$tb pei-ia64.lo pepigen.lo cofflink.lo"; target_size=64 ;; |
| 1386 | diff -Nruw bfd/configure.in bfd/configure.in |
| 1387 | --- bfd/configure.in 2009-10-16 17:17:44.000000000 +0530 |
| 1388 | +++ bfd/configure.in 2010-02-10 17:35:58.331474600 +0530 |
| 1389 | @@ -670,6 +670,8 @@ |
| 1390 | armpe_little_vec) tb="$tb pe-arm.lo peigen.lo cofflink.lo " ;; |
| 1391 | armpei_big_vec) tb="$tb pei-arm.lo peigen.lo cofflink.lo " ;; |
| 1392 | armpei_little_vec) tb="$tb pei-arm.lo peigen.lo cofflink.lo " ;; |
| 1393 | + avrcoff_vec) tb="$tb coff-avr.lo cofflink.lo " ;; |
| 1394 | + avrextcoff_vec) tb="$tb coff-ext-avr.lo cofflink.lo " ;; |
| 1395 | b_out_vec_big_host) tb="$tb bout.lo aout32.lo" ;; |
| 1396 | b_out_vec_little_host) tb="$tb bout.lo aout32.lo" ;; |
| 1397 | bfd_pei_ia64_vec) tb="$tb pei-ia64.lo pepigen.lo cofflink.lo"; target_size=64 ;; |
| 1398 | diff -Nruw bfd/targets.c bfd/targets.c |
| 1399 | --- bfd/targets.c 2009-09-10 17:17:13.000000000 +0530 |
| 1400 | +++ bfd/targets.c 2010-02-10 17:35:58.347099600 +0530 |
| 1401 | @@ -564,6 +564,8 @@ |
| 1402 | extern const bfd_target armpe_little_vec; |
| 1403 | extern const bfd_target armpei_big_vec; |
| 1404 | extern const bfd_target armpei_little_vec; |
| 1405 | +extern const bfd_target avrcoff_vec; |
| 1406 | +extern const bfd_target avrextcoff_vec; |
| 1407 | extern const bfd_target b_out_vec_big_host; |
| 1408 | extern const bfd_target b_out_vec_little_host; |
| 1409 | extern const bfd_target bfd_pei_ia64_vec; |
| 1410 | @@ -890,6 +892,8 @@ |
| 1411 | &armpe_little_vec, |
| 1412 | &armpei_big_vec, |
| 1413 | &armpei_little_vec, |
| 1414 | + &avrcoff_vec, |
| 1415 | + &avrextcoff_vec, |
| 1416 | &b_out_vec_big_host, |
| 1417 | &b_out_vec_little_host, |
| 1418 | #ifdef BFD64 |
| 1419 | diff -Nruw binutils/Makefile.am binutils/Makefile.am |
| 1420 | --- binutils/Makefile.am 2009-09-09 13:43:23.000000000 +0530 |
| 1421 | +++ binutils/Makefile.am 2010-02-10 17:35:57.972099600 +0530 |
| 1422 | @@ -101,7 +101,7 @@ |
| 1423 | resbin.c rescoff.c resrc.c resres.c \ |
| 1424 | size.c srconv.c stabs.c strings.c sysdump.c \ |
| 1425 | unwind-ia64.c version.c \ |
| 1426 | - windres.c winduni.c wrstabs.c \ |
| 1427 | + windres.c winduni.c wrcoff.c wrstabs.c \ |
| 1428 | windmc.c mclex.c |
| 1429 | |
| 1430 | GENERATED_CFILES = \ |
| 1431 | @@ -109,7 +109,7 @@ |
| 1432 | defparse.c deflex.c nlmheader.c rcparse.c mcparse.c |
| 1433 | |
| 1434 | DEBUG_SRCS = rddbg.c debug.c stabs.c ieee.c rdcoff.c |
| 1435 | -WRITE_DEBUG_SRCS = $(DEBUG_SRCS) wrstabs.c |
| 1436 | +WRITE_DEBUG_SRCS = $(DEBUG_SRCS) wrstabs.c wrcoff.c |
| 1437 | |
| 1438 | # Code shared by all the binutils. |
| 1439 | BULIBS = bucomm.c version.c filemode.c |
| 1440 | diff -Nruw binutils/Makefile.in binutils/Makefile.in |
| 1441 | --- binutils/Makefile.in 2009-09-09 13:43:23.000000000 +0530 |
| 1442 | +++ binutils/Makefile.in 2010-02-10 17:35:57.987724600 +0530 |
| 1443 | @@ -126,7 +126,7 @@ |
| 1444 | nm_new_OBJECTS = $(am_nm_new_OBJECTS) |
| 1445 | nm_new_LDADD = $(LDADD) |
| 1446 | am__objects_2 = rddbg.$(OBJEXT) debug.$(OBJEXT) stabs.$(OBJEXT) \ |
| 1447 | - ieee.$(OBJEXT) rdcoff.$(OBJEXT) |
| 1448 | + ieee.$(OBJEXT) rdcoff.$(OBJEXT) wrcoff.$(OBJEXT) |
| 1449 | am__objects_3 = $(am__objects_2) wrstabs.$(OBJEXT) |
| 1450 | am_objcopy_OBJECTS = objcopy.$(OBJEXT) not-strip.$(OBJEXT) \ |
| 1451 | rename.$(OBJEXT) $(am__objects_3) $(am__objects_1) |
| 1452 | @@ -439,7 +439,7 @@ |
| 1453 | resbin.c rescoff.c resrc.c resres.c \ |
| 1454 | size.c srconv.c stabs.c strings.c sysdump.c \ |
| 1455 | unwind-ia64.c version.c \ |
| 1456 | - windres.c winduni.c wrstabs.c \ |
| 1457 | + windres.c winduni.c wrcoff.c wrstabs.c \ |
| 1458 | windmc.c mclex.c |
| 1459 | |
| 1460 | GENERATED_CFILES = \ |
| 1461 | @@ -447,7 +447,7 @@ |
| 1462 | defparse.c deflex.c nlmheader.c rcparse.c mcparse.c |
| 1463 | |
| 1464 | DEBUG_SRCS = rddbg.c debug.c stabs.c ieee.c rdcoff.c |
| 1465 | -WRITE_DEBUG_SRCS = $(DEBUG_SRCS) wrstabs.c |
| 1466 | +WRITE_DEBUG_SRCS = $(DEBUG_SRCS) wrstabs.c wrcoff.c |
| 1467 | |
| 1468 | # Code shared by all the binutils. |
| 1469 | BULIBS = bucomm.c version.c filemode.c |
| 1470 | diff -Nruw binutils/bucomm.c binutils/bucomm.c |
| 1471 | --- binutils/bucomm.c 2009-09-14 17:13:26.000000000 +0530 |
| 1472 | +++ binutils/bucomm.c 2010-02-10 17:35:58.034599600 +0530 |
| 1473 | @@ -550,6 +550,32 @@ |
| 1474 | return ret; |
| 1475 | } |
| 1476 | |
| 1477 | +/* Return the basename of "file", i. e. everything minus whatever |
| 1478 | + directory part has been provided. Stolen from bfd/archive.c. |
| 1479 | + Should we also handle the VMS case (as in bfd/archive.c)? */ |
| 1480 | +const char * |
| 1481 | +bu_basename (file) |
| 1482 | + const char *file; |
| 1483 | +{ |
| 1484 | + const char *filename = strrchr (file, '/'); |
| 1485 | + |
| 1486 | +#ifdef HAVE_DOS_BASED_FILE_SYSTEM |
| 1487 | + { |
| 1488 | + /* We could have foo/bar\\baz, or foo\\bar, or d:bar. */ |
| 1489 | + char *bslash = strrchr (file, '\\'); |
| 1490 | + if (filename == NULL || (bslash != NULL && bslash > filename)) |
| 1491 | + filename = bslash; |
| 1492 | + if (filename == NULL && file[0] != '\0' && file[1] == ':') |
| 1493 | + filename = file + 1; |
| 1494 | + } |
| 1495 | +#endif |
| 1496 | + if (filename != (char *) NULL) |
| 1497 | + filename++; |
| 1498 | + else |
| 1499 | + filename = file; |
| 1500 | + return filename; |
| 1501 | +} |
| 1502 | + |
| 1503 | /* Returns the size of the named file. If the file does not |
| 1504 | exist, or if it is not a real file, then a suitable non-fatal |
| 1505 | error message is printed and zero is returned. */ |
| 1506 | diff -Nruw binutils/bucomm.h binutils/bucomm.h |
| 1507 | --- binutils/bucomm.h 2009-09-02 12:52:31.000000000 +0530 |
| 1508 | +++ binutils/bucomm.h 2010-02-10 17:35:58.050224600 +0530 |
| 1509 | @@ -58,6 +58,8 @@ |
| 1510 | |
| 1511 | off_t get_file_size (const char *); |
| 1512 | |
| 1513 | +const char *bu_basename PARAMS ((const char *)); |
| 1514 | + |
| 1515 | extern char *program_name; |
| 1516 | |
| 1517 | /* filemode.c */ |
| 1518 | diff -Nruw binutils/budbg.h binutils/budbg.h |
| 1519 | --- binutils/budbg.h 2009-09-02 12:52:31.000000000 +0530 |
| 1520 | +++ binutils/budbg.h 2010-02-10 17:35:58.050224600 +0530 |
| 1521 | @@ -52,8 +52,11 @@ |
| 1522 | |
| 1523 | extern bfd_boolean write_ieee_debugging_info (bfd *, void *); |
| 1524 | |
| 1525 | -/* Routine used to read COFF debugging information. */ |
| 1526 | +/* Routine used to read and write COFF debugging information. */ |
| 1527 | |
| 1528 | extern bfd_boolean parse_coff (bfd *, asymbol **, long, void *); |
| 1529 | |
| 1530 | +extern bfd_boolean write_coff_debugging_info |
| 1531 | + (bfd *abfd, void *, long *symcountp, asymbol ***); |
| 1532 | + |
| 1533 | #endif |
| 1534 | diff -Nruw binutils/debug.c binutils/debug.c |
| 1535 | --- binutils/debug.c 2009-09-14 17:13:26.000000000 +0530 |
| 1536 | +++ binutils/debug.c 2010-02-11 10:50:38.043866600 +0530 |
| 1537 | @@ -31,6 +31,7 @@ |
| 1538 | #include <assert.h> |
| 1539 | #include "bfd.h" |
| 1540 | #include "libiberty.h" |
| 1541 | +#include "bucomm.h" |
| 1542 | #include "debug.h" |
| 1543 | |
| 1544 | /* Global information we keep for debugging. A pointer to this |
| 1545 | @@ -552,6 +553,19 @@ |
| 1546 | struct debug_type_s *t; |
| 1547 | }; |
| 1548 | |
| 1549 | +/* Simple list, used for pathname translations. */ |
| 1550 | +struct xlat_list |
| 1551 | +{ |
| 1552 | + /* Next string on list. */ |
| 1553 | + struct xlat_list *next; |
| 1554 | + /* Old part to match against. */ |
| 1555 | + const char *old; |
| 1556 | + size_t olen; |
| 1557 | + /* New part to replace. */ |
| 1558 | + const char *newstr; |
| 1559 | + size_t nlen; |
| 1560 | +}; |
| 1561 | + |
| 1562 | /* Local functions. */ |
| 1563 | |
| 1564 | static void debug_error (const char *); |
| 1565 | @@ -588,6 +602,11 @@ |
| 1566 | (struct debug_handle *, struct debug_type_s *, struct debug_type_s *); |
| 1567 | static bfd_boolean debug_class_type_samep |
| 1568 | (struct debug_handle *, struct debug_type_s *, struct debug_type_s *); |
| 1569 | +static const char *debug_xlat_pathname (const char *); |
| 1570 | + |
| 1571 | +/* List of pathname translations. */ |
| 1572 | +static struct xlat_list *xlat, *xltail; |
| 1573 | +static bfd_boolean xlat_basename; |
| 1574 | |
| 1841 | /* Return the slot for a type. */ |
| 1842 | |
| 1843 | @@ -271,8 +275,7 @@ |
| 1844 | break; |
| 1845 | |
| 1846 | case T_INT: |
| 1847 | - /* FIXME: Perhaps the size should depend upon the architecture. */ |
| 1848 | - ret = debug_make_int_type (dhandle, 4, FALSE); |
| 1849 | + ret = debug_make_int_type (dhandle, types->intsize, FALSE); |
| 1850 | name = "int"; |
| 1851 | break; |
| 1852 | |
| 1853 | @@ -287,7 +290,7 @@ |
| 1854 | break; |
| 1855 | |
| 1856 | case T_DOUBLE: |
| 1857 | - ret = debug_make_float_type (dhandle, 8); |
| 1858 | + ret = debug_make_float_type (dhandle, types->doublesize); |
| 1859 | name = "double"; |
| 1860 | break; |
| 1861 | |
| 1862 | @@ -307,7 +310,7 @@ |
| 1863 | break; |
| 1864 | |
| 1865 | case T_UINT: |
| 1866 | - ret = debug_make_int_type (dhandle, 4, TRUE); |
| 1867 | + ret = debug_make_int_type (dhandle, types->intsize, TRUE); |
| 1868 | name = "unsigned int"; |
| 1869 | break; |
| 1870 | |
| 1871 | @@ -565,6 +568,8 @@ |
| 1872 | |
| 1873 | case C_WEAKEXT: |
| 1874 | case C_EXT: |
| 1875 | + /* AVR COFF abuses C_EXTDEF */ |
| 1876 | + case C_EXTDEF: |
| 1877 | if (! debug_record_variable (dhandle, bfd_asymbol_name (sym), type, |
| 1878 | DEBUG_GLOBAL, bfd_asymbol_value (sym))) |
| 1879 | return FALSE; |
| 1880 | @@ -580,9 +585,9 @@ |
| 1881 | break; |
| 1882 | |
| 1883 | case C_REG: |
| 1884 | - /* FIXME: We may need to convert the register number. */ |
| 1885 | if (! debug_record_variable (dhandle, bfd_asymbol_name (sym), type, |
| 1886 | - DEBUG_REGISTER, bfd_asymbol_value (sym))) |
| 1887 | + DEBUG_REGISTER, |
| 1888 | + coff_convert_register (abfd, bfd_asymbol_value (sym)))) |
| 1889 | return FALSE; |
| 1890 | break; |
| 1891 | |
| 1892 | @@ -596,9 +601,9 @@ |
| 1893 | break; |
| 1894 | |
| 1895 | case C_REGPARM: |
| 1896 | - /* FIXME: We may need to convert the register number. */ |
| 1897 | if (! debug_record_parameter (dhandle, bfd_asymbol_name (sym), type, |
| 1898 | - DEBUG_PARM_REG, bfd_asymbol_value (sym))) |
| 1899 | + DEBUG_PARM_REG, |
| 1900 | + coff_convert_register (abfd, bfd_asymbol_value (sym)))) |
| 1901 | return FALSE; |
| 1902 | break; |
| 1903 | |
| 1904 | @@ -648,6 +653,28 @@ |
| 1905 | return FALSE; |
| 1906 | } |
| 1907 | |
| 1908 | +static bfd_vma |
| 1909 | +coff_convert_register (abfd, val) |
| 1910 | + bfd *abfd; |
| 1911 | + bfd_vma val; |
| 1912 | +{ |
| 1913 | + |
| 1914 | + switch (bfd_get_arch (abfd)) |
| 1915 | + { |
| 1916 | + case bfd_arch_avr: |
| 1917 | + /* AVR COFF wants to describe up to four registers by the four |
| 1918 | + bytes of the 32-bit value. Unused bytes are filled with |
| 1919 | + 0xff. In theory, this would allow for non-contiguous |
| 1920 | + register usage to hold a single value, but hopefully, no |
| 1921 | + compiler is going to use that feature. We could not handle |
| 1922 | + it anyway. */ |
| 1923 | + return val & 0xff; |
| 1924 | + |
| 1925 | + default: |
| 1926 | + return val; |
| 1927 | + } |
| 1928 | +} |
| 1929 | + |
| 1930 | /* This is the main routine. It looks through all the symbols and |
| 1931 | handles them. */ |
| 1932 | |
| 1933 | @@ -674,6 +701,17 @@ |
| 1934 | types.slots = NULL; |
| 1935 | for (i = 0; i <= T_MAX; i++) |
| 1936 | types.basic[i] = DEBUG_TYPE_NULL; |
| 1937 | + switch (bfd_get_arch (abfd)) |
| 1938 | + { |
| 1939 | + case bfd_arch_avr: |
| 1940 | + types.intsize = 2; |
| 1941 | + types.doublesize = 4; |
| 1942 | + break; |
| 1943 | + |
| 1944 | + default: |
| 1945 | + types.intsize = 4; |
| 1946 | + types.doublesize = 8; |
| 1947 | + } |
| 1948 | |
| 1949 | next_c_file = -1; |
| 1950 | fnname = NULL; |
| 1951 | @@ -734,7 +772,6 @@ |
| 1952 | switch (syment.n_sclass) |
| 1953 | { |
| 1954 | case C_EFCN: |
| 1955 | - case C_EXTDEF: |
| 1956 | case C_ULABEL: |
| 1957 | case C_USTATIC: |
| 1958 | case C_LINE: |
| 1959 | @@ -757,6 +794,8 @@ |
| 1960 | /* Fall through. */ |
| 1961 | case C_WEAKEXT: |
| 1962 | case C_EXT: |
| 1963 | + /* AVR COFF abuses C_EXTDEF for C_EXT */ |
| 1964 | + case C_EXTDEF: |
| 1965 | if (ISFCN (syment.n_type)) |
| 1966 | { |
| 1967 | fnname = name; |
| 1968 | diff -Nruw binutils/wrcoff.c binutils/wrcoff.c |
| 1969 | --- binutils/wrcoff.c 1970-01-01 05:30:00.000000000 +0530 |
| 1970 | +++ binutils/wrcoff.c 2010-02-10 17:35:58.159599600 +0530 |
| 1971 | @@ -0,0 +1,3410 @@ |
| 1972 | +/* wrcoff.c -- Generate (AVR) COFF debugging information |
| 1973 | + Copyright 2003 Free Software Foundation, Inc. |
| 1974 | + |
| 1975 | + Written by Joerg Wunsch. |
| 1976 | + |
| 1977 | + This file is part of GNU Binutils. |
| 1978 | + |
| 1979 | + This program is free software; you can redistribute it and/or modify |
| 1980 | + it under the terms of the GNU General Public License as published by |
| 1981 | + the Free Software Foundation; either version 2 of the License, or |
| 1982 | + (at your option) any later version. |
| 1983 | + |
| 1984 | + This program is distributed in the hope that it will be useful, |
| 1985 | + but WITHOUT ANY WARRANTY; without even the implied warranty of |
| 1986 | + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| 1987 | + GNU General Public License for more details. |
| 1988 | + |
| 1989 | + You should have received a copy of the GNU General Public License |
| 1990 | + along with this program; if not, write to the Free Software |
| 1991 | + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA |
| 1992 | + 02111-1307, USA. */ |
| 1993 | + |
| 1994 | +/* This file contains code which writes out COFF debugging |
| 1995 | + information. By now, this has only been tested on the AVR |
| 1996 | + platform, though any attempt has been made to keep the conversion |
| 1997 | + applicable to possible other COFF debugging consumers as well. */ |
| 1998 | + |
| 1999 | +#include <stdio.h> |
| 2000 | +#include <assert.h> |
| 2001 | + |
| 2002 | +#include "sysdep.h" |
| 2003 | +#include "bfd.h" |
| 2004 | +#include "coff/internal.h" |
| 2005 | +#include "bucomm.h" |
| 2006 | +#include "libiberty.h" |
| 2007 | +#include "safe-ctype.h" |
| 2008 | +#include "debug.h" |
| 2009 | +#include "budbg.h" |
| 2010 | + |
| 2011 | +/* Enabling COFF_DEBUG will trace the internal callback functions and |
| 2012 | + their parameters as debug_write() calls them. */ |
| 2013 | +//#define COFF_DEBUG 1 |
| 2014 | + |
| 2015 | +#include "libcoff.h" |
| 2016 | + |
| 2017 | +#define N_TMASK (coff_data (info->abfd)->local_n_tmask) |
| 2018 | +#define N_BTSHFT (coff_data (info->abfd)->local_n_btshft) |
| 2019 | +#define N_BTMASK (coff_data (info->abfd)->local_n_btmask) |
| 2020 | +#define N_TSHIFT (coff_data (info->abfd)->local_n_tshift) |
| 2021 | + |
| 2022 | +/* Structure of local symbols per compilation unit. */ |
| 2023 | +struct coff_compilation_unit |
| 2024 | +{ |
| 2025 | + const char *fname; |
| 2026 | + asymbol **syms; |
| 2027 | + long nsyms, totsyms; |
| 2028 | +}; |
| 2029 | + |
| 2030 | +enum ts_kind |
| 2031 | +{ |
| 2032 | + TS_EMPTY, |
| 2033 | + TS_VOID, |
| 2034 | + TS_INT, |
| 2035 | + TS_FLOAT, |
| 2036 | + TS_COMPLEX, |
| 2037 | + TS_ENUM, |
| 2038 | + TS_POINTER, |
| 2039 | + TS_FUNC, |
| 2040 | + TS_ARRAY, |
| 2041 | + TS_STRUCT, |
| 2042 | + TS_NONE = -1 |
| 2043 | +}; |
| 2044 | + |
| 2045 | +/* Structure defining the pre-defined types. */ |
| 2046 | +struct coff_predef_type |
| 2047 | +{ |
| 2048 | + enum ts_kind kind; |
| 2049 | + unsigned int size; /* in bytes */ |
| 2050 | + bfd_boolean isunsigned; |
| 2051 | + int slot; |
| 2052 | +}; |
| 2053 | + |
| 2054 | +struct coff_type_stack; |
| 2055 | +struct coff_hash_entry; |
| 2056 | + |
| 2057 | +struct coff_struct_fields |
| 2058 | +{ |
| 2059 | + const char *name; |
| 2060 | + bfd_vma bitpos; |
| 2061 | + bfd_vma bitsize; |
| 2062 | + enum debug_visibility visibility; |
| 2063 | + struct coff_type_stack *types; |
| 2064 | +}; |
| 2065 | + |
| 2066 | +/* Our type stack. */ |
| 2067 | +struct coff_type_stack |
| 2068 | +{ |
| 2069 | + struct coff_type_stack *next; |
| 2070 | + enum ts_kind tsk; |
| 2071 | + union |
| 2072 | + { |
| 2073 | + /* TS_INT */ |
| 2074 | + struct |
| 2075 | + { |
| 2076 | + unsigned int size; |
| 2077 | + bfd_boolean isunsigned; |
| 2078 | + } |
| 2079 | + ts_int; |
| 2080 | + |
| 2081 | + /* TS_FLOAT */ |
| 2082 | + struct |
| 2083 | + { |
| 2084 | + unsigned int size; |
| 2085 | + } |
| 2086 | + ts_float; |
| 2087 | + |
| 2088 | + /* TS_ENUM */ |
| 2089 | + struct |
| 2090 | + { |
| 2091 | + union |
| 2092 | + { |
| 2093 | + const char *fixtag; |
| 2094 | + char *malloctag; |
| 2095 | + } |
| 2096 | + tag; |
| 2097 | + bfd_boolean tagismalloced; |
| 2098 | + const char **names; |
| 2099 | + bfd_signed_vma *vals; |
| 2100 | + struct coff_enum_hash_entry *ehash; |
| 2101 | + } |
| 2102 | + ts_enum; |
| 2103 | + |
| 2104 | + /* TS_FUNC */ |
| 2105 | + struct |
| 2106 | + { |
| 2107 | + struct coff_type_stack *savedts; |
| 2108 | + } |
| 2109 | + ts_func; |
| 2110 | + |
| 2111 | + /* TS_ARRAY */ |
| 2112 | + struct |
| 2113 | + { |
| 2114 | + bfd_signed_vma low; |
| 2115 | + bfd_signed_vma high; |
| 2116 | + } |
| 2117 | + ts_array; |
| 2118 | + |
| 2119 | + /* TS_STRUCT */ |
| 2120 | + struct |
| 2121 | + { |
| 2122 | + union |
| 2123 | + { |
| 2124 | + const char *fixtag; |
| 2125 | + char *malloctag; |
| 2126 | + } |
| 2127 | + tag; |
| 2128 | + bfd_boolean tagismalloced; |
| 2129 | + unsigned int id; |
| 2130 | + bfd_boolean isstruct; |
| 2131 | + unsigned int size; |
| 2132 | + long nfields; |
| 2133 | + struct coff_struct_fields *fields; |
| 2134 | + struct coff_type_stack *savedts; |
| 2135 | + struct coff_struct_hash_entry *shash; |
| 2136 | + } |
| 2137 | + ts_struct; |
| 2138 | + } |
| 2139 | + u; |
| 2140 | +}; |
| 2141 | + |
| 2142 | +struct coff_name_type_hash_table |
| 2143 | +{ |
| 2144 | + struct bfd_hash_table root; |
| 2145 | +}; |
| 2146 | + |
| 2147 | +struct coff_name_type_hash_entry |
| 2148 | +{ |
| 2149 | + struct bfd_hash_entry root; |
| 2150 | + /* Information for this name. */ |
| 2151 | + struct coff_type_stack *types; |
| 2152 | + bfd_boolean emitted; |
| 2153 | +}; |
| 2154 | + |
| 2155 | +struct coff_struct_hash_table |
| 2156 | +{ |
| 2157 | + struct bfd_hash_table root; |
| 2158 | +}; |
| 2159 | + |
| 2160 | +struct coff_struct_hash_entry |
| 2161 | +{ |
| 2162 | + struct bfd_hash_entry root; |
| 2163 | + /* Information for this name. */ |
| 2164 | + struct coff_type_stack *types; |
| 2165 | + bfd_boolean emitted; |
| 2166 | + combined_entry_type *native; |
| 2167 | + /* list of symbol indices that need fixing */ |
| 2168 | + long *fixidxs; |
| 2169 | + unsigned nfixidxs; |
| 2170 | +}; |
| 2171 | + |
| 2172 | +struct coff_enum_hash_table |
| 2173 | +{ |
| 2174 | + struct bfd_hash_table root; |
| 2175 | +}; |
| 2176 | + |
| 2177 | +struct coff_enum_hash_entry |
| 2178 | +{ |
| 2179 | + struct bfd_hash_entry root; |
| 2180 | + /* Information for this name. */ |
| 2181 | + struct coff_type_stack *types; |
| 2182 | + bfd_boolean emitted; |
| 2183 | + combined_entry_type *native; |
| 2184 | + /* list of symbol indices that need fixing */ |
| 2185 | + long *fixidxs; |
| 2186 | + unsigned nfixidxs; |
| 2187 | +}; |
| 2188 | + |
| 2189 | +/* COFF private symbol data. Used as a cookie to pass data around |
| 2190 | + between various processing stages. The generic COFF handling code |
| 2191 | + doesn't use any private data. */ |
| 2192 | +struct coff_private_symdata |
| 2193 | +{ |
| 2194 | + unsigned int size; /* size of symbol, used in AVR register |
| 2195 | + translation */ |
| 2196 | + struct coff_struct_hash_entry *shash; /* TS_STRUCT hash for fixups */ |
| 2197 | + struct coff_enum_hash_entry *ehash; /* TS_ENUM hash for fixups */ |
| 2198 | +}; |
| 2199 | + |
| 2200 | +/* Stack of tags that need endndx fixing. */ |
| 2201 | +struct coff_fix_stack |
| 2202 | +{ |
| 2203 | + struct coff_fix_stack *next; |
| 2204 | + combined_entry_type *native; |
| 2205 | +}; |
| 2206 | + |
| 2207 | +/* This is the handle passed through debug_write. */ |
| 2208 | + |
| 2209 | +struct coff_write_handle |
| 2210 | +{ |
| 2211 | + /* The BFD. */ |
| 2212 | + bfd *abfd; |
| 2213 | + /* Pointers to .text and .data sections, can be used as defaults if |
| 2214 | + no other information is available. */ |
| 2215 | + asection *textsect; |
| 2216 | + asection *datasect; |
| 2217 | + /* Some special flags. */ |
| 2218 | + unsigned long flags; |
| 2219 | + /* Flags describing architecture options. */ |
| 2220 | +#define COFF_FL_AVR 0x0001 /* COFF is for AVR platform. */ |
| 2221 | +#define COFF_FL_EXT_AVR 0x0002 /* AVR "extended" COFF */ |
| 2222 | + /* Flags describing internal status information. */ |
| 2223 | +#define COFF_FL_FIX_ENDNDX 0x10000 /* apply endndx fix at next symbol */ |
| 2224 | +#define COFF_FL_START_FCN 0x20000 /* begin of function pending */ |
| 2225 | +#define COFF_FL_FIX_BB 0x40000 /* fix last ".bb" symbol */ |
| 2226 | + /* List of our compilation units, from input symbol table. */ |
| 2227 | + struct coff_compilation_unit *units; |
| 2228 | + long nunits; |
| 2229 | + struct coff_compilation_unit *currentfile; |
| 2230 | + /* Global symbols from input symbol table. */ |
| 2231 | + asymbol **globals; |
| 2232 | + long nglobals; |
| 2233 | + /* Section syms for named sections. */ |
| 2234 | + coff_symbol_type **secsyms; |
| 2235 | + long nsecsyms; |
| 2236 | + /* Our COFF symbols. */ |
| 2237 | + asymbol **syms; |
| 2238 | + long nsyms; |
| 2239 | + /* Total line number count. */ |
| 2240 | + unsigned long totlnos; |
| 2241 | + /* Size of standard objects on this arch. */ |
| 2242 | + unsigned int pointersize; |
| 2243 | + unsigned int enumsize; |
| 2244 | + /* Pending information when starting a function. We have to defer |
| 2245 | + almost everything, some actions can be taken when seeing the |
| 2246 | + starting block of that function, some will even have to wait |
| 2247 | + until we see the end of the function. */ |
| 2248 | + const char *funname; /* name of function */ |
| 2249 | + bfd_boolean funglobal; /* global/local function? */ |
| 2250 | + unsigned int lastlno; /* last line number seen so far */ |
| 2251 | + long funcindex; /* index of ".func" symbol in syms */ |
| 2252 | + unsigned int nlnos; /* line numbers recorded for this function*/ |
| 2253 | + bfd_vma endaddr; /* last .eb address we have seen so far */ |
| 2254 | + unsigned int funlno; /* first line number in function */ |
| 2255 | + coff_symbol_type **fargs; /* function arguments */ |
| 2256 | + unsigned int nfargs; |
| 2257 | + asection *funcsection; /* section the current function is using */ |
| 2258 | + /* Type information */ |
| 2259 | + struct coff_type_stack *tstack; |
| 2260 | + struct coff_name_type_hash_table types; |
| 2261 | + struct coff_struct_hash_table structs; |
| 2262 | + struct coff_enum_hash_table enums; |
| 2263 | + unsigned nenums; /* counter for anonymous enum tags */ |
| 2264 | + /* Stack of pending endndx fixes, see coff_record_symbol(). */ |
| 2265 | + struct coff_fix_stack *fixes; |
| 2266 | +}; |
| 2267 | + |
| 2268 | +/* Predefined types, default to usual 32-bit architectures. |
| 2269 | + Arch-dependant different byte sizes will be tuned upon entering |
| 2270 | + write_coff_debugging_info(). The table is looked up from front to |
| 2271 | + end, so we put `more popular' types that might have the same size |
| 2272 | + as other types first (e. g. "int" precedes "long" and "short"). */ |
| 2273 | +static struct coff_predef_type coff_predef_types[] = |
| 2274 | +{ |
| 2275 | + { TS_INT, 4, FALSE, 4 }, /* signed int */ |
| 2276 | + { TS_INT, 1, FALSE, 2 }, /* signed char */ |
| 2277 | + { TS_INT, 2, FALSE, 3 }, /* signed short */ |
| 2278 | + { TS_INT, 4, FALSE, 5 }, /* long int */ |
| 2279 | + { TS_FLOAT, 8, FALSE, 7 }, /* double */ |
| 2280 | + { TS_FLOAT, 4, FALSE, 6 }, /* float */ |
| 2281 | + { TS_INT, 4, TRUE, 14 }, /* unsigned int */ |
| 2282 | + { TS_INT, 1, TRUE, 12 }, /* unsigned char */ |
| 2283 | + { TS_INT, 2, TRUE, 13 }, /* unsigned short */ |
| 2284 | + { TS_INT, 4, TRUE, 15 }, /* unsigned long */ |
| 2285 | +}; |
| 2286 | + |
| 2287 | +static bfd_boolean coff_copy_symbols |
| 2288 | + PARAMS ((struct coff_write_handle *, long, asymbol **)); |
| 2289 | +static asymbol *coff_find_symbol |
| 2290 | + PARAMS ((struct coff_write_handle *, const char *, bfd_boolean, bfd_boolean)); |
| 2291 | +static void coff_record_symbol |
| 2292 | + PARAMS ((struct coff_write_handle *, coff_symbol_type *)); |
| 2293 | +static symvalue coff_fixup_avr_register PARAMS ((symvalue, int)); |
| 2294 | +static struct bfd_hash_entry *coff_name_type_newfunc |
| 2295 | + PARAMS ((struct bfd_hash_entry *, struct bfd_hash_table *, const char *)); |
| 2296 | +static bfd_boolean coff_free_type_info |
| 2297 | + PARAMS ((struct coff_name_type_hash_entry *, PTR)); |
| 2298 | +static struct bfd_hash_entry *coff_struct_newfunc |
| 2299 | + PARAMS ((struct bfd_hash_entry *, struct bfd_hash_table *, const char *)); |
| 2300 | +static bfd_boolean coff_free_struct_info |
| 2301 | + PARAMS ((struct coff_struct_hash_entry *, PTR)); |
| 2302 | +static struct bfd_hash_entry *coff_enum_newfunc |
| 2303 | + PARAMS ((struct bfd_hash_entry *, struct bfd_hash_table *, const char *)); |
| 2304 | +static bfd_boolean coff_free_enum_info |
| 2305 | + PARAMS ((struct coff_enum_hash_entry *, PTR)); |
| 2306 | +static unsigned int coff_get_fundamental_type |
| 2307 | + PARAMS ((struct coff_write_handle *, struct coff_type_stack *)); |
| 2308 | +static bfd_boolean coff_make_typed_symbol |
| 2309 | + PARAMS ((struct coff_write_handle *, coff_symbol_type **, enum ts_kind)); |
| 2310 | +static bfd_boolean coff_emit_struct |
| 2311 | + PARAMS ((struct coff_write_handle *, struct coff_type_stack *, |
| 2312 | + struct coff_struct_hash_entry *)); |
| 2313 | +static bfd_boolean coff_emit_enum |
| 2314 | + PARAMS ((struct coff_write_handle *, struct coff_type_stack *, |
| 2315 | + struct coff_enum_hash_entry *)); |
| 2316 | +static bfd_boolean coff_emit_ndebug_sym |
| 2317 | + PARAMS ((struct coff_write_handle *, asymbol *, bfd_boolean)); |
| 2318 | + |
| 2319 | +static bfd_boolean coff_start_compilation_unit PARAMS ((PTR, const char *)); |
| 2320 | +static bfd_boolean coff_start_source PARAMS ((PTR, const char *)); |
| 2321 | +static bfd_boolean coff_empty_type PARAMS ((PTR)); |
| 2322 | +static bfd_boolean coff_void_type PARAMS ((PTR)); |
| 2323 | +static bfd_boolean coff_int_type PARAMS ((PTR, unsigned int, bfd_boolean)); |
| 2324 | +static bfd_boolean coff_float_type PARAMS ((PTR, unsigned int)); |
| 2325 | +static bfd_boolean coff_complex_type PARAMS ((PTR, unsigned int)); |
| 2326 | +static bfd_boolean coff_bool_type PARAMS ((PTR, unsigned int)); |
| 2327 | +static bfd_boolean coff_enum_type |
| 2328 | + PARAMS ((PTR, const char *, const char **, bfd_signed_vma *)); |
| 2329 | +static bfd_boolean coff_pointer_type PARAMS ((PTR)); |
| 2330 | +static bfd_boolean coff_function_type PARAMS ((PTR, int, bfd_boolean)); |
| 2331 | +static bfd_boolean coff_reference_type PARAMS ((PTR)); |
| 2332 | +static bfd_boolean coff_range_type PARAMS ((PTR, bfd_signed_vma, bfd_signed_vma)); |
| 2333 | +static bfd_boolean coff_array_type |
| 2334 | + PARAMS ((PTR, bfd_signed_vma, bfd_signed_vma, bfd_boolean)); |
| 2335 | +static bfd_boolean coff_set_type PARAMS ((PTR, bfd_boolean)); |
| 2336 | +static bfd_boolean coff_offset_type PARAMS ((PTR)); |
| 2337 | +static bfd_boolean coff_method_type PARAMS ((PTR, bfd_boolean, int, bfd_boolean)); |
| 2338 | +static bfd_boolean coff_const_type PARAMS ((PTR)); |
| 2339 | +static bfd_boolean coff_volatile_type PARAMS ((PTR)); |
| 2340 | +static bfd_boolean coff_start_struct_type |
| 2341 | + PARAMS ((PTR, const char *, unsigned int, bfd_boolean, unsigned int)); |
| 2342 | +static bfd_boolean coff_struct_field |
| 2343 | + PARAMS ((PTR, const char *, bfd_vma, bfd_vma, enum debug_visibility)); |
| 2344 | +static bfd_boolean coff_end_struct_type PARAMS ((PTR)); |
| 2345 | +static bfd_boolean coff_start_class_type |
| 2346 | + PARAMS ((PTR, const char *, unsigned int, bfd_boolean, unsigned int, bfd_boolean, |
| 2347 | + bfd_boolean)); |
| 2348 | +static bfd_boolean coff_class_static_member |
| 2349 | + PARAMS ((PTR, const char *, const char *, enum debug_visibility)); |
| 2350 | +static bfd_boolean coff_class_baseclass |
| 2351 | + PARAMS ((PTR, bfd_vma, bfd_boolean, enum debug_visibility)); |
| 2352 | +static bfd_boolean coff_class_start_method PARAMS ((PTR, const char *)); |
| 2353 | +static bfd_boolean coff_class_method_variant |
| 2354 | + PARAMS ((PTR, const char *, enum debug_visibility, bfd_boolean, bfd_boolean, |
| 2355 | + bfd_vma, bfd_boolean)); |
| 2356 | +static bfd_boolean coff_class_static_method_variant |
| 2357 | + PARAMS ((PTR, const char *, enum debug_visibility, bfd_boolean, bfd_boolean)); |
| 2358 | +static bfd_boolean coff_class_end_method PARAMS ((PTR)); |
| 2359 | +static bfd_boolean coff_end_class_type PARAMS ((PTR)); |
| 2360 | +static bfd_boolean coff_typedef_type PARAMS ((PTR, const char *)); |
| 2361 | +static bfd_boolean coff_tag_type |
| 2362 | + PARAMS ((PTR, const char *, unsigned int, enum debug_type_kind)); |
| 2363 | +static bfd_boolean coff_typdef PARAMS ((PTR, const char *)); |
| 2364 | +static bfd_boolean coff_tag PARAMS ((PTR, const char *)); |
| 2365 | +static bfd_boolean coff_int_constant PARAMS ((PTR, const char *, bfd_vma)); |
| 2366 | +static bfd_boolean coff_float_constant PARAMS ((PTR, const char *, double)); |
| 2367 | +static bfd_boolean coff_typed_constant PARAMS ((PTR, const char *, bfd_vma)); |
| 2368 | +static bfd_boolean coff_variable |
| 2369 | + PARAMS ((PTR, const char *, enum debug_var_kind, bfd_vma)); |
| 2370 | +static bfd_boolean coff_start_function PARAMS ((PTR, const char *, bfd_boolean)); |
| 2371 | +static bfd_boolean coff_function_parameter |
| 2372 | + PARAMS ((PTR, const char *, enum debug_parm_kind, bfd_vma)); |
| 2373 | +static bfd_boolean coff_start_block PARAMS ((PTR, bfd_vma)); |
| 2374 | +static bfd_boolean coff_end_block PARAMS ((PTR, bfd_vma)); |
| 2375 | +static bfd_boolean coff_end_function PARAMS ((PTR)); |
| 2376 | +static bfd_boolean coff_lineno |
| 2377 | + PARAMS ((PTR, const char *, unsigned long, bfd_vma)); |
| 2378 | + |
| 2379 | +static const struct debug_write_fns coff_fns = |
| 2380 | +{ |
| 2381 | + coff_start_compilation_unit, |
| 2382 | + coff_start_source, |
| 2383 | + coff_empty_type, |
| 2384 | + coff_void_type, |
| 2385 | + coff_int_type, |
| 2386 | + coff_float_type, |
| 2387 | + coff_complex_type, |
| 2388 | + coff_bool_type, |
| 2389 | + coff_enum_type, |
| 2390 | + coff_pointer_type, |
| 2391 | + coff_function_type, |
| 2392 | + coff_reference_type, |
| 2393 | + coff_range_type, |
| 2394 | + coff_array_type, |
| 2395 | + coff_set_type, |
| 2396 | + coff_offset_type, |
| 2397 | + coff_method_type, |
| 2398 | + coff_const_type, |
| 2399 | + coff_volatile_type, |
| 2400 | + coff_start_struct_type, |
| 2401 | + coff_struct_field, |
| 2402 | + coff_end_struct_type, |
| 2403 | + coff_start_class_type, |
| 2404 | + coff_class_static_member, |
| 2405 | + coff_class_baseclass, |
| 2406 | + coff_class_start_method, |
| 2407 | + coff_class_method_variant, |
| 2408 | + coff_class_static_method_variant, |
| 2409 | + coff_class_end_method, |
| 2410 | + coff_end_class_type, |
| 2411 | + coff_typedef_type, |
| 2412 | + coff_tag_type, |
| 2413 | + coff_typdef, |
| 2414 | + coff_tag, |
| 2415 | + coff_int_constant, |
| 2416 | + coff_float_constant, |
| 2417 | + coff_typed_constant, |
| 2418 | + coff_variable, |
| 2419 | + coff_start_function, |
| 2420 | + coff_function_parameter, |
| 2421 | + coff_start_block, |
| 2422 | + coff_end_block, |
| 2423 | + coff_end_function, |
| 2424 | + coff_lineno |
| 2425 | +}; |
| 2426 | + |
| 2428 | +/* |
| 2429 | + * Copy our input (non-debugging) symbols. Local symbols will be |
| 2430 | + * maintained in one bucket per each compilation unit, global (and |
| 2431 | + * weak) symbols will be kept in a simple array. |
| 2432 | + */ |
| 2433 | +static bfd_boolean |
| 2434 | +coff_copy_symbols (info, count, sympp) |
| 2435 | + struct coff_write_handle *info; |
| 2436 | + long count; |
| 2437 | + asymbol **sympp; |
| 2438 | +{ |
| 2439 | + asymbol *osym; |
| 2440 | + long i; |
| 2441 | + struct coff_compilation_unit *up; |
| 2442 | + |
| 2443 | + up = NULL; |
| 2444 | + |
| 2445 | + for (i = 0; i < count; i++) |
| 2446 | + { |
| 2447 | + osym = sympp[i]; |
| 2448 | + |
| 2449 | + /* Try to figure out the .text and .data sections from our input |
| 2450 | + symbols as we walk them. Unfortunately, this ought to be the |
| 2451 | + /input/ section pointers, so their ->output_section is |
| 2452 | + non-NULL. That's why we can't simply walk through all the |
| 2453 | + sections of our abfd since this is describing the output |
| 2454 | + only. */ |
| 2455 | + if (info->textsect == NULL && osym->section->flags & SEC_CODE) |
| 2456 | + /* Assume this to be our .text section. */ |
| 2457 | + info->textsect = osym->section; |
| 2458 | + else if (info->datasect == NULL && osym->section->flags & SEC_DATA) |
| 2459 | + /* Assume this to be our .data section. */ |
| 2460 | + info->datasect = osym->section; |
| 2461 | + |
| 2462 | + if (osym->flags & BSF_FILE) |
| 2463 | + { |
| 2464 | + /* New file name. */ |
| 2465 | + long l; |
| 2466 | + |
| 2467 | + up = NULL; |
| 2468 | + |
| 2469 | + /* Well, maybe an old one actually? If so, append it there. |
| 2470 | + This can happen for files that contribute to multiple |
| 2471 | + (input) sections that were concatenated by the linker |
| 2472 | + (like crt1.S). */ |
| 2473 | + for (l = 0; l < info->nunits; l++) |
| 2474 | + { |
| 2475 | + if (strcmp (info->units[l].fname, osym->name) == 0) |
| 2476 | + { |
| 2477 | + up = info->units + l; |
| 2478 | + break; |
| 2479 | + } |
| 2480 | + } |
| 2481 | + |
| 2482 | + if (up == NULL) |
| 2483 | + { |
| 2484 | + info->units = (struct coff_compilation_unit *) |
| 2485 | + xrealloc (info->units, |
| 2486 | + ++info->nunits * sizeof(struct coff_compilation_unit)); |
| 2487 | + up = info->units + (info->nunits - 1); |
| 2488 | + up->fname = osym->name; |
| 2489 | + up->syms = NULL; |
| 2490 | + up->nsyms = up->totsyms = 0; |
| 2491 | + } |
| 2492 | + } |
| 2493 | + else if (osym->flags & (BSF_GLOBAL | BSF_WEAK)) |
| 2494 | + { |
| 2495 | + /* Global (or weak) symbols are recorded outside compilation |
| 2496 | + units. */ |
| 2497 | + info->globals = (asymbol **) |
| 2498 | + xrealloc (info->globals, ++info->nglobals * sizeof(asymbol *)); |
| 2499 | + info->globals[info->nglobals - 1] = osym; |
| 2500 | + continue; |
| 2501 | + } |
| 2502 | + else if (!bfd_is_const_section(osym->section)) |
| 2503 | + { |
| 2504 | + if (osym->flags & BSF_SECTION_SYM) |
| 2505 | + { |
| 2506 | + coff_symbol_type *csymp; |
| 2507 | + /* Just record them by now, they'll be fixed up later. */ |
| 2508 | + |
| 2509 | + if (info->nsyms == 0 && (info->flags & COFF_FL_AVR) == 0) |
| 2510 | + { |
| 2511 | + /* Very first symbol, fake a compilation unit name |
| 2512 | + for it. Historical precedence seems to dictate |
| 2513 | + this, but AVR COFF does not use that. */ |
| 2514 | + csymp = (coff_symbol_type *) |
| 2515 | + coff_bfd_make_debug_symbol (info->abfd, 0, 0); |
| 2516 | + if (csymp == NULL) |
| 2517 | + return FALSE; |
| 2518 | + |
| 2519 | + csymp->symbol.name = xstrdup ("<fake>"); |
| 2520 | + csymp->symbol.value = 0; |
| 2521 | + csymp->symbol.udata.p = NULL; |
| 2522 | + csymp->native->u.syment.n_sclass = C_FILE; |
| 2523 | + /* force filename into aux entry */ |
| 2524 | + csymp->native->u.syment.n_numaux = 1; |
| 2525 | + coff_record_symbol (info, csymp); |
| 2526 | + } |
| 2527 | + |
| 2528 | + /* convert to COFF native section symbol */ |
| 2529 | + csymp = (coff_symbol_type *) |
| 2530 | + coff_bfd_make_debug_symbol (info->abfd, 0, 0); |
| 2531 | + if (csymp == NULL) |
| 2532 | + return FALSE; |
| 2533 | + |
| 2534 | + csymp->symbol.name = xstrdup (osym->section->name); |
| 2535 | + csymp->symbol.value = osym->section->output_section->vma; |
| 2536 | + csymp->symbol.flags = BSF_DEBUGGING | BSF_SECTION_SYM; |
| 2537 | + csymp->symbol.section = osym->section; |
| 2538 | + csymp->symbol.udata.p = NULL; |
| 2539 | + csymp->native->fix_scnlen = 1; |
| 2540 | + csymp->native->u.syment.n_sclass = C_STAT; |
| 2541 | + csymp->native->u.syment.n_type = T_NULL; |
| 2542 | + csymp->native->u.syment.n_numaux = 1; |
| 2543 | + |
| 2544 | + coff_record_symbol (info, csymp); |
| 2545 | + |
| 2546 | + info->secsyms = (coff_symbol_type **) |
| 2547 | + xrealloc (info->secsyms, |
| 2548 | + ++info->nsecsyms * sizeof(coff_symbol_type *)); |
| 2549 | + info->secsyms[info->nsecsyms - 1] = csymp; |
| 2550 | + } |
| 2551 | + else |
| 2552 | + { |
| 2553 | + /* Local symbol in a named section, will be recorded |
| 2554 | + within the respective compilation unit. */ |
| 2555 | + if (up == NULL) |
| 2556 | + { |
| 2557 | + fprintf (stderr, |
| 2558 | + _("Discarding local symbol outside any compilation unit")); |
| 2559 | + if (osym->name) |
| 2560 | + fprintf (stderr, ": %s", osym->name); |
| 2561 | + putc ('\n', stderr); |
| 2562 | + } |
| 2563 | + else |
| 2564 | + { |
| 2565 | + up->syms = (asymbol **) |
| 2566 | + xrealloc (up->syms, ++up->nsyms * sizeof(asymbol *)); |
| 2567 | + up->syms[up->nsyms - 1] = osym; |
| 2568 | + up->totsyms = up->nsyms; |
| 2569 | + continue; |
| 2570 | + } |
| 2571 | + } |
| 2572 | + } |
| 2573 | + } |
| 2574 | + |
| 2575 | + return TRUE; |
| 2576 | +} |
| 2577 | + |
| 2578 | +/* Find a name in the symbol table. If found, the respective entry in |
| 2579 | + the symbol vector is zeroed, so after processing all debugging |
| 2580 | + symbols, only non-debugging symbols will remain. */ |
| 2581 | +static asymbol * |
| 2582 | +coff_find_symbol (info, name, isfunction, global) |
| 2583 | + struct coff_write_handle *info; |
| 2584 | + const char *name; |
| 2585 | + bfd_boolean isfunction; |
| 2586 | + bfd_boolean global; |
| 2587 | +{ |
| 2588 | + asymbol *symp; |
| 2589 | + long i; |
| 2590 | + size_t namelen; |
| 2591 | + |
| 2592 | + if (global) |
| 2593 | + { |
| 2594 | + for (i = 0; i < info->nglobals; i++) |
| 2595 | + { |
| 2596 | + symp = info->globals[i]; |
| 2597 | + if (symp == NULL) |
| 2598 | + continue; |
| 2599 | + if (strcmp (name, symp->name) == 0 |
| 2600 | + && ((symp->flags & BSF_FUNCTION) != 0) == (isfunction == TRUE)) |
| 2601 | + { |
| 2602 | + info->globals[i] = NULL; |
| 2603 | + return symp; |
| 2604 | + } |
| 2605 | + } |
| 2606 | + return NULL; |
| 2607 | + } |
| 2608 | + |
| 2609 | + if (info->currentfile == NULL) |
| 2610 | + return NULL; |
| 2611 | + |
| 2612 | + /* For local symbols, the match optionally stops at a dot in the |
| 2613 | + symtab symbol's name; this is used by gcc to indicate |
| 2614 | + function-scope static symbols (e. g. symbol "foo" will become |
| 2615 | + "foo.1" in function scope). */ |
| 2616 | + namelen = strlen (name); |
| 2617 | + for (i = 0; i < info->currentfile->nsyms; i++) |
| 2618 | + { |
| 2619 | + symp = info->currentfile->syms[i]; |
| 2620 | + if (symp == NULL) |
| 2621 | + continue; |
| 2622 | + if (strncmp (name, symp->name, namelen) == 0 |
| 2623 | + && (symp->name[namelen] == '\0' || symp->name[namelen] == '.') |
| 2624 | + && ((symp->flags & BSF_FUNCTION) != 0) == (isfunction == TRUE)) |
| 2625 | + { |
| 2626 | + info->currentfile->syms[i] = NULL; |
| 2627 | + info->currentfile->totsyms--; |
| 2628 | + return symp; |
| 2629 | + } |
| 2630 | + } |
| 2631 | + return NULL; |
| 2632 | +} |
| 2633 | + |
| 2634 | +static void |
| 2635 | +coff_record_symbol (info, csymp) |
| 2636 | + struct coff_write_handle *info; |
| 2637 | + coff_symbol_type *csymp; |
| 2638 | +{ |
| 2639 | + struct coff_private_symdata *priv; |
| 2640 | + |
| 2641 | + info->syms = (asymbol **) xrealloc (info->syms, |
| 2642 | + ++info->nsyms * sizeof (asymbol *)); |
| 2643 | + info->syms[info->nsyms - 1] = (asymbol *)csymp; |
| 2644 | + |
| 2645 | + if ((priv = csymp->symbol.udata.p) != NULL) |
| 2646 | + { |
| 2647 | + if (priv->shash != NULL) |
| 2648 | + { |
| 2649 | + struct coff_struct_hash_entry *shash = priv->shash; |
| 2650 | + shash->fixidxs = (long *) |
| 2651 | + xrealloc (shash->fixidxs, ++shash->nfixidxs * sizeof (long)); |
| 2652 | + shash->fixidxs[shash->nfixidxs - 1] = info->nsyms - 1; |
| 2653 | + } |
| 2654 | + if (priv->ehash != NULL) |
| 2655 | + { |
| 2656 | + struct coff_enum_hash_entry *ehash = priv->ehash; |
| 2657 | + ehash->fixidxs = (long *) |
| 2658 | + xrealloc (ehash->fixidxs, ++ehash->nfixidxs * sizeof (long)); |
| 2659 | + ehash->fixidxs[ehash->nfixidxs - 1] = info->nsyms - 1; |
| 2660 | + } |
| 2661 | + free (priv); |
| 2662 | + csymp->symbol.udata.p = NULL; |
| 2663 | + } |
| 2664 | + |
| 2665 | + /* If there are any pending endndx fixes, pop the last element from |
| 2666 | + that stack, and record the current symbol for fixing. We need to |
| 2667 | + do this here since we need to record our current csymp->native |
| 2668 | + (where that csymp is completely unrelated to whatever symbol was |
| 2669 | + previously generated that requested the fixup). The stack of |
| 2670 | + pending fixes is required since several endndx fixes could be |
| 2671 | + nested, e. g. the start of a function has a pending fix that |
| 2672 | + needs to point to the first symbol after the function, but there |
| 2673 | + could be an anonymous struct definition inside that function's |
| 2674 | + local variables where the endndx needs to point after the last |
| 2675 | + symbol of this struct. Also, structs and unions could be nested. |
| 2676 | + |
| 2677 | + Each call to coff_record_symbol() can fix at most one endndx |
| 2678 | + (even if more are pending in the stack), but that's OK. |
| 2679 | + |
| 2680 | + Note that bfd/coffgen.c converts that csymp->native into a |
| 2681 | + symtable slot number after coff_renumber_symbols() has been |
| 2682 | + run. */ |
| 2683 | + if (info->flags & COFF_FL_FIX_ENDNDX) |
| 2684 | + { |
| 2685 | + struct coff_fix_stack *fsp, *ofsp; |
| 2686 | + union internal_auxent *aux; |
| 2687 | + |
| 2688 | + assert (info->fixes != NULL); |
| 2689 | + |
| 2690 | + fsp = info->fixes; |
| 2691 | + ofsp = NULL; |
| 2692 | + while (fsp->next != NULL) |
| 2693 | + { |
| 2694 | + ofsp = fsp; |
| 2695 | + fsp = fsp->next; |
| 2696 | + } |
| 2697 | + if (ofsp == NULL) |
| 2698 | + info->fixes = NULL; |
| 2699 | + else |
| 2700 | + ofsp->next = NULL; |
| 2701 | + |
| 2702 | + aux = &(fsp->native->u.auxent); |
| 2703 | + fsp->native->fix_end = 1; |
| 2704 | + aux->x_sym.x_fcnary.x_fcn.x_endndx.p = csymp->native; |
| 2705 | + free (fsp); |
| 2706 | + |
| 2707 | + info->flags &= ~COFF_FL_FIX_ENDNDX; |
| 2708 | + } |
| 2709 | +} |
| 2710 | + |
| 2711 | +/* Fixup AVR COFF register handling: they don't only mention the |
| 2712 | + starting register number, but all registers, each within one byte |
| 2713 | + of the value. Unused register positions are filled up with |
| 2714 | + 0xff. */ |
| 2715 | +static symvalue |
| 2716 | +coff_fixup_avr_register (val, size) |
| 2717 | + symvalue val; |
| 2718 | + int size; |
| 2719 | +{ |
| 2720 | + union |
| 2721 | + { |
| 2722 | + unsigned char c[4]; |
| 2723 | + symvalue v; |
| 2724 | + } u; |
| 2725 | + |
| 2726 | + u.c[1] = u.c[2] = u.c[3] = 0xff; |
| 2727 | + u.c[0] = val; |
| 2728 | + if (size > 8) |
| 2729 | + u.c[1] = val + 1; |
| 2730 | + if (size > 16) |
| 2731 | + { |
| 2732 | + u.c[2] = val + 2; |
| 2733 | + u.c[3] = val + 3; |
| 2734 | + } |
| 2735 | + |
| 2736 | + return u.v; |
| 2737 | +} |
| 2738 | + |
| 2739 | +/* Initialize an entry in the hash tables. */ |
| 2740 | + |
| 2741 | +static struct bfd_hash_entry * |
| 2742 | +coff_name_type_newfunc (entry, table, string) |
| 2743 | + struct bfd_hash_entry *entry; |
| 2744 | + struct bfd_hash_table *table; |
| 2745 | + const char *string; |
| 2746 | +{ |
| 2747 | + struct coff_name_type_hash_entry *ret = |
| 2748 | + (struct coff_name_type_hash_entry *) entry; |
| 2749 | + |
| 2750 | + /* Allocate the structure if it has not already been allocated by a |
| 2751 | + subclass. */ |
| 2752 | + if (ret == NULL) |
| 2753 | + ret = ((struct coff_name_type_hash_entry *) |
| 2754 | + bfd_hash_allocate (table, sizeof *ret)); |
| 2755 | + if (ret == NULL) |
| 2756 | + return NULL; |
| 2757 | + |
| 2758 | + /* Call the allocation method of the superclass. */ |
| 2759 | + ret = ((struct coff_name_type_hash_entry *) |
| 2760 | + bfd_hash_newfunc ((struct bfd_hash_entry *) ret, table, string)); |
| 2761 | + if (ret) |
| 2762 | + { |
| 2763 | + /* Set local fields. */ |
| 2764 | + ret->types = NULL; |
| 2765 | + ret->emitted = FALSE; |
| 2766 | + } |
| 2767 | + |
| 2768 | + return (struct bfd_hash_entry *) ret; |
| 2769 | +} |
| 2770 | + |
| 2771 | +static struct bfd_hash_entry * |
| 2772 | +coff_struct_newfunc (entry, table, string) |
| 2773 | + struct bfd_hash_entry *entry; |
| 2774 | + struct bfd_hash_table *table; |
| 2775 | + const char *string; |
| 2776 | +{ |
| 2777 | + struct coff_struct_hash_entry *ret = |
| 2778 | + (struct coff_struct_hash_entry *) entry; |
| 2779 | + |
| 2780 | + /* Allocate the structure if it has not already been allocated by a |
| 2781 | + subclass. */ |
| 2782 | + if (ret == NULL) |
| 2783 | + ret = ((struct coff_struct_hash_entry *) |
| 2784 | + bfd_hash_allocate (table, sizeof *ret)); |
| 2785 | + if (ret == NULL) |
| 2786 | + return NULL; |
| 2787 | + |
| 2788 | + /* Call the allocation method of the superclass. */ |
| 2789 | + ret = ((struct coff_struct_hash_entry *) |
| 2790 | + bfd_hash_newfunc ((struct bfd_hash_entry *) ret, table, string)); |
| 2791 | + if (ret) |
| 2792 | + { |
| 2793 | + /* Set local fields. */ |
| 2794 | + ret->types = NULL; |
| 2795 | + ret->emitted = FALSE; |
| 2796 | + ret->fixidxs = NULL; |
| 2797 | + ret->nfixidxs = 0; |
| 2798 | + ret->native = NULL; |
| 2799 | + } |
| 2800 | + |
| 2801 | + return (struct bfd_hash_entry *) ret; |
| 2802 | +} |
| 2803 | + |
| 2804 | +static struct bfd_hash_entry * |
| 2805 | +coff_enum_newfunc (entry, table, string) |
| 2806 | + struct bfd_hash_entry *entry; |
| 2807 | + struct bfd_hash_table *table; |
| 2808 | + const char *string; |
| 2809 | +{ |
| 2810 | + struct coff_enum_hash_entry *ret = |
| 2811 | + (struct coff_enum_hash_entry *) entry; |
| 2812 | + |
| 2813 | + /* Allocate the structure if it has not already been allocated by a |
| 2814 | + subclass. */ |
| 2815 | + if (ret == NULL) |
| 2816 | + ret = ((struct coff_enum_hash_entry *) |
| 2817 | + bfd_hash_allocate (table, sizeof *ret)); |
| 2818 | + if (ret == NULL) |
| 2819 | + return NULL; |
| 2820 | + |
| 2821 | + /* Call the allocation method of the superclass. */ |
| 2822 | + ret = ((struct coff_enum_hash_entry *) |
| 2823 | + bfd_hash_newfunc ((struct bfd_hash_entry *) ret, table, string)); |
| 2824 | + if (ret) |
| 2825 | + { |
| 2826 | + /* Set local fields. */ |
| 2827 | + ret->types = NULL; |
| 2828 | + ret->emitted = FALSE; |
| 2829 | + ret->fixidxs = NULL; |
| 2830 | + ret->nfixidxs = 0; |
| 2831 | + ret->native = NULL; |
| 2832 | + } |
| 2833 | + |
| 2834 | + return (struct bfd_hash_entry *) ret; |
| 2835 | +} |
| 2836 | + |
| 2837 | +/* Look up an entry in the hash tables. */ |
| 2838 | + |
| 2839 | +#define coff_name_type_hash_lookup(table, string, create, copy) \ |
| 2840 | + ((struct coff_name_type_hash_entry *) \ |
| 2841 | + bfd_hash_lookup (&(table)->root, (string), (create), (copy))) |
| 2842 | + |
| 2843 | +/* Traverse the hash table. */ |
| 2844 | + |
| 2845 | +#define coff_name_type_hash_traverse(table, func, info) \ |
| 2846 | + (bfd_hash_traverse \ |
| 2847 | + (&(table)->root, \ |
| 2848 | + (bfd_boolean (*) PARAMS ((struct bfd_hash_entry *, PTR))) (func), \ |
| 2849 | + (info))) |
| 2850 | + |
| 2851 | +#define coff_struct_hash_lookup(table, string, create, copy) \ |
| 2852 | + ((struct coff_struct_hash_entry *) \ |
| 2853 | + bfd_hash_lookup (&(table)->root, (string), (create), (copy))) |
| 2854 | + |
| 2855 | +/* Traverse the hash table. */ |
| 2856 | + |
| 2857 | +#define coff_struct_hash_traverse(table, func, info) \ |
| 2858 | + (bfd_hash_traverse \ |
| 2859 | + (&(table)->root, \ |
| 2860 | + (bfd_boolean (*) PARAMS ((struct bfd_hash_entry *, PTR))) (func), \ |
| 2861 | + (info))) |
| 2862 | + |
| 2863 | +#define coff_enum_hash_lookup(table, string, create, copy) \ |
| 2864 | + ((struct coff_enum_hash_entry *) \ |
| 2865 | + bfd_hash_lookup (&(table)->root, (string), (create), (copy))) |
| 2866 | + |
| 2867 | +/* Traverse the hash table. */ |
| 2868 | + |
| 2869 | +#define coff_enum_hash_traverse(table, func, info) \ |
| 2870 | + (bfd_hash_traverse \ |
| 2871 | + (&(table)->root, \ |
| 2872 | + (bfd_boolean (*) PARAMS ((struct bfd_hash_entry *, PTR))) (func), \ |
| 2873 | + (info))) |
| 2874 | + |
| 2875 | +#define coff_push_type(kind) \ |
| 2876 | + tst = (struct coff_type_stack *) xmalloc (sizeof (struct coff_type_stack)); \ |
| 2877 | + memset (tst, 0, sizeof (*tst)); \ |
| 2878 | + tst->next = info->tstack; \ |
| 2879 | + tst->tsk = kind; \ |
| 2880 | + info->tstack = tst |
| 2881 | + |
| 2882 | +#define coff_pop_type() \ |
| 2883 | + tst = info->tstack; \ |
| 2884 | + if (tst == NULL) { \ |
| 2885 | + fprintf (stderr, _("empty type stack in coff_pop_type()\n")); \ |
| 2886 | + return FALSE; \ |
| 2887 | + } \ |
| 2888 | + info->tstack = tst->next; \ |
| 2889 | + tst->next = NULL |
| 2890 | + |
| 2891 | +#define coff_complain_unsupp(s) \ |
| 2892 | + fprintf (stderr, _("%s type not supported in %s\n"), \ |
| 2893 | + s, info->abfd->xvec->name); \ |
| 2894 | + return FALSE |
| 2895 | + |
| 2896 | +/* These function is called via the hash traverse routine when freeing |
| 2897 | + a hash table (at the end of a translation unit). */ |
| 2898 | +static bfd_boolean |
| 2899 | +coff_free_type_info (h, p) |
| 2900 | + struct coff_name_type_hash_entry *h; |
| 2901 | + PTR p ATTRIBUTE_UNUSED; |
| 2902 | +{ |
| 2903 | + struct coff_type_stack *tst, *otst; |
| 2904 | + |
| 2905 | + for (tst = h->types; tst != NULL;) |
| 2906 | + { |
| 2907 | + otst = tst; |
| 2908 | + tst = tst->next; |
| 2909 | + free (otst); |
| 2910 | + } |
| 2911 | + return TRUE; |
| 2912 | +} |
| 2913 | + |
| 2914 | +static bfd_boolean |
| 2915 | +coff_free_struct_info (h, p) |
| 2916 | + struct coff_struct_hash_entry *h; |
| 2917 | + PTR p ATTRIBUTE_UNUSED; |
| 2918 | +{ |
| 2919 | + struct coff_type_stack *tst, *otst, *xtst, *xotst; |
| 2920 | + struct coff_struct_fields *fp; |
| 2921 | + long i; |
| 2922 | + |
| 2923 | + for (tst = h->types; tst != NULL;) |
| 2924 | + { |
| 2925 | + otst = tst; |
| 2926 | + if (tst->u.ts_struct.tagismalloced) |
| 2927 | + free (tst->u.ts_struct.tag.malloctag); |
| 2928 | + for (i = 0, fp = tst->u.ts_struct.fields; |
| 2929 | + i < tst->u.ts_struct.nfields; |
| 2930 | + i++, fp++) |
| 2931 | + { |
| 2932 | + xtst = fp->types; |
| 2933 | + while (xtst != NULL) |
| 2934 | + { |
| 2935 | + xotst = xtst->next; |
| 2936 | + free (xtst); |
| 2937 | + xtst = xotst; |
| 2938 | + } |
| 2939 | + } |
| 2940 | + free (tst->u.ts_struct.fields); |
| 2941 | + tst = tst->next; |
| 2942 | + free (otst); |
| 2943 | + } |
| 2944 | + return TRUE; |
| 2945 | +} |
| 2946 | + |
| 2947 | +static bfd_boolean |
| 2948 | +coff_free_enum_info (h, p) |
| 2949 | + struct coff_enum_hash_entry *h; |
| 2950 | + PTR p ATTRIBUTE_UNUSED; |
| 2951 | +{ |
| 2952 | + struct coff_type_stack *tst, *otst; |
| 2953 | + |
| 2954 | + for (tst = h->types; tst != NULL;) |
| 2955 | + { |
| 2956 | + otst = tst; |
| 2957 | + if (tst->u.ts_enum.tagismalloced) |
| 2958 | + free (tst->u.ts_enum.tag.malloctag); |
| 2959 | + tst = tst->next; |
| 2960 | + free (otst); |
| 2961 | + } |
| 2962 | + return TRUE; |
| 2963 | +} |
| 2964 | + |
| 2965 | +static unsigned int |
| 2966 | +coff_get_fundamental_type (info, tst) |
| 2967 | + struct coff_write_handle *info ATTRIBUTE_UNUSED; |
| 2968 | + struct coff_type_stack *tst; |
| 2969 | +{ |
| 2970 | + size_t i; |
| 2971 | + |
| 2972 | + /* See if one of our predefined types will fit. */ |
| 2973 | + if (tst->tsk == TS_INT) |
| 2974 | + { |
| 2975 | + for (i = 0; |
| 2976 | + i < sizeof coff_predef_types / sizeof (struct coff_predef_type); |
| 2977 | + i++) |
| 2978 | + { |
| 2979 | + if (coff_predef_types[i].kind == TS_INT |
| 2980 | + && coff_predef_types[i].size == tst->u.ts_int.size |
| 2981 | + && coff_predef_types[i].isunsigned == tst->u.ts_int.isunsigned) |
| 2982 | + return coff_predef_types[i].slot; |
| 2983 | + } |
| 2984 | + fprintf (stderr, |
| 2985 | + _("%ssigned %d-bit integer type not available in COFF\n"), |
| 2986 | + tst->u.ts_int.isunsigned? "un": "", tst->u.ts_int.size * 8); |
| 2987 | + } |
| 2988 | + else |
| 2989 | + { |
| 2990 | + for (i = 0; |
| 2991 | + i < sizeof coff_predef_types / sizeof (struct coff_predef_type); |
| 2992 | + i++) |
| 2993 | + { |
| 2994 | + if (coff_predef_types[i].kind == TS_FLOAT |
| 2995 | + && coff_predef_types[i].size == tst->u.ts_float.size) |
| 2996 | + return coff_predef_types[i].slot; |
| 2997 | + } |
| 2998 | + fprintf (stderr, _("%d-bit float type not available in COFF\n"), |
| 2999 | + tst->u.ts_float.size * 8); |
| 3000 | + } |
| 3001 | + |
| 3002 | + return T_NULL; |
| 3003 | +} |
| 3004 | + |
| 3005 | +static bfd_boolean |
| 3006 | +coff_make_typed_symbol (info, csympp, stopat) |
| 3007 | + struct coff_write_handle *info; |
| 3008 | + coff_symbol_type **csympp; |
| 3009 | + enum ts_kind stopat; |
| 3010 | +{ |
| 3011 | + struct coff_type_stack *tst; |
| 3012 | + union internal_auxent *aux; |
| 3013 | + struct coff_struct_hash_entry *shash; |
| 3014 | + struct coff_enum_hash_entry *ehash; |
| 3015 | + struct coff_private_symdata *priv; |
| 3016 | + unsigned int type, numaux, arydim, size, i, nele, nderived; |
| 3017 | + const char *name; |
| 3018 | + bfd_boolean oldavrcoff = (info->flags & (COFF_FL_AVR | COFF_FL_EXT_AVR)) |
| 3019 | + == COFF_FL_AVR; |
| 3020 | + |
| 3021 | + /* Synthesize a new internal COFF symbol. */ |
| 3022 | + *csympp = (coff_symbol_type *) coff_bfd_make_debug_symbol (info->abfd, 0, 0); |
| 3023 | + if (*csympp == NULL) |
| 3024 | + return FALSE; |
| 3025 | + |
| 3026 | + priv = (struct coff_private_symdata *) xmalloc (sizeof *priv); |
| 3027 | + memset (priv, 0, sizeof *priv); |
| 3028 | + |
| 3029 | + type = arydim = size = nderived = 0; |
| 3030 | + |
| 3031 | + aux = &(((*csympp)->native + 1)->u.auxent); |
| 3032 | + |
| 3033 | + /* Now, walk the type stack, and see how we could convert the info |
| 3034 | + we've got to what COFF understands. */ |
| 3035 | + for (;;) |
| 3036 | + { |
| 3037 | + if (info->tstack == NULL) |
| 3038 | + break; |
| 3039 | + |
| 3040 | + /* If we have been advised to not pop the entire stack, stop |
| 3041 | + here. */ |
| 3042 | + if (info->tstack->tsk == stopat && info->tstack->next == NULL) |
| 3043 | + break; |
| 3044 | + |
| 3045 | + coff_pop_type (); |
| 3046 | + |
| 3047 | + switch (tst->tsk) |
| 3048 | + { |
| 3049 | + case TS_NONE: |
| 3050 | + /* cannot happen */ |
| 3051 | + break; |
| 3052 | + |
| 3053 | + case TS_EMPTY: |
| 3054 | + if (info->tstack != NULL && info->tstack->tsk != stopat) |
| 3055 | + fprintf (stderr, _("empty type not last on type stack\n")); |
| 3056 | + /* type |= T_NULL; */ |
| 3057 | + break; |
| 3058 | + |
| 3059 | + case TS_VOID: |
| 3060 | + if (info->tstack != NULL && info->tstack->tsk != stopat) |
| 3061 | + fprintf (stderr, _("void type not last on type stack\n")); |
| 3062 | + type |= T_VOID; |
| 3063 | + break; |
| 3064 | + |
| 3065 | + case TS_INT: |
| 3066 | + if (info->tstack != NULL && info->tstack->tsk != stopat) |
| 3067 | + fprintf (stderr, _("int type not last on type stack\n")); |
| 3068 | + type |= coff_get_fundamental_type (info, tst); |
| 3069 | + if (size == 0) |
| 3070 | + size = tst->u.ts_int.size; |
| 3071 | + break; |
| 3072 | + |
| 3073 | + case TS_FLOAT: |
| 3074 | + if (info->tstack != NULL && info->tstack->tsk != stopat) |
| 3075 | + fprintf (stderr, _("float type not last on type stack\n")); |
| 3076 | + type |= coff_get_fundamental_type (info, tst); |
| 3077 | + if (size == 0) |
| 3078 | + size = tst->u.ts_float.size; |
| 3079 | + break; |
| 3080 | + |
| 3081 | + case TS_POINTER: |
| 3082 | + nderived++; |
| 3083 | + type = ((type & ~N_BTMASK) << N_TSHIFT) | (DT_PTR << N_BTSHFT); |
| 3084 | + size = info->pointersize; |
| 3085 | + break; |
| 3086 | + |
| 3087 | + case TS_FUNC: |
| 3088 | + nderived++; |
| 3089 | + type = ((type & ~N_BTMASK) << N_TSHIFT) | (DT_FCN << N_BTSHFT); |
| 3090 | + /* AUX entry for DT_FCN will be filled in elsewhere. */ |
| 3091 | + break; |
| 3092 | + |
| 3093 | + case TS_ARRAY: |
| 3094 | + /* We need to limit arydim so the assignment below won't |
| 3095 | + overwrite random locations. */ |
| 3096 | + if (arydim >= DIMNUM) |
| 3097 | + { |
| 3098 | + fprintf (stderr, |
| 3099 | + _("More than %d array dimensions, result is invalid.\n"), |
| 3100 | + DIMNUM); |
| 3101 | + arydim = DIMNUM - 1; |
| 3102 | + } |
| 3103 | + nderived++; |
| 3104 | + type = ((type & ~N_BTMASK) << N_TSHIFT) | (DT_ARY << N_BTSHFT); |
| 3105 | + aux->x_sym.x_fcnary.x_ary.x_dimen[arydim++] = |
| 3106 | + tst->u.ts_array.high - tst->u.ts_array.low + 1; |
| 3107 | + |
| 3108 | + break; |
| 3109 | + |
| 3110 | + case TS_COMPLEX: |
| 3111 | + coff_complain_unsupp (_("complex")); |
| 3112 | + |
| 3113 | + case TS_ENUM: |
| 3114 | + type |= T_ENUM; |
| 3115 | + if (size == 0) |
| 3116 | + size = info->enumsize; |
| 3117 | + |
| 3118 | + if (tst->u.ts_enum.ehash != NULL) |
| 3119 | + { |
| 3120 | + /* enum tag will be fixed later. */ |
| 3121 | + priv->ehash = tst->u.ts_enum.ehash; |
| 3122 | + break; |
| 3123 | + } |
| 3124 | + if (tst->u.ts_enum.tagismalloced) |
| 3125 | + name = tst->u.ts_enum.tag.malloctag; |
| 3126 | + else |
| 3127 | + name = tst->u.ts_enum.tag.fixtag; |
| 3128 | + ehash = coff_enum_hash_lookup (&info->enums, name, |
| 3129 | + TRUE, tst->u.ts_enum.tagismalloced); |
| 3130 | + if (ehash == NULL) |
| 3131 | + return FALSE; |
| 3132 | + if (!ehash->emitted) |
| 3133 | + { |
| 3134 | + if (ehash->types == NULL) |
| 3135 | + { |
| 3136 | + ehash->types = (struct coff_type_stack *) |
| 3137 | + xmalloc (sizeof (struct coff_type_stack)); |
| 3138 | + memcpy (ehash->types, tst, sizeof (struct coff_type_stack)); |
| 3139 | + } |
| 3140 | + ehash->emitted = TRUE; |
| 3141 | + coff_emit_enum (info, tst, ehash); |
| 3142 | + if (ehash->nfixidxs != 0) |
| 3143 | + { |
| 3144 | + coff_symbol_type *symp; |
| 3145 | + unsigned i; |
| 3146 | + |
| 3147 | + for (i = 0; i < ehash->nfixidxs; i++) |
| 3148 | + { |
| 3149 | + combined_entry_type *np; |
| 3150 | + |
| 3151 | + symp = (coff_symbol_type *) info->syms[ehash->fixidxs[i]]; |
| 3152 | + symp->native->u.syment.n_type &= ~N_BTMASK; |
| 3153 | + symp->native->u.syment.n_type |= T_ENUM; |
| 3154 | + |
| 3155 | + if (oldavrcoff) |
| 3156 | + continue; |
| 3157 | + |
| 3158 | + np = symp->native + 1; |
| 3159 | + np->fix_tag = 1; |
| 3160 | + np->u.auxent.x_sym.x_tagndx.p = ehash->native; |
| 3161 | + if (np->u.auxent.x_sym.x_misc.x_fsize == 0) |
| 3162 | + np->u.auxent.x_sym.x_misc.x_lnsz.x_size = size; |
| 3163 | + } |
| 3164 | + |
| 3165 | + free (ehash->fixidxs); |
| 3166 | + ehash->nfixidxs = 0; |
| 3167 | + } |
| 3168 | + } |
| 3169 | + if (!oldavrcoff) |
| 3170 | + { |
| 3171 | + ((*csympp)->native + 1)->fix_tag = 1; |
| 3172 | + aux->x_sym.x_tagndx.p = ehash->native; |
| 3173 | + if (aux->x_sym.x_misc.x_fsize == 0) |
| 3174 | + aux->x_sym.x_misc.x_lnsz.x_size = size; |
| 3175 | + } |
| 3176 | + break; |
| 3177 | + |
| 3178 | + case TS_STRUCT: |
| 3179 | + if (tst->u.ts_struct.isstruct) |
| 3180 | + type |= T_STRUCT; |
| 3181 | + else |
| 3182 | + type |= T_UNION; |
| 3183 | + if (size == 0) |
| 3184 | + size = tst->u.ts_struct.size; |
| 3185 | + |
| 3186 | + if (tst->u.ts_struct.shash != NULL) |
| 3187 | + { |
| 3188 | + /* struct tag will be fixed later. */ |
| 3189 | + priv->shash = tst->u.ts_struct.shash; |
| 3190 | + break; |
| 3191 | + } |
| 3192 | + if (tst->u.ts_struct.tagismalloced) |
| 3193 | + name = tst->u.ts_struct.tag.malloctag; |
| 3194 | + else |
| 3195 | + name = tst->u.ts_struct.tag.fixtag; |
| 3196 | + shash = coff_struct_hash_lookup (&info->structs, name, |
| 3197 | + TRUE, tst->u.ts_struct.tagismalloced); |
| 3198 | + if (shash == NULL) |
| 3199 | + return FALSE; |
| 3200 | + if (!shash->emitted) |
| 3201 | + { |
| 3202 | + if (shash->types == NULL) |
| 3203 | + { |
| 3204 | + shash->types = (struct coff_type_stack *) |
| 3205 | + xmalloc (sizeof (struct coff_type_stack)); |
| 3206 | + memcpy (shash->types, tst, sizeof (struct coff_type_stack)); |
| 3207 | + } |
| 3208 | + shash->emitted = TRUE; |
| 3209 | + coff_emit_struct (info, tst, shash); |
| 3210 | + if (shash->nfixidxs != 0) |
| 3211 | + { |
| 3212 | + coff_symbol_type *symp; |
| 3213 | + unsigned i; |
| 3214 | + |
| 3215 | + for (i = 0; i < shash->nfixidxs; i++) |
| 3216 | + { |
| 3217 | + combined_entry_type *np; |
| 3218 | + |
| 3219 | + symp = (coff_symbol_type *) info->syms[shash->fixidxs[i]]; |
| 3220 | + symp->native->u.syment.n_type &= ~N_BTMASK; |
| 3221 | + if (tst->u.ts_struct.isstruct) |
| 3222 | + symp->native->u.syment.n_type |= T_STRUCT; |
| 3223 | + else |
| 3224 | + symp->native->u.syment.n_type |= T_UNION; |
| 3225 | + |
| 3226 | + if (oldavrcoff) |
| 3227 | + continue; |
| 3228 | + |
| 3229 | + np = symp->native + 1; |
| 3230 | + np->fix_tag = 1; |
| 3231 | + np->u.auxent.x_sym.x_tagndx.p = shash->native; |
| 3232 | + if (np->u.auxent.x_sym.x_misc.x_fsize == 0) |
| 3233 | + np->u.auxent.x_sym.x_misc.x_lnsz.x_size = size; |
| 3234 | + } |
| 3235 | + |
| 3236 | + free (shash->fixidxs); |
| 3237 | + shash->nfixidxs = 0; |
| 3238 | + } |
| 3239 | + } |
| 3240 | + if (!oldavrcoff) |
| 3241 | + { |
| 3242 | + ((*csympp)->native + 1)->fix_tag = 1; |
| 3243 | + aux->x_sym.x_tagndx.p = shash->native; |
| 3244 | + if (aux->x_sym.x_misc.x_fsize == 0) |
| 3245 | + aux->x_sym.x_misc.x_lnsz.x_size = size; |
| 3246 | + } |
| 3247 | + break; |
| 3248 | + } |
| 3249 | + free (tst); |
| 3250 | + } |
| 3251 | + |
| 3252 | + if (nderived > 6) |
| 3253 | + fprintf (stderr, |
| 3254 | + _("More than 6 derived type specifiers, result is invalid.\n")); |
| 3255 | + |
| 3256 | + /* Our type computation so far used the reverse order for derived |
| 3257 | + type specifiers. Fix this here if there was more than one |
| 3258 | + derived type specifier. */ |
| 3259 | + if (nderived > 1) |
| 3260 | + { |
| 3261 | + unsigned int nty, bty; |
| 3262 | + bty = type & N_BTMASK; |
| 3263 | + type = type >> N_BTSHFT; |
| 3264 | + nty = 0; |
| 3265 | + while (nderived-- > 0) |
| 3266 | + { |
| 3267 | + nty = (nty << N_TSHIFT) | (type & (N_TMASK >> N_BTSHFT)); |
| 3268 | + type >>= N_TSHIFT; |
| 3269 | + } |
| 3270 | + type = (nty << N_BTSHFT) | bty; |
| 3271 | + } |
| 3272 | + |
| 3273 | + if (ISARY (type)) |
| 3274 | + { |
| 3275 | + /* Compute size of entire array. */ |
| 3276 | + for (i = 0, nele = 1; i < arydim; i++) |
| 3277 | + nele *= aux->x_sym.x_fcnary.x_ary.x_dimen[i]; |
| 3278 | + aux->x_sym.x_misc.x_lnsz.x_size = size * nele; |
| 3279 | + } |
| 3280 | + |
| 3281 | + numaux = 0; |
| 3282 | + if (ISARY (type) || ISFCN (type)) |
| 3283 | + numaux++; |
| 3284 | + if ((BTYPE (type) == T_STRUCT || BTYPE (type) == T_UNION |
| 3285 | + || BTYPE (type) == T_ENUM) |
| 3286 | + && !oldavrcoff) |
| 3287 | + numaux++; |
| 3288 | + /* Only AVR COFF uses multiple AUX entries. */ |
| 3289 | + if (numaux > 1 && (info->flags & COFF_FL_AVR) == 0) |
| 3290 | + numaux = 1; |
| 3291 | + |
| 3292 | + priv->size = size; |
| 3293 | + (*csympp)->symbol.udata.p = priv; |
| 3294 | + (*csympp)->native->u.syment.n_type = type; |
| 3295 | + (*csympp)->native->u.syment.n_numaux = numaux; |
| 3296 | + |
| 3297 | + /* If the fundamental type comes out as T_NULL, this means we don't |
| 3298 | + have any type information. Just don't emit any aux entries in |
| 3299 | + that case, and drop any derived type information as well. */ |
| 3300 | + if (BTYPE (type) == T_NULL) |
| 3301 | + { |
| 3302 | + printf ("coff_make_typed_symbol() -> T_NULL\n"); |
| 3303 | + //(*csympp)->native->u.syment.n_type = T_NULL; |
| 3304 | + (*csympp)->native->u.syment.n_numaux = 0; |
| 3305 | + } |
| 3306 | + |
| 3307 | + return TRUE; |
| 3308 | +} |
| 3309 | + |
| 3310 | +static bfd_boolean coff_emit_struct (info, tst, shash) |
| 3311 | + struct coff_write_handle *info; |
| 3312 | + struct coff_type_stack *tst; |
| 3313 | + struct coff_struct_hash_entry *shash; |
| 3314 | +{ |
| 3315 | + coff_symbol_type *csymp, *scsymp, *ecsymp; |
| 3316 | + union internal_auxent *aux; |
| 3317 | + struct coff_fix_stack *fixp, *ofp; |
| 3318 | + bfd_boolean isstruct = tst->u.ts_struct.isstruct; |
| 3319 | + bfd_boolean isbitfield = FALSE; |
| 3320 | + struct coff_type_stack *savedtst; |
| 3321 | + struct coff_struct_fields *fp; |
| 3322 | + unsigned short sclass; |
| 3323 | + long i; |
| 3324 | + |
| 3325 | + if ((info->flags & (COFF_FL_AVR | COFF_FL_EXT_AVR)) == |
| 3326 | + COFF_FL_AVR) |
| 3327 | + /* old AVR COFF doesn't support struct debugging */ |
| 3328 | + return TRUE; |
| 3329 | + |
| 3330 | + /* Synthesize a new internal COFF symbol for the struct/union. */ |
| 3331 | + scsymp = (coff_symbol_type *) coff_bfd_make_debug_symbol (info->abfd, 0, 0); |
| 3332 | + if (scsymp == NULL) |
| 3333 | + return FALSE; |
| 3334 | + |
| 3335 | + if (tst->u.ts_struct.tagismalloced) |
| 3336 | + scsymp->symbol.name = xstrdup (tst->u.ts_struct.tag.malloctag); |
| 3337 | + else |
| 3338 | + scsymp->symbol.name = tst->u.ts_struct.tag.fixtag; |
| 3339 | + scsymp->symbol.flags = BSF_NOT_AT_END; |
| 3340 | + scsymp->symbol.section = bfd_und_section_ptr; |
| 3341 | + scsymp->native->u.syment.n_sclass = isstruct? C_STRTAG: C_UNTAG; |
| 3342 | + scsymp->native->u.syment.n_type = isstruct? T_STRUCT: T_UNION; |
| 3343 | + scsymp->native->u.syment.n_numaux = 1; |
| 3344 | + scsymp->symbol.udata.p = NULL; |
| 3345 | + scsymp->symbol.value = 0; |
| 3346 | + |
| 3347 | + shash->native = scsymp->native; |
| 3348 | + |
| 3349 | + /* Synthesize a new internal COFF symbol for the end of struct/union. */ |
| 3350 | + ecsymp = (coff_symbol_type *) coff_bfd_make_debug_symbol (info->abfd, 0, 0); |
| 3351 | + if (ecsymp == NULL) |
| 3352 | + return FALSE; |
| 3353 | + |
| 3354 | + ecsymp->symbol.name = ".eos"; |
| 3355 | + ecsymp->symbol.flags = BSF_NOT_AT_END; |
| 3356 | + /* We need to use the com section here since bfd/coffgen.c |
| 3357 | + translates this into an N_UNDEF one without clobbering the |
| 3358 | + value. */ |
| 3359 | + ecsymp->symbol.section = bfd_com_section_ptr; |
| 3360 | + ecsymp->native->u.syment.n_sclass = C_EOS; |
| 3361 | + ecsymp->symbol.udata.p = NULL; |
| 3362 | + ecsymp->symbol.value = tst->u.ts_struct.size; |
| 3363 | + ecsymp->native->u.syment.n_numaux = 1; |
| 3364 | + (ecsymp->native + 1)->fix_tag = 1; |
| 3365 | + aux = &((ecsymp->native + 1)->u.auxent); |
| 3366 | + aux->x_sym.x_tagndx.p = scsymp->native; |
| 3367 | + aux->x_sym.x_misc.x_lnsz.x_size = tst->u.ts_struct.size; |
| 3368 | + |
| 3369 | + coff_record_symbol (info, scsymp); |
| 3370 | + |
| 3371 | + savedtst = info->tstack; |
| 3372 | + |
| 3373 | + if (isstruct) |
| 3374 | + { |
| 3375 | + /* First, make a quick walk along all the fields, and figure out |
| 3376 | + * whether we've got a genuine struct or a bitfield struct. */ |
| 3377 | + for (i = 0, fp = tst->u.ts_struct.fields; |
| 3378 | + i < tst->u.ts_struct.nfields; |
| 3379 | + i++, fp++) |
| 3380 | + if (fp->bitsize % 8 != 0) |
| 3381 | + { |
| 3382 | + isbitfield = TRUE; |
| 3383 | + break; |
| 3384 | + } |
| 3385 | + } |
| 3386 | + |
| 3387 | + sclass = isstruct? (isbitfield? C_FIELD: C_MOS): C_MOU; |
| 3388 | + |
| 3389 | + for (i = 0, fp = tst->u.ts_struct.fields; |
| 3390 | + i < tst->u.ts_struct.nfields; |
| 3391 | + i++, fp++) |
| 3392 | + { |
| 3393 | + if (strlen (fp->name) == 0) |
| 3394 | + { |
| 3395 | + /* empty name could happen inside bitfield */ |
| 3396 | + fp->types = NULL; |
| 3397 | + continue; |
| 3398 | + } |
| 3399 | + |
| 3400 | + info->tstack = fp->types; |
| 3401 | + if (!coff_make_typed_symbol (info, &csymp, TS_NONE)) |
| 3402 | + return FALSE; |
| 3403 | + |
| 3404 | + csymp->symbol.name = xstrdup (fp->name); |
| 3405 | + csymp->symbol.flags = BSF_NOT_AT_END; |
| 3406 | + csymp->symbol.section = bfd_com_section_ptr; |
| 3407 | + csymp->native->u.syment.n_sclass = sclass; |
| 3408 | + csymp->symbol.value = isbitfield? fp->bitpos: fp->bitpos / 8; |
| 3409 | + if (isbitfield) |
| 3410 | + { |
| 3411 | + csymp->native->u.syment.n_numaux = 1; |
| 3412 | + aux = &((csymp->native + 1)->u.auxent); |
| 3413 | + aux->x_sym.x_misc.x_lnsz.x_size = fp->bitsize; |
| 3414 | + } |
| 3415 | + |
| 3416 | + coff_record_symbol (info, csymp); |
| 3417 | + |
| 3418 | + fp->types = NULL; |
| 3419 | + } |
| 3420 | + |
| 3421 | + info->tstack = savedtst; |
| 3422 | + |
| 3423 | + /* Record our endndx field for later fixing. */ |
| 3424 | + fixp = (struct coff_fix_stack *) xmalloc (sizeof (struct coff_fix_stack)); |
| 3425 | + fixp->native = scsymp->native + 1; /* points to first AUX */ |
| 3426 | + fixp->next = NULL; |
| 3427 | + if (info->fixes == NULL) |
| 3428 | + info->fixes = fixp; |
| 3429 | + else |
| 3430 | + { |
| 3431 | + for (ofp = info->fixes; ofp->next != NULL;) |
| 3432 | + ofp = ofp->next; |
| 3433 | + ofp->next = fixp; |
| 3434 | + } |
| 3435 | + |
| 3436 | + coff_record_symbol (info, ecsymp); |
| 3437 | + info->flags |= COFF_FL_FIX_ENDNDX; |
| 3438 | + |
| 3439 | + return TRUE; |
| 3440 | +} |
| 3441 | + |
| 3442 | +static bfd_boolean coff_emit_enum (info, tst, ehash) |
| 3443 | + struct coff_write_handle *info; |
| 3444 | + struct coff_type_stack *tst; |
| 3445 | + struct coff_enum_hash_entry *ehash; |
| 3446 | +{ |
| 3447 | + coff_symbol_type *csymp, *scsymp, *ecsymp; |
| 3448 | + union internal_auxent *aux; |
| 3449 | + struct coff_fix_stack *fixp, *ofp; |
| 3450 | + int i; |
| 3451 | + |
| 3452 | + if ((info->flags & (COFF_FL_AVR | COFF_FL_EXT_AVR)) == |
| 3453 | + COFF_FL_AVR) |
| 3454 | + /* old AVR COFF doesn't support enum debugging */ |
| 3455 | + return TRUE; |
| 3456 | + |
| 3457 | + /* Synthesize a new internal COFF symbol for the enum. */ |
| 3458 | + scsymp = (coff_symbol_type *) coff_bfd_make_debug_symbol (info->abfd, 0, 0); |
| 3459 | + if (scsymp == NULL) |
| 3460 | + return FALSE; |
| 3461 | + |
| 3462 | + if (tst->u.ts_enum.tagismalloced) |
| 3463 | + scsymp->symbol.name = xstrdup (tst->u.ts_enum.tag.malloctag); |
| 3464 | + else |
| 3465 | + scsymp->symbol.name = tst->u.ts_enum.tag.fixtag; |
| 3466 | + scsymp->symbol.flags = BSF_NOT_AT_END; |
| 3467 | + scsymp->symbol.section = bfd_und_section_ptr; |
| 3468 | + scsymp->native->u.syment.n_sclass = C_ENTAG; |
| 3469 | + scsymp->native->u.syment.n_type = T_ENUM; |
| 3470 | + scsymp->native->u.syment.n_numaux = 1; |
| 3471 | + scsymp->symbol.udata.p = NULL; |
| 3472 | + scsymp->symbol.value = 0; |
| 3473 | + |
| 3474 | + ehash->native = scsymp->native; |
| 3475 | + |
| 3476 | + /* Synthesize a new internal COFF symbol for the end of struct/union. */ |
| 3477 | + ecsymp = (coff_symbol_type *) coff_bfd_make_debug_symbol (info->abfd, 0, 0); |
| 3478 | + if (ecsymp == NULL) |
| 3479 | + return FALSE; |
| 3480 | + |
| 3481 | + ecsymp->symbol.name = ".eos"; |
| 3482 | + ecsymp->symbol.flags = BSF_NOT_AT_END; |
| 3483 | + /* We need to use the com section here since bfd/coffgen.c |
| 3484 | + translates this into an N_UNDEF one without clobbering the |
| 3485 | + value. */ |
| 3486 | + ecsymp->symbol.section = bfd_com_section_ptr; |
| 3487 | + ecsymp->native->u.syment.n_sclass = C_EOS; |
| 3488 | + ecsymp->symbol.udata.p = NULL; |
| 3489 | + ecsymp->symbol.value = info->enumsize; |
| 3490 | + ecsymp->native->u.syment.n_numaux = 1; |
| 3491 | + (ecsymp->native + 1)->fix_tag = 1; |
| 3492 | + aux = &((ecsymp->native + 1)->u.auxent); |
| 3493 | + aux->x_sym.x_tagndx.p = scsymp->native; |
| 3494 | + aux->x_sym.x_misc.x_lnsz.x_size = info->enumsize; |
| 3495 | + |
| 3496 | + coff_record_symbol (info, scsymp); |
| 3497 | + |
| 3498 | + for (i = 0;; i++) |
| 3499 | + { |
| 3500 | + const char *name = tst->u.ts_enum.names[i]; |
| 3501 | + if (name == NULL) |
| 3502 | + break; |
| 3503 | + |
| 3504 | + /* Synthesize a new internal COFF symbol for the enum. */ |
| 3505 | + csymp = (coff_symbol_type *) coff_bfd_make_debug_symbol (info->abfd, 0, 0); |
| 3506 | + if (csymp == NULL) |
| 3507 | + return FALSE; |
| 3508 | + |
| 3509 | + csymp->symbol.name = xstrdup (name); |
| 3510 | + csymp->symbol.flags = BSF_NOT_AT_END; |
| 3511 | + csymp->symbol.section = bfd_com_section_ptr; |
| 3512 | + csymp->native->u.syment.n_sclass = C_MOE; |
| 3513 | + csymp->symbol.udata.p = NULL; |
| 3514 | + csymp->symbol.value = tst->u.ts_enum.vals[i]; |
| 3515 | + |
| 3516 | + coff_record_symbol (info, csymp); |
| 3517 | + } |
| 3518 | + |
| 3519 | + /* Record our endndx field for later fixing. */ |
| 3520 | + fixp = (struct coff_fix_stack *) xmalloc (sizeof (struct coff_fix_stack)); |
| 3521 | + fixp->native = scsymp->native + 1; /* points to first AUX */ |
| 3522 | + fixp->next = NULL; |
| 3523 | + if (info->fixes == NULL) |
| 3524 | + info->fixes = fixp; |
| 3525 | + else |
| 3526 | + { |
| 3527 | + for (ofp = info->fixes; ofp->next != NULL;) |
| 3528 | + ofp = ofp->next; |
| 3529 | + ofp->next = fixp; |
| 3530 | + } |
| 3531 | + |
| 3532 | + coff_record_symbol (info, ecsymp); |
| 3533 | + info->flags |= COFF_FL_FIX_ENDNDX; |
| 3534 | + |
| 3535 | + return TRUE; |
| 3536 | +} |
| 3537 | + |
| 3538 | +/* Emit a non-debugging symbol that came from the input symbol table, |
| 3539 | + and has not been claimed by one of the debugging symbols. */ |
| 3540 | +static bfd_boolean |
| 3541 | +coff_emit_ndebug_sym (info, osymp, localp) |
| 3542 | + struct coff_write_handle *info; |
| 3543 | + asymbol *osymp; |
| 3544 | + bfd_boolean localp; |
| 3545 | +{ |
| 3546 | + coff_symbol_type *csymp; |
| 3547 | + |
| 3548 | + /* Create new COFF symbol. */ |
| 3549 | + csymp = (coff_symbol_type *) coff_bfd_make_debug_symbol (info->abfd, 0, 0); |
| 3550 | + if (csymp == NULL) |
| 3551 | + return FALSE; |
| 3552 | + |
| 3553 | + csymp->symbol.name = xstrdup (osymp->name); |
| 3554 | + csymp->symbol.value = osymp->value; |
| 3555 | + csymp->symbol.flags = localp? BSF_LOCAL: BSF_GLOBAL; |
| 3556 | + csymp->symbol.section = osymp->section; |
| 3557 | + csymp->symbol.udata.p = NULL; |
| 3558 | + csymp->native->u.syment.n_sclass = localp? C_STAT: C_EXT; |
| 3559 | + csymp->native->u.syment.n_type = T_NULL; |
| 3560 | + |
| 3561 | + coff_record_symbol (info, csymp); |
| 3562 | + |
| 3563 | + return TRUE; |
| 3564 | +} |
| 3565 | + |
| 3567 | +/* The general routine to write out COFF debugging information. This |
| 3568 | + synthesizes and accumulates the COFF symbols. Actual symbol table |
| 3569 | + output is performed later on by the BFD functions. ABFD is the BFD |
| 3570 | + and DHANDLE is the handle for the debugging information. symcountp |
| 3571 | + and symppp point to the incoming (parsed) symbol list on entry, and |
| 3572 | + will be updated to point to the new symbol table's values upon |
| 3573 | + exit. */ |
| 3574 | + |
| 3575 | +bfd_boolean |
| 3576 | +write_coff_debugging_info (abfd, dhandle, symcountp, symppp) |
| 3577 | + bfd *abfd; |
| 3578 | + PTR dhandle; |
| 3579 | + long *symcountp; |
| 3580 | + asymbol ***symppp; |
| 3581 | +{ |
| 3582 | + struct coff_write_handle info; |
| 3583 | + long i, l; |
| 3584 | + asymbol *symp; |
| 3585 | + struct coff_compilation_unit *up; |
| 3586 | + coff_symbol_type *csymp; |
| 3587 | + |
| 3588 | + memset ((void *)&info, 0, sizeof info); |
| 3589 | + |
| 3590 | + info.abfd = abfd; |
| 3591 | + |
| 3592 | + info.pointersize = info.enumsize = 4; |
| 3593 | + |
| 3594 | + switch (bfd_get_arch (abfd)) |
| 3595 | + { |
| 3596 | + case bfd_arch_avr: |
| 3597 | + info.flags |= COFF_FL_AVR; |
| 3598 | + if (strcmp (abfd->xvec->name, "coff-ext-avr") == 0) |
| 3599 | + info.flags |= COFF_FL_EXT_AVR; |
| 3600 | + /* Fix the builtin type sizes. */ |
| 3601 | + coff_predef_types[0].size = 2; /* sizeof(int) == 2 */ |
| 3602 | + coff_predef_types[4].size = 4; /* sizeof(double) == 4 */ |
| 3603 | + coff_predef_types[6].size = 2; /* sizeof(unsigned int) == 2 */ |
| 3604 | + info.pointersize = info.enumsize = 2; |
| 3605 | + break; |
| 3606 | + |
| 3607 | + default: |
| 3608 | + ; |
| 3609 | + } |
| 3610 | + |
| 3611 | + coff_copy_symbols(&info, *symcountp, *symppp); |
| 3612 | + |
| 3613 | + if (info.textsect == NULL) |
| 3614 | + { |
| 3615 | + fprintf (stderr, _("Warning: no \"text\" section found in output file\n")); |
| 3616 | + info.textsect = bfd_abs_section_ptr; |
| 3617 | + } |
| 3618 | + if (info.datasect == NULL) |
| 3619 | + { |
| 3620 | + fprintf (stderr, _("Warning: no \"data\" section found in output file\n")); |
| 3621 | + info.datasect = bfd_abs_section_ptr; |
| 3622 | + } |
| 3623 | + |
| 3624 | + if (! bfd_hash_table_init (&info.types.root, coff_name_type_newfunc, |
| 3625 | + sizeof(struct coff_name_type_hash_entry))) |
| 3626 | + return FALSE; |
| 3627 | + |
| 3628 | + if (! bfd_hash_table_init (&info.structs.root, coff_struct_newfunc, |
| 3629 | + sizeof(struct coff_struct_hash_entry))) |
| 3630 | + return FALSE; |
| 3631 | + |
| 3632 | + if (! bfd_hash_table_init (&info.enums.root, coff_enum_newfunc, |
| 3633 | + sizeof(struct coff_enum_hash_entry))) |
| 3634 | + return FALSE; |
| 3635 | + |
| 3636 | + if (! debug_write (dhandle, &coff_fns, (PTR) &info)) |
| 3637 | + return FALSE; |
| 3638 | + |
| 3639 | + /* If there is an old compilation unit that has got any local |
| 3640 | + non-debugging symbols left over, send them out now. */ |
| 3641 | + if (info.currentfile != NULL && info.currentfile->totsyms != 0) |
| 3642 | + for (i = 0; i < info.currentfile->nsyms; i++) |
| 3643 | + { |
| 3644 | + up = info.currentfile; |
| 3645 | + |
| 3646 | + if (up->syms[i] != NULL) |
| 3647 | + { |
| 3648 | + coff_emit_ndebug_sym (&info, up->syms[i], TRUE); |
| 3649 | + up->syms[i] = NULL; |
| 3650 | + up->totsyms--; |
| 3651 | + } |
| 3652 | + } |
| 3653 | + |
| 3654 | + /* See whether there are any non-debugging symbols left from the |
| 3655 | + input symbol table. First look at all local symbols which must |
| 3656 | + be from entire compilation units we didn't see yet in the |
| 3657 | + debugging information, because anything else has already been |
| 3658 | + handled at the end of each compilation unit (like in the loop |
| 3659 | + immediately above). Any compilation unit that has already been |
| 3660 | + processed that way is supposed to have its "totsyms" counted down |
| 3661 | + to 0 now, so we can skip them. |
| 3662 | + |
| 3663 | + Finally, put out all remaining global non-debugging symbols. */ |
| 3664 | + for (l = 0; l < info.nunits; l++) |
| 3665 | + { |
| 3666 | + const char *bn; |
| 3667 | + |
| 3668 | + up = info.units + l; |
| 3669 | + if (up->totsyms == 0) |
| 3670 | + continue; |
| 3671 | + |
| 3672 | + /* Create COFF symbol for this compilation unit. */ |
| 3673 | + csymp = (coff_symbol_type *) coff_bfd_make_debug_symbol (info.abfd, 0, 0); |
| 3674 | + if (csymp == NULL) |
| 3675 | + return FALSE; |
| 3676 | + |
| 3677 | + bn = bu_basename (up->fname); |
| 3678 | + |
| 3679 | + if (bfd_coff_long_filenames (info.abfd)) |
| 3680 | + csymp->symbol.name = up->fname; |
| 3681 | + else |
| 3682 | + csymp->symbol.name = bn; |
| 3683 | + |
| 3684 | + csymp->symbol.value = 0; |
| 3685 | + csymp->symbol.udata.p = NULL; |
| 3686 | + csymp->native->u.syment.n_sclass = C_FILE; |
| 3687 | + csymp->native->u.syment.n_numaux = 1; /* force filename into aux entry */ |
| 3688 | + coff_record_symbol (&info, csymp); |
| 3689 | + |
| 3690 | + for (i = 0; i < up->nsyms; i++) |
| 3691 | + { |
| 3692 | + symp = up->syms[i]; |
| 3693 | + if (symp == NULL) |
| 3694 | + continue; |
| 3695 | + |
| 3696 | + coff_emit_ndebug_sym (&info, symp, TRUE); |
| 3697 | + } |
| 3698 | + } |
| 3699 | + |
| 3700 | + for (i = 0; i < info.nglobals; i++) |
| 3701 | + { |
| 3702 | + symp = info.globals[i]; |
| 3703 | + if (symp == NULL) |
| 3704 | + continue; |
| 3705 | + |
| 3706 | + coff_emit_ndebug_sym (&info, symp, FALSE); |
| 3707 | + } |
| 3708 | + |
| 3709 | + /* Fixup the AUX entries for the section symbols we have emitted |
| 3710 | + earlier (so they are guaranteed to be at the beginning of the |
| 3711 | + symbol table). In particular, the line number count (which we |
| 3712 | + only have for the text section) is known right now. */ |
| 3713 | + for (i = 0; i < info.nsecsyms; i++) |
| 3714 | + { |
| 3715 | + union internal_auxent *aux; |
| 3716 | + |
| 3717 | + csymp = info.secsyms[i]; |
| 3718 | + |
| 3719 | + aux = &((csymp->native + 1)->u.auxent); |
| 3720 | + aux->x_scn.x_scnlen = csymp->symbol.section->output_section->rawsize; |
| 3721 | + aux->x_scn.x_nreloc = csymp->symbol.section->reloc_count; |
| 3722 | + if (csymp->symbol.section == info.textsect) |
| 3723 | + aux->x_scn.x_nlinno = info.totlnos; |
| 3724 | + } |
| 3725 | + free (info.secsyms); |
| 3726 | + |
| 3727 | + coff_name_type_hash_traverse (&info.types, coff_free_type_info, NULL); |
| 3728 | + bfd_hash_table_free (&info.types.root); |
| 3729 | + |
| 3730 | + coff_struct_hash_traverse (&info.structs, coff_free_struct_info, NULL); |
| 3731 | + bfd_hash_table_free (&info.structs.root); |
| 3732 | + |
| 3733 | + coff_enum_hash_traverse (&info.enums, coff_free_enum_info, NULL); |
| 3734 | + bfd_hash_table_free (&info.enums.root); |
| 3735 | + |
| 3736 | + /* FIXME: free all the other stuff remembered in "info". */ |
| 3737 | + |
| 3738 | + free (*symppp); |
| 3739 | + |
| 3740 | + *symcountp = info.nsyms; |
| 3741 | + *symppp = (asymbol **)info.syms; |
| 3742 | + |
| 3743 | + return TRUE; |
| 3744 | +} |
| 3745 | + |
| 3746 | +/* Start writing out information for a compilation unit. */ |
| 3747 | + |
| 3748 | +static bfd_boolean |
| 3749 | +coff_start_compilation_unit (p, filename) |
| 3750 | + PTR p; |
| 3751 | + const char *filename; |
| 3752 | +{ |
| 3753 | + struct coff_write_handle *info = (struct coff_write_handle *) p; |
| 3754 | + long i; |
| 3755 | + const char *bn; |
| 3756 | + bfd_boolean found; |
| 3757 | + coff_symbol_type *csymp; |
| 3758 | + |
| 3759 | +#if COFF_DEBUG |
| 3760 | + printf ("coff_start_compilation_unit(%s)\n", filename); |
| 3761 | +#endif |
| 3762 | + |
| 3763 | + /* If there is an old compilation unit that has got any local |
| 3764 | + non-debugging symbols left over, send them out now. */ |
| 3765 | + if (info->currentfile != NULL && info->currentfile->totsyms != 0) |
| 3766 | + for (i = 0; i < info->currentfile->nsyms; i++) |
| 3767 | + { |
| 3768 | + struct coff_compilation_unit *up = info->currentfile; |
| 3769 | + |
| 3770 | + if (up->syms[i] != NULL) |
| 3771 | + { |
| 3772 | + coff_emit_ndebug_sym (info, up->syms[i], TRUE); |
| 3773 | + up->syms[i] = NULL; |
| 3774 | + up->totsyms--; |
| 3775 | + } |
| 3776 | + } |
| 3777 | + |
| 3778 | + /* symtab (and thus COFF debugging) symbols can only transfer the |
| 3779 | + basename of the file, so strip the dirname */ |
| 3780 | + bn = bu_basename (filename); |
| 3781 | + |
| 3782 | + for (i = 0, found = FALSE; i < info->nunits; i++) |
| 3783 | + { |
| 3784 | + if (strcmp (info->units[i].fname, bn) == 0) |
| 3785 | + { |
| 3786 | + info->currentfile = info->units + i; |
| 3787 | + found = TRUE; |
| 3788 | + break; |
| 3789 | + } |
| 3790 | + } |
| 3791 | + if (!found) |
| 3792 | + { |
| 3793 | + fprintf(stderr, |
| 3794 | + _("Warning: file %s not found in symbol table, ignoring\n"), |
| 3795 | + filename); |
| 3796 | + info->currentfile = NULL; |
| 3797 | + return TRUE; |
| 3798 | + } |
| 3799 | + |
| 3800 | + /* Synthesize a new internal COFF symbol. */ |
| 3801 | + csymp = (coff_symbol_type *) coff_bfd_make_debug_symbol (info->abfd, 0, 0); |
| 3802 | + if (csymp == NULL) |
| 3803 | + return FALSE; |
| 3804 | + |
| 3805 | + /* Note that coff_fix_symbol_name() [coffgen.c] will fix this for |
| 3806 | + us: the symbol name will be replaced by ".file", and the filename |
| 3807 | + will be moved to the aux entries. We use the long name obtained |
| 3808 | + from the debugging information (that includes the full path) if |
| 3809 | + our COFF format supports long filenames, otherwise we only use |
| 3810 | + the basename of the file. */ |
| 3811 | + if (bfd_coff_long_filenames (info->abfd)) |
| 3812 | + csymp->symbol.name = filename; |
| 3813 | + else |
| 3814 | + csymp->symbol.name = bn; |
| 3815 | + csymp->symbol.value = 0; |
| 3816 | + csymp->symbol.udata.p = NULL; |
| 3817 | + csymp->native->u.syment.n_sclass = C_FILE; |
| 3818 | + csymp->native->u.syment.n_numaux = 1; /* force filename into aux entry */ |
| 3819 | + coff_record_symbol (info, csymp); |
| 3820 | + |
| 3821 | + return TRUE; |
| 3822 | +} |
| 3823 | + |
| 3824 | +/* Start writing out information for a particular source file. */ |
| 3825 | + |
| 3826 | +static bfd_boolean |
| 3827 | +coff_start_source (p, filename) |
| 3828 | + PTR p ATTRIBUTE_UNUSED; |
| 3829 | + const char *filename ATTRIBUTE_UNUSED; |
| 3830 | +{ |
| 3831 | + |
| 3832 | +#if COFF_DEBUG |
| 3833 | + printf ("coff_start_source(%s)\n", filename); |
| 3834 | +#endif |
| 3835 | + |
| 3836 | + /* COFF cannot handle include filenames. */ |
| 3837 | + |
| 3838 | + return TRUE; |
| 3839 | +} |
| 3840 | + |
| 3841 | +/* Push an empty type. This shouldn't normally happen. */ |
| 3842 | + |
| 3843 | +static bfd_boolean |
| 3844 | +coff_empty_type (p) |
| 3845 | + PTR p; |
| 3846 | +{ |
| 3847 | + struct coff_write_handle *info = (struct coff_write_handle *) p; |
| 3848 | + struct coff_type_stack *tst; |
| 3849 | + |
| 3850 | +#if COFF_DEBUG |
| 3851 | + printf ("coff_empty_type()\n"); |
| 3852 | +#endif |
| 3853 | + |
| 3854 | + coff_push_type (TS_EMPTY); |
| 3855 | + |
| 3856 | + return TRUE; |
| 3857 | +} |
| 3858 | + |
| 3859 | +/* Push a void type. */ |
| 3860 | + |
| 3861 | +static bfd_boolean |
| 3862 | +coff_void_type (p) |
| 3863 | + PTR p; |
| 3864 | +{ |
| 3865 | + struct coff_write_handle *info = (struct coff_write_handle *) p; |
| 3866 | + struct coff_type_stack *tst; |
| 3867 | + |
| 3868 | +#if COFF_DEBUG |
| 3869 | + printf ("coff_void_type()\n"); |
| 3870 | +#endif |
| 3871 | + |
| 3872 | + coff_push_type (TS_VOID); |
| 3873 | + |
| 3874 | + return TRUE; |
| 3875 | +} |
| 3876 | + |
| 3877 | +/* Push an integer type. */ |
| 3878 | + |
| 3879 | +static bfd_boolean |
| 3880 | +coff_int_type (p, size, unsignedp) |
| 3881 | + PTR p; |
| 3882 | + unsigned int size; |
| 3883 | + bfd_boolean unsignedp; |
| 3884 | +{ |
| 3885 | + struct coff_write_handle *info = (struct coff_write_handle *) p; |
| 3886 | + struct coff_type_stack *tst; |
| 3887 | + |
| 3888 | +#if COFF_DEBUG |
| 3889 | + printf ("coff_int_type(%d, %d)\n", size, unsignedp); |
| 3890 | +#endif |
| 3891 | + |
| 3892 | + coff_push_type (TS_INT); |
| 3893 | + tst->u.ts_int.size = size; |
| 3894 | + tst->u.ts_int.isunsigned = unsignedp; |
| 3895 | + |
| 3896 | + return TRUE; |
| 3897 | +} |
| 3898 | + |
| 3899 | +/* Push a floating point type. */ |
| 3900 | + |
| 3901 | +static bfd_boolean |
| 3902 | +coff_float_type (p, size) |
| 3903 | + PTR p; |
| 3904 | + unsigned int size; |
| 3905 | +{ |
| 3906 | + struct coff_write_handle *info = (struct coff_write_handle *) p; |
| 3907 | + struct coff_type_stack *tst; |
| 3908 | + |
| 3909 | +#if COFF_DEBUG |
| 3910 | + printf ("coff_float_type(%d)\n", size); |
| 3911 | +#endif |
| 3912 | + |
| 3913 | + coff_push_type (TS_FLOAT); |
| 3914 | + tst->u.ts_float.size = size; |
| 3915 | + |
| 3916 | + return TRUE; |
| 3917 | +} |
| 3918 | + |
| 3919 | +/* Push a complex type. */ |
| 3920 | + |
| 3921 | +static bfd_boolean |
| 3922 | +coff_complex_type (p, size) |
| 3923 | + PTR p; |
| 3924 | + unsigned int size ATTRIBUTE_UNUSED; |
| 3925 | +{ |
| 3926 | + struct coff_write_handle *info = (struct coff_write_handle *) p; |
| 3927 | + struct coff_type_stack *tst; |
| 3928 | + |
| 3929 | +#if COFF_DEBUG |
| 3930 | + printf ("coff_complex_type(%d)\n", size); |
| 3931 | +#endif |
| 3932 | + |
| 3933 | + coff_push_type (TS_COMPLEX); |
| 3934 | + |
| 3935 | + return TRUE; |
| 3936 | +} |
| 3937 | + |
| 3938 | +/* Push a bfd_boolean type. */ |
| 3939 | + |
| 3940 | +static bfd_boolean |
| 3941 | +coff_bool_type (p, size) |
| 3942 | + PTR p; |
| 3943 | + unsigned int size; |
| 3944 | +{ |
| 3945 | + struct coff_write_handle *info = (struct coff_write_handle *) p; |
| 3946 | + struct coff_type_stack *tst; |
| 3947 | + |
| 3948 | +#if COFF_DEBUG |
| 3949 | + printf ("coff_bool_type(%d)\n", size); |
| 3950 | +#endif |
| 3951 | + |
| 3952 | + coff_push_type (TS_INT); |
| 3953 | + tst->u.ts_int.size = size; |
| 3954 | + tst->u.ts_int.isunsigned = TRUE; |
| 3955 | + |
| 3956 | + return TRUE; |
| 3957 | +} |
| 3958 | + |
| 3959 | +/* Push an enum type. */ |
| 3960 | + |
| 3961 | +static bfd_boolean |
| 3962 | +coff_enum_type (p, tag, names, vals) |
| 3963 | + PTR p; |
| 3964 | + const char *tag; |
| 3965 | + const char **names; |
| 3966 | + bfd_signed_vma *vals; |
| 3967 | +{ |
| 3968 | + struct coff_write_handle *info = (struct coff_write_handle *) p; |
| 3969 | + struct coff_type_stack *tst; |
| 3970 | + char buf[20]; |
| 3971 | + |
| 3972 | +#if COFF_DEBUG |
| 3973 | + int idx; |
| 3974 | + printf ("coff_enum_type(%s [", tag); |
| 3975 | + for (idx = 0; names[idx] != NULL; idx++) |
| 3976 | + printf ("%s -> %d, ", names[idx], (int)vals[idx]); |
| 3977 | + printf ("])\n"); |
| 3978 | +#endif |
| 3979 | + |
| 3980 | + coff_push_type (TS_ENUM); |
| 3981 | + |
| 3982 | + if (tag == NULL) |
| 3983 | + { |
| 3984 | + sprintf(buf, ".%dfake", info->nenums++); |
| 3985 | + tst->u.ts_enum.tag.malloctag = xstrdup (buf); |
| 3986 | + tst->u.ts_enum.tagismalloced = TRUE; |
| 3987 | + } |
| 3988 | + else |
| 3989 | + tst->u.ts_enum.tag.fixtag = tag; |
| 3990 | + tst->u.ts_enum.names = names; |
| 3991 | + tst->u.ts_enum.vals = vals; |
| 3992 | + |
| 3993 | + return TRUE; |
| 3994 | +} |
| 3995 | + |
| 3996 | +/* Push a pointer type. */ |
| 3997 | + |
| 3998 | +static bfd_boolean |
| 3999 | +coff_pointer_type (p) |
| 4000 | + PTR p; |
| 4001 | +{ |
| 4002 | + struct coff_write_handle *info = (struct coff_write_handle *) p; |
| 4003 | + struct coff_type_stack *tst; |
| 4004 | + |
| 4005 | +#if COFF_DEBUG |
| 4006 | + printf ("coff_pointer_type()\n"); |
| 4007 | +#endif |
| 4008 | + |
| 4009 | + coff_push_type (TS_POINTER); |
| 4010 | + |
| 4011 | + return TRUE; |
| 4012 | +} |
| 4013 | + |
| 4014 | +/* Push a function type. */ |
| 4015 | + |
| 4016 | +static bfd_boolean |
| 4017 | +coff_function_type (p, argcount, varargs) |
| 4018 | + PTR p; |
| 4019 | + int argcount; |
| 4020 | + bfd_boolean varargs ATTRIBUTE_UNUSED; |
| 4021 | +{ |
| 4022 | + struct coff_write_handle *info = (struct coff_write_handle *) p; |
| 4023 | + struct coff_type_stack *tst; |
| 4024 | + |
| 4025 | +#if COFF_DEBUG |
| 4026 | + printf ("coff_function_type(%d, %d)\n", argcount, varargs); |
| 4027 | +#endif |
| 4028 | + |
| 4029 | + coff_push_type (TS_FUNC); |
| 4030 | + |
| 4031 | + /* FIXME should properly discard function arguments */ |
| 4032 | + if (argcount > -1) |
| 4033 | + { |
| 4034 | + fprintf (stderr, |
| 4035 | + _("coff_function_type() called with positive argcount\n")); |
| 4036 | + return FALSE; |
| 4037 | + } |
| 4038 | + |
| 4039 | + return TRUE; |
| 4040 | +} |
| 4041 | + |
| 4042 | +/* Push a reference type. */ |
| 4043 | + |
| 4044 | +static bfd_boolean |
| 4045 | +coff_reference_type (p) |
| 4046 | + PTR p; |
| 4047 | +{ |
| 4048 | + struct coff_write_handle *info = (struct coff_write_handle *) p; |
| 4049 | + |
| 4050 | +#if COFF_DEBUG |
| 4051 | + printf ("coff_reference_type()\n"); |
| 4052 | +#endif |
| 4053 | + |
| 4054 | + coff_complain_unsupp (_("reference")); |
| 4055 | + |
| 4056 | + return TRUE; |
| 4057 | +} |
| 4058 | + |
| 4059 | +/* Push a range type. */ |
| 4060 | + |
| 4061 | +static bfd_boolean |
| 4062 | +coff_range_type (p, low, high) |
| 4063 | + PTR p; |
| 4064 | + bfd_signed_vma low ATTRIBUTE_UNUSED; |
| 4065 | + bfd_signed_vma high ATTRIBUTE_UNUSED; |
| 4066 | +{ |
| 4067 | + struct coff_write_handle *info = (struct coff_write_handle *) p; |
| 4068 | + |
| 4069 | +#if COFF_DEBUG |
| 4070 | + printf ("coff_range_type([%d..%d)\n", (int)low, (int)high); |
| 4071 | +#endif |
| 4072 | + |
| 4073 | + coff_complain_unsupp (_("range")); |
| 4074 | + |
| 4075 | + return TRUE; |
| 4076 | +} |
| 4077 | + |
| 4078 | +/* Push an array type. */ |
| 4079 | + |
| 4080 | +static bfd_boolean |
| 4081 | +coff_array_type (p, low, high, stringp) |
| 4082 | + PTR p; |
| 4083 | + bfd_signed_vma low; |
| 4084 | + bfd_signed_vma high; |
| 4085 | + bfd_boolean stringp; |
| 4086 | +{ |
| 4087 | + struct coff_write_handle *info = (struct coff_write_handle *) p; |
| 4088 | + struct coff_type_stack *tst; |
| 4089 | + |
| 4090 | +#if COFF_DEBUG |
| 4091 | + printf ("coff_array_type([%d..%d], %d)\n", |
| 4092 | + (int)low, (int)high, stringp); |
| 4093 | +#endif |
| 4094 | + |
| 4095 | + /* Pop the range type, but ignore it. COFF doesn't use it. */ |
| 4096 | + coff_pop_type (); |
| 4097 | + |
| 4098 | + /* FIXME What to do here? */ |
| 4099 | + if (stringp) |
| 4100 | + { |
| 4101 | + fprintf(stderr, _("coff_array_type(): stringp == TRUE\n")); |
| 4102 | + return FALSE; |
| 4103 | + } |
| 4104 | + |
| 4105 | + coff_push_type (TS_ARRAY); |
| 4106 | + tst->u.ts_array.low = low; |
| 4107 | + tst->u.ts_array.high = high; |
| 4108 | + |
| 4109 | + return TRUE; |
| 4110 | +} |
| 4111 | + |
| 4112 | +/* Push a set type. */ |
| 4113 | + |
| 4114 | +static bfd_boolean |
| 4115 | +coff_set_type (p, bitstringp) |
| 4116 | + PTR p; |
| 4117 | + bfd_boolean bitstringp ATTRIBUTE_UNUSED; |
| 4118 | +{ |
| 4119 | + struct coff_write_handle *info = (struct coff_write_handle *) p; |
| 4120 | + |
| 4121 | +#if COFF_DEBUG |
| 4122 | + printf ("coff_set_type(%d)\n", bitstringp); |
| 4123 | +#endif |
| 4124 | + |
| 4125 | + coff_complain_unsupp (_("set")); |
| 4126 | + |
| 4127 | + return TRUE; |
| 4128 | +} |
| 4129 | + |
| 4130 | +/* Push an offset type. */ |
| 4131 | + |
| 4132 | +static bfd_boolean |
| 4133 | +coff_offset_type (p) |
| 4134 | + PTR p; |
| 4135 | +{ |
| 4136 | + struct coff_write_handle *info = (struct coff_write_handle *) p; |
| 4137 | + |
| 4138 | +#if COFF_DEBUG |
| 4139 | + printf ("coff_offset_type()\n"); |
| 4140 | +#endif |
| 4141 | + |
| 4142 | + coff_complain_unsupp (_("offset")); |
| 4143 | + |
| 4144 | + return TRUE; |
| 4145 | +} |
| 4146 | + |
| 4147 | +/* Push a method type. */ |
| 4148 | + |
| 4149 | +static bfd_boolean |
| 4150 | +coff_method_type (p, domainp, argcount, varargs) |
| 4151 | + PTR p; |
| 4152 | + bfd_boolean domainp ATTRIBUTE_UNUSED; |
| 4153 | + int argcount ATTRIBUTE_UNUSED; |
| 4154 | + bfd_boolean varargs ATTRIBUTE_UNUSED; |
| 4155 | +{ |
| 4156 | + struct coff_write_handle *info = (struct coff_write_handle *) p; |
| 4157 | + |
| 4158 | +#if COFF_DEBUG |
| 4159 | + printf ("coff_method_type(%d, %d, %d)\n", |
| 4160 | + domainp, argcount, varargs); |
| 4161 | +#endif |
| 4162 | + |
| 4163 | + coff_complain_unsupp (_("method")); |
| 4164 | + |
| 4165 | + return TRUE; |
| 4166 | +} |
| 4167 | + |
| 4168 | +/* Push a const version of a type. */ |
| 4169 | + |
| 4170 | +static bfd_boolean |
| 4171 | +coff_const_type (p) |
| 4172 | + PTR p ATTRIBUTE_UNUSED; |
| 4173 | +{ |
| 4174 | + |
| 4175 | +#if COFF_DEBUG |
| 4176 | + printf ("coff_const_type()\n"); |
| 4177 | +#endif |
| 4178 | + |
| 4179 | + /* const modifier is ignored by COFF */ |
| 4180 | + |
| 4181 | + return TRUE; |
| 4182 | +} |
| 4183 | + |
| 4184 | +/* Push a volatile version of a type. */ |
| 4185 | + |
| 4186 | +static bfd_boolean |
| 4187 | +coff_volatile_type (p) |
| 4188 | + PTR p ATTRIBUTE_UNUSED; |
| 4189 | +{ |
| 4190 | + |
| 4191 | +#if COFF_DEBUG |
| 4192 | + printf ("coff_volatile_type()\n"); |
| 4193 | +#endif |
| 4194 | + |
| 4195 | + /* volatile modifier is ignored by COFF */ |
| 4196 | + |
| 4197 | + return TRUE; |
| 4198 | +} |
| 4199 | + |
| 4200 | +/* Start outputting a struct. */ |
| 4201 | + |
| 4202 | +static bfd_boolean |
| 4203 | +coff_start_struct_type (p, tag, id, structp, size) |
| 4204 | + PTR p; |
| 4205 | + const char *tag; |
| 4206 | + unsigned int id; |
| 4207 | + bfd_boolean structp; |
| 4208 | + unsigned int size; |
| 4209 | +{ |
| 4210 | + struct coff_write_handle *info = (struct coff_write_handle *) p; |
| 4211 | + struct coff_type_stack *tst, *savedts; |
| 4212 | + struct coff_struct_hash_entry *shash; |
| 4213 | + char buf[20]; |
| 4214 | + const char *name; |
| 4215 | + |
| 4216 | +#if COFF_DEBUG |
| 4217 | + printf ("coff_start_struct_type(%s, %d, %d, %d)\n", |
| 4218 | + tag, id, structp, size); |
| 4219 | +#endif |
| 4220 | + |
| 4221 | + savedts = info->tstack; |
| 4222 | + info->tstack = NULL; |
| 4223 | + |
| 4224 | + coff_push_type (TS_STRUCT); |
| 4225 | + |
| 4226 | + if (tag == NULL) |
| 4227 | + { |
| 4228 | + sprintf(buf, ".%dfake", id); |
| 4229 | + name = tst->u.ts_struct.tag.malloctag = xstrdup (buf); |
| 4230 | + tst->u.ts_struct.tagismalloced = TRUE; |
| 4231 | + } |
| 4232 | + else |
| 4233 | + name = tst->u.ts_struct.tag.fixtag = tag; |
| 4234 | + tst->u.ts_struct.id = id; |
| 4235 | + tst->u.ts_struct.isstruct = structp; |
| 4236 | + tst->u.ts_struct.size = size; |
| 4237 | + tst->u.ts_struct.savedts = savedts; |
| 4238 | + |
| 4239 | + shash = coff_struct_hash_lookup (&info->structs, name, FALSE, FALSE); |
| 4240 | + if (shash != NULL && shash->types != NULL) |
| 4241 | + { |
| 4242 | +#if COFF_DEBUG |
| 4243 | + printf ("new %s definition for %s\n", |
| 4244 | + tst->u.ts_struct.isstruct? "struct": "union", name); |
| 4245 | +#endif |
| 4246 | + coff_free_struct_info (shash, NULL); |
| 4247 | + shash->types = NULL; |
| 4248 | + shash->emitted = FALSE; |
| 4249 | + } |
| 4250 | + else |
| 4251 | + (void)coff_struct_hash_lookup (&info->structs, name, |
| 4252 | + TRUE, tst->u.ts_struct.tagismalloced); |
| 4253 | + |
| 4254 | + return TRUE; |
| 4255 | +} |
| 4256 | + |
| 4257 | +/* Add a field to a struct. */ |
| 4258 | + |
| 4259 | +static bfd_boolean |
| 4260 | +coff_struct_field (p, name, bitpos, bitsize, visibility) |
| 4261 | + PTR p; |
| 4262 | + const char *name; |
| 4263 | + bfd_vma bitpos; |
| 4264 | + bfd_vma bitsize; |
| 4265 | + enum debug_visibility visibility; |
| 4266 | +{ |
| 4267 | + struct coff_write_handle *info = (struct coff_write_handle *) p; |
| 4268 | + struct coff_type_stack *tst, *otst; |
| 4269 | + struct coff_struct_fields *fp; |
| 4270 | + struct coff_struct_hash_entry *shash; |
| 4271 | + struct coff_enum_hash_entry *ehash; |
| 4272 | + const char *tag; |
| 4273 | + |
| 4274 | +#if COFF_DEBUG |
| 4275 | + printf ("coff_struct_field(%s, %d, %d, %d)\n", |
| 4276 | + name, (int)bitpos, (int)bitsize, (int)visibility); |
| 4277 | +#endif |
| 4278 | + |
| 4279 | + /* Find the last element on the type stack. */ |
| 4280 | + assert (info->tstack != NULL); |
| 4281 | + for (tst = info->tstack, otst = NULL; tst->next != NULL;) |
| 4282 | + { |
| 4283 | + otst = tst; |
| 4284 | + tst = tst->next; |
| 4285 | + } |
| 4286 | + if (otst != NULL) |
| 4287 | + otst->next = NULL; |
| 4288 | + |
| 4289 | + if (tst->tsk != TS_STRUCT) |
| 4290 | + { |
| 4291 | + fprintf (stderr, "coff_struct_field() not within structure definition\n"); |
| 4292 | + return FALSE; |
| 4293 | + } |
| 4294 | + tst->u.ts_struct.fields = (struct coff_struct_fields *) |
| 4295 | + xrealloc (tst->u.ts_struct.fields, |
| 4296 | + ++tst->u.ts_struct.nfields * sizeof (struct coff_struct_fields)); |
| 4297 | + fp = tst->u.ts_struct.fields + (tst->u.ts_struct.nfields - 1); |
| 4298 | + fp->name = name; |
| 4299 | + fp->bitpos = bitpos; |
| 4300 | + fp->bitsize = bitsize; |
| 4301 | + fp->visibility = visibility; |
| 4302 | + otst = fp->types = info->tstack; |
| 4303 | + while (otst->next != NULL) |
| 4304 | + otst = otst->next; |
| 4305 | + if (otst->tsk == TS_STRUCT && otst->u.ts_struct.shash == NULL) |
| 4306 | + { |
| 4307 | + if (otst->u.ts_struct.tagismalloced) |
| 4308 | + tag = otst->u.ts_struct.tag.malloctag; |
| 4309 | + else |
| 4310 | + tag = otst->u.ts_struct.tag.fixtag; |
| 4311 | + shash = coff_struct_hash_lookup (&info->structs, tag, FALSE, FALSE); |
| 4312 | + assert (shash != NULL); |
| 4313 | + if (!shash->emitted) |
| 4314 | + { |
| 4315 | + if (shash->types == NULL) |
| 4316 | + { |
| 4317 | + shash->types = (struct coff_type_stack *) |
| 4318 | + xmalloc (sizeof (struct coff_type_stack)); |
| 4319 | + memcpy (shash->types, otst, sizeof (struct coff_type_stack)); |
| 4320 | + } |
| 4321 | + shash->emitted = TRUE; |
| 4322 | + coff_emit_struct (info, otst, shash); |
| 4323 | + } |
| 4324 | + } |
| 4325 | + else if (otst->tsk == TS_ENUM) |
| 4326 | + { |
| 4327 | + if (otst->u.ts_enum.tagismalloced) |
| 4328 | + tag = otst->u.ts_enum.tag.malloctag; |
| 4329 | + else |
| 4330 | + tag = otst->u.ts_enum.tag.fixtag; |
| 4331 | + ehash = coff_enum_hash_lookup (&info->enums, tag, TRUE, FALSE); |
| 4332 | + assert (ehash != NULL); |
| 4333 | + if (!ehash->emitted) |
| 4334 | + { |
| 4335 | + if (ehash->types == NULL) |
| 4336 | + { |
| 4337 | + ehash->types = (struct coff_type_stack *) |
| 4338 | + xmalloc (sizeof (struct coff_type_stack)); |
| 4339 | + memcpy (ehash->types, otst, sizeof (struct coff_type_stack)); |
| 4340 | + } |
| 4341 | + ehash->emitted = TRUE; |
| 4342 | + coff_emit_enum (info, otst, ehash); |
| 4343 | + } |
| 4344 | + } |
| 4345 | + |
| 4346 | + info->tstack = tst; |
| 4347 | + |
| 4348 | + return TRUE; |
| 4349 | +} |
| 4350 | + |
| 4351 | +/* Finish up a struct. */ |
| 4352 | + |
| 4353 | +static bfd_boolean |
| 4354 | +coff_end_struct_type (p) |
| 4355 | + PTR p; |
| 4356 | +{ |
| 4357 | + struct coff_write_handle *info = (struct coff_write_handle *) p; |
| 4358 | + struct coff_type_stack *tst, *savedts; |
| 4359 | + |
| 4360 | +#if COFF_DEBUG |
| 4361 | + printf ("coff_end_struct_type()\n"); |
| 4362 | +#endif |
| 4363 | + |
| 4364 | + /* Our struct definition should be the only type stack element by |
| 4365 | + now. */ |
| 4366 | + assert (info->tstack != NULL); |
| 4367 | + tst = info->tstack; |
| 4368 | + if (tst->tsk != TS_STRUCT || tst->next != NULL) |
| 4369 | + { |
| 4370 | + fprintf (stderr, "coff_struct_field() not within structure definition\n"); |
| 4371 | + return FALSE; |
| 4372 | + } |
| 4373 | + |
| 4374 | + /* Restore saved type stack, and push our now complete struct |
| 4375 | + definition on top. */ |
| 4376 | + savedts = tst->u.ts_struct.savedts; |
| 4377 | + tst->u.ts_struct.savedts = info->tstack; |
| 4378 | + info->tstack = savedts; |
| 4379 | + tst->next = info->tstack; |
| 4380 | + info->tstack = tst; |
| 4381 | + |
| 4382 | + return TRUE; |
| 4383 | +} |
| 4384 | + |
| 4385 | +/* Start outputting a class. */ |
| 4386 | + |
| 4387 | +static bfd_boolean |
| 4388 | +coff_start_class_type (p, tag, id, structp, size, vptr, ownvptr) |
| 4389 | + PTR p; |
| 4390 | + const char *tag ATTRIBUTE_UNUSED; |
| 4391 | + unsigned int id ATTRIBUTE_UNUSED; |
| 4392 | + bfd_boolean structp ATTRIBUTE_UNUSED; |
| 4393 | + unsigned int size ATTRIBUTE_UNUSED; |
| 4394 | + bfd_boolean vptr ATTRIBUTE_UNUSED; |
| 4395 | + bfd_boolean ownvptr ATTRIBUTE_UNUSED; |
| 4396 | +{ |
| 4397 | + struct coff_write_handle *info = (struct coff_write_handle *) p; |
| 4398 | + |
| 4399 | +#if COFF_DEBUG |
| 4400 | + printf ("coff_start_class_type(%s, %d, %d, %d, %d, %d)\n", |
| 4401 | + tag, id, structp, size, vptr, ownvptr); |
| 4402 | +#endif |
| 4403 | + |
| 4404 | + coff_complain_unsupp (_("class")); |
| 4405 | + |
| 4406 | + return TRUE; |
| 4407 | +} |
| 4408 | + |
| 4409 | +/* Add a static member to the class on the type stack. */ |
| 4410 | + |
| 4411 | +static bfd_boolean |
| 4412 | +coff_class_static_member (p, name, physname, visibility) |
| 4413 | + PTR p ATTRIBUTE_UNUSED; |
| 4414 | + const char *name ATTRIBUTE_UNUSED; |
| 4415 | + const char *physname ATTRIBUTE_UNUSED; |
| 4416 | + enum debug_visibility visibility ATTRIBUTE_UNUSED; |
| 4417 | +{ |
| 4418 | + |
| 4419 | +#if COFF_DEBUG |
| 4420 | + printf ("coff_class_static_member(%s, %s, %d)\n", |
| 4421 | + name, physname, (int)visibility); |
| 4422 | +#endif |
| 4423 | + |
| 4424 | + return TRUE; |
| 4425 | +} |
| 4426 | + |
| 4427 | +/* Add a base class to the class on the type stack. */ |
| 4428 | + |
| 4429 | +static bfd_boolean |
| 4430 | +coff_class_baseclass (p, bitpos, virtual, visibility) |
| 4431 | + PTR p ATTRIBUTE_UNUSED; |
| 4432 | + bfd_vma bitpos ATTRIBUTE_UNUSED; |
| 4433 | + bfd_boolean virtual ATTRIBUTE_UNUSED; |
| 4434 | + enum debug_visibility visibility ATTRIBUTE_UNUSED; |
| 4435 | +{ |
| 4436 | + |
| 4437 | +#if COFF_DEBUG |
| 4438 | + printf ("coff_class_baseclass(%d, %d, %d)\n", |
| 4439 | + (int)bitpos, virtual, (int)visibility); |
| 4440 | +#endif |
| 4441 | + |
| 4442 | + return TRUE; |
| 4443 | +} |
| 4444 | + |
| 4445 | +/* Start adding a method to the class on the type stack. */ |
| 4446 | + |
| 4447 | +static bfd_boolean |
| 4448 | +coff_class_start_method (p, name) |
| 4449 | + PTR p ATTRIBUTE_UNUSED; |
| 4450 | + const char *name ATTRIBUTE_UNUSED; |
| 4451 | +{ |
| 4452 | + |
| 4453 | +#if COFF_DEBUG |
| 4454 | + printf ("coff_class_start_method(%s)\n", name); |
| 4455 | +#endif |
| 4456 | + |
| 4457 | + return TRUE; |
| 4458 | +} |
| 4459 | + |
| 4460 | +/* Add a variant to the current method. */ |
| 4461 | + |
| 4462 | +static bfd_boolean |
| 4463 | +coff_class_method_variant (p, physname, visibility, constp, volatilep, |
| 4464 | + voffset, contextp) |
| 4465 | + PTR p ATTRIBUTE_UNUSED; |
| 4466 | + const char *physname ATTRIBUTE_UNUSED; |
| 4467 | + enum debug_visibility visibility ATTRIBUTE_UNUSED; |
| 4468 | + bfd_boolean constp ATTRIBUTE_UNUSED; |
| 4469 | + bfd_boolean volatilep ATTRIBUTE_UNUSED; |
| 4470 | + bfd_vma voffset ATTRIBUTE_UNUSED; |
| 4471 | + bfd_boolean contextp ATTRIBUTE_UNUSED; |
| 4472 | +{ |
| 4473 | + |
| 4474 | +#if COFF_DEBUG |
| 4475 | + printf ("coff_class_method_variant(%s, %d, %d, %d, %d, %d)\n", |
| 4476 | + physname, (int)visibility, constp, volatilep, |
| 4477 | + (int)voffset, contextp); |
| 4478 | +#endif |
| 4479 | + |
| 4480 | + return TRUE; |
| 4481 | +} |
| 4482 | + |
| 4483 | +/* Add a static variant to the current method. */ |
| 4484 | + |
| 4485 | +static bfd_boolean |
| 4486 | +coff_class_static_method_variant (p, physname, visibility, constp, volatilep) |
| 4487 | + PTR p ATTRIBUTE_UNUSED; |
| 4488 | + const char *physname ATTRIBUTE_UNUSED; |
| 4489 | + enum debug_visibility visibility ATTRIBUTE_UNUSED; |
| 4490 | + bfd_boolean constp ATTRIBUTE_UNUSED; |
| 4491 | + bfd_boolean volatilep ATTRIBUTE_UNUSED; |
| 4492 | +{ |
| 4493 | + |
| 4494 | +#if COFF_DEBUG |
| 4495 | + printf ("coff_class_static_method_variant(%s, %d, %d, %d)\n", |
| 4496 | + physname, (int)visibility, constp, volatilep); |
| 4497 | +#endif |
| 4498 | + |
| 4499 | + return TRUE; |
| 4500 | +} |
| 4501 | + |
| 4502 | +/* Finish up a method. */ |
| 4503 | + |
| 4504 | +static bfd_boolean |
| 4505 | +coff_class_end_method (p) |
| 4506 | + PTR p ATTRIBUTE_UNUSED; |
| 4507 | +{ |
| 4508 | + |
| 4509 | +#if COFF_DEBUG |
| 4510 | + printf ("coff_class_end_method()\n"); |
| 4511 | +#endif |
| 4512 | + |
| 4513 | + return TRUE; |
| 4514 | +} |
| 4515 | + |
| 4516 | +/* Finish up a class. */ |
| 4517 | + |
| 4518 | +static bfd_boolean |
| 4519 | +coff_end_class_type (p) |
| 4520 | + PTR p ATTRIBUTE_UNUSED; |
| 4521 | +{ |
| 4522 | + |
| 4523 | +#if COFF_DEBUG |
| 4524 | + printf ("coff_end_class_type()\n"); |
| 4525 | +#endif |
| 4526 | + |
| 4527 | + return TRUE; |
| 4528 | +} |
| 4529 | + |
| 4530 | +/* Push a typedef which was previously defined. */ |
| 4531 | + |
| 4532 | +static bfd_boolean |
| 4533 | +coff_typedef_type (p, name) |
| 4534 | + PTR p; |
| 4535 | + const char *name; |
| 4536 | +{ |
| 4537 | + struct coff_write_handle *info = (struct coff_write_handle *) p; |
| 4538 | + struct coff_name_type_hash_entry *nthash; |
| 4539 | + struct coff_type_stack *tst, *newchain, *newst, *temp; |
| 4540 | + |
| 4541 | +#if COFF_DEBUG |
| 4542 | + printf ("coff_typedef_type(%s)\n", name); |
| 4543 | +#endif |
| 4544 | + |
| 4545 | + nthash = coff_name_type_hash_lookup (&info->types, name, FALSE, FALSE); |
| 4546 | + |
| 4547 | + /* nthash should never be NULL, since that would imply that the |
| 4548 | + generic debugging code has asked for a typedef which it has not |
| 4549 | + yet defined. */ |
| 4550 | + assert (nthash != NULL); |
| 4551 | + |
| 4552 | + /* Just push the entire type stack snapshot we've got on top of the |
| 4553 | + existing typestack. See coff_typdef() below for how this |
| 4554 | + works. We need to copy over each element however, since anybody |
| 4555 | + popping elements off the typestack is supposed to free() each of |
| 4556 | + them. */ |
| 4557 | + |
| 4558 | + for (tst = nthash->types, temp = newst = newchain = NULL; tst != NULL;) |
| 4559 | + { |
| 4560 | + temp = newst; |
| 4561 | + newst = (struct coff_type_stack *) xmalloc (sizeof (*newst)); |
| 4562 | + if (newchain == NULL) |
| 4563 | + newchain = newst; |
| 4564 | + memcpy (newst, tst, sizeof (*newst)); |
| 4565 | + if (temp != NULL) |
| 4566 | + temp->next = newst; |
| 4567 | + |
| 4568 | + tst = tst->next; |
| 4569 | + } |
| 4570 | + newst->next = info->tstack; |
| 4571 | + info->tstack = newchain; |
| 4572 | + |
| 4573 | + return TRUE; |
| 4574 | +} |
| 4575 | + |
| 4576 | +/* Push a struct, union or class tag. */ |
| 4577 | + |
| 4578 | +static bfd_boolean |
| 4579 | +coff_tag_type (p, name, id, kind) |
| 4580 | + PTR p; |
| 4581 | + const char *name; |
| 4582 | + unsigned int id ATTRIBUTE_UNUSED; |
| 4583 | + enum debug_type_kind kind; |
| 4584 | +{ |
| 4585 | + struct coff_write_handle *info = (struct coff_write_handle *) p; |
| 4586 | + struct coff_type_stack *tst, *newchain, *newst, *temp; |
| 4587 | + struct coff_struct_hash_entry *shash; |
| 4588 | + struct coff_enum_hash_entry *ehash; |
| 4589 | + char buf[20]; |
| 4590 | + bfd_boolean needcopy = FALSE; |
| 4591 | + bfd_boolean isstruct = TRUE; |
| 4592 | + |
| 4593 | +#if COFF_DEBUG |
| 4594 | + printf ("coff_tag_type(%s, %d, %d)\n", |
| 4595 | + name, id, kind); |
| 4596 | +#endif |
| 4597 | + |
| 4598 | + if (name == NULL) |
| 4599 | + { |
| 4600 | + sprintf(buf, ".%dfake", id); |
| 4601 | + needcopy = TRUE; |
| 4602 | + } |
| 4603 | + |
| 4604 | + switch (kind) |
| 4605 | + { |
| 4606 | + case DEBUG_KIND_UNION: |
| 4607 | + case DEBUG_KIND_UNION_CLASS: |
| 4608 | + isstruct = FALSE; |
| 4609 | + /* FALLTHROUGH */ |
| 4610 | + case DEBUG_KIND_STRUCT: |
| 4611 | + case DEBUG_KIND_CLASS: |
| 4612 | + shash = coff_struct_hash_lookup (&info->structs, |
| 4613 | + name == NULL? buf: name, TRUE, needcopy); |
| 4614 | + assert (shash != NULL); |
| 4615 | + tst = shash->types; |
| 4616 | + if (tst == NULL) |
| 4617 | + { |
| 4618 | + /* This is a reference to a tag that has not yet been |
| 4619 | + defined (i. e., a forward reference). Synthesize a |
| 4620 | + ts_struct entry by now, and mark it for later fixup. */ |
| 4621 | + tst = (struct coff_type_stack *) xmalloc (sizeof *tst); |
| 4622 | + memset (tst, 0, sizeof *tst); |
| 4623 | + tst->tsk = TS_STRUCT; |
| 4624 | + tst->u.ts_struct.isstruct = isstruct; |
| 4625 | + tst->u.ts_struct.shash = shash; |
| 4626 | + } |
| 4627 | + docopystack: |
| 4628 | + /* Just push the entire type stack snapshot we've got on top of the |
| 4629 | + existing typestack. See coff_typdef() below for how this |
| 4630 | + works. We need to copy over each element however, since anybody |
| 4631 | + popping elements off the typestack is supposed to free() each of |
| 4632 | + them. */ |
| 4633 | + for (temp = newst = newchain = NULL; tst != NULL;) |
| 4634 | + { |
| 4635 | + temp = newst; |
| 4636 | + newst = (struct coff_type_stack *) xmalloc (sizeof (*newst)); |
| 4637 | + if (newchain == NULL) |
| 4638 | + newchain = newst; |
| 4639 | + memcpy (newst, tst, sizeof (*newst)); |
| 4640 | + if (temp != NULL) |
| 4641 | + temp->next = newst; |
| 4642 | + |
| 4643 | + tst = tst->next; |
| 4644 | + } |
| 4645 | + if (newst) |
| 4646 | + { |
| 4647 | + newst->next = info->tstack; |
| 4648 | + info->tstack = newchain; |
| 4649 | + } |
| 4650 | + break; |
| 4651 | + |
| 4652 | + case DEBUG_KIND_ENUM: |
| 4653 | + ehash = coff_enum_hash_lookup (&info->enums, |
| 4654 | + name == NULL? buf: name, TRUE, needcopy); |
| 4655 | + assert (ehash != NULL); |
| 4656 | + tst = ehash->types; |
| 4657 | + if (tst == NULL) |
| 4658 | + { |
| 4659 | + /* This is a reference to a tag that has not yet been |
| 4660 | + defined (i. e., a forward reference). Synthesize a |
| 4661 | + ts_enum entry by now, and mark it for later fixup. */ |
| 4662 | + tst = (struct coff_type_stack *) xmalloc (sizeof *tst); |
| 4663 | + memset (tst, 0, sizeof *tst); |
| 4664 | + tst->tsk = TS_ENUM; |
| 4665 | + tst->u.ts_enum.ehash = ehash; |
| 4666 | + } |
| 4667 | + goto docopystack; |
| 4668 | + |
| 4669 | + default: |
| 4670 | + fprintf (stderr, _("illegal kind %d in coff_tag_type()\n"), |
| 4671 | + (int)kind); |
| 4672 | + return FALSE; |
| 4673 | + } |
| 4674 | + return TRUE; |
| 4675 | +} |
| 4676 | + |
| 4677 | +/* Define a typedef. */ |
| 4678 | + |
| 4679 | +static bfd_boolean |
| 4680 | +coff_typdef (p, name) |
| 4681 | + PTR p; |
| 4682 | + const char *name; |
| 4683 | +{ |
| 4684 | + struct coff_write_handle *info = (struct coff_write_handle *) p; |
| 4685 | + struct coff_name_type_hash_entry *nthash; |
| 4686 | + |
| 4687 | +#if COFF_DEBUG |
| 4688 | + printf ("coff_typdef(%s)\n", name); |
| 4689 | +#endif |
| 4690 | + |
| 4691 | + /* COFF cannot really handle typedefs. While there is the option to |
| 4692 | + mark a symbol using the storage class C_TPDEF (so the COFF reader |
| 4693 | + will know that name), there is no way to place a reference to |
| 4694 | + that typedef into the just 16 bits COFF reserves for all of its |
| 4695 | + type information. Thus, any use of the typedef must always fully |
| 4696 | + dereference the typedef again. We do this by "snapshotting" the |
| 4697 | + current type stack under the name of our typedef, and later on, |
| 4698 | + when BFD debugging tells us to make use of the typedef (in |
| 4699 | + coff_typedef_type()), we just look it up, and push all we've got |
| 4700 | + completely onto the type stack again. */ |
| 4701 | + |
| 4702 | + if (info->tstack == NULL) |
| 4703 | + { |
| 4704 | + fprintf (stderr, _("coff_typdef() on an empty type stack\n")); |
| 4705 | + return FALSE; |
| 4706 | + } |
| 4707 | + |
| 4708 | + nthash = coff_name_type_hash_lookup (&info->types, name, FALSE, FALSE); |
| 4709 | + if (nthash != NULL) |
| 4710 | + { |
| 4711 | +#if COFF_DEBUG |
| 4712 | + printf ("new typedef for %s\n", name); |
| 4713 | +#endif |
| 4714 | + coff_free_type_info (nthash, NULL); |
| 4715 | + } |
| 4716 | + else |
| 4717 | + nthash = coff_name_type_hash_lookup (&info->types, name, TRUE, FALSE); |
| 4718 | + if (nthash == NULL) |
| 4719 | + return FALSE; |
| 4720 | + nthash->types = info->tstack; |
| 4721 | + |
| 4722 | + /* If the typestack is "sufficiently complex", emit a C_TPDEF symbol |
| 4723 | + for it. We assume it to be sufficiently complex if there are |
| 4724 | + either at least two derived types, or one derived type where the |
| 4725 | + base type is not a simple scalar one. */ |
| 4726 | + if (!nthash->emitted |
| 4727 | + && info->tstack->next != NULL |
| 4728 | + && (info->tstack->next->next != NULL || info->tstack->next->tsk >= TS_ENUM)) |
| 4729 | + { |
| 4730 | + struct coff_type_stack *newchain, *otst, *tst, *ntst; |
| 4731 | + coff_symbol_type *csymp; |
| 4732 | + |
| 4733 | + nthash->emitted = TRUE; |
| 4734 | + |
| 4735 | + for (tst = info->tstack, newchain = otst = NULL; |
| 4736 | + tst != NULL; |
| 4737 | + tst = tst->next) |
| 4738 | + { |
| 4739 | + ntst = (struct coff_type_stack *) |
| 4740 | + xmalloc (sizeof (struct coff_type_stack)); |
| 4741 | + memcpy (ntst, tst, sizeof (struct coff_type_stack)); |
| 4742 | + if (otst == NULL) |
| 4743 | + newchain = ntst; |
| 4744 | + else |
| 4745 | + otst->next = ntst; |
| 4746 | + otst = ntst; |
| 4747 | + } |
| 4748 | + info->tstack = newchain; |
| 4749 | + if (!coff_make_typed_symbol (info, &csymp, TS_NONE)) |
| 4750 | + return FALSE; |
| 4751 | + |
| 4752 | + csymp->symbol.name = xstrdup (name); |
| 4753 | + csymp->symbol.flags = BSF_NOT_AT_END; |
| 4754 | + csymp->symbol.section = bfd_com_section_ptr; |
| 4755 | + csymp->native->u.syment.n_sclass = C_TPDEF; |
| 4756 | + csymp->symbol.value = 0; |
| 4757 | + |
| 4758 | + coff_record_symbol (info, csymp); |
| 4759 | + } |
| 4760 | + info->tstack = NULL; |
| 4761 | + |
| 4762 | + return TRUE; |
| 4763 | +} |
| 4764 | + |
| 4765 | +/* Define a tag. */ |
| 4766 | + |
| 4767 | +static bfd_boolean |
| 4768 | +coff_tag (p, tag) |
| 4769 | + PTR p; |
| 4770 | + const char *tag; |
| 4771 | +{ |
| 4772 | + struct coff_write_handle *info = (struct coff_write_handle *) p; |
| 4773 | + struct coff_type_stack *tst = NULL; |
| 4774 | + struct coff_struct_hash_entry *shash; |
| 4775 | + struct coff_enum_hash_entry *ehash; |
| 4776 | + |
| 4777 | + |
| 4778 | +#if COFF_DEBUG |
| 4779 | + printf ("coff_tag(%s)\n", tag); |
| 4780 | +#endif |
| 4781 | + |
| 4782 | + if (info->tstack == NULL) |
| 4783 | + { |
| 4784 | + fprintf (stderr, _("coff_tag() called on an empty typestack\n")); |
| 4785 | + return FALSE; |
| 4786 | + } |
| 4787 | + |
| 4788 | + switch (info->tstack->tsk) |
| 4789 | + { |
| 4790 | + case TS_STRUCT: |
| 4791 | + shash = coff_struct_hash_lookup (&info->structs, tag, FALSE, FALSE); |
| 4792 | + assert (shash != NULL); |
| 4793 | + shash->types = info->tstack; |
| 4794 | + info->tstack = NULL; |
| 4795 | + break; |
| 4796 | + |
| 4797 | + case TS_ENUM: |
| 4798 | + ehash = coff_enum_hash_lookup (&info->enums, tag, FALSE, FALSE); |
| 4799 | + if (ehash != NULL && ehash->types != NULL) |
| 4800 | + { |
| 4801 | +#if COFF_DEBUG |
| 4802 | + printf ("new enum definition for %s\n", tag); |
| 4803 | +#endif |
| 4804 | + coff_free_enum_info (ehash, NULL); |
| 4805 | + } |
| 4806 | + else |
| 4807 | + ehash = coff_enum_hash_lookup (&info->enums, tag, TRUE, FALSE); |
| 4808 | + if (ehash == NULL) |
| 4809 | + return FALSE; |
| 4810 | + ehash->types = info->tstack; |
| 4811 | + info->tstack = NULL; |
| 4812 | + break; |
| 4813 | + |
| 4814 | + default: |
| 4815 | + fprintf (stderr, _("Illegal typestack (%d) in coff_tag()\n"), tst->tsk); |
| 4816 | + return FALSE; |
| 4817 | + } |
| 4818 | + |
| 4819 | + return TRUE; |
| 4820 | +} |
| 4821 | + |
| 4822 | +/* Define an integer constant. */ |
| 4823 | + |
| 4824 | +static bfd_boolean |
| 4825 | +coff_int_constant (p, name, val) |
| 4826 | + PTR p; |
| 4827 | + const char *name ATTRIBUTE_UNUSED; |
| 4828 | + bfd_vma val ATTRIBUTE_UNUSED; |
| 4829 | +{ |
| 4830 | + struct coff_write_handle *info = (struct coff_write_handle *) p; |
| 4831 | + |
| 4832 | +#if COFF_DEBUG |
| 4833 | + printf ("coff_int_constant(%s, %d)\n", name, (int)val); |
| 4834 | +#endif |
| 4835 | + |
| 4836 | + coff_complain_unsupp (_("int constant")); |
| 4837 | + |
| 4838 | + return TRUE; |
| 4839 | +} |
| 4840 | + |
| 4841 | +/* Define a floating point constant. */ |
| 4842 | + |
| 4843 | +static bfd_boolean |
| 4844 | +coff_float_constant (p, name, val) |
| 4845 | + PTR p; |
| 4846 | + const char *name ATTRIBUTE_UNUSED; |
| 4847 | + double val ATTRIBUTE_UNUSED; |
| 4848 | +{ |
| 4849 | + struct coff_write_handle *info = (struct coff_write_handle *) p; |
| 4850 | + |
| 4851 | +#if COFF_DEBUG |
| 4852 | + printf ("coff_float_constant(%s, %g)\n", name, val); |
| 4853 | +#endif |
| 4854 | + |
| 4855 | + coff_complain_unsupp (_("float constant")); |
| 4856 | + |
| 4857 | + return TRUE; |
| 4858 | +} |
| 4859 | + |
| 4860 | +/* Define a typed constant. */ |
| 4861 | + |
| 4862 | +static bfd_boolean |
| 4863 | +coff_typed_constant (p, name, val) |
| 4864 | + PTR p; |
| 4865 | + const char *name ATTRIBUTE_UNUSED; |
| 4866 | + bfd_vma val ATTRIBUTE_UNUSED; |
| 4867 | +{ |
| 4868 | + struct coff_write_handle *info = (struct coff_write_handle *) p; |
| 4869 | + |
| 4870 | +#if COFF_DEBUG |
| 4871 | + printf ("coff_typed_constant(%s, %d)\n", name, (int)val); |
| 4872 | +#endif |
| 4873 | + |
| 4874 | + coff_complain_unsupp (_("typed constant")); |
| 4875 | + |
| 4876 | + return TRUE; |
| 4877 | +} |
| 4878 | + |
| 4879 | +/* Record a variable. */ |
| 4880 | + |
| 4881 | +static bfd_boolean |
| 4882 | +coff_variable (p, name, kind, val) |
| 4883 | + PTR p; |
| 4884 | + const char *name; |
| 4885 | + enum debug_var_kind kind; |
| 4886 | + bfd_vma val; |
| 4887 | +{ |
| 4888 | + struct coff_write_handle *info = (struct coff_write_handle *) p; |
| 4889 | + unsigned char class; |
| 4890 | + asymbol *symp = NULL; |
| 4891 | + coff_symbol_type *csymp; |
| 4892 | + bfd_boolean global = FALSE; |
| 4893 | + flagword flags = BSF_LOCAL; |
| 4894 | + bfd_vma vmadiff = 0; |
| 4895 | + |
| 4896 | +#if COFF_DEBUG |
| 4897 | + printf ("coff_variable(%s, %d, %d)\n", |
| 4898 | + name, (int)kind, (int)val); |
| 4899 | +#endif |
| 4900 | + |
| 4901 | + switch (kind) |
| 4902 | + { |
| 4903 | + default: |
| 4904 | + abort (); |
| 4905 | + |
| 4906 | + case DEBUG_GLOBAL: |
| 4907 | + flags = BSF_GLOBAL; |
| 4908 | + global = TRUE; |
| 4909 | + /* AVR COFF historically used C_EXTDEF for global variables, and |
| 4910 | + C_EXT for global functions. Since some AVR COFF consumers |
| 4911 | + apparently depend on this, we mimic this behaviour as |
| 4912 | + well. */ |
| 4913 | + class = info->flags & COFF_FL_AVR? C_EXTDEF: C_EXT; |
| 4914 | + break; |
| 4915 | + |
| 4916 | + case DEBUG_STATIC: |
| 4917 | + case DEBUG_LOCAL_STATIC: |
| 4918 | + class = C_STAT; |
| 4919 | + break; |
| 4920 | + |
| 4921 | + case DEBUG_LOCAL: |
| 4922 | + class = C_AUTO; |
| 4923 | + break; |
| 4924 | + |
| 4925 | + case DEBUG_REGISTER: |
| 4926 | + class = C_REG; |
| 4927 | + break; |
| 4928 | + } |
| 4929 | + |
| 4930 | + if (!coff_make_typed_symbol (info, &csymp, TS_NONE)) |
| 4931 | + return FALSE; |
| 4932 | + |
| 4933 | + if (class == C_REG && (info->flags & COFF_FL_AVR) != 0) |
| 4934 | + { |
| 4935 | + struct coff_private_symdata *priv = (struct coff_private_symdata *) |
| 4936 | + csymp->symbol.udata.p; |
| 4937 | + val = coff_fixup_avr_register (val, priv->size * 8); |
| 4938 | + } |
| 4939 | + |
| 4940 | + csymp->symbol.name = name; |
| 4941 | + csymp->symbol.flags = flags; /* Note: this clears BSF_DEBUGGING. */ |
| 4942 | + |
| 4943 | + /* Match the debugging symbol against the input symtab symbols. If |
| 4944 | + we found one, use the section information from it. Otherwise, we |
| 4945 | + are lost here and just use the absolute section that was |
| 4946 | + predeclared by coff_bfd_make_debug_symbol(). C_REG and C_AUTO |
| 4947 | + symbols (which we do not attempt to lookup in the symtab symbols |
| 4948 | + at all) go into the ABS section anyway. */ |
| 4949 | + if (class != C_REG && class != C_AUTO) |
| 4950 | + { |
| 4951 | + symp = coff_find_symbol (info, name, FALSE, global); |
| 4952 | + if (symp) |
| 4953 | + { |
| 4954 | + csymp->symbol.section = symp->section; |
| 4955 | + vmadiff = symp->section->vma; |
| 4956 | + } |
| 4957 | + } |
| 4958 | + |
| 4959 | + /* Symbols are relative to section vma. */ |
| 4960 | + csymp->symbol.value = val - vmadiff; |
| 4961 | + csymp->native->u.syment.n_sclass = class; |
| 4962 | + coff_record_symbol (info, csymp); |
| 4963 | + |
| 4964 | + return TRUE; |
| 4965 | +} |
| 4966 | + |
| 4967 | +/* Start outputting a function. */ |
| 4968 | + |
| 4969 | +static bfd_boolean |
| 4970 | +coff_start_function (p, name, globalp) |
| 4971 | + PTR p; |
| 4972 | + const char *name; |
| 4973 | + bfd_boolean globalp; |
| 4974 | +{ |
| 4975 | + struct coff_write_handle *info = (struct coff_write_handle *) p; |
| 4976 | + struct coff_type_stack *tst, *savedts; |
| 4977 | + |
| 4978 | +#if COFF_DEBUG |
| 4979 | + printf ("coff_start_function(%s, %d)\n", |
| 4980 | + name, globalp); |
| 4981 | +#endif |
| 4982 | + |
| 4983 | + savedts = info->tstack; |
| 4984 | + info->tstack = NULL; |
| 4985 | + |
| 4986 | + coff_push_type (TS_FUNC); |
| 4987 | + |
| 4988 | + if (info->funname != NULL) |
| 4989 | + { |
| 4990 | + fprintf (stderr, |
| 4991 | + _("coff_start_function() called twice, pending %s, new %s\n"), |
| 4992 | + info->funname, name); |
| 4993 | + return FALSE; |
| 4994 | + } |
| 4995 | + info->funname = name; |
| 4996 | + info->funglobal = globalp; |
| 4997 | + info->flags |= COFF_FL_START_FCN; |
| 4998 | + tst->u.ts_func.savedts = savedts; |
| 4999 | + |
| 5000 | + return TRUE; |
| 5001 | +} |
| 5002 | + |
| 5003 | +/* Output a function parameter. */ |
| 5004 | + |
| 5005 | +static bfd_boolean |
| 5006 | +coff_function_parameter (p, name, kind, val) |
| 5007 | + PTR p; |
| 5008 | + const char *name; |
| 5009 | + enum debug_parm_kind kind; |
| 5010 | + bfd_vma val; |
| 5011 | +{ |
| 5012 | + struct coff_write_handle *info = (struct coff_write_handle *) p; |
| 5013 | + coff_symbol_type *csymp; |
| 5014 | + unsigned char class; |
| 5015 | + |
| 5016 | +#if COFF_DEBUG |
| 5017 | + printf ("coff_function_parameter(%s, %d, %d)\n", |
| 5018 | + name, (int)kind, (int)val); |
| 5019 | +#endif |
| 5020 | + |
| 5021 | + switch (kind) |
| 5022 | + { |
| 5023 | + default: |
| 5024 | + abort (); |
| 5025 | + |
| 5026 | + case DEBUG_PARM_STACK: |
| 5027 | + class = C_ARG; |
| 5028 | + break; |
| 5029 | + |
| 5030 | + case DEBUG_PARM_REG: |
| 5031 | + class = C_REGPARM; |
| 5032 | + break; |
| 5033 | + |
| 5034 | + case DEBUG_PARM_REFERENCE: |
| 5035 | + case DEBUG_PARM_REF_REG: |
| 5036 | + fprintf (stderr, _("Reference parameters not available in COFF\n")); |
| 5037 | + return TRUE; |
| 5038 | + } |
| 5039 | + |
| 5040 | + if (!coff_make_typed_symbol (info, &csymp, TS_FUNC)) |
| 5041 | + return FALSE; |
| 5042 | + |
| 5043 | + if (class == C_REGPARM && (info->flags & COFF_FL_AVR) != 0) |
| 5044 | + { |
| 5045 | + struct coff_private_symdata *priv = (struct coff_private_symdata *) |
| 5046 | + csymp->symbol.udata.p; |
| 5047 | + val = coff_fixup_avr_register (val, priv->size * 8); |
| 5048 | + } |
| 5049 | + |
| 5050 | + csymp->symbol.name = name; |
| 5051 | + csymp->symbol.value = val; |
| 5052 | + csymp->symbol.flags |= BSF_LOCAL; |
| 5053 | + csymp->native->u.syment.n_sclass = class; |
| 5054 | + |
| 5055 | + /* Since function parameters precede the actual function definition, |
| 5056 | + defer their output until the function has been created. */ |
| 5057 | + info->fargs = (coff_symbol_type **) |
| 5058 | + xrealloc (info->fargs, ++info->nfargs * sizeof (coff_symbol_type *)); |
| 5059 | + info->fargs[info->nfargs - 1] = csymp; |
| 5060 | + |
| 5061 | + return TRUE; |
| 5062 | +} |
| 5063 | + |
| 5064 | +/* Start a block. */ |
| 5065 | + |
| 5066 | +static bfd_boolean |
| 5067 | +coff_start_block (p, addr) |
| 5068 | + PTR p; |
| 5069 | + bfd_vma addr; |
| 5070 | +{ |
| 5071 | + struct coff_write_handle *info = (struct coff_write_handle *) p; |
| 5072 | + struct coff_type_stack *tst, *otst; |
| 5073 | + struct coff_fix_stack *fixp, *ofp; |
| 5074 | + asymbol *symp; |
| 5075 | + coff_symbol_type *csymp; |
| 5076 | + unsigned int i; |
| 5077 | + bfd_boolean is_start_fcn; |
| 5078 | + |
| 5079 | +#if COFF_DEBUG |
| 5080 | + printf ("coff_start_block(%#x)\n", (int)addr); |
| 5081 | +#endif |
| 5082 | + |
| 5083 | + is_start_fcn = info->flags & COFF_FL_START_FCN; |
| 5084 | + |
| 5085 | + if (is_start_fcn) |
| 5086 | + { |
| 5087 | + /* This is the starting block of a function. We are going to |
| 5088 | + write three symbols here, one for the function itself, one |
| 5089 | + ".bf" symbol to indicate the begin of the function, and |
| 5090 | + finally one ".bb" for the first block inside the function. */ |
| 5091 | + info->flags &= ~COFF_FL_START_FCN; |
| 5092 | + |
| 5093 | + /* Our function definition should be the only type stack element |
| 5094 | + by now. */ |
| 5095 | + assert (info->tstack != NULL); |
| 5096 | + tst = info->tstack; |
| 5097 | + if (tst->tsk != TS_FUNC || tst->next != NULL) |
| 5098 | + { |
| 5099 | + fprintf (stderr, |
| 5100 | + _("coff_start_block() not within function definition\n")); |
| 5101 | + return FALSE; |
| 5102 | + } |
| 5103 | + |
| 5104 | + /* Restore saved type stack, and push our now complete function |
| 5105 | + definition on top. */ |
| 5106 | + info->tstack = tst->u.ts_func.savedts; |
| 5107 | + tst->next = info->tstack; |
| 5108 | + info->tstack = tst; |
| 5109 | + |
| 5110 | + if (info->currentfile == NULL) |
| 5111 | + { |
| 5112 | + fprintf (stderr, |
| 5113 | + _("Warning: ignoring function %s() outside any compilation unit\n"), |
| 5114 | + info->funname); |
| 5115 | + for (tst = info->tstack, otst = NULL; tst != NULL;) |
| 5116 | + { |
| 5117 | + otst = tst; |
| 5118 | + tst = otst->next; |
| 5119 | + if (otst->tsk == TS_ENUM && |
| 5120 | + otst->u.ts_enum.tagismalloced) |
| 5121 | + free (otst->u.ts_enum.tag.malloctag); |
| 5122 | + else if (otst->tsk == TS_STRUCT && |
| 5123 | + otst->u.ts_struct.tagismalloced) |
| 5124 | + free (otst->u.ts_struct.tag.malloctag); |
| 5125 | + free (otst); |
| 5126 | + } |
| 5127 | + info->tstack = NULL; |
| 5128 | + info->funname = NULL; |
| 5129 | + |
| 5130 | + return TRUE; |
| 5131 | + } |
| 5132 | + |
| 5133 | + if (!coff_make_typed_symbol (info, &csymp, TS_NONE)) |
| 5134 | + return FALSE; |
| 5135 | + |
| 5136 | + csymp->symbol.name = info->funname; |
| 5137 | + csymp->symbol.flags = BSF_FUNCTION | |
| 5138 | + (info->funglobal? BSF_GLOBAL: BSF_LOCAL); |
| 5139 | + symp = coff_find_symbol (info, info->funname, TRUE, info->funglobal); |
| 5140 | + if (symp == NULL) |
| 5141 | + { |
| 5142 | + fprintf (stderr, |
| 5143 | + _("function %s not found in symbol table, defaulting to \"text\" section\n"), |
| 5144 | + info->funname); |
| 5145 | + csymp->symbol.section = info->funcsection = info->textsect; |
| 5146 | + } |
| 5147 | + else |
| 5148 | + csymp->symbol.section = info->funcsection = symp->section; |
| 5149 | + |
| 5150 | + /* Symbol addresses are relative to section vma. */ |
| 5151 | + csymp->symbol.value = addr - info->funcsection->vma; |
| 5152 | + csymp->native->u.syment.n_sclass = info->funglobal? C_EXT: C_STAT; |
| 5153 | + /* Create two initial line number entries. The first one holds |
| 5154 | + the function symbol, the second one is the trailing record |
| 5155 | + that is required by coffgen.c::coff_write_native_symbol() to |
| 5156 | + have a line number of zero. */ |
| 5157 | + csymp->lineno = (alent *) xmalloc (2 * sizeof (alent)); |
| 5158 | + memset (csymp->lineno, 0, 2 * sizeof (alent)); |
| 5159 | + info->nlnos = 2; |
| 5160 | + info->totlnos++; |
| 5161 | + csymp->lineno[0].u.sym = (asymbol *)csymp; |
| 5162 | + coff_record_symbol (info, csymp); |
| 5163 | + info->funcindex = info->nsyms - 1; /* remember for later */ |
| 5164 | + /* Record our endndx field for later fixing. */ |
| 5165 | + fixp = (struct coff_fix_stack *) xmalloc (sizeof (struct coff_fix_stack)); |
| 5166 | + fixp->native = csymp->native + 1; /* points to first AUX */ |
| 5167 | + fixp->next = NULL; |
| 5168 | + if (info->fixes == NULL) |
| 5169 | + info->fixes = fixp; |
| 5170 | + else |
| 5171 | + { |
| 5172 | + for (ofp = info->fixes; ofp->next != NULL;) |
| 5173 | + ofp = ofp->next; |
| 5174 | + ofp->next = fixp; |
| 5175 | + } |
| 5176 | + |
| 5177 | + csymp = (coff_symbol_type *) coff_bfd_make_debug_symbol (info->abfd, 0, 0); |
| 5178 | + if (csymp == NULL) |
| 5179 | + return FALSE; |
| 5180 | + |
| 5181 | + csymp->symbol.name = ".bf"; |
| 5182 | + csymp->native->u.syment.n_sclass = C_FCN; |
| 5183 | + csymp->native->u.syment.n_numaux = 1; |
| 5184 | + csymp->symbol.value = addr - info->funcsection->vma; |
| 5185 | + csymp->symbol.section = info->funcsection; |
| 5186 | + csymp->symbol.udata.p = NULL; |
| 5187 | + coff_record_symbol (info, csymp); |
| 5188 | + } |
| 5189 | + |
| 5190 | + if (info->funname == NULL) |
| 5191 | + return TRUE; |
| 5192 | + |
| 5193 | + csymp = (coff_symbol_type *) coff_bfd_make_debug_symbol (info->abfd, 0, 0); |
| 5194 | + if (csymp == NULL) |
| 5195 | + return FALSE; |
| 5196 | + |
| 5197 | + csymp->symbol.name = ".bb"; |
| 5198 | + csymp->native->u.syment.n_sclass = C_BLOCK; |
| 5199 | + csymp->native->u.syment.n_numaux = 1; |
| 5200 | + csymp->symbol.value = addr - info->funcsection->vma; |
| 5201 | + csymp->symbol.section = info->funcsection; |
| 5202 | + csymp->symbol.udata.p = NULL; |
| 5203 | + coff_record_symbol (info, csymp); |
| 5204 | + |
| 5205 | + info->flags |= COFF_FL_FIX_BB; |
| 5206 | + |
| 5207 | + /* Output any pending function parameters, if any. */ |
| 5208 | + if (is_start_fcn && info->nfargs) |
| 5209 | + { |
| 5210 | + for (i = 0; i < info->nfargs; i++) |
| 5211 | + coff_record_symbol (info, info->fargs[i]); |
| 5212 | + |
| 5213 | + free (info->fargs); |
| 5214 | + info->fargs = NULL; |
| 5215 | + info->nfargs = 0; |
| 5216 | + } |
| 5217 | + |
| 5218 | + return TRUE; |
| 5219 | +} |
| 5220 | + |
| 5221 | +/* End a block. */ |
| 5222 | + |
| 5223 | +static bfd_boolean |
| 5224 | +coff_end_block (p, addr) |
| 5225 | + PTR p; |
| 5226 | + bfd_vma addr; |
| 5227 | +{ |
| 5228 | + struct coff_write_handle *info = (struct coff_write_handle *) p; |
| 5229 | + coff_symbol_type *csymp; |
| 5230 | + union internal_auxent *aux; |
| 5231 | + |
| 5232 | +#if COFF_DEBUG |
| 5233 | + printf ("coff_end_block(%#x)\n", (int)addr); |
| 5234 | +#endif |
| 5235 | + |
| 5236 | + if (info->funname == NULL) |
| 5237 | + return TRUE; |
| 5238 | + |
| 5239 | + csymp = (coff_symbol_type *) coff_bfd_make_debug_symbol (info->abfd, 0, 0); |
| 5240 | + if (csymp == NULL) |
| 5241 | + return FALSE; |
| 5242 | + |
| 5243 | + csymp->symbol.name = ".eb"; |
| 5244 | + csymp->symbol.value = addr - info->funcsection->vma; |
| 5245 | + csymp->native->u.syment.n_sclass = C_BLOCK; |
| 5246 | + csymp->native->u.syment.n_numaux = 1; |
| 5247 | + csymp->symbol.udata.p = NULL; |
| 5248 | + csymp->symbol.section = info->funcsection; |
| 5249 | + aux = &((csymp->native + 1)->u.auxent); |
| 5250 | + aux->x_sym.x_misc.x_lnsz.x_lnno = info->lastlno; |
| 5251 | + coff_record_symbol (info, csymp); |
| 5252 | + |
| 5253 | + info->endaddr = addr; |
| 5254 | + |
| 5255 | + return TRUE; |
| 5256 | +} |
| 5257 | + |
| 5258 | +/* End a function. */ |
| 5259 | + |
| 5260 | +static bfd_boolean |
| 5261 | +coff_end_function (p) |
| 5262 | + PTR p; |
| 5263 | +{ |
| 5264 | + struct coff_write_handle *info = (struct coff_write_handle *) p; |
| 5265 | + coff_symbol_type *csymp; |
| 5266 | + union internal_auxent *aux; |
| 5267 | + |
| 5268 | +#if COFF_DEBUG |
| 5269 | + printf ("coff_end_function()\n"); |
| 5270 | +#endif |
| 5271 | + |
| 5272 | + if (info->funname == NULL) |
| 5273 | + return TRUE; |
| 5274 | + |
| 5275 | + csymp = (coff_symbol_type *) coff_bfd_make_debug_symbol (info->abfd, 0, 0); |
| 5276 | + if (csymp == NULL) |
| 5277 | + return FALSE; |
| 5278 | + |
| 5279 | + csymp->symbol.name = ".ef"; |
| 5280 | + csymp->symbol.value = info->endaddr - info->funcsection->vma; |
| 5281 | + csymp->native->u.syment.n_sclass = C_FCN; |
| 5282 | + csymp->native->u.syment.n_numaux = 1; |
| 5283 | + csymp->symbol.udata.p = NULL; |
| 5284 | + csymp->symbol.section = info->funcsection; |
| 5285 | + aux = &((csymp->native + 1)->u.auxent); |
| 5286 | + aux->x_sym.x_misc.x_lnsz.x_lnno = info->lastlno; |
| 5287 | + |
| 5288 | + coff_record_symbol (info, csymp); |
| 5289 | + |
| 5290 | + csymp = (coff_symbol_type *) info->syms[info->funcindex]; |
| 5291 | + aux = &((csymp->native + 1)->u.auxent); |
| 5292 | + aux->x_sym.x_misc.x_fsize = info->endaddr - csymp->symbol.value; |
| 5293 | + |
| 5294 | + info->flags |= COFF_FL_FIX_ENDNDX; |
| 5295 | + info->funname = NULL; |
| 5296 | + |
| 5297 | + return TRUE; |
| 5298 | +} |
| 5299 | + |
| 5300 | +/* Output a line number. */ |
| 5301 | + |
| 5302 | +static bfd_boolean |
| 5303 | +coff_lineno (p, file, lineno, addr) |
| 5304 | + PTR p; |
| 5305 | + const char *file ATTRIBUTE_UNUSED; |
| 5306 | + unsigned long lineno; |
| 5307 | + bfd_vma addr; |
| 5308 | +{ |
| 5309 | + struct coff_write_handle *info = (struct coff_write_handle *) p; |
| 5310 | + coff_symbol_type *csymp; |
| 5311 | + union internal_auxent *aux; |
| 5312 | + long i; |
| 5313 | + |
| 5314 | +#if COFF_DEBUG |
| 5315 | + printf ("coff_lineno(%s, %ld, %d)\n", |
| 5316 | + file, lineno, (int)addr); |
| 5317 | +#endif |
| 5318 | + |
| 5319 | + /* COFF can inherently only handle line numbers inside of functions. |
| 5320 | + If we are not inside a function, punt. */ |
| 5321 | + if (info->funname == NULL) |
| 5322 | + return TRUE; |
| 5323 | + |
| 5324 | + if (info->nlnos == 2) |
| 5325 | + { |
| 5326 | + /* This is the first line number of this function. Fix the line |
| 5327 | + number for the .bf symbol immediately following the start of |
| 5328 | + function. We also have to remember the starting line number |
| 5329 | + of our function since all line number entries are relative to |
| 5330 | + it in COFF. Since regular line numbers must always be |
| 5331 | + non-zero, we artificially force the function to start one |
| 5332 | + line earlier. */ |
| 5333 | + csymp = (coff_symbol_type *) info->syms[info->funcindex + 1]; |
| 5334 | + aux = &((csymp->native + 1)->u.auxent); |
| 5335 | + aux->x_sym.x_misc.x_lnsz.x_lnno = lineno; |
| 5336 | + info->funlno = lineno - 1; |
| 5337 | + } |
| 5338 | + |
| 5339 | + if (info->flags & COFF_FL_FIX_BB) |
| 5340 | + { |
| 5341 | + /* This is the first line number after one (or more) .bb |
| 5342 | + symbols. Fix them. In order to cope with multiple blocks |
| 5343 | + starting at the same line number, we walk back the list of |
| 5344 | + symbols until we find a C_BLOCK one that had already been |
| 5345 | + fixed, or until we find a C_FCN symbol (presumably, the start |
| 5346 | + of our current function). */ |
| 5347 | + info->flags &= ~COFF_FL_FIX_BB; |
| 5348 | + |
| 5349 | + for (i = info->nsyms - 1; i >= 0; i--) |
| 5350 | + { |
| 5351 | + csymp = (coff_symbol_type *) info->syms[i]; |
| 5352 | + if (csymp->native->u.syment.n_sclass == C_FCN) |
| 5353 | + break; |
| 5354 | + if (csymp->native->u.syment.n_sclass == C_BLOCK) |
| 5355 | + { |
| 5356 | + aux = &((csymp->native + 1)->u.auxent); |
| 5357 | + if (aux->x_sym.x_misc.x_lnsz.x_lnno != 0) |
| 5358 | + /* already set up properly */ |
| 5359 | + break; |
| 5360 | + aux->x_sym.x_misc.x_lnsz.x_lnno = lineno; |
| 5361 | + } |
| 5362 | + } |
| 5363 | + } |
| 5364 | + |
| 5365 | + csymp = (coff_symbol_type *) info->syms[info->funcindex]; |
| 5366 | + csymp->lineno = (alent *) xrealloc (csymp->lineno, |
| 5367 | + ++info->nlnos * sizeof (alent)); |
| 5368 | + memset (csymp->lineno + info->nlnos - 1, 0, sizeof (alent)); |
| 5369 | + if (lineno > info->funlno) |
| 5370 | + csymp->lineno[info->nlnos - 2].line_number = lineno - info->funlno; |
| 5371 | + else |
| 5372 | + /* Line number unreasonable. Can e. g. happen for a line number |
| 5373 | + from an include file, which we cannot process in COFF. Just |
| 5374 | + set it to the first line, to avoid generating a large unsigned |
| 5375 | + short (~ 65000) line number. */ |
| 5376 | + csymp->lineno[info->nlnos - 2].line_number = 1; |
| 5377 | + csymp->lineno[info->nlnos - 2].u.offset = addr; |
| 5378 | + |
| 5379 | + info->lastlno = lineno; |
| 5380 | + info->totlnos++; |
| 5381 | + |
| 5382 | + return TRUE; |
| 5383 | +} |
| 5384 | diff -Nruw include/coff/avr.h include/coff/avr.h |
| 5385 | --- include/coff/avr.h 1970-01-01 05:30:00.000000000 +0530 |
| 5386 | +++ include/coff/avr.h 2010-02-10 17:35:58.362724600 +0530 |
| 5387 | @@ -0,0 +1,110 @@ |
| 5388 | +/* coff information for Atmel AVR. |
| 5389 | + |
| 5390 | + Copyright 2001 Free Software Foundation, Inc. |
| 5391 | + |
| 5392 | + This program is free software; you can redistribute it and/or modify |
| 5393 | + it under the terms of the GNU General Public License as published by |
| 5394 | + the Free Software Foundation; either version 2 of the License, or |
| 5395 | + (at your option) any later version. |
| 5396 | + |
| 5397 | + This program is distributed in the hope that it will be useful, |
| 5398 | + but WITHOUT ANY WARRANTY; without even the implied warranty of |
| 5399 | + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| 5400 | + GNU General Public License for more details. |
| 5401 | + |
| 5402 | + You should have received a copy of the GNU General Public License |
| 5403 | + along with this program; if not, write to the Free Software |
| 5404 | + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ |
| 5405 | + |
| 5406 | +/* This file was hacked from i860.h */ |
| 5407 | + |
| 5408 | +#define L_LNNO_SIZE 2 |
| 5409 | +#include "coff/external.h" |
| 5410 | + |
| 5411 | +/* Bits for f_flags: |
| 5412 | + F_RELFLG relocation info stripped from file |
| 5413 | + F_EXEC file is executable (no unresolved external references) |
| 5414 | + F_LNNO line numbers stripped from file |
| 5415 | + F_LSYMS local symbols stripped from file */ |
| 5416 | + |
| 5417 | +#define F_RELFLG (0x0001) |
| 5418 | +#define F_EXEC (0x0002) |
| 5419 | +#define F_LNNO (0x0004) |
| 5420 | +#define F_LSYMS (0x0008) |
| 5421 | +/* Upper nibble of flags always needs to be set. This used to be |
| 5422 | + * undocumented, recent information from Atmel says that bit 7 used to |
| 5423 | + * differentiate between an old vendor-specific deviation of the |
| 5424 | + * format and the current format. */ |
| 5425 | +#define F_JUNK (0x00f0) |
| 5426 | +#define F_UNUSED (0xff00) |
| 5427 | + |
| 5428 | +#define AVRMAGIC 0xa12 |
| 5429 | + |
| 5430 | +#undef AOUTSZ |
| 5431 | +#ifdef AVR_EXT_COFF |
| 5432 | + |
| 5433 | +/* AVR "extended" COFF format. This uses the optional header ("a.out" |
| 5434 | + header) to inform the consumer about some additional features that |
| 5435 | + are supported. */ |
| 5436 | +#define COFF_LONG_FILENAMES yes /* long filenames supported in consecutive aux entries */ |
| 5437 | +#define AOUTSZ 28 /* size of optional header in "extended" COFF */ |
| 5438 | + |
| 5439 | +/* Flags in the optional header; they are stored in the vstamp field. */ |
| 5440 | +#define F_FULLPATHS 0x0001 /* long filenames supported */ |
| 5441 | +#define F_STRUCTINFO 0x0002 /* structure information contained */ |
| 5442 | +#define F_PTRINFO 0x0004 /* inter-segment pointers supported */ |
| 5443 | + |
| 5444 | +#else /* old AVR COFF */ |
| 5445 | + |
| 5446 | +#define AOUTSZ 0 /* no a.out for AVR */ |
| 5447 | +#endif |
| 5448 | + |
| 5449 | +/* #define AVRAOUTMAGIC 0x406 */ /* "general" magic number of optional header */ |
| 5450 | +/* |
| 5451 | + * The following magic number causes AVR Studio 4.x to recognize |
| 5452 | + * avr-gcc/GNU binutils produced AVR extended COFF files. By now, |
| 5453 | + * the only special treatment for them is that the contents of .data |
| 5454 | + * will be appended after .text in the simulator flash. |
| 5455 | + * |
| 5456 | + * 0x9cc has been chosen since it resembles "gcc". ;-) |
| 5457 | + */ |
| 5458 | +#define AVRAOUTMAGIC 0x9cc /* "gcc" magic number */ |
| 5459 | + |
| 5460 | +/* By matching not only the magic number, but also the size of the |
| 5461 | + optional a.out header, we can differentiate between both |
| 5462 | + formats. */ |
| 5463 | +#define AVRBADMAG(x) ((x).f_magic != AVRMAGIC || (x).f_opthdr != AOUTSZ) |
| 5464 | + |
| 5465 | +/* AVR COFF has several anomalities in the way the handle the derived |
| 5466 | + type information, and AUX entries, mainly because they apparently |
| 5467 | + didn't bother to learn how COFF is supposed to work before they |
| 5468 | + started. We fix many of them at the export/import boundary, so all |
| 5469 | + the internal generic COFF handling will work mostly as designed. */ |
| 5470 | + |
| 5471 | +/* NB: these functions are only defined in bfd/coff-avr.c, but also |
| 5472 | + used in coff-ext-avr.c, so the latter can only be configured if the |
| 5473 | + former is also present. This is certainly always the case |
| 5474 | + anyway. */ |
| 5475 | +extern void avr_coff_adjust_sym_in_post |
| 5476 | + PARAMS((bfd *, PTR, PTR)); |
| 5477 | + |
| 5478 | +extern void avr_coff_adjust_sym_out_post |
| 5479 | + PARAMS((bfd *, PTR, PTR)); |
| 5480 | + |
| 5481 | +#define COFF_ADJUST_SYM_IN_POST(ABFD, EXT, INT) \ |
| 5482 | + avr_coff_adjust_sym_in_post (ABFD, EXT, INT) |
| 5483 | + |
| 5484 | +#define COFF_ADJUST_SYM_OUT_POST(ABFD, INT, EXT) \ |
| 5485 | + avr_coff_adjust_sym_out_post (ABFD, INT, EXT) |
| 5486 | + |
| 5487 | +/********************** RELOCATION DIRECTIVES **********************/ |
| 5488 | + |
| 5489 | +struct external_reloc |
| 5490 | +{ |
| 5491 | + char r_vaddr[4]; |
| 5492 | + char r_symndx[4]; |
| 5493 | + char r_type[2]; |
| 5494 | +}; |
| 5495 | + |
| 5496 | +#define RELOC struct external_reloc |
| 5497 | +#define RELSZ 10 |
| 5498 | diff -Nruw include/coff/internal.h include/coff/internal.h |
| 5499 | --- include/coff/internal.h 2009-09-02 12:51:39.000000000 +0530 |
| 5500 | +++ include/coff/internal.h 2010-02-10 17:35:58.378349600 +0530 |
| 5501 | @@ -646,6 +646,8 @@ |
| 5502 | |
| 5503 | }; |
| 5504 | |
| 5505 | +#define NAUXENTS 10 /* number of pre-allocated aux entries */ |