OSDN Git Service

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