OpenCores
URL https://opencores.org/ocsvn/open8_urisc/open8_urisc/trunk

Subversion Repositories open8_urisc

[/] [open8_urisc/] [trunk/] [gnu/] [binutils/] [bfd/] [nlmcode.h] - Blame information for rev 14

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 14 khays
/* NLM (NetWare Loadable Module) executable support for BFD.
2
   Copyright 1993, 1994, 1995, 1998, 1999, 2000, 2001, 2002, 2003, 2004,
3
   2005, 2006, 2007, 2011  Free Software Foundation, Inc.
4
 
5
   Written by Fred Fish @ Cygnus Support, using ELF support as the
6
   template.
7
 
8
   This file is part of BFD, the Binary File Descriptor library.
9
 
10
   This program is free software; you can redistribute it and/or modify
11
   it under the terms of the GNU General Public License as published by
12
   the Free Software Foundation; either version 3 of the License, or
13
   (at your option) any later version.
14
 
15
   This program is distributed in the hope that it will be useful,
16
   but WITHOUT ANY WARRANTY; without even the implied warranty of
17
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18
   GNU General Public License for more details.
19
 
20
   You should have received a copy of the GNU General Public License
21
   along with this program; if not, write to the Free Software
22
   Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
23
   MA 02110-1301, USA.  */
24
 
25
#include "sysdep.h"
26
#include "bfd.h"
27
#include "libbfd.h"
28
#include "libnlm.h"
29
 
30
/* The functions in this file do not use the names they appear to use.
31
   This file is actually compiled multiple times, once for each size
32
   of NLM target we are using.  At each size we use a different name,
33
   constructed by the macro nlmNAME.  For example, the function which
34
   is named nlm_symbol_type below is actually named nlm32_symbol_type
35
   in the final executable.  */
36
 
37
#define Nlm_External_Fixed_Header       NlmNAME (External_Fixed_Header)
38
#define Nlm_External_Version_Header     NlmNAME (External_Version_Header)
39
#define Nlm_External_Copyright_Header   NlmNAME (External_Copyright_Header)
40
#define Nlm_External_Extended_Header    NlmNAME (External_Extended_Header)
41
#define Nlm_External_Custom_Header      NlmNAME (External_Custom_Header)
42
#define Nlm_External_Cygnus_Ext_Header  NlmNAME (External_Cygnus_Ext_Header)
43
 
44
#define nlm_symbol_type                 nlmNAME (symbol_type)
45
#define nlm_get_symtab_upper_bound      nlmNAME (get_symtab_upper_bound)
46
#define nlm_canonicalize_symtab         nlmNAME (canonicalize_symtab)
47
#define nlm_make_empty_symbol           nlmNAME (make_empty_symbol)
48
#define nlm_print_symbol                nlmNAME (print_symbol)
49
#define nlm_get_symbol_info             nlmNAME (get_symbol_info)
50
#define nlm_get_reloc_upper_bound       nlmNAME (get_reloc_upper_bound)
51
#define nlm_canonicalize_reloc          nlmNAME (canonicalize_reloc)
52
#define nlm_object_p                    nlmNAME (object_p)
53
#define nlm_set_section_contents        nlmNAME (set_section_contents)
54
#define nlm_write_object_contents       nlmNAME (write_object_contents)
55
 
56
#define nlm_swap_fixed_header_in(abfd,src,dst) \
57
  (nlm_swap_fixed_header_in_func (abfd)) (abfd, src, dst)
58
#define nlm_swap_fixed_header_out(abfd,src,dst) \
59
  (nlm_swap_fixed_header_out_func (abfd)) (abfd, src, dst)
60
 
61
/* Should perhaps use put_offset, put_word, etc.  For now, the two versions
62
   can be handled by explicitly specifying 32 bits or "the long type".  */
63
#if ARCH_SIZE == 64
64
#define put_word        H_PUT_64
65
#define get_word        H_GET_64
66
#endif
67
#if ARCH_SIZE == 32
68
#define put_word        H_PUT_32
69
#define get_word        H_GET_32
70
#endif
71
 
72
/* Read and swap in the variable length header.  All the fields must
73
   exist in the NLM, and must exist in the order they are read here.  */
74
 
75
static bfd_boolean
76
nlm_swap_variable_header_in (bfd *abfd)
77
{
78
  unsigned char temp[NLM_TARGET_LONG_SIZE];
79
  bfd_size_type amt;
80
 
81
  /* Read the description length and text members.  */
82
  amt = sizeof (nlm_variable_header (abfd)->descriptionLength);
83
  if (bfd_bread ((void *) &nlm_variable_header (abfd)->descriptionLength,
84
                amt, abfd) != amt)
85
    return FALSE;
86
  amt = nlm_variable_header (abfd)->descriptionLength + 1;
87
  if (bfd_bread ((void *) nlm_variable_header (abfd)->descriptionText,
88
                amt, abfd) != amt)
89
    return FALSE;
90
 
91
  /* Read and convert the stackSize field.  */
92
  amt = sizeof (temp);
93
  if (bfd_bread ((void *) temp, amt, abfd) != amt)
94
    return FALSE;
95
  nlm_variable_header (abfd)->stackSize = get_word (abfd, (bfd_byte *) temp);
96
 
97
  /* Read and convert the reserved field.  */
98
  amt = sizeof (temp);
99
  if (bfd_bread ((void *) temp, amt, abfd) != amt)
100
    return FALSE;
101
  nlm_variable_header (abfd)->reserved = get_word (abfd, (bfd_byte *) temp);
102
 
103
  /* Read the oldThreadName field.  This field is a fixed length string.  */
104
  amt = sizeof (nlm_variable_header (abfd)->oldThreadName);
105
  if (bfd_bread ((void *) nlm_variable_header (abfd)->oldThreadName,
106
                amt, abfd) != amt)
107
    return FALSE;
108
 
109
  /* Read the screen name length and text members.  */
110
  amt = sizeof (nlm_variable_header (abfd)->screenNameLength);
111
  if (bfd_bread ((void *) & nlm_variable_header (abfd)->screenNameLength,
112
                amt, abfd) != amt)
113
    return FALSE;
114
  amt = nlm_variable_header (abfd)->screenNameLength + 1;
115
  if (bfd_bread ((void *) nlm_variable_header (abfd)->screenName,
116
                amt, abfd) != amt)
117
    return FALSE;
118
 
119
  /* Read the thread name length and text members.  */
120
  amt = sizeof (nlm_variable_header (abfd)->threadNameLength);
121
  if (bfd_bread ((void *) & nlm_variable_header (abfd)->threadNameLength,
122
                amt, abfd) != amt)
123
    return FALSE;
124
  amt = nlm_variable_header (abfd)->threadNameLength + 1;
125
  if (bfd_bread ((void *) nlm_variable_header (abfd)->threadName,
126
                amt, abfd) != amt)
127
    return FALSE;
128
  return TRUE;
129
}
130
 
