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