View | Details | Raw Unified | Return to bug 11539 | Differences between
and this patch

Collapse All | Expand All

(-)binutils-2.20/bfd/coffcode.h (-1 / +1 lines)
Lines 5597-5603 Link Here
5597
#endif
5597
#endif
5598
5598
5599
#ifndef coff_bfd_gc_sections
5599
#ifndef coff_bfd_gc_sections
5600
#define coff_bfd_gc_sections		    bfd_generic_gc_sections
5600
#define coff_bfd_gc_sections		    bfd_coff_gc_sections
5601
#endif
5601
#endif
5602
5602
5603
#ifndef coff_bfd_merge_sections
5603
#ifndef coff_bfd_merge_sections
(-)binutils-2.20/bfd/cofflink.c (+448 lines)
Lines 3056-3058 Link Here
3056
    }
3056
    }
3057
  return TRUE;
3057
  return TRUE;
3058
}
3058
}
3059
3060
/* Initialize COOKIE for input bfd ABFD.  */
3061
3062
static bfd_boolean
3063
init_reloc_cookie (struct coff_reloc_cookie *cookie,
3064
		   struct bfd_link_info *info ATTRIBUTE_UNUSED, bfd *abfd)
3065
{
3066
  const bfd_coff_backend_data *bed;
3067
3068
  bed = coff_backend_info (abfd);
3069
3070
  cookie->abfd = abfd;
3071
  cookie->sym_hashes = obj_coff_sym_hashes (abfd);
3072
3073
  /* FIXME: Sometimes the symbol table does not yet have been loaded here;
3074
     is this the correct way to handle it? */
3075
  bfd_coff_slurp_symbol_table(abfd);
3076
3077
  cookie->symbols = obj_symbols(abfd);
3078
3079
  return TRUE;
3080
}
3081
3082
/* Free the memory allocated by init_reloc_cookie, if appropriate.  */
3083
3084
static void
3085
fini_reloc_cookie (struct coff_reloc_cookie *cookie ATTRIBUTE_UNUSED, bfd *abfd ATTRIBUTE_UNUSED)
3086
{
3087
  /* FIXME: Nothing to do for the COFF case it seems? */
3088
#if 0
3089
  coff_Internal_Shdr *symtab_hdr;
3090
3091
  symtab_hdr = &coff_tdata (abfd)->symtab_hdr;
3092
  if (cookie->locsyms != NULL
3093
      && symtab_hdr->contents != (unsigned char *) cookie->locsyms)
3094
    free (cookie->locsyms);
3095
#endif
3096
}
3097
3098
3099
/* Initialize the relocation information in COOKIE for input section SEC
3100
   of input bfd ABFD.  */
3101
3102
static bfd_boolean
3103
init_reloc_cookie_rels (struct coff_reloc_cookie *cookie,
3104
			struct bfd_link_info *info ATTRIBUTE_UNUSED, bfd *abfd,
3105
			asection *sec)
3106
{
3107
  const bfd_coff_backend_data *bed;
3108
3109
  if (sec->reloc_count == 0)
3110
    {
3111
      cookie->rels = NULL;
3112
      cookie->relend = NULL;
3113
    }
3114
  else
3115
    {
3116
      bed = coff_backend_info (abfd);
3117
      cookie->rels = _bfd_coff_read_internal_relocs (abfd, sec, FALSE, NULL, 0, NULL);
3118
      if (cookie->rels == NULL)
3119
	return FALSE;
3120
      cookie->rel = cookie->rels;
3121
      cookie->relend = (cookie->rels + sec->reloc_count);
3122
    }
3123
  cookie->rel = cookie->rels;
3124
  return TRUE;
3125
}
3126
3127
/* Free the memory allocated by init_reloc_cookie_rels,
3128
   if appropriate.  */
3129
3130
static void
3131
fini_reloc_cookie_rels (struct coff_reloc_cookie *cookie,
3132
			asection *sec)
3133
{
3134
  if (cookie->rels && coff_section_data (NULL, sec)->relocs != cookie->rels)
3135
    free (cookie->rels);
3136
}
3137
3138
/* Initialize the whole of COOKIE for input section SEC.  */
3139
3140
static bfd_boolean
3141
init_reloc_cookie_for_section (struct coff_reloc_cookie *cookie,
3142
			       struct bfd_link_info *info,
3143
			       asection *sec) 
