]> git.ipfire.org Git - thirdparty/binutils-gdb.git/blame - binutils/nlmconv.c
* Many files: Added gettext invocations around user-visible
[thirdparty/binutils-gdb.git] / binutils / nlmconv.c
CommitLineData
d92aadfd 1/* nlmconv.c -- NLM conversion program
1d1a5a53 2 Copyright (C) 1993, 94, 95, 96, 1997 Free Software Foundation, Inc.
d92aadfd
ILT
3
4This file is part of GNU Binutils.
5
6This program is free software; you can redistribute it and/or modify
7it under the terms of the GNU General Public License as published by
8the Free Software Foundation; either version 2 of the License, or
9(at your option) any later version.
10
11This program is distributed in the hope that it will be useful,
12but WITHOUT ANY WARRANTY; without even the implied warranty of
13MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14GNU General Public License for more details.
15
16You should have received a copy of the GNU General Public License
17along with this program; if not, write to the Free Software
1d1a5a53 18Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
d92aadfd
ILT
19
20/* Written by Ian Lance Taylor <ian@cygnus.com>.
21
22 This program can be used to convert any appropriate object file
23 into a NetWare Loadable Module (an NLM). It will accept a linker
24 specification file which is identical to that accepted by the
1d1a5a53
ILT
25 NetWare linker, NLMLINK. */
26
27/* AIX requires this to be the first thing in the file. */
28#ifndef __GNUC__
29# ifdef _AIX
30 #pragma alloca
31#endif
32#endif
33
34#include "bfd.h"
35#include "libiberty.h"
36#include "bucomm.h"
d92aadfd
ILT
37
38#include <ansidecl.h>
ef5b5368 39#include <time.h>
90d8edfd 40#include <ctype.h>
d92aadfd 41#include <sys/stat.h>
0f6df2ee 42#include <sys/file.h>
d92aadfd
ILT
43#include <assert.h>
44#include <getopt.h>
1d1a5a53 45
d92aadfd
ILT
46/* Internal BFD NLM header. */
47#include "libnlm.h"
48#include "nlmconv.h"
49
9d11577a 50#ifdef NLMCONV_ALPHA
419093bc
ILT
51#include "coff/sym.h"
52#include "coff/ecoff.h"
9d11577a 53#endif
419093bc 54
d92aadfd
ILT
55/* If strerror is just a macro, we want to use the one from libiberty
56 since it will handle undefined values. */
57#undef strerror
58extern char *strerror ();
ef5b5368
ILT
59
60#ifndef localtime
61extern struct tm *localtime ();
62#endif
63
64#ifndef SEEK_SET
65#define SEEK_SET 0
66#endif
0f6df2ee
ILT
67
68#ifndef R_OK
69#define R_OK 4
70#define W_OK 2
71#define X_OK 1
72#endif
d92aadfd
ILT
73\f
74/* Global variables. */
75
76/* The name used to invoke the program. */
77char *program_name;
78
ef5b5368
ILT
79/* Local variables. */
80
0f6df2ee
ILT
81/* Whether to print out debugging information (currently just controls
82 whether it prints the linker command if there is one). */
83static int debug;
84
ef5b5368 85/* The symbol table. */
d92aadfd
ILT
86static asymbol **symbols;
87
dcb210cb
ILT
88/* A section we create in the output file to hold pointers to where
89 the sections of the input file end up. We will put a pointer to
90 this section in the NLM header. These is an entry for each input
91 section. The format is
92 null terminated section name
93 zeroes to adjust to 4 byte boundary
94 4 byte section data file pointer
95 4 byte section size
96 We don't need a version number. The way we find this information
97 is by finding a stamp in the NLM header information. If we need to
98 change the format of this information, we can simply change the
99 stamp. */
100static asection *secsec;
101
0f6df2ee
ILT
102/* A temporary file name to be unlinked on exit. Actually, for most
103 errors, we leave it around. It's not clear whether that is helpful
104 or not. */
105static char *unlink_on_exit;
106
d92aadfd
ILT
107/* The list of long options. */
108static struct option long_options[] =
109{
0f6df2ee 110 { "debug", no_argument, 0, 'd' },
419093bc 111 { "header-file", required_argument, 0, 'T' },
ef5b5368 112 { "help", no_argument, 0, 'h' },
e70f2bde
ILT
113 { "input-target", required_argument, 0, 'I' },
114 { "input-format", required_argument, 0, 'I' }, /* Obsolete */
0f6df2ee 115 { "linker", required_argument, 0, 'l' },
e70f2bde
ILT
116 { "output-target", required_argument, 0, 'O' },
117 { "output-format", required_argument, 0, 'O' }, /* Obsolete */
ef5b5368 118 { "version", no_argument, 0, 'V' },
d92aadfd
ILT
119 { NULL, no_argument, 0, 0 }
120};
121
122/* Local routines. */
123
124static void show_help PARAMS ((void));
125static void show_usage PARAMS ((FILE *, int));
126static const char *select_output_format PARAMS ((enum bfd_architecture,
419093bc 127 unsigned long, boolean));
d92aadfd
ILT
128static void setup_sections PARAMS ((bfd *, asection *, PTR));
129static void copy_sections PARAMS ((bfd *, asection *, PTR));
419093bc 130static void mangle_relocs PARAMS ((bfd *, asection *, arelent ***,
ae5d2ff5 131 long *, char *,
d92aadfd 132 bfd_size_type));
9d11577a
ILT
133static void default_mangle_relocs PARAMS ((bfd *, asection *, arelent ***,
134 long *, char *,
135 bfd_size_type));
136static char *link_inputs PARAMS ((struct string_list *, char *));
9d11577a
ILT
137
138#ifdef NLMCONV_I386
419093bc 139static void i386_mangle_relocs PARAMS ((bfd *, asection *, arelent ***,
ae5d2ff5 140 long *, char *,
a30f59a4 141 bfd_size_type));
9d11577a
ILT
142#endif
143
144#ifdef NLMCONV_ALPHA
419093bc 145static void alpha_mangle_relocs PARAMS ((bfd *, asection *, arelent ***,
ae5d2ff5 146 long *, char *,
419093bc 147 bfd_size_type));
9d11577a
ILT
148#endif
149
150#ifdef NLMCONV_POWERPC
c59fa195 151static void powerpc_build_stubs PARAMS ((bfd *, bfd *, asymbol ***, long *));
4bd7a65f
ILT
152static void powerpc_resolve_stubs PARAMS ((bfd *, bfd *));
153static void powerpc_mangle_relocs PARAMS ((bfd *, asection *, arelent ***,
ae5d2ff5 154 long *, char *,
4bd7a65f 155 bfd_size_type));
9d11577a 156#endif
d92aadfd
ILT
157\f
158/* The main routine. */
159
160int
161main (argc, argv)
162 int argc;
163 char **argv;
164{
165 int opt;
0f6df2ee 166 char *input_file = NULL;
d92aadfd
ILT
167 const char *input_format = NULL;
168 const char *output_format = NULL;
169 const char *header_file = NULL;
0f6df2ee
ILT
170 char *ld_arg = NULL;
171 Nlm_Internal_Fixed_Header fixed_hdr_struct;
172 Nlm_Internal_Variable_Header var_hdr_struct;
173 Nlm_Internal_Version_Header version_hdr_struct;
174 Nlm_Internal_Copyright_Header copyright_hdr_struct;
175 Nlm_Internal_Extended_Header extended_hdr_struct;
d92aadfd
ILT
176 bfd *inbfd;
177 bfd *outbfd;
ef5b5368 178 asymbol **newsyms, **outsyms;
ae5d2ff5
ILT
179 long symcount, newsymalloc, newsymcount;
180 long symsize;
4bd7a65f 181 asection *text_sec, *bss_sec, *data_sec;
90d8edfd
ILT
182 bfd_vma vma;
183 bfd_size_type align;
ef5b5368 184 asymbol *endsym;
ae5d2ff5 185 long i;
d92aadfd
ILT
186 char inlead, outlead;
187 boolean gotstart, gotexit, gotcheck;
188 struct stat st;
ef5b5368 189 FILE *custom_data, *help_data, *message_data, *rpc_data, *shared_data;
419093bc 190 size_t custom_size, help_size, message_size, module_size, rpc_size;
d92aadfd 191 asection *custom_section, *help_section, *message_section, *module_section;
ef5b5368
ILT
192 asection *rpc_section, *shared_section;
193 bfd *sharedbfd;
419093bc 194 size_t shared_offset, shared_size;
ef5b5368 195 Nlm_Internal_Fixed_Header sharedhdr;
d92aadfd 196 int len;
90d8edfd 197 char *modname;
cef35d48 198 char **matching;
d92aadfd
ILT
199
200 program_name = argv[0];
7681bc7b 201 xmalloc_set_program_name (program_name);
d92aadfd
ILT
202
203 bfd_init ();
1d1a5a53 204 set_default_bfd_target ();
d92aadfd 205
0f6df2ee
ILT
206 while ((opt = getopt_long (argc, argv, "dhI:l:O:T:V", long_options,
207 (int *) NULL))
d92aadfd
ILT
208 != EOF)
209 {
210 switch (opt)
211 {
0f6df2ee
ILT
212 case 'd':
213 debug = 1;
214 break;
ef5b5368 215 case 'h':
d92aadfd
ILT
216 show_help ();
217 /*NOTREACHED*/
218 case 'I':
219 input_format = optarg;
220 break;
0f6df2ee
ILT
221 case 'l':
222 ld_arg = optarg;
223 break;
d92aadfd
ILT
224 case 'O':
225 output_format = optarg;
226 break;
227 case 'T':
228 header_file = optarg;
229 break;
ef5b5368 230 case 'V':
1d1a5a53 231 print_version ("nlmconv");
d92aadfd
ILT
232 /*NOTREACHED*/
233 case 0:
234 break;
235 default:
236 show_usage (stderr, 1);
237 /*NOTREACHED*/
238 }
239 }
240
0f6df2ee
ILT
241 /* The input and output files may be named on the command line. */
242 output_file = NULL;
243 if (optind < argc)
d92aadfd 244 {
0f6df2ee
ILT
245 input_file = argv[optind];
246 ++optind;
247 if (optind < argc)
248 {
249 output_file = argv[optind];
250 ++optind;
251 if (optind < argc)
252 show_usage (stderr, 1);
253 if (strcmp (input_file, output_file) == 0)
254 {
255 fprintf (stderr,
256 "%s: input and output files must be different\n",
257 program_name);
258 exit (1);
259 }
260 }
d92aadfd
ILT
261 }
262
d92aadfd 263 /* Initialize the header information to default values. */
0f6df2ee
ILT
264 fixed_hdr = &fixed_hdr_struct;
265 memset ((PTR) &fixed_hdr_struct, 0, sizeof fixed_hdr_struct);
266 var_hdr = &var_hdr_struct;
267 memset ((PTR) &var_hdr_struct, 0, sizeof var_hdr_struct);
268 version_hdr = &version_hdr_struct;
269 memset ((PTR) &version_hdr_struct, 0, sizeof version_hdr_struct);
270 copyright_hdr = &copyright_hdr_struct;
271 memset ((PTR) &copyright_hdr_struct, 0, sizeof copyright_hdr_struct);
272 extended_hdr = &extended_hdr_struct;
273 memset ((PTR) &extended_hdr_struct, 0, sizeof extended_hdr_struct);
d92aadfd
ILT
274 check_procedure = NULL;
275 custom_file = NULL;
276 debug_info = false;
277 exit_procedure = "_Stop";
278 export_symbols = NULL;
279 map_file = NULL;
280 full_map = false;
281 help_file = NULL;
282 import_symbols = NULL;
283 message_file = NULL;
284 modules = NULL;
285 sharelib_file = NULL;
286 start_procedure = "_Prelude";
287 verbose = false;
288 rpc_file = NULL;
289
290 parse_errors = 0;
291
292 /* Parse the header file (if there is one). */
293 if (header_file != NULL)
294 {
295 if (! nlmlex_file (header_file)
296 || yyparse () != 0
297 || parse_errors != 0)
298 exit (1);
299 }
300
0f6df2ee
ILT
301 if (input_files != NULL)
302 {
303 if (input_file != NULL)
304 {
305 fprintf (stderr,
306 "%s: input file named both on command line and with INPUT\n",
307 program_name);
308 exit (1);
309 }
310 if (input_files->next == NULL)
311 input_file = input_files->string;
312 else
313 input_file = link_inputs (input_files, ld_arg);
314 }
315 else if (input_file == NULL)
316 {
317 fprintf (stderr, "%s: no input file\n", program_name);
318 show_usage (stderr, 1);
319 }
320
321 inbfd = bfd_openr (input_file, input_format);
322 if (inbfd == NULL)
323 bfd_fatal (input_file);
324
cef35d48
DM
325 if (! bfd_check_format_matches (inbfd, bfd_object, &matching))
326 {
327 bfd_nonfatal (input_file);
7681bc7b 328 if (bfd_get_error () == bfd_error_file_ambiguously_recognized)
cef35d48
DM
329 {
330 list_matching_formats (matching);
331 free (matching);
332 }
333 exit (1);
334 }
0f6df2ee
ILT
335
336 if (output_format == NULL)
337 output_format = select_output_format (bfd_get_arch (inbfd),
338 bfd_get_mach (inbfd),
1d1a5a53 339 bfd_big_endian (inbfd));
0f6df2ee
ILT
340
341 assert (output_format != NULL);
342
343 /* Use the output file named on the command line if it exists.
344 Otherwise use the file named in the OUTPUT statement. */
345 if (output_file == NULL)
346 {
347 fprintf (stderr, "%s: no name for output file\n",
348 program_name);
349 show_usage (stderr, 1);
350 }
351
352 outbfd = bfd_openw (output_file, output_format);
353 if (outbfd == NULL)
354 bfd_fatal (output_file);
355 if (! bfd_set_format (outbfd, bfd_object))
356 bfd_fatal (output_file);
357
0c5dc23c 358 assert (bfd_get_flavour (outbfd) == bfd_target_nlm_flavour);
0f6df2ee
ILT
359
360 if (bfd_arch_get_compatible (inbfd, outbfd) == NULL)
361 fprintf (stderr,
362 "%s: warning:input and output formats are not compatible\n",
363 program_name);
364
365 /* Move the values read from the command file into outbfd. */
366 *nlm_fixed_header (outbfd) = fixed_hdr_struct;
367 *nlm_variable_header (outbfd) = var_hdr_struct;
368 *nlm_version_header (outbfd) = version_hdr_struct;
369 *nlm_copyright_header (outbfd) = copyright_hdr_struct;
370 *nlm_extended_header (outbfd) = extended_hdr_struct;
371
d92aadfd
ILT
372 /* Start copying the input BFD to the output BFD. */
373 if (! bfd_set_file_flags (outbfd, bfd_get_file_flags (inbfd)))
374 bfd_fatal (bfd_get_filename (outbfd));
375
ae5d2ff5
ILT
376 symsize = bfd_get_symtab_upper_bound (inbfd);
377 if (symsize < 0)
378 bfd_fatal (input_file);
379 symbols = (asymbol **) xmalloc (symsize);
d92aadfd 380 symcount = bfd_canonicalize_symtab (inbfd, symbols);
ae5d2ff5
ILT
381 if (symcount < 0)
382 bfd_fatal (input_file);
d92aadfd 383
90d8edfd 384 /* Make sure we have a .bss section. */
ef5b5368
ILT
385 bss_sec = bfd_get_section_by_name (outbfd, NLM_UNINITIALIZED_DATA_NAME);
386 if (bss_sec == NULL)
387 {
388 bss_sec = bfd_make_section (outbfd, NLM_UNINITIALIZED_DATA_NAME);
90d8edfd
ILT
389 if (bss_sec == NULL
390 || ! bfd_set_section_flags (outbfd, bss_sec, SEC_ALLOC)
391 || ! bfd_set_section_alignment (outbfd, bss_sec, 1))
ef5b5368 392 bfd_fatal ("make .bss section");
ef5b5368 393 }
dcb210cb
ILT
394
395 /* We store the original section names in the .nlmsections section,
396 so that programs which understand it can resurrect the original
397 sections from the NLM. We will put a pointer to .nlmsections in
398 the NLM header area. */
399 secsec = bfd_make_section (outbfd, ".nlmsections");
400 if (secsec == NULL)
401 bfd_fatal ("make .nlmsections section");
402 if (! bfd_set_section_flags (outbfd, secsec, SEC_HAS_CONTENTS))
403 bfd_fatal ("set .nlmsections flags");
4bd7a65f 404
9d11577a 405#ifdef NLMCONV_POWERPC
4bd7a65f
ILT
406 /* For PowerPC NetWare we need to build stubs for calls to undefined
407 symbols. Because each stub requires an entry in the TOC section
408 which must be at the same location as other entries in the TOC
409 section, we must do this before determining where the TOC section
410 goes in setup_sections. */
03975925 411 if (bfd_get_arch (inbfd) == bfd_arch_powerpc)
c59fa195 412 powerpc_build_stubs (inbfd, outbfd, &symbols, &symcount);
9d11577a 413#endif
ef5b5368
ILT
414
415 /* Set up the sections. */
416 bfd_map_over_sections (inbfd, setup_sections, (PTR) outbfd);
417
4bd7a65f
ILT
418 text_sec = bfd_get_section_by_name (outbfd, NLM_CODE_NAME);
419
90d8edfd
ILT
420 /* The .bss section immediately follows the .data section. */
421 data_sec = bfd_get_section_by_name (outbfd, NLM_INITIALIZED_DATA_NAME);
422 if (data_sec != NULL)
423 {
424 bfd_size_type add;
425
426 vma = bfd_get_section_size_before_reloc (data_sec);
427 align = 1 << bss_sec->alignment_power;
428 add = ((vma + align - 1) &~ (align - 1)) - vma;
429 vma += add;
430 if (! bfd_set_section_vma (outbfd, bss_sec, vma))
431 bfd_fatal ("set .bss vma");
432 if (add != 0)
433 {
434 bfd_size_type data_size;
435
436 data_size = bfd_get_section_size_before_reloc (data_sec);
437 if (! bfd_set_section_size (outbfd, data_sec, data_size + add))
438 bfd_fatal ("set .data size");
439 }
440 }
441
d92aadfd
ILT
442 /* Adjust symbol information. */
443 inlead = bfd_get_symbol_leading_char (inbfd);
444 outlead = bfd_get_symbol_leading_char (outbfd);
445 gotstart = false;
446 gotexit = false;
447 gotcheck = false;
ef5b5368
ILT
448 newsymalloc = 10;
449 newsyms = (asymbol **) xmalloc (newsymalloc * sizeof (asymbol *));
450 newsymcount = 0;
451 endsym = NULL;
d92aadfd
ILT
452 for (i = 0; i < symcount; i++)
453 {
454 register asymbol *sym;
455
456 sym = symbols[i];
457
458 /* Add or remove a leading underscore. */
459 if (inlead != outlead)
460 {
461 if (inlead != '\0')
462 {
463 if (bfd_asymbol_name (sym)[0] == inlead)
464 {
465 if (outlead == '\0')
466 ++sym->name;
467 else
468 {
469 char *new;
470
471 new = xmalloc (strlen (bfd_asymbol_name (sym)) + 1);
472 new[0] = outlead;
473 strcpy (new + 1, bfd_asymbol_name (sym) + 1);
474 sym->name = new;
475 }
476 }
477 }
478 else
479 {
480 char *new;
481
482 new = xmalloc (strlen (bfd_asymbol_name (sym)) + 2);
483 new[0] = outlead;
484 strcpy (new + 1, bfd_asymbol_name (sym));
485 sym->name = new;
486 }
487 }
488
ef5b5368
ILT
489 /* NLM's have an uninitialized data section, but they do not
490 have a common section in the Unix sense. Move all common
491 symbols into the .bss section, and mark them as exported. */
492 if (bfd_is_com_section (bfd_get_section (sym)))
493 {
494 bfd_vma size;
ef5b5368
ILT
495
496 sym->section = bss_sec;
497 size = sym->value;
498 sym->value = bss_sec->_raw_size;
499 bss_sec->_raw_size += size;
500 align = 1 << bss_sec->alignment_power;
501 bss_sec->_raw_size = (bss_sec->_raw_size + align - 1) &~ (align - 1);
ef5b5368
ILT
502 sym->flags |= BSF_EXPORT | BSF_GLOBAL;
503 }
90d8edfd
ILT
504 else if (bfd_get_section (sym)->output_section != NULL)
505 {
506 /* Move the symbol into the output section. */
507 sym->value += bfd_get_section (sym)->output_offset;
508 sym->section = bfd_get_section (sym)->output_section;
509 /* This is no longer a section symbol. */
510 sym->flags &=~ BSF_SECTION_SYM;
511 }
ef5b5368
ILT
512
513 /* Force _edata and _end to be defined. This would normally be
514 done by the linker, but the manipulation of the common
515 symbols will confuse it. */
4bd7a65f
ILT
516 if ((sym->flags & BSF_DEBUGGING) == 0
517 && bfd_asymbol_name (sym)[0] == '_'
a18ff4a7 518 && bfd_is_und_section (bfd_get_section (sym)))
ef5b5368
ILT
519 {
520 if (strcmp (bfd_asymbol_name (sym), "_edata") == 0)
521 {
522 sym->section = bss_sec;
523 sym->value = 0;
524 }
525 if (strcmp (bfd_asymbol_name (sym), "_end") == 0)
526 {
527 sym->section = bss_sec;
528 endsym = sym;
529 }
d5e29b60 530
9d11577a 531#ifdef NLMCONV_POWERPC
4bd7a65f
ILT
532 /* For PowerPC NetWare, we define __GOT0. This is the start
533 of the .got section. */
534 if (bfd_get_arch (inbfd) == bfd_arch_powerpc
535 && strcmp (bfd_asymbol_name (sym), "__GOT0") == 0)
536 {
537 asection *got_sec;
538
539 got_sec = bfd_get_section_by_name (inbfd, ".got");
540 assert (got_sec != (asection *) NULL);
541 sym->value = got_sec->output_offset;
542 sym->section = got_sec->output_section;
543 }
9d11577a 544#endif
4bd7a65f 545 }
ef5b5368
ILT
546
547 /* If this is a global symbol, check the export list. */
548 if ((sym->flags & (BSF_EXPORT | BSF_GLOBAL)) != 0)
d92aadfd
ILT
549 {
550 register struct string_list *l;
ef5b5368 551 int found_simple;
d92aadfd 552
ef5b5368
ILT
553 /* Unfortunately, a symbol can appear multiple times on the
554 export list, with and without prefixes. */
555 found_simple = 0;
d92aadfd
ILT
556 for (l = export_symbols; l != NULL; l = l->next)
557 {
558 if (strcmp (l->string, bfd_asymbol_name (sym)) == 0)
ef5b5368 559 found_simple = 1;
d92aadfd
ILT
560 else
561 {
562 char *zbase;
563
564 zbase = strchr (l->string, '@');
565 if (zbase != NULL
566 && strcmp (zbase + 1, bfd_asymbol_name (sym)) == 0)
567 {
ef5b5368
ILT
568 /* We must add a symbol with this prefix. */
569 if (newsymcount >= newsymalloc)
570 {
571 newsymalloc += 10;
572 newsyms = ((asymbol **)
cef35d48 573 xrealloc ((PTR) newsyms,
ef5b5368
ILT
574 (newsymalloc
575 * sizeof (asymbol *))));
576 }
577 newsyms[newsymcount] =
578 (asymbol *) xmalloc (sizeof (asymbol));
579 *newsyms[newsymcount] = *sym;
580 newsyms[newsymcount]->name = l->string;
581 ++newsymcount;
d92aadfd
ILT
582 }
583 }
584 }
ef5b5368
ILT
585 if (! found_simple)
586 {
587 /* The unmodified symbol is actually not exported at
588 all. */
589 sym->flags &=~ (BSF_GLOBAL | BSF_EXPORT);
590 sym->flags |= BSF_LOCAL;
591 }
d92aadfd
ILT
592 }
593
594 /* If it's an undefined symbol, see if it's on the import list.
595 Change the prefix if necessary. */
a18ff4a7 596 if (bfd_is_und_section (bfd_get_section (sym)))
d92aadfd
ILT
597 {
598 register struct string_list *l;
599
600 for (l = import_symbols; l != NULL; l = l->next)
601 {
602 if (strcmp (l->string, bfd_asymbol_name (sym)) == 0)
603 break;
604 else
605 {
606 char *zbase;
607
608 zbase = strchr (l->string, '@');
609 if (zbase != NULL
610 && strcmp (zbase + 1, bfd_asymbol_name (sym)) == 0)
611 {
612 sym->name = l->string;
613 break;
614 }
615 }
616 }
617 if (l == NULL)
618 fprintf (stderr,
619 "%s: warning: symbol %s imported but not in import list\n",
620 program_name, bfd_asymbol_name (sym));
621 }
622
623 /* See if it's one of the special named symbols. */
4bd7a65f 624 if ((sym->flags & BSF_DEBUGGING) == 0)
d92aadfd 625 {
4bd7a65f
ILT
626 bfd_vma val;
627
628 /* FIXME: If these symbols are not in the .text section, we
629 add the .text section size to the value. This may not be
630 correct for all targets. I'm not sure how this should
631 really be handled. */
632 if (strcmp (bfd_asymbol_name (sym), start_procedure) == 0)
633 {
634 val = bfd_asymbol_value (sym);
635 if (bfd_get_section (sym) == data_sec
636 && text_sec != (asection *) NULL)
637 val += bfd_section_size (outbfd, text_sec);
638 if (! bfd_set_start_address (outbfd, val))
639 bfd_fatal ("set start address");
640 gotstart = true;
641 }
642 if (strcmp (bfd_asymbol_name (sym), exit_procedure) == 0)
643 {
644 val = bfd_asymbol_value (sym);
645 if (bfd_get_section (sym) == data_sec
646 && text_sec != (asection *) NULL)
647 val += bfd_section_size (outbfd, text_sec);
648 nlm_fixed_header (outbfd)->exitProcedureOffset = val;
649 gotexit = true;
650 }
651 if (check_procedure != NULL
652 && strcmp (bfd_asymbol_name (sym), check_procedure) == 0)
653 {
654 val = bfd_asymbol_value (sym);
655 if (bfd_get_section (sym) == data_sec
656 && text_sec != (asection *) NULL)
657 val += bfd_section_size (outbfd, text_sec);
658 nlm_fixed_header (outbfd)->checkUnloadProcedureOffset = val;
659 gotcheck = true;
660 }
d92aadfd
ILT
661 }
662 }
663
ef5b5368 664 if (endsym != NULL)
4bd7a65f
ILT
665 {
666 endsym->value = bfd_get_section_size_before_reloc (bss_sec);
667
668 /* FIXME: If any relocs referring to _end use inplace addends,
669 then I think they need to be updated. This is handled by
670 i386_mangle_relocs. Is it needed for any other object
671 formats? */
672 }
ef5b5368
ILT
673
674 if (newsymcount == 0)
675 outsyms = symbols;
676 else
677 {
678 outsyms = (asymbol **) xmalloc ((symcount + newsymcount + 1)
679 * sizeof (asymbol *));
680 memcpy (outsyms, symbols, symcount * sizeof (asymbol *));
681 memcpy (outsyms + symcount, newsyms, newsymcount * sizeof (asymbol *));
682 outsyms[symcount + newsymcount] = NULL;
683 }
684
685 bfd_set_symtab (outbfd, outsyms, symcount + newsymcount);
d92aadfd
ILT
686
687 if (! gotstart)
688 fprintf (stderr, "%s: warning: START procedure %s not defined\n",
689 program_name, start_procedure);
690 if (! gotexit)
691 fprintf (stderr, "%s: warning: EXIT procedure %s not defined\n",
692 program_name, exit_procedure);
693 if (check_procedure != NULL
694 && ! gotcheck)
695 fprintf (stderr, "%s: warning: CHECK procedure %s not defined\n",
696 program_name, check_procedure);
697
d92aadfd
ILT
698 /* Add additional sections required for the header information. */
699 if (custom_file != NULL)
700 {
701 custom_data = fopen (custom_file, "r");
702 if (custom_data == NULL
703 || fstat (fileno (custom_data), &st) < 0)
704 {
705 fprintf (stderr, "%s:%s: %s\n", program_name, custom_file,
706 strerror (errno));
707 custom_file = NULL;
708 }
709 else
710 {
711 custom_size = st.st_size;
712 custom_section = bfd_make_section (outbfd, ".nlmcustom");
713 if (custom_section == NULL
714 || ! bfd_set_section_size (outbfd, custom_section, custom_size)
715 || ! bfd_set_section_flags (outbfd, custom_section,
716 SEC_HAS_CONTENTS))
717 bfd_fatal ("custom section");
718 }
719 }
720 if (help_file != NULL)
721 {
722 help_data = fopen (help_file, "r");
723 if (help_data == NULL
724 || fstat (fileno (help_data), &st) < 0)
725 {
726 fprintf (stderr, "%s:%s: %s\n", program_name, help_file,
727 strerror (errno));
728 help_file = NULL;
729 }
730 else
731 {
732 help_size = st.st_size;
733 help_section = bfd_make_section (outbfd, ".nlmhelp");
734 if (help_section == NULL
735 || ! bfd_set_section_size (outbfd, help_section, help_size)
736 || ! bfd_set_section_flags (outbfd, help_section,
737 SEC_HAS_CONTENTS))
738 bfd_fatal ("help section");
739 strncpy (nlm_extended_header (outbfd)->stamp, "MeSsAgEs", 8);
740 }
741 }
742 if (message_file != NULL)
743 {
744 message_data = fopen (message_file, "r");
745 if (message_data == NULL
746 || fstat (fileno (message_data), &st) < 0)
747 {
748 fprintf (stderr, "%s:%s: %s\n", program_name, message_file,
749 strerror (errno));
750 message_file = NULL;
751 }
752 else
753 {
754 message_size = st.st_size;
755 message_section = bfd_make_section (outbfd, ".nlmmessages");
756 if (message_section == NULL
757 || ! bfd_set_section_size (outbfd, message_section, message_size)
758 || ! bfd_set_section_flags (outbfd, message_section,
759 SEC_HAS_CONTENTS))
760 bfd_fatal ("message section");
761 strncpy (nlm_extended_header (outbfd)->stamp, "MeSsAgEs", 8);
762 }
763 }
764 if (modules != NULL)
765 {
766 struct string_list *l;
767
768 module_size = 0;
769 for (l = modules; l != NULL; l = l->next)
770 module_size += strlen (l->string) + 1;
771 module_section = bfd_make_section (outbfd, ".nlmmodules");
772 if (module_section == NULL
773 || ! bfd_set_section_size (outbfd, module_section, module_size)
774 || ! bfd_set_section_flags (outbfd, module_section,
775 SEC_HAS_CONTENTS))
776 bfd_fatal ("module section");
777 }
778 if (rpc_file != NULL)
779 {
780 rpc_data = fopen (rpc_file, "r");
781 if (rpc_data == NULL
782 || fstat (fileno (rpc_data), &st) < 0)
783 {
784 fprintf (stderr, "%s:%s: %s\n", program_name, rpc_file,
785 strerror (errno));
786 rpc_file = NULL;
787 }
788 else
789 {
790 rpc_size = st.st_size;
791 rpc_section = bfd_make_section (outbfd, ".nlmrpc");
792 if (rpc_section == NULL
793 || ! bfd_set_section_size (outbfd, rpc_section, rpc_size)
794 || ! bfd_set_section_flags (outbfd, rpc_section,
795 SEC_HAS_CONTENTS))
796 bfd_fatal ("rpc section");
797 strncpy (nlm_extended_header (outbfd)->stamp, "MeSsAgEs", 8);
798 }
799 }
ef5b5368
ILT
800 if (sharelib_file != NULL)
801 {
802 sharedbfd = bfd_openr (sharelib_file, output_format);
803 if (sharedbfd == NULL
804 || ! bfd_check_format (sharedbfd, bfd_object))
805 {
806 fprintf (stderr, "%s:%s: %s\n", program_name, sharelib_file,
7681bc7b 807 bfd_errmsg (bfd_get_error ()));
ef5b5368
ILT
808 sharelib_file = NULL;
809 }
810 else
811 {
812 sharedhdr = *nlm_fixed_header (sharedbfd);
813 bfd_close (sharedbfd);
814 shared_data = fopen (sharelib_file, "r");
815 if (shared_data == NULL
816 || (fstat (fileno (shared_data), &st) < 0))
817 {
818 fprintf (stderr, "%s:%s: %s\n", program_name, sharelib_file,
819 strerror (errno));
820 sharelib_file = NULL;
821 }
822 else
823 {
824 /* If we were clever, we could just copy out the
825 sections of the shared library which we actually
826 need. However, we would have to figure out the sizes
827 of the external and public information, and that can
828 not be done without reading through them. */
1edb7335
ILT
829 if (sharedhdr.uninitializedDataSize > 0)
830 {
831 /* There is no place to record this information. */
832 fprintf (stderr,
833 "%s:%s: warning: shared libraries can not have uninitialized data\n",
834 program_name, sharelib_file);
835 }
ef5b5368
ILT
836 shared_offset = st.st_size;
837 if (shared_offset > sharedhdr.codeImageOffset)
838 shared_offset = sharedhdr.codeImageOffset;
839 if (shared_offset > sharedhdr.dataImageOffset)
840 shared_offset = sharedhdr.dataImageOffset;
841 if (shared_offset > sharedhdr.relocationFixupOffset)
842 shared_offset = sharedhdr.relocationFixupOffset;
843 if (shared_offset > sharedhdr.externalReferencesOffset)
844 shared_offset = sharedhdr.externalReferencesOffset;
845 if (shared_offset > sharedhdr.publicsOffset)
846 shared_offset = sharedhdr.publicsOffset;
847 shared_size = st.st_size - shared_offset;
848 shared_section = bfd_make_section (outbfd, ".nlmshared");
849 if (shared_section == NULL
850 || ! bfd_set_section_size (outbfd, shared_section,
851 shared_size)
852 || ! bfd_set_section_flags (outbfd, shared_section,
853 SEC_HAS_CONTENTS))
854 bfd_fatal ("shared section");
855 strncpy (nlm_extended_header (outbfd)->stamp, "MeSsAgEs", 8);
856 }
857 }
858 }
859
860 /* Check whether a version was given. */
861 if (strncmp (version_hdr->stamp, "VeRsIoN#", 8) != 0)
862 fprintf (stderr, "%s: warning: No version number given\n",
863 program_name);
864
865 /* At least for now, always create an extended header, because that
866 is what NLMLINK does. */
867 strncpy (nlm_extended_header (outbfd)->stamp, "MeSsAgEs", 8);
868
162794fe 869 strncpy (nlm_cygnus_ext_header (outbfd)->stamp, "CyGnUsEx", 8);
dcb210cb 870
ef5b5368
ILT
871 /* If the date was not given, force it in. */
872 if (nlm_version_header (outbfd)->month == 0
873 && nlm_version_header (outbfd)->day == 0
874 && nlm_version_header (outbfd)->year == 0)
875 {
90d8edfd 876 time_t now;
ef5b5368
ILT
877 struct tm *ptm;
878
879 time (&now);
880 ptm = localtime (&now);
881 nlm_version_header (outbfd)->month = ptm->tm_mon + 1;
882 nlm_version_header (outbfd)->day = ptm->tm_mday;
883 nlm_version_header (outbfd)->year = ptm->tm_year + 1900;
884 strncpy (version_hdr->stamp, "VeRsIoN#", 8);
885 }
4bd7a65f 886
9d11577a 887#ifdef NLMCONV_POWERPC
4bd7a65f 888 /* Resolve the stubs we build for PowerPC NetWare. */
03975925
ILT
889 if (bfd_get_arch (inbfd) == bfd_arch_powerpc)
890 powerpc_resolve_stubs (inbfd, outbfd);
9d11577a 891#endif
d92aadfd
ILT
892
893 /* Copy over the sections. */
894 bfd_map_over_sections (inbfd, copy_sections, (PTR) outbfd);
895
896 /* Finish up the header information. */
897 if (custom_file != NULL)
898 {
899 PTR data;
900
901 data = xmalloc (custom_size);
902 if (fread (data, 1, custom_size, custom_data) != custom_size)
903 fprintf (stderr, "%s:%s: read: %s\n", program_name, custom_file,
904 strerror (errno));
905 else
906 {
907 if (! bfd_set_section_contents (outbfd, custom_section, data,
908 (file_ptr) 0, custom_size))
909 bfd_fatal ("custom section");
910 nlm_fixed_header (outbfd)->customDataOffset =
911 custom_section->filepos;
912 nlm_fixed_header (outbfd)->customDataSize = custom_size;
913 }
914 free (data);
915 }
916 if (! debug_info)
917 {
918 /* As a special hack, the backend recognizes a debugInfoOffset
919 of -1 to mean that it should not output any debugging
920 information. This can not be handling by fiddling with the
921 symbol table because exported symbols appear in both the
922 export information and the debugging information. */
923 nlm_fixed_header (outbfd)->debugInfoOffset = (file_ptr) -1;
924 }
925 if (map_file != NULL)
926 fprintf (stderr,
e70f2bde 927 "%s: warning: MAP and FULLMAP are not supported; try ld -M\n",
d92aadfd
ILT
928 program_name);
929 if (help_file != NULL)
930 {
931 PTR data;
932
933 data = xmalloc (help_size);
934 if (fread (data, 1, help_size, help_data) != help_size)
935 fprintf (stderr, "%s:%s: read: %s\n", program_name, help_file,
936 strerror (errno));
937 else
938 {
939 if (! bfd_set_section_contents (outbfd, help_section, data,
940 (file_ptr) 0, help_size))
941 bfd_fatal ("help section");
942 nlm_extended_header (outbfd)->helpFileOffset =
943 help_section->filepos;
944 nlm_extended_header (outbfd)->helpFileLength = help_size;
945 }
946 free (data);
947 }
948 if (message_file != NULL)
949 {
950 PTR data;
951
952 data = xmalloc (message_size);
953 if (fread (data, 1, message_size, message_data) != message_size)
954 fprintf (stderr, "%s:%s: read: %s\n", program_name, message_file,
955 strerror (errno));
956 else
957 {
958 if (! bfd_set_section_contents (outbfd, message_section, data,
959 (file_ptr) 0, message_size))
960 bfd_fatal ("message section");
961 nlm_extended_header (outbfd)->messageFileOffset =
962 message_section->filepos;
963 nlm_extended_header (outbfd)->messageFileLength = message_size;
964
965 /* FIXME: Are these offsets correct on all platforms? Are
966 they 32 bits on all platforms? What endianness? */
967 nlm_extended_header (outbfd)->languageID =
968 bfd_h_get_32 (outbfd, (bfd_byte *) data + 106);
969 nlm_extended_header (outbfd)->messageCount =
970 bfd_h_get_32 (outbfd, (bfd_byte *) data + 110);
971 }
972 free (data);
973 }
974 if (modules != NULL)
975 {
976 PTR data;
419093bc 977 unsigned char *set;
d92aadfd
ILT
978 struct string_list *l;
979 bfd_size_type c;
980
981 data = xmalloc (module_size);
982 c = 0;
419093bc 983 set = (unsigned char *) data;
d92aadfd
ILT
984 for (l = modules; l != NULL; l = l->next)
985 {
986 *set = strlen (l->string);
987 strncpy (set + 1, l->string, *set);
988 set += *set + 1;
989 ++c;
990 }
991 if (! bfd_set_section_contents (outbfd, module_section, data,
992 (file_ptr) 0, module_size))
993 bfd_fatal ("module section");
994 nlm_fixed_header (outbfd)->moduleDependencyOffset =
995 module_section->filepos;
996 nlm_fixed_header (outbfd)->numberOfModuleDependencies = c;
997 }
998 if (rpc_file != NULL)
999 {
1000 PTR data;
1001
1002 data = xmalloc (rpc_size);
1003 if (fread (data, 1, rpc_size, rpc_data) != rpc_size)
1004 fprintf (stderr, "%s:%s: read: %s\n", program_name, rpc_file,
1005 strerror (errno));
1006 else
1007 {
1008 if (! bfd_set_section_contents (outbfd, rpc_section, data,
1009 (file_ptr) 0, rpc_size))
1010 bfd_fatal ("rpc section");
1011 nlm_extended_header (outbfd)->RPCDataOffset =
1012 rpc_section->filepos;
1013 nlm_extended_header (outbfd)->RPCDataLength = rpc_size;
1014 }
1015 free (data);
1016 }
ef5b5368
ILT
1017 if (sharelib_file != NULL)
1018 {
1019 PTR data;
1020
1021 data = xmalloc (shared_size);
1022 if (fseek (shared_data, shared_offset, SEEK_SET) != 0
1023 || fread (data, 1, shared_size, shared_data) != shared_size)
1024 fprintf (stderr, "%s:%s: read: %s\n", program_name, sharelib_file,
1025 strerror (errno));
1026 else
1027 {
1028 if (! bfd_set_section_contents (outbfd, shared_section, data,
1029 (file_ptr) 0, shared_size))
1030 bfd_fatal ("shared section");
1031 }
1032 nlm_extended_header (outbfd)->sharedCodeOffset =
1033 sharedhdr.codeImageOffset - shared_offset + shared_section->filepos;
1034 nlm_extended_header (outbfd)->sharedCodeLength =
1035 sharedhdr.codeImageSize;
1036 nlm_extended_header (outbfd)->sharedDataOffset =
1037 sharedhdr.dataImageOffset - shared_offset + shared_section->filepos;
1038 nlm_extended_header (outbfd)->sharedDataLength =
1039 sharedhdr.dataImageSize;
1040 nlm_extended_header (outbfd)->sharedRelocationFixupOffset =
1041 (sharedhdr.relocationFixupOffset
1042 - shared_offset
1043 + shared_section->filepos);
1044 nlm_extended_header (outbfd)->sharedRelocationFixupCount =
1045 sharedhdr.numberOfRelocationFixups;
1046 nlm_extended_header (outbfd)->sharedExternalReferenceOffset =
1047 (sharedhdr.externalReferencesOffset
1048 - shared_offset
1049 + shared_section->filepos);
1050 nlm_extended_header (outbfd)->sharedExternalReferenceCount =
1051 sharedhdr.numberOfExternalReferences;
1052 nlm_extended_header (outbfd)->sharedPublicsOffset =
1053 sharedhdr.publicsOffset - shared_offset + shared_section->filepos;
1054 nlm_extended_header (outbfd)->sharedPublicsCount =
1055 sharedhdr.numberOfPublics;
a30f59a4
ILT
1056 nlm_extended_header (outbfd)->sharedDebugRecordOffset =
1057 sharedhdr.debugInfoOffset - shared_offset + shared_section->filepos;
1058 nlm_extended_header (outbfd)->sharedDebugRecordCount =
1059 sharedhdr.numberOfDebugRecords;
ef5b5368
ILT
1060 nlm_extended_header (outbfd)->SharedInitializationOffset =
1061 sharedhdr.codeStartOffset;
1062 nlm_extended_header (outbfd)->SharedExitProcedureOffset =
1063 sharedhdr.exitProcedureOffset;
1064 free (data);
1065 }
0f6df2ee 1066 len = strlen (output_file);
d92aadfd
ILT
1067 if (len > NLM_MODULE_NAME_SIZE - 2)
1068 len = NLM_MODULE_NAME_SIZE - 2;
1069 nlm_fixed_header (outbfd)->moduleName[0] = len;
90d8edfd 1070
0f6df2ee 1071 strncpy (nlm_fixed_header (outbfd)->moduleName + 1, output_file,
d92aadfd
ILT
1072 NLM_MODULE_NAME_SIZE - 2);
1073 nlm_fixed_header (outbfd)->moduleName[NLM_MODULE_NAME_SIZE - 1] = '\0';
90d8edfd
ILT
1074 for (modname = nlm_fixed_header (outbfd)->moduleName;
1075 *modname != '\0';
1076 modname++)
1077 if (islower (*modname))
1078 *modname = toupper (*modname);
1079
d92aadfd
ILT
1080 strncpy (nlm_variable_header (outbfd)->oldThreadName, " LONG",
1081 NLM_OLD_THREAD_NAME_LENGTH);
1082
162794fe
ILT
1083 nlm_cygnus_ext_header (outbfd)->offset = secsec->filepos;
1084 nlm_cygnus_ext_header (outbfd)->length = bfd_section_size (outbfd, secsec);
dcb210cb 1085
d92aadfd 1086 if (! bfd_close (outbfd))
0f6df2ee 1087 bfd_fatal (output_file);
d92aadfd 1088 if (! bfd_close (inbfd))
0f6df2ee
ILT
1089 bfd_fatal (input_file);
1090
1091 if (unlink_on_exit != NULL)
1092 unlink (unlink_on_exit);
d92aadfd
ILT
1093
1094 return 0;
1095}
1096\f
1097/* Display a help message and exit. */
1098
1099static void
1100show_help ()
1101{
1102 printf ("%s: Convert an object file into a NetWare Loadable Module\n",
1103 program_name);
1104 show_usage (stdout, 0);
1105}
1106
1107/* Show a usage message and exit. */
1108
1109static void
1110show_usage (file, status)
1111 FILE *file;
1112 int status;
1113{
1114 fprintf (file, "\
e70f2bde
ILT
1115Usage: %s [-dhV] [-I bfdname] [-O bfdname] [-T header-file] [-l linker]\n\
1116 [--input-target=bfdname] [--output-target=bfdname]\n\
0f6df2ee
ILT
1117 [--header-file=file] [--linker=linker] [--debug]\n\
1118 [--help] [--version]\n\
1119 [in-file [out-file]]\n",
d92aadfd 1120 program_name);
1d1a5a53
ILT
1121 if (status == 0)
1122 fprintf (file, "Report bugs to bug-gnu-utils@prep.ai.mit.edu\n");
d92aadfd
ILT
1123 exit (status);
1124}
1125\f
1126/* Select the output format based on the input architecture, machine,
1127 and endianness. This chooses the appropriate NLM target. */
1128
1129static const char *
1130select_output_format (arch, mach, bigendian)
1131 enum bfd_architecture arch;
419093bc 1132 unsigned long mach;
d92aadfd
ILT
1133 boolean bigendian;
1134{
1135 switch (arch)
1136 {
9d11577a 1137#ifdef NLMCONV_I386
d92aadfd
ILT
1138 case bfd_arch_i386:
1139 return "nlm32-i386";
9d11577a
ILT
1140#endif
1141#ifdef NLMCONV_SPARC
a30f59a4
ILT
1142 case bfd_arch_sparc:
1143 return "nlm32-sparc";
9d11577a
ILT
1144#endif
1145#ifdef NLMCONV_ALPHA
419093bc
ILT
1146 case bfd_arch_alpha:
1147 return "nlm32-alpha";
9d11577a
ILT
1148#endif
1149#ifdef NLMCONV_POWERPC
4bd7a65f
ILT
1150 case bfd_arch_powerpc:
1151 return "nlm32-powerpc";
9d11577a 1152#endif
d92aadfd 1153 default:
9d11577a 1154 fprintf (stderr, "%s: support not compiled in for %s\n",
d92aadfd
ILT
1155 program_name, bfd_printable_arch_mach (arch, mach));
1156 exit (1);
1157 /* Avoid warning. */
1158 return NULL;
1159 }
1160 /*NOTREACHED*/
1161}
1162\f
90d8edfd
ILT
1163/* The BFD sections are copied in two passes. This function selects
1164 the output section for each input section, and sets up the section
1165 name, size, etc. */
d92aadfd
ILT
1166
1167static void
1168setup_sections (inbfd, insec, data_ptr)
1169 bfd *inbfd;
1170 asection *insec;
1171 PTR data_ptr;
1172{
1173 bfd *outbfd = (bfd *) data_ptr;
ef5b5368 1174 flagword f;
90d8edfd
ILT
1175 const char *outname;
1176 asection *outsec;
e70f2bde
ILT
1177 bfd_vma offset;
1178 bfd_size_type align;
1179 bfd_size_type add;
dcb210cb 1180 bfd_size_type secsecsize;
d92aadfd 1181
90d8edfd
ILT
1182 f = bfd_get_section_flags (inbfd, insec);
1183 if (f & SEC_CODE)
1184 outname = NLM_CODE_NAME;
1185 else if ((f & SEC_LOAD) && (f & SEC_HAS_CONTENTS))
1186 outname = NLM_INITIALIZED_DATA_NAME;
1187 else if (f & SEC_ALLOC)
1188 outname = NLM_UNINITIALIZED_DATA_NAME;
1189 else
1190 outname = bfd_section_name (inbfd, insec);
1191
1192 outsec = bfd_get_section_by_name (outbfd, outname);
d92aadfd
ILT
1193 if (outsec == NULL)
1194 {
90d8edfd 1195 outsec = bfd_make_section (outbfd, outname);
d92aadfd
ILT
1196 if (outsec == NULL)
1197 bfd_fatal ("make section");
1198 }
1199
1200 insec->output_section = outsec;
e70f2bde
ILT
1201
1202 offset = bfd_section_size (outbfd, outsec);
1203 align = 1 << bfd_section_alignment (inbfd, insec);
1204 add = ((offset + align - 1) &~ (align - 1)) - offset;
1205 insec->output_offset = offset + add;
d92aadfd
ILT
1206
1207 if (! bfd_set_section_size (outbfd, outsec,
90d8edfd 1208 (bfd_section_size (outbfd, outsec)
e70f2bde
ILT
1209 + bfd_section_size (inbfd, insec)
1210 + add)))
d92aadfd
ILT
1211 bfd_fatal ("set section size");
1212
90d8edfd
ILT
1213 if ((bfd_section_alignment (inbfd, insec)
1214 > bfd_section_alignment (outbfd, outsec))
1215 && ! bfd_set_section_alignment (outbfd, outsec,
1216 bfd_section_alignment (inbfd, insec)))
d92aadfd
ILT
1217 bfd_fatal ("set section alignment");
1218
1d1a5a53
ILT
1219 if (! bfd_set_section_flags (outbfd, outsec,
1220 f | bfd_get_section_flags (outbfd, outsec)))
d92aadfd 1221 bfd_fatal ("set section flags");
419093bc
ILT
1222
1223 bfd_set_reloc (outbfd, outsec, (arelent **) NULL, 0);
dcb210cb
ILT
1224
1225 /* For each input section we allocate space for an entry in
1226 .nlmsections. */
1227 secsecsize = bfd_section_size (outbfd, secsec);
1228 secsecsize += strlen (bfd_section_name (inbfd, insec)) + 1;
1229 secsecsize = (secsecsize + 3) &~ 3;
1230 secsecsize += 8;
1231 if (! bfd_set_section_size (outbfd, secsec, secsecsize))
1232 bfd_fatal ("set .nlmsections size");
d92aadfd
ILT
1233}
1234
1235/* Copy the section contents. */
1236
1237static void
1238copy_sections (inbfd, insec, data_ptr)
1239 bfd *inbfd;
1240 asection *insec;
1241 PTR data_ptr;
1242{
dcb210cb 1243 static bfd_size_type secsecoff = 0;
d92aadfd 1244 bfd *outbfd = (bfd *) data_ptr;
dcb210cb 1245 const char *inname;
d92aadfd
ILT
1246 asection *outsec;
1247 bfd_size_type size;
1248 PTR contents;
ae5d2ff5 1249 long reloc_size;
dcb210cb
ILT
1250 bfd_byte buf[4];
1251 bfd_size_type add;
1252
1253 inname = bfd_section_name (inbfd, insec);
d92aadfd 1254
90d8edfd 1255 outsec = insec->output_section;
d92aadfd
ILT
1256 assert (outsec != NULL);
1257
1258 size = bfd_get_section_size_before_reloc (insec);
d92aadfd
ILT
1259
1260 /* FIXME: Why are these necessary? */
1261 insec->_cooked_size = insec->_raw_size;
1262 insec->reloc_done = true;
1263
1264 if ((bfd_get_section_flags (inbfd, insec) & SEC_HAS_CONTENTS) == 0)
1265 contents = NULL;
1266 else
1267 {
1268 contents = xmalloc (size);
1269 if (! bfd_get_section_contents (inbfd, insec, contents,
1270 (file_ptr) 0, size))
1271 bfd_fatal (bfd_get_filename (inbfd));
1272 }
1273
1274 reloc_size = bfd_get_reloc_upper_bound (inbfd, insec);
ae5d2ff5
ILT
1275 if (reloc_size < 0)
1276 bfd_fatal (bfd_get_filename (inbfd));
419093bc 1277 if (reloc_size != 0)
d92aadfd
ILT
1278 {
1279 arelent **relocs;
ae5d2ff5 1280 long reloc_count;
d92aadfd
ILT
1281
1282 relocs = (arelent **) xmalloc (reloc_size);
1283 reloc_count = bfd_canonicalize_reloc (inbfd, insec, relocs, symbols);
ae5d2ff5
ILT
1284 if (reloc_count < 0)
1285 bfd_fatal (bfd_get_filename (inbfd));
419093bc 1286 mangle_relocs (outbfd, insec, &relocs, &reloc_count, (char *) contents,
ef5b5368 1287 size);
419093bc
ILT
1288
1289 /* FIXME: refers to internal BFD fields. */
1290 if (outsec->orelocation != (arelent **) NULL)
1291 {
1292 bfd_size_type total_count;
1293 arelent **combined;
1294
1295 total_count = reloc_count + outsec->reloc_count;
d5e29b60 1296 combined = (arelent **) xmalloc (total_count * sizeof (arelent *));
419093bc 1297 memcpy (combined, outsec->orelocation,
d5e29b60 1298 outsec->reloc_count * sizeof (arelent *));
419093bc 1299 memcpy (combined + outsec->reloc_count, relocs,
d5e29b60 1300 (size_t) (reloc_count * sizeof (arelent *)));
419093bc
ILT
1301 free (outsec->orelocation);
1302 reloc_count = total_count;
1303 relocs = combined;
1304 }
1305
d92aadfd
ILT
1306 bfd_set_reloc (outbfd, outsec, relocs, reloc_count);
1307 }
1308
1309 if (contents != NULL)
1310 {
1311 if (! bfd_set_section_contents (outbfd, outsec, contents,
90d8edfd 1312 insec->output_offset, size))
d92aadfd
ILT
1313 bfd_fatal (bfd_get_filename (outbfd));
1314 free (contents);
1315 }
dcb210cb
ILT
1316
1317 /* Add this section to .nlmsections. */
1318 if (! bfd_set_section_contents (outbfd, secsec, (PTR) inname, secsecoff,
1319 strlen (inname) + 1))
1320 bfd_fatal ("set .nlmsection contents");
1321 secsecoff += strlen (inname) + 1;
1322
1323 add = ((secsecoff + 3) &~ 3) - secsecoff;
1324 if (add != 0)
1325 {
1326 bfd_h_put_32 (outbfd, (bfd_vma) 0, buf);
1327 if (! bfd_set_section_contents (outbfd, secsec, buf, secsecoff, add))
1328 bfd_fatal ("set .nlmsection contents");
1329 secsecoff += add;
1330 }
1331
1332 if (contents != NULL)
1333 bfd_h_put_32 (outbfd, (bfd_vma) outsec->filepos, buf);
1334 else
1335 bfd_h_put_32 (outbfd, (bfd_vma) 0, buf);
1336 if (! bfd_set_section_contents (outbfd, secsec, buf, secsecoff, 4))
1337 bfd_fatal ("set .nlmsection contents");
1338 secsecoff += 4;
1339
1340 bfd_h_put_32 (outbfd, (bfd_vma) size, buf);
1341 if (! bfd_set_section_contents (outbfd, secsec, buf, secsecoff, 4))
1342 bfd_fatal ("set .nlmsection contents");
1343 secsecoff += 4;
d92aadfd
ILT
1344}
1345
1346/* Some, perhaps all, NetWare targets require changing the relocs used
1347 by the input formats. */
1348
1349static void
419093bc
ILT
1350mangle_relocs (outbfd, insec, relocs_ptr, reloc_count_ptr, contents,
1351 contents_size)
d92aadfd 1352 bfd *outbfd;
ef5b5368 1353 asection *insec;
419093bc 1354 arelent ***relocs_ptr;
ae5d2ff5 1355 long *reloc_count_ptr;
d92aadfd
ILT
1356 char *contents;
1357 bfd_size_type contents_size;
1358{
1359 switch (bfd_get_arch (outbfd))
1360 {
9d11577a 1361#ifdef NLMCONV_I386
d92aadfd 1362 case bfd_arch_i386:
419093bc
ILT
1363 i386_mangle_relocs (outbfd, insec, relocs_ptr, reloc_count_ptr,
1364 contents, contents_size);
1365 break;
9d11577a
ILT
1366#endif
1367#ifdef NLMCONV_ALPHA
419093bc
ILT
1368 case bfd_arch_alpha:
1369 alpha_mangle_relocs (outbfd, insec, relocs_ptr, reloc_count_ptr,
1370 contents, contents_size);
d92aadfd 1371 break;
9d11577a
ILT
1372#endif
1373#ifdef NLMCONV_POWERPC
4bd7a65f
ILT
1374 case bfd_arch_powerpc:
1375 powerpc_mangle_relocs (outbfd, insec, relocs_ptr, reloc_count_ptr,
1376 contents, contents_size);
1377 break;
9d11577a 1378#endif
d92aadfd 1379 default:
419093bc
ILT
1380 default_mangle_relocs (outbfd, insec, relocs_ptr, reloc_count_ptr,
1381 contents, contents_size);
d92aadfd
ILT
1382 break;
1383 }
1384}
1385
419093bc
ILT
1386/* By default all we need to do for relocs is change the address by
1387 the output_offset. */
1388
1389/*ARGSUSED*/
1390static void
1391default_mangle_relocs (outbfd, insec, relocs_ptr, reloc_count_ptr, contents,
1392 contents_size)
1393 bfd *outbfd;
1394 asection *insec;
1395 arelent ***relocs_ptr;
ae5d2ff5 1396 long *reloc_count_ptr;
419093bc
ILT
1397 char *contents;
1398 bfd_size_type contents_size;
1399{
1400 if (insec->output_offset != 0)
1401 {
ae5d2ff5 1402 long reloc_count;
419093bc 1403 register arelent **relocs;
ae5d2ff5 1404 register long i;
419093bc
ILT
1405
1406 reloc_count = *reloc_count_ptr;
1407 relocs = *relocs_ptr;
1408 for (i = 0; i < reloc_count; i++, relocs++)
1409 (*relocs)->address += insec->output_offset;
1410 }
1411}
9d11577a
ILT
1412\f
1413#ifdef NLMCONV_I386
419093bc 1414
d92aadfd
ILT
1415/* NetWare on the i386 supports a restricted set of relocs, which are
1416 different from those used on other i386 targets. This routine
1417 converts the relocs. It is, obviously, very target dependent. At
1418 the moment, the nlm32-i386 backend performs similar translations;
1419 however, it is more reliable and efficient to do them here. */
1420
1421static reloc_howto_type nlm_i386_pcrel_howto =
1422 HOWTO (1, /* type */
1423 0, /* rightshift */
1424 2, /* size (0 = byte, 1 = short, 2 = long) */
1425 32, /* bitsize */
1426 true, /* pc_relative */
1427 0, /* bitpos */
1428 complain_overflow_signed, /* complain_on_overflow */
1429 0, /* special_function */
1430 "DISP32", /* name */
1431 true, /* partial_inplace */
1432 0xffffffff, /* src_mask */
1433 0xffffffff, /* dst_mask */
1434 true); /* pcrel_offset */
1435
1436static void
419093bc 1437i386_mangle_relocs (outbfd, insec, relocs_ptr, reloc_count_ptr, contents,
ef5b5368 1438 contents_size)
d92aadfd 1439 bfd *outbfd;
ef5b5368 1440 asection *insec;
419093bc 1441 arelent ***relocs_ptr;
ae5d2ff5 1442 long *reloc_count_ptr;
d92aadfd
ILT
1443 char *contents;
1444 bfd_size_type contents_size;
1445{
ae5d2ff5 1446 long reloc_count, i;
419093bc 1447 arelent **relocs;
ef5b5368
ILT
1448
1449 reloc_count = *reloc_count_ptr;
419093bc 1450 relocs = *relocs_ptr;
ef5b5368 1451 for (i = 0; i < reloc_count; i++)
d92aadfd
ILT
1452 {
1453 arelent *rel;
1454 asymbol *sym;
a30f59a4 1455 bfd_size_type address;
d92aadfd
ILT
1456 bfd_vma addend;
1457
1458 rel = *relocs++;
1459 sym = *rel->sym_ptr_ptr;
1460
a30f59a4
ILT
1461 /* We're moving the relocs from the input section to the output
1462 section, so we must adjust the address accordingly. */
1463 address = rel->address;
1464 rel->address += insec->output_offset;
1465
d92aadfd
ILT
1466 /* Note that no serious harm will ensue if we fail to change a
1467 reloc. The backend will fail when writing out the reloc. */
1468
1469 /* Make sure this reloc is within the data we have. We use only
1470 4 byte relocs here, so we insist on having 4 bytes. */
a30f59a4 1471 if (address + 4 > contents_size)
d92aadfd
ILT
1472 continue;
1473
ef5b5368
ILT
1474 /* A PC relative reloc entirely within a single section is
1475 completely unnecessary. This can be generated by ld -r. */
1476 if (sym == insec->symbol
1477 && rel->howto != NULL
1478 && rel->howto->pc_relative
1479 && ! rel->howto->pcrel_offset)
1480 {
1481 --*reloc_count_ptr;
1482 --relocs;
1483 memmove (relocs, relocs + 1,
419093bc 1484 (size_t) ((reloc_count - i) * sizeof (arelent *)));
ef5b5368
ILT
1485 continue;
1486 }
1487
90d8edfd
ILT
1488 /* Get the amount the relocation will add in. */
1489 addend = rel->addend + sym->value;
1490
1491 /* NetWare doesn't support PC relative relocs against defined
1492 symbols, so we have to eliminate them by doing the relocation
1493 now. We can only do this if the reloc is within a single
1494 section. */
1495 if (rel->howto != NULL
1496 && rel->howto->pc_relative
1497 && bfd_get_section (sym) == insec->output_section)
1498 {
1499 bfd_vma val;
1500
1501 if (rel->howto->pcrel_offset)
a30f59a4 1502 addend -= address;
90d8edfd 1503
a30f59a4 1504 val = bfd_get_32 (outbfd, (bfd_byte *) contents + address);
90d8edfd 1505 val += addend;
a30f59a4 1506 bfd_put_32 (outbfd, val, (bfd_byte *) contents + address);
90d8edfd
ILT
1507
1508 --*reloc_count_ptr;
1509 --relocs;
1510 memmove (relocs, relocs + 1,
419093bc 1511 (size_t) ((reloc_count - i) * sizeof (arelent *)));
90d8edfd
ILT
1512 continue;
1513 }
1514
d92aadfd
ILT
1515 /* NetWare doesn't support reloc addends, so we get rid of them
1516 here by simply adding them into the object data. We handle
1517 the symbol value, if any, the same way. */
d92aadfd
ILT
1518 if (addend != 0
1519 && rel->howto != NULL
1520 && rel->howto->rightshift == 0
1521 && rel->howto->size == 2
1522 && rel->howto->bitsize == 32
1523 && rel->howto->bitpos == 0
1524 && rel->howto->src_mask == 0xffffffff
1525 && rel->howto->dst_mask == 0xffffffff)
1526 {
1527 bfd_vma val;
1528
a30f59a4 1529 val = bfd_get_32 (outbfd, (bfd_byte *) contents + address);
d92aadfd 1530 val += addend;
a30f59a4 1531 bfd_put_32 (outbfd, val, (bfd_byte *) contents + address);
d92aadfd
ILT
1532
1533 /* Adjust the reloc for the changes we just made. */
1534 rel->addend = 0;
a18ff4a7 1535 if (! bfd_is_und_section (bfd_get_section (sym)))
d92aadfd
ILT
1536 rel->sym_ptr_ptr = bfd_get_section (sym)->symbol_ptr_ptr;
1537 }
1538
1539 /* NetWare uses a reloc with pcrel_offset set. We adjust
1540 pc_relative relocs accordingly. We are going to change the
1541 howto field, so we can only do this if the current one is
1542 compatible. We should check that special_function is NULL
1543 here, but at the moment coff-i386 uses a special_function
1544 which does not affect what we are doing here. */
1545 if (rel->howto != NULL
1546 && rel->howto->pc_relative
1547 && ! rel->howto->pcrel_offset
1548 && rel->howto->rightshift == 0
1549 && rel->howto->size == 2
1550 && rel->howto->bitsize == 32
1551 && rel->howto->bitpos == 0
1552 && rel->howto->src_mask == 0xffffffff
1553 && rel->howto->dst_mask == 0xffffffff)
1554 {
1555 bfd_vma val;
1556
1557 /* When pcrel_offset is not set, it means that the negative
1558 of the address of the memory location is stored in the
1559 memory location. We must add it back in. */
a30f59a4
ILT
1560 val = bfd_get_32 (outbfd, (bfd_byte *) contents + address);
1561 val += address;
1562 bfd_put_32 (outbfd, val, (bfd_byte *) contents + address);
d92aadfd
ILT
1563
1564 /* We must change to a new howto. */
1565 rel->howto = &nlm_i386_pcrel_howto;
1566 }
1567 }
1568}
419093bc 1569
9d11577a
ILT
1570#endif /* NLMCONV_I386 */
1571\f
1572#ifdef NLMCONV_ALPHA
1573
419093bc
ILT
1574/* On the Alpha the first reloc for every section must be a special
1575 relocs which hold the GP address. Also, the first reloc in the
1576 file must be a special reloc which holds the address of the .lita
1577 section. */
1578
1579static reloc_howto_type nlm32_alpha_nw_howto =
1580 HOWTO (ALPHA_R_NW_RELOC, /* type */
1581 0, /* rightshift */
1582 0, /* size (0 = byte, 1 = short, 2 = long) */
1583 0, /* bitsize */
1584 false, /* pc_relative */
1585 0, /* bitpos */
1586 complain_overflow_dont, /* complain_on_overflow */
1587 0, /* special_function */
1588 "NW_RELOC", /* name */
1589 false, /* partial_inplace */
1590 0, /* src_mask */
1591 0, /* dst_mask */
1592 false); /* pcrel_offset */
1593
1594/*ARGSUSED*/
1595static void
1596alpha_mangle_relocs (outbfd, insec, relocs_ptr, reloc_count_ptr, contents,
1597 contents_size)
1598 bfd *outbfd;
1599 asection *insec;
1600 register arelent ***relocs_ptr;
ae5d2ff5 1601 long *reloc_count_ptr;
419093bc
ILT
1602 char *contents;
1603 bfd_size_type contents_size;
1604{
ae5d2ff5 1605 long old_reloc_count;
419093bc
ILT
1606 arelent **old_relocs;
1607 register arelent **relocs;
1608
1609 old_reloc_count = *reloc_count_ptr;
1610 old_relocs = *relocs_ptr;
1611 relocs = (arelent **) xmalloc ((old_reloc_count + 3) * sizeof (arelent *));
1612 *relocs_ptr = relocs;
1613
1614 if (nlm_alpha_backend_data (outbfd)->lita_address == 0)
1615 {
1616 bfd *inbfd;
1617 asection *lita_section;
1618
1619 inbfd = insec->owner;
1620 lita_section = bfd_get_section_by_name (inbfd, _LITA);
1621 if (lita_section != (asection *) NULL)
1622 {
1623 nlm_alpha_backend_data (outbfd)->lita_address =
1624 bfd_get_section_vma (inbfd, lita_section);
1625 nlm_alpha_backend_data (outbfd)->lita_size =
1626 bfd_section_size (inbfd, lita_section);
1627 }
1628 else
1629 {
1630 /* Avoid outputting this reloc again. */
1631 nlm_alpha_backend_data (outbfd)->lita_address = 4;
1632 }
1633
1634 *relocs = (arelent *) xmalloc (sizeof (arelent));
a18ff4a7 1635 (*relocs)->sym_ptr_ptr = bfd_abs_section_ptr->symbol_ptr_ptr;
419093bc
ILT
1636 (*relocs)->address = nlm_alpha_backend_data (outbfd)->lita_address;
1637 (*relocs)->addend = nlm_alpha_backend_data (outbfd)->lita_size + 1;
1638 (*relocs)->howto = &nlm32_alpha_nw_howto;
1639 ++relocs;
1640 ++(*reloc_count_ptr);
1641 }
1642
f645a4bf 1643 /* Get the GP value from bfd. */
419093bc 1644 if (nlm_alpha_backend_data (outbfd)->gp == 0)
f645a4bf
ILT
1645 nlm_alpha_backend_data (outbfd)->gp =
1646 bfd_ecoff_get_gp_value (insec->owner);
419093bc
ILT
1647
1648 *relocs = (arelent *) xmalloc (sizeof (arelent));
a18ff4a7 1649 (*relocs)->sym_ptr_ptr = bfd_abs_section_ptr->symbol_ptr_ptr;
419093bc
ILT
1650 (*relocs)->address = nlm_alpha_backend_data (outbfd)->gp;
1651 (*relocs)->addend = 0;
1652 (*relocs)->howto = &nlm32_alpha_nw_howto;
1653 ++relocs;
1654 ++(*reloc_count_ptr);
1655
1656 memcpy ((PTR) relocs, (PTR) old_relocs,
1657 (size_t) old_reloc_count * sizeof (arelent *));
1658 relocs[old_reloc_count] = (arelent *) NULL;
1659
1660 free (old_relocs);
1661
1662 if (insec->output_offset != 0)
1663 {
1664 register bfd_size_type i;
1665
1666 for (i = 0; i < old_reloc_count; i++, relocs++)
1667 (*relocs)->address += insec->output_offset;
1668 }
1669}
4bd7a65f 1670
9d11577a
ILT
1671#endif /* NLMCONV_ALPHA */
1672\f
1673#ifdef NLMCONV_POWERPC
1674
4bd7a65f
ILT
1675/* We keep a linked list of stubs which we must build. Because BFD
1676 requires us to know the sizes of all sections before we can set the
1677 contents of any, we must figure out which stubs we want to build
1678 before we can actually build any of them. */
1679
1680struct powerpc_stub
1681{
1682 /* Next stub in linked list. */
1683 struct powerpc_stub *next;
1684
1685 /* Symbol whose value is the start of the stub. This is a symbol
1686 whose name begins with `.'. */
1687 asymbol *start;
1688
1689 /* Symbol we are going to create a reloc against. This is a symbol
1690 with the same name as START but without the leading `.'. */
1691 asymbol *reloc;
1692
1693 /* The TOC index for this stub. This is the index into the TOC
1694 section at which the reloc is created. */
1695 unsigned int toc_index;
1696};
1697
1698/* The linked list of stubs. */
1699
1700static struct powerpc_stub *powerpc_stubs;
1701
1702/* This is what a stub looks like. The first instruction will get
1703 adjusted with the correct TOC index. */
1704
1705static unsigned long powerpc_stub_insns[] =
1706{
1707 0x81820000, /* lwz r12,0(r2) */
1708 0x90410014, /* stw r2,20(r1) */
1709 0x800c0000, /* lwz r0,0(r12) */
1710 0x804c0004, /* lwz r2,r(r12) */
1711 0x7c0903a6, /* mtctr r0 */
1712 0x4e800420, /* bctr */
1713 0, /* Traceback table. */
1714 0xc8000,
1715 0
1716};
1717
1718#define POWERPC_STUB_INSN_COUNT \
1719 (sizeof powerpc_stub_insns / sizeof powerpc_stub_insns[0])
1720
1721#define POWERPC_STUB_SIZE (4 * POWERPC_STUB_INSN_COUNT)
1722
1723/* Each stub uses a four byte TOC entry. */
1724#define POWERPC_STUB_TOC_ENTRY_SIZE (4)
1725
1726/* The original size of the .got section. */
1727static bfd_size_type powerpc_initial_got_size;
1728
1729/* Look for all undefined symbols beginning with `.', and prepare to
1730 build a stub for each one. */
1731
1732static void
c59fa195 1733powerpc_build_stubs (inbfd, outbfd, symbols_ptr, symcount_ptr)
4bd7a65f 1734 bfd *inbfd;
c59fa195 1735 bfd *outbfd;
4bd7a65f 1736 asymbol ***symbols_ptr;
ae5d2ff5 1737 long *symcount_ptr;
4bd7a65f
ILT
1738{
1739 asection *stub_sec;
1740 asection *got_sec;
1741 unsigned int got_base;
ae5d2ff5
ILT
1742 long i;
1743 long symcount;
1744 long stubcount;
4bd7a65f
ILT
1745
1746 /* Make a section to hold stubs. We don't set SEC_HAS_CONTENTS for
1747 the section to prevent copy_sections from reading from it. */
1748 stub_sec = bfd_make_section (inbfd, ".stubs");
1749 if (stub_sec == (asection *) NULL
1750 || ! bfd_set_section_flags (inbfd, stub_sec,
1751 (SEC_CODE
1752 | SEC_RELOC
1753 | SEC_ALLOC
1754 | SEC_LOAD))
1755 || ! bfd_set_section_alignment (inbfd, stub_sec, 2))
1756 bfd_fatal (".stubs");
1757
1758 /* Get the TOC section, which is named .got. */
1759 got_sec = bfd_get_section_by_name (inbfd, ".got");
1760 if (got_sec == (asection *) NULL)
1761 {
1762 got_sec = bfd_make_section (inbfd, ".got");
1763 if (got_sec == (asection *) NULL
1764 || ! bfd_set_section_flags (inbfd, got_sec,
1765 (SEC_DATA
1766 | SEC_RELOC
1767 | SEC_ALLOC
1768 | SEC_LOAD
1769 | SEC_HAS_CONTENTS))
1770 || ! bfd_set_section_alignment (inbfd, got_sec, 2))
1771 bfd_fatal (".got");
1772 }
1773
1774 powerpc_initial_got_size = bfd_section_size (inbfd, got_sec);
1775 got_base = powerpc_initial_got_size;
1776 got_base = (got_base + 3) &~ 3;
1777
1778 stubcount = 0;
1779
1780 symcount = *symcount_ptr;
1781 for (i = 0; i < symcount; i++)
1782 {
1783 asymbol *sym;
1784 asymbol *newsym;
1785 char *newname;
1786 struct powerpc_stub *item;
1787
1788 sym = (*symbols_ptr)[i];
1789
1790 /* We must make a stub for every undefined symbol whose name
1791 starts with '.'. */
1792 if (bfd_asymbol_name (sym)[0] != '.'
a18ff4a7 1793 || ! bfd_is_und_section (bfd_get_section (sym)))
4bd7a65f
ILT
1794 continue;
1795
1796 /* Make a new undefined symbol with the same name but without
1797 the leading `.'. */
1798 newsym = (asymbol *) xmalloc (sizeof (asymbol));
1799 *newsym = *sym;
1800 newname = (char *) xmalloc (strlen (bfd_asymbol_name (sym)));
1801 strcpy (newname, bfd_asymbol_name (sym) + 1);
1802 newsym->name = newname;
1803
1804 /* Define the `.' symbol to be in the stub section. */
1805 sym->section = stub_sec;
1806 sym->value = stubcount * POWERPC_STUB_SIZE;
ae5d2ff5
ILT
1807 /* We set the BSF_DYNAMIC flag here so that we can check it when
1808 we are mangling relocs. FIXME: This is a hack. */
1809 sym->flags = BSF_LOCAL | BSF_DYNAMIC;
4bd7a65f
ILT
1810
1811 /* Add this stub to the linked list. */
1812 item = (struct powerpc_stub *) xmalloc (sizeof (struct powerpc_stub));
1813 item->start = sym;
1814 item->reloc = newsym;
1815 item->toc_index = got_base + stubcount * POWERPC_STUB_TOC_ENTRY_SIZE;
1816
1817 item->next = powerpc_stubs;
1818 powerpc_stubs = item;
1819
1820 ++stubcount;
1821 }
1822
1823 if (stubcount > 0)
1824 {
1825 asymbol **s;
1826 struct powerpc_stub *l;
1827
1828 /* Add the new symbols we just created to the symbol table. */
1829 *symbols_ptr = (asymbol **) xrealloc ((char *) *symbols_ptr,
1830 ((symcount + stubcount)
1831 * sizeof (asymbol)));
1832 *symcount_ptr += stubcount;
1833 s = &(*symbols_ptr)[symcount];
1834 for (l = powerpc_stubs; l != (struct powerpc_stub *) NULL; l = l->next)
1835 *s++ = l->reloc;
1836
1837 /* Set the size of the .stubs section and increase the size of
1838 the .got section. */
1839 if (! bfd_set_section_size (inbfd, stub_sec,
1840 stubcount * POWERPC_STUB_SIZE)
1841 || ! bfd_set_section_size (inbfd, got_sec,
1842 (got_base
1843 + (stubcount
1844 * POWERPC_STUB_TOC_ENTRY_SIZE))))
1845 bfd_fatal ("stub section sizes");
1846 }
1847}
1848
1849/* Resolve all the stubs for PowerPC NetWare. We fill in the contents
1850 of the output section, and create new relocs in the TOC. */
1851
1852static void
1853powerpc_resolve_stubs (inbfd, outbfd)
1854 bfd *inbfd;
1855 bfd *outbfd;
1856{
1857 bfd_byte buf[POWERPC_STUB_SIZE];
1858 unsigned int i;
1859 unsigned int stubcount;
1860 arelent **relocs;
1861 asection *got_sec;
1862 arelent **r;
1863 struct powerpc_stub *l;
1864
1865 if (powerpc_stubs == (struct powerpc_stub *) NULL)
1866 return;
1867
1868 for (i = 0; i < POWERPC_STUB_INSN_COUNT; i++)
1869 bfd_put_32 (outbfd, (bfd_vma) powerpc_stub_insns[i], buf + i * 4);
1870
1871 got_sec = bfd_get_section_by_name (inbfd, ".got");
1872 assert (got_sec != (asection *) NULL);
1873 assert (got_sec->output_section->orelocation == (arelent **) NULL);
1874
1875 stubcount = 0;
1876 for (l = powerpc_stubs; l != (struct powerpc_stub *) NULL; l = l->next)
1877 ++stubcount;
1878 relocs = (arelent **) xmalloc (stubcount * sizeof (arelent *));
1879
1880 r = relocs;
1881 for (l = powerpc_stubs; l != (struct powerpc_stub *) NULL; l = l->next)
1882 {
1883 arelent *reloc;
1884
1885 /* Adjust the first instruction to use the right TOC index. */
1886 bfd_put_32 (outbfd, (bfd_vma) powerpc_stub_insns[0] + l->toc_index, buf);
1887
1888 /* Write this stub out. */
1889 if (! bfd_set_section_contents (outbfd,
1890 bfd_get_section (l->start),
1891 buf,
1892 l->start->value,
1893 POWERPC_STUB_SIZE))
1894 bfd_fatal ("writing stub");
1895
1896 /* Create a new reloc for the TOC entry. */
1897 reloc = (arelent *) xmalloc (sizeof (arelent));
1898 reloc->sym_ptr_ptr = &l->reloc;
1899 reloc->address = l->toc_index + got_sec->output_offset;
1900 reloc->addend = 0;
1901 reloc->howto = bfd_reloc_type_lookup (inbfd, BFD_RELOC_32);
1902
1903 *r++ = reloc;
1904 }
1905
1906 bfd_set_reloc (outbfd, got_sec->output_section, relocs, stubcount);
1907}
1908
1909/* Adjust relocation entries for PowerPC NetWare. We do not output
1910 TOC relocations. The object code already contains the offset from
1911 the TOC pointer. When the function is called, the TOC register,
1912 r2, will be set to the correct TOC value, so there is no need for
1913 any further reloc. */
1914
1915/*ARGSUSED*/
1916static void
1917powerpc_mangle_relocs (outbfd, insec, relocs_ptr, reloc_count_ptr, contents,
1918 contents_size)
1919 bfd *outbfd;
1920 asection *insec;
1921 register arelent ***relocs_ptr;
ae5d2ff5 1922 long *reloc_count_ptr;
4bd7a65f
ILT
1923 char *contents;
1924 bfd_size_type contents_size;
1925{
1d1a5a53 1926 reloc_howto_type *toc_howto;
ae5d2ff5 1927 long reloc_count;
4bd7a65f 1928 register arelent **relocs;
ae5d2ff5 1929 register long i;
4bd7a65f
ILT
1930
1931 toc_howto = bfd_reloc_type_lookup (insec->owner, BFD_RELOC_PPC_TOC16);
1932 if (toc_howto == (reloc_howto_type *) NULL)
1933 abort ();
1934
1935 /* If this is the .got section, clear out all the contents beyond
1936 the initial size. We must do this here because copy_sections is
1937 going to write out whatever we return in the contents field. */
1938 if (strcmp (bfd_get_section_name (insec->owner, insec), ".got") == 0)
1939 memset (contents + powerpc_initial_got_size, 0,
1d1a5a53
ILT
1940 (size_t) (bfd_get_section_size_after_reloc (insec)
1941 - powerpc_initial_got_size));
4bd7a65f
ILT
1942
1943 reloc_count = *reloc_count_ptr;
1944 relocs = *relocs_ptr;
1945 for (i = 0; i < reloc_count; i++)
1946 {
1947 arelent *rel;
1948 asymbol *sym;
1d1a5a53 1949 bfd_vma sym_value;
4bd7a65f
ILT
1950
1951 rel = *relocs++;
1952 sym = *rel->sym_ptr_ptr;
1953
1d1a5a53
ILT
1954 /* Convert any relocs against the .bss section into relocs
1955 against the .data section. */
1956 if (strcmp (bfd_get_section_name (outbfd, bfd_get_section (sym)),
1957 NLM_UNINITIALIZED_DATA_NAME) == 0)
1958 {
1959 asection *datasec;
1960
1961 datasec = bfd_get_section_by_name (outbfd,
1962 NLM_INITIALIZED_DATA_NAME);
1963 if (datasec != NULL)
1964 {
1965 rel->addend += (bfd_get_section_vma (outbfd,
1966 bfd_get_section (sym))
1967 + sym->value);
1968 rel->sym_ptr_ptr = datasec->symbol_ptr_ptr;
1969 sym = *rel->sym_ptr_ptr;
1970 }
1971 }
1972
4bd7a65f
ILT
1973 /* We must be able to resolve all PC relative relocs at this
1974 point. If we get a branch to an undefined symbol we build a
1975 stub, since NetWare will resolve undefined symbols into a
1976 pointer to a function descriptor. */
1977 if (rel->howto->pc_relative)
1978 {
1979 /* This check for whether a symbol is in the same section as
1980 the reloc will be wrong if there is a PC relative reloc
1981 between two sections both of which were placed in the
1982 same output section. This should not happen. */
1983 if (bfd_get_section (sym) != insec->output_section)
1984 fprintf (stderr, "%s: unresolved PC relative reloc against %s\n",
1985 program_name, bfd_asymbol_name (sym));
1986 else
1987 {
1988 bfd_vma val;
1989
1990 assert (rel->howto->size == 2 && rel->howto->pcrel_offset);
1991 val = bfd_get_32 (outbfd, (bfd_byte *) contents + rel->address);
1992 val = ((val &~ rel->howto->dst_mask)
1993 | (((val & rel->howto->src_mask)
1994 + (sym->value - rel->address)
1995 + rel->addend)
1996 & rel->howto->dst_mask));
1997 bfd_put_32 (outbfd, val, (bfd_byte *) contents + rel->address);
1998
ae5d2ff5
ILT
1999 /* If this reloc is against an stubbed symbol and the
2000 next instruction is
4bd7a65f
ILT
2001 cror 31,31,31
2002 then we replace the next instruction with
2003 lwz r2,20(r1)
ae5d2ff5 2004 This reloads the TOC pointer after a stub call. */
4bd7a65f 2005 if (bfd_asymbol_name (sym)[0] == '.'
ae5d2ff5 2006 && (sym->flags & BSF_DYNAMIC) != 0
4bd7a65f
ILT
2007 && (bfd_get_32 (outbfd,
2008 (bfd_byte *) contents + rel->address + 4)
2009 == 0x4ffffb82)) /* cror 31,31,31 */
2010 bfd_put_32 (outbfd, (bfd_vma) 0x80410014, /* lwz r2,20(r1) */
2011 (bfd_byte *) contents + rel->address + 4);
2012
2013 --*reloc_count_ptr;
2014 --relocs;
2015 memmove (relocs, relocs + 1,
2016 (size_t) ((reloc_count - 1) * sizeof (arelent *)));
2017 continue;
2018 }
2019 }
2020
2021 /* When considering a TOC reloc, we do not want to include the
2022 symbol value. The symbol will be start of the TOC section
2023 (which is named .got). We do want to include the addend. */
2024 if (rel->howto == toc_howto)
1d1a5a53 2025 sym_value = 0;
4bd7a65f 2026 else
1d1a5a53 2027 sym_value = sym->value;
4bd7a65f
ILT
2028
2029 /* If this is a relocation against a symbol with a value, or
2030 there is a reloc addend, we need to update the addend in the
2031 object file. */
1d1a5a53 2032 if (sym_value + rel->addend != 0)
4bd7a65f
ILT
2033 {
2034 bfd_vma val;
2035
2036 switch (rel->howto->size)
2037 {
2038 case 1:
2039 val = bfd_get_16 (outbfd,
2040 (bfd_byte *) contents + rel->address);
2041 val = ((val &~ rel->howto->dst_mask)
2042 | (((val & rel->howto->src_mask)
1d1a5a53 2043 + sym_value
4bd7a65f
ILT
2044 + rel->addend)
2045 & rel->howto->dst_mask));
2046 if ((bfd_signed_vma) val < - 0x8000
2047 || (bfd_signed_vma) val >= 0x8000)
2048 fprintf (stderr,
2049 "%s: overflow when adjusting relocation against %s\n",
2050 program_name, bfd_asymbol_name (sym));
2051 bfd_put_16 (outbfd, val, (bfd_byte *) contents + rel->address);
2052 break;
2053
2054 case 2:
2055 val = bfd_get_32 (outbfd,
2056 (bfd_byte *) contents + rel->address);
2057 val = ((val &~ rel->howto->dst_mask)
2058 | (((val & rel->howto->src_mask)
1d1a5a53 2059 + sym_value
4bd7a65f
ILT
2060 + rel->addend)
2061 & rel->howto->dst_mask));
2062 bfd_put_32 (outbfd, val, (bfd_byte *) contents + rel->address);
2063 break;
2064
2065 default:
2066 abort ();
2067 }
2068
1d1a5a53
ILT
2069 if (! bfd_is_und_section (bfd_get_section (sym)))
2070 rel->sym_ptr_ptr = bfd_get_section (sym)->symbol_ptr_ptr;
4bd7a65f
ILT
2071 rel->addend = 0;
2072 }
2073
2074 /* Now that we have incorporated the addend, remove any TOC
2075 relocs. */
2076 if (rel->howto == toc_howto)
2077 {
2078 --*reloc_count_ptr;
2079 --relocs;
2080 memmove (relocs, relocs + 1,
2081 (size_t) ((reloc_count - i) * sizeof (arelent *)));
2082 continue;
2083 }
2084
2085 rel->address += insec->output_offset;
2086 }
2087}
9d11577a
ILT
2088
2089#endif /* NLMCONV_POWERPC */
0f6df2ee
ILT
2090\f
2091/* Name of linker. */
2092#ifndef LD_NAME
2093#define LD_NAME "ld"
2094#endif
2095
2096/* Temporary file name base. */
2097static char *temp_filename;
2098
2099/* The user has specified several input files. Invoke the linker to
2100 link them all together, and convert and delete the resulting output
2101 file. */
2102
2103static char *
2104link_inputs (inputs, ld)
2105 struct string_list *inputs;
2106 char *ld;
2107{
2108 size_t c;
2109 struct string_list *q;
2110 char **argv;
2111 size_t i;
2112 int pid;
2113 int status;
1d1a5a53
ILT
2114 char *errfmt;
2115 char *errarg;
0f6df2ee
ILT
2116
2117 c = 0;
2118 for (q = inputs; q != NULL; q = q->next)
2119 ++c;
2120
1d1a5a53 2121 argv = (char **) alloca ((c + 5) * sizeof(char *));
0f6df2ee
ILT
2122
2123#ifndef __MSDOS__
2124 if (ld == NULL)
2125 {
2126 char *p;
2127
2128 /* Find the linker to invoke based on how nlmconv was run. */
2129 p = program_name + strlen (program_name);
2130 while (p != program_name)
2131 {
2132 if (p[-1] == '/')
2133 {
2134 ld = (char *) xmalloc (p - program_name + strlen (LD_NAME) + 1);
2135 memcpy (ld, program_name, p - program_name);
2136 strcpy (ld + (p - program_name), LD_NAME);
2137 break;
2138 }
2139 --p;
2140 }
2141 }
2142#endif
2143
2144 if (ld == NULL)
2145 ld = (char *) LD_NAME;
2146
1d1a5a53 2147 temp_filename = choose_temp_base ();
0f6df2ee
ILT
2148
2149 unlink_on_exit = xmalloc (strlen (temp_filename) + 3);
2150 sprintf (unlink_on_exit, "%s.O", temp_filename);
2151
2152 argv[0] = ld;
1d1a5a53 2153 argv[1] = (char *) "-Ur";
0f6df2ee
ILT
2154 argv[2] = (char *) "-o";
2155 argv[3] = unlink_on_exit;
2156 i = 4;
2157 for (q = inputs; q != NULL; q = q->next, i++)
2158 argv[i] = q->string;
2159 argv[i] = NULL;
2160
2161 if (debug)
2162 {
2163 for (i = 0; argv[i] != NULL; i++)
2164 fprintf (stderr, " %s", argv[i]);
2165 fprintf (stderr, "\n");
2166 }
2167
1d1a5a53
ILT
2168 pid = pexecute (ld, argv, program_name, (char *) NULL, &errfmt, &errarg,
2169 PEXECUTE_SEARCH | PEXECUTE_ONE);
2170 if (pid == -1)
0f6df2ee 2171 {
1d1a5a53
ILT
2172 fprintf (stderr, "%s: execution of %s failed: ", program_name, ld);
2173 fprintf (stderr, errfmt, errarg);
0f6df2ee
ILT
2174 unlink (unlink_on_exit);
2175 exit (1);
2176 }
2177
1d1a5a53 2178 if (pwait (pid, &status, 0) < 0)
0f6df2ee 2179 {
1d1a5a53 2180 perror ("pwait");
0f6df2ee
ILT
2181 unlink (unlink_on_exit);
2182 exit (1);
2183 }
2184
1d1a5a53 2185 if (status != 0)
0f6df2ee 2186 {
1d1a5a53
ILT
2187 fprintf (stderr, "%s: Execution of %s failed\n", program_name, ld);
2188 unlink (unlink_on_exit);
0f6df2ee 2189 exit (1);
0f6df2ee 2190 }
0f6df2ee 2191
1d1a5a53 2192 return unlink_on_exit;
0f6df2ee 2193}