source: trunk/src/binutils/bfd/nlmcode.h@ 524

Last change on this file since 524 was 10, checked in by bird, 22 years ago

Initial revision

  • Property cvs2svn:cvs-rev set to 1.1
  • Property svn:eol-style set to native
  • Property svn:executable set to *
File size: 64.5 KB
Line 
1/* 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
7This file is part of BFD, the Binary File Descriptor library.
8
9This program is free software; you can redistribute it and/or modify
10it under the terms of the GNU General Public License as published by
11the Free Software Foundation; either version 2 of the License, or
12(at your option) any later version.
13
14This program is distributed in the hope that it will be useful,
15but WITHOUT ANY WARRANTY; without even the implied warranty of
16MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17GNU General Public License for more details.
18
19You should have received a copy of the GNU General Public License
20along with this program; if not, write to the Free Software
21Foundation, 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
61static boolean add_bfd_section
62 PARAMS ((bfd *, char *, file_ptr, bfd_size_type, flagword));
63static boolean nlm_swap_variable_header_in
64 PARAMS ((bfd *));
65static boolean nlm_swap_variable_header_out
66 PARAMS ((bfd *));
67static boolean find_nonzero
68 PARAMS ((PTR, size_t));
69static boolean nlm_swap_auxiliary_headers_in
70 PARAMS ((bfd *));
71static boolean nlm_swap_auxiliary_headers_out
72 PARAMS ((bfd *));
73static boolean nlm_slurp_symbol_table
74 PARAMS ((bfd *));
75static boolean nlm_slurp_reloc_fixups
76 PARAMS ((bfd *));
77static boolean nlm_compute_section_file_positions
78 PARAMS ((bfd *));
79static 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
93const bfd_target *
94nlm_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
215got_wrong_format_error:
216 bfd_set_error (bfd_error_wrong_format);
217got_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
228static boolean
229add_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
254static boolean
255nlm_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
324static boolean
325nlm_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
402static boolean
403nlm_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
681static boolean
682find_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
698static boolean
699nlm_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
915long
916nlm_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
934long
935nlm_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
957asymbol *
958nlm_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
971void
972nlm_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
982void
983nlm_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
1027static boolean
1028nlm_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
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
1207static boolean
1208nlm_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
1256long
1257nlm_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
1294long
1295nlm_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
1359/* Compute the section file positions for an NLM file. All variable
1360 length data in the file headers must be set before this function is
1361 called. If the variable length data is changed later, the
1362 resulting object file will be incorrect. Unfortunately, there is
1363 no way to check this.
1364
1365 This routine also sets the Size and Offset fields in the fixed
1366 header.
1367
1368 It also looks over the symbols and moves any common symbols into
1369 the .bss section; NLM has no way to represent a common symbol.
1370 This approach means that either the symbols must already have been
1371 set at this point, or there must be no common symbols. We need to
1372 move the symbols at this point so that mangle_relocs can see the
1373 final values. */
1374
1375static boolean
1376nlm_compute_section_file_positions (abfd)
1377 bfd *abfd;
1378{
1379 file_ptr sofar;
1380 asection *sec;
1381 bfd_vma text, data, bss;
1382 bfd_vma text_low, data_low;
1383 unsigned int text_align, data_align, other_align;
1384 file_ptr text_ptr, data_ptr, other_ptr;
1385 asection *bss_sec;
1386 asymbol **sym_ptr_ptr;
1387
1388 if (abfd->output_has_begun == true)
1389 return true;
1390
1391 /* Make sure we have a section to hold uninitialized data. */
1392 bss_sec = bfd_get_section_by_name (abfd, NLM_UNINITIALIZED_DATA_NAME);
1393 if (bss_sec == NULL)
1394 {
1395 if (!add_bfd_section (abfd, NLM_UNINITIALIZED_DATA_NAME,
1396 (file_ptr) 0, (bfd_size_type) 0,
1397 SEC_ALLOC))
1398 return false;
1399 bss_sec = bfd_get_section_by_name (abfd, NLM_UNINITIALIZED_DATA_NAME);
1400 }
1401
1402 abfd->output_has_begun = true;
1403
1404 /* The fixed header. */
1405 sofar = nlm_optional_prefix_size (abfd) + nlm_fixed_header_size (abfd);
1406
1407 /* The variable header. */
1408 sofar += (sizeof (nlm_variable_header (abfd)->descriptionLength)
1409 + nlm_variable_header (abfd)->descriptionLength + 1
1410 + NLM_TARGET_LONG_SIZE /* stackSize */
1411 + NLM_TARGET_LONG_SIZE /* reserved */
1412 + sizeof (nlm_variable_header (abfd)->oldThreadName)
1413 + sizeof (nlm_variable_header (abfd)->screenNameLength)
1414 + nlm_variable_header (abfd)->screenNameLength + 1
1415 + sizeof (nlm_variable_header (abfd)->threadNameLength)
1416 + nlm_variable_header (abfd)->threadNameLength + 1);
1417
1418 /* The auxiliary headers. */
1419 if (find_nonzero ((PTR) nlm_version_header (abfd),
1420 sizeof (Nlm_Internal_Version_Header)))
1421 sofar += sizeof (Nlm_External_Version_Header);
1422 if (find_nonzero ((PTR) nlm_extended_header (abfd),
1423 sizeof (Nlm_Internal_Extended_Header)))
1424 sofar += sizeof (Nlm_External_Extended_Header);
1425 if (find_nonzero ((PTR) nlm_copyright_header (abfd),
1426 sizeof (Nlm_Internal_Copyright_Header)))
1427 sofar += (sizeof (Nlm_External_Copyright_Header)
1428 + nlm_copyright_header (abfd)->copyrightMessageLength + 1);
1429 if (find_nonzero ((PTR) nlm_custom_header (abfd),
1430 sizeof (Nlm_Internal_Custom_Header)))
1431 sofar += (sizeof (Nlm_External_Custom_Header)
1432 + nlm_custom_header (abfd)->hdrLength);
1433 if (find_nonzero ((PTR) nlm_cygnus_ext_header (abfd),
1434 sizeof (Nlm_Internal_Cygnus_Ext_Header)))
1435 sofar += sizeof (Nlm_External_Custom_Header);
1436
1437 /* Compute the section file positions in two passes. First get the
1438 sizes of the text and data sections, and then set the file
1439 positions. This code aligns the sections in the file using the
1440 same alignment restrictions that apply to the sections in memory;
1441 this may not be necessary. */
1442 text = 0;
1443 text_low = (bfd_vma) - 1;
1444 text_align = 0;
1445 data = 0;
1446 data_low = (bfd_vma) - 1;
1447 data_align = 0;
1448 bss = 0;
1449 other_align = 0;
1450 for (sec = abfd->sections; sec != (asection *) NULL; sec = sec->next)
1451 {
1452 flagword f;
1453
1454 sec->_raw_size = BFD_ALIGN (sec->_raw_size, 1 << sec->alignment_power);
1455
1456 f = bfd_get_section_flags (abfd, sec);
1457 if (f & SEC_CODE)
1458 {
1459 text += sec->_raw_size;
1460 if (bfd_get_section_vma (abfd, sec) < text_low)
1461 text_low = bfd_get_section_vma (abfd, sec);
1462 if (sec->alignment_power > text_align)
1463 text_align = sec->alignment_power;
1464 }
1465 else if (f & SEC_DATA)
1466 {
1467 data += sec->_raw_size;
1468 if (bfd_get_section_vma (abfd, sec) < data_low)
1469 data_low = bfd_get_section_vma (abfd, sec);
1470 if (sec->alignment_power > data_align)
1471 data_align = sec->alignment_power;
1472 }
1473 else if (f & SEC_HAS_CONTENTS)
1474 {
1475 if (sec->alignment_power > other_align)
1476 other_align = sec->alignment_power;
1477 }
1478 else if (f & SEC_ALLOC)
1479 bss += sec->_raw_size;
1480 }
1481
1482 nlm_set_text_low (abfd, text_low);
1483 nlm_set_data_low (abfd, data_low);
1484
1485 if (nlm_no_uninitialized_data (abfd))
1486 {
1487 /* This NetWare format does not use uninitialized data. We must
1488 increase the size of the data section. We will never wind up
1489 writing those file locations, so they will remain zero. */
1490 data += bss;
1491 bss = 0;
1492 }
1493
1494 text_ptr = BFD_ALIGN (sofar, 1 << text_align);
1495 data_ptr = BFD_ALIGN (text_ptr + text, 1 << data_align);
1496 other_ptr = BFD_ALIGN (data_ptr + data, 1 << other_align);
1497
1498 /* Fill in some fields in the header for which we now have the
1499 information. */
1500 nlm_fixed_header (abfd)->codeImageOffset = text_ptr;
1501 nlm_fixed_header (abfd)->codeImageSize = text;
1502 nlm_fixed_header (abfd)->dataImageOffset = data_ptr;
1503 nlm_fixed_header (abfd)->dataImageSize = data;
1504 nlm_fixed_header (abfd)->uninitializedDataSize = bss;
1505
1506 for (sec = abfd->sections; sec != (asection *) NULL; sec = sec->next)
1507 {
1508 flagword f;
1509
1510 f = bfd_get_section_flags (abfd, sec);
1511
1512 if (f & SEC_CODE)
1513 {
1514 sec->filepos = text_ptr;
1515 text_ptr += sec->_raw_size;
1516 }
1517 else if (f & SEC_DATA)
1518 {
1519 sec->filepos = data_ptr;
1520 data_ptr += sec->_raw_size;
1521 }
1522 else if (f & SEC_HAS_CONTENTS)
1523 {
1524 sec->filepos = other_ptr;
1525 other_ptr += sec->_raw_size;
1526 }
1527 }
1528
1529 nlm_fixed_header (abfd)->relocationFixupOffset = other_ptr;
1530
1531 /* Move all common symbols into the .bss section. */
1532
1533 sym_ptr_ptr = bfd_get_outsymbols (abfd);
1534 if (sym_ptr_ptr != NULL)
1535 {
1536 asymbol **sym_end;
1537 bfd_vma add;
1538
1539 sym_end = sym_ptr_ptr + bfd_get_symcount (abfd);
1540 add = 0;
1541 for (; sym_ptr_ptr < sym_end; sym_ptr_ptr++)
1542 {
1543 asymbol *sym;
1544 bfd_vma size;
1545
1546 sym = *sym_ptr_ptr;
1547
1548 if (!bfd_is_com_section (bfd_get_section (sym)))
1549 continue;
1550
1551 /* Put the common symbol in the .bss section, and increase
1552 the size of the .bss section by the size of the common
1553 symbol (which is the old value of the symbol). */
1554 sym->section = bss_sec;
1555 size = sym->value;
1556 sym->value = bss_sec->_raw_size + add;
1557 add += size;
1558 add = BFD_ALIGN (add, 1 << bss_sec->alignment_power);
1559 }
1560 if (add != 0)
1561 {
1562 if (nlm_no_uninitialized_data (abfd))
1563 {
1564 /* We could handle this case, but so far it hasn't been
1565 necessary. */
1566 abort ();
1567 }
1568 nlm_fixed_header (abfd)->uninitializedDataSize += add;
1569 bss_sec->_raw_size += add;
1570 }
1571 }
1572
1573 return true;
1574}
1575
1576/* Set the contents of a section. To do this we need to know where
1577 the section is going to be located in the output file. That means
1578 that the sizes of all the sections must be set, and all the
1579 variable size header information must be known. */
1580
1581boolean
1582nlm_set_section_contents (abfd, section, location, offset, count)
1583 bfd *abfd;
1584 asection *section;
1585 PTR location;
1586 file_ptr offset;
1587 bfd_size_type count;
1588{
1589 if (abfd->output_has_begun == false
1590 && nlm_compute_section_file_positions (abfd) == false)
1591 return false;
1592
1593 if (count == 0)
1594 return true;
1595
1596 /* i386 NetWare has a very restricted set of relocs. In order for
1597 objcopy to work, the NLM i386 backend needs a chance to rework
1598 the section contents so that its set of relocs will work. If all
1599 the relocs are already acceptable, this will not do anything. */
1600 if (section->reloc_count != 0)
1601 {
1602 boolean (*mangle_relocs_func) PARAMS ((bfd *, asection *, PTR,
1603 bfd_vma, bfd_size_type));
1604
1605 mangle_relocs_func = nlm_mangle_relocs_func (abfd);
1606 if (mangle_relocs_func != NULL)
1607 {
1608 if (!(*mangle_relocs_func) (abfd, section, location,
1609 (bfd_vma) offset, count))
1610 return false;
1611 }
1612 }
1613
1614 if (bfd_seek (abfd, (file_ptr) (section->filepos + offset), SEEK_SET) != 0
1615 || bfd_write (location, 1, count, abfd) != count)
1616 return false;
1617
1618 return true;
1619}
1620
1621/* We need to sort a list of relocs associated with sections when we
1622 write out the external relocs. */
1623
1624static int
1625nlm_external_reloc_compare (p1, p2)
1626 const void *p1;
1627 const void *p2;
1628{
1629 const struct reloc_and_sec *r1 = (const struct reloc_and_sec *) p1;
1630 const struct reloc_and_sec *r2 = (const struct reloc_and_sec *) p2;
1631 int cmp;
1632
1633 cmp = strcmp ((*r1->rel->sym_ptr_ptr)->name,
1634 (*r2->rel->sym_ptr_ptr)->name);
1635 if (cmp != 0)
1636 return cmp;
1637
1638 /* We sort by address within symbol to make the sort more stable and
1639 increase the chances that different hosts will generate bit for
1640 bit equivalent results. */
1641 return (int) (r1->rel->address - r2->rel->address);
1642}
1643
1644/* Write out an NLM file. We write out the information in this order:
1645 fixed header
1646 variable header
1647 auxiliary headers
1648 code sections
1649 data sections
1650 other sections (custom data, messages, help, shared NLM, RPC,
1651 module dependencies)
1652 relocation fixups
1653 external references (imports)
1654 public symbols (exports)
1655 debugging records
1656 This is similar to the order used by the NetWare tools; the
1657 difference is that NetWare puts the sections other than code, data
1658 and custom data at the end of the NLM. It is convenient for us to
1659 know where the sections are going to be before worrying about the
1660 size of the other information.
1661
1662 By the time this function is called, all the section data should
1663 have been output using set_section_contents. Note that custom
1664 data, the message file, the help file, the shared NLM file, the RPC
1665 data, and the module dependencies are all considered to be
1666 sections; the caller is responsible for filling in the offset and
1667 length fields in the NLM headers. The relocation fixups and
1668 imports are both obtained from the list of relocs attached to each
1669 section. The exports and debugging records are obtained from the
1670 list of outsymbols. */
1671
1672boolean
1673nlm_write_object_contents (abfd)
1674 bfd *abfd;
1675{
1676 asection *sec;
1677 boolean (*write_import_func) PARAMS ((bfd *, asection *, arelent *));
1678 bfd_size_type external_reloc_count, internal_reloc_count, i, c;
1679 struct reloc_and_sec *external_relocs;
1680 asymbol **sym_ptr_ptr;
1681 file_ptr last;
1682 boolean (*write_prefix_func) PARAMS ((bfd *));
1683 unsigned char *fixed_header = NULL;
1684
1685 fixed_header = ((unsigned char *)
1686 bfd_malloc ((size_t) nlm_fixed_header_size (abfd)));
1687 if (fixed_header == NULL)
1688 goto error_return;
1689
1690 if (abfd->output_has_begun == false
1691 && nlm_compute_section_file_positions (abfd) == false)
1692 goto error_return;
1693
1694 /* Write out the variable length headers. */
1695 if (bfd_seek (abfd,
1696 nlm_optional_prefix_size (abfd) + nlm_fixed_header_size (abfd),
1697 SEEK_SET) != 0)
1698 goto error_return;
1699 if (nlm_swap_variable_header_out (abfd) == false
1700 || nlm_swap_auxiliary_headers_out (abfd) == false)
1701 {
1702 bfd_set_error (bfd_error_system_call);
1703 goto error_return;
1704 }
1705
1706 /* A weak check on whether the section file positions were
1707 reasonable. */
1708 if (bfd_tell (abfd) > nlm_fixed_header (abfd)->codeImageOffset)
1709 {
1710 bfd_set_error (bfd_error_invalid_operation);
1711 goto error_return;
1712 }
1713
1714 /* Advance to the relocs. */
1715 if (bfd_seek (abfd, nlm_fixed_header (abfd)->relocationFixupOffset,
1716 SEEK_SET) != 0)
1717 goto error_return;
1718
1719 /* The format of the relocation entries is dependent upon the
1720 particular target. We use an external routine to write the reloc
1721 out. */
1722 write_import_func = nlm_write_import_func (abfd);
1723
1724 /* Write out the internal relocation fixups. While we're looping
1725 over the relocs, we also count the external relocs, which is
1726 needed when they are written out below. */
1727 internal_reloc_count = 0;
1728 external_reloc_count = 0;
1729 for (sec = abfd->sections; sec != (asection *) NULL; sec = sec->next)
1730 {
1731 arelent **rel_ptr_ptr, **rel_end;
1732
1733 if (sec->reloc_count == 0)
1734 continue;
1735
1736 /* We can only represent relocs within a code or data
1737 section. We ignore them for a debugging section. */
1738 if ((bfd_get_section_flags (abfd, sec) & (SEC_CODE | SEC_DATA)) == 0)
1739 continue;
1740
1741 /* We need to know how to write out imports */
1742 if (write_import_func == NULL)
1743 {
1744 bfd_set_error (bfd_error_invalid_operation);
1745 goto error_return;
1746 }
1747
1748 rel_ptr_ptr = sec->orelocation;
1749 rel_end = rel_ptr_ptr + sec->reloc_count;
1750 for (; rel_ptr_ptr < rel_end; rel_ptr_ptr++)
1751 {
1752 arelent *rel;
1753 asymbol *sym;
1754
1755 rel = *rel_ptr_ptr;
1756 sym = *rel->sym_ptr_ptr;
1757
1758 if (! bfd_is_und_section (bfd_get_section (sym)))
1759 {
1760 ++internal_reloc_count;
1761 if ((*write_import_func) (abfd, sec, rel) == false)
1762 goto error_return;
1763 }
1764 else
1765 ++external_reloc_count;
1766 }
1767 }
1768 nlm_fixed_header (abfd)->numberOfRelocationFixups = internal_reloc_count;
1769
1770 /* Write out the imports (relocs against external symbols). These
1771 are output as a symbol name followed by all the relocs for that
1772 symbol, so we must first gather together all the relocs against
1773 external symbols and sort them. */
1774 external_relocs =
1775 (struct reloc_and_sec *) bfd_alloc (abfd,
1776 (external_reloc_count
1777 * sizeof (struct reloc_and_sec)));
1778 if (external_relocs == (struct reloc_and_sec *) NULL)
1779 goto error_return;
1780 i = 0;
1781 for (sec = abfd->sections; sec != (asection *) NULL; sec = sec->next)
1782 {
1783 arelent **rel_ptr_ptr, **rel_end;
1784
1785 if (sec->reloc_count == 0)
1786 continue;
1787
1788 rel_ptr_ptr = sec->orelocation;
1789 rel_end = rel_ptr_ptr + sec->reloc_count;
1790 for (; rel_ptr_ptr < rel_end; rel_ptr_ptr++)
1791 {
1792 arelent *rel;
1793 asymbol *sym;
1794
1795 rel = *rel_ptr_ptr;
1796 sym = *rel->sym_ptr_ptr;
1797
1798 if (! bfd_is_und_section (bfd_get_section (sym)))
1799 continue;
1800
1801 external_relocs[i].rel = rel;
1802 external_relocs[i].sec = sec;
1803 ++i;
1804 }
1805 }
1806
1807 BFD_ASSERT (i == external_reloc_count);
1808
1809 /* Sort the external relocs by name. */
1810 qsort ((PTR) external_relocs, (size_t) external_reloc_count,
1811 sizeof (struct reloc_and_sec), nlm_external_reloc_compare);
1812
1813 /* Write out the external relocs. */
1814 nlm_fixed_header (abfd)->externalReferencesOffset = bfd_tell (abfd);
1815 c = 0;
1816 i = 0;
1817 while (i < external_reloc_count)
1818 {
1819 arelent *rel;
1820 asymbol *sym;
1821 bfd_size_type j, cnt;
1822
1823 ++c;
1824
1825 rel = external_relocs[i].rel;
1826 sym = *rel->sym_ptr_ptr;
1827
1828 cnt = 0;
1829 for (j = i;
1830 (j < external_reloc_count
1831 && *external_relocs[j].rel->sym_ptr_ptr == sym);
1832 j++)
1833 ++cnt;
1834
1835 if ((*nlm_write_external_func (abfd)) (abfd, cnt, sym,
1836 &external_relocs[i])
1837 == false)
1838 goto error_return;
1839
1840 i += cnt;
1841 }
1842
1843 nlm_fixed_header (abfd)->numberOfExternalReferences = c;
1844
1845 /* Write out the public symbols (exports). */
1846 sym_ptr_ptr = bfd_get_outsymbols (abfd);
1847 if (sym_ptr_ptr != (asymbol **) NULL)
1848 {
1849 bfd_vma (*get_public_offset_func) PARAMS ((bfd *, asymbol *));
1850 boolean (*write_export_func) PARAMS ((bfd *, asymbol *, bfd_vma));
1851
1852 asymbol **sym_end;
1853
1854 nlm_fixed_header (abfd)->publicsOffset = bfd_tell (abfd);
1855 get_public_offset_func = nlm_get_public_offset_func (abfd);
1856 write_export_func = nlm_write_export_func (abfd);
1857 c = 0;
1858 sym_end = sym_ptr_ptr + bfd_get_symcount (abfd);
1859 for (; sym_ptr_ptr < sym_end; sym_ptr_ptr++)
1860 {
1861 asymbol *sym;
1862 bfd_byte len;
1863 bfd_vma offset;
1864 bfd_byte temp[NLM_TARGET_LONG_SIZE];
1865
1866 sym = *sym_ptr_ptr;
1867
1868 if ((sym->flags & (BSF_EXPORT | BSF_GLOBAL)) == 0
1869 || bfd_is_und_section (bfd_get_section (sym)))
1870 continue;
1871
1872 ++c;
1873
1874 if (get_public_offset_func)
1875 {
1876 /* Most backends can use the code below, but
1877 unfortunately some use a different scheme. */
1878 offset = (*get_public_offset_func) (abfd, sym);
1879 }
1880 else
1881 {
1882 offset = bfd_asymbol_value (sym);
1883 sec = sym->section;
1884 if (sec->flags & SEC_CODE)
1885 {
1886 offset -= nlm_get_text_low (abfd);
1887 offset |= NLM_HIBIT;
1888 }
1889 else if (sec->flags & (SEC_DATA | SEC_ALLOC))
1890 {
1891 /* SEC_ALLOC is for the .bss section. */
1892 offset -= nlm_get_data_low (abfd);
1893 }
1894 else
1895 {
1896 /* We can't handle an exported symbol that is not in
1897 the code or data segment. */
1898 bfd_set_error (bfd_error_invalid_operation);
1899 goto error_return;
1900 }
1901 }
1902
1903 if (write_export_func)
1904 {
1905 if ((*write_export_func) (abfd, sym, offset) == false)
1906 goto error_return;
1907 }
1908 else
1909 {
1910 len = strlen (sym->name);
1911 if ((bfd_write (&len, sizeof (bfd_byte), 1, abfd)
1912 != sizeof (bfd_byte))
1913 || bfd_write (sym->name, len, 1, abfd) != len)
1914 goto error_return;
1915
1916 put_word (abfd, offset, temp);
1917 if (bfd_write (temp, sizeof (temp), 1, abfd) != sizeof (temp))
1918 goto error_return;
1919 }
1920 }
1921 nlm_fixed_header (abfd)->numberOfPublics = c;
1922
1923 /* Write out the debugging records. The NLM conversion program
1924 wants to be able to inhibit this, so as a special hack if
1925 debugInfoOffset is set to -1 we don't write any debugging
1926 information. This can not be handled by fiddling with the
1927 symbol table, because exported symbols appear in both the
1928 exported symbol list and the debugging information. */
1929 if (nlm_fixed_header (abfd)->debugInfoOffset == (file_ptr) - 1)
1930 {
1931 nlm_fixed_header (abfd)->debugInfoOffset = 0;
1932 nlm_fixed_header (abfd)->numberOfDebugRecords = 0;
1933 }
1934 else
1935 {
1936 nlm_fixed_header (abfd)->debugInfoOffset = bfd_tell (abfd);
1937 c = 0;
1938 sym_ptr_ptr = bfd_get_outsymbols (abfd);
1939 sym_end = sym_ptr_ptr + bfd_get_symcount (abfd);
1940 for (; sym_ptr_ptr < sym_end; sym_ptr_ptr++)
1941 {
1942 asymbol *sym;
1943 bfd_byte type, len;
1944 bfd_vma offset;
1945 bfd_byte temp[NLM_TARGET_LONG_SIZE];
1946
1947 sym = *sym_ptr_ptr;
1948
1949 /* The NLM notion of a debugging symbol is actually what
1950 BFD calls a local or global symbol. What BFD calls a
1951 debugging symbol NLM does not understand at all. */
1952 if ((sym->flags & (BSF_LOCAL | BSF_GLOBAL | BSF_EXPORT)) == 0
1953 || (sym->flags & BSF_DEBUGGING) != 0
1954 || bfd_is_und_section (bfd_get_section (sym)))
1955 continue;
1956
1957 ++c;
1958
1959 offset = bfd_asymbol_value (sym);
1960 sec = sym->section;
1961 if (sec->flags & SEC_CODE)
1962 {
1963 offset -= nlm_get_text_low (abfd);
1964 type = 1;
1965 }
1966 else if (sec->flags & (SEC_DATA | SEC_ALLOC))
1967 {
1968 /* SEC_ALLOC is for the .bss section. */
1969 offset -= nlm_get_data_low (abfd);
1970 type = 0;
1971 }
1972 else
1973 type = 2;
1974
1975 /* The type is 0 for data, 1 for code, 2 for absolute. */
1976 if (bfd_write (&type, sizeof (bfd_byte), 1, abfd)
1977 != sizeof (bfd_byte))
1978 goto error_return;
1979
1980 put_word (abfd, offset, temp);
1981 if (bfd_write (temp, sizeof (temp), 1, abfd) != sizeof (temp))
1982 goto error_return;
1983
1984 len = strlen (sym->name);
1985 if ((bfd_write (&len, sizeof (bfd_byte), 1, abfd)
1986 != sizeof (bfd_byte))
1987 || bfd_write (sym->name, len, 1, abfd) != len)
1988 goto error_return;
1989 }
1990 nlm_fixed_header (abfd)->numberOfDebugRecords = c;
1991 }
1992 }
1993
1994 /* NLMLINK fills in offset values even if there is no data, so we do
1995 the same. */
1996 last = bfd_tell (abfd);
1997 if (nlm_fixed_header (abfd)->codeImageOffset == 0)
1998 nlm_fixed_header (abfd)->codeImageOffset = last;
1999 if (nlm_fixed_header (abfd)->dataImageOffset == 0)
2000 nlm_fixed_header (abfd)->dataImageOffset = last;
2001 if (nlm_fixed_header (abfd)->customDataOffset == 0)
2002 nlm_fixed_header (abfd)->customDataOffset = last;
2003 if (nlm_fixed_header (abfd)->moduleDependencyOffset == 0)
2004 nlm_fixed_header (abfd)->moduleDependencyOffset = last;
2005 if (nlm_fixed_header (abfd)->relocationFixupOffset == 0)
2006 nlm_fixed_header (abfd)->relocationFixupOffset = last;
2007 if (nlm_fixed_header (abfd)->externalReferencesOffset == 0)
2008 nlm_fixed_header (abfd)->externalReferencesOffset = last;
2009 if (nlm_fixed_header (abfd)->publicsOffset == 0)
2010 nlm_fixed_header (abfd)->publicsOffset = last;
2011 if (nlm_fixed_header (abfd)->debugInfoOffset == 0)
2012 nlm_fixed_header (abfd)->debugInfoOffset = last;
2013
2014 /* At this point everything has been written out except the fixed
2015 header. */
2016 memcpy (nlm_fixed_header (abfd)->signature, nlm_signature (abfd),
2017 NLM_SIGNATURE_SIZE);
2018 nlm_fixed_header (abfd)->version = NLM_HEADER_VERSION;
2019 nlm_fixed_header (abfd)->codeStartOffset =
2020 (bfd_get_start_address (abfd)
2021 - nlm_get_text_low (abfd));
2022
2023 /* We have no convenient way for the caller to pass in the exit
2024 procedure or the check unload procedure, so the caller must set
2025 the values in the header to the values of the symbols. */
2026 nlm_fixed_header (abfd)->exitProcedureOffset -= nlm_get_text_low (abfd);
2027 if (nlm_fixed_header (abfd)->checkUnloadProcedureOffset != 0)
2028 nlm_fixed_header (abfd)->checkUnloadProcedureOffset -=
2029 nlm_get_text_low (abfd);
2030
2031 if (bfd_seek (abfd, 0, SEEK_SET) != 0)
2032 goto error_return;
2033
2034 write_prefix_func = nlm_write_prefix_func (abfd);
2035 if (write_prefix_func)
2036 {
2037 if ((*write_prefix_func) (abfd) == false)
2038 goto error_return;
2039 }
2040
2041 BFD_ASSERT ((bfd_size_type) bfd_tell (abfd)
2042 == nlm_optional_prefix_size (abfd));
2043
2044 nlm_swap_fixed_header_out (abfd, nlm_fixed_header (abfd), fixed_header);
2045 if (bfd_write (fixed_header, nlm_fixed_header_size (abfd), 1, abfd)
2046 != nlm_fixed_header_size (abfd))
2047 goto error_return;
2048
2049 if (fixed_header != NULL)
2050 free (fixed_header);
2051 return true;
2052
2053error_return:
2054 if (fixed_header != NULL)
2055 free (fixed_header);
2056 return false;
2057}
Note: See TracBrowser for help on using the repository browser.