3144
{
3145
  if (!init_reloc_cookie (cookie, info, sec->owner))
3146
    goto error1;
3147
  if (!init_reloc_cookie_rels (cookie, info, sec->owner, sec))
3148
    goto error2;
3149
  return TRUE;
3150
3151
 error2:
3152
  fini_reloc_cookie (cookie, sec->owner);
3153
 error1:
3154
  return FALSE;
3155
}
3156
3157
/* Free the memory allocated by init_reloc_cookie_for_section,
3158
   if appropriate.  */
3159
3160
static void
3161
fini_reloc_cookie_for_section (struct coff_reloc_cookie *cookie,
3162
			       asection *sec)
3163
{
3164
  fini_reloc_cookie_rels (cookie, sec);
3165
  fini_reloc_cookie (cookie, sec->owner);
3166
}
3167
3168
static asection *
3169
_bfd_coff_gc_mark_hook (asection *sec,
3170
		       struct bfd_link_info *info ATTRIBUTE_UNUSED,
3171
		       struct internal_reloc *rel ATTRIBUTE_UNUSED,
3172
		       struct coff_link_hash_entry *h,
3173
		       struct internal_syment *sym)
3174
{
3175
  if (h != NULL)
3176
    {
3177
      switch (h->root.type)
3178
        {
3179
        case bfd_link_hash_defined:
3180
        case bfd_link_hash_defweak:
3181
          return h->root.u.def.section;
3182
3183
        case bfd_link_hash_common:
3184
          return h->root.u.c.p->section;
3185
3186
        default:
3187
          break;
3188
        }
3189
    }
3190
  else
3191
    return coff_section_from_bfd_index (sec->owner, sym->n_scnum);
3192
    /* FIXME: is the above corrent? elflink.c has:
3193
    return bfd_section_from_elf_index (sec->owner, sym->st_shndx); */
3194
3195
  return NULL;
3196
}
3197
3198
/* COOKIE->rel describes a relocation against section SEC, which is
3199
   a section we've decided to keep.  Return the section that contains
3200
   the relocation symbol, or NULL if no section contains it.  */
3201
static asection *
3202
_bfd_coff_gc_mark_rsec (struct bfd_link_info *info, asection *sec,
3203
		       coff_gc_mark_hook_fn gc_mark_hook,
3204
		       struct coff_reloc_cookie *cookie)
3205
{
3206
  struct coff_link_hash_entry *h;
3207
3208
  h = cookie->sym_hashes[cookie->rel->r_symndx];
3209
  if (h != NULL) {
3210
    while (h->root.type == bfd_link_hash_indirect
3211
           || h->root.type == bfd_link_hash_warning)
3212
      h = (struct coff_link_hash_entry *) h->root.u.i.link;
3213
3214
    return (*gc_mark_hook) (sec, info, cookie->rel, h, NULL);
3215
  }
3216
3217
  return (*gc_mark_hook) (sec, info, cookie->rel, NULL,
3218
			  &(cookie->symbols + obj_convert (sec->owner)[cookie->rel->r_symndx])->native->u.syment);
3219
}
3220
3221
static
3222
bfd_boolean
3223
_bfd_coff_gc_mark (struct bfd_link_info *info,
3224
		  asection *sec,
3225
		  coff_gc_mark_hook_fn gc_mark_hook);
3226
3227
/* COOKIE->rel describes a relocation against section SEC, which is
3228
   a section we've decided to keep.  Mark the section that contains
3229
   the relocation symbol.  */
3230
static bfd_boolean
3231
_bfd_coff_gc_mark_reloc (struct bfd_link_info *info,
3232
			asection *sec,
3233
			coff_gc_mark_hook_fn gc_mark_hook,
3234
			struct coff_reloc_cookie *cookie)
3235
{
3236
  asection *rsec;
3237
3238
  rsec = _bfd_coff_gc_mark_rsec (info, sec, gc_mark_hook, cookie);
3239
  if (rsec && !rsec->gc_mark)
3240
    {
3241
      if (bfd_get_flavour (rsec->owner) != bfd_target_coff_flavour)
3242
	rsec->gc_mark = 1;
3243
      else if (!_bfd_coff_gc_mark (info, rsec, gc_mark_hook))
3244
	return FALSE;
3245
    }
3246
  return TRUE;
3247
}
3248
3249
/* The mark phase of garbage collection.  For a given section, mark
3250
   it and any sections in this section's group, and all the sections
3251
   which define symbols to which it refers.  */
