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