1 /* ldwrite.c -- write out the linked file 2 Copyright (C) 1991, 92, 93, 94, 95, 96, 97, 1998 3 Free Software Foundation, Inc. 4 Written by Steve Chamberlain sac@cygnus.com 5 6 This file is part of GLD, the Gnu Linker. 7 8 This program is free software; you can redistribute it and/or modify 9 it under the terms of the GNU General Public License as published by 10 the Free Software Foundation; either version 2 of the License, or 11 (at your option) any later version. 12 13 This program is distributed in the hope that it will be useful, 14 but WITHOUT ANY WARRANTY; without even the implied warranty of 15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 GNU General Public License for more details. 17 18 You should have received a copy of the GNU General Public License 19 along with this program; if not, write to the Free Software 20 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ 21 22 #include "bfd.h" 23 #include "sysdep.h" 24 #include "bfdlink.h" 25 #include "libiberty.h" 26 27 #include "ld.h" 28 #include "ldexp.h" 29 #include "ldlang.h" 30 #include "ldwrite.h" 31 #include "ldmisc.h" 32 #include "ldgram.h" 33 #include "ldmain.h" 34 35 static void build_link_order PARAMS ((lang_statement_union_type *)); 36 static asection *clone_section PARAMS ((bfd *, asection *, int *)); 37 static void split_sections PARAMS ((bfd *, struct bfd_link_info *)); 38 39 /* Build link_order structures for the BFD linker. */ 40 41 static void 42 build_link_order (statement) 43 lang_statement_union_type *statement; 44 { 45 switch (statement->header.type) 46 { 47 case lang_data_statement_enum: 48 { 49 asection *output_section; 50 struct bfd_link_order *link_order; 51 bfd_vma value; 52 boolean big_endian = false; 53 54 output_section = statement->data_statement.output_section; 55 ASSERT (output_section->owner == output_bfd); 56 57 link_order = bfd_new_link_order (output_bfd, output_section); 58 if (link_order == NULL) 59 einfo (_("%P%F: bfd_new_link_order failed\n")); 60 61 link_order->type = bfd_data_link_order; 62 link_order->offset = statement->data_statement.output_vma; 63 link_order->u.data.contents = (bfd_byte *) xmalloc (QUAD_SIZE); 64 65 value = statement->data_statement.value; 66 67 /* If the endianness of the output BFD is not known, then we 68 base the endianness of the data on the first input file. 69 By convention, the bfd_put routines for an unknown 70 endianness are big endian, so we must swap here if the 71 input file is little endian. */ 72 if (bfd_big_endian (output_bfd)) 73 big_endian = true; 74 else if (bfd_little_endian (output_bfd)) 75 big_endian = false; 76 else 77 { 78 boolean swap; 79 80 swap = false; 81 if (command_line.endian == ENDIAN_BIG) 82 big_endian = true; 83 else if (command_line.endian == ENDIAN_LITTLE) 84 { 85 big_endian = false; 86 swap = true; 87 } 88 else if (command_line.endian == ENDIAN_UNSET) 89 { 90 big_endian = true; 91 { 92 LANG_FOR_EACH_INPUT_STATEMENT (s) 93 { 94 if (s->the_bfd != NULL) 95 { 96 if (bfd_little_endian (s->the_bfd)) 97 { 98 big_endian = false; 99 swap = true; 100 } 101 break; 102 } 103 } 104 } 105 } 106 107 if (swap) 108 { 109 bfd_byte buffer[8]; 110 111 switch (statement->data_statement.type) 112 { 113 case QUAD: 114 case SQUAD: 115 if (sizeof (bfd_vma) >= QUAD_SIZE) 116 { 117 bfd_putl64 (value, buffer); 118 value = bfd_getb64 (buffer); 119 break; 120 } 121 /* Fall through. */ 122 case LONG: 123 bfd_putl32 (value, buffer); 124 value = bfd_getb32 (buffer); 125 break; 126 case SHORT: 127 bfd_putl16 (value, buffer); 128 value = bfd_getb16 (buffer); 129 break; 130 case BYTE: 131 break; 132 default: 133 abort (); 134 } 135 } 136 } 137 138 ASSERT (output_section->owner == output_bfd); 139 switch (statement->data_statement.type) 140 { 141 case QUAD: 142 case SQUAD: 143 if (sizeof (bfd_vma) >= QUAD_SIZE) 144 bfd_put_64 (output_bfd, value, link_order->u.data.contents); 145 else 146 { 147 bfd_vma high; 148 149 if (statement->data_statement.type == QUAD) 150 high = 0; 151 else if ((value & 0x80000000) == 0) 152 high = 0; 153 else 154 high = (bfd_vma) -1; 155 bfd_put_32 (output_bfd, high, 156 (link_order->u.data.contents 157 + (big_endian ? 0 : 4))); 158 bfd_put_32 (output_bfd, value, 159 (link_order->u.data.contents 160 + (big_endian ? 4 : 0))); 161 } 162 link_order->size = QUAD_SIZE; 163 break; 164 case LONG: 165 bfd_put_32 (output_bfd, value, link_order->u.data.contents); 166 link_order->size = LONG_SIZE; 167 break; 168 case SHORT: 169 bfd_put_16 (output_bfd, value, link_order->u.data.contents); 170 link_order->size = SHORT_SIZE; 171 break; 172 case BYTE: 173 bfd_put_8 (output_bfd, value, link_order->u.data.contents); 174 link_order->size = BYTE_SIZE; 175 break; 176 default: 177 abort (); 178 } 179 } 180 break; 181 182 case lang_reloc_statement_enum: 183 { 184 lang_reloc_statement_type *rs; 185 asection *output_section; 186 struct bfd_link_order *link_order; 187 188 rs = &statement->reloc_statement; 189 190 output_section = rs->output_section; 191 ASSERT (output_section->owner == output_bfd); 192 193 link_order = bfd_new_link_order (output_bfd, output_section); 194 if (link_order == NULL) 195 einfo (_("%P%F: bfd_new_link_order failed\n")); 196 197 link_order->offset = rs->output_vma; 198 link_order->size = bfd_get_reloc_size (rs->howto); 199 200 link_order->u.reloc.p = 201 ((struct bfd_link_order_reloc *) 202 xmalloc (sizeof (struct bfd_link_order_reloc))); 203 204 link_order->u.reloc.p->reloc = rs->reloc; 205 link_order->u.reloc.p->addend = rs->addend_value; 206 207 if (rs->name == NULL) 208 { 209 link_order->type = bfd_section_reloc_link_order; 210 if (rs->section->owner == output_bfd) 211 link_order->u.reloc.p->u.section = rs->section; 212 else 213 { 214 link_order->u.reloc.p->u.section = rs->section->output_section; 215 link_order->u.reloc.p->addend += rs->section->output_offset; 216 } 217 } 218 else 219 { 220 link_order->type = bfd_symbol_reloc_link_order; 221 link_order->u.reloc.p->u.name = rs->name; 222 } 223 } 224 break; 225 226 case lang_input_section_enum: 227 /* Create a new link_order in the output section with this 228 attached */ 229 if (statement->input_section.ifile->just_syms_flag == false) 230 { 231 asection *i = statement->input_section.section; 232 asection *output_section = i->output_section; 233 234 ASSERT (output_section->owner == output_bfd); 235 236 if ((output_section->flags & SEC_HAS_CONTENTS) != 0) 237 { 238 struct bfd_link_order *link_order; 239 240 link_order = bfd_new_link_order (output_bfd, output_section); 241 242 if (i->flags & SEC_NEVER_LOAD) 243 { 244 /* We've got a never load section inside one which 245 is going to be output, we'll change it into a 246 fill link_order */ 247 link_order->type = bfd_fill_link_order; 248 link_order->u.fill.value = 0; 249 } 250 else 251 { 252 link_order->type = bfd_indirect_link_order; 253 link_order->u.indirect.section = i; 254 ASSERT (i->output_section == output_section); 255 } 256 if (i->_cooked_size) 257 link_order->size = i->_cooked_size; 258 else 259 link_order->size = bfd_get_section_size_before_reloc (i); 260 link_order->offset = i->output_offset; 261 } 262 } 263 break; 264 265 case lang_padding_statement_enum: 266 /* Make a new link_order with the right filler */ 267 { 268 asection *output_section; 269 struct bfd_link_order *link_order; 270 271 output_section = statement->padding_statement.output_section; 272 ASSERT (statement->padding_statement.output_section->owner 273 == output_bfd); 274 if ((output_section->flags & SEC_HAS_CONTENTS) != 0) 275 { 276 link_order = bfd_new_link_order (output_bfd, output_section); 277 link_order->type = bfd_fill_link_order; 278 link_order->size = statement->padding_statement.size; 279 link_order->offset = statement->padding_statement.output_offset; 280 link_order->u.fill.value = statement->padding_statement.fill; 281 } 282 } 283 break; 284 285 default: 286 /* All the other ones fall through */ 287 break; 288 } 289 } 290 291 /* Call BFD to write out the linked file. */ 292 293 294 /**********************************************************************/ 295 296 297 /* Wander around the input sections, make sure that 298 we'll never try and create an output section with more relocs 299 than will fit.. Do this by always assuming the worst case, and 300 creating new output sections with all the right bits */ 301 #define TESTIT 1 302 static asection * 303 clone_section (abfd, s, count) 304 bfd *abfd; 305 asection *s; 306 int *count; 307 { 308 #define SSIZE 8 309 char sname[SSIZE]; /* ?? find the name for this size */ 310 asection *n; 311 struct bfd_link_hash_entry *h; 312 /* Invent a section name - use first five 313 chars of base section name and a digit suffix */ 314 do 315 { 316 unsigned int i; 317 char b[6]; 318 for (i = 0; i < sizeof (b) - 1 && s->name[i]; i++) 319 b[i] = s->name[i]; 320 b[i] = 0; 321 sprintf (sname, "%s%d", b, (*count)++); 322 } 323 while (bfd_get_section_by_name (abfd, sname)); 324 325 n = bfd_make_section_anyway (abfd, xstrdup (sname)); 326 327 /* Create a symbol of the same name */ 328 329 h = bfd_link_hash_lookup (link_info.hash, 330 sname, true, true, false); 331 h->type = bfd_link_hash_defined; 332 h->u.def.value = 0; 333 h->u.def.section = n ; 334 335 336 n->flags = s->flags; 337 n->vma = s->vma; 338 n->user_set_vma = s->user_set_vma; 339 n->lma = s->lma; 340 n->_cooked_size = 0; 341 n->_raw_size = 0; 342 n->output_offset = s->output_offset; 343 n->output_section = n; 344 n->orelocation = 0; 345 n->reloc_count = 0; 346 n->alignment_power = s->alignment_power; 347 return n; 348 } 349 350 #if TESTING 351 static void 352 ds (s) 353 asection *s; 354 { 355 struct bfd_link_order *l = s->link_order_head; 356 printf ("vma %x size %x\n", s->vma, s->_raw_size); 357 while (l) 358 { 359 if (l->type == bfd_indirect_link_order) 360 { 361 printf ("%8x %s\n", l->offset, l->u.indirect.section->owner->filename); 362 } 363 else 364 { 365 printf (_("%8x something else\n"), l->offset); 366 } 367 l = l->next; 368 } 369 printf ("\n"); 370 } 371 dump (s, a1, a2) 372 char *s; 373 asection *a1; 374 asection *a2; 375 { 376 printf ("%s\n", s); 377 ds (a1); 378 ds (a2); 379 } 380 381 static void 382 sanity_check (abfd) 383 bfd *abfd; 384 { 385 asection *s; 386 for (s = abfd->sections; s; s = s->next) 387 { 388 struct bfd_link_order *p; 389 bfd_vma prev = 0; 390 for (p = s->link_order_head; p; p = p->next) 391 { 392 if (p->offset > 100000) 393 abort (); 394 if (p->offset < prev) 395 abort (); 396 prev = p->offset; 397 } 398 } 399 } 400 #else 401 #define sanity_check(a) 402 #define dump(a, b, c) 403 #endif 404 405 static void 406 split_sections (abfd, info) 407 bfd *abfd; 408 struct bfd_link_info *info; 409 { 410 asection *original_sec; 411 int nsecs = abfd->section_count; 412 sanity_check (abfd); 413 /* look through all the original sections */ 414 for (original_sec = abfd->sections; 415 original_sec && nsecs; 416 original_sec = original_sec->next, nsecs--) 417 { 418 boolean first = true; 419 int count = 0; 420 int lines = 0; 421 int relocs = 0; 422 struct bfd_link_order **pp; 423 bfd_vma vma = original_sec->vma; 424 bfd_vma shift_offset = 0; 425 asection *cursor = original_sec; 426 427 /* count up the relocations and line entries to see if 428 anything would be too big to fit */ 429 for (pp = &(cursor->link_order_head); *pp; pp = &((*pp)->next)) 430 { 431 struct bfd_link_order *p = *pp; 432 int thislines = 0; 433 int thisrelocs = 0; 434 if (p->type == bfd_indirect_link_order) 435 { 436 asection *sec; 437 438 sec = p->u.indirect.section; 439 440 if (info->strip == strip_none 441 || info->strip == strip_some) 442 thislines = sec->lineno_count; 443 444 if (info->relocateable) 445 thisrelocs = sec->reloc_count; 446 447 } 448 else if (info->relocateable 449 && (p->type == bfd_section_reloc_link_order 450 || p->type == bfd_symbol_reloc_link_order)) 451 thisrelocs++; 452 453 if (! first 454 && (thisrelocs + relocs > config.split_by_reloc 455 || thislines + lines > config.split_by_reloc 456 || config.split_by_file)) 457 { 458 /* create a new section and put this link order and the 459 following link orders into it */ 460 struct bfd_link_order *l = p; 461 asection *n = clone_section (abfd, cursor, &count); 462 *pp = NULL; /* Snip off link orders from old section */ 463 n->link_order_head = l; /* attach to new section */ 464 pp = &n->link_order_head; 465 466 /* change the size of the original section and 467 update the vma of the new one */ 468 469 dump ("before snip", cursor, n); 470 471 n->_raw_size = cursor->_raw_size - l->offset; 472 cursor->_raw_size = l->offset; 473 474 vma += cursor->_raw_size; 475 n->lma = n->vma = vma; 476 477 shift_offset = l->offset; 478 479 /* run down the chain and change the output section to 480 the right one, update the offsets too */ 481 482 while (l) 483 { 484 l->offset -= shift_offset; 485 if (l->type == bfd_indirect_link_order) 486 { 487 l->u.indirect.section->output_section = n; 488 l->u.indirect.section->output_offset = l->offset; 489 } 490 l = l->next; 491 } 492 dump ("after snip", cursor, n); 493 cursor = n; 494 relocs = thisrelocs; 495 lines = thislines; 496 } 497 else 498 { 499 relocs += thisrelocs; 500 lines += thislines; 501 } 502 503 first = false; 504 } 505 } 506 sanity_check (abfd); 507 } 508 /**********************************************************************/ 509 void 510 ldwrite () 511 { 512 /* Reset error indicator, which can typically something like invalid 513 format from openning up the .o files */ 514 bfd_set_error (bfd_error_no_error); 515 lang_for_each_statement (build_link_order); 516 517 if (config.split_by_reloc || config.split_by_file) 518 split_sections (output_bfd, &link_info); 519 if (!bfd_final_link (output_bfd, &link_info)) 520 { 521 /* If there was an error recorded, print it out. Otherwise assume 522 an appropriate error message like unknown symbol was printed 523 out. */ 524 525 if (bfd_get_error () != bfd_error_no_error) 526 einfo (_("%F%P: final link failed: %E\n"), output_bfd); 527 else 528 xexit(1); 529 } 530 } 531