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

Subversion Repositories or1k

[/] [or1k/] [trunk/] [gdb-5.0/] [bfd/] [nlmcode.h] - Blame information for rev 1765

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 104 markom
/* NLM (NetWare Loadable Module) executable support for BFD.
2
   Copyright (C) 1993, 94, 95, 98, 1999 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
 
824
  /* Write out the copyright header if there is one.  */
825
  if (find_nonzero ((PTR) nlm_copyright_header (abfd),
826
                    sizeof (Nlm_Internal_Copyright_Header)))
827
    {
828
      Nlm_External_Copyright_Header thdr;
829
 
830
      memcpy (thdr.stamp, "CoPyRiGhT=", 10);
831
      if (bfd_write ((PTR) thdr.stamp, sizeof (thdr.stamp), 1, abfd)
832
          != sizeof (thdr.stamp))
833
        return false;
834
      thdr.copyrightMessageLength[0] =
835
        nlm_copyright_header (abfd)->copyrightMessageLength;
836
      if (bfd_write ((PTR) thdr.copyrightMessageLength, 1, 1, abfd) != 1)
837
        return false;
838
      /* The copyright message is a variable length string. */
839
      if (bfd_write ((PTR) nlm_copyright_header (abfd)->copyrightMessage,
840
                     nlm_copyright_header (abfd)->copyrightMessageLength + 1,
841
                     1, abfd) !=
842
          ((bfd_size_type)
843
           nlm_copyright_header (abfd)->copyrightMessageLength + 1))
844
        return false;
845
    }
846
 
847
  /* Write out the custom header if there is one.   */
848
  if (find_nonzero ((PTR) nlm_custom_header (abfd),
849
                    sizeof (Nlm_Internal_Custom_Header)))
850
    {
851
      Nlm_External_Custom_Header thdr;
852
      boolean ds;
853
      bfd_size_type hdrLength;
854
 
855
      ds = find_nonzero ((PTR) nlm_custom_header (abfd)->dataStamp,
856
                         sizeof (nlm_custom_header (abfd)->dataStamp));
857
      memcpy (thdr.stamp, "CuStHeAd", 8);
858
      hdrLength = (2 * NLM_TARGET_LONG_SIZE + (ds ? 8 : 0)
859
                   + nlm_custom_header (abfd)->hdrLength);
860
      put_word (abfd, hdrLength, thdr.length);
861
      put_word (abfd, (bfd_vma) nlm_custom_header (abfd)->dataOffset,
862
                thdr.dataOffset);
863
      put_word (abfd, (bfd_vma) nlm_custom_header (abfd)->dataLength,
864
                thdr.dataLength);
865
      if (! ds)
866
        {
867
          BFD_ASSERT (nlm_custom_header (abfd)->hdrLength == 0);
868
          if (bfd_write ((PTR) &thdr, 1,
869
                         sizeof (thdr) - sizeof (thdr.dataStamp), abfd)
870
              != sizeof (thdr) - sizeof (thdr.dataStamp))
871
            return false;
872
        }
873
      else
874
        {
875
          memcpy (thdr.dataStamp, nlm_custom_header (abfd)->dataStamp,
876
                  sizeof (thdr.dataStamp));
877
          if (bfd_write ((PTR) &thdr, sizeof (thdr), 1, abfd) != sizeof (thdr))
878
            return false;
879
          if (bfd_write (nlm_custom_header (abfd)->hdr, 1,
880
                         nlm_custom_header (abfd)->hdrLength, abfd)
881
              != nlm_custom_header (abfd)->hdrLength)
882
            return false;
883
        }
884
    }
885
 
886
  /* Write out the Cygnus debugging header if there is one.  */
887
  if (find_nonzero ((PTR) nlm_cygnus_ext_header (abfd),
888
                    sizeof (Nlm_Internal_Cygnus_Ext_Header)))
889
    {
890
      Nlm_External_Custom_Header thdr;
891
 
892
      memcpy (thdr.stamp, "CuStHeAd", 8);
893
      put_word (abfd, (bfd_vma) 2 * NLM_TARGET_LONG_SIZE + 8,
894
                (bfd_byte *) thdr.length);
895
      put_word (abfd, (bfd_vma) nlm_cygnus_ext_header (abfd)->offset,
896
                (bfd_byte *) thdr.dataOffset);
897
      put_word (abfd, (bfd_vma) nlm_cygnus_ext_header (abfd)->length,
898
                (bfd_byte *) thdr.dataLength);
899
      memcpy (thdr.dataStamp, "CyGnUsEx", 8);
900
      if (bfd_write ((PTR) &thdr, sizeof (thdr), 1, abfd) != sizeof (thdr))
901
        return false;
902
    }
903
 
904
  return true;
905
}
906
 
907
/* We read the NLM's public symbols and use it to generate a bfd symbol
908
   table (hey, it's better than nothing) on a one-for-one basis.  Thus
909
   use the number of public symbols as the number of bfd symbols we will
910
   have once we actually get around to reading them in.
911
 
912
   Return the number of bytes required to hold the symtab vector, based on
913
   the count plus 1, since we will NULL terminate the vector allocated based
914
   on this size. */
915
 
916
long
917
nlm_get_symtab_upper_bound (abfd)
918
     bfd *abfd;
919
{
920
  Nlm_Internal_Fixed_Header *i_fxdhdrp; /* Nlm file header, internal form */
921
  long symcount;
922
  long symtab_size = 0;
923
 
924
  i_fxdhdrp = nlm_fixed_header (abfd);
925
  symcount = (i_fxdhdrp->numberOfPublics
926
              + i_fxdhdrp->numberOfDebugRecords
927
              + i_fxdhdrp->numberOfExternalReferences);
928
  symtab_size = (symcount + 1) * (sizeof (asymbol));
929
  return (symtab_size);
930
}
931
 
932
/* Note that bfd_get_symcount is guaranteed to be zero if slurping the
933
   symbol table fails. */
934
 
935
long
936
nlm_get_symtab (abfd, alocation)
937
     bfd *abfd;
938
     asymbol **alocation;
939
{
940
  nlm_symbol_type *symbase;
941
  bfd_size_type counter = 0;
942
 
943
  if (nlm_slurp_symbol_table (abfd) == false)
944
    return -1;
945
  symbase = nlm_get_symbols (abfd);
946
  while (counter < bfd_get_symcount (abfd))
947
    {
948
      *alocation++ = &symbase->symbol;
949
      symbase++;
950
      counter++;
951
    }
952
  *alocation = (asymbol *) NULL;
953
  return bfd_get_symcount (abfd);
954
}
955
 
956
/* Make an NLM symbol.  There is nothing special to do here.  */
957
 