3252
3253
static
3254
bfd_boolean
3255
_bfd_coff_gc_mark (struct bfd_link_info *info,
3256
		  asection *sec,
3257
		  coff_gc_mark_hook_fn gc_mark_hook)
3258
{
3259
  bfd_boolean ret;
3260
3261
  sec->gc_mark = 1;
3262
3263
  /* FIXME: elflink.c has "Mark all the sections in the group."
3264
     functionality here - does COFF require something similar? */
3265
3266
  /* FIXME: elflink.c has some eh_frame handling here - does COFF
3267
     require something similar? */
3268
3269
  /* Look through the section relocs.  */
3270
  ret = TRUE;
3271
  if ((sec->flags & SEC_RELOC) != 0
3272
      && sec->reloc_count > 0)
3273
    {
3274
      struct coff_reloc_cookie cookie;
3275
3276
3277
      if (!init_reloc_cookie_for_section (&cookie, info, sec))
3278
        ret = FALSE;
3279
      else
3280
        {
3281
          for (; cookie.rel < cookie.relend; cookie.rel++) {
3282
            if (!_bfd_coff_gc_mark_reloc (info, sec, gc_mark_hook, &cookie))
3283
              {
3284
                ret = FALSE;
3285
                break;
3286
              }
3287
          }
3288
          fini_reloc_cookie_for_section (&cookie, sec);
3289
        }
3290
3291
    }
3292
3293
  /* FIXME: elflink.c has some eh_frame handling here - does COFF
3294
     require something similar? */
3295
3296
  return ret;
3297
}
3298
3299
/* Sweep symbols in swept sections.  Called via coff_link_hash_traverse.  */
3300
3301
struct coff_gc_sweep_symbol_info
3302
{
3303
  struct bfd_link_info *info;
3304
  void (*hide_symbol) (struct bfd_link_info *, struct coff_link_hash_entry *,
3305
		       bfd_boolean);
3306
};
3307
3308
static bfd_boolean
3309
coff_gc_sweep_symbol (struct coff_link_hash_entry *h, void *data)
3310
{
3311
3312
  if (h->root.type == bfd_link_hash_warning)
3313
    h = (struct coff_link_hash_entry *) h->root.u.i.link;
3314
3315
  if ((h->root.type == bfd_link_hash_defined
3316
       || h->root.type == bfd_link_hash_defweak)
3317
      && !h->root.u.def.section->gc_mark
3318
      && !(h->root.u.def.section->owner->flags & DYNAMIC))
3319
    {
3320
      struct coff_gc_sweep_symbol_info *inf ATTRIBUTE_UNUSED =
3321
          (struct coff_gc_sweep_symbol_info *) data;
3322
      /* FIXME: elflink.c hides the symbol here - how can we do this for COFF?
3323
      (*inf->hide_symbol) (inf->info, h, TRUE); */
3324
    }
3325
3326
  return TRUE;
3327
}
3328
3329
/* The sweep phase of garbage collection.  Remove all garbage sections.  */
3330
3331
typedef bfd_boolean (*gc_sweep_hook_fn)
3332
  (bfd *, struct bfd_link_info *, asection *, const struct internal_reloc *);
