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