daily update
[deliverable/binutils-gdb.git] / bfd / nlmcode.h
CommitLineData
252b5132 1/* NLM (NetWare Loadable Module) executable support for BFD.
7920ce38
NC
2 Copyright 1993, 1994, 1995, 1998, 1999, 2000, 2001, 2002, 2003, 2004,
3 2005 Free Software Foundation, Inc.
252b5132
RH
4
5 Written by Fred Fish @ Cygnus Support, using ELF support as the
6 template.
7
9e12c7db 8 This file is part of BFD, the Binary File Descriptor library.
252b5132 9
9e12c7db
NC
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.
252b5132 14
9e12c7db
NC
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.
252b5132 19
9e12c7db
NC
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
3e110533 22 Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA. */
252b5132
RH
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
7920ce38
NC
36#define Nlm_External_Fixed_Header NlmNAME (External_Fixed_Header)
37#define Nlm_External_Version_Header NlmNAME (External_Version_Header)
38#define Nlm_External_Copyright_Header NlmNAME (External_Copyright_Header)
39#define Nlm_External_Extended_Header NlmNAME (External_Extended_Header)
40#define Nlm_External_Custom_Header NlmNAME (External_Custom_Header)
41#define Nlm_External_Cygnus_Ext_Header NlmNAME (External_Cygnus_Ext_Header)
42
43#define nlm_symbol_type nlmNAME (symbol_type)
44#define nlm_get_symtab_upper_bound nlmNAME (get_symtab_upper_bound)
45#define nlm_canonicalize_symtab nlmNAME (canonicalize_symtab)
46#define nlm_make_empty_symbol nlmNAME (make_empty_symbol)
47#define nlm_print_symbol nlmNAME (print_symbol)
48#define nlm_get_symbol_info nlmNAME (get_symbol_info)
49#define nlm_get_reloc_upper_bound nlmNAME (get_reloc_upper_bound)
50#define nlm_canonicalize_reloc nlmNAME (canonicalize_reloc)
51#define nlm_object_p nlmNAME (object_p)
52#define nlm_set_section_contents nlmNAME (set_section_contents)
53#define nlm_write_object_contents nlmNAME (write_object_contents)
252b5132
RH
54
55#define nlm_swap_fixed_header_in(abfd,src,dst) \
7920ce38 56 (nlm_swap_fixed_header_in_func (abfd)) (abfd, src, dst)
252b5132 57#define nlm_swap_fixed_header_out(abfd,src,dst) \
7920ce38 58 (nlm_swap_fixed_header_out_func (abfd)) (abfd, src, dst)
252b5132
RH
59
60/* Should perhaps use put_offset, put_word, etc. For now, the two versions
61 can be handled by explicitly specifying 32 bits or "the long type". */
62#if ARCH_SIZE == 64
dc810e39
AM
63#define put_word H_PUT_64
64#define get_word H_GET_64
252b5132
RH
65#endif
66#if ARCH_SIZE == 32
dc810e39
AM
67#define put_word H_PUT_32
68#define get_word H_GET_32
252b5132
RH
69#endif
70
252b5132 71/* Read and swap in the variable length header. All the fields must
1518639e 72 exist in the NLM, and must exist in the order they are read here. */
252b5132 73
b34976b6 74static bfd_boolean
7920ce38 75nlm_swap_variable_header_in (bfd *abfd)
252b5132
RH
76{
77 unsigned char temp[NLM_TARGET_LONG_SIZE];
dc810e39 78 bfd_size_type amt;
252b5132 79
1518639e 80 /* Read the description length and text members. */
dc810e39 81 amt = sizeof (nlm_variable_header (abfd)->descriptionLength);
7920ce38 82 if (bfd_bread ((void *) &nlm_variable_header (abfd)->descriptionLength,
dc810e39 83 amt, abfd) != amt)
b34976b6 84 return FALSE;
dc810e39 85 amt = nlm_variable_header (abfd)->descriptionLength + 1;
7920ce38 86 if (bfd_bread ((void *) nlm_variable_header (abfd)->descriptionText,
dc810e39 87 amt, abfd) != amt)
b34976b6 88 return FALSE;
252b5132 89
1518639e 90 /* Read and convert the stackSize field. */
dc810e39 91 amt = sizeof (temp);
7920ce38 92 if (bfd_bread ((void *) temp, amt, abfd) != amt)
b34976b6 93 return FALSE;
252b5132
RH
94 nlm_variable_header (abfd)->stackSize = get_word (abfd, (bfd_byte *) temp);
95
1518639e 96 /* Read and convert the reserved field. */
dc810e39 97 amt = sizeof (temp);
7920ce38 98 if (bfd_bread ((void *) temp, amt, abfd) != amt)
b34976b6 99 return FALSE;
252b5132
RH
100 nlm_variable_header (abfd)->reserved = get_word (abfd, (bfd_byte *) temp);
101
1518639e 102 /* Read the oldThreadName field. This field is a fixed length string. */
dc810e39 103 amt = sizeof (nlm_variable_header (abfd)->oldThreadName);
7920ce38 104 if (bfd_bread ((void *) nlm_variable_header (abfd)->oldThreadName,
dc810e39 105 amt, abfd) != amt)
b34976b6 106 return FALSE;
252b5132 107
1518639e 108 /* Read the screen name length and text members. */
dc810e39 109 amt = sizeof (nlm_variable_header (abfd)->screenNameLength);
7920ce38 110 if (bfd_bread ((void *) & nlm_variable_header (abfd)->screenNameLength,
dc810e39 111 amt, abfd) != amt)
b34976b6 112 return FALSE;
dc810e39 113 amt = nlm_variable_header (abfd)->screenNameLength + 1;
7920ce38 114 if (bfd_bread ((void *) nlm_variable_header (abfd)->screenName,
dc810e39 115 amt, abfd) != amt)
b34976b6 116 return FALSE;
252b5132 117
1518639e 118 /* Read the thread name length and text members. */
dc810e39 119 amt = sizeof (nlm_variable_header (abfd)->threadNameLength);
7920ce38 120 if (bfd_bread ((void *) & nlm_variable_header (abfd)->threadNameLength,
dc810e39 121 amt, abfd) != amt)
b34976b6 122 return FALSE;
dc810e39 123 amt = nlm_variable_header (abfd)->threadNameLength + 1;
7920ce38 124 if (bfd_bread ((void *) nlm_variable_header (abfd)->threadName,
dc810e39 125 amt, abfd) != amt)
b34976b6
AM
126 return FALSE;
127 return TRUE;
252b5132
RH
128}
129
7920ce38 130/* Add a section to the bfd. */
252b5132 131
b34976b6 132static bfd_boolean
7920ce38
NC
133add_bfd_section (bfd *abfd,
134 char *name,
135 file_ptr offset,
136 bfd_size_type size,
137 flagword flags)
252b5132 138{
7920ce38 139 asection *newsect;
252b5132 140
7920ce38
NC
141 newsect = bfd_make_section (abfd, name);
142 if (newsect == NULL)
b34976b6 143 return FALSE;
252b5132 144
7920ce38
NC
145 newsect->vma = 0; /* NLM's are relocatable. */
146 newsect->size = size;
147 newsect->filepos = offset;
148 newsect->flags = flags;
149 newsect->alignment_power = bfd_log2 ((bfd_vma) 0); /* FIXME */
252b5132 150
b34976b6 151 return TRUE;
252b5132
RH
152}
153
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
1518639e 161 recognize it. */
252b5132 162
b34976b6 163static bfd_boolean
7920ce38 164nlm_swap_auxiliary_headers_in (bfd *abfd)
252b5132
RH
165{
166 char tempstr[16];
dc810e39
AM
167 file_ptr position;
168 bfd_size_type amt;
252b5132
RH
169
170 for (;;)
171 {
172 position = bfd_tell (abfd);
dc810e39 173 amt = sizeof (tempstr);
7920ce38 174 if (bfd_bread ((void *) tempstr, amt, abfd) != amt)
b34976b6 175 return FALSE;
dc810e39 176 if (bfd_seek (abfd, position, SEEK_SET) != 0)
b34976b6 177 return FALSE;
252b5132
RH
178 if (strncmp (tempstr, "VeRsIoN#", 8) == 0)
179 {
180 Nlm_External_Version_Header thdr;
dc810e39
AM
181
182 amt = sizeof (thdr);
7920ce38 183 if (bfd_bread ((void *) &thdr, amt, abfd) != amt)
b34976b6 184 return FALSE;
252b5132
RH
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);
199 }
200 else if (strncmp (tempstr, "MeSsAgEs", 8) == 0)
201 {
202 Nlm_External_Extended_Header thdr;
dc810e39
AM
203
204 amt = sizeof (thdr);
7920ce38 205 if (bfd_bread ((void *) &thdr, amt, abfd) != amt)
b34976b6 206 return FALSE;
252b5132
RH
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);
267 }
268 else if (strncmp (tempstr, "CoPyRiGhT=", 10) == 0)
269 {
dc810e39 270 amt = sizeof (nlm_copyright_header (abfd)->stamp);
7920ce38 271 if (bfd_bread ((void *) nlm_copyright_header (abfd)->stamp,
dc810e39 272 amt, abfd) != amt)
b34976b6 273 return FALSE;
7920ce38 274 if (bfd_bread ((void *) &(nlm_copyright_header (abfd)
dc810e39
AM
275 ->copyrightMessageLength),
276 (bfd_size_type) 1, abfd) != 1)
b34976b6 277 return FALSE;
1518639e 278 /* The copyright message is a variable length string. */
dc810e39 279 amt = nlm_copyright_header (abfd)->copyrightMessageLength + 1;
7920ce38 280 if (bfd_bread ((void *) nlm_copyright_header (abfd)->copyrightMessage,
dc810e39 281 amt, abfd) != amt)
b34976b6 282 return FALSE;
252b5132
RH
283 }
284 else if (strncmp (tempstr, "CuStHeAd", 8) == 0)
285 {
286 Nlm_External_Custom_Header thdr;
287 bfd_size_type hdrLength;
288 file_ptr dataOffset;
289 bfd_size_type dataLength;
290 char dataStamp[8];
7920ce38 291 void * hdr;
252b5132
RH
292
293 /* Read the stamp ("CuStHeAd"). */
dc810e39 294 amt = sizeof (thdr.stamp);
7920ce38 295 if (bfd_bread ((void *) thdr.stamp, amt, abfd) != amt)
b34976b6 296 return FALSE;
252b5132 297 /* Read the length of this custom header. */
dc810e39 298 amt = sizeof (thdr.length);
7920ce38 299 if (bfd_bread ((void *) thdr.length, amt, abfd) != amt)
b34976b6 300 return FALSE;
252b5132
RH
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
306 {
dc810e39 307 amt = sizeof (thdr.dataOffset);
7920ce38 308 if (bfd_bread ((void *) thdr.dataOffset, amt, abfd) != amt)
b34976b6 309 return FALSE;
252b5132
RH
310 dataOffset = get_word (abfd, (bfd_byte *) thdr.dataOffset);
311 }
312 if (hdrLength < 2 * NLM_TARGET_LONG_SIZE)
313 dataLength = 0;
314 else
315 {
dc810e39 316 amt = sizeof (thdr.dataLength);
7920ce38 317 if (bfd_bread ((void *) thdr.dataLength, amt, abfd) != amt)
b34976b6 318 return FALSE;
252b5132
RH
319 dataLength = get_word (abfd, (bfd_byte *) thdr.dataLength);
320 }
321 if (hdrLength < 2 * NLM_TARGET_LONG_SIZE + 8)
322 memset (dataStamp, 0, sizeof (dataStamp));
323 else
324 {
dc810e39 325 amt = sizeof (dataStamp);
7920ce38 326 if (bfd_bread ((void *) dataStamp, amt, abfd) != amt)
b34976b6 327 return FALSE;
252b5132
RH
328 }
329
330 /* Read the rest of the header, if any. */
331 if (hdrLength <= 2 * NLM_TARGET_LONG_SIZE + 8)
332 {
333 hdr = NULL;
334 hdrLength = 0;
335 }
336 else
337 {
338 hdrLength -= 2 * NLM_TARGET_LONG_SIZE + 8;
339 hdr = bfd_alloc (abfd, hdrLength);
340 if (hdr == NULL)
b34976b6 341 return FALSE;
dc810e39 342 if (bfd_bread (hdr, hdrLength, abfd) != hdrLength)
b34976b6 343 return FALSE;
252b5132
RH
344 }
345
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 (strncmp (dataStamp, "CyGnUsEx", 8) == 0)
350 {
351 file_ptr pos;
352 bfd_byte *contents;
353 bfd_byte *p, *pend;
354
355 BFD_ASSERT (hdrLength == 0 && hdr == NULL);
356
357 pos = bfd_tell (abfd);
358 if (bfd_seek (abfd, dataOffset, SEEK_SET) != 0)
b34976b6 359 return FALSE;
7920ce38 360 contents = bfd_alloc (abfd, dataLength);
252b5132 361 if (contents == NULL)
b34976b6 362 return FALSE;
dc810e39 363 if (bfd_bread (contents, dataLength, abfd) != dataLength)
b34976b6 364 return FALSE;
252b5132 365 if (bfd_seek (abfd, pos, SEEK_SET) != 0)
b34976b6 366 return FALSE;
252b5132
RH
367
368 memcpy (nlm_cygnus_ext_header (abfd), "CyGnUsEx", 8);
369 nlm_cygnus_ext_header (abfd)->offset = dataOffset;
370 nlm_cygnus_ext_header (abfd)->length = dataLength;
371
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)
385 {
386 char *name;
387 size_t l;
388 file_ptr filepos;
389 bfd_size_type size;
390 asection *newsec;
391
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
7920ce38 396 4 byte section size. */
252b5132
RH
397
398 name = (char *) p;
399 l = strlen (name) + 1;
dc810e39 400 l = (l + 3) &~ (size_t) 3;
252b5132 401 p += l;
dc810e39 402 filepos = H_GET_32 (abfd, p);
252b5132 403 p += 4;
dc810e39 404 size = H_GET_32 (abfd, p);
252b5132
RH
405 p += 4;
406
407 newsec = bfd_make_section_anyway (abfd, name);
7920ce38 408 if (newsec == NULL)
b34976b6 409 return FALSE;
eea6121a 410 newsec->size = size;
252b5132
RH
411 if (filepos != 0)
412 {
413 newsec->filepos = filepos;
414 newsec->flags |= SEC_HAS_CONTENTS;
415 }
416 }
417 }
418 else
419 {
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;
428 }
429 }
430 else
9e12c7db 431 break;
252b5132 432 }
b34976b6 433 return TRUE;
252b5132
RH
434}
435
7920ce38
NC
436const bfd_target *
437nlm_object_p (bfd *abfd)
438{
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;
447
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)
452 {
453 if (!(*backend_object_p) (abfd))
454 goto got_wrong_format_error;
455 }
456
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;
462
463 if (bfd_bread ((void *) x_fxdhdr, amt, abfd) != amt)
464 {
465 if (bfd_get_error () != bfd_error_system_call)
466 goto got_wrong_format_error;
467 else
468 goto got_no_match;
469 }
470
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;
477
478 nlm_tdata (abfd) = new_tdata;
479
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;
484
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;
493
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;
499
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))
504 {
505 if (bfd_get_error () != bfd_error_system_call)
506 goto got_wrong_format_error;
507 else
508 goto got_no_match;
509 }
510
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;
531
532 if (!nlm_swap_auxiliary_headers_in (abfd))
533 goto got_no_match;
534
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;
542
543 arch = nlm_architecture (abfd);
544 if (arch != bfd_arch_unknown)
545 bfd_default_set_arch_mach (abfd, arch, (unsigned long) 0);
546
547 abfd->flags |= EXEC_P;
548 bfd_get_start_address (abfd) = nlm_fixed_header (abfd)->codeStartOffset;
549
550 return abfd->xvec;
551
552got_wrong_format_error:
553 bfd_set_error (bfd_error_wrong_format);
554got_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);
560
561 return NULL;
562}
563
564/* Swap and write out the variable length header. All the fields must
565 exist in the NLM, and must exist in this order. */
566
567static bfd_boolean
568nlm_swap_variable_header_out (bfd *abfd)
569{
570 bfd_byte temp[NLM_TARGET_LONG_SIZE];
571 bfd_size_type amt;
572
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;
582
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;
588
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;
594
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;
600
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;
609
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;
619}
620
252b5132
RH
621/* Return whether there is a non-zero byte in a memory block. */
622
b34976b6 623static bfd_boolean
7920ce38 624find_nonzero (void * buf, size_t size)
252b5132
RH
625{
626 char *p = (char *) buf;
627
628 while (size-- != 0)
629 if (*p++ != 0)
b34976b6
AM
630 return TRUE;
631 return FALSE;
252b5132
RH
632}
633
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. */
637
b34976b6 638static bfd_boolean
7920ce38 639nlm_swap_auxiliary_headers_out (bfd *abfd)
252b5132 640{
dc810e39
AM
641 bfd_size_type amt;
642
252b5132 643 /* Write out the version header if there is one. */
7920ce38 644 if (find_nonzero (nlm_version_header (abfd),
252b5132
RH
645 sizeof (Nlm_Internal_Version_Header)))
646 {
647 Nlm_External_Version_Header thdr;
648
649 memcpy (thdr.stamp, "VeRsIoN#", 8);
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);
7920ce38 662 if (bfd_bwrite ((void *) &thdr, (bfd_size_type) sizeof (thdr), abfd)
dc810e39 663 != sizeof (thdr))
b34976b6 664 return FALSE;
252b5132
RH
665 }
666
9e12c7db
NC
667 /* Note - the CoPyRiGhT tag is emitted before the MeSsAgEs
668 tag in order to make the NW4.x and NW5.x loaders happy. */
669
670 /* Write out the copyright header if there is one. */
7920ce38 671 if (find_nonzero (nlm_copyright_header (abfd),
9e12c7db
NC
672 sizeof (Nlm_Internal_Copyright_Header)))
673 {
674 Nlm_External_Copyright_Header thdr;
675
676 memcpy (thdr.stamp, "CoPyRiGhT=", 10);
677 amt = sizeof (thdr.stamp);
7920ce38 678 if (bfd_bwrite ((void *) thdr.stamp, amt, abfd) != amt)
b34976b6 679 return FALSE;
9e12c7db
NC
680 thdr.copyrightMessageLength[0] =
681 nlm_copyright_header (abfd)->copyrightMessageLength;
682 amt = 1;
7920ce38 683 if (bfd_bwrite ((void *) thdr.copyrightMessageLength, amt, abfd) != amt)
b34976b6 684 return FALSE;
9e12c7db
NC
685 /* The copyright message is a variable length string. */
686 amt = nlm_copyright_header (abfd)->copyrightMessageLength + 1;
7920ce38 687 if (bfd_bwrite ((void *) nlm_copyright_header (abfd)->copyrightMessage,
9e12c7db 688 amt, abfd) != amt)
b34976b6 689 return FALSE;
9e12c7db
NC
690 }
691
252b5132 692 /* Write out the extended header if there is one. */
7920ce38 693 if (find_nonzero (nlm_extended_header (abfd),
252b5132
RH
694 sizeof (Nlm_Internal_Extended_Header)))
695 {
696 Nlm_External_Extended_Header thdr;
697
698 memcpy (thdr.stamp, "MeSsAgEs", 8);
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);
7920ce38 786 if (bfd_bwrite ((void *) &thdr, (bfd_size_type) sizeof (thdr), abfd)
dc810e39 787 != sizeof (thdr))
b34976b6 788 return FALSE;
252b5132
RH
789 }
790
252b5132 791 /* Write out the custom header if there is one. */
7920ce38 792 if (find_nonzero (nlm_custom_header (abfd),
252b5132
RH
793 sizeof (Nlm_Internal_Custom_Header)))
794 {
795 Nlm_External_Custom_Header thdr;
b34976b6 796 bfd_boolean ds;
252b5132
RH
797 bfd_size_type hdrLength;
798
7920ce38 799 ds = find_nonzero (nlm_custom_header (abfd)->dataStamp,
252b5132
RH
800 sizeof (nlm_custom_header (abfd)->dataStamp));
801 memcpy (thdr.stamp, "CuStHeAd", 8);
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)
810 {
811 BFD_ASSERT (nlm_custom_header (abfd)->hdrLength == 0);
dc810e39 812 amt = sizeof (thdr) - sizeof (thdr.dataStamp);
7920ce38 813 if (bfd_bwrite ((void *) &thdr, amt, abfd) != amt)
b34976b6 814 return FALSE;
252b5132
RH
815 }
816 else
817 {
818 memcpy (thdr.dataStamp, nlm_custom_header (abfd)->dataStamp,
819 sizeof (thdr.dataStamp));
dc810e39 820 amt = sizeof (thdr);
7920ce38 821 if (bfd_bwrite ((void *) &thdr, amt, abfd) != amt)
b34976b6 822 return FALSE;
dc810e39
AM
823 amt = nlm_custom_header (abfd)->hdrLength;
824 if (bfd_bwrite (nlm_custom_header (abfd)->hdr, amt, abfd) != amt)
b34976b6 825 return FALSE;
252b5132
RH
826 }
827 }
828
829 /* Write out the Cygnus debugging header if there is one. */
7920ce38 830 if (find_nonzero (nlm_cygnus_ext_header (abfd),
252b5132
RH
831 sizeof (Nlm_Internal_Cygnus_Ext_Header)))
832 {
833 Nlm_External_Custom_Header thdr;
834
835 memcpy (thdr.stamp, "CuStHeAd", 8);
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 memcpy (thdr.dataStamp, "CyGnUsEx", 8);
dc810e39 843 amt = sizeof (thdr);
7920ce38 844 if (bfd_bwrite ((void *) &thdr, amt, abfd) != amt)
b34976b6 845 return FALSE;
252b5132
RH
846 }
847
b34976b6 848 return TRUE;
252b5132
RH
849}
850
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.
855
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
1518639e 858 on this size. */
252b5132
RH
859
860long
7920ce38 861nlm_get_symtab_upper_bound (bfd *abfd)
252b5132 862{
9e12c7db 863 Nlm_Internal_Fixed_Header *i_fxdhdrp; /* Nlm file header, internal form. */
252b5132
RH
864 long symcount;
865 long symtab_size = 0;
866
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));
7920ce38 872 return symtab_size;
252b5132
RH
873}
874
875/* Slurp in nlm symbol table.
876
877 In the external (in-file) form, NLM export records are variable length,
878 with the following form:
879
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
883
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.
888
7920ce38 889 The bfd symbols are copied to SYMvoid *S.
252b5132
RH
890
891 When we return, the bfd symcount is either zero or contains the correct
9e12c7db 892 number of symbols. */
252b5132 893
b34976b6 894static bfd_boolean
7920ce38 895nlm_slurp_symbol_table (bfd *abfd)
252b5132 896{
9e12c7db
NC
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. */
7920ce38
NC
904 bfd_boolean (*read_import_func) (bfd *, nlm_symbol_type *);
905 bfd_boolean (*set_public_section_func) (bfd *, nlm_symbol_type *);
dc810e39 906 bfd_size_type amt;
252b5132
RH
907
908 if (nlm_get_symbols (abfd) != NULL)
b34976b6 909 return TRUE;
252b5132
RH
910
911 /* Read each raw NLM symbol, using the information to create a canonical bfd
912 symbol table entry.
913
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.
1518639e 917 When we have all the symbols, we build the caller's pointer vector. */
252b5132
RH
918
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)
b34976b6 925 return TRUE;
252b5132 926
dc810e39 927 if (bfd_seek (abfd, i_fxdhdrp->publicsOffset, SEEK_SET) != 0)
b34976b6 928 return FALSE;
252b5132 929
dc810e39 930 amt = totsymcount * sizeof (nlm_symbol_type);
7920ce38 931 sym = bfd_zalloc (abfd, amt);
252b5132 932 if (!sym)
b34976b6 933 return FALSE;
252b5132
RH
934 nlm_set_symbols (abfd, sym);
935
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
1518639e 938 were read. */
252b5132
RH
939
940 set_public_section_func = nlm_set_public_section_func (abfd);
941 symcount = i_fxdhdrp->numberOfPublics;
942 while (abfd->symcount < symcount)
943 {
dc810e39 944 amt = sizeof (symlength);
7920ce38 945 if (bfd_bread ((void *) &symlength, amt, abfd) != amt)
b34976b6 946 return FALSE;
dc810e39 947 amt = symlength;
252b5132 948 sym->symbol.the_bfd = abfd;
dc810e39 949 sym->symbol.name = bfd_alloc (abfd, amt + 1);
252b5132 950 if (!sym->symbol.name)
b34976b6 951 return FALSE;
7920ce38 952 if (bfd_bread ((void *) sym->symbol.name, amt, abfd) != amt)
b34976b6 953 return FALSE;
252b5132
RH
954 /* Cast away const. */
955 ((char *) (sym->symbol.name))[symlength] = '\0';
dc810e39 956 amt = sizeof (temp);
7920ce38 957 if (bfd_bread ((void *) temp, amt, abfd) != amt)
b34976b6 958 return FALSE;
252b5132
RH
959 sym->symbol.flags = BSF_GLOBAL | BSF_EXPORT;
960 sym->symbol.value = get_word (abfd, temp);
961 if (set_public_section_func)
962 {
963 /* Most backends can use the code below, but unfortunately
964 some use a different scheme. */
82e51918 965 if (! (*set_public_section_func) (abfd, sym))
b34976b6 966 return FALSE;
252b5132
RH
967 }
968 else
969 {
970 if (sym->symbol.value & NLM_HIBIT)
971 {
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);
976 }
977 else
7920ce38
NC
978 sym->symbol.section =
979 bfd_get_section_by_name (abfd, NLM_INITIALIZED_DATA_NAME);
252b5132
RH
980 }
981 sym->rcnt = 0;
982 abfd->symcount++;
983 sym++;
984 }
985
986 /* Read the debugging records. */
987
988 if (i_fxdhdrp->numberOfDebugRecords > 0)
989 {
dc810e39 990 if (bfd_seek (abfd, i_fxdhdrp->debugInfoOffset, SEEK_SET) != 0)
b34976b6 991 return FALSE;
252b5132
RH
992
993 symcount += i_fxdhdrp->numberOfDebugRecords;
994 while (abfd->symcount < symcount)
995 {
dc810e39 996 amt = sizeof (symtype);
7920ce38 997 if (bfd_bread ((void *) &symtype, amt, abfd) != amt)
b34976b6 998 return FALSE;
dc810e39 999 amt = sizeof (temp);
7920ce38 1000 if (bfd_bread ((void *) temp, amt, abfd) != amt)
b34976b6 1001 return FALSE;
dc810e39 1002 amt = sizeof (symlength);
7920ce38 1003 if (bfd_bread ((void *) &symlength, amt, abfd) != amt)
b34976b6 1004 return FALSE;
dc810e39 1005 amt = symlength;
252b5132 1006 sym->symbol.the_bfd = abfd;
dc810e39 1007 sym->symbol.name = bfd_alloc (abfd, amt + 1);
252b5132 1008 if (!sym->symbol.name)
b34976b6 1009 return FALSE;
7920ce38 1010 if (bfd_bread ((void *) sym->symbol.name, amt, abfd) != amt)
b34976b6 1011 return FALSE;
252b5132
RH
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);
7920ce38 1016
252b5132 1017 if (symtype == 0)
7920ce38
NC
1018 sym->symbol.section =
1019 bfd_get_section_by_name (abfd, NLM_INITIALIZED_DATA_NAME);
252b5132
RH
1020 else if (symtype == 1)
1021 {
1022 sym->symbol.flags |= BSF_FUNCTION;
1023 sym->symbol.section =
1024 bfd_get_section_by_name (abfd, NLM_CODE_NAME);
1025 }
1026 else
7920ce38
NC
1027 sym->symbol.section = bfd_abs_section_ptr;
1028
252b5132
RH
1029 sym->rcnt = 0;
1030 abfd->symcount++;
1031 sym++;
1032 }
1033 }
1034
1035 /* Read in the import records. We can only do this if we know how
1036 to read relocs for this target. */
252b5132
RH
1037 read_import_func = nlm_read_import_func (abfd);
1038 if (read_import_func != NULL)
1039 {
dc810e39 1040 if (bfd_seek (abfd, i_fxdhdrp->externalReferencesOffset, SEEK_SET) != 0)
b34976b6 1041 return FALSE;
252b5132
RH
1042
1043 symcount += i_fxdhdrp->numberOfExternalReferences;
1044 while (abfd->symcount < symcount)
1045 {
82e51918 1046 if (! (*read_import_func) (abfd, sym))
b34976b6 1047 return FALSE;
252b5132
RH
1048 sym++;
1049 abfd->symcount++;
1050 }
1051 }
1052
b34976b6 1053 return TRUE;
252b5132 1054}
7920ce38
NC
1055
1056/* Note that bfd_get_symcount is guaranteed to be zero if slurping the
1057 symbol table fails. */
1058
1059long
1060nlm_canonicalize_symtab (bfd *abfd, asymbol **alocation)
1061{
1062 nlm_symbol_type *symbase;
1063 bfd_size_type counter = 0;
1064
1065 if (! nlm_slurp_symbol_table (abfd))
1066 return -1;
1067 symbase = nlm_get_symbols (abfd);
1068 while (counter < bfd_get_symcount (abfd))
1069 {
1070 *alocation++ = &symbase->symbol;
1071 symbase++;
1072 counter++;
1073 }
1074 *alocation = NULL;
1075 return bfd_get_symcount (abfd);
1076}
1077
1078/* Make an NLM symbol. There is nothing special to do here. */
1079
1080asymbol *
1081nlm_make_empty_symbol (bfd *abfd)
1082{
1083 bfd_size_type amt = sizeof (nlm_symbol_type);
1084 nlm_symbol_type *new = bfd_zalloc (abfd, amt);
1085
1086 if (new == NULL)
1087 return NULL;
1088 new->symbol.the_bfd = abfd;
1089 return & new->symbol;
1090}
1091
1092/* Get symbol information. */
1093
1094void
1095nlm_get_symbol_info (bfd *ignore_abfd ATTRIBUTE_UNUSED,
1096 asymbol *symbol,
1097 symbol_info *ret)
1098{
1099 bfd_symbol_info (symbol, ret);
1100}
1101
1102/* Print symbol information. */
1103
1104void
1105nlm_print_symbol (bfd *abfd,
1106 void * afile,
1107 asymbol *symbol,
1108 bfd_print_symbol_type how)
1109{
1110 FILE *file = (FILE *) afile;
1111
1112 switch (how)
1113 {
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;
1125 }
1126}
252b5132
RH
1127\f
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.
1132
1133 The actual format used to store the relocs is machine specific. */
1134
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. */
1140
b34976b6 1141static bfd_boolean
7920ce38 1142nlm_slurp_reloc_fixups (bfd *abfd)
252b5132 1143{
7920ce38 1144 bfd_boolean (*read_func) (bfd *, nlm_symbol_type *, asection **, arelent *);
dc810e39 1145 bfd_size_type count, amt;
252b5132
RH
1146 arelent *rels;
1147 asection **secs;
1148
1149 if (nlm_relocation_fixups (abfd) != NULL)
b34976b6 1150 return TRUE;
252b5132
RH
1151 read_func = nlm_read_reloc_func (abfd);
1152 if (read_func == NULL)
b34976b6 1153 return TRUE;
252b5132
RH
1154
1155 if (bfd_seek (abfd, nlm_fixed_header (abfd)->relocationFixupOffset,
1156 SEEK_SET) != 0)
b34976b6 1157 return FALSE;
252b5132
RH
1158
1159 count = nlm_fixed_header (abfd)->numberOfRelocationFixups;
dc810e39 1160 amt = count * sizeof (arelent);
7920ce38 1161 rels = bfd_alloc (abfd, amt);
dc810e39 1162 amt = count * sizeof (asection *);
7920ce38 1163 secs = bfd_alloc (abfd, amt);
252b5132 1164 if ((rels == NULL || secs == NULL) && count != 0)
b34976b6 1165 return FALSE;
252b5132
RH
1166 nlm_relocation_fixups (abfd) = rels;
1167 nlm_relocation_fixup_secs (abfd) = secs;
1168
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)
1172 {
7920ce38 1173 if (! (*read_func) (abfd, NULL, secs, rels))
252b5132
RH
1174 {
1175 nlm_relocation_fixups (abfd) = NULL;
1176 nlm_relocation_fixup_secs (abfd) = NULL;
b34976b6 1177 return FALSE;
252b5132
RH
1178 }
1179 ++secs;
1180 ++rels;
1181 }
1182
b34976b6 1183 return TRUE;
252b5132
RH
1184}
1185
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. */
1189
1190long
7920ce38 1191nlm_get_reloc_upper_bound (bfd *abfd, asection *sec)
252b5132
RH
1192{
1193 nlm_symbol_type *syms;
1194 bfd_size_type count;
1195 unsigned int ret;
1196
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;
1203
1204 syms = nlm_get_symbols (abfd);
1205 if (syms == NULL)
1206 {
82e51918 1207 if (! nlm_slurp_symbol_table (abfd))
252b5132
RH
1208 return -1;
1209 syms = nlm_get_symbols (abfd);
1210 }
1211
1212 ret = nlm_fixed_header (abfd)->numberOfRelocationFixups;
1213
1214 count = bfd_get_symcount (abfd);
1215 while (count-- != 0)
1216 {
1217 ret += syms->rcnt;
1218 ++syms;
1219 }
1220
1221 return (ret + 1) * sizeof (arelent *);
1222}
1223
1224/* Get the relocs themselves. */
1225
1226long
7920ce38
NC
1227nlm_canonicalize_reloc (bfd *abfd,
1228 asection *sec,
1229 arelent **relptr,
1230 asymbol **symbols)
252b5132
RH
1231{
1232 arelent *rels;
1233 asection **secs;
1234 bfd_size_type count, i;
7920ce38 1235 long ret;
252b5132
RH
1236
1237 /* Get the relocation fixups. */
1238 rels = nlm_relocation_fixups (abfd);
1239 if (rels == NULL)
1240 {
82e51918 1241 if (! nlm_slurp_reloc_fixups (abfd))
252b5132
RH
1242 return -1;
1243 rels = nlm_relocation_fixups (abfd);
1244 }
1245 secs = nlm_relocation_fixup_secs (abfd);
1246
1247 ret = 0;
1248 count = nlm_fixed_header (abfd)->numberOfRelocationFixups;
1249 for (i = 0; i < count; i++, rels++, secs++)
1250 {
1251 if (*secs == sec)
1252 {
1253 *relptr++ = rels;
1254 ++ret;
1255 }
1256 }
1257
1258 /* Get the import symbols. */
1259 count = bfd_get_symcount (abfd);
1260 for (i = 0; i < count; i++, symbols++)
1261 {
1262 asymbol *sym;
1263
1264 sym = *symbols;
1265 if (bfd_asymbol_flavour (sym) == bfd_target_nlm_flavour)
1266 {
1267 nlm_symbol_type *nlm_sym;
1268 bfd_size_type j;
1269
1270 nlm_sym = (nlm_symbol_type *) sym;
1271 for (j = 0; j < nlm_sym->rcnt; j++)
1272 {
1273 if (nlm_sym->relocs[j].section == sec)
1274 {
1275 *relptr = &nlm_sym->relocs[j].reloc;
1276 (*relptr)->sym_ptr_ptr = symbols;
1277 ++relptr;
1278 ++ret;
1279 }
1280 }
1281 }
1282 }
1283
1284 *relptr = NULL;
1285
1286 return ret;
1287}
1288\f
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.
1294
1295 This routine also sets the Size and Offset fields in the fixed
1296 header.
1297
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. */
1304
b34976b6 1305static bfd_boolean
7920ce38 1306nlm_compute_section_file_positions (bfd *abfd)
252b5132
RH
1307{
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;
1316
82e51918 1317 if (abfd->output_has_begun)
b34976b6 1318 return TRUE;
252b5132
RH
1319
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)
1323 {
1324 if (!add_bfd_section (abfd, NLM_UNINITIALIZED_DATA_NAME,
1325 (file_ptr) 0, (bfd_size_type) 0,
1326 SEC_ALLOC))
b34976b6 1327 return FALSE;
252b5132
RH
1328 bss_sec = bfd_get_section_by_name (abfd, NLM_UNINITIALIZED_DATA_NAME);
1329 }
1330
b34976b6 1331 abfd->output_has_begun = TRUE;
252b5132
RH
1332
1333 /* The fixed header. */
1334 sofar = nlm_optional_prefix_size (abfd) + nlm_fixed_header_size (abfd);
1335
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);
1346
1347 /* The auxiliary headers. */
7920ce38 1348 if (find_nonzero (nlm_version_header (abfd),
252b5132
RH
1349 sizeof (Nlm_Internal_Version_Header)))
1350 sofar += sizeof (Nlm_External_Version_Header);
7920ce38 1351 if (find_nonzero (nlm_extended_header (abfd),
252b5132
RH
1352 sizeof (Nlm_Internal_Extended_Header)))
1353 sofar += sizeof (Nlm_External_Extended_Header);
7920ce38 1354 if (find_nonzero (nlm_copyright_header (abfd),
252b5132
RH
1355 sizeof (Nlm_Internal_Copyright_Header)))
1356 sofar += (sizeof (Nlm_External_Copyright_Header)
1357 + nlm_copyright_header (abfd)->copyrightMessageLength + 1);
7920ce38 1358 if (find_nonzero (nlm_custom_header (abfd),
252b5132
RH
1359 sizeof (Nlm_Internal_Custom_Header)))
1360 sofar += (sizeof (Nlm_External_Custom_Header)
1361 + nlm_custom_header (abfd)->hdrLength);
7920ce38 1362 if (find_nonzero (nlm_cygnus_ext_header (abfd),
252b5132
RH
1363 sizeof (Nlm_Internal_Cygnus_Ext_Header)))
1364 sofar += sizeof (Nlm_External_Custom_Header);
1365
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;
7920ce38 1379 for (sec = abfd->sections; sec != NULL; sec = sec->next)
252b5132
RH
1380 {
1381 flagword f;
1382
eea6121a 1383 sec->size = BFD_ALIGN (sec->size, 1 << sec->alignment_power);
252b5132
RH
1384
1385 f = bfd_get_section_flags (abfd, sec);
1386 if (f & SEC_CODE)
1387 {
eea6121a 1388 text += sec->size;
252b5132
RH
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;
1393 }
1394 else if (f & SEC_DATA)
1395 {
eea6121a 1396 data += sec->size;
252b5132
RH
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;
1401 }
1402 else if (f & SEC_HAS_CONTENTS)
1403 {
1404 if (sec->alignment_power > other_align)
1405 other_align = sec->alignment_power;
1406 }
1407 else if (f & SEC_ALLOC)
eea6121a 1408 bss += sec->size;
252b5132
RH
1409 }
1410
1411 nlm_set_text_low (abfd, text_low);
1412 nlm_set_data_low (abfd, data_low);
1413
1414 if (nlm_no_uninitialized_data (abfd))
1415 {
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;
1421 }
1422
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);
1426
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;
1434
7920ce38 1435 for (sec = abfd->sections; sec != NULL; sec = sec->next)
252b5132
RH
1436 {
1437 flagword f;
1438
1439 f = bfd_get_section_flags (abfd, sec);
1440
1441 if (f & SEC_CODE)
1442 {
1443 sec->filepos = text_ptr;
eea6121a 1444 text_ptr += sec->size;
252b5132
RH
1445 }
1446 else if (f & SEC_DATA)
1447 {
1448 sec->filepos = data_ptr;
eea6121a 1449 data_ptr += sec->size;
252b5132
RH
1450 }
1451 else if (f & SEC_HAS_CONTENTS)
1452 {
1453 sec->filepos = other_ptr;
eea6121a 1454 other_ptr += sec->size;
252b5132
RH
1455 }
1456 }
1457
1458 nlm_fixed_header (abfd)->relocationFixupOffset = other_ptr;
1459
1460 /* Move all common symbols into the .bss section. */
1461
1462 sym_ptr_ptr = bfd_get_outsymbols (abfd);
1463 if (sym_ptr_ptr != NULL)
1464 {
1465 asymbol **sym_end;
1466 bfd_vma add;
1467
1468 sym_end = sym_ptr_ptr + bfd_get_symcount (abfd);
1469 add = 0;
1470 for (; sym_ptr_ptr < sym_end; sym_ptr_ptr++)
1471 {
1472 asymbol *sym;
1473 bfd_vma size;
1474
1475 sym = *sym_ptr_ptr;
1476
1477 if (!bfd_is_com_section (bfd_get_section (sym)))
1478 continue;
1479
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;
eea6121a 1485 sym->value = bss_sec->size + add;
252b5132
RH
1486 add += size;
1487 add = BFD_ALIGN (add, 1 << bss_sec->alignment_power);
1488 }
1489 if (add != 0)
1490 {
1491 if (nlm_no_uninitialized_data (abfd))
1492 {
1493 /* We could handle this case, but so far it hasn't been
1494 necessary. */
1495 abort ();
1496 }
1497 nlm_fixed_header (abfd)->uninitializedDataSize += add;
eea6121a 1498 bss_sec->size += add;
252b5132
RH
1499 }
1500 }
1501
b34976b6 1502 return TRUE;
252b5132
RH
1503}
1504
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. */
1509
b34976b6 1510bfd_boolean
7920ce38
NC
1511nlm_set_section_contents (bfd *abfd,
1512 asection *section,
1513 const void * location,
1514 file_ptr offset,
1515 bfd_size_type count)
252b5132 1516{
82e51918
AM
1517 if (! abfd->output_has_begun
1518 && ! nlm_compute_section_file_positions (abfd))
b34976b6 1519 return FALSE;
252b5132
RH
1520
1521 if (count == 0)
b34976b6 1522 return TRUE;
252b5132
RH
1523
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)
1529 {
b34976b6 1530 bfd_boolean (*mangle_relocs_func)
7920ce38 1531 (bfd *, asection *, const void *, bfd_vma, bfd_size_type);
252b5132
RH
1532
1533 mangle_relocs_func = nlm_mangle_relocs_func (abfd);
1534 if (mangle_relocs_func != NULL)
1535 {
1536 if (!(*mangle_relocs_func) (abfd, section, location,
1537 (bfd_vma) offset, count))
b34976b6 1538 return FALSE;
252b5132
RH
1539 }
1540 }
1541
dc810e39
AM
1542 if (bfd_seek (abfd, section->filepos + offset, SEEK_SET) != 0
1543 || bfd_bwrite (location, count, abfd) != count)
b34976b6 1544 return FALSE;
252b5132 1545
b34976b6 1546 return TRUE;
252b5132
RH
1547}
1548
1549/* We need to sort a list of relocs associated with sections when we
1550 write out the external relocs. */
1551
1552static int
7920ce38 1553nlm_external_reloc_compare (const void *p1, const void *p2)
252b5132
RH
1554{
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;
1558
1559 cmp = strcmp ((*r1->rel->sym_ptr_ptr)->name,
1560 (*r2->rel->sym_ptr_ptr)->name);
1561 if (cmp != 0)
1562 return cmp;
1563
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);
1568}
1569
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.
1587
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. */
1597
b34976b6 1598bfd_boolean
7920ce38 1599nlm_write_object_contents (bfd *abfd)
252b5132
RH
1600{
1601 asection *sec;
7920ce38 1602 bfd_boolean (*write_import_func) (bfd *, asection *, arelent *);
252b5132
RH
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;
7920ce38 1607 bfd_boolean (*write_prefix_func) (bfd *);
252b5132 1608 unsigned char *fixed_header = NULL;
dc810e39
AM
1609 file_ptr pos;
1610 bfd_size_type amt;
252b5132 1611
7920ce38 1612 fixed_header = bfd_malloc (nlm_fixed_header_size (abfd));
252b5132
RH
1613 if (fixed_header == NULL)
1614 goto error_return;
1615
82e51918
AM
1616 if (! abfd->output_has_begun
1617 && ! nlm_compute_section_file_positions (abfd))
252b5132
RH
1618 goto error_return;
1619
1620 /* Write out the variable length headers. */
dc810e39
AM
1621 pos = nlm_optional_prefix_size (abfd) + nlm_fixed_header_size (abfd);
1622 if (bfd_seek (abfd, pos, SEEK_SET) != 0)
252b5132 1623 goto error_return;
82e51918
AM
1624 if (! nlm_swap_variable_header_out (abfd)
1625 || ! nlm_swap_auxiliary_headers_out (abfd))
252b5132
RH
1626 {
1627 bfd_set_error (bfd_error_system_call);
1628 goto error_return;
1629 }
1630
1631 /* A weak check on whether the section file positions were
1632 reasonable. */
de52dba4 1633 if (bfd_tell (abfd) > nlm_fixed_header (abfd)->codeImageOffset)
252b5132
RH
1634 {
1635 bfd_set_error (bfd_error_invalid_operation);
1636 goto error_return;
1637 }
1638
1639 /* Advance to the relocs. */
1640 if (bfd_seek (abfd, nlm_fixed_header (abfd)->relocationFixupOffset,
1641 SEEK_SET) != 0)
1642 goto error_return;
1643
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);
1648
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;
7920ce38 1654 for (sec = abfd->sections; sec != NULL; sec = sec->next)
252b5132
RH
1655 {
1656 arelent **rel_ptr_ptr, **rel_end;
1657
1658 if (sec->reloc_count == 0)
1659 continue;
1660
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;
1665
1666 /* We need to know how to write out imports */
1667 if (write_import_func == NULL)
1668 {
1669 bfd_set_error (bfd_error_invalid_operation);
1670 goto error_return;
1671 }
1672
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++)
1676 {
1677 arelent *rel;
1678 asymbol *sym;
1679
1680 rel = *rel_ptr_ptr;
1681 sym = *rel->sym_ptr_ptr;
1682
1683 if (! bfd_is_und_section (bfd_get_section (sym)))
1684 {
1685 ++internal_reloc_count;
82e51918 1686 if (! (*write_import_func) (abfd, sec, rel))
252b5132
RH
1687 goto error_return;
1688 }
1689 else
1690 ++external_reloc_count;
1691 }
1692 }
1693 nlm_fixed_header (abfd)->numberOfRelocationFixups = internal_reloc_count;
1694
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. */
dc810e39 1699 amt = external_reloc_count * sizeof (struct reloc_and_sec);
7920ce38
NC
1700 external_relocs = bfd_alloc (abfd, amt);
1701 if (external_relocs == NULL)
252b5132
RH
1702 goto error_return;
1703 i = 0;
7920ce38 1704 for (sec = abfd->sections; sec != NULL; sec = sec->next)
252b5132
RH
1705 {
1706 arelent **rel_ptr_ptr, **rel_end;
1707
1708 if (sec->reloc_count == 0)
1709 continue;
1710
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++)
1714 {
1715 arelent *rel;
1716 asymbol *sym;
1717
1718 rel = *rel_ptr_ptr;
1719 sym = *rel->sym_ptr_ptr;
1720
1721 if (! bfd_is_und_section (bfd_get_section (sym)))
1722 continue;
1723
1724 external_relocs[i].rel = rel;
1725 external_relocs[i].sec = sec;
1726 ++i;
1727 }
1728 }
1729
1730 BFD_ASSERT (i == external_reloc_count);
1731
1732 /* Sort the external relocs by name. */
7920ce38 1733 qsort (external_relocs, (size_t) external_reloc_count,
252b5132
RH
1734 sizeof (struct reloc_and_sec), nlm_external_reloc_compare);
1735
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)
1741 {
1742 arelent *rel;
1743 asymbol *sym;
1744 bfd_size_type j, cnt;
1745
1746 ++c;
1747
1748 rel = external_relocs[i].rel;
1749 sym = *rel->sym_ptr_ptr;
1750
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;
1757
82e51918
AM
1758 if (! (*nlm_write_external_func (abfd)) (abfd, cnt, sym,
1759 &external_relocs[i]))
252b5132
RH
1760 goto error_return;
1761
1762 i += cnt;
1763 }
1764
1765 nlm_fixed_header (abfd)->numberOfExternalReferences = c;
1766
1767 /* Write out the public symbols (exports). */
1768 sym_ptr_ptr = bfd_get_outsymbols (abfd);
7920ce38 1769 if (sym_ptr_ptr != NULL)
252b5132 1770 {
7920ce38
NC
1771 bfd_vma (*get_public_offset_func) (bfd *, asymbol *);
1772 bfd_boolean (*write_export_func) (bfd *, asymbol *, bfd_vma);
252b5132
RH
1773
1774 asymbol **sym_end;
1775
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++)
1782 {
1783 asymbol *sym;
1784 bfd_byte len;
1785 bfd_vma offset;
1786 bfd_byte temp[NLM_TARGET_LONG_SIZE];
1787
1788 sym = *sym_ptr_ptr;
1789
1790 if ((sym->flags & (BSF_EXPORT | BSF_GLOBAL)) == 0
1791 || bfd_is_und_section (bfd_get_section (sym)))
1792 continue;
1793
1794 ++c;
1795
1796 if (get_public_offset_func)
1797 {
1798 /* Most backends can use the code below, but
1799 unfortunately some use a different scheme. */
1800 offset = (*get_public_offset_func) (abfd, sym);
1801 }
1802 else
1803 {
1804 offset = bfd_asymbol_value (sym);
1805 sec = sym->section;
1806 if (sec->flags & SEC_CODE)
1807 {
1808 offset -= nlm_get_text_low (abfd);
1809 offset |= NLM_HIBIT;
1810 }
1811 else if (sec->flags & (SEC_DATA | SEC_ALLOC))
1812 {
1813 /* SEC_ALLOC is for the .bss section. */
1814 offset -= nlm_get_data_low (abfd);
1815 }
1816 else
1817 {
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;
1822 }
1823 }
1824
1825 if (write_export_func)
1826 {
82e51918 1827 if (! (*write_export_func) (abfd, sym, offset))
252b5132
RH
1828 goto error_return;
1829 }
1830 else
1831 {
1832 len = strlen (sym->name);
dc810e39 1833 if ((bfd_bwrite (&len, (bfd_size_type) sizeof (bfd_byte), abfd)
252b5132 1834 != sizeof (bfd_byte))
dc810e39 1835 || bfd_bwrite (sym->name, (bfd_size_type) len, abfd) != len)
252b5132
RH
1836 goto error_return;
1837
1838 put_word (abfd, offset, temp);
dc810e39
AM
1839 if (bfd_bwrite (temp, (bfd_size_type) sizeof (temp), abfd)
1840 != sizeof (temp))
252b5132
RH
1841 goto error_return;
1842 }
1843 }
1844 nlm_fixed_header (abfd)->numberOfPublics = c;
1845
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)
1853 {
1854 nlm_fixed_header (abfd)->debugInfoOffset = 0;
1855 nlm_fixed_header (abfd)->numberOfDebugRecords = 0;
1856 }
1857 else
1858 {
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++)
1864 {
1865 asymbol *sym;
1866 bfd_byte type, len;
1867 bfd_vma offset;
1868 bfd_byte temp[NLM_TARGET_LONG_SIZE];
1869
1870 sym = *sym_ptr_ptr;
1871
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;
1879
1880 ++c;
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 type = 1;
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 type = 0;
1894 }
1895 else
1896 type = 2;
1897
1898 /* The type is 0 for data, 1 for code, 2 for absolute. */
dc810e39 1899 if (bfd_bwrite (&type, (bfd_size_type) sizeof (bfd_byte), abfd)
252b5132
RH
1900 != sizeof (bfd_byte))
1901 goto error_return;
1902
1903 put_word (abfd, offset, temp);
dc810e39
AM
1904 if (bfd_bwrite (temp, (bfd_size_type) sizeof (temp), abfd)
1905 != sizeof (temp))
252b5132
RH
1906 goto error_return;
1907
1908 len = strlen (sym->name);
dc810e39 1909 if ((bfd_bwrite (&len, (bfd_size_type) sizeof (bfd_byte), abfd)
252b5132 1910 != sizeof (bfd_byte))
dc810e39 1911 || bfd_bwrite (sym->name, (bfd_size_type) len, abfd) != len)
252b5132
RH
1912 goto error_return;
1913 }
1914 nlm_fixed_header (abfd)->numberOfDebugRecords = c;
1915 }
1916 }
1917
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;
1937
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));
1946
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);
1954
dc810e39 1955 if (bfd_seek (abfd, (file_ptr) 0, SEEK_SET) != 0)
252b5132
RH
1956 goto error_return;
1957
1958 write_prefix_func = nlm_write_prefix_func (abfd);
1959 if (write_prefix_func)
1960 {
82e51918 1961 if (! (*write_prefix_func) (abfd))
252b5132
RH
1962 goto error_return;
1963 }
1964
1965 BFD_ASSERT ((bfd_size_type) bfd_tell (abfd)
1966 == nlm_optional_prefix_size (abfd));
1967
1968 nlm_swap_fixed_header_out (abfd, nlm_fixed_header (abfd), fixed_header);
dc810e39 1969 if (bfd_bwrite (fixed_header, nlm_fixed_header_size (abfd), abfd)
252b5132
RH
1970 != nlm_fixed_header_size (abfd))
1971 goto error_return;
1972
1973 if (fixed_header != NULL)
1974 free (fixed_header);
b34976b6 1975 return TRUE;
252b5132
RH
1976
1977error_return:
1978 if (fixed_header != NULL)
1979 free (fixed_header);
b34976b6 1980 return FALSE;
252b5132 1981}
This page took 0.591215 seconds and 4 git commands to generate.