root/trunk/ld/ld_dynamic.c @ 2927

Revision 2927, 15.2 KB (checked in by kaiwang27, 13 months ago)

Set the type of the ".dynamic" output section to SHT_DYNAMIC.

  • Property svn:keywords set to Id
Line 
1/*-
2 * Copyright (c) 2012,2013 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_dynamic.h"
30#include "ld_file.h"
31#include "ld_hash.h"
32#include "ld_input.h"
33#include "ld_layout.h"
34#include "ld_output.h"
35#include "ld_path.h"
36#include "ld_symbols.h"
37#include "ld_symver.h"
38#include "ld_strtab.h"
39
40ELFTC_VCSID("$Id$");
41
42static void _check_dso_needed(struct ld *ld, struct ld_output *lo);
43static void _create_dynamic(struct ld *ld, struct ld_output *lo);
44static void _create_interp(struct ld *ld, struct ld_output *lo);
45static void _create_dynsym_and_dynstr_section(struct ld *ld,
46    struct ld_output *lo);
47static void _finalize_dynamic(struct ld *ld, struct ld_output *lo);
48
49void
50ld_dynamic_create(struct ld *ld)
51{
52        struct ld_output *lo;
53
54        lo = ld->ld_output;
55        assert(lo != NULL);
56
57        /* Check how many DSOs is needed for output object. */
58        _check_dso_needed(ld, lo);
59
60        /* Link statically if we don't use DSOs? */
61        if (lo->lo_dso_needed == 0)
62                return;
63
64        ld->ld_dynamic_link = 1;
65
66        /* Create .interp section. */
67        if (!ld->ld_dso)
68                _create_interp(ld, lo);
69
70        /* Create .dynamic section. */
71        _create_dynamic(ld, lo);
72
73        /* Create .dynsym and .dynstr sections. */
74        _create_dynsym_and_dynstr_section(ld, lo);
75
76        /* Create .hash section. */
77        ld_hash_create_svr4_hash_section(ld);
78
79        /*
80         * Create .gnu.version_d section if the linker creats a shared
81         * library and version script is provided.
82         */
83        lo->lo_version_index = 2;
84        if (ld->ld_dso)
85                ld_symver_create_verdef_section(ld);
86
87        /* Create .gnu.version_r section. */
88        ld_symver_create_verneed_section(ld);
89
90        /* Create .gnu.version section. */
91        ld_symver_create_versym_section(ld);
92}
93
94void
95ld_dynamic_finalize(struct ld *ld)
96{
97        struct ld_output *lo;
98
99        lo = ld->ld_output;
100        assert(lo != NULL);
101
102        if (lo->lo_dso_needed == 0)
103                return;
104
105        /* Finalize .dynamic section */
106        _finalize_dynamic(ld, lo);
107}
108
109void
110ld_dynamic_load_dso_dynamic(struct ld *ld, struct ld_input *li, Elf *e,
111    Elf_Scn *scn, size_t strndx)
112{
113        GElf_Shdr shdr;
114        GElf_Dyn dyn;
115        Elf_Data *d;
116        int elferr, i, len;
117        const char *name;
118
119        if (strndx == SHN_UNDEF)
120                return;
121
122        if (gelf_getshdr(scn, &shdr) != &shdr) {
123                ld_warn(ld, "%s: gelf_getshdr failed: %s", li->li_name,
124                    elf_errmsg(-1));
125                return;
126        }
127
128        (void) elf_errno();
129        if ((d = elf_getdata(scn, NULL)) == NULL) {
130                elferr = elf_errno();
131                if (elferr != 0)
132                        ld_warn(ld, "%s: elf_getdata failed: %s", li->li_name,
133                            elf_errmsg(elferr));
134                return;
135        }
136
137        len = d->d_size / shdr.sh_entsize;
138        for (i = 0; i < len; i++) {
139                if (gelf_getdyn(d, i, &dyn) != &dyn) {
140                        ld_warn(ld, "%s: gelf_getdyn failed: %s", li->li_name,
141                            elf_errmsg(-1));
142                        continue;
143                }
144                if (dyn.d_tag == DT_SONAME) {
145                        name = elf_strptr(e, strndx, dyn.d_un.d_ptr);
146                        if (name != NULL &&
147                            (li->li_soname = strdup(name)) == NULL)
148                                ld_fatal_std(ld, "strdup");
149                        break;
150                }
151        }
152}
153
154void
155ld_dynamic_reserve_dynbss_entry(struct ld *ld, struct ld_symbol *lsb)
156{
157        struct ld_input *li;
158        struct ld_input_section *dynbss, *is;
159        uint64_t a;
160
161        /* Create .dynbss section if it doesn't yet exist. */
162        dynbss = ld_input_find_internal_section(ld, ".dynbss");
163        if (dynbss == NULL) {
164                dynbss = ld_input_add_internal_section(ld, ".dynbss");
165                dynbss->is_type = SHT_NOBITS;
166        }
167
168        li = lsb->lsb_input;
169        assert(li != NULL && li->li_type == LIT_DSO);
170
171        /*
172         * TODO: we don't have to create copy relocation
173         * for every import object. Some import objects
174         * are read-only, in that case we can create other
175         * dynamic relocations for them.
176         */
177
178        /*
179         * If the section to which the symbols belong has a larger
180         * alignment requirement, we increase .dynbss section alignment
181         * accordingly. XXX What if it is a DSO common symbol?
182         */
183        is = NULL;
184        if (lsb->lsb_shndx != SHN_COMMON) {
185                assert(lsb->lsb_shndx < li->li_shnum - 1);
186                is = &li->li_is[lsb->lsb_shndx];
187                if (is->is_align > dynbss->is_align)
188                        dynbss->is_align = is->is_align;
189        }
190
191        /*
192         * Calculate the alignment for this object.
193         */
194        if (is != NULL) {
195                for (a = is->is_align; a > 1; a >>= 1) {
196                        if ((lsb->lsb_value - is->is_off) % a == 0)
197                                break;
198                }
199        } else
200                a = 1;
201
202        if (a > 1)
203                dynbss->is_size = roundup(dynbss->is_size, a);
204
205        lsb->lsb_value = dynbss->is_size;
206        lsb->lsb_copy_reloc = 1;
207        lsb->lsb_input = dynbss->is_input;
208        lsb->lsb_shndx = dynbss->is_index;
209        lsb->lsb_is = dynbss;
210
211        dynbss->is_size += lsb->lsb_size;
212}
213
214static void
215_create_interp(struct ld *ld, struct ld_output *lo)
216{
217        struct ld_output_section *os;
218        struct ld_output_data_buffer *odb;
219        const char *interp;
220        char interp_name[] = ".interp";
221
222        HASH_FIND_STR(lo->lo_ostbl, interp_name, os);
223        if (os == NULL)
224                os = ld_layout_insert_output_section(ld, interp_name,
225                    SHF_ALLOC);
226        os->os_type = SHT_PROGBITS;
227        os->os_align = 1;
228        os->os_entsize = 0;
229        os->os_flags = SHF_ALLOC;
230
231        lo->lo_interp = os;
232
233        if (ld->ld_interp != NULL)
234                interp = ld->ld_interp;
235        else
236                interp = ld->ld_arch->interp;
237        assert(interp != NULL);
238
239        if ((odb = calloc(1, sizeof(*odb))) == NULL)
240                ld_fatal_std(ld, "calloc");
241        odb->odb_size = strlen(interp) + 1;
242        odb->odb_align = 1;
243        odb->odb_type = ELF_T_BYTE;
244
245        if ((odb->odb_buf = calloc(odb->odb_size, 1)) == NULL)
246                ld_fatal_std(ld, "calloc");
247        strncpy(odb->odb_buf, interp, strlen(interp));
248        odb->odb_buf[strlen(interp)] = '\0';
249
250        (void) ld_output_create_section_element(ld, os, OET_DATA_BUFFER, odb,
251            NULL);
252}
253
254static void
255_create_dynamic(struct ld *ld, struct ld_output *lo)
256{
257        struct ld_output_section *os, *_os;
258        struct ld_output_data_buffer *odb;
259        char dynamic_name[] = ".dynamic";
260        char init_name[] = ".init";
261        char fini_name[] = ".fini";
262        char *rpath;
263        int entries;
264
265        HASH_FIND_STR(lo->lo_ostbl, dynamic_name, os);
266        if (os == NULL)
267                os = ld_layout_insert_output_section(ld, dynamic_name,
268                    SHF_ALLOC | SHF_WRITE);
269        os->os_type = SHT_DYNAMIC;
270        os->os_flags = SHF_ALLOC | SHF_WRITE;
271        if (lo->lo_ec == ELFCLASS32) {
272                os->os_entsize = 8;
273                os->os_align = 4;
274        } else {
275                os->os_entsize = 16;
276                os->os_align = 8;
277        }
278
279        lo->lo_dynamic = os;
280
281        /* .dynamic section should link to .dynstr section. */
282        if ((os->os_link = strdup(".dynstr")) == NULL)
283                ld_fatal_std(ld, "strdup");
284
285        /* DT_NEEDED */
286        entries = lo->lo_dso_needed;
287
288        /* DT_SONAME. */
289        if (ld->ld_soname != NULL) {
290                lo->lo_soname_nameindex = ld_strtab_insert_no_suffix(ld,
291                    ld->ld_dynstr, ld->ld_soname);
292                entries++;
293        }
294
295        /* DT_INIT */
296        HASH_FIND_STR(lo->lo_ostbl, init_name, _os);
297        if (_os != NULL && !_os->os_empty) {
298                lo->lo_init = _os;
299                entries++;
300        }
301
302        /* DT_FINI */
303        HASH_FIND_STR(lo->lo_ostbl, fini_name, _os);
304        if (_os != NULL && !_os->os_empty) {
305                lo->lo_fini = _os;
306                entries++;
307        }
308
309        /* DT_HASH, DT_STRTAB, DT_SYMTAB, DT_STRSZ and DT_SYMENT */
310        if (ld->ld_dynsym)
311                entries += 5;
312
313        /* DT_RPATH. */
314        if (!STAILQ_EMPTY(&ld->ld_state.ls_rplist)) {
315                rpath = ld_path_join_rpath(ld);
316                lo->lo_rpath_nameindex = ld_strtab_insert_no_suffix(ld,
317                    ld->ld_dynstr, rpath);
318                entries++;
319        }
320
321        /*
322         * DT_DEBUG. dynamic linker changes this at runtime, gdb uses
323         * it to find all the loaded DSOs. (thus .dynamic has to be
324         * writable)
325         */
326        if (!ld->ld_dso)
327                entries++;
328
329        /* DT_PLTGOT, DT_PLTRELSZ, DT_PLTREL and DT_JMPREL. */
330        entries += 4;
331
332        /* DT_REL/DT_RELA, DT_RELSZ/DT_RELASZ and DT_RELENT/DT_RELAENT */
333        entries += 3;
334
335        /*
336         * DT_VERNEED, DT_VERNEEDNUM, DT_VERDEF, DT_VERDEFNUM and DT_VERSYM.
337         */
338        entries += 5;
339
340        /* DT_RELCOUNT/DT_RELACOUNT. */
341        if (ld->ld_state.ls_relative_reloc > 0)
342                entries++;
343
344        /* DT_NULL. TODO: Reserve multiple DT_NULL entries for DT_RPATH? */
345        entries++;
346
347        /*
348         * Reserve space for .dynamic section, based on number of entries.
349         */
350        if ((odb = calloc(1, sizeof(*odb))) == NULL)
351                ld_fatal_std(ld, "calloc");
352        odb->odb_size = entries * os->os_entsize;
353        if ((odb->odb_buf = malloc(odb->odb_size)) == NULL)
354                ld_fatal_std(ld, "malloc");
355        odb->odb_align = os->os_align;
356        odb->odb_type = ELF_T_DYN;
357
358        (void) ld_output_create_section_element(ld, os, OET_DATA_BUFFER, odb,
359            NULL);
360
361        lo->lo_dynamic_odb = odb;
362
363        /* Create _DYNAMIC symobl. */
364        ld_symbols_add_internal(ld, "_DYNAMIC", 0, 0, SHN_ABS, STB_LOCAL,
365            STT_OBJECT, STV_HIDDEN, NULL, os);
366}
367
368#define DT_ENTRY_VAL(tag,val)                                   \
369        do {                                                    \
370                if (lo->lo_ec == ELFCLASS32) {                  \
371                        assert(dt32 < end32);                   \
372                        dt32->d_tag = (int32_t) (tag);          \
373                        dt32->d_un.d_val = (uint32_t) (val);    \
374                        dt32++;                                 \
375                } else {                                        \
376                        assert(dt64 < end64);                   \
377                        dt64->d_tag = (tag);                    \
378                        dt64->d_un.d_val = (val);               \
379                        dt64++;                                 \
380                }                                               \
381        } while(0)
382
383#define DT_ENTRY_PTR(tag,ptr)                                   \
384        do {                                                    \
385                if (lo->lo_ec == ELFCLASS32) {                  \
386                        assert(dt32 < end32);                   \
387                        dt32->d_tag = (int32_t) (tag);          \
388                        dt32->d_un.d_ptr = (uint32_t) (ptr);    \
389                        dt32++;                                 \
390                } else {                                        \
391                        assert(dt64 < end64);                   \
392                        dt64->d_tag = (tag);                    \
393                        dt64->d_un.d_ptr = (ptr);               \
394                        dt64++;                                 \
395                }                                               \
396        } while(0)
397
398#define DT_ENTRY_NULL                                           \
399        do {                                                    \
400                if (lo->lo_ec == ELFCLASS32) {                  \
401                        assert(dt32 < end32);                   \
402                        while (dt32 < end32)                    \
403                                DT_ENTRY_VAL(DT_NULL, 0);       \
404                        assert(dt32 == end32);                  \
405                } else {                                        \
406                        assert(dt64 < end64);                   \
407                        while (dt64 < end64)                    \
408                                DT_ENTRY_VAL(DT_NULL, 0);       \
409                        assert(dt64 == end64);                  \
410                }                                               \
411        } while(0)
412
413static void
414_finalize_dynamic(struct ld *ld, struct ld_output *lo)
415{
416        struct ld_output_data_buffer *odb;
417        Elf32_Dyn *dt32, *end32;
418        Elf64_Dyn *dt64, *end64;
419        int *p;
420
421        odb = lo->lo_dynamic_odb;
422        assert(odb != NULL);
423
424        dt32 = (Elf32_Dyn *) (uintptr_t) odb->odb_buf;
425        dt64 = (Elf64_Dyn *) (uintptr_t) odb->odb_buf;
426        end32 = (Elf32_Dyn *) (uintptr_t) (odb->odb_buf + odb->odb_size);
427        end64 = (Elf64_Dyn *) (uintptr_t) (odb->odb_buf + odb->odb_size);
428
429        /* DT_NEEDED. */
430        for (p = (int *) (uintptr_t) utarray_front(lo->lo_dso_nameindex);
431             p != NULL;
432             p = (int *) (uintptr_t) utarray_next(lo->lo_dso_nameindex, p))
433                DT_ENTRY_VAL(DT_NEEDED, *p);
434
435        /* DT_SONAME. */
436        if (ld->ld_soname != NULL)
437                DT_ENTRY_VAL(DT_SONAME, lo->lo_soname_nameindex);
438
439        /* DT_INIT and DT_FINI */
440        if (lo->lo_init != NULL)
441                DT_ENTRY_PTR(DT_INIT, lo->lo_init->os_addr);
442        if (lo->lo_fini != NULL)
443                DT_ENTRY_PTR(DT_FINI, lo->lo_fini->os_addr);
444
445        /* DT_HASH */
446        if (lo->lo_hash != NULL)
447                DT_ENTRY_PTR(DT_HASH, lo->lo_hash->os_addr);
448
449        /* DT_HASH, DT_STRTAB, DT_SYMTAB, DT_STRSZ and DT_SYMENT */
450        if (lo->lo_dynsym != NULL && lo->lo_dynstr != NULL) {
451                DT_ENTRY_PTR(DT_STRTAB, lo->lo_dynstr->os_addr);
452                DT_ENTRY_PTR(DT_SYMTAB, lo->lo_dynsym->os_addr);
453                DT_ENTRY_VAL(DT_STRSZ, ld->ld_dynstr->st_size);
454                DT_ENTRY_VAL(DT_SYMENT,
455                    lo->lo_ec == ELFCLASS32 ? sizeof(Elf32_Sym) :
456                    sizeof(Elf64_Sym));
457        }
458
459        /* DT_RPATH */
460        if (!STAILQ_EMPTY(&ld->ld_state.ls_rplist))
461                DT_ENTRY_VAL(DT_RPATH, lo->lo_rpath_nameindex);
462
463        /* DT_DEBUG */
464        if (!ld->ld_dso)
465                DT_ENTRY_VAL(DT_DEBUG, 0);
466
467        /* DT_PLTGOT, DT_PLTRELSZ, DT_PLTREL and DT_JMPREL. */
468        if (lo->lo_gotplt != NULL)
469                DT_ENTRY_PTR(DT_PLTGOT, lo->lo_gotplt->os_addr);
470        if (lo->lo_rel_plt != NULL) {
471                DT_ENTRY_VAL(DT_PLTRELSZ, lo->lo_rel_plt->os_size);
472                DT_ENTRY_VAL(DT_PLTREL,
473                    ld->ld_arch->reloc_is_rela ? DT_RELA : DT_REL);
474                DT_ENTRY_PTR(DT_JMPREL, lo->lo_rel_plt->os_addr);
475        }
476
477        /* DT_REL/DT_RELA, DT_RELSZ/DT_RELASZ and DT_RELENT/DT_RELAENT */
478        if (lo->lo_rel_dyn != NULL) {
479                if (!ld->ld_arch->reloc_is_rela) {
480                        DT_ENTRY_PTR(DT_REL, lo->lo_rel_dyn->os_addr);
481                        DT_ENTRY_VAL(DT_RELSZ, lo->lo_rel_dyn->os_size);
482                        DT_ENTRY_VAL(DT_RELENT, ld->ld_arch->reloc_entsize);
483                } else {
484                        DT_ENTRY_PTR(DT_RELA, lo->lo_rel_dyn->os_addr);
485                        DT_ENTRY_VAL(DT_RELASZ, lo->lo_rel_dyn->os_size);
486                        DT_ENTRY_VAL(DT_RELAENT, ld->ld_arch->reloc_entsize);
487                }
488        }
489
490        /*
491         * DT_VERNEED, DT_VERNEEDNUM, DT_VERDEF, DT_VERDEFNUM and
492         * DT_VERSYM.
493         */
494        if (lo->lo_verdef != NULL) {
495                DT_ENTRY_PTR(DT_VERDEF, lo->lo_verdef->os_addr);
496                DT_ENTRY_VAL(DT_VERDEFNUM, lo->lo_verdef_num);
497        }
498        if (lo->lo_verneed != NULL) {
499                DT_ENTRY_PTR(DT_VERNEED, lo->lo_verneed->os_addr);
500                DT_ENTRY_VAL(DT_VERNEEDNUM, lo->lo_verneed_num);
501        }
502        if (lo->lo_versym != NULL)
503                DT_ENTRY_PTR(DT_VERSYM, lo->lo_versym->os_addr);
504
505        /* DT_RELCOUNT/DT_RELACOUNT. */
506        if (ld->ld_state.ls_relative_reloc > 0)
507                DT_ENTRY_VAL(ld->ld_arch->reloc_is_rela ? DT_RELACOUNT :
508                    DT_RELCOUNT, ld->ld_state.ls_relative_reloc);
509
510        /* Fill in the space left with DT_NULL entries */
511        DT_ENTRY_NULL;
512}
513
514static void
515_create_dynsym_and_dynstr_section(struct ld *ld, struct ld_output *lo)
516{
517        struct ld_output_section *os;
518        char dynsym_name[] = ".dynsym";
519        char dynstr_name[] = ".dynstr";
520
521        /*
522         * Create .dynsym section.
523         */
524
525        HASH_FIND_STR(lo->lo_ostbl, dynsym_name, os);
526        if (os == NULL)
527                os = ld_layout_insert_output_section(ld, dynsym_name,
528                    SHF_ALLOC);
529        os->os_type = SHT_DYNSYM;
530        os->os_flags = SHF_ALLOC;
531        if (lo->lo_ec == ELFCLASS32) {
532                os->os_entsize = sizeof(Elf32_Sym);
533                os->os_align = 4;
534        } else {
535                os->os_entsize = sizeof(Elf64_Sym);
536                os->os_align = 8;
537        }
538        lo->lo_dynsym = os;
539
540        (void) ld_output_create_section_element(ld, os, OET_SYMTAB,
541            ld->ld_dynsym, NULL);
542
543        /*
544         * Create .dynstr section.
545         */
546
547        HASH_FIND_STR(lo->lo_ostbl, dynstr_name, os);
548        if (os == NULL)
549                os = ld_layout_insert_output_section(ld, dynstr_name,
550                    SHF_ALLOC);
551        os->os_type = SHT_STRTAB;
552        os->os_flags = SHF_ALLOC;
553        os->os_entsize = 0;
554        os->os_align = 1;
555        lo->lo_dynstr = os;
556
557        (void) ld_output_create_section_element(ld, os, OET_STRTAB,
558            ld->ld_dynstr, NULL);
559
560        if ((lo->lo_dynsym->os_link = strdup(".dynstr")) == NULL)
561                ld_fatal_std(ld, "strdup");
562}
563
564static void
565_check_dso_needed(struct ld *ld, struct ld_output *lo)
566{
567        struct ld_input *li;
568        const char *bn;
569        int ndx;
570
571        lo->lo_dso_needed = 0;
572
573        STAILQ_FOREACH(li, &ld->ld_lilist, li_next) {
574                if (li->li_type != LIT_DSO)
575                        continue;
576
577                if (li->li_dso_refcnt > 0 || !li->li_file->lf_as_needed) {
578                        lo->lo_dso_needed++;
579
580                        if (ld->ld_dynstr == NULL)
581                                ld->ld_dynstr = ld_strtab_alloc(ld);
582
583                        /* Insert DSO name to the .dynstr string table. */
584                        if (li->li_soname != NULL)
585                                bn = li->li_soname;
586                        else {
587                                if ((bn = strrchr(li->li_name, '/')) == NULL)
588                                        bn = li->li_name;
589                                else
590                                        bn++;
591                        }
592                        ndx = ld_strtab_insert_no_suffix(ld, ld->ld_dynstr,
593                            bn);
594
595                        /* Save the generated name index for later use. */
596                        if (lo->lo_dso_nameindex == NULL)
597                                utarray_new(lo->lo_dso_nameindex, &ut_int_icd);
598                        utarray_push_back(lo->lo_dso_nameindex, &ndx);
599                }
600        }
601}
Note: See TracBrowser for help on using the browser.