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 #include "bfd.h"
00027 #include "sysdep.h"
00028 #include "bfdlink.h"
00029 #include "libiberty.h"
00030 #include "safe-ctype.h"
00031
00032 #include "ld.h"
00033 #include "ldexp.h"
00034 #include "ldlang.h"
00035 #include "ldwrite.h"
00036 #include "ldmisc.h"
00037 #include <ldgram.h>
00038 #include "ldmain.h"
00039
00040
00041
00042 static void
00043 build_link_order (lang_statement_union_type *statement)
00044 {
00045 switch (statement->header.type)
00046 {
00047 case lang_data_statement_enum:
00048 {
00049 asection *output_section;
00050 struct bfd_link_order *link_order;
00051 bfd_vma value;
00052 bfd_boolean big_endian = FALSE;
00053
00054 output_section = statement->data_statement.output_section;
00055 ASSERT (output_section->owner == output_bfd);
00056
00057 link_order = bfd_new_link_order (output_bfd, output_section);
00058 if (link_order == NULL)
00059 einfo (_("%P%F: bfd_new_link_order failed\n"));
00060
00061 link_order->type = bfd_data_link_order;
00062 link_order->offset = statement->data_statement.output_vma;
00063 link_order->u.data.contents = xmalloc (QUAD_SIZE);
00064
00065 value = statement->data_statement.value;
00066
00067
00068
00069
00070
00071
00072 if (bfd_big_endian (output_bfd))
00073 big_endian = TRUE;
00074 else if (bfd_little_endian (output_bfd))
00075 big_endian = FALSE;
00076 else
00077 {
00078 bfd_boolean swap;
00079
00080 swap = FALSE;
00081 if (command_line.endian == ENDIAN_BIG)
00082 big_endian = TRUE;
00083 else if (command_line.endian == ENDIAN_LITTLE)
00084 {
00085 big_endian = FALSE;
00086 swap = TRUE;
00087 }
00088 else if (command_line.endian == ENDIAN_UNSET)
00089 {
00090 big_endian = TRUE;
00091 {
00092 LANG_FOR_EACH_INPUT_STATEMENT (s)
00093 {
00094 if (s->the_bfd != NULL)
00095 {
00096 if (bfd_little_endian (s->the_bfd))
00097 {
00098 big_endian = FALSE;
00099 swap = TRUE;
00100 }
00101 break;
00102 }
00103 }
00104 }
00105 }
00106
00107 if (swap)
00108 {
00109 bfd_byte buffer[8];
00110
00111 switch (statement->data_statement.type)
00112 {
00113 case QUAD:
00114 case SQUAD:
00115 if (sizeof (bfd_vma) >= QUAD_SIZE)
00116 {
00117 bfd_putl64 (value, buffer);
00118 value = bfd_getb64 (buffer);
00119 break;
00120 }
00121
00122 case LONG:
00123 bfd_putl32 (value, buffer);
00124 value = bfd_getb32 (buffer);
00125 break;
00126 case SHORT:
00127 bfd_putl16 (value, buffer);
00128 value = bfd_getb16 (buffer);
00129 break;
00130 case BYTE:
00131 break;
00132 default:
00133 abort ();
00134 }
00135 }
00136 }
00137
00138 ASSERT (output_section->owner == output_bfd);
00139 switch (statement->data_statement.type)
00140 {
00141 case QUAD:
00142 case SQUAD:
00143 if (sizeof (bfd_vma) >= QUAD_SIZE)
00144 bfd_put_64 (output_bfd, value, link_order->u.data.contents);
00145 else
00146 {
00147 bfd_vma high;
00148
00149 if (statement->data_statement.type == QUAD)
00150 high = 0;
00151 else if ((value & 0x80000000) == 0)
00152 high = 0;
00153 else
00154 high = (bfd_vma) -1;
00155 bfd_put_32 (output_bfd, high,
00156 (link_order->u.data.contents
00157 + (big_endian ? 0 : 4)));
00158 bfd_put_32 (output_bfd, value,
00159 (link_order->u.data.contents
00160 + (big_endian ? 4 : 0)));
00161 }
00162 link_order->size = QUAD_SIZE;
00163 break;
00164 case LONG:
00165 bfd_put_32 (output_bfd, value, link_order->u.data.contents);
00166 link_order->size = LONG_SIZE;
00167 break;
00168 case SHORT:
00169 bfd_put_16 (output_bfd, value, link_order->u.data.contents);
00170 link_order->size = SHORT_SIZE;
00171 break;
00172 case BYTE:
00173 bfd_put_8 (output_bfd, value, link_order->u.data.contents);
00174 link_order->size = BYTE_SIZE;
00175 break;
00176 default:
00177 abort ();
00178 }
00179 }
00180 break;
00181
00182 case lang_reloc_statement_enum:
00183 {
00184 lang_reloc_statement_type *rs;
00185 asection *output_section;
00186 struct bfd_link_order *link_order;
00187
00188 rs = &statement->reloc_statement;
00189
00190 output_section = rs->output_section;
00191 ASSERT (output_section->owner == output_bfd);
00192
00193 link_order = bfd_new_link_order (output_bfd, output_section);
00194 if (link_order == NULL)
00195 einfo (_("%P%F: bfd_new_link_order failed\n"));
00196
00197 link_order->offset = rs->output_vma;
00198 link_order->size = bfd_get_reloc_size (rs->howto);
00199
00200 link_order->u.reloc.p = xmalloc (sizeof (struct bfd_link_order_reloc));
00201
00202 link_order->u.reloc.p->reloc = rs->reloc;
00203 link_order->u.reloc.p->addend = rs->addend_value;
00204
00205 if (rs->name == NULL)
00206 {
00207 link_order->type = bfd_section_reloc_link_order;
00208 if (rs->section->owner == output_bfd)
00209 link_order->u.reloc.p->u.section = rs->section;
00210 else
00211 {
00212 link_order->u.reloc.p->u.section = rs->section->output_section;
00213 link_order->u.reloc.p->addend += rs->section->output_offset;
00214 }
00215 }
00216 else
00217 {
00218 link_order->type = bfd_symbol_reloc_link_order;
00219 link_order->u.reloc.p->u.name = rs->name;
00220 }
00221 }
00222 break;
00223
00224 case lang_input_section_enum:
00225
00226
00227 if (!statement->input_section.ifile->just_syms_flag
00228 && (statement->input_section.section->flags & SEC_EXCLUDE) == 0)
00229 {
00230 asection *i = statement->input_section.section;
00231 asection *output_section = i->output_section;
00232
00233 ASSERT (output_section->owner == output_bfd);
00234
00235 if ((output_section->flags & SEC_HAS_CONTENTS) != 0
00236 || ((output_section->flags & SEC_LOAD) != 0
00237 && (output_section->flags & SEC_THREAD_LOCAL)))
00238 {
00239 struct bfd_link_order *link_order;
00240
00241 link_order = bfd_new_link_order (output_bfd, output_section);
00242
00243 if (i->flags & SEC_NEVER_LOAD)
00244 {
00245
00246
00247
00248 link_order->type = bfd_data_link_order;
00249 link_order->u.data.contents = (unsigned char *) "";
00250 link_order->u.data.size = 1;
00251 }
00252 else
00253 {
00254 link_order->type = bfd_indirect_link_order;
00255 link_order->u.indirect.section = i;
00256 ASSERT (i->output_section == output_section);
00257 }
00258 link_order->size = i->size;
00259 link_order->offset = i->output_offset;
00260 }
00261 }
00262 break;
00263
00264 case lang_padding_statement_enum:
00265
00266 {
00267 asection *output_section;
00268 struct bfd_link_order *link_order;
00269
00270 output_section = statement->padding_statement.output_section;
00271 ASSERT (statement->padding_statement.output_section->owner
00272 == output_bfd);
00273 if ((output_section->flags & SEC_HAS_CONTENTS) != 0)
00274 {
00275 link_order = bfd_new_link_order (output_bfd, output_section);
00276 link_order->type = bfd_data_link_order;
00277 link_order->size = statement->padding_statement.size;
00278 link_order->offset = statement->padding_statement.output_offset;
00279 link_order->u.data.contents = statement->padding_statement.fill->data;
00280 link_order->u.data.size = statement->padding_statement.fill->size;
00281 }
00282 }
00283 break;
00284
00285 default:
00286
00287 break;
00288 }
00289 }
00290
00291
00292
00293
00294 static bfd_boolean
00295 unsplittable_name (const char *name)
00296 {
00297 if (strncmp (name, ".stab", 5) == 0)
00298 {
00299
00300
00301 unsigned len = strlen (name);
00302 if (strcmp (&name[len-3], "str") == 0)
00303 return TRUE;
00304 }
00305 else if (strcmp (name, "$GDB_STRINGS$") == 0)
00306 return TRUE;
00307 return FALSE;
00308 }
00309
00310
00311
00312
00313
00314 #define TESTIT 1
00315 static asection *
00316 clone_section (bfd *abfd, asection *s, const char *name, int *count)
00317 {
00318 char *tname;
00319 char *sname;
00320 unsigned int len;
00321 asection *n;
00322 struct bfd_link_hash_entry *h;
00323
00324
00325
00326 len = strlen (name);
00327 tname = xmalloc (len + 1);
00328 memcpy (tname, name, len + 1);
00329
00330 while (len && ISDIGIT (tname[len-1]))
00331 len--;
00332 if (len > 1 && tname[len-1] == '.')
00333
00334 tname[len-1] = 0;
00335
00336
00337
00338 if (bfd_family_coff (abfd) && strlen (tname) > 5)
00339 {
00340
00341
00342 if (strncmp (name, ".stab", 5) == 0
00343 || strcmp (name, "$GDB_SYMBOLS$") == 0)
00344 {
00345 einfo (_ ("%F%P: cannot create split section name for %s\n"), name);
00346
00347 return NULL;
00348 }
00349 tname[5] = 0;
00350 }
00351
00352 if ((sname = bfd_get_unique_section_name (abfd, tname, count)) == NULL
00353 || (n = bfd_make_section_anyway (abfd, sname)) == NULL
00354 || (h = bfd_link_hash_lookup (link_info.hash,
00355 sname, TRUE, TRUE, FALSE)) == NULL)
00356 {
00357 einfo (_("%F%P: clone section failed: %E\n"));
00358
00359 return NULL;
00360 }
00361 free (tname);
00362
00363
00364 h->type = bfd_link_hash_defined;
00365 h->u.def.value = 0;
00366 h->u.def.section = n;
00367
00368 n->flags = s->flags;
00369 n->vma = s->vma;
00370 n->user_set_vma = s->user_set_vma;
00371 n->lma = s->lma;
00372 n->size = 0;
00373 n->output_offset = s->output_offset;
00374 n->output_section = n;
00375 n->orelocation = 0;
00376 n->reloc_count = 0;
00377 n->alignment_power = s->alignment_power;
00378 return n;
00379 }
00380
00381 #if TESTING
00382 static void
00383 ds (asection *s)
00384 {
00385 struct bfd_link_order *l = s->link_order_head;
00386 printf ("vma %x size %x\n", s->vma, s->size);
00387 while (l)
00388 {
00389 if (l->type == bfd_indirect_link_order)
00390 {
00391 printf ("%8x %s\n", l->offset, l->u.indirect.section->owner->filename);
00392 }
00393 else
00394 {
00395 printf (_("%8x something else\n"), l->offset);
00396 }
00397 l = l->next;
00398 }
00399 printf ("\n");
00400 }
00401
00402 dump (char *s, asection *a1, asection *a2)
00403 {
00404 printf ("%s\n", s);
00405 ds (a1);
00406 ds (a2);
00407 }
00408
00409 static void
00410 sanity_check (bfd *abfd)
00411 {
00412 asection *s;
00413 for (s = abfd->sections; s; s = s->next)
00414 {
00415 struct bfd_link_order *p;
00416 bfd_vma prev = 0;
00417 for (p = s->link_order_head; p; p = p->next)
00418 {
00419 if (p->offset > 100000)
00420 abort ();
00421 if (p->offset < prev)
00422 abort ();
00423 prev = p->offset;
00424 }
00425 }
00426 }
00427 #else
00428 #define sanity_check(a)
00429 #define dump(a, b, c)
00430 #endif
00431
00432 static void
00433 split_sections (bfd *abfd, struct bfd_link_info *info)
00434 {
00435 asection *original_sec;
00436 int nsecs = abfd->section_count;
00437 sanity_check (abfd);
00438
00439 for (original_sec = abfd->sections;
00440 original_sec && nsecs;
00441 original_sec = original_sec->next, nsecs--)
00442 {
00443 int count = 0;
00444 unsigned int lines = 0;
00445 unsigned int relocs = 0;
00446 bfd_size_type sec_size = 0;
00447 struct bfd_link_order *l;
00448 struct bfd_link_order *p;
00449 bfd_vma vma = original_sec->vma;
00450 asection *cursor = original_sec;
00451
00452
00453
00454 for (l = NULL, p = cursor->link_order_head; p != NULL; p = l->next)
00455 {
00456 unsigned int thislines = 0;
00457 unsigned int thisrelocs = 0;
00458 bfd_size_type thissize = 0;
00459 if (p->type == bfd_indirect_link_order)
00460 {
00461 asection *sec;
00462
00463 sec = p->u.indirect.section;
00464
00465 if (info->strip == strip_none
00466 || info->strip == strip_some)
00467 thislines = sec->lineno_count;
00468
00469 if (info->relocatable)
00470 thisrelocs = sec->reloc_count;
00471
00472 thissize = sec->size;
00473
00474 }
00475 else if (info->relocatable
00476 && (p->type == bfd_section_reloc_link_order
00477 || p->type == bfd_symbol_reloc_link_order))
00478 thisrelocs++;
00479
00480 if (l != NULL
00481 && (thisrelocs + relocs >= config.split_by_reloc
00482 || thislines + lines >= config.split_by_reloc
00483 || (thissize + sec_size >= config.split_by_file))
00484 && !unsplittable_name (cursor->name))
00485 {
00486
00487
00488 bfd_vma shift_offset;
00489 asection *n;
00490
00491 n = clone_section (abfd, cursor, original_sec->name, &count);
00492
00493
00494
00495 n->link_order_head = p;
00496 n->link_order_tail = cursor->link_order_tail;
00497 cursor->link_order_tail = l;
00498 l->next = NULL;
00499 l = p;
00500
00501
00502
00503
00504 dump ("before snip", cursor, n);
00505
00506 shift_offset = p->offset;
00507 n->size = cursor->size - shift_offset;
00508 cursor->size = shift_offset;
00509
00510 vma += shift_offset;
00511 n->lma = n->vma = vma;
00512
00513
00514
00515 do
00516 {
00517 p->offset -= shift_offset;
00518 if (p->type == bfd_indirect_link_order)
00519 {
00520 p->u.indirect.section->output_section = n;
00521 p->u.indirect.section->output_offset = p->offset;
00522 }
00523 p = p->next;
00524 }
00525 while (p);
00526
00527 dump ("after snip", cursor, n);
00528 cursor = n;
00529 relocs = thisrelocs;
00530 lines = thislines;
00531 sec_size = thissize;
00532 }
00533 else
00534 {
00535 l = p;
00536 relocs += thisrelocs;
00537 lines += thislines;
00538 sec_size += thissize;
00539 }
00540 }
00541 }
00542 sanity_check (abfd);
00543 }
00544
00545
00546
00547 void
00548 ldwrite (void)
00549 {
00550
00551
00552 bfd_set_error (bfd_error_no_error);
00553 lang_for_each_statement (build_link_order);
00554
00555 if (config.split_by_reloc != (unsigned) -1
00556 || config.split_by_file != (bfd_size_type) -1)
00557 split_sections (output_bfd, &link_info);
00558 if (!bfd_final_link (output_bfd, &link_info))
00559 {
00560
00561
00562
00563
00564 if (bfd_get_error () != bfd_error_no_error)
00565 einfo (_("%F%P: final link failed: %E\n"));
00566 else
00567 xexit (1);
00568 }
00569 }