3333
3334
static bfd_boolean
3335
coff_gc_sweep (bfd *abfd ATTRIBUTE_UNUSED, struct bfd_link_info *info)
3336
{
3337
  bfd *sub;
3338
  struct coff_gc_sweep_symbol_info sweep_info;
3339
3340
  for (sub = info->input_bfds; sub != NULL; sub = sub->link_next)
3341
    {
3342
      asection *o;
3343
3344
      if (bfd_get_flavour (sub) != bfd_target_coff_flavour)
3345
	continue;
3346
3347
      for (o = sub->sections; o != NULL; o = o->next)
3348
	{
3349
3350
          /* FIXME: We must preserve the import table, but is this the correct
3351
             way to do it? */
3352
          if (strncmp(o->name, ".idata", 6) == 0)
3353
            o->gc_mark = 1;
3354
3355
          /* FIXME: elflink.c has some section group
3356
             functionality here - does COFF require something similar? */
3357
3358
          if ((o->flags & (SEC_DEBUGGING | SEC_LINKER_CREATED)) != 0
3359
		   || (o->flags & (SEC_ALLOC | SEC_LOAD | SEC_RELOC)) == 0)
3360
	    {
3361
	      /* Keep debug and special sections.  */
3362
	      o->gc_mark = 1;
3363
	    }
3364
3365
	  if (o->gc_mark)
3366
	    continue;
3367
3368
	  /* Skip sweeping sections already excluded.  */
3369
	  if (o->flags & SEC_EXCLUDE)
3370
	    continue;
3371
3372
	  /* Since this is early in the link process, it is simple
3373
	     to remove a section from the output.  */
3374
	  o->flags |= SEC_EXCLUDE;
3375
3376
	  if (info->print_gc_sections && o->size != 0)
3377
            _bfd_error_handler (_("Removing unused section '%s' in file '%B'"), sub, o->name);
3378
3379
          /* FIXME: Do we need something like this for COFF? */
3380
#if 0
3381
	  /* But we also have to update some of the relocation
3382
	     info we collected before.  */
3383
	  if (gc_sweep_hook
3384
	      && (o->flags & SEC_RELOC) != 0
3385
	      && o->reloc_count > 0
3386
	      && !bfd_is_abs_section (o->output_section))
3387
	    {
3388
	      struct internal_reloc *internal_relocs;
3389
	      bfd_boolean r;
3390
3391
	      internal_relocs
3392
		= _bfd_coff_link_read_relocs (o->owner, o, NULL, NULL,
3393
					     info->keep_memory);
3394
	      if (internal_relocs == NULL)
3395
		return FALSE;
3396
3397
	      r = (*gc_sweep_hook) (o->owner, info, o, internal_relocs);
3398
3399
	      if (coff_section_data (o)->relocs != internal_relocs)
3400
		free (internal_relocs);
3401
3402
	      if (!r)
3403
		return FALSE;
3404
	    }
3405
#endif
3406
	}
3407
    }
3408
3409
  /* Remove the symbols that were in the swept sections from the dynamic
3410
     symbol table.  GCFIXME: Anyone know how to get them out of the
3411
     static symbol table as well?  */
3412
3413
  sweep_info.info = info;
3414
  /* FIXME: Do we need this for COFF?
3415
  sweep_info.hide_symbol = bed->coff_backend_hide_symbol; */
3416
  coff_link_hash_traverse (coff_hash_table (info), coff_gc_sweep_symbol,
3417
			  &sweep_info);
3418
3419
  /* FIXME: Do we need this for COFF?
3420
  _bfd_coff_link_renumber_dynsyms (abfd, info, &section_sym_count); */
3421
3422
  return TRUE;
3423
}
3424
3425
/* Keep all sections containing symbols undefined on the command-line,
3426
   and the section containing the entry symbol.  */