958
asymbol *
959
nlm_make_empty_symbol (abfd)
960
     bfd *abfd;
961
{
962
  nlm_symbol_type *new;
963
 
964
  new = (nlm_symbol_type *) bfd_zalloc (abfd, sizeof (nlm_symbol_type));
965
  if (new)
966
    new->symbol.the_bfd = abfd;
967
  return &new->symbol;
968
}
969
 
970
/* Get symbol information.  */
971
 
972
void
973
nlm_get_symbol_info (ignore_abfd, symbol, ret)
974
     bfd *ignore_abfd ATTRIBUTE_UNUSED;
975
     asymbol *symbol;
976
     symbol_info *ret;
977
{
978
  bfd_symbol_info (symbol, ret);
979
}
980
 
981
/* Print symbol information.  */
982
 
983
void
984
nlm_print_symbol (abfd, afile, symbol, how)
985
     bfd *abfd ATTRIBUTE_UNUSED;
986
     PTR afile;
987
     asymbol *symbol;
988
     bfd_print_symbol_type how;
989
{
990
  FILE *file = (FILE *) afile;
991
 
992
  switch (how)
993
    {
994
    case bfd_print_symbol_name:
995
    case bfd_print_symbol_more:
996
      if (symbol->name)
997
        fprintf (file, "%s", symbol->name);
998
      break;
999
    case bfd_print_symbol_all:
1000
      bfd_print_symbol_vandf ((PTR) file, symbol);
1001
      fprintf (file, " %-5s", symbol->section->name);
1002
      if (symbol->name)
1003
        fprintf (file, " %s", symbol->name);
1004
      break;
1005
    }
1006
}
1007
 
1008
/* Slurp in nlm symbol table.
1009
 
1010
   In the external (in-file) form, NLM export records are variable length,
1011
   with the following form:
1012
 
1013
        1 byte          length of the symbol name (N)
1014
        N bytes         the symbol name
1015
        4 bytes         the symbol offset from start of it's section
1016
 
1017
   We also read in the debugging symbols and import records.  Import
1018
   records are treated as undefined symbols.  As we read the import
1019
   records we also read in the associated reloc information, which is
1020
   attached to the symbol.
1021
 
1022
   The bfd symbols are copied to SYMPTRS.
1023
 
1024
   When we return, the bfd symcount is either zero or contains the correct
1025
   number of symbols.
1026
*/
1027
 
1028
static boolean
1029
nlm_slurp_symbol_table (abfd)
1030
     bfd *abfd;
1031
{
1032
  Nlm_Internal_Fixed_Header *i_fxdhdrp; /* Nlm file header, internal form */
1033
  bfd_size_type totsymcount;    /* Number of NLM symbols */
1034
  bfd_size_type symcount;       /* Counter of NLM symbols */
1035
  nlm_symbol_type *sym;         /* Pointer to current bfd symbol */
1036
  unsigned char symlength;      /* Symbol length read into here */
1037
  unsigned char symtype;        /* Type of debugging symbol */
1038
  bfd_byte temp[NLM_TARGET_LONG_SIZE];  /* Symbol offsets read into here */
1039
  boolean (*read_import_func) PARAMS ((bfd *, nlm_symbol_type *));
1040
  boolean (*set_public_section_func) PARAMS ((bfd *, nlm_symbol_type *));
1041
 
1042
  if (nlm_get_symbols (abfd) != NULL)
1043
    return (true);
1044
 
1045
  /* Read each raw NLM symbol, using the information to create a canonical bfd
1046
     symbol table entry.
1047
 
1048
     Note that we allocate the initial bfd canonical symbol buffer based on a
1049
     one-to-one mapping of the NLM symbols to canonical symbols.  We actually
1050
     use all the NLM symbols, so there will be no space left over at the end.
1051
     When we have all the symbols, we build the caller's pointer vector. */
1052
 
1053
  abfd->symcount = 0;
1054
  i_fxdhdrp = nlm_fixed_header (abfd);
1055
  totsymcount = (i_fxdhdrp->numberOfPublics
1056
                 + i_fxdhdrp->numberOfDebugRecords
1057
                 + i_fxdhdrp->numberOfExternalReferences);
1058
  if (totsymcount == 0)
1059
    {
1060
      return (true);
1061
    }
1062
 
1063
  if (bfd_seek (abfd, i_fxdhdrp->publicsOffset, SEEK_SET) == -1)
1064
    return (false);
1065
 
1066
  sym = ((nlm_symbol_type *)
1067
         bfd_zalloc (abfd, totsymcount * sizeof (nlm_symbol_type)));
1068
  if (!sym)
1069
    return false;
1070
  nlm_set_symbols (abfd, sym);
1071
 
1072
  /* We use the bfd's symcount directly as the control count, so that early
1073
     termination of the loop leaves the symcount correct for the symbols that
1074
     were read. */
1075
 
1076
  set_public_section_func = nlm_set_public_section_func (abfd);
1077
  symcount = i_fxdhdrp->numberOfPublics;
1078
  while (abfd->symcount < symcount)
1079
    {
1080
      if (bfd_read ((PTR) & symlength, sizeof (symlength), 1, abfd)
1081
          != sizeof (symlength))
1082
        return (false);
1083
      sym->symbol.the_bfd = abfd;
1084
      sym->symbol.name = bfd_alloc (abfd, symlength + 1);
1085
      if (!sym->symbol.name)
1086
        return false;
1087
      if (bfd_read ((PTR) sym->symbol.name, symlength, 1, abfd)
1088
          != symlength)
1089
        return (false);
1090
      /* Cast away const.  */
1091
      ((char *) (sym->symbol.name))[symlength] = '\0';
1092
      if (bfd_read ((PTR) temp, sizeof (temp), 1, abfd) != sizeof (temp))
1093
        return (false);
1094
      sym->symbol.flags = BSF_GLOBAL | BSF_EXPORT;
1095
      sym->symbol.value = get_word (abfd, temp);
1096
      if (set_public_section_func)
1097
        {
1098
          /* Most backends can use the code below, but unfortunately
1099
             some use a different scheme.  */
1100
          if ((*set_public_section_func) (abfd, sym) == false)
1101
            return false;
1102
        }
1103
      else
1104
        {
1105
          if (sym->symbol.value & NLM_HIBIT)
1106
            {
1107
              sym->symbol.value &= ~NLM_HIBIT;
1108
              sym->symbol.flags |= BSF_FUNCTION;
1109
              sym->symbol.section =
1110
                bfd_get_section_by_name (abfd, NLM_CODE_NAME);
1111
            }
1112
          else
1113
            {
1114
              sym->symbol.section =
1115
                bfd_get_section_by_name (abfd, NLM_INITIALIZED_DATA_NAME);
1116
            }
1117
        }
1118
      sym->rcnt = 0;
1119
      abfd->symcount++;
1120
      sym++;
1121
    }
1122
 
1123
  /* Read the debugging records.  */
1124
 
1125
  if (i_fxdhdrp->numberOfDebugRecords > 0)
1126
    {
1127
      if (bfd_seek (abfd, i_fxdhdrp->debugInfoOffset, SEEK_SET) == -1)
1128
        return (false);
1129
 
1130
      symcount += i_fxdhdrp->numberOfDebugRecords;
1131
      while (abfd->symcount < symcount)
1132
        {
1133
          if ((bfd_read ((PTR) & symtype, sizeof (symtype), 1, abfd)
1134
               != sizeof (symtype))
1135
           || bfd_read ((PTR) temp, sizeof (temp), 1, abfd) != sizeof (temp)
1136
              || (bfd_read ((PTR) & symlength, sizeof (symlength), 1, abfd)
1137
                  != sizeof (symlength)))
1138
            return false;
1139
          sym->symbol.the_bfd = abfd;
1140
          sym->symbol.name = bfd_alloc (abfd, symlength + 1);
1141
          if (!sym->symbol.name)
1142
            return false;
1143
          if (bfd_read ((PTR) sym->symbol.name, symlength, 1, abfd)
1144
              != symlength)
1145
            return (false);
1146
          /* Cast away const.  */
1147
          ((char *) (sym->symbol.name))[symlength] = '\0';
1148
          sym->symbol.flags = BSF_LOCAL;
1149
          sym->symbol.value = get_word (abfd, temp);
1150
          if (symtype == 0)
1151
            {
1152
              sym->symbol.section =
1153
                bfd_get_section_by_name (abfd, NLM_INITIALIZED_DATA_NAME);
1154
            }
1155
          else if (symtype == 1)
1156
            {
1157
              sym->symbol.flags |= BSF_FUNCTION;
1158
              sym->symbol.section =
1159
                bfd_get_section_by_name (abfd, NLM_CODE_NAME);
1160
            }
1161
          else
1162
            {
1163
              sym->symbol.section = bfd_abs_section_ptr;
1164
            }
1165
          sym->rcnt = 0;
1166
          abfd->symcount++;
1167
          sym++;
1168
        }
1169
    }
1170
 
1171
  /* Read in the import records.  We can only do this if we know how
1172
     to read relocs for this target.  */
1173
 
1174
  read_import_func = nlm_read_import_func (abfd);
1175
  if (read_import_func != NULL)
1176
    {
1177
      if (bfd_seek (abfd, i_fxdhdrp->externalReferencesOffset, SEEK_SET)
1178
          == -1)
1179
        return (false);
1180
 
1181
      symcount += i_fxdhdrp->numberOfExternalReferences;
1182
      while (abfd->symcount < symcount)
1183
        {
1184
          if ((*read_import_func) (abfd, sym) == false)
1185
            return false;
1186
          sym++;
1187
          abfd->symcount++;
1188
        }
1189
    }
1190
 
1191
  return (true);
1192
}
1193
 
