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

Subversion Repositories or1k

[/] [or1k/] [tags/] [start/] [insight/] [bfd/] [nlmcode.h] - Blame information for rev 1780

Go to most recent revision | Details | Compare with Previous | View Log

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

powered by: WebSVN 2.1.0

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