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