1194
/* Get the relocs for an NLM file.  There are two types of relocs.
1195
   Imports are relocs against symbols defined in other NLM files.  We
1196
   treat these as relocs against global symbols.  Relocation fixups
1197
   are internal relocs.
1198
 
1199
   The actual format used to store the relocs is machine specific.  */
1200
 
1201
/* Read in the relocation fixup information.  This is stored in
1202
   nlm_relocation_fixups, an array of arelent structures, and
1203
   nlm_relocation_fixup_secs, an array of section pointers.  The
1204
   section pointers are needed because the relocs are not sorted by
1205
   section.  */
1206
 
1207
static boolean
1208
nlm_slurp_reloc_fixups (abfd)
1209
     bfd *abfd;
1210
{
1211
  boolean (*read_func) PARAMS ((bfd *, nlm_symbol_type *, asection **,
1212
                                arelent *));
1213
  bfd_size_type count;
1214
  arelent *rels;
1215
  asection **secs;
1216
 
1217
  if (nlm_relocation_fixups (abfd) != NULL)
1218
    return true;
1219
  read_func = nlm_read_reloc_func (abfd);
1220
  if (read_func == NULL)
1221
    return true;
1222
 
1223
  if (bfd_seek (abfd, nlm_fixed_header (abfd)->relocationFixupOffset,
1224
                SEEK_SET) != 0)
1225
    return false;
1226
 
1227
  count = nlm_fixed_header (abfd)->numberOfRelocationFixups;
1228
  rels = (arelent *) bfd_alloc (abfd, count * sizeof (arelent));
1229
  secs = (asection **) bfd_alloc (abfd, count * sizeof (asection *));
1230
  if ((rels == NULL || secs == NULL) && count != 0)
1231
    return false;
1232
  nlm_relocation_fixups (abfd) = rels;
1233
  nlm_relocation_fixup_secs (abfd) = secs;
1234
 
1235
  /* We have to read piece by piece, because we don't know how large
1236
     the machine specific reloc information is.  */
1237
  while (count-- != 0)
1238
    {
1239
      if ((*read_func) (abfd, (nlm_symbol_type *) NULL, secs, rels) == false)
1240
        {
1241
          nlm_relocation_fixups (abfd) = NULL;
1242
          nlm_relocation_fixup_secs (abfd) = NULL;
1243
          return false;
1244
        }
1245
      ++secs;
1246
      ++rels;
1247
    }
1248
 
1249
  return true;
1250
}
1251
 
1252
/* Get the number of relocs.  This really just returns an upper bound,
1253
   since it does not attempt to distinguish them based on the section.
1254
   That will be handled when they are actually read.  */
1255
 
1256
long
1257
nlm_get_reloc_upper_bound (abfd, sec)
1258
     bfd *abfd;
1259
     asection *sec;
1260
{
1261
  nlm_symbol_type *syms;
1262
  bfd_size_type count;
1263
  unsigned int ret;
1264
 
1265
  /* If we don't know how to read relocs, just return 0.  */
1266
  if (nlm_read_reloc_func (abfd) == NULL)
1267
    return -1;
1268
  /* Make sure we have either the code or the data section.  */
1269
  if ((bfd_get_section_flags (abfd, sec) & (SEC_CODE | SEC_DATA)) == 0)
1270
    return 0;
1271
 
1272
  syms = nlm_get_symbols (abfd);
1273
  if (syms == NULL)
1274
    {
1275
      if (nlm_slurp_symbol_table (abfd) == false)
1276
        return -1;
1277
      syms = nlm_get_symbols (abfd);
1278
    }
1279
 
1280
  ret = nlm_fixed_header (abfd)->numberOfRelocationFixups;
1281
 
1282
  count = bfd_get_symcount (abfd);
1283
  while (count-- != 0)
1284
    {
1285
      ret += syms->rcnt;
1286
      ++syms;
1287
    }
1288
 
1289
  return (ret + 1) * sizeof (arelent *);
1290
}
1291
 
