]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - sys/kern/link_elf_obj.c
This commit was generated by cvs2svn to compensate for changes in r160814,
[FreeBSD/FreeBSD.git] / sys / kern / link_elf_obj.c
1 /*-
2  * Copyright (c) 1998-2000 Doug Rabson
3  * Copyright (c) 2004 Peter Wemm
4  * All rights reserved.
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions
8  * are met:
9  * 1. Redistributions of source code must retain the above copyright
10  *    notice, this list of conditions and the following disclaimer.
11  * 2. Redistributions in binary form must reproduce the above copyright
12  *    notice, this list of conditions and the following disclaimer in the
13  *    documentation and/or other materials provided with the distribution.
14  *
15  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
16  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
19  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25  * SUCH DAMAGE.
26  */
27
28 #include <sys/cdefs.h>
29 __FBSDID("$FreeBSD$");
30
31 #include "opt_ddb.h"
32 #include "opt_mac.h"
33
34 #include <sys/param.h>
35 #include <sys/systm.h>
36 #include <sys/kernel.h>
37 #include <sys/lock.h>
38 #include <sys/mac.h>
39 #include <sys/malloc.h>
40 #include <sys/mutex.h>
41 #include <sys/mount.h>
42 #include <sys/proc.h>
43 #include <sys/namei.h>
44 #include <sys/fcntl.h>
45 #include <sys/vnode.h>
46 #include <sys/linker.h>
47
48 #include <machine/elf.h>
49
50 #include <vm/vm.h>
51 #include <vm/vm_param.h>
52 #include <vm/vm_object.h>
53 #include <vm/vm_kern.h>
54 #include <vm/vm_extern.h>
55 #include <vm/pmap.h>
56 #include <vm/vm_map.h>
57
58 #include <sys/link_elf.h>
59
60 #include "linker_if.h"
61
62 typedef struct {
63         void            *addr;
64         Elf_Off         size;
65         int             flags;
66         int             sec;    /* Original section */
67         char            *name;
68 } Elf_progent;
69
70 typedef struct {
71         Elf_Rel         *rel;
72         int             nrel;
73         int             sec;
74 } Elf_relent;
75
76 typedef struct {
77         Elf_Rela        *rela;
78         int             nrela;
79         int             sec;
80 } Elf_relaent;
81
82
83 typedef struct elf_file {
84         struct linker_file lf;          /* Common fields */
85
86         int             preloaded;
87         caddr_t         address;        /* Relocation address */
88         vm_object_t     object;         /* VM object to hold file pages */
89         Elf_Shdr        *e_shdr;
90
91         Elf_progent     *progtab;
92         int             nprogtab;
93
94         Elf_relaent     *relatab;
95         int             nrela;
96
97         Elf_relent      *reltab;
98         int             nrel;
99
100         Elf_Sym         *ddbsymtab;     /* The symbol table we are using */
101         long            ddbsymcnt;      /* Number of symbols */
102         caddr_t         ddbstrtab;      /* String table */
103         long            ddbstrcnt;      /* number of bytes in string table */
104
105         caddr_t         shstrtab;       /* Section name string table */
106         long            shstrcnt;       /* number of bytes in string table */
107
108 } *elf_file_t;
109
110 static int      link_elf_link_preload(linker_class_t cls,
111                     const char *, linker_file_t *);
112 static int      link_elf_link_preload_finish(linker_file_t);
113 static int      link_elf_load_file(linker_class_t, const char *, linker_file_t *);
114 static int      link_elf_lookup_symbol(linker_file_t, const char *,
115                     c_linker_sym_t *);
116 static int      link_elf_symbol_values(linker_file_t, c_linker_sym_t,
117                     linker_symval_t *);
118 static int      link_elf_search_symbol(linker_file_t, caddr_t value,
119                     c_linker_sym_t *sym, long *diffp);
120
121 static void     link_elf_unload_file(linker_file_t);
122 static int      link_elf_lookup_set(linker_file_t, const char *,
123                     void ***, void ***, int *);
124 static int      link_elf_each_function_name(linker_file_t,
125                     int (*)(const char *, void *), void *);
126 static void     link_elf_reloc_local(linker_file_t);
127
128 static Elf_Addr elf_obj_lookup(linker_file_t lf, Elf_Size symidx, int deps);
129
130 static kobj_method_t link_elf_methods[] = {
131         KOBJMETHOD(linker_lookup_symbol,        link_elf_lookup_symbol),
132         KOBJMETHOD(linker_symbol_values,        link_elf_symbol_values),
133         KOBJMETHOD(linker_search_symbol,        link_elf_search_symbol),
134         KOBJMETHOD(linker_unload,               link_elf_unload_file),
135         KOBJMETHOD(linker_load_file,            link_elf_load_file),
136         KOBJMETHOD(linker_link_preload,         link_elf_link_preload),
137         KOBJMETHOD(linker_link_preload_finish,  link_elf_link_preload_finish),
138         KOBJMETHOD(linker_lookup_set,           link_elf_lookup_set),
139         KOBJMETHOD(linker_each_function_name,   link_elf_each_function_name),
140         { 0, 0 }
141 };
142
143 static struct linker_class link_elf_class = {
144 #if ELF_TARG_CLASS == ELFCLASS32
145         "elf32_obj",
146 #else
147         "elf64_obj",
148 #endif
149         link_elf_methods, sizeof(struct elf_file)
150 };
151
152 static int      relocate_file(elf_file_t ef);
153
154 static void
155 link_elf_error(const char *s)
156 {
157         printf("kldload: %s\n", s);
158 }
159
160 static void
161 link_elf_init(void *arg)
162 {
163
164         linker_add_class(&link_elf_class);
165 }
166
167 SYSINIT(link_elf_obj, SI_SUB_KLD, SI_ORDER_SECOND, link_elf_init, 0);
168
169 static int
170 link_elf_link_preload(linker_class_t cls, const char *filename,
171     linker_file_t *result)
172 {
173         Elf_Ehdr *hdr;
174         Elf_Shdr *shdr;
175         Elf_Sym *es;
176         void *modptr, *baseptr, *sizeptr;
177         char *type;
178         elf_file_t ef;
179         linker_file_t lf;
180         Elf_Addr off;
181         int error, i, j, pb, ra, rl, shstrindex, symstrindex, symtabindex;
182
183         /* Look to see if we have the file preloaded */
184         modptr = preload_search_by_name(filename);
185         if (modptr == NULL)
186                 return ENOENT;
187
188         type = (char *)preload_search_info(modptr, MODINFO_TYPE);
189         baseptr = preload_search_info(modptr, MODINFO_ADDR);
190         sizeptr = preload_search_info(modptr, MODINFO_SIZE);
191         hdr = (Elf_Ehdr *)preload_search_info(modptr, MODINFO_METADATA |
192             MODINFOMD_ELFHDR);
193         shdr = (Elf_Shdr *)preload_search_info(modptr, MODINFO_METADATA |
194             MODINFOMD_SHDR);
195         if (type == NULL || (strcmp(type, "elf" __XSTRING(__ELF_WORD_SIZE)
196             " obj module") != 0 &&
197             strcmp(type, "elf obj module") != 0)) {
198                 return (EFTYPE);
199         }
200         if (baseptr == NULL || sizeptr == NULL || hdr == NULL ||
201             shdr == NULL)
202                 return (EINVAL);
203
204         lf = linker_make_file(filename, &link_elf_class);
205         if (lf == NULL)
206                 return (ENOMEM);
207
208         ef = (elf_file_t)lf;
209         ef->preloaded = 1;
210         ef->address = *(caddr_t *)baseptr;
211         lf->address = *(caddr_t *)baseptr;
212         lf->size = *(size_t *)sizeptr;
213
214         if (hdr->e_ident[EI_CLASS] != ELF_TARG_CLASS ||
215             hdr->e_ident[EI_DATA] != ELF_TARG_DATA ||
216             hdr->e_ident[EI_VERSION] != EV_CURRENT ||
217             hdr->e_version != EV_CURRENT ||
218             hdr->e_type != ET_REL ||
219             hdr->e_machine != ELF_TARG_MACH) {
220                 error = EFTYPE;
221                 goto out;
222         }
223         ef->e_shdr = shdr;
224
225         /* Scan the section header for information and table sizing. */
226         symtabindex = -1;
227         symstrindex = -1;
228         for (i = 0; i < hdr->e_shnum; i++) {
229                 switch (shdr[i].sh_type) {
230                 case SHT_PROGBITS:
231                 case SHT_NOBITS:
232                         ef->nprogtab++;
233                         break;
234                 case SHT_SYMTAB:
235                         symtabindex = i;
236                         symstrindex = shdr[i].sh_link;
237                         break;
238                 case SHT_REL:
239                         ef->nrel++;
240                         break;
241                 case SHT_RELA:
242                         ef->nrela++;
243                         break;
244                 }
245         }
246
247         shstrindex = hdr->e_shstrndx;
248         if (ef->nprogtab == 0 || symstrindex < 0 ||
249             symstrindex >= hdr->e_shnum ||
250             shdr[symstrindex].sh_type != SHT_STRTAB || shstrindex == 0 ||
251             shstrindex >= hdr->e_shnum ||
252             shdr[shstrindex].sh_type != SHT_STRTAB) {
253                 printf("%s: bad/missing section headers\n", filename);
254                 error = ENOEXEC;
255                 goto out;
256         }
257
258         /* Allocate space for tracking the load chunks */
259         if (ef->nprogtab != 0)
260                 ef->progtab = malloc(ef->nprogtab * sizeof(*ef->progtab),
261                     M_LINKER, M_WAITOK | M_ZERO);
262         if (ef->nrel != 0)
263                 ef->reltab = malloc(ef->nrel * sizeof(*ef->reltab), M_LINKER,
264                     M_WAITOK | M_ZERO);
265         if (ef->nrela != 0)
266                 ef->relatab = malloc(ef->nrela * sizeof(*ef->relatab), M_LINKER,
267                     M_WAITOK | M_ZERO);
268         if ((ef->nprogtab != 0 && ef->progtab == NULL) ||
269             (ef->nrel != 0 && ef->reltab == NULL) ||
270             (ef->nrela != 0 && ef->relatab == NULL)) {
271                 error = ENOMEM;
272                 goto out;
273         }
274
275         /* XXX, relocate the sh_addr fields saved by the loader. */
276         off = 0;
277         for (i = 0; i < hdr->e_shnum; i++) {
278                 if (shdr[i].sh_addr != 0 && (off == 0 || shdr[i].sh_addr < off))
279                         off = shdr[i].sh_addr;
280         }
281         for (i = 0; i < hdr->e_shnum; i++) {
282                 if (shdr[i].sh_addr != 0)
283                         shdr[i].sh_addr = shdr[i].sh_addr - off +
284                             (Elf_Addr)ef->address;
285         }
286
287         ef->ddbsymcnt = shdr[symtabindex].sh_size / sizeof(Elf_Sym);
288         ef->ddbsymtab = (Elf_Sym *)shdr[symtabindex].sh_addr;
289         ef->ddbstrcnt = shdr[symstrindex].sh_size;
290         ef->ddbstrtab = (char *)shdr[symstrindex].sh_addr;
291         ef->shstrcnt = shdr[shstrindex].sh_size;
292         ef->shstrtab = (char *)shdr[shstrindex].sh_addr;
293
294         /* Now fill out progtab and the relocation tables. */
295         pb = 0;
296         rl = 0;
297         ra = 0;
298         for (i = 0; i < hdr->e_shnum; i++) {
299                 switch (shdr[i].sh_type) {
300                 case SHT_PROGBITS:
301                 case SHT_NOBITS:
302                         ef->progtab[pb].addr = (void *)shdr[i].sh_addr;
303                         if (shdr[i].sh_type == SHT_PROGBITS)
304                                 ef->progtab[pb].name = "<<PROGBITS>>";
305                         else
306                                 ef->progtab[pb].name = "<<NOBITS>>";
307                         ef->progtab[pb].size = shdr[i].sh_size;
308                         ef->progtab[pb].sec = i;
309                         if (ef->shstrtab && shdr[i].sh_name != 0)
310                                 ef->progtab[pb].name =
311                                     ef->shstrtab + shdr[i].sh_name;
312
313                         /* Update all symbol values with the offset. */
314                         for (j = 0; j < ef->ddbsymcnt; j++) {
315                                 es = &ef->ddbsymtab[j];
316                                 if (es->st_shndx != i)
317                                         continue;
318                                 es->st_value += (Elf_Addr)ef->progtab[pb].addr;
319                         }
320                         pb++;
321                         break;
322                 case SHT_REL:
323                         ef->reltab[rl].rel = (Elf_Rel *)shdr[i].sh_addr;
324                         ef->reltab[rl].nrel = shdr[i].sh_size / sizeof(Elf_Rel);
325                         ef->reltab[rl].sec = shdr[i].sh_info;
326                         rl++;
327                         break;
328                 case SHT_RELA:
329                         ef->relatab[ra].rela = (Elf_Rela *)shdr[i].sh_addr;
330                         ef->relatab[ra].nrela =
331                             shdr[i].sh_size / sizeof(Elf_Rela);
332                         ef->relatab[ra].sec = shdr[i].sh_info;
333                         ra++;
334                         break;
335                 }
336         }
337         if (pb != ef->nprogtab)
338                 panic("lost progbits");
339         if (rl != ef->nrel)
340                 panic("lost rel");
341         if (ra != ef->nrela)
342                 panic("lost rela");
343
344         /* Local intra-module relocations */
345         link_elf_reloc_local(lf);
346
347         *result = lf;
348         return (0);
349
350 out:
351         /* preload not done this way */
352         linker_file_unload(lf, LINKER_UNLOAD_FORCE);
353         return (error);
354 }
355
356 static int
357 link_elf_link_preload_finish(linker_file_t lf)
358 {
359         elf_file_t ef;
360         int error;
361
362         ef = (elf_file_t)lf;
363         error = relocate_file(ef);
364         if (error)
365                 return error;
366
367         /* Notify MD code that a module is being loaded. */
368         error = elf_cpu_load_file(lf);
369         if (error)
370                 return (error);
371
372         return (0);
373 }
374
375 static int
376 link_elf_load_file(linker_class_t cls, const char *filename,
377     linker_file_t *result)
378 {
379         struct nameidata nd;
380         struct thread *td = curthread;  /* XXX */
381         Elf_Ehdr *hdr;
382         Elf_Shdr *shdr;
383         Elf_Sym *es;
384         int nbytes, i, j;
385         vm_offset_t mapbase;
386         size_t mapsize;
387         int error = 0;
388         int resid, flags;
389         elf_file_t ef;
390         linker_file_t lf;
391         int symtabindex;
392         int symstrindex;
393         int shstrindex;
394         int nsym;
395         int pb, rl, ra;
396         int alignmask;
397         int vfslocked;
398
399         shdr = NULL;
400         lf = NULL;
401         mapsize = 0;
402         hdr = NULL;
403
404         NDINIT(&nd, LOOKUP, FOLLOW | MPSAFE, UIO_SYSSPACE, filename, td);
405         flags = FREAD;
406         error = vn_open(&nd, &flags, 0, -1);
407         if (error)
408                 return error;
409         vfslocked = NDHASGIANT(&nd);
410         NDFREE(&nd, NDF_ONLY_PNBUF);
411 #ifdef MAC
412         error = mac_check_kld_load(td->td_ucred, nd.ni_vp);
413         if (error) {
414                 goto out;
415         }
416 #endif
417
418         /* Read the elf header from the file. */
419         hdr = malloc(sizeof(*hdr), M_LINKER, M_WAITOK);
420         if (hdr == NULL) {
421                 error = ENOMEM;
422                 goto out;
423         }
424         error = vn_rdwr(UIO_READ, nd.ni_vp, (void *)hdr, sizeof(*hdr), 0,
425             UIO_SYSSPACE, IO_NODELOCKED, td->td_ucred, NOCRED,
426             &resid, td);
427         if (error)
428                 goto out;
429         if (resid != 0){
430                 error = ENOEXEC;
431                 goto out;
432         }
433
434         if (!IS_ELF(*hdr)) {
435                 error = ENOEXEC;
436                 goto out;
437         }
438
439         if (hdr->e_ident[EI_CLASS] != ELF_TARG_CLASS
440             || hdr->e_ident[EI_DATA] != ELF_TARG_DATA) {
441                 link_elf_error("Unsupported file layout");
442                 error = ENOEXEC;
443                 goto out;
444         }
445         if (hdr->e_ident[EI_VERSION] != EV_CURRENT
446             || hdr->e_version != EV_CURRENT) {
447                 link_elf_error("Unsupported file version");
448                 error = ENOEXEC;
449                 goto out;
450         }
451         if (hdr->e_type != ET_REL) {
452                 link_elf_error("Unsupported file type");
453                 error = ENOEXEC;
454                 goto out;
455         }
456         if (hdr->e_machine != ELF_TARG_MACH) {
457                 link_elf_error("Unsupported machine");
458                 error = ENOEXEC;
459                 goto out;
460         }
461
462         lf = linker_make_file(filename, &link_elf_class);
463         if (!lf) {
464                 error = ENOMEM;
465                 goto out;
466         }
467         ef = (elf_file_t) lf;
468         ef->nprogtab = 0;
469         ef->e_shdr = 0;
470         ef->nrel = 0;
471         ef->nrela = 0;
472
473         /* Allocate and read in the section header */
474         nbytes = hdr->e_shnum * hdr->e_shentsize;
475         if (nbytes == 0 || hdr->e_shoff == 0 ||
476             hdr->e_shentsize != sizeof(Elf_Shdr)) {
477                 error = ENOEXEC;
478                 goto out;
479         }
480         shdr = malloc(nbytes, M_LINKER, M_WAITOK);
481         if (shdr == NULL) {
482                 error = ENOMEM;
483                 goto out;
484         }
485         ef->e_shdr = shdr;
486         error = vn_rdwr(UIO_READ, nd.ni_vp, (caddr_t)shdr, nbytes, hdr->e_shoff,
487             UIO_SYSSPACE, IO_NODELOCKED, td->td_ucred, NOCRED, &resid, td);
488         if (error)
489                 goto out;
490         if (resid) {
491                 error = ENOEXEC;
492                 goto out;
493         }
494
495         /* Scan the section header for information and table sizing. */
496         nsym = 0;
497         symtabindex = -1;
498         symstrindex = -1;
499         for (i = 0; i < hdr->e_shnum; i++) {
500                 switch (shdr[i].sh_type) {
501                 case SHT_PROGBITS:
502                 case SHT_NOBITS:
503                         ef->nprogtab++;
504                         break;
505                 case SHT_SYMTAB:
506                         nsym++;
507                         symtabindex = i;
508                         symstrindex = shdr[i].sh_link;
509                         break;
510                 case SHT_REL:
511                         ef->nrel++;
512                         break;
513                 case SHT_RELA:
514                         ef->nrela++;
515                         break;
516                 case SHT_STRTAB:
517                         break;
518                 }
519         }
520         if (ef->nprogtab == 0) {
521                 link_elf_error("file has no contents");
522                 error = ENOEXEC;
523                 goto out;
524         }
525         if (nsym != 1) {
526                 /* Only allow one symbol table for now */
527                 link_elf_error("file has no valid symbol table");
528                 error = ENOEXEC;
529                 goto out;
530         }
531         if (symstrindex < 0 || symstrindex > hdr->e_shnum ||
532             shdr[symstrindex].sh_type != SHT_STRTAB) {
533                 link_elf_error("file has invalid symbol strings");
534                 error = ENOEXEC;
535                 goto out;
536         }
537
538         /* Allocate space for tracking the load chunks */
539         if (ef->nprogtab != 0)
540                 ef->progtab = malloc(ef->nprogtab * sizeof(*ef->progtab),
541                     M_LINKER, M_WAITOK | M_ZERO);
542         if (ef->nrel != 0)
543                 ef->reltab = malloc(ef->nrel * sizeof(*ef->reltab), M_LINKER,
544                     M_WAITOK | M_ZERO);
545         if (ef->nrela != 0)
546                 ef->relatab = malloc(ef->nrela * sizeof(*ef->relatab), M_LINKER,
547                     M_WAITOK | M_ZERO);
548         if ((ef->nprogtab != 0 && ef->progtab == NULL) ||
549             (ef->nrel != 0 && ef->reltab == NULL) ||
550             (ef->nrela != 0 && ef->relatab == NULL)) {
551                 error = ENOMEM;
552                 goto out;
553         }
554
555         if (symtabindex == -1)
556                 panic("lost symbol table index");
557         /* Allocate space for and load the symbol table */
558         ef->ddbsymcnt = shdr[symtabindex].sh_size / sizeof(Elf_Sym);
559         ef->ddbsymtab = malloc(shdr[symtabindex].sh_size, M_LINKER, M_WAITOK);
560         if (ef->ddbsymtab == NULL) {
561                 error = ENOMEM;
562                 goto out;
563         }
564         error = vn_rdwr(UIO_READ, nd.ni_vp, (void *)ef->ddbsymtab,
565             shdr[symtabindex].sh_size, shdr[symtabindex].sh_offset,
566             UIO_SYSSPACE, IO_NODELOCKED, td->td_ucred, NOCRED,
567             &resid, td);
568         if (error)
569                 goto out;
570         if (resid != 0){
571                 error = EINVAL;
572                 goto out;
573         }
574
575         if (symstrindex == -1)
576                 panic("lost symbol string index");
577         /* Allocate space for and load the symbol strings */
578         ef->ddbstrcnt = shdr[symstrindex].sh_size;
579         ef->ddbstrtab = malloc(shdr[symstrindex].sh_size, M_LINKER, M_WAITOK);
580         if (ef->ddbstrtab == NULL) {
581                 error = ENOMEM;
582                 goto out;
583         }
584         error = vn_rdwr(UIO_READ, nd.ni_vp, ef->ddbstrtab,
585             shdr[symstrindex].sh_size, shdr[symstrindex].sh_offset,
586             UIO_SYSSPACE, IO_NODELOCKED, td->td_ucred, NOCRED,
587             &resid, td);
588         if (error)
589                 goto out;
590         if (resid != 0){
591                 error = EINVAL;
592                 goto out;
593         }
594
595         /* Do we have a string table for the section names?  */
596         shstrindex = -1;
597         if (hdr->e_shstrndx != 0 &&
598             shdr[hdr->e_shstrndx].sh_type == SHT_STRTAB) {
599                 shstrindex = hdr->e_shstrndx;
600                 ef->shstrcnt = shdr[shstrindex].sh_size;
601                 ef->shstrtab = malloc(shdr[shstrindex].sh_size, M_LINKER,
602                     M_WAITOK);
603                 if (ef->shstrtab == NULL) {
604                         error = ENOMEM;
605                         goto out;
606                 }
607                 error = vn_rdwr(UIO_READ, nd.ni_vp, ef->shstrtab,
608                     shdr[shstrindex].sh_size, shdr[shstrindex].sh_offset,
609                     UIO_SYSSPACE, IO_NODELOCKED, td->td_ucred, NOCRED,
610                     &resid, td);
611                 if (error)
612                         goto out;
613                 if (resid != 0){
614                         error = EINVAL;
615                         goto out;
616                 }
617         }
618
619         /* Size up code/data(progbits) and bss(nobits). */
620         alignmask = 0;
621         for (i = 0; i < hdr->e_shnum; i++) {
622                 switch (shdr[i].sh_type) {
623                 case SHT_PROGBITS:
624                 case SHT_NOBITS:
625                         alignmask = shdr[i].sh_addralign - 1;
626                         mapsize += alignmask;
627                         mapsize &= ~alignmask;
628                         mapsize += shdr[i].sh_size;
629                         break;
630                 }
631         }
632
633         /*
634          * We know how much space we need for the text/data/bss/etc.
635          * This stuff needs to be in a single chunk so that profiling etc
636          * can get the bounds and gdb can associate offsets with modules
637          */
638         ef->object = vm_object_allocate(OBJT_DEFAULT,
639             round_page(mapsize) >> PAGE_SHIFT);
640         if (ef->object == NULL) {
641                 error = ENOMEM;
642                 goto out;
643         }
644         ef->address = (caddr_t) vm_map_min(kernel_map);
645         error = vm_map_find(kernel_map, ef->object, 0, &mapbase,
646             round_page(mapsize), TRUE, VM_PROT_ALL, VM_PROT_ALL, FALSE);
647         if (error) {
648                 vm_object_deallocate(ef->object);
649                 ef->object = 0;
650                 goto out;
651         }
652
653         /* Wire the pages */
654         error = vm_map_wire(kernel_map, mapbase,
655             mapbase + round_page(mapsize),
656             VM_MAP_WIRE_SYSTEM|VM_MAP_WIRE_NOHOLES);
657         if (error != KERN_SUCCESS) {
658                 error = ENOMEM;
659                 goto out;
660         }
661
662         /* Inform the kld system about the situation */
663         lf->address = ef->address = (caddr_t)mapbase;
664         lf->size = mapsize;
665
666         /*
667          * Now load code/data(progbits), zero bss(nobits), allocate space for
668          * and load relocs
669          */
670         pb = 0;
671         rl = 0;
672         ra = 0;
673         alignmask = 0;
674         for (i = 0; i < hdr->e_shnum; i++) {
675                 switch (shdr[i].sh_type) {
676                 case SHT_PROGBITS:
677                 case SHT_NOBITS:
678                         alignmask = shdr[i].sh_addralign - 1;
679                         mapbase += alignmask;
680                         mapbase &= ~alignmask;
681                         ef->progtab[pb].addr = (void *)(uintptr_t)mapbase;
682                         if (shdr[i].sh_type == SHT_PROGBITS) {
683                                 ef->progtab[pb].name = "<<PROGBITS>>";
684                                 error = vn_rdwr(UIO_READ, nd.ni_vp,
685                                     ef->progtab[pb].addr,
686                                     shdr[i].sh_size, shdr[i].sh_offset,
687                                     UIO_SYSSPACE, IO_NODELOCKED, td->td_ucred,
688                                     NOCRED, &resid, td);
689                                 if (error)
690                                         goto out;
691                                 if (resid != 0){
692                                         error = EINVAL;
693                                         goto out;
694                                 }
695                         } else {
696                                 ef->progtab[pb].name = "<<NOBITS>>";
697                                 bzero(ef->progtab[pb].addr, shdr[i].sh_size);
698                         }
699                         ef->progtab[pb].size = shdr[i].sh_size;
700                         ef->progtab[pb].sec = i;
701                         if (ef->shstrtab && shdr[i].sh_name != 0)
702                                 ef->progtab[pb].name =
703                                     ef->shstrtab + shdr[i].sh_name;
704
705                         /* Update all symbol values with the offset. */
706                         for (j = 0; j < ef->ddbsymcnt; j++) {
707                                 es = &ef->ddbsymtab[j];
708                                 if (es->st_shndx != i)
709                                         continue;
710                                 es->st_value += (Elf_Addr)ef->progtab[pb].addr;
711                         }
712                         mapbase += shdr[i].sh_size;
713                         pb++;
714                         break;
715                 case SHT_REL:
716                         ef->reltab[rl].rel = malloc(shdr[i].sh_size, M_LINKER,
717                             M_WAITOK);
718                         ef->reltab[rl].nrel = shdr[i].sh_size / sizeof(Elf_Rel);
719                         ef->reltab[rl].sec = shdr[i].sh_info;
720                         error = vn_rdwr(UIO_READ, nd.ni_vp,
721                             (void *)ef->reltab[rl].rel,
722                             shdr[i].sh_size, shdr[i].sh_offset,
723                             UIO_SYSSPACE, IO_NODELOCKED, td->td_ucred, NOCRED,
724                             &resid, td);
725                         if (error)
726                                 goto out;
727                         if (resid != 0){
728                                 error = EINVAL;
729                                 goto out;
730                         }
731                         rl++;
732                         break;
733                 case SHT_RELA:
734                         ef->relatab[ra].rela = malloc(shdr[i].sh_size, M_LINKER,
735                             M_WAITOK);
736                         ef->relatab[ra].nrela =
737                             shdr[i].sh_size / sizeof(Elf_Rela);
738                         ef->relatab[ra].sec = shdr[i].sh_info;
739                         error = vn_rdwr(UIO_READ, nd.ni_vp,
740                             (void *)ef->relatab[ra].rela,
741                             shdr[i].sh_size, shdr[i].sh_offset,
742                             UIO_SYSSPACE, IO_NODELOCKED, td->td_ucred, NOCRED,
743                             &resid, td);
744                         if (error)
745                                 goto out;
746                         if (resid != 0){
747                                 error = EINVAL;
748                                 goto out;
749                         }
750                         ra++;
751                         break;
752                 }
753         }
754         if (pb != ef->nprogtab)
755                 panic("lost progbits");
756         if (rl != ef->nrel)
757                 panic("lost rel");
758         if (ra != ef->nrela)
759                 panic("lost rela");
760         if (mapbase != (vm_offset_t)ef->address + mapsize)
761                 panic("mapbase 0x%lx != address %p + mapsize 0x%lx (0x%lx)\n",
762                     mapbase, ef->address, mapsize,
763                     (vm_offset_t)ef->address + mapsize);
764
765         /* Local intra-module relocations */
766         link_elf_reloc_local(lf);
767
768         /* Pull in dependencies */
769         error = linker_load_dependencies(lf);
770         if (error)
771                 goto out;
772
773         /* External relocations */
774         error = relocate_file(ef);
775         if (error)
776                 goto out;
777
778         /* Notify MD code that a module is being loaded. */
779         error = elf_cpu_load_file(lf);
780         if (error)
781                 goto out;
782
783         *result = lf;
784
785 out:
786         if (error && lf)
787                 linker_file_unload(lf, LINKER_UNLOAD_FORCE);
788         if (hdr)
789                 free(hdr, M_LINKER);
790         VOP_UNLOCK(nd.ni_vp, 0, td);
791         vn_close(nd.ni_vp, FREAD, td->td_ucred, td);
792         VFS_UNLOCK_GIANT(vfslocked);
793
794         return error;
795 }
796
797 static void
798 link_elf_unload_file(linker_file_t file)
799 {
800         elf_file_t ef = (elf_file_t) file;
801         int i;
802
803         /* Notify MD code that a module is being unloaded. */
804         elf_cpu_unload_file(file);
805
806         if (ef->preloaded) {
807                 if (ef->reltab)
808                         free(ef->reltab, M_LINKER);
809                 if (ef->relatab)
810                         free(ef->relatab, M_LINKER);
811                 if (ef->progtab)
812                         free(ef->progtab, M_LINKER);
813                 if (file->filename != NULL)
814                         preload_delete_name(file->filename);
815                 /* XXX reclaim module memory? */
816                 return;
817         }
818
819         for (i = 0; i < ef->nrel; i++)
820                 if (ef->reltab[i].rel)
821                         free(ef->reltab[i].rel, M_LINKER);
822         for (i = 0; i < ef->nrela; i++)
823                 if (ef->relatab[i].rela)
824                         free(ef->relatab[i].rela, M_LINKER);
825         if (ef->reltab)
826                 free(ef->reltab, M_LINKER);
827         if (ef->relatab)
828                 free(ef->relatab, M_LINKER);
829         if (ef->progtab)
830                 free(ef->progtab, M_LINKER);
831
832         if (ef->object) {
833                 vm_map_remove(kernel_map, (vm_offset_t) ef->address,
834                     (vm_offset_t) ef->address +
835                     (ef->object->size << PAGE_SHIFT));
836         }
837         if (ef->e_shdr)
838                 free(ef->e_shdr, M_LINKER);
839         if (ef->ddbsymtab)
840                 free(ef->ddbsymtab, M_LINKER);
841         if (ef->ddbstrtab)
842                 free(ef->ddbstrtab, M_LINKER);
843         if (ef->shstrtab)
844                 free(ef->shstrtab, M_LINKER);
845 }
846
847 static const char *
848 symbol_name(elf_file_t ef, Elf_Size r_info)
849 {
850         const Elf_Sym *ref;
851
852         if (ELF_R_SYM(r_info)) {
853                 ref = ef->ddbsymtab + ELF_R_SYM(r_info);
854                 return ef->ddbstrtab + ref->st_name;
855         } else
856                 return NULL;
857 }
858
859 static Elf_Addr
860 findbase(elf_file_t ef, int sec)
861 {
862         int i;
863         Elf_Addr base = 0;
864
865         for (i = 0; i < ef->nprogtab; i++) {
866                 if (sec == ef->progtab[i].sec) {
867                         base = (Elf_Addr)ef->progtab[i].addr;
868                         break;
869                 }
870         }
871         return base;
872 }
873
874 static int
875 relocate_file(elf_file_t ef)
876 {
877         const Elf_Rel *rellim;
878         const Elf_Rel *rel;
879         const Elf_Rela *relalim;
880         const Elf_Rela *rela;
881         const char *symname;
882         const Elf_Sym *sym;
883         int i;
884         Elf_Size symidx;
885         Elf_Addr base;
886
887
888         /* Perform relocations without addend if there are any: */
889         for (i = 0; i < ef->nrel; i++) {
890                 rel = ef->reltab[i].rel;
891                 if (rel == NULL)
892                         panic("lost a reltab!");
893                 rellim = rel + ef->reltab[i].nrel;
894                 base = findbase(ef, ef->reltab[i].sec);
895                 if (base == 0)
896                         panic("lost base for reltab");
897                 for ( ; rel < rellim; rel++) {
898                         symidx = ELF_R_SYM(rel->r_info);
899                         if (symidx >= ef->ddbsymcnt)
900                                 continue;
901                         sym = ef->ddbsymtab + symidx;
902                         /* Local relocs are already done */
903                         if (ELF_ST_BIND(sym->st_info) == STB_LOCAL)
904                                 continue;
905                         if (elf_reloc(&ef->lf, base, rel, ELF_RELOC_REL,
906                             elf_obj_lookup)) {
907                                 symname = symbol_name(ef, rel->r_info);
908                                 printf("link_elf_obj: symbol %s undefined\n",
909                                     symname);
910                                 return ENOENT;
911                         }
912                 }
913         }
914
915         /* Perform relocations with addend if there are any: */
916         for (i = 0; i < ef->nrela; i++) {
917                 rela = ef->relatab[i].rela;
918                 if (rela == NULL)
919                         panic("lost a relatab!");
920                 relalim = rela + ef->relatab[i].nrela;
921                 base = findbase(ef, ef->relatab[i].sec);
922                 if (base == 0)
923                         panic("lost base for relatab");
924                 for ( ; rela < relalim; rela++) {
925                         symidx = ELF_R_SYM(rela->r_info);
926                         if (symidx >= ef->ddbsymcnt)
927                                 continue;
928                         sym = ef->ddbsymtab + symidx;
929                         /* Local relocs are already done */
930                         if (ELF_ST_BIND(sym->st_info) == STB_LOCAL)
931                                 continue;
932                         if (elf_reloc(&ef->lf, base, rela, ELF_RELOC_RELA,
933                             elf_obj_lookup)) {
934                                 symname = symbol_name(ef, rela->r_info);
935                                 printf("link_elf_obj: symbol %s undefined\n",
936                                     symname);
937                                 return ENOENT;
938                         }
939                 }
940         }
941
942         return 0;
943 }
944
945 static int
946 link_elf_lookup_symbol(linker_file_t lf, const char *name, c_linker_sym_t *sym)
947 {
948         elf_file_t ef = (elf_file_t) lf;
949         const Elf_Sym *symp;
950         const char *strp;
951         int i;
952
953         for (i = 0, symp = ef->ddbsymtab; i < ef->ddbsymcnt; i++, symp++) {
954                 strp = ef->ddbstrtab + symp->st_name;
955                 if (symp->st_shndx != SHN_UNDEF && strcmp(name, strp) == 0) {
956                         *sym = (c_linker_sym_t) symp;
957                         return 0;
958                 }
959         }
960         return ENOENT;
961 }
962
963 static int
964 link_elf_symbol_values(linker_file_t lf, c_linker_sym_t sym,
965     linker_symval_t *symval)
966 {
967         elf_file_t ef = (elf_file_t) lf;
968         const Elf_Sym *es = (const Elf_Sym*) sym;
969
970         if (es >= ef->ddbsymtab && es < (ef->ddbsymtab + ef->ddbsymcnt)) {
971                 symval->name = ef->ddbstrtab + es->st_name;
972                 symval->value = (caddr_t)es->st_value;
973                 symval->size = es->st_size;
974                 return 0;
975         }
976         return ENOENT;
977 }
978
979 static int
980 link_elf_search_symbol(linker_file_t lf, caddr_t value,
981     c_linker_sym_t *sym, long *diffp)
982 {
983         elf_file_t ef = (elf_file_t) lf;
984         u_long off = (uintptr_t) (void *) value;
985         u_long diff = off;
986         u_long st_value;
987         const Elf_Sym *es;
988         const Elf_Sym *best = 0;
989         int i;
990
991         for (i = 0, es = ef->ddbsymtab; i < ef->ddbsymcnt; i++, es++) {
992                 if (es->st_name == 0)
993                         continue;
994                 st_value = es->st_value;
995                 if (off >= st_value) {
996                         if (off - st_value < diff) {
997                                 diff = off - st_value;
998                                 best = es;
999                                 if (diff == 0)
1000                                         break;
1001                         } else if (off - st_value == diff) {
1002                                 best = es;
1003                         }
1004                 }
1005         }
1006         if (best == 0)
1007                 *diffp = off;
1008         else
1009                 *diffp = diff;
1010         *sym = (c_linker_sym_t) best;
1011
1012         return 0;
1013 }
1014
1015 /*
1016  * Look up a linker set on an ELF system.
1017  */
1018 static int
1019 link_elf_lookup_set(linker_file_t lf, const char *name,
1020     void ***startp, void ***stopp, int *countp)
1021 {
1022         elf_file_t ef = (elf_file_t)lf;
1023         void **start, **stop;
1024         int i, count;
1025
1026         /* Relative to section number */
1027         for (i = 0; i < ef->nprogtab; i++) {
1028                 if ((strncmp(ef->progtab[i].name, "set_", 4) == 0) &&
1029                     strcmp(ef->progtab[i].name + 4, name) == 0) {
1030                         start  = (void **)ef->progtab[i].addr;
1031                         stop = (void **)((char *)ef->progtab[i].addr +
1032                             ef->progtab[i].size);
1033                         count = stop - start;
1034                         if (startp)
1035                                 *startp = start;
1036                         if (stopp)
1037                                 *stopp = stop;
1038                         if (countp)
1039                                 *countp = count;
1040                         return (0);
1041                 }
1042         }
1043         return (ESRCH);
1044 }
1045
1046 static int
1047 link_elf_each_function_name(linker_file_t file,
1048     int (*callback)(const char *, void *), void *opaque)
1049 {
1050         elf_file_t ef = (elf_file_t)file;
1051         const Elf_Sym *symp;
1052         int i, error;
1053         
1054         /* Exhaustive search */
1055         for (i = 0, symp = ef->ddbsymtab; i < ef->ddbsymcnt; i++, symp++) {
1056                 if (symp->st_value != 0 &&
1057                     ELF_ST_TYPE(symp->st_info) == STT_FUNC) {
1058                         error = callback(ef->ddbstrtab + symp->st_name, opaque);
1059                         if (error)
1060                                 return (error);
1061                 }
1062         }
1063         return (0);
1064 }
1065
1066 /*
1067  * Symbol lookup function that can be used when the symbol index is known (ie
1068  * in relocations). It uses the symbol index instead of doing a fully fledged
1069  * hash table based lookup when such is valid. For example for local symbols.
1070  * This is not only more efficient, it's also more correct. It's not always
1071  * the case that the symbol can be found through the hash table.
1072  */
1073 static Elf_Addr
1074 elf_obj_lookup(linker_file_t lf, Elf_Size symidx, int deps)
1075 {
1076         elf_file_t ef = (elf_file_t)lf;
1077         const Elf_Sym *sym;
1078         const char *symbol;
1079         Elf_Addr ret;
1080
1081         /* Don't even try to lookup the symbol if the index is bogus. */
1082         if (symidx >= ef->ddbsymcnt)
1083                 return (0);
1084
1085         sym = ef->ddbsymtab + symidx;
1086
1087         /* Quick answer if there is a definition included. */
1088         if (sym->st_shndx != SHN_UNDEF)
1089                 return (sym->st_value);
1090
1091         /* If we get here, then it is undefined and needs a lookup. */
1092         switch (ELF_ST_BIND(sym->st_info)) {
1093         case STB_LOCAL:
1094                 /* Local, but undefined? huh? */
1095                 return (0);
1096
1097         case STB_GLOBAL:
1098                 /* Relative to Data or Function name */
1099                 symbol = ef->ddbstrtab + sym->st_name;
1100
1101                 /* Force a lookup failure if the symbol name is bogus. */
1102                 if (*symbol == 0)
1103                         return (0);
1104                 ret = ((Elf_Addr)linker_file_lookup_symbol(lf, symbol, deps));
1105                 return ret;
1106
1107         case STB_WEAK:
1108                 printf("link_elf_obj: Weak symbols not supported\n");
1109                 return (0);
1110
1111         default:
1112                 return (0);
1113         }
1114 }
1115
1116 static void
1117 link_elf_reloc_local(linker_file_t lf)
1118 {
1119         elf_file_t ef = (elf_file_t)lf;
1120         const Elf_Rel *rellim;
1121         const Elf_Rel *rel;
1122         const Elf_Rela *relalim;
1123         const Elf_Rela *rela;
1124         const Elf_Sym *sym;
1125         Elf_Addr base;
1126         int i;
1127         Elf_Size symidx;
1128
1129         /* Perform relocations without addend if there are any: */
1130         for (i = 0; i < ef->nrel; i++) {
1131                 rel = ef->reltab[i].rel;
1132                 if (rel == NULL)
1133                         panic("lost a reltab!");
1134                 rellim = rel + ef->reltab[i].nrel;
1135                 base = findbase(ef, ef->reltab[i].sec);
1136                 if (base == 0)
1137                         panic("lost base for reltab");
1138                 for ( ; rel < rellim; rel++) {
1139                         symidx = ELF_R_SYM(rel->r_info);
1140                         if (symidx >= ef->ddbsymcnt)
1141                                 continue;
1142                         sym = ef->ddbsymtab + symidx;
1143                         /* Only do local relocs */
1144                         if (ELF_ST_BIND(sym->st_info) != STB_LOCAL)
1145                                 continue;
1146                         elf_reloc_local(lf, base, rel, ELF_RELOC_REL,
1147                             elf_obj_lookup);
1148                 }
1149         }
1150
1151         /* Perform relocations with addend if there are any: */
1152         for (i = 0; i < ef->nrela; i++) {
1153                 rela = ef->relatab[i].rela;
1154                 if (rela == NULL)
1155                         panic("lost a relatab!");
1156                 relalim = rela + ef->relatab[i].nrela;
1157                 base = findbase(ef, ef->relatab[i].sec);
1158                 if (base == 0)
1159                         panic("lost base for relatab");
1160                 for ( ; rela < relalim; rela++) {
1161                         symidx = ELF_R_SYM(rela->r_info);
1162                         if (symidx >= ef->ddbsymcnt)
1163                                 continue;
1164                         sym = ef->ddbsymtab + symidx;
1165                         /* Only do local relocs */
1166                         if (ELF_ST_BIND(sym->st_info) != STB_LOCAL)
1167                                 continue;
1168                         elf_reloc_local(lf, base, rela, ELF_RELOC_RELA,
1169                             elf_obj_lookup);
1170                 }
1171         }
1172 }