source: branches/libc-0.6/src/binutils/bfd/nlmcode.h

Last change on this file was 610, checked in by bird, 22 years ago

This commit was generated by cvs2svn to compensate for changes in r609,
which included commits to RCS files with non-trunk default branches.

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