131
/* Add a section to the bfd.  */
132
 
133
static bfd_boolean
134
add_bfd_section (bfd *abfd,
135
                 char *name,
136
                 file_ptr offset,
137
                 bfd_size_type size,
138
                 flagword flags)
139
{
140
  asection *newsect;
141
 
142
  newsect = bfd_make_section_with_flags (abfd, name, flags);
143
  if (newsect == NULL)
144
    return FALSE;
145
 
146
  newsect->vma = 0;              /* NLM's are relocatable.  */
147
  newsect->size = size;
148
  newsect->filepos = offset;
149
  newsect->alignment_power = bfd_log2 ((bfd_vma) 0);     /* FIXME */
150
 
151
  return TRUE;
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
161
   recognize it.  */
162
 
163
static bfd_boolean
164
nlm_swap_auxiliary_headers_in (bfd *abfd)
165
{
166
  char tempstr[16];
167
  file_ptr position;
168
  bfd_size_type amt;
169
 
170
  for (;;)
171
    {
172
      position = bfd_tell (abfd);
173
      amt = sizeof (tempstr);
174
      if (bfd_bread ((void *) tempstr, amt, abfd) != amt)
175
        return FALSE;
176
      if (bfd_seek (abfd, position, SEEK_SET) != 0)
177
        return FALSE;
178
      if (CONST_STRNEQ (tempstr, "VeRsIoN#"))
179
        {
180
          Nlm_External_Version_Header thdr;
181
 
182
          amt = sizeof (thdr);
183
          if (bfd_bread ((void *) &thdr, amt, abfd) != amt)
184
            return FALSE;
185
          memcpy (nlm_version_header (abfd)->stamp, thdr.stamp,
186
                  sizeof (thdr.stamp));
187
          nlm_version_header (abfd)->majorVersion =
188
            get_word (abfd, (bfd_byte *) thdr.majorVersion);
189
          nlm_version_header (abfd)->minorVersion =
190
            get_word (abfd, (bfd_byte *) thdr.minorVersion);
191
          nlm_version_header (abfd)->revision =
192
            get_word (abfd, (bfd_byte *) thdr.revision);
193
          nlm_version_header (abfd)->year =
194
            get_word (abfd, (bfd_byte *) thdr.year);
195
          nlm_version_header (abfd)->month =
196
            get_word (abfd, (bfd_byte *) thdr.month);
197
          nlm_version_header (abfd)->day =
198
            get_word (abfd, (bfd_byte *) thdr.day);
199
        }
200
      else if (CONST_STRNEQ (tempstr, "MeSsAgEs"))
201
        {
202
          Nlm_External_Extended_Header thdr;
203
 
204
          amt = sizeof (thdr);
205
          if (bfd_bread ((void *) &thdr, amt, abfd) != amt)
206
            return FALSE;
207
          memcpy (nlm_extended_header (abfd)->stamp, thdr.stamp,
208
                  sizeof (thdr.stamp));
209
          nlm_extended_header (abfd)->languageID =
210
            get_word (abfd, (bfd_byte *) thdr.languageID);
211
          nlm_extended_header (abfd)->messageFileOffset =
212
            get_word (abfd, (bfd_byte *) thdr.messageFileOffset);
213
          nlm_extended_header (abfd)->messageFileLength =
214
            get_word (abfd, (bfd_byte *) thdr.messageFileLength);
215
          nlm_extended_header (abfd)->messageCount =
216
            get_word (abfd, (bfd_byte *) thdr.messageCount);
217
          nlm_extended_header (abfd)->helpFileOffset =
218
            get_word (abfd, (bfd_byte *) thdr.helpFileOffset);
219
          nlm_extended_header (abfd)->helpFileLength =
220
            get_word (abfd, (bfd_byte *) thdr.helpFileLength);
221
          nlm_extended_header (abfd)->RPCDataOffset =
222
            get_word (abfd, (bfd_byte *) thdr.RPCDataOffset);
223
          nlm_extended_header (abfd)->RPCDataLength =
224
            get_word (abfd, (bfd_byte *) thdr.RPCDataLength);
225
          nlm_extended_header (abfd)->sharedCodeOffset =
226
            get_word (abfd, (bfd_byte *) thdr.sharedCodeOffset);
227
          nlm_extended_header (abfd)->sharedCodeLength =
228
            get_word (abfd, (bfd_byte *) thdr.sharedCodeLength);
229
          nlm_extended_header (abfd)->sharedDataOffset =
230
            get_word (abfd, (bfd_byte *) thdr.sharedDataOffset);
231
          nlm_extended_header (abfd)->sharedDataLength =
232
            get_word (abfd, (bfd_byte *) thdr.sharedDataLength);
233
          nlm_extended_header (abfd)->sharedRelocationFixupOffset =
234
            get_word (abfd, (bfd_byte *) thdr.sharedRelocationFixupOffset);
235
          nlm_extended_header (abfd)->sharedRelocationFixupCount =
236
            get_word (abfd, (bfd_byte *) thdr.sharedRelocationFixupCount);
237
          nlm_extended_header (abfd)->sharedExternalReferenceOffset =
238
            get_word (abfd, (bfd_byte *) thdr.sharedExternalReferenceOffset);
239
          nlm_extended_header (abfd)->sharedExternalReferenceCount =
240
            get_word (abfd, (bfd_byte *) thdr.sharedExternalReferenceCount);
241
          nlm_extended_header (abfd)->sharedPublicsOffset =
242
            get_word (abfd, (bfd_byte *) thdr.sharedPublicsOffset);
243
          nlm_extended_header (abfd)->sharedPublicsCount =
244
            get_word (abfd, (bfd_byte *) thdr.sharedPublicsCount);
245
          nlm_extended_header (abfd)->sharedDebugRecordOffset =
246
            get_word (abfd, (bfd_byte *) thdr.sharedDebugRecordOffset);
247
          nlm_extended_header (abfd)->sharedDebugRecordCount =
248
            get_word (abfd, (bfd_byte *) thdr.sharedDebugRecordCount);
249
          nlm_extended_header (abfd)->SharedInitializationOffset =
250
            get_word (abfd, (bfd_byte *) thdr.sharedInitializationOffset);
251
          nlm_extended_header (abfd)->SharedExitProcedureOffset =
252
            get_word (abfd, (bfd_byte *) thdr.SharedExitProcedureOffset);
253
          nlm_extended_header (abfd)->productID =
254
            get_word (abfd, (bfd_byte *) thdr.productID);
255
          nlm_extended_header (abfd)->reserved0 =
256
            get_word (abfd, (bfd_byte *) thdr.reserved0);
257
          nlm_extended_header (abfd)->reserved1 =
258
            get_word (abfd, (bfd_byte *) thdr.reserved1);
259
          nlm_extended_header (abfd)->reserved2 =
260
            get_word (abfd, (bfd_byte *) thdr.reserved2);
261
          nlm_extended_header (abfd)->reserved3 =
262
            get_word (abfd, (bfd_byte *) thdr.reserved3);
263
          nlm_extended_header (abfd)->reserved4 =
264
            get_word (abfd, (bfd_byte *) thdr.reserved4);
265
          nlm_extended_header (abfd)->reserved5 =
266
            get_word (abfd, (bfd_byte *) thdr.reserved5);
267
        }
268
      else if (CONST_STRNEQ (tempstr, "CoPyRiGhT="))
269
        {
270
          amt = sizeof (nlm_copyright_header (abfd)->stamp);
271
          if (bfd_bread ((void *) nlm_copyright_header (abfd)->stamp,
272
                        amt, abfd) != amt)
273
            return FALSE;
274
          if (bfd_bread ((void *) &(nlm_copyright_header (abfd)
275
                                ->copyrightMessageLength),
276
                        (bfd_size_type) 1, abfd) != 1)
277
            return FALSE;
278
          /* The copyright message is a variable length string.  */
279
          amt = nlm_copyright_header (abfd)->copyrightMessageLength + 1;
280
          if (bfd_bread ((void *) nlm_copyright_header (abfd)->copyrightMessage,
281
                        amt, abfd) != amt)
282
            return FALSE;
283
        }
284
      else if (CONST_STRNEQ (tempstr, "CuStHeAd"))
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];
291
          void * hdr;
292
 
293
          /* Read the stamp ("CuStHeAd").  */
294
          amt = sizeof (thdr.stamp);
295
          if (bfd_bread ((void *) thdr.stamp, amt, abfd) != amt)
296
            return FALSE;
297
          /* Read the length of this custom header.  */
298
          amt = sizeof (thdr.length);
299
          if (bfd_bread ((void *) thdr.length, amt, abfd) != amt)
300
            return FALSE;
301
          hdrLength = get_word (abfd, (bfd_byte *) thdr.length);
302
          /* Read further fields if we have them.  */
303
          if (hdrLength < NLM_TARGET_LONG_SIZE)
304
            dataOffset = 0;
305
          else
306
            {
307
              amt = sizeof (thdr.dataOffset);
308
              if (bfd_bread ((void *) thdr.dataOffset, amt, abfd) != amt)
309
                return FALSE;
310
              dataOffset = get_word (abfd, (bfd_byte *) thdr.dataOffset);
311
            }
312
          if (hdrLength < 2 * NLM_TARGET_LONG_SIZE)
313
            dataLength = 0;
314
          else
315
            {
316
              amt = sizeof (thdr.dataLength);
317
              if (bfd_bread ((void *) thdr.dataLength, amt, abfd) != amt)
318
                return FALSE;
319
              dataLength = get_word (abfd, (bfd_byte *) thdr.dataLength);
320
            }
321
          if (hdrLength < 2 * NLM_TARGET_LONG_SIZE + 8)
322
            memset (dataStamp, 0, sizeof (dataStamp));
323
          else
324
            {
325
              amt = sizeof (dataStamp);
326
              if (bfd_bread ((void *) dataStamp, amt, abfd) != amt)
327
                return FALSE;
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)
341
                return FALSE;
342
              if (bfd_bread (hdr, hdrLength, abfd) != hdrLength)
343
                return FALSE;
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 (CONST_STRNEQ (dataStamp, "CyGnUsEx"))
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)
359
                return FALSE;
360
              contents = bfd_alloc (abfd, dataLength);
361
              if (contents == NULL)
362
                return FALSE;
363
              if (bfd_bread (contents, dataLength, abfd) != dataLength)
364
                return FALSE;
365
              if (bfd_seek (abfd, pos, SEEK_SET) != 0)
366
                return FALSE;
367
 
368
              LITMEMCPY (nlm_cygnus_ext_header (abfd), "CyGnUsEx");
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
396
                     4 byte section size.  */
397
 
398
                  name = (char *) p;
399
                  l = strlen (name) + 1;
400
                  l = (l + 3) &~ (size_t) 3;
401
                  p += l;
402
                  filepos = H_GET_32 (abfd, p);
403
                  p += 4;
404
                  size = H_GET_32 (abfd, p);
405
                  p += 4;
406
 
407
                  newsec = bfd_make_section_anyway (abfd, name);
408
                  if (newsec == NULL)
409
                    return FALSE;
410
                  newsec->size = size;
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
431
        break;
432
    }