1292
/* Get the relocs themselves.  */
1293
 
1294
long
1295
nlm_canonicalize_reloc (abfd, sec, relptr, symbols)
1296
     bfd *abfd;
1297
     asection *sec;
1298
     arelent **relptr;
1299
     asymbol **symbols;
1300
{
1301
  arelent *rels;
1302
  asection **secs;
1303
  bfd_size_type count, i;
1304
  unsigned int ret;
1305
 
1306
  /* Get the relocation fixups.  */
1307
  rels = nlm_relocation_fixups (abfd);
1308
  if (rels == NULL)
1309
    {
1310
      if (nlm_slurp_reloc_fixups (abfd) == false)
1311
        return -1;
1312
      rels = nlm_relocation_fixups (abfd);
1313
    }
1314
  secs = nlm_relocation_fixup_secs (abfd);
1315
 
1316
  ret = 0;
1317
  count = nlm_fixed_header (abfd)->numberOfRelocationFixups;
1318
  for (i = 0; i < count; i++, rels++, secs++)
1319
    {
1320
      if (*secs == sec)
1321
        {
1322
          *relptr++ = rels;
1323
          ++ret;
1324
        }
1325
    }
1326
 
1327
  /* Get the import symbols.  */
1328
  count = bfd_get_symcount (abfd);
1329
  for (i = 0; i < count; i++, symbols++)
1330
    {
1331
      asymbol *sym;
1332
 
1333
      sym = *symbols;
1334
      if (bfd_asymbol_flavour (sym) == bfd_target_nlm_flavour)
1335
        {
1336
          nlm_symbol_type *nlm_sym;
1337
          bfd_size_type j;
1338
 
1339
          nlm_sym = (nlm_symbol_type *) sym;
1340
          for (j = 0; j < nlm_sym->rcnt; j++)
1341
            {
1342
              if (nlm_sym->relocs[j].section == sec)
1343
                {
1344
                  *relptr = &nlm_sym->relocs[j].reloc;
1345
                  (*relptr)->sym_ptr_ptr = symbols;
1346
                  ++relptr;
1347
                  ++ret;
1348
                }
1349
            }
1350
        }
1351
    }
1352
 
1353
  *relptr = NULL;
1354
 
1355
  return ret;
1356
}
1357
 
1358
/* Compute the section file positions for an NLM file.  All variable
1359
   length data in the file headers must be set before this function is
1360
   called.  If the variable length data is changed later, the
1361
   resulting object file will be incorrect.  Unfortunately, there is
1362
   no way to check this.
1363
 
1364
   This routine also sets the Size and Offset fields in the fixed
1365
   header.
1366
 
1367
   It also looks over the symbols and moves any common symbols into
1368
   the .bss section; NLM has no way to represent a common symbol.
1369
   This approach means that either the symbols must already have been
1370
   set at this point, or there must be no common symbols.  We need to
1371
   move the symbols at this point so that mangle_relocs can see the
1372
   final values.  */
1373
 
1374
static boolean
1375
nlm_compute_section_file_positions (abfd)
1376
     bfd *abfd;