3427
3428
static void
3429
_bfd_coff_gc_keep (struct bfd_link_info *info)
3430
{
3431
  struct bfd_sym_chain *sym;
3432
3433
  for (sym = info->gc_sym_list; sym != NULL; sym = sym->next)
3434
    {
3435
      struct coff_link_hash_entry *h;
3436
3437
      h = coff_link_hash_lookup (coff_hash_table (info), sym->name,
3438
				FALSE, FALSE, FALSE);
3439
3440
      if (h != NULL
3441
      /* FIXME: elflink.c has more conditions - what about COFF?
3442
	  && (h->root.type == bfd_link_hash_defined
3443
	      || h->root.type == bfd_link_hash_defweak)
3444
	  && !bfd_is_abs_section (h->root.u.def.section)*/)
3445
	h->root.u.def.section->flags |= SEC_KEEP;
3446
    }
3447
}
3448
3449
/* Do mark and sweep of unused sections.  */
3450
3451
bfd_boolean
3452
bfd_coff_gc_sections (bfd *abfd ATTRIBUTE_UNUSED, struct bfd_link_info *info)
3453
{
3454
3455
  bfd *sub;
3456
3457
  /* FIXME: Should we implement this? */
3458
#if 0
3459
  const bfd_coff_backend_data *bed = coff_backend_info (abfd);
3460
3461
  if (!bed->can_gc_sections
3462
      || !is_coff_hash_table (info->hash))
3463
    {
3464
      (*_bfd_error_handler)(_("Warning: gc-sections option ignored"));
3465
      return TRUE;
3466
    }
3467
#endif
3468
3469
  _bfd_coff_gc_keep (info);
3470
3471
  /* FIXME: elflink.c has some eh_frame handling here - does COFF
3472
     require something similar? */
3473
3474
  /* FIXME: elflink.c does two things here:
3475
     - Apply transitive closure to the vtable entry usage info.
3476
     - Kill the vtable relocations that were not used.
3477
     does COFF require something similar? */
3478
3479
  /* FIXME: elflink.c does a traverse with bfd_elf_gc_mark_dynamic_ref_symbol
3480
     here - does COFF require something similar? */
3481
3482
  /* Grovel through relocs to find out who stays ...  */
3483
  for (sub = info->input_bfds; sub != NULL; sub = sub->link_next)
3484
    {
3485
      asection *o;
3486
3487
      if (bfd_get_flavour (sub) != bfd_target_coff_flavour)
3488
        continue;
3489
3490
      for (o = sub->sections; o != NULL; o = o->next) {
3491
        /* FIXME: Is this the proper way to check for global constructors? */
3492
        if (((o->flags & (SEC_EXCLUDE | SEC_KEEP)) == SEC_KEEP || strncmp(o->name, ".ctors", 6) == 0) && !o->gc_mark) {
3493
          if (!_bfd_coff_gc_mark (info, o, _bfd_coff_gc_mark_hook)) {
3494
            return FALSE;
3495
          }
3496
        }
3497
      }
3498
    }
3499
3500
  /* FIXME: elflink.c has an hook for gc_mark_extra_sections
3501
     here - does COFF require something similar? */
3502
3503
  /* ... and mark SEC_EXCLUDE for those that go.  */
3504
  return coff_gc_sweep (abfd, info);
3505
}
3506
(-)binutils-2.20/bfd/libcoff.h (+14 lines)
Lines 284-289 Link Here
284
  struct stab_info stab_info;
284
  struct stab_info stab_info;
285
};
285
};
286
286
287
struct coff_reloc_cookie
288
{
289
  struct internal_reloc *rels, *rel, *relend;
290
  struct coff_symbol_struct *symbols;	/* Symtab for input bfd.  */
291
  bfd *abfd;
292
  struct coff_link_hash_entry **sym_hashes;
293
};
294
287
/* Look up an entry in a COFF linker hash table.  */
295
/* Look up an entry in a COFF linker hash table.  */
288
296
289
#define coff_link_hash_lookup(table, string, create, copy, follow)	\
297
#define coff_link_hash_lookup(table, string, create, copy, follow)	\
Lines 560-565 Link Here
560
extern bfd_boolean _bfd_coff_generic_relocate_section
568
extern bfd_boolean _bfd_coff_generic_relocate_section
561
  (bfd *, struct bfd_link_info *, bfd *, asection *, bfd_byte *,
569
  (bfd *, struct bfd_link_info *, bfd *, asection *, bfd_byte *,
562
   struct internal_reloc *, struct internal_syment *, asection **);
570
   struct internal_reloc *, struct internal_syment *, asection **);
571
extern bfd_boolean bfd_coff_gc_sections
572
  (bfd *abfd, struct bfd_link_info *info);
563
extern struct bfd_hash_entry *_bfd_coff_debug_merge_hash_newfunc
573
extern struct bfd_hash_entry *_bfd_coff_debug_merge_hash_newfunc
564
  (struct bfd_hash_entry *, struct bfd_hash_table *, const char *);
574
  (struct bfd_hash_entry *, struct bfd_hash_table *, const char *);
565
extern bfd_boolean _bfd_coff_write_global_sym
575
extern bfd_boolean _bfd_coff_write_global_sym
Lines 676-681 Link Here
676
  COFF_SYMBOL_PE_SECTION
686
  COFF_SYMBOL_PE_SECTION
677
};
687
};
678
688
689
typedef asection * (*coff_gc_mark_hook_fn)
690
  (asection *, struct bfd_link_info *, struct internal_reloc *,
691
   struct coff_link_hash_entry *, struct internal_syment *);
692
679
typedef struct
693
typedef struct
680
{
694
{
681
  void (*_bfd_coff_swap_aux_in)
695
  void (*_bfd_coff_swap_aux_in)

Return to bug 11539