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