433
  return TRUE;
434
}
435
 
436
const bfd_target *
437
nlm_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 endianness 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
 
552
got_wrong_format_error:
553
  bfd_set_error (bfd_error_wrong_format);
554
got_no_match:
555
  nlm_tdata (abfd) = preserved_tdata;
556
  if (new_tdata != NULL)
557
    bfd_release (abfd, new_tdata);
558
  if (x_fxdhdr != NULL)
559
    free (x_fxdhdr);
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
 
567
static bfd_boolean
568
nlm_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
 
621
/* Return whether there is a non-zero byte in a memory block.  */
622
 
623
static bfd_boolean
624
find_nonzero (void * buf, size_t size)
625
{
626
  char *p = (char *) buf;
627
 
628
  while (size-- != 0)
629
    if (*p++ != 0)
630
      return TRUE;
631
  return FALSE;
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
 
638
static bfd_boolean
639
nlm_swap_auxiliary_headers_out (bfd *abfd)
640
{
641
  bfd_size_type amt;
642
 
643
  /* Write out the version header if there is one.  */
644
  if (find_nonzero (nlm_version_header (abfd),
645
                    sizeof (Nlm_Internal_Version_Header)))
646
    {
647
      Nlm_External_Version_Header thdr;
648
 
649
      LITMEMCPY (thdr.stamp, "VeRsIoN#");
650
      put_word (abfd, (bfd_vma) nlm_version_header (abfd)->majorVersion,
651
                (bfd_byte *) thdr.majorVersion);
652
      put_word (abfd, (bfd_vma) nlm_version_header (abfd)->minorVersion,
653
                (bfd_byte *) thdr.minorVersion);
654
      put_word (abfd, (bfd_vma) nlm_version_header (abfd)->revision,
655
                (bfd_byte *) thdr.revision);
656
      put_word (abfd, (bfd_vma) nlm_version_header (abfd)->year,
657
                (bfd_byte *) thdr.year);
658
      put_word (abfd, (bfd_vma) nlm_version_header (abfd)->month,
659
                (bfd_byte *) thdr.month);
660
      put_word (abfd, (bfd_vma) nlm_version_header (abfd)->day,
661
                (bfd_byte *) thdr.day);
662
      if (bfd_bwrite ((void *) &thdr, (bfd_size_type) sizeof (thdr), abfd)
663
          != sizeof (thdr))
664
        return FALSE;
665
    }
666
 
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.  */
671
  if (find_nonzero (nlm_copyright_header (abfd),
672
                    sizeof (Nlm_Internal_Copyright_Header)))
673
    {
674
      Nlm_External_Copyright_Header thdr;
675
 
676
      LITMEMCPY (thdr.stamp, "CoPyRiGhT=");
677
      amt = sizeof (thdr.stamp);
678
      if (bfd_bwrite ((void *) thdr.stamp, amt, abfd) != amt)
679
        return FALSE;
680
      thdr.copyrightMessageLength[0] =
681
        nlm_copyright_header (abfd)->copyrightMessageLength;
682
      amt = 1;
683
      if (bfd_bwrite ((void *) thdr.copyrightMessageLength, amt, abfd) != amt)
684
        return FALSE;
685
      /* The copyright message is a variable length string.  */
686
      amt = nlm_copyright_header (abfd)->copyrightMessageLength + 1;
687
      if (bfd_bwrite ((void *) nlm_copyright_header (abfd)->copyrightMessage,
688
                     amt, abfd) != amt)
689
        return FALSE;
690
    }
691
 
692
  /* Write out the extended header if there is one.  */
693
  if (find_nonzero (nlm_extended_header (abfd),
694
                    sizeof (Nlm_Internal_Extended_Header)))
695
    {
696
      Nlm_External_Extended_Header thdr;
697
 
698
      LITMEMCPY (thdr.stamp, "MeSsAgEs");
699
      put_word (abfd,
700
                (bfd_vma) nlm_extended_header (abfd)->languageID,
701
                (bfd_byte *) thdr.languageID);
702
      put_word (abfd,
703
                (bfd_vma) nlm_extended_header (abfd)->messageFileOffset,
704
                (bfd_byte *) thdr.messageFileOffset);
705
      put_word (abfd,
706
                (bfd_vma) nlm_extended_header (abfd)->messageFileLength,
707
                (bfd_byte *) thdr.messageFileLength);
708
      put_word (abfd,
709
                (bfd_vma) nlm_extended_header (abfd)->messageCount,
710
                (bfd_byte *) thdr.messageCount);
711
      put_word (abfd,
712
                (bfd_vma) nlm_extended_header (abfd)->helpFileOffset,
713
                (bfd_byte *) thdr.helpFileOffset);
714
      put_word (abfd,
715
                (bfd_vma) nlm_extended_header (abfd)->helpFileLength,
716
                (bfd_byte *) thdr.helpFileLength);
717
      put_word (abfd,
718
                (bfd_vma) nlm_extended_header (abfd)->RPCDataOffset,
719
                (bfd_byte *) thdr.RPCDataOffset);
720
      put_word (abfd,
721
                (bfd_vma) nlm_extended_header (abfd)->RPCDataLength,
722
                (bfd_byte *) thdr.RPCDataLength);
723
      put_word (abfd,
724
                (bfd_vma) nlm_extended_header (abfd)->sharedCodeOffset,
725
                (bfd_byte *) thdr.sharedCodeOffset);
726
      put_word (abfd,
727
                (bfd_vma) nlm_extended_header (abfd)->sharedCodeLength,
728
                (bfd_byte *) thdr.sharedCodeLength);
729
      put_word (abfd,
730
                (bfd_vma) nlm_extended_header (abfd)->sharedDataOffset,
731
                (bfd_byte *) thdr.sharedDataOffset);
732
      put_word (abfd,
733
                (bfd_vma) nlm_extended_header (abfd)->sharedDataLength,
734
                (bfd_byte *) thdr.sharedDataLength);
735
      put_word (abfd,
736
          (bfd_vma) nlm_extended_header (abfd)->sharedRelocationFixupOffset,
737
                (bfd_byte *) thdr.sharedRelocationFixupOffset);
738
      put_word (abfd,
739
           (bfd_vma) nlm_extended_header (abfd)->sharedRelocationFixupCount,
740
                (bfd_byte *) thdr.sharedRelocationFixupCount);
741
      put_word (abfd,
742
        (bfd_vma) nlm_extended_header (abfd)->sharedExternalReferenceOffset,
743
                (bfd_byte *) thdr.sharedExternalReferenceOffset);
744
      put_word (abfd,
745
         (bfd_vma) nlm_extended_header (abfd)->sharedExternalReferenceCount,
746
                (bfd_byte *) thdr.sharedExternalReferenceCount);
747
      put_word (abfd,
748
                (bfd_vma) nlm_extended_header (abfd)->sharedPublicsOffset,
749
                (bfd_byte *) thdr.sharedPublicsOffset);
750
      put_word (abfd,
751
                (bfd_vma) nlm_extended_header (abfd)->sharedPublicsCount,
752
                (bfd_byte *) thdr.sharedPublicsCount);
753
      put_word (abfd,
754
              (bfd_vma) nlm_extended_header (abfd)->sharedDebugRecordOffset,
755
                (bfd_byte *) thdr.sharedDebugRecordOffset);
756
      put_word (abfd,
757
                (bfd_vma) nlm_extended_header (abfd)->sharedDebugRecordCount,
758
                (bfd_byte *) thdr.sharedDebugRecordCount);
759
      put_word (abfd,
760
           (bfd_vma) nlm_extended_header (abfd)->SharedInitializationOffset,
761
                (bfd_byte *) thdr.sharedInitializationOffset);
762
      put_word (abfd,
763
            (bfd_vma) nlm_extended_header (abfd)->SharedExitProcedureOffset,
764
                (bfd_byte *) thdr.SharedExitProcedureOffset);
765
      put_word (abfd,
766
                (bfd_vma) nlm_extended_header (abfd)->productID,
767
                (bfd_byte *) thdr.productID);
768
      put_word (abfd,
769
                (bfd_vma) nlm_extended_header (abfd)->reserved0,
770
                (bfd_byte *) thdr.reserved0);
771
      put_word (abfd,
772
                (bfd_vma) nlm_extended_header (abfd)->reserved1,
773
                (bfd_byte *) thdr.reserved1);
774
      put_word (abfd,
775
                (bfd_vma) nlm_extended_header (abfd)->reserved2,
776
                (bfd_byte *) thdr.reserved2);
777
      put_word (abfd,
778
                (bfd_vma) nlm_extended_header (abfd)->reserved3,
779
                (bfd_byte *) thdr.reserved3);
780
      put_word (abfd,
781
                (bfd_vma) nlm_extended_header (abfd)->reserved4,
782
                (bfd_byte *) thdr.reserved4);
783
      put_word (abfd,
784
                (bfd_vma) nlm_extended_header (abfd)->reserved5,
785
                (bfd_byte *) thdr.reserved5);
786
      if (bfd_bwrite ((void *) &thdr, (bfd_size_type) sizeof (thdr), abfd)
787
          != sizeof (thdr))
788
        return FALSE;
789
    }
790
 
791
  /* Write out the custom header if there is one.   */
792
  if (find_nonzero (nlm_custom_header (abfd),
793
                    sizeof (Nlm_Internal_Custom_Header)))
794
    {
795
      Nlm_External_Custom_Header thdr;
796
      bfd_boolean ds;
797
      bfd_size_type hdrLength;
798
 
799
      ds = find_nonzero (nlm_custom_header (abfd)->dataStamp,
800
                         sizeof (nlm_custom_header (abfd)->dataStamp));
801
      LITMEMCPY (thdr.stamp, "CuStHeAd");
802
      hdrLength = (2 * NLM_TARGET_LONG_SIZE + (ds ? 8 : 0)
803
                   + nlm_custom_header (abfd)->hdrLength);
804
      put_word (abfd, hdrLength, thdr.length);
805
      put_word (abfd, (bfd_vma) nlm_custom_header (abfd)->dataOffset,
806
                thdr.dataOffset);
807
      put_word (abfd, (bfd_vma) nlm_custom_header (abfd)->dataLength,
808
                thdr.dataLength);
809
      if (! ds)
810
        {
811
          BFD_ASSERT (nlm_custom_header (abfd)->hdrLength == 0);
812
          amt = sizeof (thdr) - sizeof (thdr.dataStamp);
813
          if (bfd_bwrite ((void *) &thdr, amt, abfd) != amt)
814
            return FALSE;
815
        }
816
      else
817
        {
818
          memcpy (thdr.dataStamp, nlm_custom_header (abfd)->dataStamp,
819
                  sizeof (thdr.dataStamp));
820
          amt = sizeof (thdr);
821
          if (bfd_bwrite ((void *) &thdr, amt, abfd) != amt)
822
            return FALSE;
823
          amt = nlm_custom_header (abfd)->hdrLength;
824
          if (bfd_bwrite (nlm_custom_header (abfd)->hdr, amt, abfd) != amt)
825
            return FALSE;
826
        }
827
    }
828
 
829
  /* Write out the Cygnus debugging header if there is one.  */
830
  if (find_nonzero (nlm_cygnus_ext_header (abfd),
831
                    sizeof (Nlm_Internal_Cygnus_Ext_Header)))
832
    {
833
      Nlm_External_Custom_Header thdr;
834
 
835
      LITMEMCPY (thdr.stamp, "CuStHeAd");
836
      put_word (abfd, (bfd_vma) 2 * NLM_TARGET_LONG_SIZE + 8,
837
                (bfd_byte *) thdr.length);
838
      put_word (abfd, (bfd_vma) nlm_cygnus_ext_header (abfd)->offset,
839
                (bfd_byte *) thdr.dataOffset);
840
      put_word (abfd, (bfd_vma) nlm_cygnus_ext_header (abfd)->length,
841
                (bfd_byte *) thdr.dataLength);
842
      LITMEMCPY (thdr.dataStamp, "CyGnUsEx");
843
      amt = sizeof (thdr);
844
      if (bfd_bwrite ((void *) &thdr, amt, abfd) != amt)
845
        return FALSE;
846
    }
847
 
848
  return TRUE;
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
858
   on this size.  */
859
 
860
long
861
nlm_get_symtab_upper_bound (bfd *abfd)
862
{
863
  Nlm_Internal_Fixed_Header *i_fxdhdrp; /* Nlm file header, internal form.  */
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));
872
  return symtab_size;
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
 
889
   The bfd symbols are copied to SYMvoid *S.
890
 
891
   When we return, the bfd symcount is either zero or contains the correct
892
   number of symbols.  */
893
 
894
static bfd_boolean
895
nlm_slurp_symbol_table (bfd *abfd)
896
{
897
  Nlm_Internal_Fixed_Header *i_fxdhdrp; /* Nlm file header, internal form.  */
898
  bfd_size_type totsymcount;    /* Number of NLM symbols.  */
899
  bfd_size_type symcount;       /* Counter of NLM symbols.  */
900
  nlm_symbol_type *sym;         /* Pointer to current bfd symbol.  */
901
  unsigned char symlength;      /* Symbol length read into here.  */
902
  unsigned char symtype;        /* Type of debugging symbol.  */
903
  bfd_byte temp[NLM_TARGET_LONG_SIZE];  /* Symbol offsets read into here.  */
904
  bfd_boolean (*read_import_func) (bfd *, nlm_symbol_type *);
905
  bfd_boolean (*set_public_section_func) (bfd *, nlm_symbol_type *);
906
  bfd_size_type amt;
907
 
908
  if (nlm_get_symbols (abfd) != NULL)
909
    return TRUE;
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.
917
     When we have all the symbols, we build the caller's pointer vector.  */
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)
925
    return TRUE;
926
 
927
  if (bfd_seek (abfd, i_fxdhdrp->publicsOffset, SEEK_SET) != 0)
928
    return FALSE;
929
 
930
  amt = totsymcount * sizeof (nlm_symbol_type);
931
  sym = bfd_zalloc (abfd, amt);
932
  if (!sym)
933
    return FALSE;
934
  nlm_set_symbols (abfd, sym);
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
938
     were read.  */
939
 
940
  set_public_section_func = nlm_set_public_section_func (abfd);
941
  symcount = i_fxdhdrp->numberOfPublics;
942
  while (abfd->symcount < symcount)
943
    {
944
      amt = sizeof (symlength);
945
      if (bfd_bread ((void *) &symlength, amt, abfd) != amt)
946
        return FALSE;
947
      amt = symlength;
948
      sym->symbol.the_bfd = abfd;
949
      sym->symbol.name = bfd_alloc (abfd, amt + 1);
950
      if (!sym->symbol.name)
951
        return FALSE;
952
      if (bfd_bread ((void *) sym->symbol.name, amt, abfd) != amt)
953
        return FALSE;
954
      /* Cast away const.  */
955
      ((char *) (sym->symbol.name))[symlength] = '\0';
956
      amt = sizeof (temp);
957
      if (bfd_bread ((void *) temp, amt, abfd) != amt)
958
        return FALSE;
959
      sym->symbol.flags = BSF_GLOBAL | BSF_EXPORT;
960
      sym->symbol.value = get_word (abfd, temp);
961
      if (set_public_section_func)
962
        {
963
          /* Most backends can use the code below, but unfortunately
964
             some use a different scheme.  */
965
          if (! (*set_public_section_func) (abfd, sym))
966
            return FALSE;
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
978
            sym->symbol.section =
979
              bfd_get_section_by_name (abfd, NLM_INITIALIZED_DATA_NAME);
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
    {
990
      if (bfd_seek (abfd, i_fxdhdrp->debugInfoOffset, SEEK_SET) != 0)
991
        return FALSE;
992
 
993
      symcount += i_fxdhdrp->numberOfDebugRecords;
994
      while (abfd->symcount < symcount)
995
        {
996
          amt = sizeof (symtype);
997
          if (bfd_bread ((void *) &symtype, amt, abfd) != amt)
998
            return FALSE;
999
          amt = sizeof (temp);
1000
          if (bfd_bread ((void *) temp, amt, abfd) != amt)
1001
            return FALSE;
1002
          amt = sizeof (symlength);
1003
          if (bfd_bread ((void *) &symlength, amt, abfd) != amt)
1004
            return FALSE;
1005
          amt = symlength;
1006
          sym->symbol.the_bfd = abfd;
1007
          sym->symbol.name = bfd_alloc (abfd, amt + 1);
1008
          if (!sym->symbol.name)
1009
            return FALSE;
1010
          if (bfd_bread ((void *) sym->symbol.name, amt, abfd) != amt)
1011
            return FALSE;
1012
          /* Cast away const.  */
1013
          ((char *) (sym->symbol.name))[symlength] = '\0';
1014
          sym->symbol.flags = BSF_LOCAL;
1015
          sym->symbol.value = get_word (abfd, temp);
1016
 
1017
          if (symtype == 0)
1018
            sym->symbol.section =
1019
              bfd_get_section_by_name (abfd, NLM_INITIALIZED_DATA_NAME);
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
1027
            sym->symbol.section = bfd_abs_section_ptr;
1028
 
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.  */
1037
  read_import_func = nlm_read_import_func (abfd);
1038
  if (read_import_func != NULL)
1039
    {
1040
      if (bfd_seek (abfd, i_fxdhdrp->externalReferencesOffset, SEEK_SET) != 0)
1041
        return FALSE;
1042
 
1043
      symcount += i_fxdhdrp->numberOfExternalReferences;
1044
      while (abfd->symcount < symcount)
1045
        {
1046
          if (! (*read_import_func) (abfd, sym))
1047
            return FALSE;
1048
          sym++;
1049
          abfd->symcount++;
1050
        }
1051
    }
1052
 
1053
  return TRUE;
1054
}
1055
 
1056
/* Note that bfd_get_symcount is guaranteed to be zero if slurping the
1057
   symbol table fails.  */
1058
 
1059
long
1060
nlm_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
 
1080
asymbol *
1081
nlm_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
 
1094
void
1095
nlm_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
 
1104
void
1105
nlm_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
}
1127
 
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
 
1141
static bfd_boolean
1142
nlm_slurp_reloc_fixups (bfd *abfd)
1143
{
1144
  bfd_boolean (*read_func) (bfd *, nlm_symbol_type *, asection **, arelent *);
1145
  bfd_size_type count, amt;
1146
  arelent *rels;
1147
  asection **secs;
1148
 
1149
  if (nlm_relocation_fixups (abfd) != NULL)
1150
    return TRUE;
1151
  read_func = nlm_read_reloc_func (abfd);
1152
  if (read_func == NULL)
1153
    return TRUE;
1154
 
1155
  if (bfd_seek (abfd, nlm_fixed_header (abfd)->relocationFixupOffset,
1156
                SEEK_SET) != 0)
1157
    return FALSE;
1158
 
1159
  count = nlm_fixed_header (abfd)->numberOfRelocationFixups;
1160
  amt = count * sizeof (arelent);
1161
  rels = bfd_alloc (abfd, amt);
1162
  amt = count * sizeof (asection *);
1163
  secs = bfd_alloc (abfd, amt);
1164
  if ((rels == NULL || secs == NULL) && count != 0)
1165
    return FALSE;
1166
  nlm_relocation_fixups (abfd) = rels;
1167
  nlm_relocation_fixup_secs (abfd) = secs;
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
    {
1173
      if (! (*read_func) (abfd, NULL, secs, rels))
1174
        {
1175
          nlm_relocation_fixups (abfd) = NULL;
1176
          nlm_relocation_fixup_secs (abfd) = NULL;
1177
          return FALSE;
1178
        }
1179
      ++secs;
1180
      ++rels;
1181
    }
1182
 
1183
  return TRUE;
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
 
1190
long
1191
nlm_get_reloc_upper_bound (bfd *abfd, asection *sec)
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
    {
1207
      if (! nlm_slurp_symbol_table (abfd))
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
 
1226
long
1227
nlm_canonicalize_reloc (bfd *abfd,
1228
                        asection *sec,
1229
                        arelent **relptr,
1230
                        asymbol **symbols)
1231
{
1232
  arelent *rels;
1233
  asection **secs;
1234
  bfd_size_type count, i;
1235
  long ret;
1236
 
1237
  /* Get the relocation fixups.  */
1238
  rels = nlm_relocation_fixups (abfd);
1239
  if (rels == NULL)
1240
    {
1241
      if (! nlm_slurp_reloc_fixups (abfd))
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
 
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
 
1305
static bfd_boolean
1306
nlm_compute_section_file_positions (bfd *abfd)
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
 
1317
  if (abfd->output_has_begun)
1318
    return TRUE;
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))
1327
        return FALSE;
1328
      bss_sec = bfd_get_section_by_name (abfd, NLM_UNINITIALIZED_DATA_NAME);
1329
    }
1330
 
1331
  abfd->output_has_begun = TRUE;
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.  */
1348
  if (find_nonzero (nlm_version_header (abfd),
1349
                    sizeof (Nlm_Internal_Version_Header)))
1350
    sofar += sizeof (Nlm_External_Version_Header);
1351
  if (find_nonzero (nlm_extended_header (abfd),
1352
                    sizeof (Nlm_Internal_Extended_Header)))
1353
    sofar += sizeof (Nlm_External_Extended_Header);
1354
  if (find_nonzero (nlm_copyright_header (abfd),
1355
                    sizeof (Nlm_Internal_Copyright_Header)))
1356
    sofar += (sizeof (Nlm_External_Copyright_Header)
1357
              + nlm_copyright_header (abfd)->copyrightMessageLength + 1);
1358
  if (find_nonzero (nlm_custom_header (abfd),
1359
                    sizeof (Nlm_Internal_Custom_Header)))
1360
    sofar += (sizeof (Nlm_External_Custom_Header)
1361
              + nlm_custom_header (abfd)->hdrLength);
1362
  if (find_nonzero (nlm_cygnus_ext_header (abfd),
1363
                    sizeof (Nlm_Internal_Cygnus_Ext_Header)))
1364
    sofar += sizeof (Nlm_External_Custom_Header);
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;
1379
  for (sec = abfd->sections; sec != NULL; sec = sec->next)
1380
    {
1381
      flagword f;
1382
 
1383
      sec->size = BFD_ALIGN (sec->size, 1 << sec->alignment_power);
1384
 
1385
      f = bfd_get_section_flags (abfd, sec);
1386
      if (f & SEC_CODE)
1387
        {
1388
          text += sec->size;
1389
          if (bfd_get_section_vma (abfd, sec) < text_low)
1390
            text_low = bfd_get_section_vma (abfd, sec);
1391
          if (sec->alignment_power > text_align)
1392
            text_align = sec->alignment_power;
1393
        }
1394
      else if (f & SEC_DATA)
1395
        {
1396
          data += sec->size;
1397
          if (bfd_get_section_vma (abfd, sec) < data_low)
1398
            data_low = bfd_get_section_vma (abfd, sec);
1399
          if (sec->alignment_power > data_align)
1400
            data_align = sec->alignment_power;
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)
1408
        bss += sec->size;
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
 
1435
  for (sec = abfd->sections; sec != NULL; sec = sec->next)
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;
1444
          text_ptr += sec->size;
1445
        }
1446
      else if (f & SEC_DATA)
1447
        {
1448
          sec->filepos = data_ptr;
1449
          data_ptr += sec->size;
1450
        }
1451
      else if (f & SEC_HAS_CONTENTS)
1452
        {
1453
          sec->filepos = other_ptr;
1454
          other_ptr += sec->size;
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;
1485
          sym->value = bss_sec->size + add;
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;
1498
          bss_sec->size += add;
1499
        }
1500
    }
1501
 
1502
  return TRUE;
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
 
1510
bfd_boolean
1511
nlm_set_section_contents (bfd *abfd,
1512
                          asection *section,
1513
                          const void * location,
1514
                          file_ptr offset,
1515
                          bfd_size_type count)
1516
{
1517
  if (! abfd->output_has_begun
1518
      && ! nlm_compute_section_file_positions (abfd))
1519
    return FALSE;
1520
 
1521
  if (count == 0)
1522
    return TRUE;
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
    {
1530
      bfd_boolean (*mangle_relocs_func)
1531
        (bfd *, asection *, const void *, bfd_vma, bfd_size_type);
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))
1538
            return FALSE;
1539
        }
1540
    }
1541
 
1542
  if (bfd_seek (abfd, section->filepos + offset, SEEK_SET) != 0
1543
      || bfd_bwrite (location, count, abfd) != count)
1544
    return FALSE;
1545
 
1546
  return TRUE;
1547
}
1548
 
