00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027 #include "bfd.h"
00028 #include "sysdep.h"
00029 #include "bfdlink.h"
00030 #include "safe-ctype.h"
00031
00032 #include "ld.h"
00033 #include "ldexp.h"
00034 #include "ldlang.h"
00035 #include "ldmisc.h"
00036 #include <ldgram.h>
00037 #include "ldmain.h"
00038 #include "ldctor.h"
00039
00040
00041
00042 lang_statement_list_type constructor_list;
00043
00044
00045
00046
00047 bfd_boolean constructors_sorted;
00048
00049
00050 struct set_info *sets;
00051
00052
00053
00054
00055
00056
00057
00058
00059 void
00060 ldctor_add_set_entry (struct bfd_link_hash_entry *h,
00061 bfd_reloc_code_real_type reloc,
00062 const char *name,
00063 asection *section,
00064 bfd_vma value)
00065 {
00066 struct set_info *p;
00067 struct set_element *e;
00068 struct set_element **epp;
00069
00070 for (p = sets; p != NULL; p = p->next)
00071 if (p->h == h)
00072 break;
00073
00074 if (p == NULL)
00075 {
00076 p = xmalloc (sizeof (struct set_info));
00077 p->next = sets;
00078 sets = p;
00079 p->h = h;
00080 p->reloc = reloc;
00081 p->count = 0;
00082 p->elements = NULL;
00083 }
00084 else
00085 {
00086 if (p->reloc != reloc)
00087 {
00088 einfo (_("%P%X: Different relocs used in set %s\n"),
00089 h->root.string);
00090 return;
00091 }
00092
00093
00094
00095
00096
00097
00098
00099
00100 if (p->elements != NULL
00101 && section->owner != NULL
00102 && p->elements->section->owner != NULL
00103 && strcmp (bfd_get_target (section->owner),
00104 bfd_get_target (p->elements->section->owner)) != 0)
00105 {
00106 einfo (_("%P%X: Different object file formats composing set %s\n"),
00107 h->root.string);
00108 return;
00109 }
00110 }
00111
00112 e = xmalloc (sizeof (struct set_element));
00113 e->next = NULL;
00114 e->name = name;
00115 e->section = section;
00116 e->value = value;
00117
00118 for (epp = &p->elements; *epp != NULL; epp = &(*epp)->next)
00119 ;
00120 *epp = e;
00121
00122 ++p->count;
00123 }
00124
00125
00126
00127
00128 static int
00129 ctor_prio (const char *name)
00130 {
00131
00132
00133
00134
00135 while (*name == '_')
00136 ++name;
00137
00138 if (strncmp (name, "GLOBAL_", sizeof "GLOBAL_" - 1) != 0)
00139 return -1;
00140
00141 name += sizeof "GLOBAL_" - 1;
00142
00143 if (name[0] != name[2])
00144 return -1;
00145 if (name[1] != 'I' && name[1] != 'D')
00146 return -1;
00147 if (! ISDIGIT (name[3]))
00148 return -1;
00149
00150 return atoi (name + 3);
00151 }
00152
00153
00154
00155
00156 static int
00157 ctor_cmp (const void *p1, const void *p2)
00158 {
00159 const struct set_element * const *pe1 = p1;
00160 const struct set_element * const *pe2 = p2;
00161 const char *n1;
00162 const char *n2;
00163 int prio1;
00164 int prio2;
00165
00166 n1 = (*pe1)->name;
00167 if (n1 == NULL)
00168 n1 = "";
00169 n2 = (*pe2)->name;
00170 if (n2 == NULL)
00171 n2 = "";
00172
00173
00174
00175
00176
00177 prio1 = ctor_prio (n1);
00178 prio2 = ctor_prio (n2);
00179
00180
00181 if (prio1 < prio2)
00182 return 1;
00183 else if (prio1 > prio2)
00184 return -1;
00185
00186
00187
00188 if (pe1 < pe2)
00189 return -1;
00190 else if (pe1 > pe2)
00191 return 1;
00192 else
00193 return 0;
00194 }
00195
00196
00197
00198
00199
00200
00201 void
00202 ldctor_build_sets (void)
00203 {
00204 static bfd_boolean called;
00205 lang_statement_list_type *old;
00206 bfd_boolean header_printed;
00207 struct set_info *p;
00208
00209
00210
00211 if (called)
00212 return;
00213 called = TRUE;
00214
00215 if (constructors_sorted)
00216 {
00217 for (p = sets; p != NULL; p = p->next)
00218 {
00219 int c, i;
00220 struct set_element *e;
00221 struct set_element **array;
00222
00223 if (p->elements == NULL)
00224 continue;
00225
00226 c = 0;
00227 for (e = p->elements; e != NULL; e = e->next)
00228 ++c;
00229
00230 array = xmalloc (c * sizeof *array);
00231
00232 i = 0;
00233 for (e = p->elements; e != NULL; e = e->next)
00234 {
00235 array[i] = e;
00236 ++i;
00237 }
00238
00239 qsort (array, c, sizeof *array, ctor_cmp);
00240
00241 e = array[0];
00242 p->elements = e;
00243 for (i = 0; i < c - 1; i++)
00244 array[i]->next = array[i + 1];
00245 array[i]->next = NULL;
00246
00247 free (array);
00248 }
00249 }
00250
00251 old = stat_ptr;
00252 stat_ptr = &constructor_list;
00253
00254 lang_list_init (stat_ptr);
00255
00256 header_printed = FALSE;
00257 for (p = sets; p != NULL; p = p->next)
00258 {
00259 struct set_element *e;
00260 reloc_howto_type *howto;
00261 int reloc_size, size;
00262
00263
00264
00265
00266 if (p->h->type == bfd_link_hash_defined
00267 || p->h->type == bfd_link_hash_defweak)
00268 continue;
00269
00270
00271
00272
00273
00274
00275
00276
00277
00278
00279
00280 howto = bfd_reloc_type_lookup (output_bfd, p->reloc);
00281 if (howto == NULL)
00282 {
00283 if (link_info.relocatable)
00284 {
00285 einfo (_("%P%X: %s does not support reloc %s for set %s\n"),
00286 bfd_get_target (output_bfd),
00287 bfd_get_reloc_code_name (p->reloc),
00288 p->h->root.string);
00289 continue;
00290 }
00291
00292
00293
00294 if (p->elements->section->owner != NULL)
00295 howto = bfd_reloc_type_lookup (p->elements->section->owner,
00296 p->reloc);
00297 if (howto == NULL)
00298 {
00299 einfo (_("%P%X: %s does not support reloc %s for set %s\n"),
00300 bfd_get_target (p->elements->section->owner),
00301 bfd_get_reloc_code_name (p->reloc),
00302 p->h->root.string);
00303 continue;
00304 }
00305 }
00306
00307 reloc_size = bfd_get_reloc_size (howto);
00308 switch (reloc_size)
00309 {
00310 case 1: size = BYTE; break;
00311 case 2: size = SHORT; break;
00312 case 4: size = LONG; break;
00313 case 8:
00314 if (howto->complain_on_overflow == complain_overflow_signed)
00315 size = SQUAD;
00316 else
00317 size = QUAD;
00318 break;
00319 default:
00320 einfo (_("%P%X: Unsupported size %d for set %s\n"),
00321 bfd_get_reloc_size (howto), p->h->root.string);
00322 size = LONG;
00323 break;
00324 }
00325
00326 lang_add_assignment (exp_assop ('=', ".",
00327 exp_unop (ALIGN_K,
00328 exp_intop (reloc_size))));
00329 lang_add_assignment (exp_assop ('=', p->h->root.string,
00330 exp_nameop (NAME, ".")));
00331 lang_add_data (size, exp_intop (p->count));
00332
00333 for (e = p->elements; e != NULL; e = e->next)
00334 {
00335 if (config.map_file != NULL)
00336 {
00337 int len;
00338
00339 if (! header_printed)
00340 {
00341 minfo (_("\nSet Symbol\n\n"));
00342 header_printed = TRUE;
00343 }
00344
00345 minfo ("%s", p->h->root.string);
00346 len = strlen (p->h->root.string);
00347
00348 if (len >= 19)
00349 {
00350 print_nl ();
00351 len = 0;
00352 }
00353 while (len < 20)
00354 {
00355 print_space ();
00356 ++len;
00357 }
00358
00359 if (e->name != NULL)
00360 minfo ("%T\n", e->name);
00361 else
00362 minfo ("%G\n", e->section->owner, e->section, e->value);
00363 }
00364
00365
00366 if (! bfd_is_abs_section (e->section))
00367 e->section->flags |= SEC_KEEP;
00368
00369 if (link_info.relocatable)
00370 lang_add_reloc (p->reloc, howto, e->section, e->name,
00371 exp_intop (e->value));
00372 else
00373 lang_add_data (size, exp_relop (e->section, e->value));
00374 }
00375
00376 lang_add_data (size, exp_intop (0));
00377 }
00378
00379 stat_ptr = old;
00380 }