PR 518
[deliverable/binutils-gdb.git] / bfd / nlmcode.h
CommitLineData
252b5132 1/* NLM (NetWare Loadable Module) executable support for BFD.
eea6121a 2 Copyright 1993, 1994, 1995, 1998, 2000, 2001, 2002, 2003, 2004
dc810e39 3 Free Software Foundation, Inc.
252b5132
RH
4
5 Written by Fred Fish @ Cygnus Support, using ELF support as the
6 template.
7
9e12c7db 8 This file is part of BFD, the Binary File Descriptor library.
252b5132 9
9e12c7db
NC
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.
252b5132 14
9e12c7db
NC
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.
252b5132 19
9e12c7db
NC
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. */
252b5132
RH
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)
6cee3f79 45#define nlm_canonicalize_symtab nlmNAME(canonicalize_symtab)
252b5132
RH
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 59
9e12c7db 60/* Forward declarations of static functions. */
252b5132 61
b34976b6 62static bfd_boolean add_bfd_section
252b5132 63 PARAMS ((bfd *, char *, file_ptr, bfd_size_type, flagword));
b34976b6 64static bfd_boolean nlm_swap_variable_header_in
252b5132 65 PARAMS ((bfd *));
b34976b6 66static bfd_boolean nlm_swap_variable_header_out
252b5132 67 PARAMS ((bfd *));
b34976b6 68static bfd_boolean find_nonzero
252b5132 69 PARAMS ((PTR, size_t));
b34976b6 70static bfd_boolean nlm_swap_auxiliary_headers_in
252b5132 71 PARAMS ((bfd *));
b34976b6 72static bfd_boolean nlm_swap_auxiliary_headers_out
252b5132 73 PARAMS ((bfd *));
b34976b6 74static bfd_boolean nlm_slurp_symbol_table
252b5132 75 PARAMS ((bfd *));
b34976b6 76static bfd_boolean nlm_slurp_reloc_fixups
252b5132 77 PARAMS ((bfd *));
b34976b6 78static bfd_boolean nlm_compute_section_file_positions
252b5132
RH
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);
b34976b6 99 bfd_boolean (*backend_object_p) PARAMS ((bfd *));
252b5132
RH
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. */
dc810e39
AM
117 amt = nlm_fixed_header_size (abfd);
118 x_fxdhdr = (PTR) bfd_malloc (amt);
252b5132
RH
119 if (x_fxdhdr == NULL)
120 goto got_no_match;
121
dc810e39 122 if (bfd_bread ((PTR) x_fxdhdr, amt, abfd) != amt)
252b5132
RH
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. */
dc810e39
AM
132 amt = sizeof (struct nlm_obj_tdata);
133 new_tdata = (struct nlm_obj_tdata *) bfd_zalloc (abfd, amt);
252b5132
RH
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
1518639e 145 the NLM signature. */
252b5132
RH
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
9e12c7db 155 XVEC. (Hack alert!) */
252b5132
RH
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) */
252b5132
RH
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. */
252b5132
RH
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
1518639e 222/* Add a section to the bfd. */
252b5132 223
b34976b6 224static bfd_boolean
252b5132
RH
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)
b34976b6 236 return FALSE;
9e12c7db 237
1518639e 238 newsect->vma = 0; /* NLM's are relocatable. */
eea6121a 239 newsect->size = size;
252b5132
RH
240 newsect->filepos = offset;
241 newsect->flags = flags;
dc810e39 242 newsect->alignment_power = bfd_log2 ((bfd_vma) 0); /* FIXME */
9e12c7db 243
b34976b6 244 return TRUE;
252b5132
RH
245}
246
247/* Read and swap in the variable length header. All the fields must
1518639e 248 exist in the NLM, and must exist in the order they are read here. */
252b5132 249
b34976b6 250static bfd_boolean
252b5132
RH
251nlm_swap_variable_header_in (abfd)
252 bfd *abfd;
253{
254 unsigned char temp[NLM_TARGET_LONG_SIZE];
dc810e39 255 bfd_size_type amt;
252b5132 256
1518639e 257 /* Read the description length and text members. */
252b5132 258
dc810e39
AM
259 amt = sizeof (nlm_variable_header (abfd)->descriptionLength);
260 if (bfd_bread ((PTR) &nlm_variable_header (abfd)->descriptionLength,
261 amt, abfd) != amt)
b34976b6 262 return FALSE;
dc810e39
AM
263 amt = nlm_variable_header (abfd)->descriptionLength + 1;
264 if (bfd_bread ((PTR) nlm_variable_header (abfd)->descriptionText,
265 amt, abfd) != amt)
b34976b6 266 return FALSE;
252b5132 267
1518639e 268 /* Read and convert the stackSize field. */
252b5132 269
dc810e39
AM
270 amt = sizeof (temp);
271 if (bfd_bread ((PTR) temp, amt, abfd) != amt)
b34976b6 272 return FALSE;
252b5132
RH
273 nlm_variable_header (abfd)->stackSize = get_word (abfd, (bfd_byte *) temp);
274
1518639e 275 /* Read and convert the reserved field. */
252b5132 276
dc810e39
AM
277 amt = sizeof (temp);
278 if (bfd_bread ((PTR) temp, amt, abfd) != amt)
b34976b6 279 return FALSE;
252b5132
RH
280 nlm_variable_header (abfd)->reserved = get_word (abfd, (bfd_byte *) temp);
281
1518639e 282 /* Read the oldThreadName field. This field is a fixed length string. */
252b5132 283
dc810e39
AM
284 amt = sizeof (nlm_variable_header (abfd)->oldThreadName);
285 if (bfd_bread ((PTR) nlm_variable_header (abfd)->oldThreadName,
286 amt, abfd) != amt)
b34976b6 287 return FALSE;
252b5132 288
1518639e 289 /* Read the screen name length and text members. */
252b5132 290
dc810e39
AM
291 amt = sizeof (nlm_variable_header (abfd)->screenNameLength);
292 if (bfd_bread ((PTR) & nlm_variable_header (abfd)->screenNameLength,
293 amt, abfd) != amt)
b34976b6 294 return FALSE;
dc810e39
AM
295 amt = nlm_variable_header (abfd)->screenNameLength + 1;
296 if (bfd_bread ((PTR) nlm_variable_header (abfd)->screenName,
297 amt, abfd) != amt)
b34976b6 298 return FALSE;
252b5132 299
1518639e 300 /* Read the thread name length and text members. */
252b5132 301
dc810e39
AM
302 amt = sizeof (nlm_variable_header (abfd)->threadNameLength);
303 if (bfd_bread ((PTR) & nlm_variable_header (abfd)->threadNameLength,
304 amt, abfd) != amt)
b34976b6 305 return FALSE;
dc810e39
AM
306 amt = nlm_variable_header (abfd)->threadNameLength + 1;
307 if (bfd_bread ((PTR) nlm_variable_header (abfd)->threadName,
308 amt, abfd) != amt)
b34976b6
AM
309 return FALSE;
310 return TRUE;
252b5132
RH
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
b34976b6 316static bfd_boolean
252b5132
RH
317nlm_swap_variable_header_out (abfd)
318 bfd *abfd;
319{
320 unsigned char temp[NLM_TARGET_LONG_SIZE];
dc810e39 321 bfd_size_type amt;
252b5132 322
1518639e 323 /* Write the description length and text members. */
dc810e39
AM
324 amt = sizeof (nlm_variable_header (abfd)->descriptionLength);
325 if (bfd_bwrite ((PTR) & nlm_variable_header (abfd)->descriptionLength, amt,
326 abfd) != amt)
b34976b6 327 return FALSE;
dc810e39
AM
328 amt = nlm_variable_header (abfd)->descriptionLength + 1;
329 if (bfd_bwrite ((PTR) nlm_variable_header (abfd)->descriptionText, amt,
330 abfd) != amt)
b34976b6 331 return FALSE;
252b5132 332
1518639e 333 /* Convert and write the stackSize field. */
252b5132
RH
334 put_word (abfd, (bfd_vma) nlm_variable_header (abfd)->stackSize,
335 (bfd_byte *) temp);
dc810e39
AM
336 amt = sizeof (temp);
337 if (bfd_bwrite ((PTR) temp, amt, abfd) != amt)
b34976b6 338 return FALSE;
252b5132 339
1518639e 340 /* Convert and write the reserved field. */
252b5132
RH
341 put_word (abfd, (bfd_vma) nlm_variable_header (abfd)->reserved,
342 (bfd_byte *) temp);
dc810e39
AM
343 amt = sizeof (temp);
344 if (bfd_bwrite ((PTR) temp, amt, abfd) != amt)
b34976b6 345 return FALSE;
252b5132 346
1518639e 347 /* Write the oldThreadName field. This field is a fixed length string. */
dc810e39
AM
348 amt = sizeof (nlm_variable_header (abfd)->oldThreadName);
349 if (bfd_bwrite ((PTR) nlm_variable_header (abfd)->oldThreadName, amt,
350 abfd) != amt)
b34976b6 351 return FALSE;
252b5132 352
1518639e 353 /* Write the screen name length and text members. */
dc810e39
AM
354 amt = sizeof (nlm_variable_header (abfd)->screenNameLength);
355 if (bfd_bwrite ((PTR) & nlm_variable_header (abfd)->screenNameLength, amt,
356 abfd) != amt)
b34976b6 357 return FALSE;
dc810e39
AM
358 amt = nlm_variable_header (abfd)->screenNameLength + 1;
359 if (bfd_bwrite ((PTR) nlm_variable_header (abfd)->screenName, amt,
360 abfd) != amt)
b34976b6 361 return FALSE;
252b5132 362
1518639e 363 /* Write the thread name length and text members. */
dc810e39
AM
364 amt = sizeof (nlm_variable_header (abfd)->threadNameLength);
365 if (bfd_bwrite ((PTR) & nlm_variable_header (abfd)->threadNameLength, amt,
366 abfd) != amt)
b34976b6 367 return FALSE;
dc810e39
AM
368 amt = nlm_variable_header (abfd)->threadNameLength + 1;
369 if (bfd_bwrite ((PTR) nlm_variable_header (abfd)->threadName, amt,
370 abfd) != amt)
b34976b6
AM
371 return FALSE;
372 return TRUE;
252b5132
RH
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
1518639e 382 recognize it. */
252b5132 383
b34976b6 384static bfd_boolean
252b5132
RH
385nlm_swap_auxiliary_headers_in (abfd)
386 bfd *abfd;
387{
388 char tempstr[16];
dc810e39
AM
389 file_ptr position;
390 bfd_size_type amt;
252b5132
RH
391
392 for (;;)
393 {
394 position = bfd_tell (abfd);
dc810e39
AM
395 amt = sizeof (tempstr);
396 if (bfd_bread ((PTR) tempstr, amt, abfd) != amt)
b34976b6 397 return FALSE;
dc810e39 398 if (bfd_seek (abfd, position, SEEK_SET) != 0)
b34976b6 399 return FALSE;
252b5132
RH
400 if (strncmp (tempstr, "VeRsIoN#", 8) == 0)
401 {
402 Nlm_External_Version_Header thdr;
dc810e39
AM
403
404 amt = sizeof (thdr);
405 if (bfd_bread ((PTR) &thdr, amt, abfd) != amt)
b34976b6 406 return FALSE;
252b5132
RH
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;
dc810e39
AM
425
426 amt = sizeof (thdr);
427 if (bfd_bread ((PTR) &thdr, amt, abfd) != amt)
b34976b6 428 return FALSE;
252b5132
RH
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 {
dc810e39
AM
492 amt = sizeof (nlm_copyright_header (abfd)->stamp);
493 if (bfd_bread ((PTR) nlm_copyright_header (abfd)->stamp,
494 amt, abfd) != amt)
b34976b6 495 return FALSE;
dc810e39
AM
496 if (bfd_bread ((PTR) &(nlm_copyright_header (abfd)
497 ->copyrightMessageLength),
498 (bfd_size_type) 1, abfd) != 1)
b34976b6 499 return FALSE;
1518639e 500 /* The copyright message is a variable length string. */
dc810e39
AM
501 amt = nlm_copyright_header (abfd)->copyrightMessageLength + 1;
502 if (bfd_bread ((PTR) nlm_copyright_header (abfd)->copyrightMessage,
503 amt, abfd) != amt)
b34976b6 504 return FALSE;
252b5132
RH
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"). */
dc810e39
AM
516 amt = sizeof (thdr.stamp);
517 if (bfd_bread ((PTR) thdr.stamp, amt, abfd) != amt)
b34976b6 518 return FALSE;
252b5132 519 /* Read the length of this custom header. */
dc810e39
AM
520 amt = sizeof (thdr.length);
521 if (bfd_bread ((PTR) thdr.length, amt, abfd) != amt)
b34976b6 522 return FALSE;
252b5132
RH
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 {
dc810e39
AM
529 amt = sizeof (thdr.dataOffset);
530 if (bfd_bread ((PTR) thdr.dataOffset, amt, abfd) != amt)
b34976b6 531 return FALSE;
252b5132
RH
532 dataOffset = get_word (abfd, (bfd_byte *) thdr.dataOffset);
533 }
534 if (hdrLength < 2 * NLM_TARGET_LONG_SIZE)
535 dataLength = 0;
536 else
537 {
dc810e39
AM
538 amt = sizeof (thdr.dataLength);
539 if (bfd_bread ((PTR) thdr.dataLength, amt, abfd) != amt)
b34976b6 540 return FALSE;
252b5132
RH
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 {
dc810e39
AM
547 amt = sizeof (dataStamp);
548 if (bfd_bread ((PTR) dataStamp, amt, abfd) != amt)
b34976b6 549 return FALSE;
252b5132
RH
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)
b34976b6 563 return FALSE;
dc810e39 564 if (bfd_bread (hdr, hdrLength, abfd) != hdrLength)
b34976b6 565 return FALSE;
252b5132
RH
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)
b34976b6 581 return FALSE;
252b5132
RH
582 contents = (bfd_byte *) bfd_alloc (abfd, dataLength);
583 if (contents == NULL)
b34976b6 584 return FALSE;
dc810e39 585 if (bfd_bread (contents, dataLength, abfd) != dataLength)
b34976b6 586 return FALSE;
252b5132 587 if (bfd_seek (abfd, pos, SEEK_SET) != 0)
b34976b6 588 return FALSE;
252b5132
RH
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;
dc810e39 623 l = (l + 3) &~ (size_t) 3;
252b5132 624 p += l;
dc810e39 625 filepos = H_GET_32 (abfd, p);
252b5132 626 p += 4;
dc810e39 627 size = H_GET_32 (abfd, p);
252b5132
RH
628 p += 4;
629
630 newsec = bfd_make_section_anyway (abfd, name);
631 if (newsec == (asection *) NULL)
b34976b6 632 return FALSE;
eea6121a 633 newsec->size = size;
252b5132
RH
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
9e12c7db 654 break;
252b5132 655 }
b34976b6 656 return TRUE;
252b5132
RH
657}
658
659/* Return whether there is a non-zero byte in a memory block. */
660
b34976b6 661static bfd_boolean
252b5132
RH
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)
b34976b6
AM
670 return TRUE;
671 return FALSE;
252b5132
RH
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
b34976b6 678static bfd_boolean
252b5132
RH
679nlm_swap_auxiliary_headers_out (abfd)
680 bfd *abfd;
681{
dc810e39
AM
682 bfd_size_type amt;
683
252b5132
RH
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);
dc810e39
AM
703 if (bfd_bwrite ((PTR) &thdr, (bfd_size_type) sizeof (thdr), abfd)
704 != sizeof (thdr))
b34976b6 705 return FALSE;
252b5132
RH
706 }
707
9e12c7db
NC
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)
b34976b6 720 return FALSE;
9e12c7db
NC
721 thdr.copyrightMessageLength[0] =
722 nlm_copyright_header (abfd)->copyrightMessageLength;
723 amt = 1;
724 if (bfd_bwrite ((PTR) thdr.copyrightMessageLength, amt, abfd) != amt)
b34976b6 725 return FALSE;
9e12c7db
NC
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)
b34976b6 730 return FALSE;
9e12c7db
NC
731 }
732
252b5132
RH
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);
dc810e39
AM
827 if (bfd_bwrite ((PTR) &thdr, (bfd_size_type) sizeof (thdr), abfd)
828 != sizeof (thdr))
b34976b6 829 return FALSE;
252b5132
RH
830 }
831
252b5132
RH
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;
b34976b6 837 bfd_boolean ds;
252b5132
RH
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);
dc810e39
AM
853 amt = sizeof (thdr) - sizeof (thdr.dataStamp);
854 if (bfd_bwrite ((PTR) &thdr, amt, abfd) != amt)
b34976b6 855 return FALSE;
252b5132
RH
856 }
857 else
858 {
859 memcpy (thdr.dataStamp, nlm_custom_header (abfd)->dataStamp,
860 sizeof (thdr.dataStamp));
dc810e39
AM
861 amt = sizeof (thdr);
862 if (bfd_bwrite ((PTR) &thdr, amt, abfd) != amt)
b34976b6 863 return FALSE;
dc810e39
AM
864 amt = nlm_custom_header (abfd)->hdrLength;
865 if (bfd_bwrite (nlm_custom_header (abfd)->hdr, amt, abfd) != amt)
b34976b6 866 return FALSE;
252b5132
RH
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);
dc810e39
AM
884 amt = sizeof (thdr);
885 if (bfd_bwrite ((PTR) &thdr, amt, abfd) != amt)
b34976b6 886 return FALSE;
252b5132
RH
887 }
888
b34976b6 889 return TRUE;
252b5132
RH
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
1518639e 899 on this size. */
252b5132
RH
900
901long
902nlm_get_symtab_upper_bound (abfd)
903 bfd *abfd;
904{
9e12c7db 905 Nlm_Internal_Fixed_Header *i_fxdhdrp; /* Nlm file header, internal form. */
252b5132
RH
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
1518639e 918 symbol table fails. */
252b5132
RH
919
920long
6cee3f79 921nlm_canonicalize_symtab (abfd, alocation)
252b5132
RH
922 bfd *abfd;
923 asymbol **alocation;
924{
925 nlm_symbol_type *symbase;
926 bfd_size_type counter = 0;
927
82e51918 928 if (! nlm_slurp_symbol_table (abfd))
252b5132
RH
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{
dc810e39
AM
947 bfd_size_type amt = sizeof (nlm_symbol_type);
948 nlm_symbol_type *new = (nlm_symbol_type *) bfd_zalloc (abfd, amt);
252b5132 949
252b5132
RH
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)
5f771d47 959 bfd *ignore_abfd ATTRIBUTE_UNUSED;
252b5132
RH
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)
60b89a18 970 bfd *abfd;
252b5132
RH
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:
60b89a18 985 bfd_print_symbol_vandf (abfd, (PTR) file, symbol);
252b5132
RH
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
9e12c7db 1010 number of symbols. */
252b5132 1011
b34976b6 1012static bfd_boolean
252b5132
RH
1013nlm_slurp_symbol_table (abfd)
1014 bfd *abfd;
1015{
9e12c7db
NC
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. */
b34976b6
AM
1023 bfd_boolean (*read_import_func) PARAMS ((bfd *, nlm_symbol_type *));
1024 bfd_boolean (*set_public_section_func) PARAMS ((bfd *, nlm_symbol_type *));
dc810e39 1025 bfd_size_type amt;
252b5132
RH
1026
1027 if (nlm_get_symbols (abfd) != NULL)
b34976b6 1028 return TRUE;
252b5132
RH
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.
1518639e 1036 When we have all the symbols, we build the caller's pointer vector. */
252b5132
RH
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)
b34976b6 1044 return TRUE;
252b5132 1045
dc810e39 1046 if (bfd_seek (abfd, i_fxdhdrp->publicsOffset, SEEK_SET) != 0)
b34976b6 1047 return FALSE;
252b5132 1048
dc810e39
AM
1049 amt = totsymcount * sizeof (nlm_symbol_type);
1050 sym = ((nlm_symbol_type *) bfd_zalloc (abfd, amt));
252b5132 1051 if (!sym)
b34976b6 1052 return FALSE;
252b5132
RH
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
1518639e 1057 were read. */
252b5132
RH
1058
1059 set_public_section_func = nlm_set_public_section_func (abfd);
1060 symcount = i_fxdhdrp->numberOfPublics;
1061 while (abfd->symcount < symcount)
1062 {
dc810e39
AM
1063 amt = sizeof (symlength);
1064 if (bfd_bread ((PTR) &symlength, amt, abfd) != amt)
b34976b6 1065 return FALSE;
dc810e39 1066 amt = symlength;
252b5132 1067 sym->symbol.the_bfd = abfd;
dc810e39 1068 sym->symbol.name = bfd_alloc (abfd, amt + 1);
252b5132 1069 if (!sym->symbol.name)
b34976b6 1070 return FALSE;
dc810e39 1071 if (bfd_bread ((PTR) sym->symbol.name, amt, abfd) != amt)
b34976b6 1072 return FALSE;
252b5132
RH
1073 /* Cast away const. */
1074 ((char *) (sym->symbol.name))[symlength] = '\0';
dc810e39
AM
1075 amt = sizeof (temp);
1076 if (bfd_bread ((PTR) temp, amt, abfd) != amt)
b34976b6 1077 return FALSE;
252b5132
RH
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. */
82e51918 1084 if (! (*set_public_section_func) (abfd, sym))
b34976b6 1085 return FALSE;
252b5132
RH
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 {
dc810e39 1111 if (bfd_seek (abfd, i_fxdhdrp->debugInfoOffset, SEEK_SET) != 0)
b34976b6 1112 return FALSE;
252b5132
RH
1113
1114 symcount += i_fxdhdrp->numberOfDebugRecords;
1115 while (abfd->symcount < symcount)
1116 {
dc810e39
AM
1117 amt = sizeof (symtype);
1118 if (bfd_bread ((PTR) &symtype, amt, abfd) != amt)
b34976b6 1119 return FALSE;
dc810e39
AM
1120 amt = sizeof (temp);
1121 if (bfd_bread ((PTR) temp, amt, abfd) != amt)
b34976b6 1122 return FALSE;
dc810e39
AM
1123 amt = sizeof (symlength);
1124 if (bfd_bread ((PTR) &symlength, amt, abfd) != amt)
b34976b6 1125 return FALSE;
dc810e39 1126 amt = symlength;
252b5132 1127 sym->symbol.the_bfd = abfd;
dc810e39 1128 sym->symbol.name = bfd_alloc (abfd, amt + 1);
252b5132 1129 if (!sym->symbol.name)
b34976b6 1130 return FALSE;
dc810e39 1131 if (bfd_bread ((PTR) sym->symbol.name, amt, abfd) != amt)
b34976b6 1132 return FALSE;
252b5132
RH
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. */
252b5132
RH
1160 read_import_func = nlm_read_import_func (abfd);
1161 if (read_import_func != NULL)
1162 {
dc810e39 1163 if (bfd_seek (abfd, i_fxdhdrp->externalReferencesOffset, SEEK_SET) != 0)
b34976b6 1164 return FALSE;
252b5132
RH
1165
1166 symcount += i_fxdhdrp->numberOfExternalReferences;
1167 while (abfd->symcount < symcount)
1168 {
82e51918 1169 if (! (*read_import_func) (abfd, sym))
b34976b6 1170 return FALSE;
252b5132
RH
1171 sym++;
1172 abfd->symcount++;
1173 }
1174 }
1175
b34976b6 1176 return TRUE;
252b5132
RH
1177}
1178\f
1179/* Get the relocs for an NLM file. There are two types of relocs.
1180 Imports are relocs against symbols defined in other NLM files. We
1181 treat these as relocs against global symbols. Relocation fixups
1182 are internal relocs.
1183
1184 The actual format used to store the relocs is machine specific. */
1185
1186/* Read in the relocation fixup information. This is stored in
1187 nlm_relocation_fixups, an array of arelent structures, and
1188 nlm_relocation_fixup_secs, an array of section pointers. The
1189 section pointers are needed because the relocs are not sorted by
1190 section. */
1191
b34976b6 1192static bfd_boolean
252b5132
RH
1193nlm_slurp_reloc_fixups (abfd)
1194 bfd *abfd;
1195{
b34976b6
AM
1196 bfd_boolean (*read_func)
1197 PARAMS ((bfd *, nlm_symbol_type *, asection **, arelent *));
dc810e39 1198 bfd_size_type count, amt;
252b5132
RH
1199 arelent *rels;
1200 asection **secs;
1201
1202 if (nlm_relocation_fixups (abfd) != NULL)
b34976b6 1203 return TRUE;
252b5132
RH
1204 read_func = nlm_read_reloc_func (abfd);
1205 if (read_func == NULL)
b34976b6 1206 return TRUE;
252b5132
RH
1207
1208 if (bfd_seek (abfd, nlm_fixed_header (abfd)->relocationFixupOffset,
1209 SEEK_SET) != 0)
b34976b6 1210 return FALSE;
252b5132
RH
1211
1212 count = nlm_fixed_header (abfd)->numberOfRelocationFixups;
dc810e39
AM
1213 amt = count * sizeof (arelent);
1214 rels = (arelent *) bfd_alloc (abfd, amt);
1215 amt = count * sizeof (asection *);
1216 secs = (asection **) bfd_alloc (abfd, amt);
252b5132 1217 if ((rels == NULL || secs == NULL) && count != 0)
b34976b6 1218 return FALSE;
252b5132
RH
1219 nlm_relocation_fixups (abfd) = rels;
1220 nlm_relocation_fixup_secs (abfd) = secs;
1221
1222 /* We have to read piece by piece, because we don't know how large
1223 the machine specific reloc information is. */
1224 while (count-- != 0)
1225 {
82e51918 1226 if (! (*read_func) (abfd, (nlm_symbol_type *) NULL, secs, rels))
252b5132
RH
1227 {
1228 nlm_relocation_fixups (abfd) = NULL;
1229 nlm_relocation_fixup_secs (abfd) = NULL;
b34976b6 1230 return FALSE;
252b5132
RH
1231 }
1232 ++secs;
1233 ++rels;
1234 }
1235
b34976b6 1236 return TRUE;
252b5132
RH
1237}
1238
1239/* Get the number of relocs. This really just returns an upper bound,
1240 since it does not attempt to distinguish them based on the section.
1241 That will be handled when they are actually read. */
1242
1243long
1244nlm_get_reloc_upper_bound (abfd, sec)
1245 bfd *abfd;
1246 asection *sec;
1247{
1248 nlm_symbol_type *syms;
1249 bfd_size_type count;
1250 unsigned int ret;
1251
1252 /* If we don't know how to read relocs, just return 0. */
1253 if (nlm_read_reloc_func (abfd) == NULL)
1254 return -1;
1255 /* Make sure we have either the code or the data section. */
1256 if ((bfd_get_section_flags (abfd, sec) & (SEC_CODE | SEC_DATA)) == 0)
1257 return 0;
1258
1259 syms = nlm_get_symbols (abfd);
1260 if (syms == NULL)
1261 {
82e51918 1262 if (! nlm_slurp_symbol_table (abfd))
252b5132
RH
1263 return -1;
1264 syms = nlm_get_symbols (abfd);
1265 }
1266
1267 ret = nlm_fixed_header (abfd)->numberOfRelocationFixups;
1268
1269 count = bfd_get_symcount (abfd);
1270 while (count-- != 0)
1271 {
1272 ret += syms->rcnt;
1273 ++syms;
1274 }
1275
1276 return (ret + 1) * sizeof (arelent *);
1277}
1278
1279/* Get the relocs themselves. */
1280
1281long
1282nlm_canonicalize_reloc (abfd, sec, relptr, symbols)
1283 bfd *abfd;
1284 asection *sec;
1285 arelent **relptr;
1286 asymbol **symbols;
1287{
1288 arelent *rels;
1289 asection **secs;
1290 bfd_size_type count, i;
1291 unsigned int ret;
1292
1293 /* Get the relocation fixups. */
1294 rels = nlm_relocation_fixups (abfd);
1295 if (rels == NULL)
1296 {
82e51918 1297 if (! nlm_slurp_reloc_fixups (abfd))
252b5132
RH
1298 return -1;
1299 rels = nlm_relocation_fixups (abfd);
1300 }
1301 secs = nlm_relocation_fixup_secs (abfd);
1302
1303 ret = 0;
1304 count = nlm_fixed_header (abfd)->numberOfRelocationFixups;
1305 for (i = 0; i < count; i++, rels++, secs++)
1306 {
1307 if (*secs == sec)
1308 {
1309 *relptr++ = rels;
1310 ++ret;
1311 }
1312 }
1313
1314 /* Get the import symbols. */
1315 count = bfd_get_symcount (abfd);
1316 for (i = 0; i < count; i++, symbols++)
1317 {
1318 asymbol *sym;
1319
1320 sym = *symbols;
1321 if (bfd_asymbol_flavour (sym) == bfd_target_nlm_flavour)
1322 {
1323 nlm_symbol_type *nlm_sym;
1324 bfd_size_type j;
1325
1326 nlm_sym = (nlm_symbol_type *) sym;
1327 for (j = 0; j < nlm_sym->rcnt; j++)
1328 {
1329 if (nlm_sym->relocs[j].section == sec)
1330 {
1331 *relptr = &nlm_sym->relocs[j].reloc;
1332 (*relptr)->sym_ptr_ptr = symbols;
1333 ++relptr;
1334 ++ret;
1335 }
1336 }
1337 }
1338 }
1339
1340 *relptr = NULL;
1341
1342 return ret;
1343}
1344\f
1345/* Compute the section file positions for an NLM file. All variable
1346 length data in the file headers must be set before this function is
1347 called. If the variable length data is changed later, the
1348 resulting object file will be incorrect. Unfortunately, there is
1349 no way to check this.
1350
1351 This routine also sets the Size and Offset fields in the fixed
1352 header.
1353
1354 It also looks over the symbols and moves any common symbols into
1355 the .bss section; NLM has no way to represent a common symbol.
1356 This approach means that either the symbols must already have been
1357 set at this point, or there must be no common symbols. We need to
1358 move the symbols at this point so that mangle_relocs can see the
1359 final values. */
1360
b34976b6 1361static bfd_boolean
252b5132
RH
1362nlm_compute_section_file_positions (abfd)
1363 bfd *abfd;
1364{
1365 file_ptr sofar;
1366 asection *sec;
1367 bfd_vma text, data, bss;
1368 bfd_vma text_low, data_low;
1369 unsigned int text_align, data_align, other_align;
1370 file_ptr text_ptr, data_ptr, other_ptr;
1371 asection *bss_sec;
1372 asymbol **sym_ptr_ptr;
1373
82e51918 1374 if (abfd->output_has_begun)
b34976b6 1375 return TRUE;
252b5132
RH
1376
1377 /* Make sure we have a section to hold uninitialized data. */
1378 bss_sec = bfd_get_section_by_name (abfd, NLM_UNINITIALIZED_DATA_NAME);
1379 if (bss_sec == NULL)
1380 {
1381 if (!add_bfd_section (abfd, NLM_UNINITIALIZED_DATA_NAME,
1382 (file_ptr) 0, (bfd_size_type) 0,
1383 SEC_ALLOC))
b34976b6 1384 return FALSE;
252b5132
RH
1385 bss_sec = bfd_get_section_by_name (abfd, NLM_UNINITIALIZED_DATA_NAME);
1386 }
1387
b34976b6 1388 abfd->output_has_begun = TRUE;
252b5132
RH
1389
1390 /* The fixed header. */
1391 sofar = nlm_optional_prefix_size (abfd) + nlm_fixed_header_size (abfd);
1392
1393 /* The variable header. */
1394 sofar += (sizeof (nlm_variable_header (abfd)->descriptionLength)
1395 + nlm_variable_header (abfd)->descriptionLength + 1
1396 + NLM_TARGET_LONG_SIZE /* stackSize */
1397 + NLM_TARGET_LONG_SIZE /* reserved */
1398 + sizeof (nlm_variable_header (abfd)->oldThreadName)
1399 + sizeof (nlm_variable_header (abfd)->screenNameLength)
1400 + nlm_variable_header (abfd)->screenNameLength + 1
1401 + sizeof (nlm_variable_header (abfd)->threadNameLength)
1402 + nlm_variable_header (abfd)->threadNameLength + 1);
1403
1404 /* The auxiliary headers. */
1405 if (find_nonzero ((PTR) nlm_version_header (abfd),
1406 sizeof (Nlm_Internal_Version_Header)))
1407 sofar += sizeof (Nlm_External_Version_Header);
1408 if (find_nonzero ((PTR) nlm_extended_header (abfd),
1409 sizeof (Nlm_Internal_Extended_Header)))
1410 sofar += sizeof (Nlm_External_Extended_Header);
1411 if (find_nonzero ((PTR) nlm_copyright_header (abfd),
1412 sizeof (Nlm_Internal_Copyright_Header)))
1413 sofar += (sizeof (Nlm_External_Copyright_Header)
1414 + nlm_copyright_header (abfd)->copyrightMessageLength + 1);
1415 if (find_nonzero ((PTR) nlm_custom_header (abfd),
1416 sizeof (Nlm_Internal_Custom_Header)))
1417 sofar += (sizeof (Nlm_External_Custom_Header)
1418 + nlm_custom_header (abfd)->hdrLength);
1419 if (find_nonzero ((PTR) nlm_cygnus_ext_header (abfd),
1420 sizeof (Nlm_Internal_Cygnus_Ext_Header)))
1421 sofar += sizeof (Nlm_External_Custom_Header);
1422
1423 /* Compute the section file positions in two passes. First get the
1424 sizes of the text and data sections, and then set the file
1425 positions. This code aligns the sections in the file using the
1426 same alignment restrictions that apply to the sections in memory;
1427 this may not be necessary. */
1428 text = 0;
1429 text_low = (bfd_vma) - 1;
1430 text_align = 0;
1431 data = 0;
1432 data_low = (bfd_vma) - 1;
1433 data_align = 0;
1434 bss = 0;
1435 other_align = 0;
1436 for (sec = abfd->sections; sec != (asection *) NULL; sec = sec->next)
1437 {
1438 flagword f;
1439
eea6121a 1440 sec->size = BFD_ALIGN (sec->size, 1 << sec->alignment_power);
252b5132
RH
1441
1442 f = bfd_get_section_flags (abfd, sec);
1443 if (f & SEC_CODE)
1444 {
eea6121a 1445 text += sec->size;
252b5132
RH
1446 if (bfd_get_section_vma (abfd, sec) < text_low)
1447 text_low = bfd_get_section_vma (abfd, sec);
1448 if (sec->alignment_power > text_align)
1449 text_align = sec->alignment_power;
1450 }
1451 else if (f & SEC_DATA)
1452 {
eea6121a 1453 data += sec->size;
252b5132
RH
1454 if (bfd_get_section_vma (abfd, sec) < data_low)
1455 data_low = bfd_get_section_vma (abfd, sec);
1456 if (sec->alignment_power > data_align)
1457 data_align = sec->alignment_power;
1458 }
1459 else if (f & SEC_HAS_CONTENTS)
1460 {
1461 if (sec->alignment_power > other_align)
1462 other_align = sec->alignment_power;
1463 }
1464 else if (f & SEC_ALLOC)
eea6121a 1465 bss += sec->size;
252b5132
RH
1466 }
1467
1468 nlm_set_text_low (abfd, text_low);
1469 nlm_set_data_low (abfd, data_low);
1470
1471 if (nlm_no_uninitialized_data (abfd))
1472 {
1473 /* This NetWare format does not use uninitialized data. We must
1474 increase the size of the data section. We will never wind up
1475 writing those file locations, so they will remain zero. */
1476 data += bss;
1477 bss = 0;
1478 }
1479
1480 text_ptr = BFD_ALIGN (sofar, 1 << text_align);
1481 data_ptr = BFD_ALIGN (text_ptr + text, 1 << data_align);
1482 other_ptr = BFD_ALIGN (data_ptr + data, 1 << other_align);
1483
1484 /* Fill in some fields in the header for which we now have the
1485 information. */
1486 nlm_fixed_header (abfd)->codeImageOffset = text_ptr;
1487 nlm_fixed_header (abfd)->codeImageSize = text;
1488 nlm_fixed_header (abfd)->dataImageOffset = data_ptr;
1489 nlm_fixed_header (abfd)->dataImageSize = data;
1490 nlm_fixed_header (abfd)->uninitializedDataSize = bss;
1491
1492 for (sec = abfd->sections; sec != (asection *) NULL; sec = sec->next)
1493 {
1494 flagword f;
1495
1496 f = bfd_get_section_flags (abfd, sec);
1497
1498 if (f & SEC_CODE)
1499 {
1500 sec->filepos = text_ptr;
eea6121a 1501 text_ptr += sec->size;
252b5132
RH
1502 }
1503 else if (f & SEC_DATA)
1504 {
1505 sec->filepos = data_ptr;
eea6121a 1506 data_ptr += sec->size;
252b5132
RH
1507 }
1508 else if (f & SEC_HAS_CONTENTS)
1509 {
1510 sec->filepos = other_ptr;
eea6121a 1511 other_ptr += sec->size;
252b5132
RH
1512 }
1513 }
1514
1515 nlm_fixed_header (abfd)->relocationFixupOffset = other_ptr;
1516
1517 /* Move all common symbols into the .bss section. */
1518
1519 sym_ptr_ptr = bfd_get_outsymbols (abfd);
1520 if (sym_ptr_ptr != NULL)
1521 {
1522 asymbol **sym_end;
1523 bfd_vma add;
1524
1525 sym_end = sym_ptr_ptr + bfd_get_symcount (abfd);
1526 add = 0;
1527 for (; sym_ptr_ptr < sym_end; sym_ptr_ptr++)
1528 {
1529 asymbol *sym;
1530 bfd_vma size;
1531
1532 sym = *sym_ptr_ptr;
1533
1534 if (!bfd_is_com_section (bfd_get_section (sym)))
1535 continue;
1536
1537 /* Put the common symbol in the .bss section, and increase
1538 the size of the .bss section by the size of the common
1539 symbol (which is the old value of the symbol). */
1540 sym->section = bss_sec;
1541 size = sym->value;
eea6121a 1542 sym->value = bss_sec->size + add;
252b5132
RH
1543 add += size;
1544 add = BFD_ALIGN (add, 1 << bss_sec->alignment_power);
1545 }
1546 if (add != 0)
1547 {
1548 if (nlm_no_uninitialized_data (abfd))
1549 {
1550 /* We could handle this case, but so far it hasn't been
1551 necessary. */
1552 abort ();
1553 }
1554 nlm_fixed_header (abfd)->uninitializedDataSize += add;
eea6121a 1555 bss_sec->size += add;
252b5132
RH
1556 }
1557 }
1558
b34976b6 1559 return TRUE;
252b5132
RH
1560}
1561
1562/* Set the contents of a section. To do this we need to know where
1563 the section is going to be located in the output file. That means
1564 that the sizes of all the sections must be set, and all the
1565 variable size header information must be known. */
1566
b34976b6 1567bfd_boolean
252b5132
RH
1568nlm_set_section_contents (abfd, section, location, offset, count)
1569 bfd *abfd;
1570 asection *section;
0f867abe 1571 const PTR location;
252b5132
RH
1572 file_ptr offset;
1573 bfd_size_type count;
1574{
82e51918
AM
1575 if (! abfd->output_has_begun
1576 && ! nlm_compute_section_file_positions (abfd))
b34976b6 1577 return FALSE;
252b5132
RH
1578
1579 if (count == 0)
b34976b6 1580 return TRUE;
252b5132
RH
1581
1582 /* i386 NetWare has a very restricted set of relocs. In order for
1583 objcopy to work, the NLM i386 backend needs a chance to rework
1584 the section contents so that its set of relocs will work. If all
1585 the relocs are already acceptable, this will not do anything. */
1586 if (section->reloc_count != 0)
1587 {
b34976b6 1588 bfd_boolean (*mangle_relocs_func)
0f867abe 1589 PARAMS ((bfd *, asection *, const PTR, bfd_vma, bfd_size_type));
252b5132
RH
1590
1591 mangle_relocs_func = nlm_mangle_relocs_func (abfd);
1592 if (mangle_relocs_func != NULL)
1593 {
1594 if (!(*mangle_relocs_func) (abfd, section, location,
1595 (bfd_vma) offset, count))
b34976b6 1596 return FALSE;
252b5132
RH
1597 }
1598 }
1599
dc810e39
AM
1600 if (bfd_seek (abfd, section->filepos + offset, SEEK_SET) != 0
1601 || bfd_bwrite (location, count, abfd) != count)
b34976b6 1602 return FALSE;
252b5132 1603
b34976b6 1604 return TRUE;
252b5132
RH
1605}
1606
1607/* We need to sort a list of relocs associated with sections when we
1608 write out the external relocs. */
1609
1610static int
1611nlm_external_reloc_compare (p1, p2)
1612 const void *p1;
1613 const void *p2;
1614{
1615 const struct reloc_and_sec *r1 = (const struct reloc_and_sec *) p1;
1616 const struct reloc_and_sec *r2 = (const struct reloc_and_sec *) p2;
1617 int cmp;
1618
1619 cmp = strcmp ((*r1->rel->sym_ptr_ptr)->name,
1620 (*r2->rel->sym_ptr_ptr)->name);
1621 if (cmp != 0)
1622 return cmp;
1623
1624 /* We sort by address within symbol to make the sort more stable and
1625 increase the chances that different hosts will generate bit for
1626 bit equivalent results. */
1627 return (int) (r1->rel->address - r2->rel->address);
1628}
1629
1630/* Write out an NLM file. We write out the information in this order:
1631 fixed header
1632 variable header
1633 auxiliary headers
1634 code sections
1635 data sections
1636 other sections (custom data, messages, help, shared NLM, RPC,
1637 module dependencies)
1638 relocation fixups
1639 external references (imports)
1640 public symbols (exports)
1641 debugging records
1642 This is similar to the order used by the NetWare tools; the
1643 difference is that NetWare puts the sections other than code, data
1644 and custom data at the end of the NLM. It is convenient for us to
1645 know where the sections are going to be before worrying about the
1646 size of the other information.
1647
1648 By the time this function is called, all the section data should
1649 have been output using set_section_contents. Note that custom
1650 data, the message file, the help file, the shared NLM file, the RPC
1651 data, and the module dependencies are all considered to be
1652 sections; the caller is responsible for filling in the offset and
1653 length fields in the NLM headers. The relocation fixups and
1654 imports are both obtained from the list of relocs attached to each
1655 section. The exports and debugging records are obtained from the
1656 list of outsymbols. */
1657
b34976b6 1658bfd_boolean
252b5132
RH
1659nlm_write_object_contents (abfd)
1660 bfd *abfd;
1661{
1662 asection *sec;
b34976b6 1663 bfd_boolean (*write_import_func) PARAMS ((bfd *, asection *, arelent *));
252b5132
RH
1664 bfd_size_type external_reloc_count, internal_reloc_count, i, c;
1665 struct reloc_and_sec *external_relocs;
1666 asymbol **sym_ptr_ptr;
1667 file_ptr last;
b34976b6 1668 bfd_boolean (*write_prefix_func) PARAMS ((bfd *));
252b5132 1669 unsigned char *fixed_header = NULL;
dc810e39
AM
1670 file_ptr pos;
1671 bfd_size_type amt;
252b5132
RH
1672
1673 fixed_header = ((unsigned char *)
dc810e39 1674 bfd_malloc (nlm_fixed_header_size (abfd)));
252b5132
RH
1675 if (fixed_header == NULL)
1676 goto error_return;
1677
82e51918
AM
1678 if (! abfd->output_has_begun
1679 && ! nlm_compute_section_file_positions (abfd))
252b5132
RH
1680 goto error_return;
1681
1682 /* Write out the variable length headers. */
dc810e39
AM
1683 pos = nlm_optional_prefix_size (abfd) + nlm_fixed_header_size (abfd);
1684 if (bfd_seek (abfd, pos, SEEK_SET) != 0)
252b5132 1685 goto error_return;
82e51918
AM
1686 if (! nlm_swap_variable_header_out (abfd)
1687 || ! nlm_swap_auxiliary_headers_out (abfd))
252b5132
RH
1688 {
1689 bfd_set_error (bfd_error_system_call);
1690 goto error_return;
1691 }
1692
1693 /* A weak check on whether the section file positions were
1694 reasonable. */
dc810e39 1695 if (bfd_tell (abfd) > (ufile_ptr) nlm_fixed_header (abfd)->codeImageOffset)
252b5132
RH
1696 {
1697 bfd_set_error (bfd_error_invalid_operation);
1698 goto error_return;
1699 }
1700
1701 /* Advance to the relocs. */
1702 if (bfd_seek (abfd, nlm_fixed_header (abfd)->relocationFixupOffset,
1703 SEEK_SET) != 0)
1704 goto error_return;
1705
1706 /* The format of the relocation entries is dependent upon the
1707 particular target. We use an external routine to write the reloc
1708 out. */
1709 write_import_func = nlm_write_import_func (abfd);
1710
1711 /* Write out the internal relocation fixups. While we're looping
1712 over the relocs, we also count the external relocs, which is
1713 needed when they are written out below. */
1714 internal_reloc_count = 0;
1715 external_reloc_count = 0;
1716 for (sec = abfd->sections; sec != (asection *) NULL; sec = sec->next)
1717 {
1718 arelent **rel_ptr_ptr, **rel_end;
1719
1720 if (sec->reloc_count == 0)
1721 continue;
1722
1723 /* We can only represent relocs within a code or data
1724 section. We ignore them for a debugging section. */
1725 if ((bfd_get_section_flags (abfd, sec) & (SEC_CODE | SEC_DATA)) == 0)
1726 continue;
1727
1728 /* We need to know how to write out imports */
1729 if (write_import_func == NULL)
1730 {
1731 bfd_set_error (bfd_error_invalid_operation);
1732 goto error_return;
1733 }
1734
1735 rel_ptr_ptr = sec->orelocation;
1736 rel_end = rel_ptr_ptr + sec->reloc_count;
1737 for (; rel_ptr_ptr < rel_end; rel_ptr_ptr++)
1738 {
1739 arelent *rel;
1740 asymbol *sym;
1741
1742 rel = *rel_ptr_ptr;
1743 sym = *rel->sym_ptr_ptr;
1744
1745 if (! bfd_is_und_section (bfd_get_section (sym)))
1746 {
1747 ++internal_reloc_count;
82e51918 1748 if (! (*write_import_func) (abfd, sec, rel))
252b5132
RH
1749 goto error_return;
1750 }
1751 else
1752 ++external_reloc_count;
1753 }
1754 }
1755 nlm_fixed_header (abfd)->numberOfRelocationFixups = internal_reloc_count;
1756
1757 /* Write out the imports (relocs against external symbols). These
1758 are output as a symbol name followed by all the relocs for that
1759 symbol, so we must first gather together all the relocs against
1760 external symbols and sort them. */
dc810e39
AM
1761 amt = external_reloc_count * sizeof (struct reloc_and_sec);
1762 external_relocs = (struct reloc_and_sec *) bfd_alloc (abfd, amt);
252b5132
RH
1763 if (external_relocs == (struct reloc_and_sec *) NULL)
1764 goto error_return;
1765 i = 0;
1766 for (sec = abfd->sections; sec != (asection *) NULL; sec = sec->next)
1767 {
1768 arelent **rel_ptr_ptr, **rel_end;
1769
1770 if (sec->reloc_count == 0)
1771 continue;
1772
1773 rel_ptr_ptr = sec->orelocation;
1774 rel_end = rel_ptr_ptr + sec->reloc_count;
1775 for (; rel_ptr_ptr < rel_end; rel_ptr_ptr++)
1776 {
1777 arelent *rel;
1778 asymbol *sym;
1779
1780 rel = *rel_ptr_ptr;
1781 sym = *rel->sym_ptr_ptr;
1782
1783 if (! bfd_is_und_section (bfd_get_section (sym)))
1784 continue;
1785
1786 external_relocs[i].rel = rel;
1787 external_relocs[i].sec = sec;
1788 ++i;
1789 }
1790 }
1791
1792 BFD_ASSERT (i == external_reloc_count);
1793
1794 /* Sort the external relocs by name. */
1795 qsort ((PTR) external_relocs, (size_t) external_reloc_count,
1796 sizeof (struct reloc_and_sec), nlm_external_reloc_compare);
1797
1798 /* Write out the external relocs. */
1799 nlm_fixed_header (abfd)->externalReferencesOffset = bfd_tell (abfd);
1800 c = 0;
1801 i = 0;
1802 while (i < external_reloc_count)
1803 {
1804 arelent *rel;
1805 asymbol *sym;
1806 bfd_size_type j, cnt;
1807
1808 ++c;
1809
1810 rel = external_relocs[i].rel;
1811 sym = *rel->sym_ptr_ptr;
1812
1813 cnt = 0;
1814 for (j = i;
1815 (j < external_reloc_count
1816 && *external_relocs[j].rel->sym_ptr_ptr == sym);
1817 j++)
1818 ++cnt;
1819
82e51918
AM
1820 if (! (*nlm_write_external_func (abfd)) (abfd, cnt, sym,
1821 &external_relocs[i]))
252b5132
RH
1822 goto error_return;
1823
1824 i += cnt;
1825 }
1826
1827 nlm_fixed_header (abfd)->numberOfExternalReferences = c;
1828
1829 /* Write out the public symbols (exports). */
1830 sym_ptr_ptr = bfd_get_outsymbols (abfd);
1831 if (sym_ptr_ptr != (asymbol **) NULL)
1832 {
1833 bfd_vma (*get_public_offset_func) PARAMS ((bfd *, asymbol *));
b34976b6 1834 bfd_boolean (*write_export_func) PARAMS ((bfd *, asymbol *, bfd_vma));
252b5132
RH
1835
1836 asymbol **sym_end;
1837
1838 nlm_fixed_header (abfd)->publicsOffset = bfd_tell (abfd);
1839 get_public_offset_func = nlm_get_public_offset_func (abfd);
1840 write_export_func = nlm_write_export_func (abfd);
1841 c = 0;
1842 sym_end = sym_ptr_ptr + bfd_get_symcount (abfd);
1843 for (; sym_ptr_ptr < sym_end; sym_ptr_ptr++)
1844 {
1845 asymbol *sym;
1846 bfd_byte len;
1847 bfd_vma offset;
1848 bfd_byte temp[NLM_TARGET_LONG_SIZE];
1849
1850 sym = *sym_ptr_ptr;
1851
1852 if ((sym->flags & (BSF_EXPORT | BSF_GLOBAL)) == 0
1853 || bfd_is_und_section (bfd_get_section (sym)))
1854 continue;
1855
1856 ++c;
1857
1858 if (get_public_offset_func)
1859 {
1860 /* Most backends can use the code below, but
1861 unfortunately some use a different scheme. */
1862 offset = (*get_public_offset_func) (abfd, sym);
1863 }
1864 else
1865 {
1866 offset = bfd_asymbol_value (sym);
1867 sec = sym->section;
1868 if (sec->flags & SEC_CODE)
1869 {
1870 offset -= nlm_get_text_low (abfd);
1871 offset |= NLM_HIBIT;
1872 }
1873 else if (sec->flags & (SEC_DATA | SEC_ALLOC))
1874 {
1875 /* SEC_ALLOC is for the .bss section. */
1876 offset -= nlm_get_data_low (abfd);
1877 }
1878 else
1879 {
1880 /* We can't handle an exported symbol that is not in
1881 the code or data segment. */
1882 bfd_set_error (bfd_error_invalid_operation);
1883 goto error_return;
1884 }
1885 }
1886
1887 if (write_export_func)
1888 {
82e51918 1889 if (! (*write_export_func) (abfd, sym, offset))
252b5132
RH
1890 goto error_return;
1891 }
1892 else
1893 {
1894 len = strlen (sym->name);
dc810e39 1895 if ((bfd_bwrite (&len, (bfd_size_type) sizeof (bfd_byte), abfd)
252b5132 1896 != sizeof (bfd_byte))
dc810e39 1897 || bfd_bwrite (sym->name, (bfd_size_type) len, abfd) != len)
252b5132
RH
1898 goto error_return;
1899
1900 put_word (abfd, offset, temp);
dc810e39
AM
1901 if (bfd_bwrite (temp, (bfd_size_type) sizeof (temp), abfd)
1902 != sizeof (temp))
252b5132
RH
1903 goto error_return;
1904 }
1905 }
1906 nlm_fixed_header (abfd)->numberOfPublics = c;
1907
1908 /* Write out the debugging records. The NLM conversion program
1909 wants to be able to inhibit this, so as a special hack if
1910 debugInfoOffset is set to -1 we don't write any debugging
1911 information. This can not be handled by fiddling with the
1912 symbol table, because exported symbols appear in both the
1913 exported symbol list and the debugging information. */
1914 if (nlm_fixed_header (abfd)->debugInfoOffset == (file_ptr) - 1)
1915 {
1916 nlm_fixed_header (abfd)->debugInfoOffset = 0;
1917 nlm_fixed_header (abfd)->numberOfDebugRecords = 0;
1918 }
1919 else
1920 {
1921 nlm_fixed_header (abfd)->debugInfoOffset = bfd_tell (abfd);
1922 c = 0;
1923 sym_ptr_ptr = bfd_get_outsymbols (abfd);
1924 sym_end = sym_ptr_ptr + bfd_get_symcount (abfd);
1925 for (; sym_ptr_ptr < sym_end; sym_ptr_ptr++)
1926 {
1927 asymbol *sym;
1928 bfd_byte type, len;
1929 bfd_vma offset;
1930 bfd_byte temp[NLM_TARGET_LONG_SIZE];
1931
1932 sym = *sym_ptr_ptr;
1933
1934 /* The NLM notion of a debugging symbol is actually what
1935 BFD calls a local or global symbol. What BFD calls a
1936 debugging symbol NLM does not understand at all. */
1937 if ((sym->flags & (BSF_LOCAL | BSF_GLOBAL | BSF_EXPORT)) == 0
1938 || (sym->flags & BSF_DEBUGGING) != 0
1939 || bfd_is_und_section (bfd_get_section (sym)))
1940 continue;
1941
1942 ++c;
1943
1944 offset = bfd_asymbol_value (sym);
1945 sec = sym->section;
1946 if (sec->flags & SEC_CODE)
1947 {
1948 offset -= nlm_get_text_low (abfd);
1949 type = 1;
1950 }
1951 else if (sec->flags & (SEC_DATA | SEC_ALLOC))
1952 {
1953 /* SEC_ALLOC is for the .bss section. */
1954 offset -= nlm_get_data_low (abfd);
1955 type = 0;
1956 }
1957 else
1958 type = 2;
1959
1960 /* The type is 0 for data, 1 for code, 2 for absolute. */
dc810e39 1961 if (bfd_bwrite (&type, (bfd_size_type) sizeof (bfd_byte), abfd)
252b5132
RH
1962 != sizeof (bfd_byte))
1963 goto error_return;
1964
1965 put_word (abfd, offset, temp);
dc810e39
AM
1966 if (bfd_bwrite (temp, (bfd_size_type) sizeof (temp), abfd)
1967 != sizeof (temp))
252b5132
RH
1968 goto error_return;
1969
1970 len = strlen (sym->name);
dc810e39 1971 if ((bfd_bwrite (&len, (bfd_size_type) sizeof (bfd_byte), abfd)
252b5132 1972 != sizeof (bfd_byte))
dc810e39 1973 || bfd_bwrite (sym->name, (bfd_size_type) len, abfd) != len)
252b5132
RH
1974 goto error_return;
1975 }
1976 nlm_fixed_header (abfd)->numberOfDebugRecords = c;
1977 }
1978 }
1979
1980 /* NLMLINK fills in offset values even if there is no data, so we do
1981 the same. */
1982 last = bfd_tell (abfd);
1983 if (nlm_fixed_header (abfd)->codeImageOffset == 0)
1984 nlm_fixed_header (abfd)->codeImageOffset = last;
1985 if (nlm_fixed_header (abfd)->dataImageOffset == 0)
1986 nlm_fixed_header (abfd)->dataImageOffset = last;
1987 if (nlm_fixed_header (abfd)->customDataOffset == 0)
1988 nlm_fixed_header (abfd)->customDataOffset = last;
1989 if (nlm_fixed_header (abfd)->moduleDependencyOffset == 0)
1990 nlm_fixed_header (abfd)->moduleDependencyOffset = last;
1991 if (nlm_fixed_header (abfd)->relocationFixupOffset == 0)
1992 nlm_fixed_header (abfd)->relocationFixupOffset = last;
1993 if (nlm_fixed_header (abfd)->externalReferencesOffset == 0)
1994 nlm_fixed_header (abfd)->externalReferencesOffset = last;
1995 if (nlm_fixed_header (abfd)->publicsOffset == 0)
1996 nlm_fixed_header (abfd)->publicsOffset = last;
1997 if (nlm_fixed_header (abfd)->debugInfoOffset == 0)
1998 nlm_fixed_header (abfd)->debugInfoOffset = last;
1999
2000 /* At this point everything has been written out except the fixed
2001 header. */
2002 memcpy (nlm_fixed_header (abfd)->signature, nlm_signature (abfd),
2003 NLM_SIGNATURE_SIZE);
2004 nlm_fixed_header (abfd)->version = NLM_HEADER_VERSION;
2005 nlm_fixed_header (abfd)->codeStartOffset =
2006 (bfd_get_start_address (abfd)
2007 - nlm_get_text_low (abfd));
2008
2009 /* We have no convenient way for the caller to pass in the exit
2010 procedure or the check unload procedure, so the caller must set
2011 the values in the header to the values of the symbols. */
2012 nlm_fixed_header (abfd)->exitProcedureOffset -= nlm_get_text_low (abfd);
2013 if (nlm_fixed_header (abfd)->checkUnloadProcedureOffset != 0)
2014 nlm_fixed_header (abfd)->checkUnloadProcedureOffset -=
2015 nlm_get_text_low (abfd);
2016
dc810e39 2017 if (bfd_seek (abfd, (file_ptr) 0, SEEK_SET) != 0)
252b5132
RH
2018 goto error_return;
2019
2020 write_prefix_func = nlm_write_prefix_func (abfd);
2021 if (write_prefix_func)
2022 {
82e51918 2023 if (! (*write_prefix_func) (abfd))
252b5132
RH
2024 goto error_return;
2025 }
2026
2027 BFD_ASSERT ((bfd_size_type) bfd_tell (abfd)
2028 == nlm_optional_prefix_size (abfd));
2029
2030 nlm_swap_fixed_header_out (abfd, nlm_fixed_header (abfd), fixed_header);
dc810e39 2031 if (bfd_bwrite (fixed_header, nlm_fixed_header_size (abfd), abfd)
252b5132
RH
2032 != nlm_fixed_header_size (abfd))
2033 goto error_return;
2034
2035 if (fixed_header != NULL)
2036 free (fixed_header);
b34976b6 2037 return TRUE;
252b5132
RH
2038
2039error_return:
2040 if (fixed_header != NULL)
2041 free (fixed_header);
b34976b6 2042 return FALSE;
252b5132 2043}
This page took 0.496064 seconds and 4 git commands to generate.