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