1 /* NLM (NetWare Loadable Module) executable support for BFD.
2    Copyright 1993, 1994, 1995, 1998, 2000, 2001, 2002, 2003
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 
62 static bfd_boolean add_bfd_section
63   PARAMS ((bfd *, char *, file_ptr, bfd_size_type, flagword));
64 static bfd_boolean nlm_swap_variable_header_in
65   PARAMS ((bfd *));
66 static bfd_boolean nlm_swap_variable_header_out
67   PARAMS ((bfd *));
68 static bfd_boolean find_nonzero
69   PARAMS ((PTR, size_t));
70 static bfd_boolean nlm_swap_auxiliary_headers_in
71   PARAMS ((bfd *));
72 static bfd_boolean nlm_swap_auxiliary_headers_out
73   PARAMS ((bfd *));
74 static bfd_boolean nlm_slurp_symbol_table
75   PARAMS ((bfd *));
76 static bfd_boolean nlm_slurp_reloc_fixups
77   PARAMS ((bfd *));
78 static bfd_boolean nlm_compute_section_file_positions
79   PARAMS ((bfd *));
80 static 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 
94 const bfd_target *
nlm_object_p(abfd)95 nlm_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 
211 got_wrong_format_error:
212   bfd_set_error (bfd_error_wrong_format);
213 got_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 
224 static bfd_boolean
add_bfd_section(abfd,name,offset,size,flags)225 add_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->_raw_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 
250 static bfd_boolean
nlm_swap_variable_header_in(abfd)251 nlm_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 
316 static bfd_boolean
nlm_swap_variable_header_out(abfd)317 nlm_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 
384 static bfd_boolean
nlm_swap_auxiliary_headers_in(abfd)385 nlm_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->_raw_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 
661 static bfd_boolean
find_nonzero(buf,size)662 find_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 
678 static bfd_boolean
nlm_swap_auxiliary_headers_out(abfd)679 nlm_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 
901 long
nlm_get_symtab_upper_bound(abfd)902 nlm_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 
920 long
nlm_canonicalize_symtab(abfd,alocation)921 nlm_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 
943 asymbol *
nlm_make_empty_symbol(abfd)944 nlm_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 
957 void
nlm_get_symbol_info(ignore_abfd,symbol,ret)958 nlm_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 
968 void
nlm_print_symbol(abfd,afile,symbol,how)969 nlm_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 
1012 static bfd_boolean
nlm_slurp_symbol_table(abfd)1013 nlm_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 
1192 static bfd_boolean
nlm_slurp_reloc_fixups(abfd)1193 nlm_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 
1243 long
nlm_get_reloc_upper_bound(abfd,sec)1244 nlm_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 
1281 long
nlm_canonicalize_reloc(abfd,sec,relptr,symbols)1282 nlm_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 
1361 static bfd_boolean
nlm_compute_section_file_positions(abfd)1362 nlm_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->_raw_size = BFD_ALIGN (sec->_raw_size, 1 << sec->alignment_power);
1441 
1442       f = bfd_get_section_flags (abfd, sec);
1443       if (f & SEC_CODE)
1444 	{
1445 	  text += sec->_raw_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->_raw_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->_raw_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->_raw_size;
1502 	}
1503       else if (f & SEC_DATA)
1504 	{
1505 	  sec->filepos = data_ptr;
1506 	  data_ptr += sec->_raw_size;
1507 	}
1508       else if (f & SEC_HAS_CONTENTS)
1509 	{
1510 	  sec->filepos = other_ptr;
1511 	  other_ptr += sec->_raw_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->_raw_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->_raw_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 
1567 bfd_boolean
nlm_set_section_contents(abfd,section,location,offset,count)1568 nlm_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 
1610 static int
nlm_external_reloc_compare(p1,p2)1611 nlm_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 
1658 bfd_boolean
nlm_write_object_contents(abfd)1659 nlm_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 
2039 error_return:
2040   if (fixed_header != NULL)
2041     free (fixed_header);
2042   return FALSE;
2043 }
2044