2009-06-12 Tristan Gingold <gingold@adacore.com>
[binutils.git] / bfd / nlmcode.h
blob21d22363533acae37ec28e80a0dad8ef148c0b5e
1 /* NLM (NetWare Loadable Module) executable support for BFD.
2 Copyright 1993, 1994, 1995, 1998, 1999, 2000, 2001, 2002, 2003, 2004,
3 2005, 2006, 2007 Free Software Foundation, Inc.
5 Written by Fred Fish @ Cygnus Support, using ELF support as the
6 template.
8 This file is part of BFD, the Binary File Descriptor library.
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 3 of the License, or
13 (at your option) any later version.
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.
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., 51 Franklin Street - Fifth Floor, Boston,
23 MA 02110-1301, USA. */
25 #include "sysdep.h"
26 #include "bfd.h"
27 #include "libbfd.h"
28 #include "libnlm.h"
30 /* The functions in this file do not use the names they appear to use.
31 This file is actually compiled multiple times, once for each size
32 of NLM target we are using. At each size we use a different name,
33 constructed by the macro nlmNAME. For example, the function which
34 is named nlm_symbol_type below is actually named nlm32_symbol_type
35 in the final executable. */
37 #define Nlm_External_Fixed_Header NlmNAME (External_Fixed_Header)
38 #define Nlm_External_Version_Header NlmNAME (External_Version_Header)
39 #define Nlm_External_Copyright_Header NlmNAME (External_Copyright_Header)
40 #define Nlm_External_Extended_Header NlmNAME (External_Extended_Header)
41 #define Nlm_External_Custom_Header NlmNAME (External_Custom_Header)
42 #define Nlm_External_Cygnus_Ext_Header NlmNAME (External_Cygnus_Ext_Header)
44 #define nlm_symbol_type nlmNAME (symbol_type)
45 #define nlm_get_symtab_upper_bound nlmNAME (get_symtab_upper_bound)
46 #define nlm_canonicalize_symtab nlmNAME (canonicalize_symtab)
47 #define nlm_make_empty_symbol nlmNAME (make_empty_symbol)
48 #define nlm_print_symbol nlmNAME (print_symbol)
49 #define nlm_get_symbol_info nlmNAME (get_symbol_info)
50 #define nlm_get_reloc_upper_bound nlmNAME (get_reloc_upper_bound)
51 #define nlm_canonicalize_reloc nlmNAME (canonicalize_reloc)
52 #define nlm_object_p nlmNAME (object_p)
53 #define nlm_set_section_contents nlmNAME (set_section_contents)
54 #define nlm_write_object_contents nlmNAME (write_object_contents)
56 #define nlm_swap_fixed_header_in(abfd,src,dst) \
57 (nlm_swap_fixed_header_in_func (abfd)) (abfd, src, dst)
58 #define nlm_swap_fixed_header_out(abfd,src,dst) \
59 (nlm_swap_fixed_header_out_func (abfd)) (abfd, src, dst)
61 /* Should perhaps use put_offset, put_word, etc. For now, the two versions
62 can be handled by explicitly specifying 32 bits or "the long type". */
63 #if ARCH_SIZE == 64
64 #define put_word H_PUT_64
65 #define get_word H_GET_64
66 #endif
67 #if ARCH_SIZE == 32
68 #define put_word H_PUT_32
69 #define get_word H_GET_32
70 #endif
72 /* Read and swap in the variable length header. All the fields must
73 exist in the NLM, and must exist in the order they are read here. */
75 static bfd_boolean
76 nlm_swap_variable_header_in (bfd *abfd)
78 unsigned char temp[NLM_TARGET_LONG_SIZE];
79 bfd_size_type amt;
81 /* Read the description length and text members. */
82 amt = sizeof (nlm_variable_header (abfd)->descriptionLength);
83 if (bfd_bread ((void *) &nlm_variable_header (abfd)->descriptionLength,
84 amt, abfd) != amt)
85 return FALSE;
86 amt = nlm_variable_header (abfd)->descriptionLength + 1;
87 if (bfd_bread ((void *) nlm_variable_header (abfd)->descriptionText,
88 amt, abfd) != amt)
89 return FALSE;
91 /* Read and convert the stackSize field. */
92 amt = sizeof (temp);
93 if (bfd_bread ((void *) temp, amt, abfd) != amt)
94 return FALSE;
95 nlm_variable_header (abfd)->stackSize = get_word (abfd, (bfd_byte *) temp);
97 /* Read and convert the reserved field. */
98 amt = sizeof (temp);
99 if (bfd_bread ((void *) temp, amt, abfd) != amt)
100 return FALSE;
101 nlm_variable_header (abfd)->reserved = get_word (abfd, (bfd_byte *) temp);
103 /* Read the oldThreadName field. This field is a fixed length string. */
104 amt = sizeof (nlm_variable_header (abfd)->oldThreadName);
105 if (bfd_bread ((void *) nlm_variable_header (abfd)->oldThreadName,
106 amt, abfd) != amt)
107 return FALSE;
109 /* Read the screen name length and text members. */
110 amt = sizeof (nlm_variable_header (abfd)->screenNameLength);
111 if (bfd_bread ((void *) & nlm_variable_header (abfd)->screenNameLength,
112 amt, abfd) != amt)
113 return FALSE;
114 amt = nlm_variable_header (abfd)->screenNameLength + 1;
115 if (bfd_bread ((void *) nlm_variable_header (abfd)->screenName,
116 amt, abfd) != amt)
117 return FALSE;
119 /* Read the thread name length and text members. */
120 amt = sizeof (nlm_variable_header (abfd)->threadNameLength);
121 if (bfd_bread ((void *) & nlm_variable_header (abfd)->threadNameLength,
122 amt, abfd) != amt)
123 return FALSE;
124 amt = nlm_variable_header (abfd)->threadNameLength + 1;
125 if (bfd_bread ((void *) nlm_variable_header (abfd)->threadName,
126 amt, abfd) != amt)
127 return FALSE;
128 return TRUE;
131 /* Add a section to the bfd. */
133 static bfd_boolean
134 add_bfd_section (bfd *abfd,
135 char *name,
136 file_ptr offset,
137 bfd_size_type size,
138 flagword flags)
140 asection *newsect;
142 newsect = bfd_make_section_with_flags (abfd, name, flags);
143 if (newsect == NULL)
144 return FALSE;
146 newsect->vma = 0; /* NLM's are relocatable. */
147 newsect->size = size;
148 newsect->filepos = offset;
149 newsect->alignment_power = bfd_log2 ((bfd_vma) 0); /* FIXME */
151 return TRUE;
154 /* Read and swap in the contents of all the auxiliary headers. Because of
155 the braindead design, we have to do strcmps on strings of indeterminate
156 length to figure out what each auxiliary header is. Even worse, we have
157 no way of knowing how many auxiliary headers there are or where the end
158 of the auxiliary headers are, except by finding something that doesn't
159 look like a known auxiliary header. This means that the first new type
160 of auxiliary header added will break all existing tools that don't
161 recognize it. */
163 static bfd_boolean
164 nlm_swap_auxiliary_headers_in (bfd *abfd)
166 char tempstr[16];
167 file_ptr position;
168 bfd_size_type amt;
170 for (;;)
172 position = bfd_tell (abfd);
173 amt = sizeof (tempstr);
174 if (bfd_bread ((void *) tempstr, amt, abfd) != amt)
175 return FALSE;
176 if (bfd_seek (abfd, position, SEEK_SET) != 0)
177 return FALSE;
178 if (CONST_STRNEQ (tempstr, "VeRsIoN#"))
180 Nlm_External_Version_Header thdr;
182 amt = sizeof (thdr);
183 if (bfd_bread ((void *) &thdr, amt, abfd) != amt)
184 return FALSE;
185 memcpy (nlm_version_header (abfd)->stamp, thdr.stamp,
186 sizeof (thdr.stamp));
187 nlm_version_header (abfd)->majorVersion =
188 get_word (abfd, (bfd_byte *) thdr.majorVersion);
189 nlm_version_header (abfd)->minorVersion =
190 get_word (abfd, (bfd_byte *) thdr.minorVersion);
191 nlm_version_header (abfd)->revision =
192 get_word (abfd, (bfd_byte *) thdr.revision);
193 nlm_version_header (abfd)->year =
194 get_word (abfd, (bfd_byte *) thdr.year);
195 nlm_version_header (abfd)->month =
196 get_word (abfd, (bfd_byte *) thdr.month);
197 nlm_version_header (abfd)->day =
198 get_word (abfd, (bfd_byte *) thdr.day);
200 else if (CONST_STRNEQ (tempstr, "MeSsAgEs"))
202 Nlm_External_Extended_Header thdr;
204 amt = sizeof (thdr);
205 if (bfd_bread ((void *) &thdr, amt, abfd) != amt)
206 return FALSE;
207 memcpy (nlm_extended_header (abfd)->stamp, thdr.stamp,
208 sizeof (thdr.stamp));
209 nlm_extended_header (abfd)->languageID =
210 get_word (abfd, (bfd_byte *) thdr.languageID);
211 nlm_extended_header (abfd)->messageFileOffset =
212 get_word (abfd, (bfd_byte *) thdr.messageFileOffset);
213 nlm_extended_header (abfd)->messageFileLength =
214 get_word (abfd, (bfd_byte *) thdr.messageFileLength);
215 nlm_extended_header (abfd)->messageCount =
216 get_word (abfd, (bfd_byte *) thdr.messageCount);
217 nlm_extended_header (abfd)->helpFileOffset =
218 get_word (abfd, (bfd_byte *) thdr.helpFileOffset);
219 nlm_extended_header (abfd)->helpFileLength =
220 get_word (abfd, (bfd_byte *) thdr.helpFileLength);
221 nlm_extended_header (abfd)->RPCDataOffset =
222 get_word (abfd, (bfd_byte *) thdr.RPCDataOffset);
223 nlm_extended_header (abfd)->RPCDataLength =
224 get_word (abfd, (bfd_byte *) thdr.RPCDataLength);
225 nlm_extended_header (abfd)->sharedCodeOffset =
226 get_word (abfd, (bfd_byte *) thdr.sharedCodeOffset);
227 nlm_extended_header (abfd)->sharedCodeLength =
228 get_word (abfd, (bfd_byte *) thdr.sharedCodeLength);
229 nlm_extended_header (abfd)->sharedDataOffset =
230 get_word (abfd, (bfd_byte *) thdr.sharedDataOffset);
231 nlm_extended_header (abfd)->sharedDataLength =
232 get_word (abfd, (bfd_byte *) thdr.sharedDataLength);
233 nlm_extended_header (abfd)->sharedRelocationFixupOffset =
234 get_word (abfd, (bfd_byte *) thdr.sharedRelocationFixupOffset);
235 nlm_extended_header (abfd)->sharedRelocationFixupCount =
236 get_word (abfd, (bfd_byte *) thdr.sharedRelocationFixupCount);
237 nlm_extended_header (abfd)->sharedExternalReferenceOffset =
238 get_word (abfd, (bfd_byte *) thdr.sharedExternalReferenceOffset);
239 nlm_extended_header (abfd)->sharedExternalReferenceCount =
240 get_word (abfd, (bfd_byte *) thdr.sharedExternalReferenceCount);
241 nlm_extended_header (abfd)->sharedPublicsOffset =
242 get_word (abfd, (bfd_byte *) thdr.sharedPublicsOffset);
243 nlm_extended_header (abfd)->sharedPublicsCount =
244 get_word (abfd, (bfd_byte *) thdr.sharedPublicsCount);
245 nlm_extended_header (abfd)->sharedDebugRecordOffset =
246 get_word (abfd, (bfd_byte *) thdr.sharedDebugRecordOffset);
247 nlm_extended_header (abfd)->sharedDebugRecordCount =
248 get_word (abfd, (bfd_byte *) thdr.sharedDebugRecordCount);
249 nlm_extended_header (abfd)->SharedInitializationOffset =
250 get_word (abfd, (bfd_byte *) thdr.sharedInitializationOffset);
251 nlm_extended_header (abfd)->SharedExitProcedureOffset =
252 get_word (abfd, (bfd_byte *) thdr.SharedExitProcedureOffset);
253 nlm_extended_header (abfd)->productID =
254 get_word (abfd, (bfd_byte *) thdr.productID);
255 nlm_extended_header (abfd)->reserved0 =
256 get_word (abfd, (bfd_byte *) thdr.reserved0);
257 nlm_extended_header (abfd)->reserved1 =
258 get_word (abfd, (bfd_byte *) thdr.reserved1);
259 nlm_extended_header (abfd)->reserved2 =
260 get_word (abfd, (bfd_byte *) thdr.reserved2);
261 nlm_extended_header (abfd)->reserved3 =
262 get_word (abfd, (bfd_byte *) thdr.reserved3);
263 nlm_extended_header (abfd)->reserved4 =
264 get_word (abfd, (bfd_byte *) thdr.reserved4);
265 nlm_extended_header (abfd)->reserved5 =
266 get_word (abfd, (bfd_byte *) thdr.reserved5);
268 else if (CONST_STRNEQ (tempstr, "CoPyRiGhT="))
270 amt = sizeof (nlm_copyright_header (abfd)->stamp);
271 if (bfd_bread ((void *) nlm_copyright_header (abfd)->stamp,
272 amt, abfd) != amt)
273 return FALSE;
274 if (bfd_bread ((void *) &(nlm_copyright_header (abfd)
275 ->copyrightMessageLength),
276 (bfd_size_type) 1, abfd) != 1)
277 return FALSE;
278 /* The copyright message is a variable length string. */
279 amt = nlm_copyright_header (abfd)->copyrightMessageLength + 1;
280 if (bfd_bread ((void *) nlm_copyright_header (abfd)->copyrightMessage,
281 amt, abfd) != amt)
282 return FALSE;
284 else if (CONST_STRNEQ (tempstr, "CuStHeAd"))
286 Nlm_External_Custom_Header thdr;
287 bfd_size_type hdrLength;
288 file_ptr dataOffset;
289 bfd_size_type dataLength;
290 char dataStamp[8];
291 void * hdr;
293 /* Read the stamp ("CuStHeAd"). */
294 amt = sizeof (thdr.stamp);
295 if (bfd_bread ((void *) thdr.stamp, amt, abfd) != amt)
296 return FALSE;
297 /* Read the length of this custom header. */
298 amt = sizeof (thdr.length);
299 if (bfd_bread ((void *) thdr.length, amt, abfd) != amt)
300 return FALSE;
301 hdrLength = get_word (abfd, (bfd_byte *) thdr.length);
302 /* Read further fields if we have them. */
303 if (hdrLength < NLM_TARGET_LONG_SIZE)
304 dataOffset = 0;
305 else
307 amt = sizeof (thdr.dataOffset);
308 if (bfd_bread ((void *) thdr.dataOffset, amt, abfd) != amt)
309 return FALSE;
310 dataOffset = get_word (abfd, (bfd_byte *) thdr.dataOffset);
312 if (hdrLength < 2 * NLM_TARGET_LONG_SIZE)
313 dataLength = 0;
314 else
316 amt = sizeof (thdr.dataLength);
317 if (bfd_bread ((void *) thdr.dataLength, amt, abfd) != amt)
318 return FALSE;
319 dataLength = get_word (abfd, (bfd_byte *) thdr.dataLength);
321 if (hdrLength < 2 * NLM_TARGET_LONG_SIZE + 8)
322 memset (dataStamp, 0, sizeof (dataStamp));
323 else
325 amt = sizeof (dataStamp);
326 if (bfd_bread ((void *) dataStamp, amt, abfd) != amt)
327 return FALSE;
330 /* Read the rest of the header, if any. */
331 if (hdrLength <= 2 * NLM_TARGET_LONG_SIZE + 8)
333 hdr = NULL;
334 hdrLength = 0;
336 else
338 hdrLength -= 2 * NLM_TARGET_LONG_SIZE + 8;
339 hdr = bfd_alloc (abfd, hdrLength);
340 if (hdr == NULL)
341 return FALSE;
342 if (bfd_bread (hdr, hdrLength, abfd) != hdrLength)
343 return FALSE;
346 /* If we have found a Cygnus header, process it. Otherwise,
347 just save the associated data without trying to interpret
348 it. */
349 if (CONST_STRNEQ (dataStamp, "CyGnUsEx"))
351 file_ptr pos;
352 bfd_byte *contents;
353 bfd_byte *p, *pend;
355 BFD_ASSERT (hdrLength == 0 && hdr == NULL);
357 pos = bfd_tell (abfd);
358 if (bfd_seek (abfd, dataOffset, SEEK_SET) != 0)
359 return FALSE;
360 contents = bfd_alloc (abfd, dataLength);
361 if (contents == NULL)
362 return FALSE;
363 if (bfd_bread (contents, dataLength, abfd) != dataLength)
364 return FALSE;
365 if (bfd_seek (abfd, pos, SEEK_SET) != 0)
366 return FALSE;
368 LITMEMCPY (nlm_cygnus_ext_header (abfd), "CyGnUsEx");
369 nlm_cygnus_ext_header (abfd)->offset = dataOffset;
370 nlm_cygnus_ext_header (abfd)->length = dataLength;
372 /* This data this header points to provides a list of
373 the sections which were in the original object file
374 which was converted to become an NLM. We locate
375 those sections and add them to the BFD. Note that
376 this is likely to create a second .text, .data and
377 .bss section; retrieving the sections by name will
378 get the actual NLM sections, which is what we want to
379 happen. The sections from the original file, which
380 may be subsets of the NLM section, can only be found
381 using bfd_map_over_sections. */
382 p = contents;
383 pend = p + dataLength;
384 while (p < pend)
386 char *name;
387 size_t l;
388 file_ptr filepos;
389 bfd_size_type size;
390 asection *newsec;
392 /* The format of this information is
393 null terminated section name
394 zeroes to adjust to 4 byte boundary
395 4 byte section data file pointer
396 4 byte section size. */
398 name = (char *) p;
399 l = strlen (name) + 1;
400 l = (l + 3) &~ (size_t) 3;
401 p += l;
402 filepos = H_GET_32 (abfd, p);
403 p += 4;
404 size = H_GET_32 (abfd, p);
405 p += 4;
407 newsec = bfd_make_section_anyway (abfd, name);
408 if (newsec == NULL)
409 return FALSE;
410 newsec->size = size;
411 if (filepos != 0)
413 newsec->filepos = filepos;
414 newsec->flags |= SEC_HAS_CONTENTS;
418 else
420 memcpy (nlm_custom_header (abfd)->stamp, thdr.stamp,
421 sizeof (thdr.stamp));
422 nlm_custom_header (abfd)->hdrLength = hdrLength;
423 nlm_custom_header (abfd)->dataOffset = dataOffset;
424 nlm_custom_header (abfd)->dataLength = dataLength;
425 memcpy (nlm_custom_header (abfd)->dataStamp, dataStamp,
426 sizeof (dataStamp));
427 nlm_custom_header (abfd)->hdr = hdr;
430 else
431 break;
433 return TRUE;
436 const bfd_target *
437 nlm_object_p (bfd *abfd)
439 struct nlm_obj_tdata *preserved_tdata = nlm_tdata (abfd);
440 bfd_boolean (*backend_object_p) (bfd *);
441 void * x_fxdhdr = NULL;
442 Nlm_Internal_Fixed_Header *i_fxdhdrp;
443 struct nlm_obj_tdata *new_tdata = NULL;
444 const char *signature;
445 enum bfd_architecture arch;
446 bfd_size_type amt;
448 /* Some NLM formats have a prefix before the standard NLM fixed
449 header. */
450 backend_object_p = nlm_backend_object_p_func (abfd);
451 if (backend_object_p)
453 if (!(*backend_object_p) (abfd))
454 goto got_wrong_format_error;
457 /* Read in the fixed length portion of the NLM header in external format. */
458 amt = nlm_fixed_header_size (abfd);
459 x_fxdhdr = bfd_malloc (amt);
460 if (x_fxdhdr == NULL)
461 goto got_no_match;
463 if (bfd_bread ((void *) x_fxdhdr, amt, abfd) != amt)
465 if (bfd_get_error () != bfd_error_system_call)
466 goto got_wrong_format_error;
467 else
468 goto got_no_match;
471 /* Allocate an instance of the nlm_obj_tdata structure and hook it up to
472 the tdata pointer in the bfd. */
473 amt = sizeof (struct nlm_obj_tdata);
474 new_tdata = bfd_zalloc (abfd, amt);
475 if (new_tdata == NULL)
476 goto got_no_match;
478 nlm_tdata (abfd) = new_tdata;
480 i_fxdhdrp = nlm_fixed_header (abfd);
481 nlm_swap_fixed_header_in (abfd, x_fxdhdr, i_fxdhdrp);
482 free (x_fxdhdr);
483 x_fxdhdr = NULL;
485 /* Check to see if we have an NLM file for this backend by matching
486 the NLM signature. */
487 signature = nlm_signature (abfd);
488 if (signature != NULL
489 && *signature != '\0'
490 && strncmp ((char *) i_fxdhdrp->signature, signature,
491 NLM_SIGNATURE_SIZE) != 0)
492 goto got_wrong_format_error;
494 /* There's no supported way to discover the endianess of an NLM, so test for
495 a sane version number after doing byte swapping appropriate for this
496 XVEC. (Hack alert!) */
497 if (i_fxdhdrp->version > 0xFFFF)
498 goto got_wrong_format_error;
500 /* There's no supported way to check for 32 bit versus 64 bit addresses,
501 so ignore this distinction for now. (FIXME) */
502 /* Swap in the rest of the required header. */
503 if (!nlm_swap_variable_header_in (abfd))
505 if (bfd_get_error () != bfd_error_system_call)
506 goto got_wrong_format_error;
507 else
508 goto got_no_match;
511 /* Add the sections supplied by all NLM's, and then read in the
512 auxiliary headers. Reading the auxiliary headers may create
513 additional sections described in the cygnus_ext header.
514 From this point on we assume that we have an NLM, and do not
515 treat errors as indicating the wrong format. */
516 if (!add_bfd_section (abfd, NLM_CODE_NAME,
517 i_fxdhdrp->codeImageOffset,
518 i_fxdhdrp->codeImageSize,
519 (SEC_CODE | SEC_ALLOC | SEC_LOAD | SEC_HAS_CONTENTS
520 | SEC_RELOC))
521 || !add_bfd_section (abfd, NLM_INITIALIZED_DATA_NAME,
522 i_fxdhdrp->dataImageOffset,
523 i_fxdhdrp->dataImageSize,
524 (SEC_DATA | SEC_ALLOC | SEC_LOAD | SEC_HAS_CONTENTS
525 | SEC_RELOC))
526 || !add_bfd_section (abfd, NLM_UNINITIALIZED_DATA_NAME,
527 (file_ptr) 0,
528 i_fxdhdrp->uninitializedDataSize,
529 SEC_ALLOC))
530 goto got_no_match;
532 if (!nlm_swap_auxiliary_headers_in (abfd))
533 goto got_no_match;
535 if (nlm_fixed_header (abfd)->numberOfRelocationFixups != 0
536 || nlm_fixed_header (abfd)->numberOfExternalReferences != 0)
537 abfd->flags |= HAS_RELOC;
538 if (nlm_fixed_header (abfd)->numberOfPublics != 0
539 || nlm_fixed_header (abfd)->numberOfDebugRecords != 0
540 || nlm_fixed_header (abfd)->numberOfExternalReferences != 0)
541 abfd->flags |= HAS_SYMS;
543 arch = nlm_architecture (abfd);
544 if (arch != bfd_arch_unknown)
545 bfd_default_set_arch_mach (abfd, arch, (unsigned long) 0);
547 abfd->flags |= EXEC_P;
548 bfd_get_start_address (abfd) = nlm_fixed_header (abfd)->codeStartOffset;
550 return abfd->xvec;
552 got_wrong_format_error:
553 bfd_set_error (bfd_error_wrong_format);
554 got_no_match:
555 nlm_tdata (abfd) = preserved_tdata;
556 if (new_tdata != NULL)
557 bfd_release (abfd, new_tdata);
558 if (x_fxdhdr != NULL)
559 free (x_fxdhdr);
561 return NULL;
564 /* Swap and write out the variable length header. All the fields must
565 exist in the NLM, and must exist in this order. */
567 static bfd_boolean
568 nlm_swap_variable_header_out (bfd *abfd)
570 bfd_byte temp[NLM_TARGET_LONG_SIZE];
571 bfd_size_type amt;
573 /* Write the description length and text members. */
574 amt = sizeof (nlm_variable_header (abfd)->descriptionLength);
575 if (bfd_bwrite (& nlm_variable_header (abfd)->descriptionLength, amt,
576 abfd) != amt)
577 return FALSE;
578 amt = nlm_variable_header (abfd)->descriptionLength + 1;
579 if (bfd_bwrite ((void *) nlm_variable_header (abfd)->descriptionText, amt,
580 abfd) != amt)
581 return FALSE;
583 /* Convert and write the stackSize field. */
584 put_word (abfd, (bfd_vma) nlm_variable_header (abfd)->stackSize, temp);
585 amt = sizeof (temp);
586 if (bfd_bwrite (temp, amt, abfd) != amt)
587 return FALSE;
589 /* Convert and write the reserved field. */
590 put_word (abfd, (bfd_vma) nlm_variable_header (abfd)->reserved, temp);
591 amt = sizeof (temp);
592 if (bfd_bwrite (temp, amt, abfd) != amt)
593 return FALSE;
595 /* Write the oldThreadName field. This field is a fixed length string. */
596 amt = sizeof (nlm_variable_header (abfd)->oldThreadName);
597 if (bfd_bwrite (nlm_variable_header (abfd)->oldThreadName, amt,
598 abfd) != amt)
599 return FALSE;
601 /* Write the screen name length and text members. */
602 amt = sizeof (nlm_variable_header (abfd)->screenNameLength);
603 if (bfd_bwrite (& nlm_variable_header (abfd)->screenNameLength, amt,
604 abfd) != amt)
605 return FALSE;
606 amt = nlm_variable_header (abfd)->screenNameLength + 1;
607 if (bfd_bwrite (nlm_variable_header (abfd)->screenName, amt, abfd) != amt)
608 return FALSE;
610 /* Write the thread name length and text members. */
611 amt = sizeof (nlm_variable_header (abfd)->threadNameLength);
612 if (bfd_bwrite (& nlm_variable_header (abfd)->threadNameLength, amt,
613 abfd) != amt)
614 return FALSE;
615 amt = nlm_variable_header (abfd)->threadNameLength + 1;
616 if (bfd_bwrite (nlm_variable_header (abfd)->threadName, amt, abfd) != amt)
617 return FALSE;
618 return TRUE;
621 /* Return whether there is a non-zero byte in a memory block. */
623 static bfd_boolean
624 find_nonzero (void * buf, size_t size)
626 char *p = (char *) buf;
628 while (size-- != 0)
629 if (*p++ != 0)
630 return TRUE;
631 return FALSE;
634 /* Swap out the contents of the auxiliary headers. We create those
635 auxiliary headers which have been set non-zero. We do not require
636 the caller to set up the stamp fields. */
638 static bfd_boolean
639 nlm_swap_auxiliary_headers_out (bfd *abfd)
641 bfd_size_type amt;
643 /* Write out the version header if there is one. */
644 if (find_nonzero (nlm_version_header (abfd),
645 sizeof (Nlm_Internal_Version_Header)))
647 Nlm_External_Version_Header thdr;
649 LITMEMCPY (thdr.stamp, "VeRsIoN#");
650 put_word (abfd, (bfd_vma) nlm_version_header (abfd)->majorVersion,
651 (bfd_byte *) thdr.majorVersion);
652 put_word (abfd, (bfd_vma) nlm_version_header (abfd)->minorVersion,
653 (bfd_byte *) thdr.minorVersion);
654 put_word (abfd, (bfd_vma) nlm_version_header (abfd)->revision,
655 (bfd_byte *) thdr.revision);
656 put_word (abfd, (bfd_vma) nlm_version_header (abfd)->year,
657 (bfd_byte *) thdr.year);
658 put_word (abfd, (bfd_vma) nlm_version_header (abfd)->month,
659 (bfd_byte *) thdr.month);
660 put_word (abfd, (bfd_vma) nlm_version_header (abfd)->day,
661 (bfd_byte *) thdr.day);
662 if (bfd_bwrite ((void *) &thdr, (bfd_size_type) sizeof (thdr), abfd)
663 != sizeof (thdr))
664 return FALSE;
667 /* Note - the CoPyRiGhT tag is emitted before the MeSsAgEs
668 tag in order to make the NW4.x and NW5.x loaders happy. */
670 /* Write out the copyright header if there is one. */
671 if (find_nonzero (nlm_copyright_header (abfd),
672 sizeof (Nlm_Internal_Copyright_Header)))
674 Nlm_External_Copyright_Header thdr;
676 LITMEMCPY (thdr.stamp, "CoPyRiGhT=");
677 amt = sizeof (thdr.stamp);
678 if (bfd_bwrite ((void *) thdr.stamp, amt, abfd) != amt)
679 return FALSE;
680 thdr.copyrightMessageLength[0] =
681 nlm_copyright_header (abfd)->copyrightMessageLength;
682 amt = 1;
683 if (bfd_bwrite ((void *) thdr.copyrightMessageLength, amt, abfd) != amt)
684 return FALSE;
685 /* The copyright message is a variable length string. */
686 amt = nlm_copyright_header (abfd)->copyrightMessageLength + 1;
687 if (bfd_bwrite ((void *) nlm_copyright_header (abfd)->copyrightMessage,
688 amt, abfd) != amt)
689 return FALSE;
692 /* Write out the extended header if there is one. */
693 if (find_nonzero (nlm_extended_header (abfd),
694 sizeof (Nlm_Internal_Extended_Header)))
696 Nlm_External_Extended_Header thdr;
698 LITMEMCPY (thdr.stamp, "MeSsAgEs");
699 put_word (abfd,
700 (bfd_vma) nlm_extended_header (abfd)->languageID,
701 (bfd_byte *) thdr.languageID);
702 put_word (abfd,
703 (bfd_vma) nlm_extended_header (abfd)->messageFileOffset,
704 (bfd_byte *) thdr.messageFileOffset);
705 put_word (abfd,
706 (bfd_vma) nlm_extended_header (abfd)->messageFileLength,
707 (bfd_byte *) thdr.messageFileLength);
708 put_word (abfd,
709 (bfd_vma) nlm_extended_header (abfd)->messageCount,
710 (bfd_byte *) thdr.messageCount);
711 put_word (abfd,
712 (bfd_vma) nlm_extended_header (abfd)->helpFileOffset,
713 (bfd_byte *) thdr.helpFileOffset);
714 put_word (abfd,
715 (bfd_vma) nlm_extended_header (abfd)->helpFileLength,
716 (bfd_byte *) thdr.helpFileLength);
717 put_word (abfd,
718 (bfd_vma) nlm_extended_header (abfd)->RPCDataOffset,
719 (bfd_byte *) thdr.RPCDataOffset);
720 put_word (abfd,
721 (bfd_vma) nlm_extended_header (abfd)->RPCDataLength,
722 (bfd_byte *) thdr.RPCDataLength);
723 put_word (abfd,
724 (bfd_vma) nlm_extended_header (abfd)->sharedCodeOffset,
725 (bfd_byte *) thdr.sharedCodeOffset);
726 put_word (abfd,
727 (bfd_vma) nlm_extended_header (abfd)->sharedCodeLength,
728 (bfd_byte *) thdr.sharedCodeLength);
729 put_word (abfd,
730 (bfd_vma) nlm_extended_header (abfd)->sharedDataOffset,
731 (bfd_byte *) thdr.sharedDataOffset);
732 put_word (abfd,
733 (bfd_vma) nlm_extended_header (abfd)->sharedDataLength,
734 (bfd_byte *) thdr.sharedDataLength);
735 put_word (abfd,
736 (bfd_vma) nlm_extended_header (abfd)->sharedRelocationFixupOffset,
737 (bfd_byte *) thdr.sharedRelocationFixupOffset);
738 put_word (abfd,
739 (bfd_vma) nlm_extended_header (abfd)->sharedRelocationFixupCount,
740 (bfd_byte *) thdr.sharedRelocationFixupCount);
741 put_word (abfd,
742 (bfd_vma) nlm_extended_header (abfd)->sharedExternalReferenceOffset,
743 (bfd_byte *) thdr.sharedExternalReferenceOffset);
744 put_word (abfd,
745 (bfd_vma) nlm_extended_header (abfd)->sharedExternalReferenceCount,
746 (bfd_byte *) thdr.sharedExternalReferenceCount);
747 put_word (abfd,
748 (bfd_vma) nlm_extended_header (abfd)->sharedPublicsOffset,
749 (bfd_byte *) thdr.sharedPublicsOffset);
750 put_word (abfd,
751 (bfd_vma) nlm_extended_header (abfd)->sharedPublicsCount,
752 (bfd_byte *) thdr.sharedPublicsCount);
753 put_word (abfd,
754 (bfd_vma) nlm_extended_header (abfd)->sharedDebugRecordOffset,
755 (bfd_byte *) thdr.sharedDebugRecordOffset);
756 put_word (abfd,
757 (bfd_vma) nlm_extended_header (abfd)->sharedDebugRecordCount,
758 (bfd_byte *) thdr.sharedDebugRecordCount);
759 put_word (abfd,
760 (bfd_vma) nlm_extended_header (abfd)->SharedInitializationOffset,
761 (bfd_byte *) thdr.sharedInitializationOffset);
762 put_word (abfd,
763 (bfd_vma) nlm_extended_header (abfd)->SharedExitProcedureOffset,
764 (bfd_byte *) thdr.SharedExitProcedureOffset);
765 put_word (abfd,
766 (bfd_vma) nlm_extended_header (abfd)->productID,
767 (bfd_byte *) thdr.productID);
768 put_word (abfd,
769 (bfd_vma) nlm_extended_header (abfd)->reserved0,
770 (bfd_byte *) thdr.reserved0);
771 put_word (abfd,
772 (bfd_vma) nlm_extended_header (abfd)->reserved1,
773 (bfd_byte *) thdr.reserved1);
774 put_word (abfd,
775 (bfd_vma) nlm_extended_header (abfd)->reserved2,
776 (bfd_byte *) thdr.reserved2);
777 put_word (abfd,
778 (bfd_vma) nlm_extended_header (abfd)->reserved3,
779 (bfd_byte *) thdr.reserved3);
780 put_word (abfd,
781 (bfd_vma) nlm_extended_header (abfd)->reserved4,
782 (bfd_byte *) thdr.reserved4);
783 put_word (abfd,
784 (bfd_vma) nlm_extended_header (abfd)->reserved5,
785 (bfd_byte *) thdr.reserved5);
786 if (bfd_bwrite ((void *) &thdr, (bfd_size_type) sizeof (thdr), abfd)
787 != sizeof (thdr))
788 return FALSE;
791 /* Write out the custom header if there is one. */
792 if (find_nonzero (nlm_custom_header (abfd),
793 sizeof (Nlm_Internal_Custom_Header)))
795 Nlm_External_Custom_Header thdr;
796 bfd_boolean ds;
797 bfd_size_type hdrLength;
799 ds = find_nonzero (nlm_custom_header (abfd)->dataStamp,
800 sizeof (nlm_custom_header (abfd)->dataStamp));
801 LITMEMCPY (thdr.stamp, "CuStHeAd");
802 hdrLength = (2 * NLM_TARGET_LONG_SIZE + (ds ? 8 : 0)
803 + nlm_custom_header (abfd)->hdrLength);
804 put_word (abfd, hdrLength, thdr.length);
805 put_word (abfd, (bfd_vma) nlm_custom_header (abfd)->dataOffset,
806 thdr.dataOffset);
807 put_word (abfd, (bfd_vma) nlm_custom_header (abfd)->dataLength,
808 thdr.dataLength);
809 if (! ds)
811 BFD_ASSERT (nlm_custom_header (abfd)->hdrLength == 0);
812 amt = sizeof (thdr) - sizeof (thdr.dataStamp);
813 if (bfd_bwrite ((void *) &thdr, amt, abfd) != amt)
814 return FALSE;
816 else
818 memcpy (thdr.dataStamp, nlm_custom_header (abfd)->dataStamp,
819 sizeof (thdr.dataStamp));
820 amt = sizeof (thdr);
821 if (bfd_bwrite ((void *) &thdr, amt, abfd) != amt)
822 return FALSE;
823 amt = nlm_custom_header (abfd)->hdrLength;
824 if (bfd_bwrite (nlm_custom_header (abfd)->hdr, amt, abfd) != amt)
825 return FALSE;
829 /* Write out the Cygnus debugging header if there is one. */
830 if (find_nonzero (nlm_cygnus_ext_header (abfd),
831 sizeof (Nlm_Internal_Cygnus_Ext_Header)))
833 Nlm_External_Custom_Header thdr;
835 LITMEMCPY (thdr.stamp, "CuStHeAd");
836 put_word (abfd, (bfd_vma) 2 * NLM_TARGET_LONG_SIZE + 8,
837 (bfd_byte *) thdr.length);
838 put_word (abfd, (bfd_vma) nlm_cygnus_ext_header (abfd)->offset,
839 (bfd_byte *) thdr.dataOffset);
840 put_word (abfd, (bfd_vma) nlm_cygnus_ext_header (abfd)->length,
841 (bfd_byte *) thdr.dataLength);
842 LITMEMCPY (thdr.dataStamp, "CyGnUsEx");
843 amt = sizeof (thdr);
844 if (bfd_bwrite ((void *) &thdr, amt, abfd) != amt)
845 return FALSE;
848 return TRUE;
851 /* We read the NLM's public symbols and use it to generate a bfd symbol
852 table (hey, it's better than nothing) on a one-for-one basis. Thus
853 use the number of public symbols as the number of bfd symbols we will
854 have once we actually get around to reading them in.
856 Return the number of bytes required to hold the symtab vector, based on
857 the count plus 1, since we will NULL terminate the vector allocated based
858 on this size. */
860 long
861 nlm_get_symtab_upper_bound (bfd *abfd)
863 Nlm_Internal_Fixed_Header *i_fxdhdrp; /* Nlm file header, internal form. */
864 long symcount;
865 long symtab_size = 0;
867 i_fxdhdrp = nlm_fixed_header (abfd);
868 symcount = (i_fxdhdrp->numberOfPublics
869 + i_fxdhdrp->numberOfDebugRecords
870 + i_fxdhdrp->numberOfExternalReferences);
871 symtab_size = (symcount + 1) * (sizeof (asymbol));
872 return symtab_size;
875 /* Slurp in nlm symbol table.
877 In the external (in-file) form, NLM export records are variable length,
878 with the following form:
880 1 byte length of the symbol name (N)
881 N bytes the symbol name
882 4 bytes the symbol offset from start of it's section
884 We also read in the debugging symbols and import records. Import
885 records are treated as undefined symbols. As we read the import
886 records we also read in the associated reloc information, which is
887 attached to the symbol.
889 The bfd symbols are copied to SYMvoid *S.
891 When we return, the bfd symcount is either zero or contains the correct
892 number of symbols. */
894 static bfd_boolean
895 nlm_slurp_symbol_table (bfd *abfd)
897 Nlm_Internal_Fixed_Header *i_fxdhdrp; /* Nlm file header, internal form. */
898 bfd_size_type totsymcount; /* Number of NLM symbols. */
899 bfd_size_type symcount; /* Counter of NLM symbols. */
900 nlm_symbol_type *sym; /* Pointer to current bfd symbol. */
901 unsigned char symlength; /* Symbol length read into here. */
902 unsigned char symtype; /* Type of debugging symbol. */
903 bfd_byte temp[NLM_TARGET_LONG_SIZE]; /* Symbol offsets read into here. */
904 bfd_boolean (*read_import_func) (bfd *, nlm_symbol_type *);
905 bfd_boolean (*set_public_section_func) (bfd *, nlm_symbol_type *);
906 bfd_size_type amt;
908 if (nlm_get_symbols (abfd) != NULL)
909 return TRUE;
911 /* Read each raw NLM symbol, using the information to create a canonical bfd
912 symbol table entry.
914 Note that we allocate the initial bfd canonical symbol buffer based on a
915 one-to-one mapping of the NLM symbols to canonical symbols. We actually
916 use all the NLM symbols, so there will be no space left over at the end.
917 When we have all the symbols, we build the caller's pointer vector. */
919 abfd->symcount = 0;
920 i_fxdhdrp = nlm_fixed_header (abfd);
921 totsymcount = (i_fxdhdrp->numberOfPublics
922 + i_fxdhdrp->numberOfDebugRecords
923 + i_fxdhdrp->numberOfExternalReferences);
924 if (totsymcount == 0)
925 return TRUE;
927 if (bfd_seek (abfd, i_fxdhdrp->publicsOffset, SEEK_SET) != 0)
928 return FALSE;
930 amt = totsymcount * sizeof (nlm_symbol_type);
931 sym = bfd_zalloc (abfd, amt);
932 if (!sym)
933 return FALSE;
934 nlm_set_symbols (abfd, sym);
936 /* We use the bfd's symcount directly as the control count, so that early
937 termination of the loop leaves the symcount correct for the symbols that
938 were read. */
940 set_public_section_func = nlm_set_public_section_func (abfd);
941 symcount = i_fxdhdrp->numberOfPublics;
942 while (abfd->symcount < symcount)
944 amt = sizeof (symlength);
945 if (bfd_bread ((void *) &symlength, amt, abfd) != amt)
946 return FALSE;
947 amt = symlength;
948 sym->symbol.the_bfd = abfd;
949 sym->symbol.name = bfd_alloc (abfd, amt + 1);
950 if (!sym->symbol.name)
951 return FALSE;
952 if (bfd_bread ((void *) sym->symbol.name, amt, abfd) != amt)
953 return FALSE;
954 /* Cast away const. */
955 ((char *) (sym->symbol.name))[symlength] = '\0';
956 amt = sizeof (temp);
957 if (bfd_bread ((void *) temp, amt, abfd) != amt)
958 return FALSE;
959 sym->symbol.flags = BSF_GLOBAL | BSF_EXPORT;
960 sym->symbol.value = get_word (abfd, temp);
961 if (set_public_section_func)
963 /* Most backends can use the code below, but unfortunately
964 some use a different scheme. */
965 if (! (*set_public_section_func) (abfd, sym))
966 return FALSE;
968 else
970 if (sym->symbol.value & NLM_HIBIT)
972 sym->symbol.value &= ~NLM_HIBIT;
973 sym->symbol.flags |= BSF_FUNCTION;
974 sym->symbol.section =
975 bfd_get_section_by_name (abfd, NLM_CODE_NAME);
977 else
978 sym->symbol.section =
979 bfd_get_section_by_name (abfd, NLM_INITIALIZED_DATA_NAME);
981 sym->rcnt = 0;
982 abfd->symcount++;
983 sym++;
986 /* Read the debugging records. */
988 if (i_fxdhdrp->numberOfDebugRecords > 0)
990 if (bfd_seek (abfd, i_fxdhdrp->debugInfoOffset, SEEK_SET) != 0)
991 return FALSE;
993 symcount += i_fxdhdrp->numberOfDebugRecords;
994 while (abfd->symcount < symcount)
996 amt = sizeof (symtype);
997 if (bfd_bread ((void *) &symtype, amt, abfd) != amt)
998 return FALSE;
999 amt = sizeof (temp);
1000 if (bfd_bread ((void *) temp, amt, abfd) != amt)
1001 return FALSE;
1002 amt = sizeof (symlength);
1003 if (bfd_bread ((void *) &symlength, amt, abfd) != amt)
1004 return FALSE;
1005 amt = symlength;
1006 sym->symbol.the_bfd = abfd;
1007 sym->symbol.name = bfd_alloc (abfd, amt + 1);
1008 if (!sym->symbol.name)
1009 return FALSE;
1010 if (bfd_bread ((void *) sym->symbol.name, amt, abfd) != amt)
1011 return FALSE;
1012 /* Cast away const. */
1013 ((char *) (sym->symbol.name))[symlength] = '\0';
1014 sym->symbol.flags = BSF_LOCAL;
1015 sym->symbol.value = get_word (abfd, temp);
1017 if (symtype == 0)
1018 sym->symbol.section =
1019 bfd_get_section_by_name (abfd, NLM_INITIALIZED_DATA_NAME);
1020 else if (symtype == 1)
1022 sym->symbol.flags |= BSF_FUNCTION;
1023 sym->symbol.section =
1024 bfd_get_section_by_name (abfd, NLM_CODE_NAME);
1026 else
1027 sym->symbol.section = bfd_abs_section_ptr;
1029 sym->rcnt = 0;
1030 abfd->symcount++;
1031 sym++;
1035 /* Read in the import records. We can only do this if we know how
1036 to read relocs for this target. */
1037 read_import_func = nlm_read_import_func (abfd);
1038 if (read_import_func != NULL)
1040 if (bfd_seek (abfd, i_fxdhdrp->externalReferencesOffset, SEEK_SET) != 0)
1041 return FALSE;
1043 symcount += i_fxdhdrp->numberOfExternalReferences;
1044 while (abfd->symcount < symcount)
1046 if (! (*read_import_func) (abfd, sym))
1047 return FALSE;
1048 sym++;
1049 abfd->symcount++;
1053 return TRUE;
1056 /* Note that bfd_get_symcount is guaranteed to be zero if slurping the
1057 symbol table fails. */
1059 long
1060 nlm_canonicalize_symtab (bfd *abfd, asymbol **alocation)
1062 nlm_symbol_type *symbase;
1063 bfd_size_type counter = 0;
1065 if (! nlm_slurp_symbol_table (abfd))
1066 return -1;
1067 symbase = nlm_get_symbols (abfd);
1068 while (counter < bfd_get_symcount (abfd))
1070 *alocation++ = &symbase->symbol;
1071 symbase++;
1072 counter++;
1074 *alocation = NULL;
1075 return bfd_get_symcount (abfd);
1078 /* Make an NLM symbol. There is nothing special to do here. */
1080 asymbol *
1081 nlm_make_empty_symbol (bfd *abfd)
1083 bfd_size_type amt = sizeof (nlm_symbol_type);
1084 nlm_symbol_type *new = bfd_zalloc (abfd, amt);
1086 if (new == NULL)
1087 return NULL;
1088 new->symbol.the_bfd = abfd;
1089 return & new->symbol;
1092 /* Get symbol information. */
1094 void
1095 nlm_get_symbol_info (bfd *ignore_abfd ATTRIBUTE_UNUSED,
1096 asymbol *symbol,
1097 symbol_info *ret)
1099 bfd_symbol_info (symbol, ret);
1102 /* Print symbol information. */
1104 void
1105 nlm_print_symbol (bfd *abfd,
1106 void * afile,
1107 asymbol *symbol,
1108 bfd_print_symbol_type how)
1110 FILE *file = (FILE *) afile;
1112 switch (how)
1114 case bfd_print_symbol_name:
1115 case bfd_print_symbol_more:
1116 if (symbol->name)
1117 fprintf (file, "%s", symbol->name);
1118 break;
1119 case bfd_print_symbol_all:
1120 bfd_print_symbol_vandf (abfd, (void *) file, symbol);
1121 fprintf (file, " %-5s", symbol->section->name);
1122 if (symbol->name)
1123 fprintf (file, " %s", symbol->name);
1124 break;
1128 /* Get the relocs for an NLM file. There are two types of relocs.
1129 Imports are relocs against symbols defined in other NLM files. We
1130 treat these as relocs against global symbols. Relocation fixups
1131 are internal relocs.
1133 The actual format used to store the relocs is machine specific. */
1135 /* Read in the relocation fixup information. This is stored in
1136 nlm_relocation_fixups, an array of arelent structures, and
1137 nlm_relocation_fixup_secs, an array of section pointers. The
1138 section pointers are needed because the relocs are not sorted by
1139 section. */
1141 static bfd_boolean
1142 nlm_slurp_reloc_fixups (bfd *abfd)
1144 bfd_boolean (*read_func) (bfd *, nlm_symbol_type *, asection **, arelent *);
1145 bfd_size_type count, amt;
1146 arelent *rels;
1147 asection **secs;
1149 if (nlm_relocation_fixups (abfd) != NULL)
1150 return TRUE;
1151 read_func = nlm_read_reloc_func (abfd);
1152 if (read_func == NULL)
1153 return TRUE;
1155 if (bfd_seek (abfd, nlm_fixed_header (abfd)->relocationFixupOffset,
1156 SEEK_SET) != 0)
1157 return FALSE;
1159 count = nlm_fixed_header (abfd)->numberOfRelocationFixups;
1160 amt = count * sizeof (arelent);
1161 rels = bfd_alloc (abfd, amt);
1162 amt = count * sizeof (asection *);
1163 secs = bfd_alloc (abfd, amt);
1164 if ((rels == NULL || secs == NULL) && count != 0)
1165 return FALSE;
1166 nlm_relocation_fixups (abfd) = rels;
1167 nlm_relocation_fixup_secs (abfd) = secs;
1169 /* We have to read piece by piece, because we don't know how large
1170 the machine specific reloc information is. */
1171 while (count-- != 0)
1173 if (! (*read_func) (abfd, NULL, secs, rels))
1175 nlm_relocation_fixups (abfd) = NULL;
1176 nlm_relocation_fixup_secs (abfd) = NULL;
1177 return FALSE;
1179 ++secs;
1180 ++rels;
1183 return TRUE;
1186 /* Get the number of relocs. This really just returns an upper bound,
1187 since it does not attempt to distinguish them based on the section.
1188 That will be handled when they are actually read. */
1190 long
1191 nlm_get_reloc_upper_bound (bfd *abfd, asection *sec)
1193 nlm_symbol_type *syms;
1194 bfd_size_type count;
1195 unsigned int ret;
1197 /* If we don't know how to read relocs, just return 0. */
1198 if (nlm_read_reloc_func (abfd) == NULL)
1199 return -1;
1200 /* Make sure we have either the code or the data section. */
1201 if ((bfd_get_section_flags (abfd, sec) & (SEC_CODE | SEC_DATA)) == 0)
1202 return 0;
1204 syms = nlm_get_symbols (abfd);
1205 if (syms == NULL)
1207 if (! nlm_slurp_symbol_table (abfd))
1208 return -1;
1209 syms = nlm_get_symbols (abfd);
1212 ret = nlm_fixed_header (abfd)->numberOfRelocationFixups;
1214 count = bfd_get_symcount (abfd);
1215 while (count-- != 0)
1217 ret += syms->rcnt;
1218 ++syms;
1221 return (ret + 1) * sizeof (arelent *);
1224 /* Get the relocs themselves. */
1226 long
1227 nlm_canonicalize_reloc (bfd *abfd,
1228 asection *sec,
1229 arelent **relptr,
1230 asymbol **symbols)
1232 arelent *rels;
1233 asection **secs;
1234 bfd_size_type count, i;
1235 long ret;
1237 /* Get the relocation fixups. */
1238 rels = nlm_relocation_fixups (abfd);
1239 if (rels == NULL)
1241 if (! nlm_slurp_reloc_fixups (abfd))
1242 return -1;
1243 rels = nlm_relocation_fixups (abfd);
1245 secs = nlm_relocation_fixup_secs (abfd);
1247 ret = 0;
1248 count = nlm_fixed_header (abfd)->numberOfRelocationFixups;
1249 for (i = 0; i < count; i++, rels++, secs++)
1251 if (*secs == sec)
1253 *relptr++ = rels;
1254 ++ret;
1258 /* Get the import symbols. */
1259 count = bfd_get_symcount (abfd);
1260 for (i = 0; i < count; i++, symbols++)
1262 asymbol *sym;
1264 sym = *symbols;
1265 if (bfd_asymbol_flavour (sym) == bfd_target_nlm_flavour)
1267 nlm_symbol_type *nlm_sym;
1268 bfd_size_type j;
1270 nlm_sym = (nlm_symbol_type *) sym;
1271 for (j = 0; j < nlm_sym->rcnt; j++)
1273 if (nlm_sym->relocs[j].section == sec)
1275 *relptr = &nlm_sym->relocs[j].reloc;
1276 (*relptr)->sym_ptr_ptr = symbols;
1277 ++relptr;
1278 ++ret;
1284 *relptr = NULL;
1286 return ret;
1289 /* Compute the section file positions for an NLM file. All variable
1290 length data in the file headers must be set before this function is
1291 called. If the variable length data is changed later, the
1292 resulting object file will be incorrect. Unfortunately, there is
1293 no way to check this.
1295 This routine also sets the Size and Offset fields in the fixed
1296 header.
1298 It also looks over the symbols and moves any common symbols into
1299 the .bss section; NLM has no way to represent a common symbol.
1300 This approach means that either the symbols must already have been
1301 set at this point, or there must be no common symbols. We need to
1302 move the symbols at this point so that mangle_relocs can see the
1303 final values. */
1305 static bfd_boolean
1306 nlm_compute_section_file_positions (bfd *abfd)
1308 file_ptr sofar;
1309 asection *sec;
1310 bfd_vma text, data, bss;
1311 bfd_vma text_low, data_low;
1312 unsigned int text_align, data_align, other_align;
1313 file_ptr text_ptr, data_ptr, other_ptr;
1314 asection *bss_sec;
1315 asymbol **sym_ptr_ptr;
1317 if (abfd->output_has_begun)
1318 return TRUE;
1320 /* Make sure we have a section to hold uninitialized data. */
1321 bss_sec = bfd_get_section_by_name (abfd, NLM_UNINITIALIZED_DATA_NAME);
1322 if (bss_sec == NULL)
1324 if (!add_bfd_section (abfd, NLM_UNINITIALIZED_DATA_NAME,
1325 (file_ptr) 0, (bfd_size_type) 0,
1326 SEC_ALLOC))
1327 return FALSE;
1328 bss_sec = bfd_get_section_by_name (abfd, NLM_UNINITIALIZED_DATA_NAME);
1331 abfd->output_has_begun = TRUE;
1333 /* The fixed header. */
1334 sofar = nlm_optional_prefix_size (abfd) + nlm_fixed_header_size (abfd);
1336 /* The variable header. */
1337 sofar += (sizeof (nlm_variable_header (abfd)->descriptionLength)
1338 + nlm_variable_header (abfd)->descriptionLength + 1
1339 + NLM_TARGET_LONG_SIZE /* stackSize */
1340 + NLM_TARGET_LONG_SIZE /* reserved */
1341 + sizeof (nlm_variable_header (abfd)->oldThreadName)
1342 + sizeof (nlm_variable_header (abfd)->screenNameLength)
1343 + nlm_variable_header (abfd)->screenNameLength + 1
1344 + sizeof (nlm_variable_header (abfd)->threadNameLength)
1345 + nlm_variable_header (abfd)->threadNameLength + 1);
1347 /* The auxiliary headers. */
1348 if (find_nonzero (nlm_version_header (abfd),
1349 sizeof (Nlm_Internal_Version_Header)))
1350 sofar += sizeof (Nlm_External_Version_Header);
1351 if (find_nonzero (nlm_extended_header (abfd),
1352 sizeof (Nlm_Internal_Extended_Header)))
1353 sofar += sizeof (Nlm_External_Extended_Header);
1354 if (find_nonzero (nlm_copyright_header (abfd),
1355 sizeof (Nlm_Internal_Copyright_Header)))
1356 sofar += (sizeof (Nlm_External_Copyright_Header)
1357 + nlm_copyright_header (abfd)->copyrightMessageLength + 1);
1358 if (find_nonzero (nlm_custom_header (abfd),
1359 sizeof (Nlm_Internal_Custom_Header)))
1360 sofar += (sizeof (Nlm_External_Custom_Header)
1361 + nlm_custom_header (abfd)->hdrLength);
1362 if (find_nonzero (nlm_cygnus_ext_header (abfd),
1363 sizeof (Nlm_Internal_Cygnus_Ext_Header)))
1364 sofar += sizeof (Nlm_External_Custom_Header);
1366 /* Compute the section file positions in two passes. First get the
1367 sizes of the text and data sections, and then set the file
1368 positions. This code aligns the sections in the file using the
1369 same alignment restrictions that apply to the sections in memory;
1370 this may not be necessary. */
1371 text = 0;
1372 text_low = (bfd_vma) - 1;
1373 text_align = 0;
1374 data = 0;
1375 data_low = (bfd_vma) - 1;
1376 data_align = 0;
1377 bss = 0;
1378 other_align = 0;
1379 for (sec = abfd->sections; sec != NULL; sec = sec->next)
1381 flagword f;
1383 sec->size = BFD_ALIGN (sec->size, 1 << sec->alignment_power);
1385 f = bfd_get_section_flags (abfd, sec);
1386 if (f & SEC_CODE)
1388 text += sec->size;
1389 if (bfd_get_section_vma (abfd, sec) < text_low)
1390 text_low = bfd_get_section_vma (abfd, sec);
1391 if (sec->alignment_power > text_align)
1392 text_align = sec->alignment_power;
1394 else if (f & SEC_DATA)
1396 data += sec->size;
1397 if (bfd_get_section_vma (abfd, sec) < data_low)
1398 data_low = bfd_get_section_vma (abfd, sec);
1399 if (sec->alignment_power > data_align)
1400 data_align = sec->alignment_power;
1402 else if (f & SEC_HAS_CONTENTS)
1404 if (sec->alignment_power > other_align)
1405 other_align = sec->alignment_power;
1407 else if (f & SEC_ALLOC)
1408 bss += sec->size;
1411 nlm_set_text_low (abfd, text_low);
1412 nlm_set_data_low (abfd, data_low);
1414 if (nlm_no_uninitialized_data (abfd))
1416 /* This NetWare format does not use uninitialized data. We must
1417 increase the size of the data section. We will never wind up
1418 writing those file locations, so they will remain zero. */
1419 data += bss;
1420 bss = 0;
1423 text_ptr = BFD_ALIGN (sofar, 1 << text_align);
1424 data_ptr = BFD_ALIGN (text_ptr + text, 1 << data_align);
1425 other_ptr = BFD_ALIGN (data_ptr + data, 1 << other_align);
1427 /* Fill in some fields in the header for which we now have the
1428 information. */
1429 nlm_fixed_header (abfd)->codeImageOffset = text_ptr;
1430 nlm_fixed_header (abfd)->codeImageSize = text;
1431 nlm_fixed_header (abfd)->dataImageOffset = data_ptr;
1432 nlm_fixed_header (abfd)->dataImageSize = data;
1433 nlm_fixed_header (abfd)->uninitializedDataSize = bss;
1435 for (sec = abfd->sections; sec != NULL; sec = sec->next)
1437 flagword f;
1439 f = bfd_get_section_flags (abfd, sec);
1441 if (f & SEC_CODE)
1443 sec->filepos = text_ptr;
1444 text_ptr += sec->size;
1446 else if (f & SEC_DATA)
1448 sec->filepos = data_ptr;
1449 data_ptr += sec->size;
1451 else if (f & SEC_HAS_CONTENTS)
1453 sec->filepos = other_ptr;
1454 other_ptr += sec->size;
1458 nlm_fixed_header (abfd)->relocationFixupOffset = other_ptr;
1460 /* Move all common symbols into the .bss section. */
1462 sym_ptr_ptr = bfd_get_outsymbols (abfd);
1463 if (sym_ptr_ptr != NULL)
1465 asymbol **sym_end;
1466 bfd_vma add;
1468 sym_end = sym_ptr_ptr + bfd_get_symcount (abfd);
1469 add = 0;
1470 for (; sym_ptr_ptr < sym_end; sym_ptr_ptr++)
1472 asymbol *sym;
1473 bfd_vma size;
1475 sym = *sym_ptr_ptr;
1477 if (!bfd_is_com_section (bfd_get_section (sym)))
1478 continue;
1480 /* Put the common symbol in the .bss section, and increase
1481 the size of the .bss section by the size of the common
1482 symbol (which is the old value of the symbol). */
1483 sym->section = bss_sec;
1484 size = sym->value;
1485 sym->value = bss_sec->size + add;
1486 add += size;
1487 add = BFD_ALIGN (add, 1 << bss_sec->alignment_power);
1489 if (add != 0)
1491 if (nlm_no_uninitialized_data (abfd))
1493 /* We could handle this case, but so far it hasn't been
1494 necessary. */
1495 abort ();
1497 nlm_fixed_header (abfd)->uninitializedDataSize += add;
1498 bss_sec->size += add;
1502 return TRUE;
1505 /* Set the contents of a section. To do this we need to know where
1506 the section is going to be located in the output file. That means
1507 that the sizes of all the sections must be set, and all the
1508 variable size header information must be known. */
1510 bfd_boolean
1511 nlm_set_section_contents (bfd *abfd,
1512 asection *section,
1513 const void * location,
1514 file_ptr offset,
1515 bfd_size_type count)
1517 if (! abfd->output_has_begun
1518 && ! nlm_compute_section_file_positions (abfd))
1519 return FALSE;
1521 if (count == 0)
1522 return TRUE;
1524 /* i386 NetWare has a very restricted set of relocs. In order for
1525 objcopy to work, the NLM i386 backend needs a chance to rework
1526 the section contents so that its set of relocs will work. If all
1527 the relocs are already acceptable, this will not do anything. */
1528 if (section->reloc_count != 0)
1530 bfd_boolean (*mangle_relocs_func)
1531 (bfd *, asection *, const void *, bfd_vma, bfd_size_type);
1533 mangle_relocs_func = nlm_mangle_relocs_func (abfd);
1534 if (mangle_relocs_func != NULL)
1536 if (!(*mangle_relocs_func) (abfd, section, location,
1537 (bfd_vma) offset, count))
1538 return FALSE;
1542 if (bfd_seek (abfd, section->filepos + offset, SEEK_SET) != 0
1543 || bfd_bwrite (location, count, abfd) != count)
1544 return FALSE;
1546 return TRUE;
1549 /* We need to sort a list of relocs associated with sections when we
1550 write out the external relocs. */
1552 static int
1553 nlm_external_reloc_compare (const void *p1, const void *p2)
1555 const struct reloc_and_sec *r1 = (const struct reloc_and_sec *) p1;
1556 const struct reloc_and_sec *r2 = (const struct reloc_and_sec *) p2;
1557 int cmp;
1559 cmp = strcmp ((*r1->rel->sym_ptr_ptr)->name,
1560 (*r2->rel->sym_ptr_ptr)->name);
1561 if (cmp != 0)
1562 return cmp;
1564 /* We sort by address within symbol to make the sort more stable and
1565 increase the chances that different hosts will generate bit for
1566 bit equivalent results. */
1567 return (int) (r1->rel->address - r2->rel->address);
1570 /* Write out an NLM file. We write out the information in this order:
1571 fixed header
1572 variable header
1573 auxiliary headers
1574 code sections
1575 data sections
1576 other sections (custom data, messages, help, shared NLM, RPC,
1577 module dependencies)
1578 relocation fixups
1579 external references (imports)
1580 public symbols (exports)
1581 debugging records
1582 This is similar to the order used by the NetWare tools; the
1583 difference is that NetWare puts the sections other than code, data
1584 and custom data at the end of the NLM. It is convenient for us to
1585 know where the sections are going to be before worrying about the
1586 size of the other information.
1588 By the time this function is called, all the section data should
1589 have been output using set_section_contents. Note that custom
1590 data, the message file, the help file, the shared NLM file, the RPC
1591 data, and the module dependencies are all considered to be
1592 sections; the caller is responsible for filling in the offset and
1593 length fields in the NLM headers. The relocation fixups and
1594 imports are both obtained from the list of relocs attached to each
1595 section. The exports and debugging records are obtained from the
1596 list of outsymbols. */
1598 bfd_boolean
1599 nlm_write_object_contents (bfd *abfd)
1601 asection *sec;
1602 bfd_boolean (*write_import_func) (bfd *, asection *, arelent *);
1603 bfd_size_type external_reloc_count, internal_reloc_count, i, c;
1604 struct reloc_and_sec *external_relocs;
1605 asymbol **sym_ptr_ptr;
1606 file_ptr last;
1607 bfd_boolean (*write_prefix_func) (bfd *);
1608 unsigned char *fixed_header = NULL;
1609 file_ptr pos;
1610 bfd_size_type amt;
1612 fixed_header = bfd_malloc (nlm_fixed_header_size (abfd));
1613 if (fixed_header == NULL)
1614 goto error_return;
1616 if (! abfd->output_has_begun
1617 && ! nlm_compute_section_file_positions (abfd))
1618 goto error_return;
1620 /* Write out the variable length headers. */
1621 pos = nlm_optional_prefix_size (abfd) + nlm_fixed_header_size (abfd);
1622 if (bfd_seek (abfd, pos, SEEK_SET) != 0)
1623 goto error_return;
1624 if (! nlm_swap_variable_header_out (abfd)
1625 || ! nlm_swap_auxiliary_headers_out (abfd))
1627 bfd_set_error (bfd_error_system_call);
1628 goto error_return;
1631 /* A weak check on whether the section file positions were
1632 reasonable. */
1633 if (bfd_tell (abfd) > nlm_fixed_header (abfd)->codeImageOffset)
1635 bfd_set_error (bfd_error_invalid_operation);
1636 goto error_return;
1639 /* Advance to the relocs. */
1640 if (bfd_seek (abfd, nlm_fixed_header (abfd)->relocationFixupOffset,
1641 SEEK_SET) != 0)
1642 goto error_return;
1644 /* The format of the relocation entries is dependent upon the
1645 particular target. We use an external routine to write the reloc
1646 out. */
1647 write_import_func = nlm_write_import_func (abfd);
1649 /* Write out the internal relocation fixups. While we're looping
1650 over the relocs, we also count the external relocs, which is
1651 needed when they are written out below. */
1652 internal_reloc_count = 0;
1653 external_reloc_count = 0;
1654 for (sec = abfd->sections; sec != NULL; sec = sec->next)
1656 arelent **rel_ptr_ptr, **rel_end;
1658 if (sec->reloc_count == 0)
1659 continue;
1661 /* We can only represent relocs within a code or data
1662 section. We ignore them for a debugging section. */
1663 if ((bfd_get_section_flags (abfd, sec) & (SEC_CODE | SEC_DATA)) == 0)
1664 continue;
1666 /* We need to know how to write out imports */
1667 if (write_import_func == NULL)
1669 bfd_set_error (bfd_error_invalid_operation);
1670 goto error_return;
1673 rel_ptr_ptr = sec->orelocation;
1674 rel_end = rel_ptr_ptr + sec->reloc_count;
1675 for (; rel_ptr_ptr < rel_end; rel_ptr_ptr++)
1677 arelent *rel;
1678 asymbol *sym;
1680 rel = *rel_ptr_ptr;
1681 sym = *rel->sym_ptr_ptr;
1683 if (! bfd_is_und_section (bfd_get_section (sym)))
1685 ++internal_reloc_count;
1686 if (! (*write_import_func) (abfd, sec, rel))
1687 goto error_return;
1689 else
1690 ++external_reloc_count;
1693 nlm_fixed_header (abfd)->numberOfRelocationFixups = internal_reloc_count;
1695 /* Write out the imports (relocs against external symbols). These
1696 are output as a symbol name followed by all the relocs for that
1697 symbol, so we must first gather together all the relocs against
1698 external symbols and sort them. */
1699 amt = external_reloc_count * sizeof (struct reloc_and_sec);
1700 external_relocs = bfd_alloc (abfd, amt);
1701 if (external_relocs == NULL)
1702 goto error_return;
1703 i = 0;
1704 for (sec = abfd->sections; sec != NULL; sec = sec->next)
1706 arelent **rel_ptr_ptr, **rel_end;
1708 if (sec->reloc_count == 0)
1709 continue;
1711 rel_ptr_ptr = sec->orelocation;
1712 rel_end = rel_ptr_ptr + sec->reloc_count;
1713 for (; rel_ptr_ptr < rel_end; rel_ptr_ptr++)
1715 arelent *rel;
1716 asymbol *sym;
1718 rel = *rel_ptr_ptr;
1719 sym = *rel->sym_ptr_ptr;
1721 if (! bfd_is_und_section (bfd_get_section (sym)))
1722 continue;
1724 external_relocs[i].rel = rel;
1725 external_relocs[i].sec = sec;
1726 ++i;
1730 BFD_ASSERT (i == external_reloc_count);
1732 /* Sort the external relocs by name. */
1733 qsort (external_relocs, (size_t) external_reloc_count,
1734 sizeof (struct reloc_and_sec), nlm_external_reloc_compare);
1736 /* Write out the external relocs. */
1737 nlm_fixed_header (abfd)->externalReferencesOffset = bfd_tell (abfd);
1738 c = 0;
1739 i = 0;
1740 while (i < external_reloc_count)
1742 arelent *rel;
1743 asymbol *sym;
1744 bfd_size_type j, cnt;
1746 ++c;
1748 rel = external_relocs[i].rel;
1749 sym = *rel->sym_ptr_ptr;
1751 cnt = 0;
1752 for (j = i;
1753 (j < external_reloc_count
1754 && *external_relocs[j].rel->sym_ptr_ptr == sym);
1755 j++)
1756 ++cnt;
1758 if (! (*nlm_write_external_func (abfd)) (abfd, cnt, sym,
1759 &external_relocs[i]))
1760 goto error_return;
1762 i += cnt;
1765 nlm_fixed_header (abfd)->numberOfExternalReferences = c;
1767 /* Write out the public symbols (exports). */
1768 sym_ptr_ptr = bfd_get_outsymbols (abfd);
1769 if (sym_ptr_ptr != NULL)
1771 bfd_vma (*get_public_offset_func) (bfd *, asymbol *);
1772 bfd_boolean (*write_export_func) (bfd *, asymbol *, bfd_vma);
1774 asymbol **sym_end;
1776 nlm_fixed_header (abfd)->publicsOffset = bfd_tell (abfd);
1777 get_public_offset_func = nlm_get_public_offset_func (abfd);
1778 write_export_func = nlm_write_export_func (abfd);
1779 c = 0;
1780 sym_end = sym_ptr_ptr + bfd_get_symcount (abfd);
1781 for (; sym_ptr_ptr < sym_end; sym_ptr_ptr++)
1783 asymbol *sym;
1784 bfd_byte len;
1785 bfd_vma offset;
1786 bfd_byte temp[NLM_TARGET_LONG_SIZE];
1788 sym = *sym_ptr_ptr;
1790 if ((sym->flags & (BSF_EXPORT | BSF_GLOBAL)) == 0
1791 || bfd_is_und_section (bfd_get_section (sym)))
1792 continue;
1794 ++c;
1796 if (get_public_offset_func)
1798 /* Most backends can use the code below, but
1799 unfortunately some use a different scheme. */
1800 offset = (*get_public_offset_func) (abfd, sym);
1802 else
1804 offset = bfd_asymbol_value (sym);
1805 sec = sym->section;
1806 if (sec->flags & SEC_CODE)
1808 offset -= nlm_get_text_low (abfd);
1809 offset |= NLM_HIBIT;
1811 else if (sec->flags & (SEC_DATA | SEC_ALLOC))
1813 /* SEC_ALLOC is for the .bss section. */
1814 offset -= nlm_get_data_low (abfd);
1816 else
1818 /* We can't handle an exported symbol that is not in
1819 the code or data segment. */
1820 bfd_set_error (bfd_error_invalid_operation);
1821 goto error_return;
1825 if (write_export_func)
1827 if (! (*write_export_func) (abfd, sym, offset))
1828 goto error_return;
1830 else
1832 len = strlen (sym->name);
1833 if ((bfd_bwrite (&len, (bfd_size_type) sizeof (bfd_byte), abfd)
1834 != sizeof (bfd_byte))
1835 || bfd_bwrite (sym->name, (bfd_size_type) len, abfd) != len)
1836 goto error_return;
1838 put_word (abfd, offset, temp);
1839 if (bfd_bwrite (temp, (bfd_size_type) sizeof (temp), abfd)
1840 != sizeof (temp))
1841 goto error_return;
1844 nlm_fixed_header (abfd)->numberOfPublics = c;
1846 /* Write out the debugging records. The NLM conversion program
1847 wants to be able to inhibit this, so as a special hack if
1848 debugInfoOffset is set to -1 we don't write any debugging
1849 information. This can not be handled by fiddling with the
1850 symbol table, because exported symbols appear in both the
1851 exported symbol list and the debugging information. */
1852 if (nlm_fixed_header (abfd)->debugInfoOffset == (file_ptr) - 1)
1854 nlm_fixed_header (abfd)->debugInfoOffset = 0;
1855 nlm_fixed_header (abfd)->numberOfDebugRecords = 0;
1857 else
1859 nlm_fixed_header (abfd)->debugInfoOffset = bfd_tell (abfd);
1860 c = 0;
1861 sym_ptr_ptr = bfd_get_outsymbols (abfd);
1862 sym_end = sym_ptr_ptr + bfd_get_symcount (abfd);
1863 for (; sym_ptr_ptr < sym_end; sym_ptr_ptr++)
1865 asymbol *sym;
1866 bfd_byte type, len;
1867 bfd_vma offset;
1868 bfd_byte temp[NLM_TARGET_LONG_SIZE];
1870 sym = *sym_ptr_ptr;
1872 /* The NLM notion of a debugging symbol is actually what
1873 BFD calls a local or global symbol. What BFD calls a
1874 debugging symbol NLM does not understand at all. */
1875 if ((sym->flags & (BSF_LOCAL | BSF_GLOBAL | BSF_EXPORT)) == 0
1876 || (sym->flags & BSF_DEBUGGING) != 0
1877 || bfd_is_und_section (bfd_get_section (sym)))
1878 continue;
1880 ++c;
1882 offset = bfd_asymbol_value (sym);
1883 sec = sym->section;
1884 if (sec->flags & SEC_CODE)
1886 offset -= nlm_get_text_low (abfd);
1887 type = 1;
1889 else if (sec->flags & (SEC_DATA | SEC_ALLOC))
1891 /* SEC_ALLOC is for the .bss section. */
1892 offset -= nlm_get_data_low (abfd);
1893 type = 0;
1895 else
1896 type = 2;
1898 /* The type is 0 for data, 1 for code, 2 for absolute. */
1899 if (bfd_bwrite (&type, (bfd_size_type) sizeof (bfd_byte), abfd)
1900 != sizeof (bfd_byte))
1901 goto error_return;
1903 put_word (abfd, offset, temp);
1904 if (bfd_bwrite (temp, (bfd_size_type) sizeof (temp), abfd)
1905 != sizeof (temp))
1906 goto error_return;
1908 len = strlen (sym->name);
1909 if ((bfd_bwrite (&len, (bfd_size_type) sizeof (bfd_byte), abfd)
1910 != sizeof (bfd_byte))
1911 || bfd_bwrite (sym->name, (bfd_size_type) len, abfd) != len)
1912 goto error_return;
1914 nlm_fixed_header (abfd)->numberOfDebugRecords = c;
1918 /* NLMLINK fills in offset values even if there is no data, so we do
1919 the same. */
1920 last = bfd_tell (abfd);
1921 if (nlm_fixed_header (abfd)->codeImageOffset == 0)
1922 nlm_fixed_header (abfd)->codeImageOffset = last;
1923 if (nlm_fixed_header (abfd)->dataImageOffset == 0)
1924 nlm_fixed_header (abfd)->dataImageOffset = last;
1925 if (nlm_fixed_header (abfd)->customDataOffset == 0)
1926 nlm_fixed_header (abfd)->customDataOffset = last;
1927 if (nlm_fixed_header (abfd)->moduleDependencyOffset == 0)
1928 nlm_fixed_header (abfd)->moduleDependencyOffset = last;
1929 if (nlm_fixed_header (abfd)->relocationFixupOffset == 0)
1930 nlm_fixed_header (abfd)->relocationFixupOffset = last;
1931 if (nlm_fixed_header (abfd)->externalReferencesOffset == 0)
1932 nlm_fixed_header (abfd)->externalReferencesOffset = last;
1933 if (nlm_fixed_header (abfd)->publicsOffset == 0)
1934 nlm_fixed_header (abfd)->publicsOffset = last;
1935 if (nlm_fixed_header (abfd)->debugInfoOffset == 0)
1936 nlm_fixed_header (abfd)->debugInfoOffset = last;
1938 /* At this point everything has been written out except the fixed
1939 header. */
1940 memcpy (nlm_fixed_header (abfd)->signature, nlm_signature (abfd),
1941 NLM_SIGNATURE_SIZE);
1942 nlm_fixed_header (abfd)->version = NLM_HEADER_VERSION;
1943 nlm_fixed_header (abfd)->codeStartOffset =
1944 (bfd_get_start_address (abfd)
1945 - nlm_get_text_low (abfd));
1947 /* We have no convenient way for the caller to pass in the exit
1948 procedure or the check unload procedure, so the caller must set
1949 the values in the header to the values of the symbols. */
1950 nlm_fixed_header (abfd)->exitProcedureOffset -= nlm_get_text_low (abfd);
1951 if (nlm_fixed_header (abfd)->checkUnloadProcedureOffset != 0)
1952 nlm_fixed_header (abfd)->checkUnloadProcedureOffset -=
1953 nlm_get_text_low (abfd);
1955 if (bfd_seek (abfd, (file_ptr) 0, SEEK_SET) != 0)
1956 goto error_return;
1958 write_prefix_func = nlm_write_prefix_func (abfd);
1959 if (write_prefix_func)
1961 if (! (*write_prefix_func) (abfd))
1962 goto error_return;
1965 BFD_ASSERT ((bfd_size_type) bfd_tell (abfd)
1966 == nlm_optional_prefix_size (abfd));
1968 nlm_swap_fixed_header_out (abfd, nlm_fixed_header (abfd), fixed_header);
1969 if (bfd_bwrite (fixed_header, nlm_fixed_header_size (abfd), abfd)
1970 != nlm_fixed_header_size (abfd))
1971 goto error_return;
1973 if (fixed_header != NULL)
1974 free (fixed_header);
1975 return TRUE;
1977 error_return:
1978 if (fixed_header != NULL)
1979 free (fixed_header);
1980 return FALSE;