OSDN Git Service

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