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