root/trunk/ld/ld_layout.c @ 2658

Revision 2658, 24.7 KB (checked in by kaiwang27, 18 months ago)

Fix typos.

  • Property svn:mime-type set to text/plain
  • Property svn:eol-style set to native
  • Property svn:keywords set to Id
Line 
1/*-
2 * Copyright (c) 2011,2012 Kai Wang
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 *
14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17 * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24 * SUCH DAMAGE.
25 */
26
27#include "ld.h"
28#include "ld_arch.h"
29#include "ld_exp.h"
30#include "ld_file.h"
31#include "ld_script.h"
32#include "ld_input.h"
33#include "ld_output.h"
34#include "ld_layout.h"
35#include "ld_options.h"
36#include "ld_symbols.h"
37#include "ld_strtab.h"
38
39ELFTC_VCSID("$Id$");
40
41/*
42 * Support routines for output section layout.
43 */
44
45static void _calc_offset(struct ld *ld);
46static void _calc_output_section_offset(struct ld *ld,
47    struct ld_output_section *os);
48static void _create_dynamic(struct ld *ld);
49static void _create_interp(struct ld *ld);
50static void _create_dynsym_and_dynstr(struct ld *ld);
51static void _insert_input_to_output(struct ld_output *lo,
52    struct ld_output_section *os, struct ld_input_section *is,
53    struct ld_input_section_head *islist);
54static void _layout_orphan_section(struct ld *ld, struct ld_input *li);
55static void _layout_output_section(struct ld *ld, struct ld_input *li,
56    struct ld_script_sections_output *ldso);
57static void _layout_sections(struct ld *ld, struct ld_script_sections *ldss);
58static void _parse_output_section_descriptor(struct ld *ld,
59    struct ld_output_section *os);
60static void _print_section_layout(struct ld *ld, struct ld_output_section *os);
61static void _print_wildcard(struct ld_wildcard *lw);
62static void _print_wildcard_list(struct ld_script_list *ldl);
63static void _set_output_section_loadable_flag(struct ld_output_section *os);
64static int _wildcard_match(struct ld_wildcard *lw, const char *string);
65static int _wildcard_list_match(struct ld_script_list *list,
66    const char *string);
67
68void
69ld_layout_sections(struct ld *ld)
70{
71        struct ld_input *li;
72        struct ld_output *lo;
73        struct ld_script *lds;
74        struct ld_script_cmd *ldc;
75        struct ld_state *ls;
76        int sections_cmd_exist;
77
78        ls = &ld->ld_state;
79        lo = ld->ld_output;
80        lds = ld->ld_scp;
81
82        sections_cmd_exist = 0;
83        STAILQ_FOREACH(ldc, &lds->lds_c, ldc_next) {
84                switch (ldc->ldc_type) {
85                case LSC_ASSERT:
86                        ld_output_create_element(ld, &lo->lo_oelist, OET_ASSERT,
87                            ldc->ldc_cmd, NULL);
88                        break;
89                case LSC_ASSIGN:
90                        ld_output_create_element(ld, &lo->lo_oelist, OET_ASSIGN,
91                            ldc->ldc_cmd, NULL);
92                        break;
93                case LSC_ENTRY:
94                        ld_output_create_element(ld, &lo->lo_oelist, OET_ENTRY,
95                            ldc->ldc_cmd, NULL);
96                        break;
97                case LSC_SECTIONS:
98                        if (sections_cmd_exist)
99                                ld_fatal(ld, "found multiple SECTIONS commands"
100                                    " in the linker script");
101                        sections_cmd_exist = 1;
102                        _layout_sections(ld, ldc->ldc_cmd);
103                        break;
104                default:
105                        break;
106                }
107        }
108
109        if (!sections_cmd_exist)
110                _layout_sections(ld, NULL);
111
112        /*
113         * Check how many DSOs is needed for output object.
114         */
115        lo->lo_dso_needed = 0;
116        STAILQ_FOREACH(li, &ld->ld_lilist, li_next) {
117                if (li->li_type != LIT_DSO)
118                        continue;
119                if (li->li_dso_refcnt > 0 || !li->li_file->lf_as_needed)
120                        lo->lo_dso_needed++;
121        }
122
123        if (lo->lo_dso_needed > 0) {
124                /* Create .interp section. */
125                _create_interp(ld);
126
127                /* Create PLT and GOT sections. */
128                ld->ld_arch->create_pltgot(ld);
129
130                /* Create .dynamic section. */
131                _create_dynamic(ld);
132
133                /* Copy relevant symbols to internal dynsym table. */
134                ld_symbols_create_dynsym(ld);
135
136                /* Create .dynsym and .dynstr sections. */
137                _create_dynsym_and_dynstr(ld);
138        }
139
140        /* Calculate section offsets of the output object. */
141        _calc_offset(ld);
142
143        if (lo->lo_dso_needed > 0) {
144                /* Finalize PLT and GOT sections. */
145                ld->ld_arch->finalize_pltgot(ld);
146
147                /* Finalize internal dynsym table. */
148                ld_symbols_finalize_dynsym(ld);
149        }
150}
151
152void
153ld_layout_print_linkmap(struct ld *ld)
154{
155        struct ld_input *li;
156        struct ld_input_section *is;
157        struct ld_output *lo;
158        struct ld_output_element *oe;
159        struct ld_script *lds;
160        int i;
161
162        lo = ld->ld_output;
163        assert(lo != NULL);
164
165        /* Print out the list of discarded sections. */
166        printf("\nDiscarded input sections:\n\n");
167        STAILQ_FOREACH(li, &ld->ld_lilist, li_next) {
168                for (i = 0; (size_t) i < li->li_shnum; i++) {
169                        is = &li->li_is[i];
170                        if (is->is_discard) {
171                                printf(" %-20s ", is->is_name);
172                                if (lo->lo_ec == ELFCLASS32)
173                                        printf("0x%08jx ",
174                                            (uintmax_t) is->is_addr);
175                                else
176                                        printf("0x%016jx ",
177                                            (uintmax_t) is->is_addr);
178                                printf("0x%jx ", (uintmax_t) is->is_size);
179                                printf("%s\n", ld_input_get_fullname(ld, li));
180                        }
181                }
182        }
183
184
185        lds = ld->ld_scp;
186        if (lds == NULL)
187                return;
188
189        /* TODO: Dump memory configuration */
190
191        printf("\nLinker script and memory map\n\n");
192
193        /* TODO: Dump loaded objects. */
194
195        STAILQ_FOREACH(oe, &lo->lo_oelist, oe_next) {
196
197                switch (oe->oe_type) {
198                case OET_ASSERT:
199                        /* TODO */
200                        break;
201                case OET_ASSIGN:
202                        ld_script_assign_dump(ld, oe->oe_entry);
203                        break;
204                case OET_ENTRY:
205                        /* TODO */
206                        break;
207                case OET_OUTPUT_SECTION:
208                        _print_section_layout(ld, oe->oe_entry);
209                        break;
210                default:
211                        break;
212                }
213        }
214}
215
216static void
217_print_section_layout(struct ld *ld, struct ld_output_section *os)
218{
219        struct ld_input_section *is;
220        struct ld_input_section_head *islist;
221        struct ld_output *lo;
222        struct ld_output_element *oe;
223        struct ld_script_sections_output_input *ldoi;
224
225        lo = ld->ld_output;
226
227        if (os->os_empty)
228                printf("\n%s\n", os->os_name);
229        else {
230                printf("\n%-15s", os->os_name);
231                if (lo->lo_ec == ELFCLASS32)
232                        printf(" 0x%08jx", (uintmax_t) os->os_addr);
233                else
234                        printf(" 0x%016jx", (uintmax_t) os->os_addr);
235                printf(" %#10jx\n", (uintmax_t) os->os_size);
236        }
237
238        STAILQ_FOREACH(oe, &os->os_e, oe_next) {
239                switch (oe->oe_type) {
240                case OET_ASSIGN:
241                        ld_script_assign_dump(ld, oe->oe_entry);
242                        break;
243                case OET_INPUT_SECTION_LIST:
244                        /*
245                         * Print out wildcard patterns and input sections
246                         * matched by these patterns.
247                         */
248                        ldoi = oe->oe_entry;
249                        if (ldoi == NULL)
250                                break;
251                        putchar(' ');
252                        if (ldoi->ldoi_ar) {
253                                _print_wildcard(ldoi->ldoi_ar);
254                                putchar(':');
255                        }
256                        _print_wildcard(ldoi->ldoi_file);
257                        putchar('(');
258                        if (ldoi->ldoi_exclude) {
259                                printf("(EXCLUDE_FILE(");
260                                _print_wildcard_list(ldoi->ldoi_exclude);
261                                putchar(')');
262                                putchar(' ');
263                        }
264                        _print_wildcard_list(ldoi->ldoi_sec);
265                        putchar(')');
266                        putchar('\n');
267                        if ((islist = oe->oe_islist) == NULL)
268                                break;
269                        STAILQ_FOREACH(is, islist, is_next) {
270                                if (!strcmp(is->is_name, "COMMON") &&
271                                    is->is_size == 0)
272                                        continue;
273                                printf(" %-14s", is->is_name);
274                                if (lo->lo_ec == ELFCLASS32)
275                                        printf(" 0x%08jx", (uintmax_t)
276                                            os->os_addr + is->is_reloff);
277                                else
278                                        printf(" 0x%016jx", (uintmax_t)
279                                            os->os_addr + is->is_reloff);
280                                if (is->is_size == 0)
281                                        printf(" %10s", "0x0");
282                                else
283                                        printf(" %#10jx", (uintmax_t)
284                                            is->is_size);
285                                printf(" %s\n", ld_input_get_fullname(ld,
286                                    is->is_input));
287                        }
288                        break;
289                default:
290                        break;
291                }
292        }
293}
294
295static void
296_print_wildcard(struct ld_wildcard *lw)
297{
298
299        switch (lw->lw_sort) {
300        case LWS_NONE:
301                printf("%s", lw->lw_name);
302                break;
303        case LWS_NAME:
304                printf("SORT_BY_NAME(%s)", lw->lw_name);
305                break;
306        case LWS_ALIGN:
307                printf("SORT_BY_ALIGNMENT(%s)", lw->lw_name);
308                break;
309        case LWS_NAME_ALIGN:
310                printf("SORT_BY_NAME(SORT_BY_ALIGNMENT(%s))", lw->lw_name);
311                break;
312        case LWS_ALIGN_NAME:
313                printf("SORT_BY_ALIGNMENT(SORT_BY_NAME(%s))", lw->lw_name);
314                break;
315        default:
316                break;
317        }
318}
319
320static void
321_print_wildcard_list(struct ld_script_list *ldl)
322{
323
324        _print_wildcard(ldl->ldl_entry);
325        if (ldl->ldl_next != NULL) {
326                putchar(' ');
327                _print_wildcard_list(ldl->ldl_next);
328        }
329}
330
331off_t
332ld_layout_calc_header_size(struct ld *ld)
333{
334        struct ld_script_phdr *ldsp;
335        struct ld_output *lo;
336        struct ld_output_section *os;
337        off_t header_size;
338        unsigned ec, w, num_phdrs;
339        int new;
340
341        lo = ld->ld_output;
342        assert(lo != NULL);
343
344        header_size = 0;
345
346        ec = elftc_bfd_target_class(ld->ld_otgt);
347
348        if (ec == ELFCLASS32)
349                header_size += sizeof(Elf32_Ehdr);
350        else
351                header_size += sizeof(Elf64_Ehdr);
352
353        if (!STAILQ_EMPTY(&ld->ld_scp->lds_p)) {
354                num_phdrs = 0;
355                STAILQ_FOREACH(ldsp, &ld->ld_scp->lds_p, ldsp_next)
356                        num_phdrs++;
357        } else {
358                if (lo->lo_phdr_num > 0)
359                        num_phdrs = lo->lo_phdr_num;
360                else {
361                        num_phdrs = 0;
362                        new = 1;
363                        w = 0;
364                        STAILQ_FOREACH(os, &lo->lo_oslist, os_next) {
365                                if (os->os_empty)
366                                        continue;
367
368                                if ((os->os_flags & SHF_ALLOC) == 0) {
369                                        new = 1;
370                                        continue;
371                                }
372
373                                if ((os->os_flags & SHF_WRITE) != w || new) {
374                                        new = 0;
375                                        num_phdrs++;
376                                        w = os->os_flags & SHF_WRITE;
377                                }
378                        }
379
380                        if (lo->lo_dso_needed > 0)
381                                num_phdrs++;
382
383                        if (lo->lo_interp != NULL)
384                                num_phdrs++;
385
386                        if (lo->lo_phdr_note)
387                                num_phdrs++;
388
389                        if (ld->ld_gen_gnustack)
390                                num_phdrs++;
391                }
392        }
393
394        if (ec == ELFCLASS32)
395                header_size += num_phdrs * sizeof(Elf32_Phdr);
396        else
397                header_size += num_phdrs * sizeof(Elf64_Phdr);
398
399        lo->lo_phdr_num = num_phdrs;
400
401        return (header_size);
402}
403
404static void
405_layout_sections(struct ld *ld, struct ld_script_sections *ldss)
406{
407        struct ld_input *li;
408        struct ld_output *lo;
409        struct ld_script_cmd *ldc;
410        int first;
411
412        ld_input_link_objects(ld);
413
414        first = 1;
415        lo = ld->ld_output;
416        STAILQ_FOREACH(li, &ld->ld_lilist, li_next) {
417                ld_input_init_sections(ld, li);
418                if (li->li_type != LIT_RELOCATABLE)
419                        continue;
420                STAILQ_FOREACH(ldc, &ldss->ldss_c, ldc_next) {
421                        switch (ldc->ldc_type) {
422                        case LSC_ASSERT:
423                                if (!first)
424                                        break;
425                                ld_output_create_element(ld, &lo->lo_oelist,
426                                    OET_ASSIGN, ldc->ldc_cmd, NULL);
427                        case LSC_ASSIGN:
428                                if (!first)
429                                        break;
430                                ld_output_create_element(ld, &lo->lo_oelist,
431                                    OET_ASSIGN, ldc->ldc_cmd, NULL);
432                                break;
433                        case LSC_ENTRY:
434                                ld_output_create_element(ld, &lo->lo_oelist,
435                                    OET_ENTRY, ldc->ldc_cmd, NULL);
436                                break;
437                        case LSC_SECTIONS_OUTPUT:
438                                _layout_output_section(ld, li, ldc->ldc_cmd);
439                                break;
440                        case LSC_SECTIONS_OVERLAY:
441                                /* TODO */
442                                break;
443                        default:
444                                break;
445                        }
446                }
447                first = 0;
448        }
449
450        STAILQ_FOREACH(li, &ld->ld_lilist, li_next) {
451                if (li->li_type != LIT_RELOCATABLE)
452                        continue;
453                _layout_orphan_section(ld, li);
454        }
455}
456
457static int
458_wildcard_match(struct ld_wildcard *lw, const char *string)
459{
460
461        return (fnmatch(lw->lw_name, string, 0) == 0);
462}
463
464static int
465_wildcard_list_match(struct ld_script_list *list, const char *string)
466{
467        struct ld_script_list *ldl;
468
469        for (ldl = list; ldl != NULL; ldl = ldl->ldl_next)
470                if (_wildcard_match(ldl->ldl_entry, string))
471                        return (1);
472
473        return (0);
474}
475
476static void
477_set_output_section_loadable_flag(struct ld_output_section *os)
478{
479        struct ld_script_sections_output *ldso;
480        struct ld_exp *le;
481
482        if ((ldso = os->os_ldso) == NULL)
483                return;
484
485        if (ldso->ldso_vma == NULL)
486                os->os_flags |= SHF_ALLOC;
487        else {
488                le = ldso->ldso_vma;
489                if (le->le_op != LEOP_CONSTANT || le->le_val != 0)
490                        os->os_flags |= SHF_ALLOC;
491        }
492
493        if (ldso->ldso_type != NULL && strcmp(ldso->ldso_type, "NOLOAD") == 0)
494                os->os_flags &= ~SHF_ALLOC;
495}
496
497static void
498_layout_output_section(struct ld *ld, struct ld_input *li,
499    struct ld_script_sections_output *ldso)
500{
501        struct ld_file *lf;
502        struct ld_output *lo;
503        struct ld_script_cmd *ldc;
504        struct ld_script_sections_output_input *ldoi;
505        struct ld_input_section *is;
506        struct ld_input_section_head *islist;
507        struct ld_output_element *oe;
508        struct ld_output_section *os;
509        int i, new_section;
510
511        lf = li->li_file;
512        lo = ld->ld_output;
513        new_section = 0;
514        oe = NULL;
515        HASH_FIND_STR(lo->lo_ostbl, ldso->ldso_name, os);
516        if (os == NULL) {
517                os = ld_output_alloc_section(ld, ldso->ldso_name, NULL);
518                os->os_ldso = ldso;
519                _set_output_section_loadable_flag(os);
520                new_section = 1;
521        } else
522                oe = STAILQ_FIRST(&os->os_e);
523
524        STAILQ_FOREACH(ldc, &ldso->ldso_c, ldc_next) {
525                switch (ldc->ldc_type) {
526                case LSC_ASSERT:
527                        if (new_section)
528                                oe = ld_output_create_element(ld, &os->os_e,
529                                    OET_ASSERT, ldc->ldc_cmd, NULL);
530                        break;
531                case LSC_ASSIGN:
532                        if (new_section)
533                                oe = ld_output_create_element(ld, &os->os_e,
534                                    OET_ASSIGN, ldc->ldc_cmd, NULL);
535                        break;
536                case LSC_SECTIONS_OUTPUT_DATA:
537                        if (new_section)
538                                oe = ld_output_create_element(ld, &os->os_e,
539                                    OET_DATA, ldc->ldc_cmd, NULL);
540                        break;
541                case LSC_SECTIONS_OUTPUT_INPUT:
542                        if (new_section) {
543                                islist = calloc(1, sizeof(*islist));
544                                if (islist == NULL)
545                                        ld_fatal_std(ld, "calloc");
546                                STAILQ_INIT(islist);
547                                oe = ld_output_create_element(ld, &os->os_e,
548                                    OET_INPUT_SECTION_LIST, ldc->ldc_cmd, NULL);
549                                oe->oe_islist = islist;
550                        }
551                        break;
552                case LSC_SECTIONS_OUTPUT_KEYWORD:
553                        if (new_section)
554                                ld_output_create_element(ld, &os->os_e,
555                                    OET_KEYWORD, ldc->ldc_cmd, NULL);
556                        break;
557                default:
558                        ld_fatal(ld, "internal: invalid output section "
559                            "command: %d", ldc->ldc_type);
560                }
561                if (ldc->ldc_type != LSC_SECTIONS_OUTPUT_INPUT)
562                        goto next_output_cmd;
563
564                ldoi = ldc->ldc_cmd;
565
566                if (ldoi->ldoi_ar != NULL && li->li_lam != NULL &&
567                    !_wildcard_match(ldoi->ldoi_ar, lf->lf_name))
568                        goto next_output_cmd;
569
570                assert(ldoi->ldoi_file != NULL);
571                if (!_wildcard_match(ldoi->ldoi_file, li->li_name))
572                        goto next_output_cmd;
573
574                if (ldoi->ldoi_exclude != NULL &&
575                    _wildcard_list_match(ldoi->ldoi_exclude, li->li_name))
576                        goto next_output_cmd;
577
578                assert(ldoi->ldoi_sec != NULL);
579                for (i = 1; (size_t) i < li->li_shnum; i++) {
580                        is = &li->li_is[i];
581                        if (!is->is_orphan)
582                                continue;
583                        if (!_wildcard_list_match(ldoi->ldoi_sec, is->is_name))
584                                continue;
585                        if (strcmp(os->os_name, "/DISCARD/") == 0) {
586                                is->is_discard = 1;
587                                continue;
588                        }
589                        assert(oe != NULL &&
590                            oe->oe_type == OET_INPUT_SECTION_LIST);
591                        _insert_input_to_output(lo, os, is, oe->oe_islist);
592                }
593
594        next_output_cmd:
595                assert(oe != NULL);
596                if (!new_section)
597                        oe = STAILQ_NEXT(oe, oe_next);                 
598        }
599}
600
601static void
602_layout_orphan_section(struct ld *ld, struct ld_input *li)
603{
604        struct ld_input_section *is;
605        struct ld_input_section_head *islist;
606        struct ld_output *lo;
607        struct ld_output_element *oe;
608        struct ld_output_section *os, *_os;
609        int i;
610
611        /*
612         * Layout the input sections that are not listed in the output
613         * section descriptor in the linker script.
614         */
615
616        lo = ld->ld_output;
617        for (i = 1; (size_t) i < li->li_shnum; i++) {
618                is = &li->li_is[i];
619
620                if (!is->is_orphan || is->is_discard)
621                        continue;
622
623                if (strcmp(is->is_name, ".shstrtab") == 0 ||
624                    strcmp(is->is_name, ".symtab") == 0 ||
625                    strcmp(is->is_name, ".strtab") == 0)
626                        continue;
627
628                if ((is->is_type == SHT_REL || is->is_type == SHT_RELA) &&
629                    !ld->ld_emit_reloc)
630                        continue;
631
632                HASH_FIND_STR(lo->lo_ostbl, is->is_name, os);
633                if (os != NULL) {
634                        oe = STAILQ_FIRST(&os->os_e);
635                        assert(oe != NULL &&
636                            oe->oe_type == OET_INPUT_SECTION_LIST);
637                        _insert_input_to_output(lo, os, is, oe->oe_islist);
638                        continue;
639                }
640
641                /*
642                 * Create a new output secton and put it in a proper place,
643                 * based on the section flag.
644                 */
645                _os = ld_layout_insert_output_section(ld, is->is_name,
646                    is->is_flags);
647
648                if ((islist = calloc(1, sizeof(*islist))) == NULL)
649                        ld_fatal_std(ld, "calloc");
650                STAILQ_INIT(islist);
651
652                oe = ld_output_create_element(ld, &_os->os_e,
653                    OET_INPUT_SECTION_LIST, NULL, NULL);
654                oe->oe_islist = islist;
655                _insert_input_to_output(lo, _os, is, oe->oe_islist);
656        }
657}
658
659struct ld_output_section *
660ld_layout_insert_output_section(struct ld *ld, const char *name,
661    uint64_t flags)
662{
663        struct ld_output *lo;
664        struct ld_output_section *os, *_os;
665
666        lo = ld->ld_output;
667        assert(lo != NULL);
668
669        STAILQ_FOREACH(os, &lo->lo_oslist, os_next) {
670                if ((os->os_flags & SHF_ALLOC) != (flags & SHF_ALLOC))
671                        continue;
672
673                if (os->os_flags == flags) {
674                        _os = STAILQ_NEXT(os, os_next);
675                        if (_os == NULL || _os->os_flags != flags)
676                                break;
677                }
678
679                _os = STAILQ_NEXT(os, os_next);
680                if (_os == NULL &&
681                    (_os->os_flags & SHF_ALLOC) != (flags & SHF_ALLOC))
682                        break;
683        }
684
685        _os = ld_output_alloc_section(ld, name, os);
686        _os->os_flags |= flags & SHF_ALLOC;
687
688        return (_os);
689}
690
691static void
692_insert_input_to_output(struct ld_output *lo, struct ld_output_section *os,
693    struct ld_input_section *is, struct ld_input_section_head *islist)
694{
695
696        /*
697         * TODO: Since we now only support "-static" linking, assume all
698         * input relocation sections has been processed and consumed.
699         */
700        if (is->is_type == SHT_REL || is->is_type == SHT_RELA)
701                return;
702
703        is->is_orphan = 0;
704        os->os_empty = 0;
705
706        os->os_flags |= is->is_flags & (SHF_EXECINSTR | SHF_WRITE);
707
708        if (is->is_align > os->os_align)
709                os->os_align = is->is_align;
710
711        if (os->os_type == SHT_NULL)
712                os->os_type = is->is_type;
713        if (is->is_type == SHT_NOTE)
714                lo->lo_phdr_note = 1;
715
716        is->is_output = os;
717        STAILQ_INSERT_TAIL(islist, is, is_next);
718}
719
720static void
721_parse_output_section_descriptor(struct ld *ld, struct ld_output_section *os)
722{
723        struct ld_script_sections_output *ldso;
724
725        if ((ldso = os->os_ldso) == NULL)
726                return;
727
728        if (ldso->ldso_vma != NULL)
729                os->os_addr = ld_exp_eval(ld, ldso->ldso_vma);
730
731        if (ldso->ldso_lma != NULL)
732                os->os_lma = ld_exp_eval(ld, ldso->ldso_lma);
733
734        if (ldso->ldso_align != NULL)
735                os->os_align = ld_exp_eval(ld, ldso->ldso_align);
736
737        /* TODO: handle other output section parameters. */
738}
739
740static void
741_calc_offset(struct ld *ld)
742{
743        struct ld_state *ls;
744        struct ld_output *lo;
745        struct ld_output_element *oe;
746
747        ls = &ld->ld_state;
748        lo = ld->ld_output;
749        ls->ls_loc_counter = 0;
750        ls->ls_offset = ld_layout_calc_header_size(ld);
751
752        STAILQ_FOREACH(oe, &lo->lo_oelist, oe_next) {
753                switch (oe->oe_type) {
754                case OET_ASSERT:
755                        /* TODO */
756                        break;
757                case OET_ASSIGN:
758                        ld_script_process_assign(ld, oe->oe_entry);
759                        break;
760                case OET_ENTRY:
761                        ld_script_process_entry(ld, oe->oe_entry);
762                        break;
763                case OET_OUTPUT_SECTION:
764                        _parse_output_section_descriptor(ld, oe->oe_entry);
765                        _calc_output_section_offset(ld, oe->oe_entry);
766                        break;
767                default:
768                        break;
769                }
770        }
771}
772
773static void
774_calc_output_section_offset(struct ld *ld, struct ld_output_section *os)
775{
776        struct ld_state *ls;
777        struct ld_output_element *oe;
778        struct ld_output_data_buffer *odb;
779        struct ld_input_section *is;
780        struct ld_input_section_head *islist;
781        struct ld_symbol_table *sy;
782        struct ld_strtab *st;
783        uint64_t addr;
784
785        ls = &ld->ld_state;
786
787        /*
788         * Location counter is an offset relative to the start of the
789         * section, when it's refered inside an output section descriptor.
790         */
791        addr = ls->ls_loc_counter;
792        ls->ls_loc_counter = 0;
793
794        STAILQ_FOREACH(oe, &os->os_e, oe_next) {
795                switch (oe->oe_type) {
796                case OET_ASSERT:
797                        /* TODO */
798                        break;
799                case OET_ASSIGN:
800                        ld_script_process_assign(ld, oe->oe_entry);
801                        break;
802                case OET_DATA:
803                        /* TODO */
804                        break;
805                case OET_DATA_BUFFER:
806                        odb = oe->oe_entry;
807                        odb->odb_off = roundup(ls->ls_loc_counter,
808                            odb->odb_align);
809                        ls->ls_loc_counter = odb->odb_off + odb->odb_size;
810                        break;
811                case OET_ENTRY:
812                        ld_script_process_entry(ld, oe->oe_entry);
813                        break;
814                case OET_INPUT_SECTION_LIST:
815                        islist = oe->oe_islist;
816                        STAILQ_FOREACH(is, islist, is_next) {
817                                if (is->is_size == 0)
818                                        continue;
819                                is->is_reloff = roundup(ls->ls_loc_counter,
820                                    is->is_align);
821#if 0
822                                printf("\t%s(%s): %#jx,%#jx(%#jx)\n",
823                                    is->is_input->li_name,
824                                    is->is_name, is->is_reloff,
825                                    is->is_size, is->is_align);
826#endif
827                                ls->ls_loc_counter = is->is_reloff +
828                                    is->is_size;
829                        }
830                        break;
831                case OET_KEYWORD:
832                        /* TODO */
833                        break;
834                case OET_SYMTAB:
835                        assert(ls->ls_loc_counter == 0);
836                        sy = oe->oe_entry;
837                        ls->ls_loc_counter = sy->sy_size * os->os_entsize;
838                        break;
839                case OET_STRTAB:
840                        assert(ls->ls_loc_counter == 0);
841                        st = oe->oe_entry;
842                        ls->ls_loc_counter = st->st_size;
843                        break;
844                default:
845                        break;
846                }
847        }
848
849        /*
850         * Properly align section vma and offset to the required section
851         * alignment.
852         */
853
854        if (os->os_flags & SHF_ALLOC) {
855                if (os->os_ldso == NULL || os->os_ldso->ldso_vma == NULL)
856                        os->os_addr = roundup(addr, os->os_align);
857        } else
858                os->os_addr = 0;
859
860        os->os_off = roundup(ls->ls_offset, os->os_align);
861        os->os_size = ls->ls_loc_counter;
862
863#if 0
864        printf("layout output section %s: (off:%#jx,size:%#jx) "
865            "vma:%#jx,align:%#jx\n", os->os_name, os->os_off, os->os_size,
866            os->os_addr, os->os_align);
867#endif
868
869        ls->ls_offset = os->os_off + os->os_size;
870
871        /* Reset location counter to the current VMA. */
872        if (os->os_flags & SHF_ALLOC)
873                ls->ls_loc_counter = os->os_addr + os->os_size;
874}
875
876static void
877_create_interp(struct ld *ld)
878{
879        struct ld_output *lo;
880        struct ld_output_section *os;
881        struct ld_output_data_buffer *odb;
882        const char *interp;
883        char interp_name[] = ".interp";
884
885        lo = ld->ld_output;
886        assert(lo != NULL);
887
888        HASH_FIND_STR(lo->lo_ostbl, interp_name, os);
889        if (os == NULL)
890                os = ld_layout_insert_output_section(ld, interp_name,
891                    SHF_ALLOC);
892        os->os_type = SHT_PROGBITS;
893        os->os_align = 1;
894        os->os_entsize = 0;
895        os->os_flags = SHF_ALLOC;
896
897        if (ld->ld_interp != NULL)
898                interp = ld->ld_interp;
899        else
900                interp = ld->ld_arch->interp;
901        assert(interp != NULL);
902
903        if ((odb = calloc(1, sizeof(*odb))) == NULL)
904                ld_fatal_std(ld, "calloc");
905        odb->odb_size = strlen(interp) + 1;
906        odb->odb_align = 1;
907        odb->odb_type = ELF_T_BYTE;
908
909        if ((odb->odb_buf = calloc(odb->odb_size, 1)) == NULL)
910                ld_fatal_std(ld, "calloc");
911        strncpy(odb->odb_buf, interp, strlen(interp));
912        odb->odb_buf[strlen(interp)] = '\0';
913       
914        (void) ld_output_create_element(ld, &os->os_e, OET_DATA_BUFFER, odb,
915            NULL);
916        lo->lo_interp = os;
917}
918
919static void
920_create_dynamic(struct ld *ld)
921{
922        struct ld_output *lo;
923        struct ld_output_section *os, *_os;
924        struct ld_output_data_buffer *odb;
925        char dynamic_name[] = ".dynamic";
926        char init_name[] = ".init";
927        char fini_name[] = ".fini";
928        int entries;
929
930        lo = ld->ld_output;
931        assert(lo != NULL);
932
933        HASH_FIND_STR(lo->lo_ostbl, dynamic_name, os);
934        if (os == NULL)
935                os = ld_layout_insert_output_section(ld, dynamic_name,
936                    SHF_ALLOC | SHF_WRITE);
937        os->os_type = SHT_PROGBITS;
938        os->os_flags = SHF_ALLOC | SHF_WRITE;
939        if (lo->lo_ec == ELFCLASS32) {
940                os->os_entsize = 8;
941                os->os_align = 4;
942        } else {
943                os->os_entsize = 16;
944                os->os_align = 8;
945        }
946
947        entries = lo->lo_dso_needed;
948
949        /* DT_INIT */
950        HASH_FIND_STR(lo->lo_ostbl, init_name, _os);
951        if (_os != NULL && !os->os_empty)
952                entries++;
953
954        /* DT_FINI */
955        HASH_FIND_STR(lo->lo_ostbl, fini_name, _os);
956        if (_os != NULL && !os->os_empty)
957                entries++;
958
959        /* DT_HASH, DT_STRTAB, DT_SYMTAB, DT_STRSZ and DT_SYMENT */
960        if (HASH_CNT(hhimp, ld->ld_symtab_import) > 0 ||
961            HASH_CNT(hhexp, ld->ld_symtab_export) > 0)
962                entries += 5;
963
964        /* TODO: DT_RPATH. */
965
966        /*
967         * DT_DEBUG. dynamic linker changes this at runtime, gdb uses
968         * it to find all the loaded DSOs. (thus .dynamic has to be
969         * writable)
970         */
971        entries++;
972
973        /* DT_PLTGOT, DT_PLTRELSZ, DT_PLTREL and DT_JMPREL. */
974        if (ld->ld_os_plt)
975                entries += 4;
976
977        /*
978         * TODO: DT_VERNEED, DT_VERNEEDNUM, DT_VERDEF, DT_VERDEFNUM and
979         * DT_VERSYM.
980         */
981
982        /* DT_NULL. TODO: Reserve multiple DT_NULL entries for DT_RPATH? */
983        entries++;
984
985        /*
986         * Reserve space for .dynamic section, based on number of entries.
987         */
988        if ((odb = calloc(1, sizeof(*odb))) == NULL)
989                ld_fatal_std(ld, "calloc");
990        odb->odb_size = entries * os->os_entsize;
991        odb->odb_align = os->os_align;
992        odb->odb_type = ELF_T_BYTE;
993
994        /* Create _DYNAMIC symobl. */
995        ld_symbols_add_internal(ld, "_DYNAMIC", 0, 0, SHN_ABS, STB_LOCAL,
996            STT_OBJECT, STV_HIDDEN, os);
997}
998
999static void
1000_create_dynsym_and_dynstr(struct ld *ld)
1001{
1002        struct ld_output *lo;
1003        struct ld_output_section *os;
1004        char dynsym_name[] = ".dynsym";
1005        char dynstr_name[] = ".dynstr";
1006
1007        lo = ld->ld_output;
1008        assert(lo != NULL);
1009
1010        /*
1011         * Create .dynsym section.
1012         */
1013
1014        HASH_FIND_STR(lo->lo_ostbl, dynsym_name, os);
1015        if (os == NULL)
1016                os = ld_layout_insert_output_section(ld, dynsym_name,
1017                    SHF_ALLOC);
1018        os->os_type = SHT_DYNSYM;
1019        os->os_flags = SHF_ALLOC;
1020        if (lo->lo_ec == ELFCLASS32) {
1021                os->os_entsize = sizeof(Elf32_Sym);
1022                os->os_align = 4;
1023        } else {
1024                os->os_entsize = sizeof(Elf64_Sym);
1025                os->os_align = 8;
1026        }
1027
1028        (void) ld_output_create_element(ld, &os->os_e, OET_SYMTAB,
1029            ld->ld_dynsym, NULL);
1030
1031        /*
1032         * Create .dynstr section.
1033         */
1034
1035        HASH_FIND_STR(lo->lo_ostbl, dynstr_name, os);
1036        if (os == NULL)
1037                os = ld_layout_insert_output_section(ld, dynstr_name,
1038                    SHF_ALLOC);
1039        os->os_type = SHT_STRTAB;
1040        os->os_flags = SHF_ALLOC;
1041        os->os_entsize = 0;
1042        os->os_align = 1;
1043
1044        (void) ld_output_create_element(ld, &os->os_e, OET_STRTAB,
1045            ld->ld_dynstr, NULL);
1046}
Note: See TracBrowser for help on using the browser.