openblt

a hobby OS from the late 90s
git clone http://frotz.net/git/openblt.git
Log | Files | Refs | LICENSE

load.c (6029B)


      1 /* $Id: //depot/blt/lib/libdl/load.c#8 $
      2 **
      3 ** Copyright 1999 Sidney Cammeresi
      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 ** 3. The name of the author may not be used to endorse or promote products
     15 **    derived from this software without specific prior written permission.
     16 **
     17 ** THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
     18 ** IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
     19 ** OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
     20 ** IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
     21 ** INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
     22 ** NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
     23 ** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
     24 ** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     25 ** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
     26 ** THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     27 */
     28 
     29 #include <stdio.h>
     30 #include <stdlib.h>
     31 #include <string.h>
     32 #include <fcntl.h>
     33 #include <unistd.h>
     34 #include <errno.h>
     35 #include <dlfcn.h>
     36 #include <sys/stat.h>
     37 #include <blt/libsyms.h>
     38 #include <blt/syscall.h>
     39 #include "dl-int.h"
     40 
     41 weak_alias (_dlopen, dlopen)
     42 weak_alias (_dlclose, dlclose)
     43 weak_alias (_dlerror, dlerror)
     44 
     45 const char *__dl_error = NULL;
     46 static volatile char initialised = 0;
     47 lib_t *file;
     48 
     49 /*
     50  * Initialise the list of loaded images with our binary.
     51  *
     52  * XXX this will break when the executable is at least partially
     53  * dynamically linked.
     54  */
     55 void __dlinit (void)
     56 {
     57 	initialised = 1;
     58 	file = malloc (sizeof (lib_t));
     59 	file->hdr = (elf32_hdr_t *) 0x1000;
     60 	file->strtab = elf_find_section_hdr (file->hdr, ".strtab");
     61 	file->strtab_data = elf_find_section_data (file->hdr, ".strtab");
     62 	file->strtab_size = elf_section_size (file->hdr, ".strtab");
     63 	file->symtab = elf_find_section_hdr (file->hdr, ".symtab");
     64 	file->symtab_data = elf_find_section_data (file->hdr, ".symtab");
     65 	file->symtab_size = elf_section_size (file->hdr, ".symtab");
     66 /*
     67 	file->dynstr = elf_find_section_hdr (file->hdr, ".dynstr");
     68 	file->dynstr_data = elf_find_section_data (file->hdr, ".dynstr");
     69 	file->dynstr_size = elf_section_size (file->hdr, ".dynstr");
     70 	file->dynsym = elf_find_section_hdr (file->hdr, ".dynsym");
     71 	file->dynsym_data = elf_find_section_data (file->hdr, ".dynsym");
     72 	file->dynsym_size = elf_section_size (file->hdr, ".dynsym");
     73 */
     74 	file->next = NULL;
     75 }
     76 
     77 /*
     78  * Loading is not completely straightforward.  There is only one hack here,
     79  * in that we guess that we will only need one page more memory than the
     80  * size of the library.  This seems to work on all libraries I can get my
     81  * hands on (both OpenBLT and Linux shared libraries).
     82  *
     83  * The memmove loop may look like a hack because you might think I'm not
     84  * completely parsing the program headers.  It's not because file offsets
     85  * and virtual addresses in an ELF file are equal, modulo 4k or larger
     86  * powers of two.  Read page 2-7 of the ELF specification for more
     87  * information.
     88  */
     89 void *_dlopen (const char *filename, int flag)
     90 {
     91 	char *c;
     92 	int i, size, fd, res, len;
     93 	struct stat buf;
     94 	lib_t *lib, *p;
     95 	elf32_pgm_hdr_t *pgm;
     96 	int (*fn)(void);
     97 
     98 	if (!initialised)
     99 		__dlinit ();
    100 
    101 	__dl_error = NULL;
    102 	if (_stat (filename, &buf))
    103 	{
    104 		errno = ENOENT;
    105 		return NULL;
    106 	}
    107 	size = buf.st_size;
    108 	size = (size & ~3) ? (size & ~3) + 0x1000 : size;
    109 	fd = _open (filename, O_RDONLY, 0);
    110 	if (fd < 0)
    111 		return NULL;
    112 	lib = malloc (sizeof (lib_t));
    113 	lib->area = area_create (size, 0, (void **) &c, 0);
    114 	len = 0;
    115 	while ((res = _read (fd, c + len, 0x2000)) > 0)
    116 		len += res;
    117 	_close (fd);
    118 
    119 	lib->hdr = (elf32_hdr_t *) c;
    120 	pgm = (elf32_pgm_hdr_t *) ((unsigned int) lib->hdr + lib->hdr->e_phoff);
    121 	for (i = lib->hdr->e_phnum - 1; i >= 0; i--)
    122 		memmove ((void *) ((unsigned int) lib->hdr + pgm[i].p_vaddr),
    123 			(void *) ((unsigned int) lib->hdr + pgm[i].p_offset),
    124 			pgm[i].p_filesz);
    125 	lib->strtab = elf_find_section_hdr (lib->hdr, ".strtab");
    126 	lib->strtab_data = elf_find_section_data (lib->hdr, ".strtab");
    127 	lib->strtab_size = elf_section_size (lib->hdr, ".strtab");
    128 	lib->symtab = elf_find_section_hdr (lib->hdr, ".symtab");
    129 	lib->symtab_data = elf_find_section_data (lib->hdr, ".symtab");
    130 	lib->symtab_size = elf_section_size (lib->hdr, ".symtab");
    131 	lib->dynstr = elf_find_section_hdr (lib->hdr, ".dynstr");
    132 	lib->dynstr_data = elf_find_section_data (lib->hdr, ".dynstr");
    133 	lib->dynstr_size = elf_section_size (file->hdr, ".dynstr");
    134 	lib->dynsym = elf_find_section_hdr (lib->hdr, ".dynsym");
    135 	lib->dynsym_data = elf_find_section_data (lib->hdr, ".dynsym");
    136 	lib->dynsym_size = elf_section_size (file->hdr, ".dynsym");
    137 
    138 	if (__dl_patchup (lib))
    139 	{
    140 		area_destroy (lib->area);
    141 		free (lib);
    142 		return NULL;
    143 	}
    144 	if ((fn = (int (*)(void)) (__dl_lookup_sym (lib, "_init") +
    145 			(unsigned int) lib->hdr)))
    146 		res = (*fn) ();
    147 	if ((flag & ~RTLD_GLOBAL) || res)
    148 	{
    149 		p = file;
    150 		while (p->next != NULL)
    151 			p = p->next;
    152 		p->next = lib;
    153 		lib->next = NULL;
    154 	}
    155 	else
    156 		lib->next = NULL;
    157 	return lib;
    158 }
    159 
    160 int _dlclose (void *handle)
    161 {
    162 	lib_t *lib, *p;
    163 	void (*fn)(void);
    164 
    165 	lib = handle;
    166 	if (file == lib)
    167 		file = file->next;
    168 	else
    169 	{
    170 		p = file;
    171 		while ((p->next != lib) && (p->next != NULL))
    172 			p = p->next;
    173 		if (p->next != NULL)
    174 			p->next = lib->next;
    175 	}
    176 	if ((fn = (void (*)(void)) (__dl_lookup_sym (lib, "_fini") +
    177 			(unsigned int) lib->hdr)))
    178 		(*fn) ();
    179 	area_destroy (lib->area);
    180 	free (handle);
    181 	return 0;
    182 }
    183 
    184 const char *_dlerror (void)
    185 {
    186 	return __dl_error;
    187 }
    188