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