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