Changed MDEC_OPT=BOOTWAIT= to BOOTWAIT=
[unix-history] / gnu / usr.bin / ld / rrs.c
CommitLineData
1136f72d
PR
1/*
2 * Copyright (c) 1993 Paul Kranenburg
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 * 3. All advertising materials mentioning features or use of this software
14 * must display the following acknowledgement:
15 * This product includes software developed by Paul Kranenburg.
16 * 4. The name of the author may not be used to endorse or promote products
6a61ea88 17 * derived from this software without specific prior written permission
1136f72d
PR
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
20 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
21 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
22 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
23 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
24 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
25 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
26 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
28 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29 *
6a61ea88 30 * $Id: rrs.c,v 1.10 1993/12/11 11:58:28 jkh Exp $
1136f72d
PR
31 */
32
33#include <sys/param.h>
34#include <stdio.h>
35#include <stdlib.h>
36#include <sys/types.h>
37#include <sys/stat.h>
38#include <sys/file.h>
39#include <sys/time.h>
40#include <sys/resource.h>
41#include <fcntl.h>
42#include <ar.h>
43#include <ranlib.h>
44#include <a.out.h>
45#include <stab.h>
46#include <string.h>
47#include <strings.h>
48
49#include "ld.h"
50
6a61ea88
JH
51static struct _dynamic rrs_dyn; /* defined in link.h */
52static struct so_debug rrs_so_debug; /* defined in link.h */
53static struct section_dispatch_table rrs_sdt; /* defined in link.h */
1136f72d
PR
54static got_t *rrs_got;
55static jmpslot_t *rrs_plt; /* defined in md.h */
56static struct relocation_info *rrs_reloc;
57static struct nzlist *rrs_symbols; /* RRS symbol table */
58static char *rrs_strtab; /* RRS strings */
59static struct rrs_hash *rrs_hashtab; /* RT hash table */
60static struct shobj *rrs_shobjs;
61
62static int reserved_rrs_relocs;
63static int claimed_rrs_relocs;
64
65static int number_of_gotslots;
66static int number_of_jmpslots;
67static int number_of_rrs_hash_entries;
68static int number_of_rrs_symbols;
69static int rrs_strtab_size;
70static int rrs_symbol_size;
71
72static int current_jmpslot_offset;
73static int current_got_offset;
74static int current_reloc_offset;
75static int current_hash_index;
6a61ea88 76int number_of_shobjs;
1136f72d
PR
77
78struct shobj {
79 struct shobj *next;
80 struct file_entry *entry;
81};
82
83/*
84RRS text segment:
6a61ea88 85 +-------------------+ <-- sdt_rel (rrs_text_start)
1136f72d
PR
86 | |
87 | relocation |
88 | |
6a61ea88 89 +-------------------+ <-- <sdt>.sdt_hash
1136f72d
PR
90 | |
91 | hash buckets |
92 | |
6a61ea88 93 +-------------------+ <-- <sdt>.sdt_nzlist
1136f72d
PR
94 | |
95 | symbols |
96 | |
6a61ea88 97 +-------------------+ <-- <sdt>.sdt_strings
1136f72d
PR
98 | |
99 | strings |
100 | |
6a61ea88 101 +-------------------+ <-- <sdt>.sdt_sods
1136f72d
PR
102 | |
103 | shobjs |
104 | |
105 +-------------------+
106 | |
6a61ea88 107 | shobjs strings | <-- <shobj>.sod_name
1136f72d
PR
108 | |
109 +-------------------+
110
111
112RRS data segment:
113
114 +-------------------+ <-- __DYNAMIC (rrs_data_start)
115 | |
6a61ea88 116 | _dymamic |
1136f72d 117 | |
6a61ea88 118 +-------------------+ <-- __DYNAMIC.d_debug
1136f72d 119 | |
6a61ea88 120 | so_debug |
1136f72d 121 | |
6a61ea88 122 +-------------------+ <-- __DYNAMIC.d_un.d_sdt
1136f72d 123 | |
6a61ea88 124 | sdt |
1136f72d 125 | |
6a61ea88 126 +-------------------+ <-- _GLOBAL_OFFSET_TABLE_ (sdt_got)
1136f72d
PR
127 | |
128 | _GOT_ |
129 | |
6a61ea88 130 +-------------------+ <-- sdt_plt
1136f72d
PR
131 | |
132 | PLT |
133 | |
134 +-------------------+
135*/
136
137/*
138 * Initialize RRS
139 */
140
141void
142init_rrs()
143{
144 reserved_rrs_relocs = 0;
145 claimed_rrs_relocs = 0;
146
147 number_of_rrs_symbols = 0;
148 rrs_strtab_size = 0;
149
150 /* First jmpslot reserved for run-time binder */
151 current_jmpslot_offset = sizeof(jmpslot_t);
152 number_of_jmpslots = 1;
153
154 /* First gotslot reserved for __DYNAMIC */
155 current_got_offset = sizeof(got_t);
156 number_of_gotslots = 1;
157
158 current_reloc_offset = 0;
159}
160
161/*
162 * Add NAME to the list of needed run-time objects.
80f25b52 163 * Return 1 if ENTRY was added to the list.
1136f72d 164 */
80f25b52 165int
1136f72d
PR
166rrs_add_shobj(entry)
167struct file_entry *entry;
168{
169 struct shobj **p;
170
80f25b52
JH
171 for (p = &rrs_shobjs; *p != NULL; p = &(*p)->next)
172 if (strcmp((*p)->entry->filename, entry->filename) == 0)
173 return 0;
1136f72d
PR
174 *p = (struct shobj *)xmalloc(sizeof(struct shobj));
175 (*p)->next = NULL;
176 (*p)->entry = entry;
177
178 number_of_shobjs++;
80f25b52 179 return 1;
1136f72d
PR
180}
181
182void
27b6ced7
JH
183alloc_rrs_reloc(entry, sp)
184struct file_entry *entry;
1136f72d
PR
185symbol *sp;
186{
187#ifdef DEBUG
27b6ced7 188printf("alloc_rrs_reloc: %s in %s\n", sp->name, get_file_name(entry));
1136f72d
PR
189#endif
190 reserved_rrs_relocs++;
191}
192
193void
27b6ced7
JH
194alloc_rrs_segment_reloc(entry, r)
195struct file_entry *entry;
1136f72d
PR
196struct relocation_info *r;
197{
198#ifdef DEBUG
27b6ced7
JH
199printf("alloc_rrs_segment_reloc at %#x in %s\n",
200 r->r_address, get_file_name(entry));
1136f72d
PR
201#endif
202 reserved_rrs_relocs++;
203}
204
205void
27b6ced7
JH
206alloc_rrs_jmpslot(entry, sp)
207struct file_entry *entry;
1136f72d
PR
208symbol *sp;
209{
210 if (sp->jmpslot_offset == -1) {
211 sp->jmpslot_offset = current_jmpslot_offset;
212 current_jmpslot_offset += sizeof(jmpslot_t);
213 number_of_jmpslots++;
214 if (!(link_mode & SYMBOLIC) || JMPSLOT_NEEDS_RELOC) {
215 reserved_rrs_relocs++;
216 }
217 }
218}
219
220void
27b6ced7
JH
221alloc_rrs_gotslot(entry, r, lsp)
222struct file_entry *entry;
1136f72d
PR
223struct relocation_info *r;
224struct localsymbol *lsp;
225{
226 symbol *sp = lsp->symbol;
227
228 if (!RELOC_EXTERN_P(r)) {
229
27b6ced7
JH
230 if (sp != NULL) {
231 error("%s: relocation for internal symbol expected at %#x",
232 get_file_name(entry), RELOC_ADDRESS(r));
233 return;
234 }
1136f72d
PR
235
236 if (!RELOC_STATICS_THROUGH_GOT_P(r))
237 /* No need for a GOT slot */
238 return;
239
240 if (lsp->gotslot_offset == -1) {
241 lsp->gotslot_offset = current_got_offset;
242 current_got_offset += sizeof(got_t);
243 number_of_gotslots++;
244 /*
245 * Now, see if slot needs run-time fixing
246 * If the load address is known (entry_symbol), this
247 * slot will have its final value set by `claim_got'
248 */
249 if ((link_mode & SHAREABLE) || (link_mode & SYMBOLIC))
250 reserved_rrs_relocs++;
251 }
252
27b6ced7
JH
253 } else {
254
255 if (sp == NULL) {
256 error("%s: relocation must refer to global symbol at %#x",
257 get_file_name(entry), RELOC_ADDRESS(r));
258 return;
259 }
1136f72d
PR
260
261 if (sp->alias)
262 sp = sp->alias;
263
27b6ced7
JH
264 if (sp->gotslot_offset != -1)
265 return;
266
1136f72d
PR
267 /*
268 * External symbols always get a relocation entry
269 */
270 sp->gotslot_offset = current_got_offset;
271 reserved_rrs_relocs++;
272 current_got_offset += sizeof(got_t);
273 number_of_gotslots++;
274 }
275
276}
277
278void
27b6ced7
JH
279alloc_rrs_cpy_reloc(entry, sp)
280struct file_entry *entry;
1136f72d
PR
281symbol *sp;
282{
6a61ea88 283 if (sp->flags & GS_CPYRELOCRESERVED)
1136f72d
PR
284 return;
285#ifdef DEBUG
27b6ced7 286printf("alloc_rrs_copy: %s in %s\n", sp->name, get_file_name(entry));
1136f72d 287#endif
6a61ea88 288 sp->flags |= GS_CPYRELOCRESERVED;
1136f72d
PR
289 reserved_rrs_relocs++;
290}
291
292static struct relocation_info *
293rrs_next_reloc()
294{
295 struct relocation_info *r;
296
297 r = rrs_reloc + claimed_rrs_relocs++;
298 if (claimed_rrs_relocs > reserved_rrs_relocs)
299 fatal("internal error: RRS relocs exceed allocation %d",
300 reserved_rrs_relocs);
301 return r;
302}
303
304/*
305 * Claim a RRS relocation as a result of a regular (ie. non-PIC)
306 * relocation record in a rel file.
307 *
308 * Return 1 if the output file needs no further updating.
309 * Return 0 if the relocation value pointed to by RELOCATION must
310 * written to a.out.
311 */
312int
27b6ced7
JH
313claim_rrs_reloc(entry, rp, sp, relocation)
314struct file_entry *entry;
1136f72d
PR
315struct relocation_info *rp;
316symbol *sp;
317long *relocation;
318{
319 struct relocation_info *r = rrs_next_reloc();
80f25b52 320
1136f72d 321 if (rp->r_address < text_start + text_size)
27b6ced7
JH
322 error("%s: RRS text relocation at %#x for \"%s\"",
323 get_file_name(entry), rp->r_address, sp->name);
80f25b52 324
6a61ea88 325#ifdef DEBUG
27b6ced7 326printf("claim_rrs_reloc: %s in %s\n", sp->name, get_file_name(entry));
1136f72d
PR
327#endif
328 r->r_address = rp->r_address;
329 r->r_symbolnum = sp->rrs_symbolnum;
330
331 if (link_mode & SYMBOLIC) {
332 if (!sp->defined)
27b6ced7
JH
333 error("Cannot reduce symbol \"%s\" in %s",
334 sp->name, get_file_name(entry));
1136f72d
PR
335 RELOC_EXTERN_P(r) = 0;
336 *relocation += sp->value;
337 (void) md_make_reloc(rp, r, RELTYPE_RELATIVE);
338 return 0;
339 } else {
340 RELOC_EXTERN_P(r) = 1;
341 return md_make_reloc(rp, r, RELTYPE_EXTERN);
342 }
343}
344
345/*
346 * Claim a jmpslot. Setup RRS relocation if claimed for the first time.
347 */
348long
27b6ced7
JH
349claim_rrs_jmpslot(entry, rp, sp, addend)
350struct file_entry *entry;
1136f72d
PR
351struct relocation_info *rp;
352symbol *sp;
353long addend;
354{
355 struct relocation_info *r;
356
6a61ea88
JH
357 if (sp->flags & GS_JMPSLOTCLAIMED)
358 return rrs_sdt.sdt_plt + sp->jmpslot_offset;
1136f72d
PR
359
360#ifdef DEBUG
27b6ced7
JH
361printf("claim_rrs_jmpslot: %s: %s(%d) -> offset %x (textreloc %#x)\n",
362 get_file_name(entry),
1136f72d
PR
363 sp->name, sp->rrs_symbolnum, sp->jmpslot_offset, text_relocation);
364#endif
365
366 if (sp->jmpslot_offset == -1)
367 fatal(
27b6ced7
JH
368 "internal error: %s: claim_rrs_jmpslot: %s: jmpslot_offset == -1\n",
369 get_file_name(entry),
1136f72d
PR
370 sp->name);
371
372 if ((link_mode & SYMBOLIC) || rrs_section_type == RRS_PARTIAL) {
373 if (!sp->defined)
27b6ced7
JH
374 error("Cannot reduce symbol \"%s\" in %s",
375 sp->name, get_file_name(entry));
1136f72d
PR
376
377 md_fix_jmpslot( rrs_plt + sp->jmpslot_offset/sizeof(jmpslot_t),
6a61ea88 378 rrs_sdt.sdt_plt + sp->jmpslot_offset,
1136f72d
PR
379 sp->value);
380 if (!JMPSLOT_NEEDS_RELOC) {
6a61ea88 381 return rrs_sdt.sdt_plt + sp->jmpslot_offset;
1136f72d
PR
382 }
383 } else {
6a61ea88 384 md_make_jmpslot(rrs_plt + sp->jmpslot_offset/sizeof(jmpslot_t),
1136f72d
PR
385 sp->jmpslot_offset,
386 claimed_rrs_relocs);
387 }
388
389 if (rrs_section_type == RRS_PARTIAL)
390 /* PLT is self-contained */
6a61ea88 391 return rrs_sdt.sdt_plt + sp->jmpslot_offset;
1136f72d
PR
392
393 /*
394 * Install a run-time relocation for this PLT entry.
395 */
396 r = rrs_next_reloc();
6a61ea88 397 sp->flags |= GS_JMPSLOTCLAIMED;
1136f72d
PR
398
399 RELOC_SYMBOL(r) = sp->rrs_symbolnum;
400
6a61ea88 401 r->r_address = (long)rrs_sdt.sdt_plt + sp->jmpslot_offset;
1136f72d
PR
402
403 if (link_mode & SYMBOLIC) {
404 RELOC_EXTERN_P(r) = 0;
405 md_make_jmpreloc(rp, r, RELTYPE_RELATIVE);
406 } else {
407 RELOC_EXTERN_P(r) = 1;
408 md_make_jmpreloc(rp, r, 0);
409 }
410
6a61ea88 411 return rrs_sdt.sdt_plt + sp->jmpslot_offset;
1136f72d
PR
412}
413
414/*
415 * Claim GOT entry for a global symbol. If this is the first relocation
416 * claiming the entry, setup a RRS relocation for it.
417 * Return offset into the GOT allocated to this symbol.
418 */
419long
27b6ced7
JH
420claim_rrs_gotslot(entry, rp, lsp, addend)
421struct file_entry *entry;
1136f72d
PR
422struct relocation_info *rp;
423struct localsymbol *lsp;
424long addend;
425{
426 struct relocation_info *r;
427 symbol *sp = lsp->symbol;
428 int reloc_type = 0;
429
27b6ced7
JH
430 if (sp == NULL) {
431 return 0;
432 }
433
1136f72d
PR
434 if (sp->alias)
435 sp = sp->alias;
436
437#ifdef DEBUG
438printf("claim_rrs_gotslot: %s(%d) slot offset %#x, addend %#x\n",
439 sp->name, sp->rrs_symbolnum, sp->gotslot_offset, addend);
440#endif
441 if (sp->gotslot_offset == -1)
442 fatal(
27b6ced7
JH
443 "internal error: %s: claim_rrs_gotslot: %s: gotslot_offset == -1\n",
444 get_file_name(entry), sp->name);
1136f72d 445
6a61ea88 446 if (sp->flags & GS_GOTSLOTCLAIMED)
1136f72d
PR
447 /* This symbol already passed here before. */
448 return sp->gotslot_offset;
449
450 if (sp->defined &&
451 (!(link_mode & SHAREABLE) || (link_mode & SYMBOLIC))) {
452
453 /*
454 * Reduce to just a base-relative translation.
455 */
456
457 *(got_t *)((long)rrs_got + sp->gotslot_offset) =
458 sp->value + addend;
459 reloc_type = RELTYPE_RELATIVE;
460
461 } else if ((link_mode & SYMBOLIC) || rrs_section_type == RRS_PARTIAL) {
462 /*
463 * SYMBOLIC: all symbols must be known.
464 * RRS_PARTIAL: we don't link against shared objects,
465 * so again all symbols must be known.
466 */
27b6ced7
JH
467 error("Cannot reduce symbol \"%s\" in %s",
468 sp->name, get_file_name(entry));
1136f72d
PR
469
470 } else {
471
472 /*
473 * This gotslot will be updated with symbol value at run-rime.
474 */
475
476 *(got_t *)((long)rrs_got + sp->gotslot_offset) = addend;
477 }
478
479 if (rrs_section_type == RRS_PARTIAL) {
480 /*
481 * Base address is known, gotslot should be fully
482 * relocated by now.
483 * NOTE: RRS_PARTIAL implies !SHAREABLE.
484 */
485 if (!sp->defined)
27b6ced7
JH
486 error("Cannot reduce symbol \"%s\" in %s",
487 sp->name, get_file_name(entry));
1136f72d
PR
488 return sp->gotslot_offset;
489 }
490
491 /*
492 * Claim a relocation entry.
493 * If symbol is defined and in "main" (!SHAREABLE)
494 * we still put out a relocation as we cannot easily
495 * undo the allocation.
496 * `RELTYPE_RELATIVE' relocations have the external bit off
497 * as no symbol need be looked up at run-time.
498 */
499 r = rrs_next_reloc();
6a61ea88
JH
500 sp->flags |= GS_GOTSLOTCLAIMED;
501 r->r_address = rrs_sdt.sdt_got + sp->gotslot_offset;
1136f72d
PR
502 RELOC_SYMBOL(r) = sp->rrs_symbolnum;
503 RELOC_EXTERN_P(r) = !(reloc_type == RELTYPE_RELATIVE);
504 md_make_gotreloc(rp, r, reloc_type);
505
506 return sp->gotslot_offset;
507}
508
509/*
510 * Claim a GOT entry for a static symbol. Return offset of the
511 * allocated GOT entry. If RELOC_STATICS_THROUGH_GOT_P is in effect
512 * return the offset of the symbol with respect to the *location* of
513 * the GOT.
514 */
515long
516claim_rrs_internal_gotslot(entry, rp, lsp, addend)
517struct file_entry *entry;
518struct relocation_info *rp;
519struct localsymbol *lsp;
520long addend;
521{
522 struct relocation_info *r;
523
524 addend += lsp->nzlist.nz_value;
525
526 if (!RELOC_STATICS_THROUGH_GOT_P(r))
6a61ea88 527 return addend - rrs_sdt.sdt_got;
1136f72d
PR
528
529#ifdef DEBUG
27b6ced7
JH
530printf("claim_rrs_internal_gotslot: %s: slot offset %#x, addend = %#x\n",
531 get_file_name(entry), lsp->gotslot_offset, addend);
1136f72d
PR
532#endif
533
534 if (lsp->gotslot_offset == -1)
535 fatal(
27b6ced7
JH
536 "internal error: %s: claim_rrs_internal_gotslot at %#x: slot_offset == -1\n",
537 get_file_name(entry), RELOC_ADDRESS(rp));
1136f72d 538
6a61ea88 539 if (lsp->flags & LS_GOTSLOTCLAIMED)
1136f72d
PR
540 /* Already done */
541 return lsp->gotslot_offset;
542
543 *(long *)((long)rrs_got + lsp->gotslot_offset) = addend;
544
545 if (!(link_mode & SHAREABLE))
546 return lsp->gotslot_offset;
547
548 /*
549 * Relocation entry needed for this static GOT entry.
550 */
551 r = rrs_next_reloc();
6a61ea88
JH
552 lsp->flags |= LS_GOTSLOTCLAIMED;
553 r->r_address = rrs_sdt.sdt_got + lsp->gotslot_offset;
1136f72d
PR
554 RELOC_EXTERN_P(r) = 0;
555 md_make_gotreloc(rp, r, RELTYPE_RELATIVE);
556 return lsp->gotslot_offset;
557}
558
559void
27b6ced7
JH
560claim_rrs_cpy_reloc(entry, rp, sp)
561struct file_entry *entry;
1136f72d
PR
562struct relocation_info *rp;
563symbol *sp;
564{
565 struct relocation_info *r;
566
6a61ea88 567 if (sp->flags & GS_CPYRELOCCLAIMED)
1136f72d
PR
568 return;
569
6a61ea88 570 if (!(sp->flags & GS_CPYRELOCRESERVED))
27b6ced7
JH
571 fatal("internal error: %s: claim_cpy_reloc: %s: no reservation\n",
572 get_file_name(entry), sp->name);
1136f72d
PR
573
574#ifdef DEBUG
27b6ced7
JH
575printf("claim_rrs_copy: %s: %s -> %x\n",
576 get_file_name(entry), sp->name, sp->so_defined);
1136f72d
PR
577#endif
578
579 r = rrs_next_reloc();
6a61ea88 580 sp->flags |= GS_CPYRELOCCLAIMED;
1136f72d
PR
581 r->r_address = rp->r_address;
582 RELOC_SYMBOL(r) = sp->rrs_symbolnum;
583 RELOC_EXTERN_P(r) = RELOC_EXTERN_P(rp);
584 md_make_cpyreloc(rp, r);
585}
586
587void
27b6ced7
JH
588claim_rrs_segment_reloc(entry, rp)
589struct file_entry *entry;
1136f72d
PR
590struct relocation_info *rp;
591{
592 struct relocation_info *r = rrs_next_reloc();
593
594#ifdef DEBUG
27b6ced7
JH
595printf("claim_rrs_segment_reloc: %s at %#x\n",
596 get_file_name(entry), rp->r_address);
1136f72d
PR
597#endif
598 r->r_address = rp->r_address;
599 RELOC_TYPE(r) = RELOC_TYPE(rp);
600 RELOC_EXTERN_P(r) = 0;
601 md_make_reloc(rp, r, RELTYPE_RELATIVE);
602
603}
604
605/*
606 * Fill the RRS hash table for the given symbol name.
607 * NOTE: the hash value computation must match the one in rtld.
608 */
609void
610rrs_insert_hash(cp, index)
611char *cp;
612int index;
613{
614 int hashval = 0;
615 struct rrs_hash *hp;
616
617 for (; *cp; cp++)
618 hashval = (hashval << 1) + *cp;
619
6a61ea88 620 hashval = (hashval & 0x7fffffff) % rrs_sdt.sdt_buckets;
1136f72d
PR
621
622 /* Get to the bucket */
623 hp = rrs_hashtab + hashval;
624 if (hp->rh_symbolnum == -1) {
625 /* Empty bucket, use it */
626 hp->rh_symbolnum = index;
627 hp->rh_next = 0;
628 return;
629 }
630
631 while (hp->rh_next != 0)
632 hp = rrs_hashtab + hp->rh_next;
633
634 hp->rh_next = current_hash_index++;
635 hp = rrs_hashtab + hp->rh_next;
636 hp->rh_symbolnum = index;
637 hp->rh_next = 0;
638}
639
640/*
641 * There are two interesting cases to consider here.
642 *
643 * 1) No shared objects were loaded, but there were PIC input rel files.
644 * In this case we must output a _GLOBAL_OFFSET_TABLE_ but no other
645 * RRS data. Also, the entries in the GOT must be fully resolved.
646 *
647 * 2) It's a genuine dynamically linked program, so the whole RRS scoop
648 * goes into a.out.
649 */
650void
651consider_rrs_section_lengths()
652{
653 int n;
6a61ea88 654 struct shobj *shp, **shpp;
1136f72d
PR
655 int symbolsize;
656
6a61ea88
JH
657#ifdef notyet
658/* We run into trouble with this as long as shared object symbols
659 are not checked for definitions */
660 /*
661 * First, determine the real number of shared objects we need.
662 */
663 for (shpp = &rrs_shobjs; *shpp; shpp = &(*shpp)->next) {
664 while (*shpp && !((*shpp)->entry->flags & E_SYMBOLS_USED)) {
665 if (--number_of_shobjs < 0)
666 fatal("internal error: number_of_shobjs < 0");
667 *shpp = (*shpp)->next;
668 }
669 if (*shpp == NULL)
670 break;
671 }
672#endif
1136f72d 673
6a61ea88 674 /* First, determine what of the RRS we want */
1136f72d
PR
675 if (relocatable_output)
676 rrs_section_type = RRS_NONE;
677 else if (link_mode & SHAREABLE)
678 rrs_section_type = RRS_FULL;
679 else if (number_of_shobjs == 0 /*&& !(link_mode & DYNAMIC)*/) {
680 /*
681 * First slots in both tables are reserved
682 * hence the "> 1" condition
683 */
684 if (number_of_gotslots > 1 || number_of_jmpslots > 1)
685 rrs_section_type = RRS_PARTIAL;
686 else
687 rrs_section_type = RRS_NONE;
688 } else
689 rrs_section_type = RRS_FULL;
690
691 if (rrs_section_type == RRS_NONE) {
692 got_symbol->defined = 0;
693 return;
694 }
695
696 rrs_symbol_size = LD_VERSION_NZLIST_P(soversion) ?
697 sizeof(struct nzlist) : sizeof(struct nlist);
698
699 /*
700 * If there is an entry point, __DYNAMIC must be referenced (usually
701 * from crt0), as this is the method used to determine whether the
702 * run-time linker must be called.
703 */
6a61ea88
JH
704 if (!(link_mode & SHAREABLE) &&
705 !(dynamic_symbol->flags & GS_REFERENCED))
1136f72d
PR
706 fatal("No reference to __DYNAMIC");
707
6a61ea88 708 dynamic_symbol->flags |= GS_REFERENCED;
1136f72d
PR
709
710 if (number_of_gotslots > 1)
6a61ea88 711 got_symbol->flags |= GS_REFERENCED;
1136f72d
PR
712
713
714 /* Next, allocate relocs, got and plt */
715 n = reserved_rrs_relocs * sizeof(struct relocation_info);
716 rrs_reloc = (struct relocation_info *)xmalloc(n);
717 bzero(rrs_reloc, n);
718
719 n = number_of_gotslots * sizeof(got_t);
720 rrs_got = (got_t *)xmalloc(n);
721 bzero(rrs_got, n);
722
723 n = number_of_jmpslots * sizeof(jmpslot_t);
724 rrs_plt = (jmpslot_t *)xmalloc(n);
725 bzero(rrs_plt, n);
726
727 /* Initialize first jmpslot */
728 md_fix_jmpslot(rrs_plt, 0, 0);
729
730 if (rrs_section_type == RRS_PARTIAL) {
731 rrs_data_size = number_of_gotslots * sizeof(got_t);
732 rrs_data_size += number_of_jmpslots * sizeof(jmpslot_t);
733 return;
734 }
735
736 /*
737 * Walk the symbol table, assign RRS symbol numbers
738 * Assign number 0 to __DYNAMIC (!! Sun compatibility)
739 */
740 dynamic_symbol->rrs_symbolnum = number_of_rrs_symbols++;
741 FOR_EACH_SYMBOL(i ,sp) {
6a61ea88 742 if (sp->flags & GS_REFERENCED) {
1136f72d
PR
743 rrs_strtab_size += 1 + strlen(sp->name);
744 if (sp != dynamic_symbol)
745 sp->rrs_symbolnum = number_of_rrs_symbols++;
0f052032
JH
746 if (sp->alias) {
747 /*
748 * (sigh) Always allocate space to hold the
749 * indirection. At this point there's not
750 * enough information to decide whether it's
751 * actually needed or not.
752 */
753 number_of_rrs_symbols++;
754 rrs_strtab_size += 1 + strlen(sp->alias->name);
755 }
1136f72d
PR
756 }
757 } END_EACH_SYMBOL;
758
759 /*
760 * Now that we know how many RRS symbols there are going to be,
761 * allocate and initialize the RRS symbol hash table.
762 */
6a61ea88
JH
763 rrs_sdt.sdt_buckets = number_of_rrs_symbols/4;
764 if (rrs_sdt.sdt_buckets < 4)
765 rrs_sdt.sdt_buckets = 4;
1136f72d 766
6a61ea88 767 number_of_rrs_hash_entries = rrs_sdt.sdt_buckets + number_of_rrs_symbols;
1136f72d
PR
768 rrs_hashtab = (struct rrs_hash *)xmalloc(
769 number_of_rrs_hash_entries * sizeof(struct rrs_hash));
6a61ea88 770 for (n = 0; n < rrs_sdt.sdt_buckets; n++)
1136f72d 771 rrs_hashtab[n].rh_symbolnum = -1;
6a61ea88 772 current_hash_index = rrs_sdt.sdt_buckets;
1136f72d
PR
773
774 /*
775 * Get symbols into hash table now, so we can fine tune the size
776 * of the latter. We adjust the value of `number_of_rrs_hash_entries'
777 * to the number of hash link slots actually used.
778 */
779 FOR_EACH_SYMBOL(i ,sp) {
6a61ea88 780 if (sp->flags & GS_REFERENCED)
1136f72d
PR
781 rrs_insert_hash(sp->name, sp->rrs_symbolnum);
782 } END_EACH_SYMBOL;
783 number_of_rrs_hash_entries = current_hash_index;
784
785 /*
786 * Calculate RRS section sizes.
787 */
6a61ea88
JH
788 rrs_data_size = sizeof(struct _dynamic);
789 rrs_data_size += sizeof(struct so_debug);
790 rrs_data_size += sizeof(struct section_dispatch_table);
1136f72d
PR
791 rrs_data_size += number_of_gotslots * sizeof(got_t);
792 rrs_data_size += number_of_jmpslots * sizeof(jmpslot_t);
793 rrs_data_size = MALIGN(rrs_data_size);
794
795 rrs_text_size = reserved_rrs_relocs * sizeof(struct relocation_info);
796 rrs_text_size += number_of_rrs_hash_entries * sizeof(struct rrs_hash);
797 rrs_text_size += number_of_rrs_symbols * rrs_symbol_size;
798
799 /* Align strings size */
800 rrs_strtab_size = MALIGN(rrs_strtab_size);
801 rrs_text_size += rrs_strtab_size;
802
803 /* Process needed shared objects */
804 for (shp = rrs_shobjs; shp; shp = shp->next) {
805 char *name = shp->entry->local_sym_name;
806
807 if (*name == '-' && *(name+1) == 'l')
808 name += 2;
809
6a61ea88 810 rrs_text_size += sizeof(struct sod);
1136f72d
PR
811 rrs_text_size += 1 + strlen(name);
812 }
813
814 /* Finally, align size */
815 rrs_text_size = MALIGN(rrs_text_size);
816}
817
818void
819relocate_rrs_addresses()
820{
821
822 dynamic_symbol->value = 0;
823
824 if (rrs_section_type == RRS_NONE)
825 return;
826
827 if (rrs_section_type == RRS_PARTIAL) {
6a61ea88
JH
828 got_symbol->value = rrs_sdt.sdt_got = rrs_data_start;
829 rrs_sdt.sdt_plt = rrs_sdt.sdt_got +
1136f72d
PR
830 number_of_gotslots * sizeof(got_t);
831 return;
832 }
833
834 /*
835 * RRS data relocations.
836 */
6a61ea88
JH
837 rrs_dyn.d_version = soversion;
838 rrs_dyn.d_debug = (struct so_debug *)
839 (rrs_data_start + sizeof(struct _dynamic));
840 rrs_dyn.d_un.d_sdt = (struct section_dispatch_table *)
841 ((long)rrs_dyn.d_debug + sizeof(struct so_debug));
1136f72d 842
6a61ea88
JH
843 rrs_sdt.sdt_got = (long)rrs_dyn.d_un.d_sdt +
844 sizeof(struct section_dispatch_table);
845 rrs_sdt.sdt_plt = rrs_sdt.sdt_got + number_of_gotslots*sizeof(got_t);
1136f72d
PR
846
847 /*
848 * RRS text relocations.
849 */
6a61ea88 850 rrs_sdt.sdt_rel = rrs_text_start;
1136f72d
PR
851 /*
852 * Sun BUG compatibility alert.
853 * Main program's RRS text values are relative to TXTADDR? WHY??
854 */
855#ifdef SUN_COMPAT
856 if (soversion == LD_VERSION_SUN && !(link_mode & SHAREABLE))
6a61ea88 857 rrs_sdt.sdt_rel -= N_TXTADDR(outheader);
1136f72d
PR
858#endif
859
6a61ea88 860 rrs_sdt.sdt_hash = rrs_sdt.sdt_rel +
1136f72d 861 reserved_rrs_relocs * sizeof(struct relocation_info);
6a61ea88 862 rrs_sdt.sdt_nzlist = rrs_sdt.sdt_hash +
1136f72d 863 number_of_rrs_hash_entries * sizeof(struct rrs_hash);
6a61ea88 864 rrs_sdt.sdt_strings = rrs_sdt.sdt_nzlist +
1136f72d 865 number_of_rrs_symbols * rrs_symbol_size;
6a61ea88
JH
866 rrs_sdt.sdt_str_sz = rrs_strtab_size;
867 rrs_sdt.sdt_text_sz = text_size;
868 rrs_sdt.sdt_plt_sz = number_of_jmpslots * sizeof(jmpslot_t);
1136f72d 869
6a61ea88
JH
870 rrs_sdt.sdt_sods = rrs_shobjs ? rrs_sdt.sdt_strings+rrs_strtab_size : 0;
871 rrs_sdt.sdt_filler1 = 0;
872 rrs_sdt.sdt_filler2 = 0;
1136f72d
PR
873
874 /*
875 * Assign addresses to _GLOBAL_OFFSET_TABLE_ and __DYNAMIC
876 * &__DYNAMIC is also in the first GOT entry.
877 */
6a61ea88 878 got_symbol->value = rrs_sdt.sdt_got;
1136f72d
PR
879
880 *rrs_got = dynamic_symbol->value = rrs_data_start;
881
882}
883
884void
885write_rrs_data()
886{
887 long pos;
888
889 if (rrs_section_type == RRS_NONE)
890 return;
891
892 pos = rrs_data_start + (N_DATOFF(outheader) - DATA_START(outheader));
893 if (lseek(outdesc, pos, L_SET) != pos)
894 fatal("write_rrs_data: cant position in output file");
895
896 if (rrs_section_type == RRS_PARTIAL) {
897 /*
898 * Only a GOT and PLT are needed.
899 */
900 if (number_of_gotslots <= 1)
901 fatal("write_rrs_data: # gotslots <= 1");
902
903 md_swapout_got(rrs_got, number_of_gotslots);
904 mywrite(rrs_got, number_of_gotslots,
905 sizeof(got_t), outdesc);
906
907 if (number_of_jmpslots <= 1)
908 fatal("write_rrs_data: # jmpslots <= 1");
909
910 md_swapout_jmpslot(rrs_plt, number_of_jmpslots);
911 mywrite(rrs_plt, number_of_jmpslots,
912 sizeof(jmpslot_t), outdesc);
913 return;
914 }
915
6a61ea88
JH
916 md_swapout__dynamic(&rrs_dyn);
917 mywrite(&rrs_dyn, 1, sizeof(struct _dynamic), outdesc);
1136f72d 918
6a61ea88
JH
919 md_swapout_so_debug(&rrs_so_debug);
920 mywrite(&rrs_so_debug, 1, sizeof(struct so_debug), outdesc);
1136f72d 921
6a61ea88
JH
922 md_swapout_section_dispatch_table(&rrs_sdt);
923 mywrite(&rrs_sdt, 1, sizeof(struct section_dispatch_table), outdesc);
1136f72d
PR
924
925 md_swapout_got(rrs_got, number_of_gotslots);
926 mywrite(rrs_got, number_of_gotslots, sizeof(got_t), outdesc);
927
928 md_swapout_jmpslot(rrs_plt, number_of_jmpslots);
929 mywrite(rrs_plt, number_of_jmpslots, sizeof(jmpslot_t), outdesc);
930}
931
932void
933write_rrs_text()
934{
935 long pos;
936 int i;
937 int symsize;
938 struct nzlist *nlp;
939 int offset = 0;
940 struct shobj *shp;
6a61ea88 941 struct sod *sodp;
1136f72d
PR
942
943 if (rrs_section_type == RRS_PARTIAL)
944 return;
945
946 pos = rrs_text_start + (N_TXTOFF(outheader) - TEXT_START(outheader));
947 if (lseek(outdesc, pos, L_SET) != pos)
948 fatal("write_rrs_text: cant position in output file");
949
950 /* Write relocation records */
951 md_swapout_reloc(rrs_reloc, reserved_rrs_relocs);
952 mywrite(rrs_reloc, reserved_rrs_relocs,
953 sizeof(struct relocation_info), outdesc);
954
955 /* Write the RRS symbol hash tables */
956 md_swapout_rrs_hash(rrs_hashtab, number_of_rrs_hash_entries);
957 mywrite(rrs_hashtab, number_of_rrs_hash_entries, sizeof(struct rrs_hash), outdesc);
958
959 /*
960 * Determine size of an RRS symbol entry, allocate space
961 * to collect them in.
962 */
963 symsize = number_of_rrs_symbols * rrs_symbol_size;
964 nlp = rrs_symbols = (struct nzlist *)alloca(symsize);
965 rrs_strtab = (char *)alloca(rrs_strtab_size);
966
967#define INCR_NLP(p) ((p) = (struct nzlist *)((long)(p) + rrs_symbol_size))
968
969 /* __DYNAMIC symbol *must* be first for Sun compatibility */
970 nlp->nz_desc = nlp->nz_other = 0;
971 if (LD_VERSION_NZLIST_P(soversion))
972 nlp->nz_size = 0;
973 nlp->nz_type = dynamic_symbol->defined;
974 nlp->nz_value = dynamic_symbol->value;
975 nlp->nz_value = dynamic_symbol->value;
976 nlp->nz_strx = offset;
977 strcpy(rrs_strtab + offset, dynamic_symbol->name);
978 offset += 1 + strlen(dynamic_symbol->name);
979 INCR_NLP(nlp);
980
981 /*
982 * Now, for each global symbol, construct a nzlist element
983 * for inclusion in the RRS symbol table.
984 */
985 FOR_EACH_SYMBOL(i, sp) {
986
6a61ea88 987 if (!(sp->flags & GS_REFERENCED) || sp == dynamic_symbol)
1136f72d
PR
988 continue;
989
990 if ((long)nlp - (long)rrs_symbols >=
991 number_of_rrs_symbols * rrs_symbol_size)
992 fatal(
993 "internal error: rrs symbols exceed allocation %d ",
994 number_of_rrs_symbols);
995
996 nlp->nz_desc = 0;
997 nlp->nz_other = 0;
998 if (LD_VERSION_NZLIST_P(soversion))
999 nlp->nz_size = 0;
1000
1001 if (sp->defined > 1) {
1002 /* defined with known type */
0f052032
JH
1003 if (!(link_mode & SHAREABLE) &&
1004 sp->alias && sp->alias->defined > 1) {
1005 /*
1006 * If the target of an indirect symbol has
1007 * been defined and we are outputting an
1008 * executable, resolve the indirection; it's
1009 * no longer needed.
1010 */
1011 nlp->nz_type = sp->alias->defined;
1012 nlp->nz_value = sp->alias->value;
6a61ea88 1013 nlp->nz_other = N_OTHER(0, sp->alias->aux);
0f052032 1014 } else if (sp->defined == N_SIZE) {
1136f72d
PR
1015 /*
1016 * Make sure this symbol isn't going
1017 * to define anything.
1018 */
1019 nlp->nz_type = N_UNDF;
1020 nlp->nz_value = 0;
1021 } else {
1022 nlp->nz_type = sp->defined;
1023 nlp->nz_value = sp->value;
6a61ea88 1024 nlp->nz_other = N_OTHER(0, sp->aux);
1136f72d
PR
1025 }
1026 if (LD_VERSION_NZLIST_P(soversion))
1027 nlp->nz_size = sp->size;
6a61ea88 1028 } else if (sp->common_size) {
1136f72d
PR
1029 /*
1030 * a common definition
1031 */
1032 nlp->nz_type = N_UNDF | N_EXT;
6a61ea88 1033 nlp->nz_value = sp->common_size;
1136f72d
PR
1034 } else if (!sp->defined) {
1035 /* undefined */
1036 nlp->nz_type = N_UNDF | N_EXT;
1037 nlp->nz_value = 0;
6a61ea88
JH
1038 if (sp->so_defined && sp->jmpslot_offset != -1) {
1039 /*
1040 * Define a "weak" function symbol.
1041 */
1042 if (sp->aux != AUX_FUNC)
1043 fatal("%s: non-function jmpslot",
1044 sp->name);
1045 nlp->nz_other = N_OTHER(0, sp->aux);
1046 nlp->nz_value =
1047 rrs_sdt.sdt_plt + sp->jmpslot_offset;
1048 }
1136f72d
PR
1049 } else
1050 fatal(
1051 "internal error: %s defined in mysterious way",
1052 sp->name);
1053
80f25b52 1054 /* Set symbol's name */
1136f72d
PR
1055 nlp->nz_strx = offset;
1056 strcpy(rrs_strtab + offset, sp->name);
1057 offset += 1 + strlen(sp->name);
1058
0f052032
JH
1059 if (sp->alias) {
1060 /*
1061 * Write an extra symbol for indirections (possibly
1062 * just a dummy).
1063 */
1064 int t = (nlp->nz_type == N_INDR + N_EXT);
1065
1066 INCR_NLP(nlp);
1067 nlp->nz_type = N_UNDF + t?N_EXT:0;
1068 nlp->nz_un.n_strx = offset;
1069 nlp->nz_value = 0;
1070 nlp->nz_other = 0;
1071 nlp->nz_desc = 0;
1072 nlp->nz_size = 0;
1073 strcpy(rrs_strtab + offset, sp->alias->name);
1074 offset += 1 + strlen(sp->alias->name);
1075 }
1076
1136f72d
PR
1077 INCR_NLP(nlp);
1078
1079 } END_EACH_SYMBOL;
1080
1081 if (MALIGN(offset) != rrs_strtab_size)
1082 fatal(
0f052032
JH
1083 "internal error: inconsistent RRS string table length: %d, expected %d",
1084 offset, rrs_strtab_size);
1136f72d
PR
1085
1086 /* Write the symbol table */
1087 if (rrs_symbol_size == sizeof(struct nlist))
1088 md_swapout_symbols(rrs_symbols, number_of_rrs_symbols);
1089 else
1090 md_swapout_zsymbols(rrs_symbols, number_of_rrs_symbols);
1091 mywrite(rrs_symbols, symsize, 1, outdesc);
1092
1093 /* Write the strings */
1094 mywrite(rrs_strtab, rrs_strtab_size, 1, outdesc);
1095
1096 /*
1097 * Write the names of the shared objects needed at run-time
1098 */
6a61ea88
JH
1099 pos = rrs_sdt.sdt_sods + number_of_shobjs * sizeof(struct sod);
1100 sodp = (struct sod *)alloca( number_of_shobjs * sizeof(struct sod));
1136f72d
PR
1101
1102 for (i = 0, shp = rrs_shobjs; shp; i++, shp = shp->next) {
1103 char *name = shp->entry->local_sym_name;
1104
0f052032
JH
1105 if (i >= number_of_shobjs)
1106 fatal("internal error: # of link objects exceeds %d",
1107 number_of_shobjs);
1136f72d 1108
6a61ea88
JH
1109 sodp[i].sod_name = pos;
1110 sodp[i].sod_major = shp->entry->lib_major;
1111 sodp[i].sod_minor = shp->entry->lib_minor;
1136f72d
PR
1112
1113 if (*name == '-' && *(name+1) == 'l') {
1114 name += 2;
6a61ea88 1115 sodp[i].sod_library = 1;
1136f72d 1116 } else
6a61ea88 1117 sodp[i].sod_library = 0;
1136f72d
PR
1118
1119 pos += 1 + strlen(name);
6a61ea88
JH
1120 sodp[i].sod_next = (i == number_of_shobjs - 1) ? 0 :
1121 (rrs_sdt.sdt_sods + (i+1)*sizeof(struct sod));
1558d71a 1122 }
0f052032
JH
1123
1124 if (i < number_of_shobjs)
1125 fatal("internal error: # of link objects less then expected %d",
1126 number_of_shobjs);
1136f72d 1127
6a61ea88
JH
1128 md_swapout_sod(sodp, number_of_shobjs);
1129 mywrite(sodp, number_of_shobjs, sizeof(struct sod), outdesc);
1136f72d
PR
1130
1131 for (i = 0, shp = rrs_shobjs; shp; i++, shp = shp->next) {
1132 char *name = shp->entry->local_sym_name;
1133
1134 if (*name == '-' && *(name+1) == 'l') {
1135 name += 2;
1136 }
1137
1138 mywrite(name, strlen(name) + 1, 1, outdesc);
1139 }
1140}
1141
1142void
1143write_rrs()
1144{
1145
1146 /*
1147 * First, do some consistency checks on the RRS segment.
1148 */
1149 if (rrs_section_type == RRS_NONE) {
1150 if (reserved_rrs_relocs > 1)
1151 fatal(
1152 "internal error: RRS relocs in static program: %d",
1153 reserved_rrs_relocs-1);
1154 return;
1155 }
1156
1157#ifdef DEBUG
1158printf("rrs_relocs %d, gotslots %d, jmpslots %d\n",
1159 reserved_rrs_relocs, number_of_gotslots-1, number_of_jmpslots-1);
1160#endif
1161
1162 if (claimed_rrs_relocs != reserved_rrs_relocs) {
1163/*
1164 fatal("internal error: reserved relocs(%d) != claimed(%d)",
1165 reserved_rrs_relocs, claimed_rrs_relocs);
1166*/
1167 printf("FIX:internal error: reserved relocs(%d) != claimed(%d)\n",
1168 reserved_rrs_relocs, claimed_rrs_relocs);
1169 }
1170
1171 /* Write the RRS segments. */
1172 write_rrs_text ();
1173 write_rrs_data ();
1174}