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