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