1/* NLM (NetWare Loadable Module) executable support for BFD.
2   Copyright 1993, 1994, 1995, 1998, 2000, 2001, 2002, 2003, 2004
3   Free Software Foundation, Inc.
4
5   Written by Fred Fish @ Cygnus Support, using ELF support as the
6   template.
7
8   This file is part of BFD, the Binary File Descriptor library.
9
10   This program is free software; you can redistribute it and/or modify
11   it under the terms of the GNU General Public License as published by
12   the Free Software Foundation; either version 2 of the License, or
13   (at your option) any later version.
14
15   This program is distributed in the hope that it will be useful,
16   but WITHOUT ANY WARRANTY; without even the implied warranty of
17   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18   GNU General Public License for more details.
19
20   You should have received a copy of the GNU General Public License
21   along with this program; if not, write to the Free Software
22   Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
23
24#include "bfd.h"
25#include "sysdep.h"
26#include "libbfd.h"
27#include "libnlm.h"
28
29/* The functions in this file do not use the names they appear to use.
30   This file is actually compiled multiple times, once for each size
31   of NLM target we are using.  At each size we use a different name,
32   constructed by the macro nlmNAME.  For example, the function which
33   is named nlm_symbol_type below is actually named nlm32_symbol_type
34   in the final executable.  */
35
36#define Nlm_External_Fixed_Header	NlmNAME(External_Fixed_Header)
37#define Nlm_External_Version_Header	NlmNAME(External_Version_Header)
38#define Nlm_External_Copyright_Header	NlmNAME(External_Copyright_Header)
39#define Nlm_External_Extended_Header	NlmNAME(External_Extended_Header)
40#define Nlm_External_Custom_Header	NlmNAME(External_Custom_Header)
41#define Nlm_External_Cygnus_Ext_Header	NlmNAME(External_Cygnus_Ext_Header)
42
43#define nlm_symbol_type			nlmNAME(symbol_type)
44#define nlm_get_symtab_upper_bound	nlmNAME(get_symtab_upper_bound)
45#define nlm_canonicalize_symtab		nlmNAME(canonicalize_symtab)
46#define nlm_make_empty_symbol		nlmNAME(make_empty_symbol)
47#define nlm_print_symbol		nlmNAME(print_symbol)
48#define nlm_get_symbol_info		nlmNAME(get_symbol_info)
49#define nlm_get_reloc_upper_bound	nlmNAME(get_reloc_upper_bound)
50#define nlm_canonicalize_reloc		nlmNAME(canonicalize_reloc)
51#define nlm_object_p			nlmNAME(object_p)
52#define nlm_set_section_contents	nlmNAME(set_section_contents)
53#define nlm_write_object_contents	nlmNAME(write_object_contents)
54
55#define nlm_swap_fixed_header_in(abfd,src,dst) \
56  (nlm_swap_fixed_header_in_func(abfd)) (abfd,src,dst)
57#define nlm_swap_fixed_header_out(abfd,src,dst) \
58  (nlm_swap_fixed_header_out_func(abfd)) (abfd,src,dst)
59
60/* Forward declarations of static functions.  */
61
62static bfd_boolean add_bfd_section
63  PARAMS ((bfd *, char *, file_ptr, bfd_size_type, flagword));
64static bfd_boolean nlm_swap_variable_header_in
65  PARAMS ((bfd *));
66static bfd_boolean nlm_swap_variable_header_out
67  PARAMS ((bfd *));
68static bfd_boolean find_nonzero
69  PARAMS ((PTR, size_t));
70static bfd_boolean nlm_swap_auxiliary_headers_in
71  PARAMS ((bfd *));
72static bfd_boolean nlm_swap_auxiliary_headers_out
73  PARAMS ((bfd *));
74static bfd_boolean nlm_slurp_symbol_table
75  PARAMS ((bfd *));
76static bfd_boolean nlm_slurp_reloc_fixups
77  PARAMS ((bfd *));
78static bfd_boolean nlm_compute_section_file_positions
79  PARAMS ((bfd *));
80static int nlm_external_reloc_compare
81  PARAMS ((const void *, const void *));
82
83/* Should perhaps use put_offset, put_word, etc.  For now, the two versions
84   can be handled by explicitly specifying 32 bits or "the long type".  */
85#if ARCH_SIZE == 64
86#define put_word	H_PUT_64
87#define get_word	H_GET_64
88#endif
89#if ARCH_SIZE == 32
90#define put_word	H_PUT_32
91#define get_word	H_GET_32
92#endif
93
94const bfd_target *
95nlm_object_p (abfd)
96     bfd *abfd;
97{
98  struct nlm_obj_tdata *preserved_tdata = nlm_tdata (abfd);
99  bfd_boolean (*backend_object_p) PARAMS ((bfd *));
100  PTR x_fxdhdr = NULL;
101  Nlm_Internal_Fixed_Header *i_fxdhdrp;
102  struct nlm_obj_tdata *new_tdata = NULL;
103  const char *signature;
104  enum bfd_architecture arch;
105  bfd_size_type amt;
106
107  /* Some NLM formats have a prefix before the standard NLM fixed
108     header.  */
109  backend_object_p = nlm_backend_object_p_func (abfd);
110  if (backend_object_p)
111    {
112      if (!(*backend_object_p) (abfd))
113	goto got_wrong_format_error;
114    }
115
116  /* Read in the fixed length portion of the NLM header in external format.  */
117  amt = nlm_fixed_header_size (abfd);
118  x_fxdhdr = (PTR) bfd_malloc (amt);
119  if (x_fxdhdr == NULL)
120    goto got_no_match;
121
122  if (bfd_bread ((PTR) x_fxdhdr, amt, abfd) != amt)
123    {
124      if (bfd_get_error () != bfd_error_system_call)
125	goto got_wrong_format_error;
126      else
127	goto got_no_match;
128    }
129
130  /* Allocate an instance of the nlm_obj_tdata structure and hook it up to
131     the tdata pointer in the bfd.  */
132  amt = sizeof (struct nlm_obj_tdata);
133  new_tdata = (struct nlm_obj_tdata *) bfd_zalloc (abfd, amt);
134  if (new_tdata == NULL)
135    goto got_no_match;
136
137  nlm_tdata (abfd) = new_tdata;
138
139  i_fxdhdrp = nlm_fixed_header (abfd);
140  nlm_swap_fixed_header_in (abfd, x_fxdhdr, i_fxdhdrp);
141  free (x_fxdhdr);
142  x_fxdhdr = NULL;
143
144  /* Check to see if we have an NLM file for this backend by matching
145     the NLM signature.  */
146  signature = nlm_signature (abfd);
147  if (signature != NULL
148      && *signature != '\0'
149      && strncmp ((char *) i_fxdhdrp->signature, signature,
150		  NLM_SIGNATURE_SIZE) != 0)
151    goto got_wrong_format_error;
152
153  /* There's no supported way to discover the endianess of an NLM, so test for
154     a sane version number after doing byte swapping appropriate for this
155     XVEC.  (Hack alert!)  */
156  if (i_fxdhdrp->version > 0xFFFF)
157    goto got_wrong_format_error;
158
159  /* There's no supported way to check for 32 bit versus 64 bit addresses,
160     so ignore this distinction for now.  (FIXME) */
161  /* Swap in the rest of the required header.  */
162  if (!nlm_swap_variable_header_in (abfd))
163    {
164      if (bfd_get_error () != bfd_error_system_call)
165	goto got_wrong_format_error;
166      else
167	goto got_no_match;
168    }
169
170  /* Add the sections supplied by all NLM's, and then read in the
171     auxiliary headers.  Reading the auxiliary headers may create
172     additional sections described in the cygnus_ext header.
173     From this point on we assume that we have an NLM, and do not
174     treat errors as indicating the wrong format.  */
175  if (!add_bfd_section (abfd, NLM_CODE_NAME,
176			i_fxdhdrp->codeImageOffset,
177			i_fxdhdrp->codeImageSize,
178			(SEC_CODE | SEC_ALLOC | SEC_LOAD | SEC_HAS_CONTENTS
179			 | SEC_RELOC))
180      || !add_bfd_section (abfd, NLM_INITIALIZED_DATA_NAME,
181			   i_fxdhdrp->dataImageOffset,
182			   i_fxdhdrp->dataImageSize,
183			   (SEC_DATA | SEC_ALLOC | SEC_LOAD | SEC_HAS_CONTENTS
184			    | SEC_RELOC))
185      || !add_bfd_section (abfd, NLM_UNINITIALIZED_DATA_NAME,
186			   (file_ptr) 0,
187			   i_fxdhdrp->uninitializedDataSize,
188			   SEC_ALLOC))
189    goto got_no_match;
190
191  if (!nlm_swap_auxiliary_headers_in (abfd))
192    goto got_no_match;
193
194  if (nlm_fixed_header (abfd)->numberOfRelocationFixups != 0
195      || nlm_fixed_header (abfd)->numberOfExternalReferences != 0)
196    abfd->flags |= HAS_RELOC;
197  if (nlm_fixed_header (abfd)->numberOfPublics != 0
198      || nlm_fixed_header (abfd)->numberOfDebugRecords != 0
199      || nlm_fixed_header (abfd)->numberOfExternalReferences != 0)
200    abfd->flags |= HAS_SYMS;
201
202  arch = nlm_architecture (abfd);
203  if (arch != bfd_arch_unknown)
204    bfd_default_set_arch_mach (abfd, arch, (unsigned long) 0);
205
206  abfd->flags |= EXEC_P;
207  bfd_get_start_address (abfd) = nlm_fixed_header (abfd)->codeStartOffset;
208
209  return (abfd->xvec);
210
211got_wrong_format_error:
212  bfd_set_error (bfd_error_wrong_format);
213got_no_match:
214  nlm_tdata (abfd) = preserved_tdata;
215  if (new_tdata != NULL)
216    bfd_release (abfd, new_tdata);
217  if (x_fxdhdr != NULL)
218    free (x_fxdhdr);
219  return (NULL);
220}
221
222/* Add a section to the bfd.  */
223
224static bfd_boolean
225add_bfd_section (abfd, name, offset, size, flags)
226     bfd *abfd;
227     char *name;
228     file_ptr offset;
229     bfd_size_type size;
230     flagword flags;
231{
232  asection *newsect;
233
234  newsect = bfd_make_section (abfd, name);
235  if (newsect == NULL)
236    return FALSE;
237
238  newsect->vma = 0;		/* NLM's are relocatable.  */
239  newsect->size = size;
240  newsect->filepos = offset;
241  newsect->flags = flags;
242  newsect->alignment_power = bfd_log2 ((bfd_vma) 0);	/* FIXME */
243
244  return TRUE;
245}
246
247/* Read and swap in the variable length header.  All the fields must
248   exist in the NLM, and must exist in the order they are read here.  */
249
250static bfd_boolean
251nlm_swap_variable_header_in (abfd)
252     bfd *abfd;
253{
254  unsigned char temp[NLM_TARGET_LONG_SIZE];
255  bfd_size_type amt;
256
257  /* Read the description length and text members.  */
258
259  amt = sizeof (nlm_variable_header (abfd)->descriptionLength);
260  if (bfd_bread ((PTR) &nlm_variable_header (abfd)->descriptionLength,
261		amt, abfd) != amt)
262    return FALSE;
263  amt = nlm_variable_header (abfd)->descriptionLength + 1;
264  if (bfd_bread ((PTR) nlm_variable_header (abfd)->descriptionText,
265		amt, abfd) != amt)
266    return FALSE;
267
268  /* Read and convert the stackSize field.  */
269
270  amt = sizeof (temp);
271  if (bfd_bread ((PTR) temp, amt, abfd) != amt)
272    return FALSE;
273  nlm_variable_header (abfd)->stackSize = get_word (abfd, (bfd_byte *) temp);
274
275  /* Read and convert the reserved field.  */
276
277  amt = sizeof (temp);
278  if (bfd_bread ((PTR) temp, amt, abfd) != amt)
279    return FALSE;
280  nlm_variable_header (abfd)->reserved = get_word (abfd, (bfd_byte *) temp);
281
282  /* Read the oldThreadName field.  This field is a fixed length string.  */
283
284  amt = sizeof (nlm_variable_header (abfd)->oldThreadName);
285  if (bfd_bread ((PTR) nlm_variable_header (abfd)->oldThreadName,
286		amt, abfd) != amt)
287    return FALSE;
288
289  /* Read the screen name length and text members.  */
290
291  amt = sizeof (nlm_variable_header (abfd)->screenNameLength);
292  if (bfd_bread ((PTR) & nlm_variable_header (abfd)->screenNameLength,
293		amt, abfd) != amt)
294    return FALSE;
295  amt = nlm_variable_header (abfd)->screenNameLength + 1;
296  if (bfd_bread ((PTR) nlm_variable_header (abfd)->screenName,
297		amt, abfd) != amt)
298    return FALSE;
299
300  /* Read the thread name length and text members.  */
301
302  amt = sizeof (nlm_variable_header (abfd)->threadNameLength);
303  if (bfd_bread ((PTR) & nlm_variable_header (abfd)->threadNameLength,
304		amt, abfd) != amt)
305    return FALSE;
306  amt = nlm_variable_header (abfd)->threadNameLength + 1;
307  if (bfd_bread ((PTR) nlm_variable_header (abfd)->threadName,
308		amt, abfd) != amt)
309    return FALSE;
310  return TRUE;
311}
312
313/* Swap and write out the variable length header.  All the fields must
314   exist in the NLM, and must exist in this order.  */
315
316static bfd_boolean
317nlm_swap_variable_header_out (abfd)
318     bfd *abfd;
319{
320  unsigned char temp[NLM_TARGET_LONG_SIZE];
321  bfd_size_type amt;
322
323  /* Write the description length and text members.  */
324  amt = sizeof (nlm_variable_header (abfd)->descriptionLength);
325  if (bfd_bwrite ((PTR) & nlm_variable_header (abfd)->descriptionLength, amt,
326		 abfd) != amt)
327    return FALSE;
328  amt = nlm_variable_header (abfd)->descriptionLength + 1;
329  if (bfd_bwrite ((PTR) nlm_variable_header (abfd)->descriptionText, amt,
330		 abfd) != amt)
331    return FALSE;
332
333  /* Convert and write the stackSize field.  */
334  put_word (abfd, (bfd_vma) nlm_variable_header (abfd)->stackSize,
335	    (bfd_byte *) temp);
336  amt = sizeof (temp);
337  if (bfd_bwrite ((PTR) temp, amt, abfd) != amt)
338    return FALSE;
339
340  /* Convert and write the reserved field.  */
341  put_word (abfd, (bfd_vma) nlm_variable_header (abfd)->reserved,
342	    (bfd_byte *) temp);
343  amt = sizeof (temp);
344  if (bfd_bwrite ((PTR) temp, amt, abfd) != amt)
345    return FALSE;
346
347  /* Write the oldThreadName field.  This field is a fixed length string.  */
348  amt = sizeof (nlm_variable_header (abfd)->oldThreadName);
349  if (bfd_bwrite ((PTR) nlm_variable_header (abfd)->oldThreadName, amt,
350		 abfd) != amt)
351    return FALSE;
352
353  /* Write the screen name length and text members.  */
354  amt = sizeof (nlm_variable_header (abfd)->screenNameLength);
355  if (bfd_bwrite ((PTR) & nlm_variable_header (abfd)->screenNameLength, amt,
356		 abfd) != amt)
357    return FALSE;
358  amt = nlm_variable_header (abfd)->screenNameLength + 1;
359  if (bfd_bwrite ((PTR) nlm_variable_header (abfd)->screenName, amt,
360		 abfd) != amt)
361    return FALSE;
362
363  /* Write the thread name length and text members.  */
364  amt = sizeof (nlm_variable_header (abfd)->threadNameLength);
365  if (bfd_bwrite ((PTR) & nlm_variable_header (abfd)->threadNameLength, amt,
366		 abfd) != amt)
367    return FALSE;
368  amt = nlm_variable_header (abfd)->threadNameLength + 1;
369  if (bfd_bwrite ((PTR) nlm_variable_header (abfd)->threadName, amt,
370		 abfd) != amt)
371    return FALSE;
372  return TRUE;
373}
374
375/* Read and swap in the contents of all the auxiliary headers.  Because of
376   the braindead design, we have to do strcmps on strings of indeterminate
377   length to figure out what each auxiliary header is.  Even worse, we have
378   no way of knowing how many auxiliary headers there are or where the end
379   of the auxiliary headers are, except by finding something that doesn't
380   look like a known auxiliary header.  This means that the first new type
381   of auxiliary header added will break all existing tools that don't
382   recognize it.  */
383
384static bfd_boolean
385nlm_swap_auxiliary_headers_in (abfd)
386     bfd *abfd;
387{
388  char tempstr[16];
389  file_ptr position;
390  bfd_size_type amt;
391
392  for (;;)
393    {
394      position = bfd_tell (abfd);
395      amt = sizeof (tempstr);
396      if (bfd_bread ((PTR) tempstr, amt, abfd) != amt)
397	return FALSE;
398      if (bfd_seek (abfd, position, SEEK_SET) != 0)
399	return FALSE;
400      if (strncmp (tempstr, "VeRsIoN#", 8) == 0)
401	{
402	  Nlm_External_Version_Header thdr;
403
404	  amt = sizeof (thdr);
405	  if (bfd_bread ((PTR) &thdr, amt, abfd) != amt)
406	    return FALSE;
407	  memcpy (nlm_version_header (abfd)->stamp, thdr.stamp,
408		  sizeof (thdr.stamp));
409	  nlm_version_header (abfd)->majorVersion =
410	    get_word (abfd, (bfd_byte *) thdr.majorVersion);
411	  nlm_version_header (abfd)->minorVersion =
412	    get_word (abfd, (bfd_byte *) thdr.minorVersion);
413	  nlm_version_header (abfd)->revision =
414	    get_word (abfd, (bfd_byte *) thdr.revision);
415	  nlm_version_header (abfd)->year =
416	    get_word (abfd, (bfd_byte *) thdr.year);
417	  nlm_version_header (abfd)->month =
418	    get_word (abfd, (bfd_byte *) thdr.month);
419	  nlm_version_header (abfd)->day =
420	    get_word (abfd, (bfd_byte *) thdr.day);
421	}
422      else if (strncmp (tempstr, "MeSsAgEs", 8) == 0)
423	{
424	  Nlm_External_Extended_Header thdr;
425
426	  amt = sizeof (thdr);
427	  if (bfd_bread ((PTR) &thdr, amt, abfd) != amt)
428	    return FALSE;
429	  memcpy (nlm_extended_header (abfd)->stamp, thdr.stamp,
430		  sizeof (thdr.stamp));
431	  nlm_extended_header (abfd)->languageID =
432	    get_word (abfd, (bfd_byte *) thdr.languageID);
433	  nlm_extended_header (abfd)->messageFileOffset =
434	    get_word (abfd, (bfd_byte *) thdr.messageFileOffset);
435	  nlm_extended_header (abfd)->messageFileLength =
436	    get_word (abfd, (bfd_byte *) thdr.messageFileLength);
437	  nlm_extended_header (abfd)->messageCount =
438	    get_word (abfd, (bfd_byte *) thdr.messageCount);
439	  nlm_extended_header (abfd)->helpFileOffset =
440	    get_word (abfd, (bfd_byte *) thdr.helpFileOffset);
441	  nlm_extended_header (abfd)->helpFileLength =
442	    get_word (abfd, (bfd_byte *) thdr.helpFileLength);
443	  nlm_extended_header (abfd)->RPCDataOffset =
444	    get_word (abfd, (bfd_byte *) thdr.RPCDataOffset);
445	  nlm_extended_header (abfd)->RPCDataLength =
446	    get_word (abfd, (bfd_byte *) thdr.RPCDataLength);
447	  nlm_extended_header (abfd)->sharedCodeOffset =
448	    get_word (abfd, (bfd_byte *) thdr.sharedCodeOffset);
449	  nlm_extended_header (abfd)->sharedCodeLength =
450	    get_word (abfd, (bfd_byte *) thdr.sharedCodeLength);
451	  nlm_extended_header (abfd)->sharedDataOffset =
452	    get_word (abfd, (bfd_byte *) thdr.sharedDataOffset);
453	  nlm_extended_header (abfd)->sharedDataLength =
454	    get_word (abfd, (bfd_byte *) thdr.sharedDataLength);
455	  nlm_extended_header (abfd)->sharedRelocationFixupOffset =
456	    get_word (abfd, (bfd_byte *) thdr.sharedRelocationFixupOffset);
457	  nlm_extended_header (abfd)->sharedRelocationFixupCount =
458	    get_word (abfd, (bfd_byte *) thdr.sharedRelocationFixupCount);
459	  nlm_extended_header (abfd)->sharedExternalReferenceOffset =
460	    get_word (abfd, (bfd_byte *) thdr.sharedExternalReferenceOffset);
461	  nlm_extended_header (abfd)->sharedExternalReferenceCount =
462	    get_word (abfd, (bfd_byte *) thdr.sharedExternalReferenceCount);
463	  nlm_extended_header (abfd)->sharedPublicsOffset =
464	    get_word (abfd, (bfd_byte *) thdr.sharedPublicsOffset);
465	  nlm_extended_header (abfd)->sharedPublicsCount =
466	    get_word (abfd, (bfd_byte *) thdr.sharedPublicsCount);
467	  nlm_extended_header (abfd)->sharedDebugRecordOffset =
468	    get_word (abfd, (bfd_byte *) thdr.sharedDebugRecordOffset);
469	  nlm_extended_header (abfd)->sharedDebugRecordCount =
470	    get_word (abfd, (bfd_byte *) thdr.sharedDebugRecordCount);
471	  nlm_extended_header (abfd)->SharedInitializationOffset =
472	    get_word (abfd, (bfd_byte *) thdr.sharedInitializationOffset);
473	  nlm_extended_header (abfd)->SharedExitProcedureOffset =
474	    get_word (abfd, (bfd_byte *) thdr.SharedExitProcedureOffset);
475	  nlm_extended_header (abfd)->productID =
476	    get_word (abfd, (bfd_byte *) thdr.productID);
477	  nlm_extended_header (abfd)->reserved0 =
478	    get_word (abfd, (bfd_byte *) thdr.reserved0);
479	  nlm_extended_header (abfd)->reserved1 =
480	    get_word (abfd, (bfd_byte *) thdr.reserved1);
481	  nlm_extended_header (abfd)->reserved2 =
482	    get_word (abfd, (bfd_byte *) thdr.reserved2);
483	  nlm_extended_header (abfd)->reserved3 =
484	    get_word (abfd, (bfd_byte *) thdr.reserved3);
485	  nlm_extended_header (abfd)->reserved4 =
486	    get_word (abfd, (bfd_byte *) thdr.reserved4);
487	  nlm_extended_header (abfd)->reserved5 =
488	    get_word (abfd, (bfd_byte *) thdr.reserved5);
489	}
490      else if (strncmp (tempstr, "CoPyRiGhT=", 10) == 0)
491	{
492	  amt = sizeof (nlm_copyright_header (abfd)->stamp);
493	  if (bfd_bread ((PTR) nlm_copyright_header (abfd)->stamp,
494			amt, abfd) != amt)
495	    return FALSE;
496	  if (bfd_bread ((PTR) &(nlm_copyright_header (abfd)
497				->copyrightMessageLength),
498			(bfd_size_type) 1, abfd) != 1)
499	    return FALSE;
500	  /* The copyright message is a variable length string.  */
501	  amt = nlm_copyright_header (abfd)->copyrightMessageLength + 1;
502	  if (bfd_bread ((PTR) nlm_copyright_header (abfd)->copyrightMessage,
503			amt, abfd) != amt)
504	    return FALSE;
505	}
506      else if (strncmp (tempstr, "CuStHeAd", 8) == 0)
507	{
508	  Nlm_External_Custom_Header thdr;
509	  bfd_size_type hdrLength;
510	  file_ptr dataOffset;
511	  bfd_size_type dataLength;
512	  char dataStamp[8];
513	  PTR hdr;
514
515	  /* Read the stamp ("CuStHeAd").  */
516	  amt = sizeof (thdr.stamp);
517	  if (bfd_bread ((PTR) thdr.stamp, amt, abfd) != amt)
518	    return FALSE;
519	  /* Read the length of this custom header.  */
520	  amt = sizeof (thdr.length);
521	  if (bfd_bread ((PTR) thdr.length, amt, abfd) != amt)
522	    return FALSE;
523	  hdrLength = get_word (abfd, (bfd_byte *) thdr.length);
524	  /* Read further fields if we have them.  */
525	  if (hdrLength < NLM_TARGET_LONG_SIZE)
526	    dataOffset = 0;
527	  else
528	    {
529	      amt = sizeof (thdr.dataOffset);
530	      if (bfd_bread ((PTR) thdr.dataOffset, amt, abfd) != amt)
531		return FALSE;
532	      dataOffset = get_word (abfd, (bfd_byte *) thdr.dataOffset);
533	    }
534	  if (hdrLength < 2 * NLM_TARGET_LONG_SIZE)
535	    dataLength = 0;
536	  else
537	    {
538	      amt = sizeof (thdr.dataLength);
539	      if (bfd_bread ((PTR) thdr.dataLength, amt, abfd) != amt)
540		return FALSE;
541	      dataLength = get_word (abfd, (bfd_byte *) thdr.dataLength);
542	    }
543	  if (hdrLength < 2 * NLM_TARGET_LONG_SIZE + 8)
544	    memset (dataStamp, 0, sizeof (dataStamp));
545	  else
546	    {
547	      amt = sizeof (dataStamp);
548	      if (bfd_bread ((PTR) dataStamp, amt, abfd) != amt)
549		return FALSE;
550	    }
551
552	  /* Read the rest of the header, if any.  */
553	  if (hdrLength <= 2 * NLM_TARGET_LONG_SIZE + 8)
554	    {
555	      hdr = NULL;
556	      hdrLength = 0;
557	    }
558	  else
559	    {
560	      hdrLength -= 2 * NLM_TARGET_LONG_SIZE + 8;
561	      hdr = bfd_alloc (abfd, hdrLength);
562	      if (hdr == NULL)
563		return FALSE;
564	      if (bfd_bread (hdr, hdrLength, abfd) != hdrLength)
565		return FALSE;
566	    }
567
568	  /* If we have found a Cygnus header, process it.  Otherwise,
569	     just save the associated data without trying to interpret
570	     it.  */
571	  if (strncmp (dataStamp, "CyGnUsEx", 8) == 0)
572	    {
573	      file_ptr pos;
574	      bfd_byte *contents;
575	      bfd_byte *p, *pend;
576
577	      BFD_ASSERT (hdrLength == 0 && hdr == NULL);
578
579	      pos = bfd_tell (abfd);
580	      if (bfd_seek (abfd, dataOffset, SEEK_SET) != 0)
581		return FALSE;
582	      contents = (bfd_byte *) bfd_alloc (abfd, dataLength);
583	      if (contents == NULL)
584		return FALSE;
585	      if (bfd_bread (contents, dataLength, abfd) != dataLength)
586		return FALSE;
587	      if (bfd_seek (abfd, pos, SEEK_SET) != 0)
588		return FALSE;
589
590	      memcpy (nlm_cygnus_ext_header (abfd), "CyGnUsEx", 8);
591	      nlm_cygnus_ext_header (abfd)->offset = dataOffset;
592	      nlm_cygnus_ext_header (abfd)->length = dataLength;
593
594	      /* This data this header points to provides a list of
595		 the sections which were in the original object file
596		 which was converted to become an NLM.  We locate
597		 those sections and add them to the BFD.  Note that
598		 this is likely to create a second .text, .data and
599		 .bss section; retrieving the sections by name will
600		 get the actual NLM sections, which is what we want to
601		 happen.  The sections from the original file, which
602		 may be subsets of the NLM section, can only be found
603		 using bfd_map_over_sections.  */
604	      p = contents;
605	      pend = p + dataLength;
606	      while (p < pend)
607		{
608		  char *name;
609		  size_t l;
610		  file_ptr filepos;
611		  bfd_size_type size;
612		  asection *newsec;
613
614		  /* The format of this information is
615		     null terminated section name
616		     zeroes to adjust to 4 byte boundary
617		     4 byte section data file pointer
618		     4 byte section size
619		     */
620
621		  name = (char *) p;
622		  l = strlen (name) + 1;
623		  l = (l + 3) &~ (size_t) 3;
624		  p += l;
625		  filepos = H_GET_32 (abfd, p);
626		  p += 4;
627		  size = H_GET_32 (abfd, p);
628		  p += 4;
629
630		  newsec = bfd_make_section_anyway (abfd, name);
631		  if (newsec == (asection *) NULL)
632		    return FALSE;
633		  newsec->size = size;
634		  if (filepos != 0)
635		    {
636		      newsec->filepos = filepos;
637		      newsec->flags |= SEC_HAS_CONTENTS;
638		    }
639		}
640	    }
641	  else
642	    {
643	      memcpy (nlm_custom_header (abfd)->stamp, thdr.stamp,
644		      sizeof (thdr.stamp));
645	      nlm_custom_header (abfd)->hdrLength = hdrLength;
646	      nlm_custom_header (abfd)->dataOffset = dataOffset;
647	      nlm_custom_header (abfd)->dataLength = dataLength;
648	      memcpy (nlm_custom_header (abfd)->dataStamp, dataStamp,
649		      sizeof (dataStamp));
650	      nlm_custom_header (abfd)->hdr = hdr;
651	    }
652	}
653      else
654	break;
655    }
656  return TRUE;
657}
658
659/* Return whether there is a non-zero byte in a memory block.  */
660
661static bfd_boolean
662find_nonzero (buf, size)
663     PTR buf;
664     size_t size;
665{
666  char *p = (char *) buf;
667
668  while (size-- != 0)
669    if (*p++ != 0)
670      return TRUE;
671  return FALSE;
672}
673
674/* Swap out the contents of the auxiliary headers.  We create those
675   auxiliary headers which have been set non-zero.  We do not require
676   the caller to set up the stamp fields.  */
677
678static bfd_boolean
679nlm_swap_auxiliary_headers_out (abfd)
680     bfd *abfd;
681{
682  bfd_size_type amt;
683
684  /* Write out the version header if there is one.  */
685  if (find_nonzero ((PTR) nlm_version_header (abfd),
686		    sizeof (Nlm_Internal_Version_Header)))
687    {
688      Nlm_External_Version_Header thdr;
689
690      memcpy (thdr.stamp, "VeRsIoN#", 8);
691      put_word (abfd, (bfd_vma) nlm_version_header (abfd)->majorVersion,
692		(bfd_byte *) thdr.majorVersion);
693      put_word (abfd, (bfd_vma) nlm_version_header (abfd)->minorVersion,
694		(bfd_byte *) thdr.minorVersion);
695      put_word (abfd, (bfd_vma) nlm_version_header (abfd)->revision,
696		(bfd_byte *) thdr.revision);
697      put_word (abfd, (bfd_vma) nlm_version_header (abfd)->year,
698		(bfd_byte *) thdr.year);
699      put_word (abfd, (bfd_vma) nlm_version_header (abfd)->month,
700		(bfd_byte *) thdr.month);
701      put_word (abfd, (bfd_vma) nlm_version_header (abfd)->day,
702		(bfd_byte *) thdr.day);
703      if (bfd_bwrite ((PTR) &thdr, (bfd_size_type) sizeof (thdr), abfd)
704	  != sizeof (thdr))
705	return FALSE;
706    }
707
708  /* Note - the CoPyRiGhT tag is emitted before the MeSsAgEs
709     tag in order to make the NW4.x and NW5.x loaders happy.  */
710
711  /* Write out the copyright header if there is one.  */
712  if (find_nonzero ((PTR) nlm_copyright_header (abfd),
713		    sizeof (Nlm_Internal_Copyright_Header)))
714    {
715      Nlm_External_Copyright_Header thdr;
716
717      memcpy (thdr.stamp, "CoPyRiGhT=", 10);
718      amt = sizeof (thdr.stamp);
719      if (bfd_bwrite ((PTR) thdr.stamp, amt, abfd) != amt)
720	return FALSE;
721      thdr.copyrightMessageLength[0] =
722	nlm_copyright_header (abfd)->copyrightMessageLength;
723      amt = 1;
724      if (bfd_bwrite ((PTR) thdr.copyrightMessageLength, amt, abfd) != amt)
725	return FALSE;
726      /* The copyright message is a variable length string.  */
727      amt = nlm_copyright_header (abfd)->copyrightMessageLength + 1;
728      if (bfd_bwrite ((PTR) nlm_copyright_header (abfd)->copyrightMessage,
729		     amt, abfd) != amt)
730	return FALSE;
731    }
732
733  /* Write out the extended header if there is one.  */
734  if (find_nonzero ((PTR) nlm_extended_header (abfd),
735		    sizeof (Nlm_Internal_Extended_Header)))
736    {
737      Nlm_External_Extended_Header thdr;
738
739      memcpy (thdr.stamp, "MeSsAgEs", 8);
740      put_word (abfd,
741		(bfd_vma) nlm_extended_header (abfd)->languageID,
742		(bfd_byte *) thdr.languageID);
743      put_word (abfd,
744		(bfd_vma) nlm_extended_header (abfd)->messageFileOffset,
745		(bfd_byte *) thdr.messageFileOffset);
746      put_word (abfd,
747		(bfd_vma) nlm_extended_header (abfd)->messageFileLength,
748		(bfd_byte *) thdr.messageFileLength);
749      put_word (abfd,
750		(bfd_vma) nlm_extended_header (abfd)->messageCount,
751		(bfd_byte *) thdr.messageCount);
752      put_word (abfd,
753		(bfd_vma) nlm_extended_header (abfd)->helpFileOffset,
754		(bfd_byte *) thdr.helpFileOffset);
755      put_word (abfd,
756		(bfd_vma) nlm_extended_header (abfd)->helpFileLength,
757		(bfd_byte *) thdr.helpFileLength);
758      put_word (abfd,
759		(bfd_vma) nlm_extended_header (abfd)->RPCDataOffset,
760		(bfd_byte *) thdr.RPCDataOffset);
761      put_word (abfd,
762		(bfd_vma) nlm_extended_header (abfd)->RPCDataLength,
763		(bfd_byte *) thdr.RPCDataLength);
764      put_word (abfd,
765		(bfd_vma) nlm_extended_header (abfd)->sharedCodeOffset,
766		(bfd_byte *) thdr.sharedCodeOffset);
767      put_word (abfd,
768		(bfd_vma) nlm_extended_header (abfd)->sharedCodeLength,
769		(bfd_byte *) thdr.sharedCodeLength);
770      put_word (abfd,
771		(bfd_vma) nlm_extended_header (abfd)->sharedDataOffset,
772		(bfd_byte *) thdr.sharedDataOffset);
773      put_word (abfd,
774		(bfd_vma) nlm_extended_header (abfd)->sharedDataLength,
775		(bfd_byte *) thdr.sharedDataLength);
776      put_word (abfd,
777	  (bfd_vma) nlm_extended_header (abfd)->sharedRelocationFixupOffset,
778		(bfd_byte *) thdr.sharedRelocationFixupOffset);
779      put_word (abfd,
780	   (bfd_vma) nlm_extended_header (abfd)->sharedRelocationFixupCount,
781		(bfd_byte *) thdr.sharedRelocationFixupCount);
782      put_word (abfd,
783	(bfd_vma) nlm_extended_header (abfd)->sharedExternalReferenceOffset,
784		(bfd_byte *) thdr.sharedExternalReferenceOffset);
785      put_word (abfd,
786	 (bfd_vma) nlm_extended_header (abfd)->sharedExternalReferenceCount,
787		(bfd_byte *) thdr.sharedExternalReferenceCount);
788      put_word (abfd,
789		(bfd_vma) nlm_extended_header (abfd)->sharedPublicsOffset,
790		(bfd_byte *) thdr.sharedPublicsOffset);
791      put_word (abfd,
792		(bfd_vma) nlm_extended_header (abfd)->sharedPublicsCount,
793		(bfd_byte *) thdr.sharedPublicsCount);
794      put_word (abfd,
795	      (bfd_vma) nlm_extended_header (abfd)->sharedDebugRecordOffset,
796		(bfd_byte *) thdr.sharedDebugRecordOffset);
797      put_word (abfd,
798		(bfd_vma) nlm_extended_header (abfd)->sharedDebugRecordCount,
799		(bfd_byte *) thdr.sharedDebugRecordCount);
800      put_word (abfd,
801	   (bfd_vma) nlm_extended_header (abfd)->SharedInitializationOffset,
802		(bfd_byte *) thdr.sharedInitializationOffset);
803      put_word (abfd,
804	    (bfd_vma) nlm_extended_header (abfd)->SharedExitProcedureOffset,
805		(bfd_byte *) thdr.SharedExitProcedureOffset);
806      put_word (abfd,
807		(bfd_vma) nlm_extended_header (abfd)->productID,
808		(bfd_byte *) thdr.productID);
809      put_word (abfd,
810		(bfd_vma) nlm_extended_header (abfd)->reserved0,
811		(bfd_byte *) thdr.reserved0);
812      put_word (abfd,
813		(bfd_vma) nlm_extended_header (abfd)->reserved1,
814		(bfd_byte *) thdr.reserved1);
815      put_word (abfd,
816		(bfd_vma) nlm_extended_header (abfd)->reserved2,
817		(bfd_byte *) thdr.reserved2);
818      put_word (abfd,
819		(bfd_vma) nlm_extended_header (abfd)->reserved3,
820		(bfd_byte *) thdr.reserved3);
821      put_word (abfd,
822		(bfd_vma) nlm_extended_header (abfd)->reserved4,
823		(bfd_byte *) thdr.reserved4);
824      put_word (abfd,
825		(bfd_vma) nlm_extended_header (abfd)->reserved5,
826		(bfd_byte *) thdr.reserved5);
827      if (bfd_bwrite ((PTR) &thdr, (bfd_size_type) sizeof (thdr), abfd)
828	  != sizeof (thdr))
829	return FALSE;
830    }
831
832  /* Write out the custom header if there is one.   */
833  if (find_nonzero ((PTR) nlm_custom_header (abfd),
834		    sizeof (Nlm_Internal_Custom_Header)))
835    {
836      Nlm_External_Custom_Header thdr;
837      bfd_boolean ds;
838      bfd_size_type hdrLength;
839
840      ds = find_nonzero ((PTR) nlm_custom_header (abfd)->dataStamp,
841			 sizeof (nlm_custom_header (abfd)->dataStamp));
842      memcpy (thdr.stamp, "CuStHeAd", 8);
843      hdrLength = (2 * NLM_TARGET_LONG_SIZE + (ds ? 8 : 0)
844		   + nlm_custom_header (abfd)->hdrLength);
845      put_word (abfd, hdrLength, thdr.length);
846      put_word (abfd, (bfd_vma) nlm_custom_header (abfd)->dataOffset,
847		thdr.dataOffset);
848      put_word (abfd, (bfd_vma) nlm_custom_header (abfd)->dataLength,
849		thdr.dataLength);
850      if (! ds)
851	{
852	  BFD_ASSERT (nlm_custom_header (abfd)->hdrLength == 0);
853	  amt = sizeof (thdr) - sizeof (thdr.dataStamp);
854	  if (bfd_bwrite ((PTR) &thdr, amt, abfd) != amt)
855	    return FALSE;
856	}
857      else
858	{
859	  memcpy (thdr.dataStamp, nlm_custom_header (abfd)->dataStamp,
860		  sizeof (thdr.dataStamp));
861	  amt = sizeof (thdr);
862	  if (bfd_bwrite ((PTR) &thdr, amt, abfd) != amt)
863	    return FALSE;
864	  amt = nlm_custom_header (abfd)->hdrLength;
865	  if (bfd_bwrite (nlm_custom_header (abfd)->hdr, amt, abfd) != amt)
866	    return FALSE;
867	}
868    }
869
870  /* Write out the Cygnus debugging header if there is one.  */
871  if (find_nonzero ((PTR) nlm_cygnus_ext_header (abfd),
872		    sizeof (Nlm_Internal_Cygnus_Ext_Header)))
873    {
874      Nlm_External_Custom_Header thdr;
875
876      memcpy (thdr.stamp, "CuStHeAd", 8);
877      put_word (abfd, (bfd_vma) 2 * NLM_TARGET_LONG_SIZE + 8,
878		(bfd_byte *) thdr.length);
879      put_word (abfd, (bfd_vma) nlm_cygnus_ext_header (abfd)->offset,
880		(bfd_byte *) thdr.dataOffset);
881      put_word (abfd, (bfd_vma) nlm_cygnus_ext_header (abfd)->length,
882		(bfd_byte *) thdr.dataLength);
883      memcpy (thdr.dataStamp, "CyGnUsEx", 8);
884      amt = sizeof (thdr);
885      if (bfd_bwrite ((PTR) &thdr, amt, abfd) != amt)
886	return FALSE;
887    }
888
889  return TRUE;
890}
891
892/* We read the NLM's public symbols and use it to generate a bfd symbol
893   table (hey, it's better than nothing) on a one-for-one basis.  Thus
894   use the number of public symbols as the number of bfd symbols we will
895   have once we actually get around to reading them in.
896
897   Return the number of bytes required to hold the symtab vector, based on
898   the count plus 1, since we will NULL terminate the vector allocated based
899   on this size.  */
900
901long
902nlm_get_symtab_upper_bound (abfd)
903     bfd *abfd;
904{
905  Nlm_Internal_Fixed_Header *i_fxdhdrp;	/* Nlm file header, internal form.  */
906  long symcount;
907  long symtab_size = 0;
908
909  i_fxdhdrp = nlm_fixed_header (abfd);
910  symcount = (i_fxdhdrp->numberOfPublics
911	      + i_fxdhdrp->numberOfDebugRecords
912	      + i_fxdhdrp->numberOfExternalReferences);
913  symtab_size = (symcount + 1) * (sizeof (asymbol));
914  return (symtab_size);
915}
916
917/* Note that bfd_get_symcount is guaranteed to be zero if slurping the
918   symbol table fails.  */
919
920long
921nlm_canonicalize_symtab (abfd, alocation)
922     bfd *abfd;
923     asymbol **alocation;
924{
925  nlm_symbol_type *symbase;
926  bfd_size_type counter = 0;
927
928  if (! nlm_slurp_symbol_table (abfd))
929    return -1;
930  symbase = nlm_get_symbols (abfd);
931  while (counter < bfd_get_symcount (abfd))
932    {
933      *alocation++ = &symbase->symbol;
934      symbase++;
935      counter++;
936    }
937  *alocation = (asymbol *) NULL;
938  return bfd_get_symcount (abfd);
939}
940
941/* Make an NLM symbol.  There is nothing special to do here.  */
942
943asymbol *
944nlm_make_empty_symbol (abfd)
945     bfd *abfd;
946{
947  bfd_size_type amt = sizeof (nlm_symbol_type);
948  nlm_symbol_type *new = (nlm_symbol_type *) bfd_zalloc (abfd, amt);
949
950  if (new)
951    new->symbol.the_bfd = abfd;
952  return &new->symbol;
953}
954
955/* Get symbol information.  */
956
957void
958nlm_get_symbol_info (ignore_abfd, symbol, ret)
959     bfd *ignore_abfd ATTRIBUTE_UNUSED;
960     asymbol *symbol;
961     symbol_info *ret;
962{
963  bfd_symbol_info (symbol, ret);
964}
965
966/* Print symbol information.  */
967
968void
969nlm_print_symbol (abfd, afile, symbol, how)
970     bfd *abfd;
971     PTR afile;
972     asymbol *symbol;
973     bfd_print_symbol_type how;
974{
975  FILE *file = (FILE *) afile;
976
977  switch (how)
978    {
979    case bfd_print_symbol_name:
980    case bfd_print_symbol_more:
981      if (symbol->name)
982	fprintf (file, "%s", symbol->name);
983      break;
984    case bfd_print_symbol_all:
985      bfd_print_symbol_vandf (abfd, (PTR) file, symbol);
986      fprintf (file, " %-5s", symbol->section->name);
987      if (symbol->name)
988	fprintf (file, " %s", symbol->name);
989      break;
990    }
991}
992
993/* Slurp in nlm symbol table.
994
995   In the external (in-file) form, NLM export records are variable length,
996   with the following form:
997
998	1 byte		length of the symbol name (N)
999	N bytes		the symbol name
1000	4 bytes		the symbol offset from start of it's section
1001
1002   We also read in the debugging symbols and import records.  Import
1003   records are treated as undefined symbols.  As we read the import
1004   records we also read in the associated reloc information, which is
1005   attached to the symbol.
1006
1007   The bfd symbols are copied to SYMPTRS.
1008
1009   When we return, the bfd symcount is either zero or contains the correct
1010   number of symbols.  */
1011
1012static bfd_boolean
1013nlm_slurp_symbol_table (abfd)
1014     bfd *abfd;
1015{
1016  Nlm_Internal_Fixed_Header *i_fxdhdrp;	/* Nlm file header, internal form.  */
1017  bfd_size_type totsymcount;	/* Number of NLM symbols.  */
1018  bfd_size_type symcount;	/* Counter of NLM symbols.  */
1019  nlm_symbol_type *sym;		/* Pointer to current bfd symbol.  */
1020  unsigned char symlength;	/* Symbol length read into here.  */
1021  unsigned char symtype;	/* Type of debugging symbol.  */
1022  bfd_byte temp[NLM_TARGET_LONG_SIZE];	/* Symbol offsets read into here.  */
1023  bfd_boolean (*read_import_func) PARAMS ((bfd *, nlm_symbol_type *));
1024  bfd_boolean (*set_public_section_func) PARAMS ((bfd *, nlm_symbol_type *));
1025  bfd_size_type amt;
1026
1027  if (nlm_get_symbols (abfd) != NULL)
1028    return TRUE;
1029
1030  /* Read each raw NLM symbol, using the information to create a canonical bfd
1031     symbol table entry.
1032
1033     Note that we allocate the initial bfd canonical symbol buffer based on a
1034     one-to-one mapping of the NLM symbols to canonical symbols.  We actually
1035     use all the NLM symbols, so there will be no space left over at the end.
1036     When we have all the symbols, we build the caller's pointer vector.  */
1037
1038  abfd->symcount = 0;
1039  i_fxdhdrp = nlm_fixed_header (abfd);
1040  totsymcount = (i_fxdhdrp->numberOfPublics
1041		 + i_fxdhdrp->numberOfDebugRecords
1042		 + i_fxdhdrp->numberOfExternalReferences);
1043  if (totsymcount == 0)
1044    return TRUE;
1045
1046  if (bfd_seek (abfd, i_fxdhdrp->publicsOffset, SEEK_SET) != 0)
1047    return FALSE;
1048
1049  amt = totsymcount * sizeof (nlm_symbol_type);
1050  sym = ((nlm_symbol_type *) bfd_zalloc (abfd, amt));
1051  if (!sym)
1052    return FALSE;
1053  nlm_set_symbols (abfd, sym);
1054
1055  /* We use the bfd's symcount directly as the control count, so that early
1056     termination of the loop leaves the symcount correct for the symbols that
1057     were read.  */
1058
1059  set_public_section_func = nlm_set_public_section_func (abfd);
1060  symcount = i_fxdhdrp->numberOfPublics;
1061  while (abfd->symcount < symcount)
1062    {
1063      amt = sizeof (symlength);
1064      if (bfd_bread ((PTR) &symlength, amt, abfd) != amt)
1065	return FALSE;
1066      amt = symlength;
1067      sym->symbol.the_bfd = abfd;
1068      sym->symbol.name = bfd_alloc (abfd, amt + 1);
1069      if (!sym->symbol.name)
1070	return FALSE;
1071      if (bfd_bread ((PTR) sym->symbol.name, amt, abfd) != amt)
1072	return FALSE;
1073      /* Cast away const.  */
1074      ((char *) (sym->symbol.name))[symlength] = '\0';
1075      amt = sizeof (temp);
1076      if (bfd_bread ((PTR) temp, amt, abfd) != amt)
1077	return FALSE;
1078      sym->symbol.flags = BSF_GLOBAL | BSF_EXPORT;
1079      sym->symbol.value = get_word (abfd, temp);
1080      if (set_public_section_func)
1081	{
1082	  /* Most backends can use the code below, but unfortunately
1083	     some use a different scheme.  */
1084	  if (! (*set_public_section_func) (abfd, sym))
1085	    return FALSE;
1086	}
1087      else
1088	{
1089	  if (sym->symbol.value & NLM_HIBIT)
1090	    {
1091	      sym->symbol.value &= ~NLM_HIBIT;
1092	      sym->symbol.flags |= BSF_FUNCTION;
1093	      sym->symbol.section =
1094		bfd_get_section_by_name (abfd, NLM_CODE_NAME);
1095	    }
1096	  else
1097	    {
1098	      sym->symbol.section =
1099		bfd_get_section_by_name (abfd, NLM_INITIALIZED_DATA_NAME);
1100	    }
1101	}
1102      sym->rcnt = 0;
1103      abfd->symcount++;
1104      sym++;
1105    }
1106
1107  /* Read the debugging records.  */
1108
1109  if (i_fxdhdrp->numberOfDebugRecords > 0)
1110    {
1111      if (bfd_seek (abfd, i_fxdhdrp->debugInfoOffset, SEEK_SET) != 0)
1112	return FALSE;
1113
1114      symcount += i_fxdhdrp->numberOfDebugRecords;
1115      while (abfd->symcount < symcount)
1116	{
1117	  amt = sizeof (symtype);
1118	  if (bfd_bread ((PTR) &symtype, amt, abfd) != amt)
1119	    return FALSE;
1120	  amt = sizeof (temp);
1121	  if (bfd_bread ((PTR) temp, amt, abfd) != amt)
1122	    return FALSE;
1123	  amt = sizeof (symlength);
1124	  if (bfd_bread ((PTR) &symlength, amt, abfd) != amt)
1125	    return FALSE;
1126	  amt = symlength;
1127	  sym->symbol.the_bfd = abfd;
1128	  sym->symbol.name = bfd_alloc (abfd, amt + 1);
1129	  if (!sym->symbol.name)
1130	    return FALSE;
1131	  if (bfd_bread ((PTR) sym->symbol.name, amt, abfd) != amt)
1132	    return FALSE;
1133	  /* Cast away const.  */
1134	  ((char *) (sym->symbol.name))[symlength] = '\0';
1135	  sym->symbol.flags = BSF_LOCAL;
1136	  sym->symbol.value = get_word (abfd, temp);
1137	  if (symtype == 0)
1138	    {
1139	      sym->symbol.section =
1140		bfd_get_section_by_name (abfd, NLM_INITIALIZED_DATA_NAME);
1141	    }
1142	  else if (symtype == 1)
1143	    {
1144	      sym->symbol.flags |= BSF_FUNCTION;
1145	      sym->symbol.section =
1146		bfd_get_section_by_name (abfd, NLM_CODE_NAME);
1147	    }
1148	  else
1149	    {
1150	      sym->symbol.section = bfd_abs_section_ptr;
1151	    }
1152	  sym->rcnt = 0;
1153	  abfd->symcount++;
1154	  sym++;
1155	}
1156    }
1157
1158  /* Read in the import records.  We can only do this if we know how
1159     to read relocs for this target.  */
1160  read_import_func = nlm_read_import_func (abfd);
1161  if (read_import_func != NULL)
1162    {
1163      if (bfd_seek (abfd, i_fxdhdrp->externalReferencesOffset, SEEK_SET) != 0)
1164	return FALSE;
1165
1166      symcount += i_fxdhdrp->numberOfExternalReferences;
1167      while (abfd->symcount < symcount)
1168	{
1169	  if (! (*read_import_func) (abfd, sym))
1170	    return FALSE;
1171	  sym++;
1172	  abfd->symcount++;
1173	}
1174    }
1175
1176  return TRUE;
1177}
1178
1179/* Get the relocs for an NLM file.  There are two types of relocs.
1180   Imports are relocs against symbols defined in other NLM files.  We
1181   treat these as relocs against global symbols.  Relocation fixups
1182   are internal relocs.
1183
1184   The actual format used to store the relocs is machine specific.  */
1185
1186/* Read in the relocation fixup information.  This is stored in
1187   nlm_relocation_fixups, an array of arelent structures, and
1188   nlm_relocation_fixup_secs, an array of section pointers.  The
1189   section pointers are needed because the relocs are not sorted by
1190   section.  */
1191
1192static bfd_boolean
1193nlm_slurp_reloc_fixups (abfd)
1194     bfd *abfd;
1195{
1196  bfd_boolean (*read_func)
1197    PARAMS ((bfd *, nlm_symbol_type *, asection **, arelent *));
1198  bfd_size_type count, amt;
1199  arelent *rels;
1200  asection **secs;
1201
1202  if (nlm_relocation_fixups (abfd) != NULL)
1203    return TRUE;
1204  read_func = nlm_read_reloc_func (abfd);
1205  if (read_func == NULL)
1206    return TRUE;
1207
1208  if (bfd_seek (abfd, nlm_fixed_header (abfd)->relocationFixupOffset,
1209		SEEK_SET) != 0)
1210    return FALSE;
1211
1212  count = nlm_fixed_header (abfd)->numberOfRelocationFixups;
1213  amt = count * sizeof (arelent);
1214  rels = (arelent *) bfd_alloc (abfd, amt);
1215  amt = count * sizeof (asection *);
1216  secs = (asection **) bfd_alloc (abfd, amt);
1217  if ((rels == NULL || secs == NULL) && count != 0)
1218    return FALSE;
1219  nlm_relocation_fixups (abfd) = rels;
1220  nlm_relocation_fixup_secs (abfd) = secs;
1221
1222  /* We have to read piece by piece, because we don't know how large
1223     the machine specific reloc information is.  */
1224  while (count-- != 0)
1225    {
1226      if (! (*read_func) (abfd, (nlm_symbol_type *) NULL, secs, rels))
1227	{
1228	  nlm_relocation_fixups (abfd) = NULL;
1229	  nlm_relocation_fixup_secs (abfd) = NULL;
1230	  return FALSE;
1231	}
1232      ++secs;
1233      ++rels;
1234    }
1235
1236  return TRUE;
1237}
1238
1239/* Get the number of relocs.  This really just returns an upper bound,
1240   since it does not attempt to distinguish them based on the section.
1241   That will be handled when they are actually read.  */
1242
1243long
1244nlm_get_reloc_upper_bound (abfd, sec)
1245     bfd *abfd;
1246     asection *sec;
1247{
1248  nlm_symbol_type *syms;
1249  bfd_size_type count;
1250  unsigned int ret;
1251
1252  /* If we don't know how to read relocs, just return 0.  */
1253  if (nlm_read_reloc_func (abfd) == NULL)
1254    return -1;
1255  /* Make sure we have either the code or the data section.  */
1256  if ((bfd_get_section_flags (abfd, sec) & (SEC_CODE | SEC_DATA)) == 0)
1257    return 0;
1258
1259  syms = nlm_get_symbols (abfd);
1260  if (syms == NULL)
1261    {
1262      if (! nlm_slurp_symbol_table (abfd))
1263	return -1;
1264      syms = nlm_get_symbols (abfd);
1265    }
1266
1267  ret = nlm_fixed_header (abfd)->numberOfRelocationFixups;
1268
1269  count = bfd_get_symcount (abfd);
1270  while (count-- != 0)
1271    {
1272      ret += syms->rcnt;
1273      ++syms;
1274    }
1275
1276  return (ret + 1) * sizeof (arelent *);
1277}
1278
1279/* Get the relocs themselves.  */
1280
1281long
1282nlm_canonicalize_reloc (abfd, sec, relptr, symbols)
1283     bfd *abfd;
1284     asection *sec;
1285     arelent **relptr;
1286     asymbol **symbols;
1287{
1288  arelent *rels;
1289  asection **secs;
1290  bfd_size_type count, i;
1291  unsigned int ret;
1292
1293  /* Get the relocation fixups.  */
1294  rels = nlm_relocation_fixups (abfd);
1295  if (rels == NULL)
1296    {
1297      if (! nlm_slurp_reloc_fixups (abfd))
1298	return -1;
1299      rels = nlm_relocation_fixups (abfd);
1300    }
1301  secs = nlm_relocation_fixup_secs (abfd);
1302
1303  ret = 0;
1304  count = nlm_fixed_header (abfd)->numberOfRelocationFixups;
1305  for (i = 0; i < count; i++, rels++, secs++)
1306    {
1307      if (*secs == sec)
1308	{
1309	  *relptr++ = rels;
1310	  ++ret;
1311	}
1312    }
1313
1314  /* Get the import symbols.  */
1315  count = bfd_get_symcount (abfd);
1316  for (i = 0; i < count; i++, symbols++)
1317    {
1318      asymbol *sym;
1319
1320      sym = *symbols;
1321      if (bfd_asymbol_flavour (sym) == bfd_target_nlm_flavour)
1322	{
1323	  nlm_symbol_type *nlm_sym;
1324	  bfd_size_type j;
1325
1326	  nlm_sym = (nlm_symbol_type *) sym;
1327	  for (j = 0; j < nlm_sym->rcnt; j++)
1328	    {
1329	      if (nlm_sym->relocs[j].section == sec)
1330		{
1331		  *relptr = &nlm_sym->relocs[j].reloc;
1332		  (*relptr)->sym_ptr_ptr = symbols;
1333		  ++relptr;
1334		  ++ret;
1335		}
1336	    }
1337	}
1338    }
1339
1340  *relptr = NULL;
1341
1342  return ret;
1343}
1344
1345/* Compute the section file positions for an NLM file.  All variable
1346   length data in the file headers must be set before this function is
1347   called.  If the variable length data is changed later, the
1348   resulting object file will be incorrect.  Unfortunately, there is
1349   no way to check this.
1350
1351   This routine also sets the Size and Offset fields in the fixed
1352   header.
1353
1354   It also looks over the symbols and moves any common symbols into
1355   the .bss section; NLM has no way to represent a common symbol.
1356   This approach means that either the symbols must already have been
1357   set at this point, or there must be no common symbols.  We need to
1358   move the symbols at this point so that mangle_relocs can see the
1359   final values.  */
1360
1361static bfd_boolean
1362nlm_compute_section_file_positions (abfd)
1363     bfd *abfd;
1364{
1365  file_ptr sofar;
1366  asection *sec;
1367  bfd_vma text, data, bss;
1368  bfd_vma text_low, data_low;
1369  unsigned int text_align, data_align, other_align;
1370  file_ptr text_ptr, data_ptr, other_ptr;
1371  asection *bss_sec;
1372  asymbol **sym_ptr_ptr;
1373
1374  if (abfd->output_has_begun)
1375    return TRUE;
1376
1377  /* Make sure we have a section to hold uninitialized data.  */
1378  bss_sec = bfd_get_section_by_name (abfd, NLM_UNINITIALIZED_DATA_NAME);
1379  if (bss_sec == NULL)
1380    {
1381      if (!add_bfd_section (abfd, NLM_UNINITIALIZED_DATA_NAME,
1382			    (file_ptr) 0, (bfd_size_type) 0,
1383			    SEC_ALLOC))
1384	return FALSE;
1385      bss_sec = bfd_get_section_by_name (abfd, NLM_UNINITIALIZED_DATA_NAME);
1386    }
1387
1388  abfd->output_has_begun = TRUE;
1389
1390  /* The fixed header.  */
1391  sofar = nlm_optional_prefix_size (abfd) + nlm_fixed_header_size (abfd);
1392
1393  /* The variable header.  */
1394  sofar += (sizeof (nlm_variable_header (abfd)->descriptionLength)
1395	    + nlm_variable_header (abfd)->descriptionLength + 1
1396	    + NLM_TARGET_LONG_SIZE	/* stackSize */
1397	    + NLM_TARGET_LONG_SIZE	/* reserved */
1398	    + sizeof (nlm_variable_header (abfd)->oldThreadName)
1399	    + sizeof (nlm_variable_header (abfd)->screenNameLength)
1400	    + nlm_variable_header (abfd)->screenNameLength + 1
1401	    + sizeof (nlm_variable_header (abfd)->threadNameLength)
1402	    + nlm_variable_header (abfd)->threadNameLength + 1);
1403
1404  /* The auxiliary headers.  */
1405  if (find_nonzero ((PTR) nlm_version_header (abfd),
1406		    sizeof (Nlm_Internal_Version_Header)))
1407    sofar += sizeof (Nlm_External_Version_Header);
1408  if (find_nonzero ((PTR) nlm_extended_header (abfd),
1409		    sizeof (Nlm_Internal_Extended_Header)))
1410    sofar += sizeof (Nlm_External_Extended_Header);
1411  if (find_nonzero ((PTR) nlm_copyright_header (abfd),
1412		    sizeof (Nlm_Internal_Copyright_Header)))
1413    sofar += (sizeof (Nlm_External_Copyright_Header)
1414	      + nlm_copyright_header (abfd)->copyrightMessageLength + 1);
1415  if (find_nonzero ((PTR) nlm_custom_header (abfd),
1416		    sizeof (Nlm_Internal_Custom_Header)))
1417    sofar += (sizeof (Nlm_External_Custom_Header)
1418	      + nlm_custom_header (abfd)->hdrLength);
1419  if (find_nonzero ((PTR) nlm_cygnus_ext_header (abfd),
1420		    sizeof (Nlm_Internal_Cygnus_Ext_Header)))
1421    sofar += sizeof (Nlm_External_Custom_Header);
1422
1423  /* Compute the section file positions in two passes.  First get the
1424     sizes of the text and data sections, and then set the file
1425     positions.  This code aligns the sections in the file using the
1426     same alignment restrictions that apply to the sections in memory;
1427     this may not be necessary.  */
1428  text = 0;
1429  text_low = (bfd_vma) - 1;
1430  text_align = 0;
1431  data = 0;
1432  data_low = (bfd_vma) - 1;
1433  data_align = 0;
1434  bss = 0;
1435  other_align = 0;
1436  for (sec = abfd->sections; sec != (asection *) NULL; sec = sec->next)
1437    {
1438      flagword f;
1439
1440      sec->size = BFD_ALIGN (sec->size, 1 << sec->alignment_power);
1441
1442      f = bfd_get_section_flags (abfd, sec);
1443      if (f & SEC_CODE)
1444	{
1445	  text += sec->size;
1446	  if (bfd_get_section_vma (abfd, sec) < text_low)
1447	    text_low = bfd_get_section_vma (abfd, sec);
1448	  if (sec->alignment_power > text_align)
1449	    text_align = sec->alignment_power;
1450	}
1451      else if (f & SEC_DATA)
1452	{
1453	  data += sec->size;
1454	  if (bfd_get_section_vma (abfd, sec) < data_low)
1455	    data_low = bfd_get_section_vma (abfd, sec);
1456	  if (sec->alignment_power > data_align)
1457	    data_align = sec->alignment_power;
1458	}
1459      else if (f & SEC_HAS_CONTENTS)
1460	{
1461	  if (sec->alignment_power > other_align)
1462	    other_align = sec->alignment_power;
1463	}
1464      else if (f & SEC_ALLOC)
1465	bss += sec->size;
1466    }
1467
1468  nlm_set_text_low (abfd, text_low);
1469  nlm_set_data_low (abfd, data_low);
1470
1471  if (nlm_no_uninitialized_data (abfd))
1472    {
1473      /* This NetWare format does not use uninitialized data.  We must
1474	 increase the size of the data section.  We will never wind up
1475	 writing those file locations, so they will remain zero.  */
1476      data += bss;
1477      bss = 0;
1478    }
1479
1480  text_ptr = BFD_ALIGN (sofar, 1 << text_align);
1481  data_ptr = BFD_ALIGN (text_ptr + text, 1 << data_align);
1482  other_ptr = BFD_ALIGN (data_ptr + data, 1 << other_align);
1483
1484  /* Fill in some fields in the header for which we now have the
1485     information.  */
1486  nlm_fixed_header (abfd)->codeImageOffset = text_ptr;
1487  nlm_fixed_header (abfd)->codeImageSize = text;
1488  nlm_fixed_header (abfd)->dataImageOffset = data_ptr;
1489  nlm_fixed_header (abfd)->dataImageSize = data;
1490  nlm_fixed_header (abfd)->uninitializedDataSize = bss;
1491
1492  for (sec = abfd->sections; sec != (asection *) NULL; sec = sec->next)
1493    {
1494      flagword f;
1495
1496      f = bfd_get_section_flags (abfd, sec);
1497
1498      if (f & SEC_CODE)
1499	{
1500	  sec->filepos = text_ptr;
1501	  text_ptr += sec->size;
1502	}
1503      else if (f & SEC_DATA)
1504	{
1505	  sec->filepos = data_ptr;
1506	  data_ptr += sec->size;
1507	}
1508      else if (f & SEC_HAS_CONTENTS)
1509	{
1510	  sec->filepos = other_ptr;
1511	  other_ptr += sec->size;
1512	}
1513    }
1514
1515  nlm_fixed_header (abfd)->relocationFixupOffset = other_ptr;
1516
1517  /* Move all common symbols into the .bss section.  */
1518
1519  sym_ptr_ptr = bfd_get_outsymbols (abfd);
1520  if (sym_ptr_ptr != NULL)
1521    {
1522      asymbol **sym_end;
1523      bfd_vma add;
1524
1525      sym_end = sym_ptr_ptr + bfd_get_symcount (abfd);
1526      add = 0;
1527      for (; sym_ptr_ptr < sym_end; sym_ptr_ptr++)
1528	{
1529	  asymbol *sym;
1530	  bfd_vma size;
1531
1532	  sym = *sym_ptr_ptr;
1533
1534	  if (!bfd_is_com_section (bfd_get_section (sym)))
1535	    continue;
1536
1537	  /* Put the common symbol in the .bss section, and increase
1538	     the size of the .bss section by the size of the common
1539	     symbol (which is the old value of the symbol).  */
1540	  sym->section = bss_sec;
1541	  size = sym->value;
1542	  sym->value = bss_sec->size + add;
1543	  add += size;
1544	  add = BFD_ALIGN (add, 1 << bss_sec->alignment_power);
1545	}
1546      if (add != 0)
1547	{
1548	  if (nlm_no_uninitialized_data (abfd))
1549	    {
1550	      /* We could handle this case, but so far it hasn't been
1551		 necessary.  */
1552	      abort ();
1553	    }
1554	  nlm_fixed_header (abfd)->uninitializedDataSize += add;
1555	  bss_sec->size += add;
1556	}
1557    }
1558
1559  return TRUE;
1560}
1561
1562/* Set the contents of a section.  To do this we need to know where
1563   the section is going to be located in the output file.  That means
1564   that the sizes of all the sections must be set, and all the
1565   variable size header information must be known.  */
1566
1567bfd_boolean
1568nlm_set_section_contents (abfd, section, location, offset, count)
1569     bfd *abfd;
1570     asection *section;
1571     const PTR location;
1572     file_ptr offset;
1573     bfd_size_type count;
1574{
1575  if (! abfd->output_has_begun
1576      && ! nlm_compute_section_file_positions (abfd))
1577    return FALSE;
1578
1579  if (count == 0)
1580    return TRUE;
1581
1582  /* i386 NetWare has a very restricted set of relocs.  In order for
1583     objcopy to work, the NLM i386 backend needs a chance to rework
1584     the section contents so that its set of relocs will work.  If all
1585     the relocs are already acceptable, this will not do anything.  */
1586  if (section->reloc_count != 0)
1587    {
1588      bfd_boolean (*mangle_relocs_func)
1589	PARAMS ((bfd *, asection *, const PTR, bfd_vma, bfd_size_type));
1590
1591      mangle_relocs_func = nlm_mangle_relocs_func (abfd);
1592      if (mangle_relocs_func != NULL)
1593	{
1594	  if (!(*mangle_relocs_func) (abfd, section, location,
1595				      (bfd_vma) offset, count))
1596	    return FALSE;
1597	}
1598    }
1599
1600  if (bfd_seek (abfd, section->filepos + offset, SEEK_SET) != 0
1601      || bfd_bwrite (location, count, abfd) != count)
1602    return FALSE;
1603
1604  return TRUE;
1605}
1606
1607/* We need to sort a list of relocs associated with sections when we
1608   write out the external relocs.  */
1609
1610static int
1611nlm_external_reloc_compare (p1, p2)
1612     const void *p1;
1613     const void *p2;
1614{
1615  const struct reloc_and_sec *r1 = (const struct reloc_and_sec *) p1;
1616  const struct reloc_and_sec *r2 = (const struct reloc_and_sec *) p2;
1617  int cmp;
1618
1619  cmp = strcmp ((*r1->rel->sym_ptr_ptr)->name,
1620		(*r2->rel->sym_ptr_ptr)->name);
1621  if (cmp != 0)
1622    return cmp;
1623
1624  /* We sort by address within symbol to make the sort more stable and
1625     increase the chances that different hosts will generate bit for
1626     bit equivalent results.  */
1627  return (int) (r1->rel->address - r2->rel->address);
1628}
1629
1630/* Write out an NLM file.  We write out the information in this order:
1631     fixed header
1632     variable header
1633     auxiliary headers
1634     code sections
1635     data sections
1636     other sections (custom data, messages, help, shared NLM, RPC,
1637     		     module dependencies)
1638     relocation fixups
1639     external references (imports)
1640     public symbols (exports)
1641     debugging records
1642   This is similar to the order used by the NetWare tools; the
1643   difference is that NetWare puts the sections other than code, data
1644   and custom data at the end of the NLM.  It is convenient for us to
1645   know where the sections are going to be before worrying about the
1646   size of the other information.
1647
1648   By the time this function is called, all the section data should
1649   have been output using set_section_contents.  Note that custom
1650   data, the message file, the help file, the shared NLM file, the RPC
1651   data, and the module dependencies are all considered to be
1652   sections; the caller is responsible for filling in the offset and
1653   length fields in the NLM headers.  The relocation fixups and
1654   imports are both obtained from the list of relocs attached to each
1655   section.  The exports and debugging records are obtained from the
1656   list of outsymbols.  */
1657
1658bfd_boolean
1659nlm_write_object_contents (abfd)
1660     bfd *abfd;
1661{
1662  asection *sec;
1663  bfd_boolean (*write_import_func) PARAMS ((bfd *, asection *, arelent *));
1664  bfd_size_type external_reloc_count, internal_reloc_count, i, c;
1665  struct reloc_and_sec *external_relocs;
1666  asymbol **sym_ptr_ptr;
1667  file_ptr last;
1668  bfd_boolean (*write_prefix_func) PARAMS ((bfd *));
1669  unsigned char *fixed_header = NULL;
1670  file_ptr pos;
1671  bfd_size_type amt;
1672
1673  fixed_header = ((unsigned char *)
1674		  bfd_malloc (nlm_fixed_header_size (abfd)));
1675  if (fixed_header == NULL)
1676    goto error_return;
1677
1678  if (! abfd->output_has_begun
1679      && ! nlm_compute_section_file_positions (abfd))
1680    goto error_return;
1681
1682  /* Write out the variable length headers.  */
1683  pos = nlm_optional_prefix_size (abfd) + nlm_fixed_header_size (abfd);
1684  if (bfd_seek (abfd, pos, SEEK_SET) != 0)
1685    goto error_return;
1686  if (! nlm_swap_variable_header_out (abfd)
1687      || ! nlm_swap_auxiliary_headers_out (abfd))
1688    {
1689      bfd_set_error (bfd_error_system_call);
1690      goto error_return;
1691    }
1692
1693  /* A weak check on whether the section file positions were
1694     reasonable.  */
1695  if (bfd_tell (abfd) > (ufile_ptr) nlm_fixed_header (abfd)->codeImageOffset)
1696    {
1697      bfd_set_error (bfd_error_invalid_operation);
1698      goto error_return;
1699    }
1700
1701  /* Advance to the relocs.  */
1702  if (bfd_seek (abfd, nlm_fixed_header (abfd)->relocationFixupOffset,
1703		SEEK_SET) != 0)
1704    goto error_return;
1705
1706  /* The format of the relocation entries is dependent upon the
1707     particular target.  We use an external routine to write the reloc
1708     out.  */
1709  write_import_func = nlm_write_import_func (abfd);
1710
1711  /* Write out the internal relocation fixups.  While we're looping
1712     over the relocs, we also count the external relocs, which is
1713     needed when they are written out below.  */
1714  internal_reloc_count = 0;
1715  external_reloc_count = 0;
1716  for (sec = abfd->sections; sec != (asection *) NULL; sec = sec->next)
1717    {
1718      arelent **rel_ptr_ptr, **rel_end;
1719
1720      if (sec->reloc_count == 0)
1721	continue;
1722
1723      /* We can only represent relocs within a code or data
1724	 section.  We ignore them for a debugging section.  */
1725      if ((bfd_get_section_flags (abfd, sec) & (SEC_CODE | SEC_DATA)) == 0)
1726	continue;
1727
1728      /* We need to know how to write out imports */
1729      if (write_import_func == NULL)
1730	{
1731	  bfd_set_error (bfd_error_invalid_operation);
1732	  goto error_return;
1733	}
1734
1735      rel_ptr_ptr = sec->orelocation;
1736      rel_end = rel_ptr_ptr + sec->reloc_count;
1737      for (; rel_ptr_ptr < rel_end; rel_ptr_ptr++)
1738	{
1739	  arelent *rel;
1740	  asymbol *sym;
1741
1742	  rel = *rel_ptr_ptr;
1743	  sym = *rel->sym_ptr_ptr;
1744
1745	  if (! bfd_is_und_section (bfd_get_section (sym)))
1746	    {
1747	      ++internal_reloc_count;
1748	      if (! (*write_import_func) (abfd, sec, rel))
1749		goto error_return;
1750	    }
1751	  else
1752	    ++external_reloc_count;
1753	}
1754    }
1755  nlm_fixed_header (abfd)->numberOfRelocationFixups = internal_reloc_count;
1756
1757  /* Write out the imports (relocs against external symbols).  These
1758     are output as a symbol name followed by all the relocs for that
1759     symbol, so we must first gather together all the relocs against
1760     external symbols and sort them.  */
1761  amt = external_reloc_count * sizeof (struct reloc_and_sec);
1762  external_relocs = (struct reloc_and_sec *) bfd_alloc (abfd, amt);
1763  if (external_relocs == (struct reloc_and_sec *) NULL)
1764    goto error_return;
1765  i = 0;
1766  for (sec = abfd->sections; sec != (asection *) NULL; sec = sec->next)
1767    {
1768      arelent **rel_ptr_ptr, **rel_end;
1769
1770      if (sec->reloc_count == 0)
1771	continue;
1772
1773      rel_ptr_ptr = sec->orelocation;
1774      rel_end = rel_ptr_ptr + sec->reloc_count;
1775      for (; rel_ptr_ptr < rel_end; rel_ptr_ptr++)
1776	{
1777	  arelent *rel;
1778	  asymbol *sym;
1779
1780	  rel = *rel_ptr_ptr;
1781	  sym = *rel->sym_ptr_ptr;
1782
1783	  if (! bfd_is_und_section (bfd_get_section (sym)))
1784	    continue;
1785
1786	  external_relocs[i].rel = rel;
1787	  external_relocs[i].sec = sec;
1788	  ++i;
1789	}
1790    }
1791
1792  BFD_ASSERT (i == external_reloc_count);
1793
1794  /* Sort the external relocs by name.  */
1795  qsort ((PTR) external_relocs, (size_t) external_reloc_count,
1796	 sizeof (struct reloc_and_sec), nlm_external_reloc_compare);
1797
1798  /* Write out the external relocs.  */
1799  nlm_fixed_header (abfd)->externalReferencesOffset = bfd_tell (abfd);
1800  c = 0;
1801  i = 0;
1802  while (i < external_reloc_count)
1803    {
1804      arelent *rel;
1805      asymbol *sym;
1806      bfd_size_type j, cnt;
1807
1808      ++c;
1809
1810      rel = external_relocs[i].rel;
1811      sym = *rel->sym_ptr_ptr;
1812
1813      cnt = 0;
1814      for (j = i;
1815	   (j < external_reloc_count
1816	    && *external_relocs[j].rel->sym_ptr_ptr == sym);
1817	   j++)
1818	++cnt;
1819
1820      if (! (*nlm_write_external_func (abfd)) (abfd, cnt, sym,
1821					       &external_relocs[i]))
1822	goto error_return;
1823
1824      i += cnt;
1825    }
1826
1827  nlm_fixed_header (abfd)->numberOfExternalReferences = c;
1828
1829  /* Write out the public symbols (exports).  */
1830  sym_ptr_ptr = bfd_get_outsymbols (abfd);
1831  if (sym_ptr_ptr != (asymbol **) NULL)
1832    {
1833      bfd_vma (*get_public_offset_func) PARAMS ((bfd *, asymbol *));
1834      bfd_boolean (*write_export_func) PARAMS ((bfd *, asymbol *, bfd_vma));
1835
1836      asymbol **sym_end;
1837
1838      nlm_fixed_header (abfd)->publicsOffset = bfd_tell (abfd);
1839      get_public_offset_func = nlm_get_public_offset_func (abfd);
1840      write_export_func = nlm_write_export_func (abfd);
1841      c = 0;
1842      sym_end = sym_ptr_ptr + bfd_get_symcount (abfd);
1843      for (; sym_ptr_ptr < sym_end; sym_ptr_ptr++)
1844	{
1845	  asymbol *sym;
1846	  bfd_byte len;
1847	  bfd_vma offset;
1848	  bfd_byte temp[NLM_TARGET_LONG_SIZE];
1849
1850	  sym = *sym_ptr_ptr;
1851
1852	  if ((sym->flags & (BSF_EXPORT | BSF_GLOBAL)) == 0
1853	      || bfd_is_und_section (bfd_get_section (sym)))
1854	    continue;
1855
1856	  ++c;
1857
1858	  if (get_public_offset_func)
1859	    {
1860	      /* Most backends can use the code below, but
1861		 unfortunately some use a different scheme.  */
1862	      offset = (*get_public_offset_func) (abfd, sym);
1863	    }
1864	  else
1865	    {
1866	      offset = bfd_asymbol_value (sym);
1867	      sec = sym->section;
1868	      if (sec->flags & SEC_CODE)
1869		{
1870		  offset -= nlm_get_text_low (abfd);
1871		  offset |= NLM_HIBIT;
1872		}
1873	      else if (sec->flags & (SEC_DATA | SEC_ALLOC))
1874		{
1875		  /* SEC_ALLOC is for the .bss section.  */
1876		  offset -= nlm_get_data_low (abfd);
1877		}
1878	      else
1879		{
1880		  /* We can't handle an exported symbol that is not in
1881		     the code or data segment.  */
1882		  bfd_set_error (bfd_error_invalid_operation);
1883		  goto error_return;
1884		}
1885	    }
1886
1887	  if (write_export_func)
1888	    {
1889	      if (! (*write_export_func) (abfd, sym, offset))
1890		goto error_return;
1891	    }
1892	  else
1893	    {
1894	      len = strlen (sym->name);
1895	      if ((bfd_bwrite (&len, (bfd_size_type) sizeof (bfd_byte), abfd)
1896		   != sizeof (bfd_byte))
1897		  || bfd_bwrite (sym->name, (bfd_size_type) len, abfd) != len)
1898		goto error_return;
1899
1900	      put_word (abfd, offset, temp);
1901	      if (bfd_bwrite (temp, (bfd_size_type) sizeof (temp), abfd)
1902		  != sizeof (temp))
1903		goto error_return;
1904	    }
1905	}
1906      nlm_fixed_header (abfd)->numberOfPublics = c;
1907
1908      /* Write out the debugging records.  The NLM conversion program
1909	 wants to be able to inhibit this, so as a special hack if
1910	 debugInfoOffset is set to -1 we don't write any debugging
1911	 information.  This can not be handled by fiddling with the
1912	 symbol table, because exported symbols appear in both the
1913	 exported symbol list and the debugging information.  */
1914      if (nlm_fixed_header (abfd)->debugInfoOffset == (file_ptr) - 1)
1915	{
1916	  nlm_fixed_header (abfd)->debugInfoOffset = 0;
1917	  nlm_fixed_header (abfd)->numberOfDebugRecords = 0;
1918	}
1919      else
1920	{
1921	  nlm_fixed_header (abfd)->debugInfoOffset = bfd_tell (abfd);
1922	  c = 0;
1923	  sym_ptr_ptr = bfd_get_outsymbols (abfd);
1924	  sym_end = sym_ptr_ptr + bfd_get_symcount (abfd);
1925	  for (; sym_ptr_ptr < sym_end; sym_ptr_ptr++)
1926	    {
1927	      asymbol *sym;
1928	      bfd_byte type, len;
1929	      bfd_vma offset;
1930	      bfd_byte temp[NLM_TARGET_LONG_SIZE];
1931
1932	      sym = *sym_ptr_ptr;
1933
1934	      /* The NLM notion of a debugging symbol is actually what
1935		 BFD calls a local or global symbol.  What BFD calls a
1936		 debugging symbol NLM does not understand at all.  */
1937	      if ((sym->flags & (BSF_LOCAL | BSF_GLOBAL | BSF_EXPORT)) == 0
1938		  || (sym->flags & BSF_DEBUGGING) != 0
1939		  || bfd_is_und_section (bfd_get_section (sym)))
1940		continue;
1941
1942	      ++c;
1943
1944	      offset = bfd_asymbol_value (sym);
1945	      sec = sym->section;
1946	      if (sec->flags & SEC_CODE)
1947		{
1948		  offset -= nlm_get_text_low (abfd);
1949		  type = 1;
1950		}
1951	      else if (sec->flags & (SEC_DATA | SEC_ALLOC))
1952		{
1953		  /* SEC_ALLOC is for the .bss section.  */
1954		  offset -= nlm_get_data_low (abfd);
1955		  type = 0;
1956		}
1957	      else
1958		type = 2;
1959
1960	      /* The type is 0 for data, 1 for code, 2 for absolute.  */
1961	      if (bfd_bwrite (&type, (bfd_size_type) sizeof (bfd_byte), abfd)
1962		  != sizeof (bfd_byte))
1963		goto error_return;
1964
1965	      put_word (abfd, offset, temp);
1966	      if (bfd_bwrite (temp, (bfd_size_type) sizeof (temp), abfd)
1967		  != sizeof (temp))
1968		goto error_return;
1969
1970	      len = strlen (sym->name);
1971	      if ((bfd_bwrite (&len, (bfd_size_type) sizeof (bfd_byte), abfd)
1972		   != sizeof (bfd_byte))
1973		  || bfd_bwrite (sym->name, (bfd_size_type) len, abfd) != len)
1974		goto error_return;
1975	    }
1976	  nlm_fixed_header (abfd)->numberOfDebugRecords = c;
1977	}
1978    }
1979
1980  /* NLMLINK fills in offset values even if there is no data, so we do
1981     the same.  */
1982  last = bfd_tell (abfd);
1983  if (nlm_fixed_header (abfd)->codeImageOffset == 0)
1984    nlm_fixed_header (abfd)->codeImageOffset = last;
1985  if (nlm_fixed_header (abfd)->dataImageOffset == 0)
1986    nlm_fixed_header (abfd)->dataImageOffset = last;
1987  if (nlm_fixed_header (abfd)->customDataOffset == 0)
1988    nlm_fixed_header (abfd)->customDataOffset = last;
1989  if (nlm_fixed_header (abfd)->moduleDependencyOffset == 0)
1990    nlm_fixed_header (abfd)->moduleDependencyOffset = last;
1991  if (nlm_fixed_header (abfd)->relocationFixupOffset == 0)
1992    nlm_fixed_header (abfd)->relocationFixupOffset = last;
1993  if (nlm_fixed_header (abfd)->externalReferencesOffset == 0)
1994    nlm_fixed_header (abfd)->externalReferencesOffset = last;
1995  if (nlm_fixed_header (abfd)->publicsOffset == 0)
1996    nlm_fixed_header (abfd)->publicsOffset = last;
1997  if (nlm_fixed_header (abfd)->debugInfoOffset == 0)
1998    nlm_fixed_header (abfd)->debugInfoOffset = last;
1999
2000  /* At this point everything has been written out except the fixed
2001     header.  */
2002  memcpy (nlm_fixed_header (abfd)->signature, nlm_signature (abfd),
2003	  NLM_SIGNATURE_SIZE);
2004  nlm_fixed_header (abfd)->version = NLM_HEADER_VERSION;
2005  nlm_fixed_header (abfd)->codeStartOffset =
2006    (bfd_get_start_address (abfd)
2007     - nlm_get_text_low (abfd));
2008
2009  /* We have no convenient way for the caller to pass in the exit
2010     procedure or the check unload procedure, so the caller must set
2011     the values in the header to the values of the symbols.  */
2012  nlm_fixed_header (abfd)->exitProcedureOffset -= nlm_get_text_low (abfd);
2013  if (nlm_fixed_header (abfd)->checkUnloadProcedureOffset != 0)
2014    nlm_fixed_header (abfd)->checkUnloadProcedureOffset -=
2015      nlm_get_text_low (abfd);
2016
2017  if (bfd_seek (abfd, (file_ptr) 0, SEEK_SET) != 0)
2018    goto error_return;
2019
2020  write_prefix_func = nlm_write_prefix_func (abfd);
2021  if (write_prefix_func)
2022    {
2023      if (! (*write_prefix_func) (abfd))
2024	goto error_return;
2025    }
2026
2027  BFD_ASSERT ((bfd_size_type) bfd_tell (abfd)
2028	      == nlm_optional_prefix_size (abfd));
2029
2030  nlm_swap_fixed_header_out (abfd, nlm_fixed_header (abfd), fixed_header);
2031  if (bfd_bwrite (fixed_header, nlm_fixed_header_size (abfd), abfd)
2032      != nlm_fixed_header_size (abfd))
2033    goto error_return;
2034
2035  if (fixed_header != NULL)
2036    free (fixed_header);
2037  return TRUE;
2038
2039error_return:
2040  if (fixed_header != NULL)
2041    free (fixed_header);
2042  return FALSE;
2043}
2044