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