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