1549
/* We need to sort a list of relocs associated with sections when we
1550
   write out the external relocs.  */
1551
 
1552
static int
1553
nlm_external_reloc_compare (const void *p1, const void *p2)
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
 
1598
bfd_boolean
1599
nlm_write_object_contents (bfd *abfd)
1600
{
1601
  asection *sec;
1602
  bfd_boolean (*write_import_func) (bfd *, asection *, arelent *);
1603
  bfd_size_type external_reloc_count, internal_reloc_count, i, c;
1604
  struct reloc_and_sec *external_relocs;
1605
  asymbol **sym_ptr_ptr;
1606
  file_ptr last;
1607
  bfd_boolean (*write_prefix_func) (bfd *);
1608
  unsigned char *fixed_header = NULL;
1609
  file_ptr pos;
1610
  bfd_size_type amt;
1611
 
1612
  fixed_header = bfd_malloc (nlm_fixed_header_size (abfd));
1613
  if (fixed_header == NULL)
1614
    goto error_return;
1615
 
1616
  if (! abfd->output_has_begun
1617
      && ! nlm_compute_section_file_positions (abfd))
1618
    goto error_return;
1619
 
1620
  /* Write out the variable length headers.  */
1621
  pos = nlm_optional_prefix_size (abfd) + nlm_fixed_header_size (abfd);
1622
  if (bfd_seek (abfd, pos, SEEK_SET) != 0)
1623
    goto error_return;
1624
  if (! nlm_swap_variable_header_out (abfd)
1625
      || ! nlm_swap_auxiliary_headers_out (abfd))
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.  */
1633
  if (bfd_tell (abfd) > nlm_fixed_header (abfd)->codeImageOffset)
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;
1654
  for (sec = abfd->sections; sec != NULL; sec = sec->next)
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;
1686
              if (! (*write_import_func) (abfd, sec, rel))
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.  */
1699
  amt = external_reloc_count * sizeof (struct reloc_and_sec);
1700
  external_relocs = bfd_alloc (abfd, amt);
1701
  if (external_relocs == NULL)
1702
    goto error_return;
1703
  i = 0;
1704
  for (sec = abfd->sections; sec != NULL; sec = sec->next)
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.  */
1733
  qsort (external_relocs, (size_t) external_reloc_count,
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
 
1758
      if (! (*nlm_write_external_func (abfd)) (abfd, cnt, sym,
1759
                                               &external_relocs[i]))
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);
1769
  if (sym_ptr_ptr != NULL)
1770
    {
1771
      bfd_vma (*get_public_offset_func) (bfd *, asymbol *);
1772
      bfd_boolean (*write_export_func) (bfd *, asymbol *, bfd_vma);
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
            {
1827
              if (! (*write_export_func) (abfd, sym, offset))
1828
                goto error_return;
1829
            }
1830
          else
1831
            {
1832
              len = strlen (sym->name);
1833
              if ((bfd_bwrite (&len, (bfd_size_type) sizeof (bfd_byte), abfd)
1834
                   != sizeof (bfd_byte))
1835
                  || bfd_bwrite (sym->name, (bfd_size_type) len, abfd) != len)
1836
                goto error_return;
1837
 
1838
              put_word (abfd, offset, temp);
1839
              if (bfd_bwrite (temp, (bfd_size_type) sizeof (temp), abfd)
1840
                  != sizeof (temp))
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.  */
1899
              if (bfd_bwrite (&type, (bfd_size_type) sizeof (bfd_byte), abfd)
1900
                  != sizeof (bfd_byte))
1901
                goto error_return;
1902
 
1903
              put_word (abfd, offset, temp);
1904
              if (bfd_bwrite (temp, (bfd_size_type) sizeof (temp), abfd)
1905
                  != sizeof (temp))
1906
                goto error_return;
1907
 
1908
              len = strlen (sym->name);
1909
              if ((bfd_bwrite (&len, (bfd_size_type) sizeof (bfd_byte), abfd)
1910
                   != sizeof (bfd_byte))
1911
                  || bfd_bwrite (sym->name, (bfd_size_type) len, abfd) != len)
1912
                goto error_return;
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
 
1955
  if (bfd_seek (abfd, (file_ptr) 0, SEEK_SET) != 0)
1956
    goto error_return;
1957
 
1958
  write_prefix_func = nlm_write_prefix_func (abfd);
1959
  if (write_prefix_func)
1960
    {
1961
      if (! (*write_prefix_func) (abfd))
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);
1969
  if (bfd_bwrite (fixed_header, nlm_fixed_header_size (abfd), abfd)
1970
      != nlm_fixed_header_size (abfd))
1971
    goto error_return;
1972
 
1973
  if (fixed_header != NULL)
1974
    free (fixed_header);
1975
  return TRUE;
1976
 
1977
error_return:
1978
  if (fixed_header != NULL)
1979
    free (fixed_header);
1980
  return FALSE;
1981
}

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.