1377
{
1378
  file_ptr sofar;
1379
  asection *sec;
1380
  bfd_vma text, data, bss;
1381
  bfd_vma text_low, data_low;
1382
  unsigned int text_align, data_align, other_align;
1383
  file_ptr text_ptr, data_ptr, other_ptr;
1384
  asection *bss_sec;
1385
  asymbol **sym_ptr_ptr;
1386
 
1387
  if (abfd->output_has_begun == true)
1388
    return true;
1389
 
1390
  /* Make sure we have a section to hold uninitialized data.  */
1391
  bss_sec = bfd_get_section_by_name (abfd, NLM_UNINITIALIZED_DATA_NAME);
1392
  if (bss_sec == NULL)
1393
    {
1394
      if (!add_bfd_section (abfd, NLM_UNINITIALIZED_DATA_NAME,
1395
                            (file_ptr) 0, (bfd_size_type) 0,
1396
                            SEC_ALLOC))
1397
        return false;
1398
      bss_sec = bfd_get_section_by_name (abfd, NLM_UNINITIALIZED_DATA_NAME);
1399
    }
1400
 
1401
  abfd->output_has_begun = true;
1402
 
1403
  /* The fixed header.  */
1404
  sofar = nlm_optional_prefix_size (abfd) + nlm_fixed_header_size (abfd);
1405
 
1406
  /* The variable header.  */
1407
  sofar += (sizeof (nlm_variable_header (abfd)->descriptionLength)
1408
            + nlm_variable_header (abfd)->descriptionLength + 1
1409
            + NLM_TARGET_LONG_SIZE      /* stackSize */
1410
            + NLM_TARGET_LONG_SIZE      /* reserved */
1411
            + sizeof (nlm_variable_header (abfd)->oldThreadName)
1412
            + sizeof (nlm_variable_header (abfd)->screenNameLength)
1413
            + nlm_variable_header (abfd)->screenNameLength + 1
1414
            + sizeof (nlm_variable_header (abfd)->threadNameLength)
1415
            + nlm_variable_header (abfd)->threadNameLength + 1);
1416
 
1417
  /* The auxiliary headers.  */
1418
  if (find_nonzero ((PTR) nlm_version_header (abfd),
1419
                    sizeof (Nlm_Internal_Version_Header)))
1420
    sofar += sizeof (Nlm_External_Version_Header);
1421
  if (find_nonzero ((PTR) nlm_extended_header (abfd),
1422
                    sizeof (Nlm_Internal_Extended_Header)))
1423
    sofar += sizeof (Nlm_External_Extended_Header);
1424
  if (find_nonzero ((PTR) nlm_copyright_header (abfd),
1425
                    sizeof (Nlm_Internal_Copyright_Header)))
1426
    sofar += (sizeof (Nlm_External_Copyright_Header)
1427
              + nlm_copyright_header (abfd)->copyrightMessageLength + 1);
1428
  if (find_nonzero ((PTR) nlm_custom_header (abfd),
1429
                    sizeof (Nlm_Internal_Custom_Header)))
1430
    sofar += (sizeof (Nlm_External_Custom_Header)
1431
              + nlm_custom_header (abfd)->hdrLength);
1432
  if (find_nonzero ((PTR) nlm_cygnus_ext_header (abfd),
1433
                    sizeof (Nlm_Internal_Cygnus_Ext_Header)))
1434
    sofar += sizeof (Nlm_External_Custom_Header);
1435
 
1436
  /* Compute the section file positions in two passes.  First get the
1437
     sizes of the text and data sections, and then set the file
1438
     positions.  This code aligns the sections in the file using the
1439
     same alignment restrictions that apply to the sections in memory;
1440
     this may not be necessary.  */
1441
  text = 0;
1442
  text_low = (bfd_vma) - 1;
1443
  text_align = 0;
1444
  data = 0;
1445
  data_low = (bfd_vma) - 1;
1446
  data_align = 0;
1447
  bss = 0;
1448
  other_align = 0;
1449
  for (sec = abfd->sections; sec != (asection *) NULL; sec = sec->next)
1450
    {
1451
      flagword f;
1452
 
1453
      sec->_raw_size = BFD_ALIGN (sec->_raw_size, 1 << sec->alignment_power);
1454
 
1455
      f = bfd_get_section_flags (abfd, sec);
1456
      if (f & SEC_CODE)
1457
        {
1458
          text += sec->_raw_size;
1459
          if (bfd_get_section_vma (abfd, sec) < text_low)
1460
            text_low = bfd_get_section_vma (abfd, sec);
1461
          if (sec->alignment_power > text_align)
1462
            text_align = sec->alignment_power;
1463
        }
1464
      else if (f & SEC_DATA)
1465
        {
1466
          data += sec->_raw_size;
1467
          if (bfd_get_section_vma (abfd, sec) < data_low)
1468
            data_low = bfd_get_section_vma (abfd, sec);
1469
          if (sec->alignment_power > data_align)
1470
            data_align = sec->alignment_power;
1471
        }
1472
      else if (f & SEC_HAS_CONTENTS)
1473
        {
1474
          if (sec->alignment_power > other_align)
1475
            other_align = sec->alignment_power;
1476
        }
1477
      else if (f & SEC_ALLOC)
1478
        bss += sec->_raw_size;
1479
    }
1480
 
1481
  nlm_set_text_low (abfd, text_low);
1482
  nlm_set_data_low (abfd, data_low);
1483
 
1484
  if (nlm_no_uninitialized_data (abfd))
1485
    {
1486
      /* This NetWare format does not use uninitialized data.  We must
1487
         increase the size of the data section.  We will never wind up
1488
         writing those file locations, so they will remain zero.  */
1489
      data += bss;
1490
      bss = 0;
1491
    }
1492
 
1493
  text_ptr = BFD_ALIGN (sofar, 1 << text_align);
1494
  data_ptr = BFD_ALIGN (text_ptr + text, 1 << data_align);
1495
  other_ptr = BFD_ALIGN (data_ptr + data, 1 << other_align);
1496
 
1497
  /* Fill in some fields in the header for which we now have the
1498
     information.  */
1499
  nlm_fixed_header (abfd)->codeImageOffset = text_ptr;
1500
  nlm_fixed_header (abfd)->codeImageSize = text;
1501
  nlm_fixed_header (abfd)->dataImageOffset = data_ptr;
1502
  nlm_fixed_header (abfd)->dataImageSize = data;
1503
  nlm_fixed_header (abfd)->uninitializedDataSize = bss;
1504
 
1505
  for (sec = abfd->sections; sec != (asection *) NULL; sec = sec->next)
1506
    {
1507
      flagword f;
1508
 
1509
      f = bfd_get_section_flags (abfd, sec);
1510
 
1511
      if (f & SEC_CODE)
1512
        {
1513
          sec->filepos = text_ptr;
1514
          text_ptr += sec->_raw_size;
1515
        }
1516
      else if (f & SEC_DATA)
1517
        {
1518
          sec->filepos = data_ptr;
1519
          data_ptr += sec->_raw_size;
1520
        }
1521
      else if (f & SEC_HAS_CONTENTS)
1522
        {
1523
          sec->filepos = other_ptr;
1524
          other_ptr += sec->_raw_size;
1525
        }
1526
    }
1527
 
1528
  nlm_fixed_header (abfd)->relocationFixupOffset = other_ptr;
1529
 
1530
  /* Move all common symbols into the .bss section.  */
1531
 
1532
  sym_ptr_ptr = bfd_get_outsymbols (abfd);
1533
  if (sym_ptr_ptr != NULL)
1534
    {
1535
      asymbol **sym_end;
1536
      bfd_vma add;
1537
 
1538
      sym_end = sym_ptr_ptr + bfd_get_symcount (abfd);
1539
      add = 0;
1540
      for (; sym_ptr_ptr < sym_end; sym_ptr_ptr++)
1541
        {
1542
          asymbol *sym;
1543
          bfd_vma size;
1544
 
1545
          sym = *sym_ptr_ptr;
1546
 
1547
          if (!bfd_is_com_section (bfd_get_section (sym)))
1548
            continue;
1549
 
1550
          /* Put the common symbol in the .bss section, and increase
1551
             the size of the .bss section by the size of the common
1552
             symbol (which is the old value of the symbol).  */
1553
          sym->section = bss_sec;
1554
          size = sym->value;
1555
          sym->value = bss_sec->_raw_size + add;
1556
          add += size;
1557
          add = BFD_ALIGN (add, 1 << bss_sec->alignment_power);
1558
        }
1559
      if (add != 0)
1560
        {
1561
          if (nlm_no_uninitialized_data (abfd))
1562
            {
1563
              /* We could handle this case, but so far it hasn't been
1564
                 necessary.  */
1565
              abort ();
1566
            }
1567
          nlm_fixed_header (abfd)->uninitializedDataSize += add;
1568
          bss_sec->_raw_size += add;
1569
        }
1570
    }
1571
 
1572
  return true;
1573
}
1574
 
1575
/* Set the contents of a section.  To do this we need to know where
1576
   the section is going to be located in the output file.  That means
1577
   that the sizes of all the sections must be set, and all the
1578
   variable size header information must be known.  */
1579
 
1580
boolean
1581
nlm_set_section_contents (abfd, section, location, offset, count)
1582
     bfd *abfd;
1583
     asection *section;
1584
     PTR location;
1585
     file_ptr offset;
1586
     bfd_size_type count;
