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