1587
{
1588
  if (abfd->output_has_begun == false
1589
      && nlm_compute_section_file_positions (abfd) == false)
1590
    return false;
1591
 
1592
  if (count == 0)
1593
    return true;
1594
 
1595
  /* i386 NetWare has a very restricted set of relocs.  In order for
1596
     objcopy to work, the NLM i386 backend needs a chance to rework
1597
     the section contents so that its set of relocs will work.  If all
1598
     the relocs are already acceptable, this will not do anything.  */
1599
  if (section->reloc_count != 0)
1600
    {
1601
      boolean (*mangle_relocs_func) PARAMS ((bfd *, asection *, PTR,
1602
                                             bfd_vma, bfd_size_type));
1603
 
1604
      mangle_relocs_func = nlm_mangle_relocs_func (abfd);
1605
      if (mangle_relocs_func != NULL)
1606
        {
1607
          if (!(*mangle_relocs_func) (abfd, section, location,
1608
                                      (bfd_vma) offset, count))
1609
            return false;
1610
        }
1611
    }
1612
 
1613
  if (bfd_seek (abfd, (file_ptr) (section->filepos + offset), SEEK_SET) != 0
1614
      || bfd_write (location, 1, count, abfd) != count)
1615
    return false;
1616
 
1617
  return true;
1618
}
1619
 
1620
/* We need to sort a list of relocs associated with sections when we
1621
   write out the external relocs.  */
1622
 
1623
static int
1624
nlm_external_reloc_compare (p1, p2)
1625
     const void *p1;
1626
     const void *p2;
1627
{
1628
  const struct reloc_and_sec *r1 = (const struct reloc_and_sec *) p1;
1629
  const struct reloc_and_sec *r2 = (const struct reloc_and_sec *) p2;
1630
  int cmp;
1631
 
1632
  cmp = strcmp ((*r1->rel->sym_ptr_ptr)->name,
1633
                (*r2->rel->sym_ptr_ptr)->name);
1634
  if (cmp != 0)
1635
    return cmp;
1636
 
1637
  /* We sort by address within symbol to make the sort more stable and
1638
     increase the chances that different hosts will generate bit for
1639
     bit equivalent results.  */
1640
  return (int) (r1->rel->address - r2->rel->address);
1641
}
1642
 
1643
/* Write out an NLM file.  We write out the information in this order:
1644
     fixed header
1645
     variable header
1646
     auxiliary headers
1647
     code sections
1648
     data sections
1649
     other sections (custom data, messages, help, shared NLM, RPC,
1650
                     module dependencies)
1651
     relocation fixups
1652
     external references (imports)
1653
     public symbols (exports)
1654
     debugging records
1655
   This is similar to the order used by the NetWare tools; the
1656
   difference is that NetWare puts the sections other than code, data
1657
   and custom data at the end of the NLM.  It is convenient for us to
1658
   know where the sections are going to be before worrying about the
1659
   size of the other information.
1660
 
1661
   By the time this function is called, all the section data should
1662
   have been output using set_section_contents.  Note that custom
1663
   data, the message file, the help file, the shared NLM file, the RPC
1664
   data, and the module dependencies are all considered to be
1665
   sections; the caller is responsible for filling in the offset and
1666
   length fields in the NLM headers.  The relocation fixups and
1667
   imports are both obtained from the list of relocs attached to each
1668
   section.  The exports and debugging records are obtained from the
1669
   list of outsymbols.  */
1670
 
1671
boolean
1672
nlm_write_object_contents (abfd)
1673
     bfd *abfd;
1674
{
1675
  asection *sec;
1676
  boolean (*write_import_func) PARAMS ((bfd *, asection *, arelent *));
1677
  bfd_size_type external_reloc_count, internal_reloc_count, i, c;
1678
  struct reloc_and_sec *external_relocs;
1679
  asymbol **sym_ptr_ptr;
1680
  file_ptr last;
1681
  boolean (*write_prefix_func) PARAMS ((bfd *));
1682
  unsigned char *fixed_header = NULL;
1683
 
1684
  fixed_header = ((unsigned char *)
1685
                  bfd_malloc ((size_t) nlm_fixed_header_size (abfd)));
1686
  if (fixed_header == NULL)
1687
    goto error_return;
1688
 
1689
  if (abfd->output_has_begun == false
1690
      && nlm_compute_section_file_positions (abfd) == false)
1691
    goto error_return;
1692
 
1693
  /* Write out the variable length headers.  */
1694
  if (bfd_seek (abfd,
1695
             nlm_optional_prefix_size (abfd) + nlm_fixed_header_size (abfd),
1696
                SEEK_SET) != 0)
1697
    goto error_return;
1698
  if (nlm_swap_variable_header_out (abfd) == false
1699
      || nlm_swap_auxiliary_headers_out (abfd) == false)
1700
    {
1701
      bfd_set_error (bfd_error_system_call);
1702
      goto error_return;
1703
    }
1704
 
1705
  /* A weak check on whether the section file positions were
1706
     reasonable.  */
1707
  if (bfd_tell (abfd) > nlm_fixed_header (abfd)->codeImageOffset)
1708
    {
1709
      bfd_set_error (bfd_error_invalid_operation);
1710
      goto error_return;
1711
    }
1712
 
1713
  /* Advance to the relocs.  */
1714
  if (bfd_seek (abfd, nlm_fixed_header (abfd)->relocationFixupOffset,
1715
                SEEK_SET) != 0)
1716
    goto error_return;
1717
 
1718
  /* The format of the relocation entries is dependent upon the
1719
     particular target.  We use an external routine to write the reloc
1720
     out.  */
1721
  write_import_func = nlm_write_import_func (abfd);
1722
 
1723
  /* Write out the internal relocation fixups.  While we're looping
1724
     over the relocs, we also count the external relocs, which is
1725
     needed when they are written out below.  */
1726
  internal_reloc_count = 0;
1727
  external_reloc_count = 0;
1728
  for (sec = abfd->sections; sec != (asection *) NULL; sec = sec->next)
1729
    {
1730
      arelent **rel_ptr_ptr, **rel_end;
1731
 
1732
      if (sec->reloc_count == 0)
1733
        continue;
1734
 
1735
      /* We can only represent relocs within a code or data
1736
         section.  We ignore them for a debugging section.  */
1737
      if ((bfd_get_section_flags (abfd, sec) & (SEC_CODE | SEC_DATA)) == 0)
1738
        continue;
1739
 
1740
      /* We need to know how to write out imports */
1741
      if (write_import_func == NULL)
1742
        {
1743
          bfd_set_error (bfd_error_invalid_operation);
1744
          goto error_return;
1745
        }
1746
 
1747
      rel_ptr_ptr = sec->orelocation;
1748
      rel_end = rel_ptr_ptr + sec->reloc_count;
1749
      for (; rel_ptr_ptr < rel_end; rel_ptr_ptr++)
1750
        {
1751
          arelent *rel;
1752
          asymbol *sym;
1753
 
1754
          rel = *rel_ptr_ptr;
1755
          sym = *rel->sym_ptr_ptr;
1756
 
1757
          if (! bfd_is_und_section (bfd_get_section (sym)))
1758
            {
1759
              ++internal_reloc_count;
1760
              if ((*write_import_func) (abfd, sec, rel) == false)
1761
                goto error_return;
1762
            }
1763
          else
1764
            ++external_reloc_count;
1765
        }
1766
    }
1767
  nlm_fixed_header (abfd)->numberOfRelocationFixups = internal_reloc_count;
1768
 
1769
  /* Write out the imports (relocs against external symbols).  These
1770
     are output as a symbol name followed by all the relocs for that
1771
     symbol, so we must first gather together all the relocs against
1772
     external symbols and sort them.  */
1773
  external_relocs =
1774
    (struct reloc_and_sec *) bfd_alloc (abfd,
1775
                                        (external_reloc_count
1776
                                         * sizeof (struct reloc_and_sec)));
1777
  if (external_relocs == (struct reloc_and_sec *) NULL)
1778
    goto error_return;
1779
  i = 0;
1780
  for (sec = abfd->sections; sec != (asection *) NULL; sec = sec->next)
1781
    {
1782
      arelent **rel_ptr_ptr, **rel_end;
1783
 
1784
      if (sec->reloc_count == 0)
1785
        continue;
1786
 
1787
      rel_ptr_ptr = sec->orelocation;
1788
      rel_end = rel_ptr_ptr + sec->reloc_count;
1789
      for (; rel_ptr_ptr < rel_end; rel_ptr_ptr++)
1790
        {
1791
          arelent *rel;
1792
          asymbol *sym;
1793
 
1794
          rel = *rel_ptr_ptr;
1795
          sym = *rel->sym_ptr_ptr;
1796
 
1797
          if (! bfd_is_und_section (bfd_get_section (sym)))
1798
            continue;
1799
 
1800
          external_relocs[i].rel = rel;
1801
          external_relocs[i].sec = sec;
1802
          ++i;
1803
        }
1804
    }
1805
 
1806
  BFD_ASSERT (i == external_reloc_count);
1807
 
1808
  /* Sort the external relocs by name.  */
1809
  qsort ((PTR) external_relocs, (size_t) external_reloc_count,
1810
         sizeof (struct reloc_and_sec), nlm_external_reloc_compare);
1811
 
1812
  /* Write out the external relocs.  */
1813
  nlm_fixed_header (abfd)->externalReferencesOffset = bfd_tell (abfd);
1814
  c = 0;
1815
  i = 0;
1816
  while (i < external_reloc_count)
1817
    {
1818
      arelent *rel;
1819
      asymbol *sym;
1820
      bfd_size_type j, cnt;
1821
 
1822
      ++c;
1823
 
1824
      rel = external_relocs[i].rel;
1825
      sym = *rel->sym_ptr_ptr;
1826
 
1827
      cnt = 0;
1828
      for (j = i;
1829
           (j < external_reloc_count
1830
            && *external_relocs[j].rel->sym_ptr_ptr == sym);
1831
           j++)
1832
        ++cnt;
1833
 
1834
      if ((*nlm_write_external_func (abfd)) (abfd, cnt, sym,
1835
                                             &external_relocs[i])
1836
          == false)
1837
        goto error_return;
1838
 
1839
      i += cnt;
1840
    }
1841
 
1842
  nlm_fixed_header (abfd)->numberOfExternalReferences = c;
1843
 
1844
  /* Write out the public symbols (exports).  */
1845
  sym_ptr_ptr = bfd_get_outsymbols (abfd);
1846
  if (sym_ptr_ptr != (asymbol **) NULL)
1847
    {
1848
      bfd_vma (*get_public_offset_func) PARAMS ((bfd *, asymbol *));
1849
      boolean (*write_export_func) PARAMS ((bfd *, asymbol *, bfd_vma));
1850
 
1851
      asymbol **sym_end;
1852
 
1853
      nlm_fixed_header (abfd)->publicsOffset = bfd_tell (abfd);
1854
      get_public_offset_func = nlm_get_public_offset_func (abfd);
1855
      write_export_func = nlm_write_export_func (abfd);
1856
      c = 0;
1857
      sym_end = sym_ptr_ptr + bfd_get_symcount (abfd);
1858
      for (; sym_ptr_ptr < sym_end; sym_ptr_ptr++)
1859
        {
1860
          asymbol *sym;
1861
          bfd_byte len;
1862
          bfd_vma offset;
1863
          bfd_byte temp[NLM_TARGET_LONG_SIZE];
1864
 
1865
          sym = *sym_ptr_ptr;
1866
 
1867
          if ((sym->flags & (BSF_EXPORT | BSF_GLOBAL)) == 0
1868
              || bfd_is_und_section (bfd_get_section (sym)))
1869
            continue;
1870
 
1871
          ++c;
1872
 
1873
          if (get_public_offset_func)
1874
            {
1875
              /* Most backends can use the code below, but
1876
                 unfortunately some use a different scheme.  */
1877
              offset = (*get_public_offset_func) (abfd, sym);
1878
            }
1879
          else
1880
            {
1881
              offset = bfd_asymbol_value (sym);
1882
              sec = sym->section;
1883
              if (sec->flags & SEC_CODE)
1884
                {
1885
                  offset -= nlm_get_text_low (abfd);
1886
                  offset |= NLM_HIBIT;
1887
                }
1888
              else if (sec->flags & (SEC_DATA | SEC_ALLOC))
1889
                {
1890
                  /* SEC_ALLOC is for the .bss section.  */
1891
                  offset -= nlm_get_data_low (abfd);
1892
                }
1893
              else
1894
                {
1895
                  /* We can't handle an exported symbol that is not in
1896
                     the code or data segment.  */
1897
                  bfd_set_error (bfd_error_invalid_operation);
1898
                  goto error_return;
1899
                }
1900
            }
1901
 
1902
          if (write_export_func)
1903
            {
1904
              if ((*write_export_func) (abfd, sym, offset) == false)
1905
                goto error_return;
1906
            }
1907
          else
1908
            {
1909
              len = strlen (sym->name);
1910
              if ((bfd_write (&len, sizeof (bfd_byte), 1, abfd)
1911
                   != sizeof (bfd_byte))
1912
                  || bfd_write (sym->name, len, 1, abfd) != len)
1913
                goto error_return;
1914
 
1915
              put_word (abfd, offset, temp);
1916
              if (bfd_write (temp, sizeof (temp), 1, abfd) != sizeof (temp))
1917
                goto error_return;
1918
            }
1919
        }
1920
      nlm_fixed_header (abfd)->numberOfPublics = c;
1921
 
1922
      /* Write out the debugging records.  The NLM conversion program
1923
         wants to be able to inhibit this, so as a special hack if
1924
         debugInfoOffset is set to -1 we don't write any debugging
1925
         information.  This can not be handled by fiddling with the
1926
         symbol table, because exported symbols appear in both the
1927
         exported symbol list and the debugging information.  */
1928
      if (nlm_fixed_header (abfd)->debugInfoOffset == (file_ptr) - 1)
1929
        {
1930
          nlm_fixed_header (abfd)->debugInfoOffset = 0;
1931
          nlm_fixed_header (abfd)->numberOfDebugRecords = 0;
1932
        }
1933
      else
1934
        {
1935
          nlm_fixed_header (abfd)->debugInfoOffset = bfd_tell (abfd);
1936
          c = 0;
1937
          sym_ptr_ptr = bfd_get_outsymbols (abfd);
1938
          sym_end = sym_ptr_ptr + bfd_get_symcount (abfd);
1939
          for (; sym_ptr_ptr < sym_end; sym_ptr_ptr++)
1940
            {
1941
              asymbol *sym;
1942
              bfd_byte type, len;
1943
              bfd_vma offset;
1944
              bfd_byte temp[NLM_TARGET_LONG_SIZE];
1945
 
1946
              sym = *sym_ptr_ptr;
1947
 
1948
              /* The NLM notion of a debugging symbol is actually what
1949
                 BFD calls a local or global symbol.  What BFD calls a
1950
                 debugging symbol NLM does not understand at all.  */
1951
              if ((sym->flags & (BSF_LOCAL | BSF_GLOBAL | BSF_EXPORT)) == 0
1952
                  || (sym->flags & BSF_DEBUGGING) != 0
1953
                  || bfd_is_und_section (bfd_get_section (sym)))
1954
                continue;
1955
 
1956
              ++c;
1957
 
1958
              offset = bfd_asymbol_value (sym);
1959
              sec = sym->section;
1960
              if (sec->flags & SEC_CODE)
1961
                {
1962
                  offset -= nlm_get_text_low (abfd);
1963
                  type = 1;
1964
                }
1965
              else if (sec->flags & (SEC_DATA | SEC_ALLOC))
1966
                {
1967
                  /* SEC_ALLOC is for the .bss section.  */
1968
                  offset -= nlm_get_data_low (abfd);
1969
                  type = 0;
1970
                }
1971
              else
1972
                type = 2;
1973
 
1974
              /* The type is 0 for data, 1 for code, 2 for absolute.  */
1975
              if (bfd_write (&type, sizeof (bfd_byte), 1, abfd)
1976
                  != sizeof (bfd_byte))
1977
                goto error_return;
1978
 
1979
              put_word (abfd, offset, temp);
1980
              if (bfd_write (temp, sizeof (temp), 1, abfd) != sizeof (temp))
1981
                goto error_return;
1982
 
1983
              len = strlen (sym->name);
1984
              if ((bfd_write (&len, sizeof (bfd_byte), 1, abfd)
1985
                   != sizeof (bfd_byte))
1986
                  || bfd_write (sym->name, len, 1, abfd) != len)
1987
                goto error_return;
1988
            }
1989
          nlm_fixed_header (abfd)->numberOfDebugRecords = c;
1990
        }
1991
    }
1992
 
1993
  /* NLMLINK fills in offset values even if there is no data, so we do
1994
     the same.  */
1995
  last = bfd_tell (abfd);
1996
  if (nlm_fixed_header (abfd)->codeImageOffset == 0)
1997
    nlm_fixed_header (abfd)->codeImageOffset = last;
1998
  if (nlm_fixed_header (abfd)->dataImageOffset == 0)
1999
    nlm_fixed_header (abfd)->dataImageOffset = last;
2000
  if (nlm_fixed_header (abfd)->customDataOffset == 0)
2001
    nlm_fixed_header (abfd)->customDataOffset = last;
2002
  if (nlm_fixed_header (abfd)->moduleDependencyOffset == 0)
2003
    nlm_fixed_header (abfd)->moduleDependencyOffset = last;
2004
  if (nlm_fixed_header (abfd)->relocationFixupOffset == 0)
2005
    nlm_fixed_header (abfd)->relocationFixupOffset = last;
2006
  if (nlm_fixed_header (abfd)->externalReferencesOffset == 0)
2007
    nlm_fixed_header (abfd)->externalReferencesOffset = last;
2008
  if (nlm_fixed_header (abfd)->publicsOffset == 0)
2009
    nlm_fixed_header (abfd)->publicsOffset = last;
2010
  if (nlm_fixed_header (abfd)->debugInfoOffset == 0)
2011
    nlm_fixed_header (abfd)->debugInfoOffset = last;
2012
 
2013
  /* At this point everything has been written out except the fixed
2014
     header.  */
2015
  memcpy (nlm_fixed_header (abfd)->signature, nlm_signature (abfd),
2016
          NLM_SIGNATURE_SIZE);
2017
  nlm_fixed_header (abfd)->version = NLM_HEADER_VERSION;
2018
  nlm_fixed_header (abfd)->codeStartOffset =
2019
    (bfd_get_start_address (abfd)
2020
     - nlm_get_text_low (abfd));
2021
 
2022
  /* We have no convenient way for the caller to pass in the exit
2023
     procedure or the check unload procedure, so the caller must set
2024
     the values in the header to the values of the symbols.  */
2025
  nlm_fixed_header (abfd)->exitProcedureOffset -= nlm_get_text_low (abfd);
2026
  if (nlm_fixed_header (abfd)->checkUnloadProcedureOffset != 0)
2027
    nlm_fixed_header (abfd)->checkUnloadProcedureOffset -=
2028
      nlm_get_text_low (abfd);
2029
 
2030
  if (bfd_seek (abfd, 0, SEEK_SET) != 0)
2031
    goto error_return;
2032
 
2033
  write_prefix_func = nlm_write_prefix_func (abfd);
2034
  if (write_prefix_func)
2035
    {
2036
      if ((*write_prefix_func) (abfd) == false)
2037
        goto error_return;
2038
    }
2039
 
2040
  BFD_ASSERT ((bfd_size_type) bfd_tell (abfd)
2041
              == nlm_optional_prefix_size (abfd));
2042
 
2043
  nlm_swap_fixed_header_out (abfd, nlm_fixed_header (abfd), fixed_header);
2044
  if (bfd_write (fixed_header, nlm_fixed_header_size (abfd), 1, abfd)
2045
      != nlm_fixed_header_size (abfd))
2046
    goto error_return;
2047
 
2048
  if (fixed_header != NULL)
2049
    free (fixed_header);
2050
  return true;
2051
 
2052
error_return:
2053
  if (fixed_header != NULL)
2054
    free (fixed_header);
2055
  return false;
2056
}

powered by: WebSVN 2.1.0

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