Fork us on GitHub Follow us on Facebook Follow us on Twitter

Changeset 17341d4 in mainline


Ignore:
Timestamp:
2016-04-20T17:25:48Z (5 years ago)
Author:
Jiri Svoboda <jiri@…>
Branches:
master
Children:
dc0d8b52
Parents:
13dfa3f9
Message:

Move rtld internals out of loader. Stop misusing rtld instance from current environment for loading dynamically linked executables.

Location:
uspace
Files:
4 added
13 edited

Legend:

Unmodified
Added
Removed
  • uspace/lib/c/Makefile

    r13dfa3f9 r17341d4  
    7979        generic/dlfcn.c \
    8080        generic/elf/elf_load.c \
     81        generic/elf/elf_mod.c \
    8182        generic/event.c \
    8283        generic/errno.c \
  • uspace/lib/c/generic/dlfcn.c

    r13dfa3f9 r17341d4  
    4242
    4343#include <rtld/module.h>
     44#include <rtld/rtld.h>
    4445#include <rtld/symbol.h>
    4546
     
    5657
    5758        printf("module_find('%s')\n", path);
    58         m = module_find(path);
     59        m = module_find(runtime_env, path);
    5960        if (m == NULL) {
    6061                printf("NULL. module_load('%s')\n", path);
    61                 m = module_load(path);
     62                m = module_load(runtime_env, path);
    6263                printf("module_load_deps(m)\n");
    6364                module_load_deps(m);
  • uspace/lib/c/generic/elf/elf_load.c

    r13dfa3f9 r17341d4  
    11/*
    2  * Copyright (c) 2006 Sergey Bondari
    3  * Copyright (c) 2006 Jakub Jermar
    4  * Copyright (c) 2011 Jiri Svoboda
     2 * Copyright (c) 2016 Jiri Svoboda
    53 * All rights reserved.
    64 *
     
    3634 * @file
    3735 * @brief       Userspace ELF loader.
    38  *
    39  * This module allows loading ELF binaries (both executables and
    40  * shared objects) from VFS. The current implementation allocates
    41  * anonymous memory, fills it with segment data and then adjusts
    42  * the memory areas' flags to the final value. In the future,
    43  * the segments will be mapped directly from the file.
    4436 */
    4537
     38#include <errno.h>
    4639#include <stdio.h>
    47 #include <sys/types.h>
    48 #include <align.h>
    49 #include <assert.h>
    50 #include <as.h>
    51 #include <elf/elf.h>
    52 #include <unistd.h>
    53 #include <fcntl.h>
    54 #include <smc.h>
    55 #include <loader/pcb.h>
    56 #include <entry_point.h>
     40#include <elf/elf_load.h>
     41#include <elf/elf_mod.h>
     42#include <rtld/rtld.h>
    5743
    58 #include <elf/elf_load.h>
    5944
    6045#define DPRINTF(...)
    6146
    62 static const char *error_codes[] = {
    63         "no error",
    64         "invalid image",
    65         "address space error",
    66         "incompatible image",
    67         "unsupported image type",
    68         "irrecoverable error"
    69 };
    70 
    71 static unsigned int elf_load(elf_ld_t *elf, size_t so_bias);
    72 static int segment_header(elf_ld_t *elf, elf_segment_header_t *entry);
    73 static int section_header(elf_ld_t *elf, elf_section_header_t *entry);
    74 static int load_segment(elf_ld_t *elf, elf_segment_header_t *entry);
    75 
    76 /** Load ELF binary from a file.
     47/** Load ELF program.
    7748 *
    78  * Load an ELF binary from the specified file. If the file is
    79  * an executable program, it is loaded unbiased. If it is a shared
    80  * object, it is loaded with the bias @a so_bias. Some information
    81  * extracted from the binary is stored in a elf_info_t structure
    82  * pointed to by @a info.
    83  *
    84  * @param file_name Path to the ELF file.
    85  * @param so_bias   Bias to use if the file is a shared object.
    86  * @param info      Pointer to a structure for storing information
    87  *                  extracted from the binary.
    88  *
    89  * @return EOK on success or negative error code.
    90  *
     49 * @param file_name File name
     50 * @param info Place to store ELF program information
     51 * @return EOK on success or non-zero error code
    9152 */
    92 int elf_load_file(const char *file_name, size_t so_bias, eld_flags_t flags,
    93     elf_info_t *info)
     53int elf_load(const char *file_name, elf_info_t *info)
    9454{
    95         elf_ld_t elf;
    96 
    97         int fd;
     55#ifdef CONFIG_RTLD
     56        rtld_t *env;
     57#endif
    9858        int rc;
    9959
    100         fd = open(file_name, O_RDONLY);
    101         if (fd < 0) {
    102                 DPRINTF("failed opening file\n");
    103                 return -1;
     60        rc = elf_load_file(file_name, 0, 0, &info->finfo);
     61        if (rc != EE_OK) {
     62                DPRINTF("Failed to load executable '%s'.\n", file_name);
     63                return rc;
    10464        }
    10565
    106         elf.fd = fd;
    107         elf.info = info;
    108         elf.flags = flags;
     66        if (info->finfo.interp == NULL) {
     67                /* Statically linked program */
     68                DPRINTF("Binary is statically linked.\n");
     69                info->env = NULL;
     70                return EE_OK;
     71        }
    10972
    110         rc = elf_load(&elf, so_bias);
     73        DPRINTF("Binary is dynamically linked.\n");
     74#ifdef CONFIG_RTLD
     75        DPRINTF( "- prog dynamic: %p\n", info->finfo.dynamic);
    11176
    112         close(fd);
    113 
     77        rc = rtld_prog_process(&info->finfo, &env);
     78        info->env = env;
     79#else
     80        rc = EE_UNSUPPORTED;
     81#endif
    11482        return rc;
    11583}
    11684
    117 /** Create the program control block (PCB).
     85/** Set ELF-related PCB entries.
    11886 *
    11987 * Fills the program control block @a pcb with information from
     
    12189 *
    12290 * @param info  Program info structure
    123  * @return EOK on success or negative error code
     91 * @param pcb PCB
    12492 */
    125 void elf_create_pcb(elf_info_t *info, pcb_t *pcb)
     93void elf_set_pcb(elf_info_t *info, pcb_t *pcb)
    12694{
    127         pcb->entry = info->entry;
    128         pcb->dynamic = info->dynamic;
    129         pcb->rtld_runtime = NULL;
    130 }
    131 
    132 
    133 /** Load an ELF binary.
    134  *
    135  * The @a elf structure contains the loader state, including
    136  * an open file, from which the binary will be loaded,
    137  * a pointer to the @c info structure etc.
    138  *
    139  * @param elf           Pointer to loader state buffer.
    140  * @param so_bias       Bias to use if the file is a shared object.
    141  * @return EE_OK on success or EE_xx error code.
    142  */
    143 static unsigned int elf_load(elf_ld_t *elf, size_t so_bias)
    144 {
    145         elf_header_t header_buf;
    146         elf_header_t *header = &header_buf;
    147         int i, rc;
    148 
    149         rc = read(elf->fd, header, sizeof(elf_header_t));
    150         if (rc != sizeof(elf_header_t)) {
    151                 DPRINTF("Read error.\n");
    152                 return EE_INVALID;
    153         }
    154 
    155         elf->header = header;
    156 
    157         /* Identify ELF */
    158         if (header->e_ident[EI_MAG0] != ELFMAG0 ||
    159             header->e_ident[EI_MAG1] != ELFMAG1 ||
    160             header->e_ident[EI_MAG2] != ELFMAG2 ||
    161             header->e_ident[EI_MAG3] != ELFMAG3) {
    162                 DPRINTF("Invalid header.\n");
    163                 return EE_INVALID;
    164         }
    165        
    166         /* Identify ELF compatibility */
    167         if (header->e_ident[EI_DATA] != ELF_DATA_ENCODING ||
    168             header->e_machine != ELF_MACHINE ||
    169             header->e_ident[EI_VERSION] != EV_CURRENT ||
    170             header->e_version != EV_CURRENT ||
    171             header->e_ident[EI_CLASS] != ELF_CLASS) {
    172                 DPRINTF("Incompatible data/version/class.\n");
    173                 return EE_INCOMPATIBLE;
    174         }
    175 
    176         if (header->e_phentsize != sizeof(elf_segment_header_t)) {
    177                 DPRINTF("e_phentsize: %u != %zu\n", header->e_phentsize,
    178                     sizeof(elf_segment_header_t));
    179                 return EE_INCOMPATIBLE;
    180         }
    181 
    182         if (header->e_shentsize != sizeof(elf_section_header_t)) {
    183                 DPRINTF("e_shentsize: %u != %zu\n", header->e_shentsize,
    184                     sizeof(elf_section_header_t));
    185                 return EE_INCOMPATIBLE;
    186         }
    187 
    188         /* Check if the object type is supported. */
    189         if (header->e_type != ET_EXEC && header->e_type != ET_DYN) {
    190                 DPRINTF("Object type %d is not supported\n", header->e_type);
    191                 return EE_UNSUPPORTED;
    192         }
    193 
    194         /* Shared objects can be loaded with a bias */
    195         if (header->e_type == ET_DYN)
    196                 elf->bias = so_bias;
    197         else
    198                 elf->bias = 0;
    199 
    200         elf->info->interp = NULL;
    201         elf->info->dynamic = NULL;
    202 
    203         /* Walk through all segment headers and process them. */
    204         for (i = 0; i < header->e_phnum; i++) {
    205                 elf_segment_header_t segment_hdr;
    206 
    207                 /* Seek to start of segment header */
    208                 lseek(elf->fd, header->e_phoff
    209                         + i * sizeof(elf_segment_header_t), SEEK_SET);
    210 
    211                 rc = read(elf->fd, &segment_hdr,
    212                     sizeof(elf_segment_header_t));
    213                 if (rc != sizeof(elf_segment_header_t)) {
    214                         DPRINTF("Read error.\n");
    215                         return EE_INVALID;
    216                 }
    217 
    218                 rc = segment_header(elf, &segment_hdr);
    219                 if (rc != EE_OK)
    220                         return rc;
    221         }
    222 
    223         DPRINTF("Parse sections.\n");
    224 
    225         /* Inspect all section headers and proccess them. */
    226         for (i = 0; i < header->e_shnum; i++) {
    227                 elf_section_header_t section_hdr;
    228 
    229                 /* Seek to start of section header */
    230                 lseek(elf->fd, header->e_shoff
    231                     + i * sizeof(elf_section_header_t), SEEK_SET);
    232 
    233                 rc = read(elf->fd, &section_hdr,
    234                     sizeof(elf_section_header_t));
    235                 if (rc != sizeof(elf_section_header_t)) {
    236                         DPRINTF("Read error.\n");
    237                         return EE_INVALID;
    238                 }
    239 
    240                 rc = section_header(elf, &section_hdr);
    241                 if (rc != EE_OK)
    242                         return rc;
    243         }
    244 
    245         elf->info->entry =
    246             (entry_point_t)((uint8_t *)header->e_entry + elf->bias);
    247 
    248         DPRINTF("Done.\n");
    249 
    250         return EE_OK;
    251 }
    252 
    253 /** Print error message according to error code.
    254  *
    255  * @param rc Return code returned by elf_load().
    256  *
    257  * @return NULL terminated description of error.
    258  */
    259 const char *elf_error(unsigned int rc)
    260 {
    261         assert(rc < sizeof(error_codes) / sizeof(char *));
    262 
    263         return error_codes[rc];
    264 }
    265 
    266 /** Process segment header.
    267  *
    268  * @param entry Segment header.
    269  *
    270  * @return EE_OK on success, error code otherwise.
    271  */
    272 static int segment_header(elf_ld_t *elf, elf_segment_header_t *entry)
    273 {
    274         switch (entry->p_type) {
    275         case PT_NULL:
    276         case PT_PHDR:
    277         case PT_NOTE:
    278                 break;
    279         case PT_LOAD:
    280                 return load_segment(elf, entry);
    281                 break;
    282         case PT_INTERP:
    283                 /* Assume silently interp == "/app/dload" */
    284                 elf->info->interp = "/app/dload";
    285                 break;
    286         case PT_DYNAMIC:
    287                 /* Record pointer to dynamic section into info structure */
    288                 elf->info->dynamic =
    289                     (void *)((uint8_t *)entry->p_vaddr + elf->bias);
    290                 DPRINTF("dynamic section found at %p\n",
    291                         (void *)elf->info->dynamic);
    292                 break;
    293         case 0x70000000:
    294                 /* FIXME: MIPS reginfo */
    295                 break;
    296         case PT_SHLIB:
    297 //      case PT_LOPROC:
    298 //      case PT_HIPROC:
    299         default:
    300                 DPRINTF("Segment p_type %d unknown.\n", entry->p_type);
    301                 return EE_UNSUPPORTED;
    302                 break;
    303         }
    304         return EE_OK;
    305 }
    306 
    307 /** Load segment described by program header entry.
    308  *
    309  * @param elf   Loader state.
    310  * @param entry Program header entry describing segment to be loaded.
    311  *
    312  * @return EE_OK on success, error code otherwise.
    313  */
    314 int load_segment(elf_ld_t *elf, elf_segment_header_t *entry)
    315 {
    316         void *a;
    317         int flags = 0;
    318         uintptr_t bias;
    319         uintptr_t base;
    320         void *seg_ptr;
    321         uintptr_t seg_addr;
    322         size_t mem_sz;
    323         ssize_t rc;
    324 
    325         bias = elf->bias;
    326 
    327         seg_addr = entry->p_vaddr + bias;
    328         seg_ptr = (void *) seg_addr;
    329 
    330         DPRINTF("Load segment at addr %p, size 0x%zx\n", (void *) seg_addr,
    331                 entry->p_memsz);
    332 
    333         if (entry->p_align > 1) {
    334                 if ((entry->p_offset % entry->p_align) !=
    335                     (seg_addr % entry->p_align)) {
    336                         DPRINTF("Align check 1 failed offset%%align=0x%zx, "
    337                             "vaddr%%align=0x%zx\n",
    338                             entry->p_offset % entry->p_align,
    339                             seg_addr % entry->p_align);
    340                         return EE_INVALID;
    341                 }
    342         }
    343 
    344         /* Final flags that will be set for the memory area */
    345 
    346         if (entry->p_flags & PF_X)
    347                 flags |= AS_AREA_EXEC;
    348         if (entry->p_flags & PF_W)
    349                 flags |= AS_AREA_WRITE;
    350         if (entry->p_flags & PF_R)
    351                 flags |= AS_AREA_READ;
    352         flags |= AS_AREA_CACHEABLE;
    353        
    354         base = ALIGN_DOWN(entry->p_vaddr, PAGE_SIZE);
    355         mem_sz = entry->p_memsz + (entry->p_vaddr - base);
    356 
    357         DPRINTF("Map to seg_addr=%p-%p.\n", (void *) seg_addr,
    358             (void *) (entry->p_vaddr + bias +
    359             ALIGN_UP(entry->p_memsz, PAGE_SIZE)));
    360 
    361         /*
    362          * For the course of loading, the area needs to be readable
    363          * and writeable.
    364          */
    365         a = as_area_create((uint8_t *) base + bias, mem_sz,
    366             AS_AREA_READ | AS_AREA_WRITE | AS_AREA_CACHEABLE);
    367         if (a == AS_MAP_FAILED) {
    368                 DPRINTF("memory mapping failed (%p, %zu)\n",
    369                     (void *) (base + bias), mem_sz);
    370                 return EE_MEMORY;
    371         }
    372 
    373         DPRINTF("as_area_create(%p, %#zx, %d) -> %p\n",
    374             (void *) (base + bias), mem_sz, flags, (void *) a);
    375 
    376         /*
    377          * Load segment data
    378          */
    379         rc = lseek(elf->fd, entry->p_offset, SEEK_SET);
    380         if (rc < 0) {
    381                 printf("seek error\n");
    382                 return EE_INVALID;
    383         }
    384 
    385 /*      rc = read(fd, (void *)(entry->p_vaddr + bias), entry->p_filesz);
    386         if (rc < 0) { printf("read error\n"); return EE_INVALID; }*/
    387 
    388         /* Long reads are not possible yet. Load segment piecewise. */
    389 
    390         unsigned left, now;
    391         uint8_t *dp;
    392 
    393         left = entry->p_filesz;
    394         dp = seg_ptr;
    395 
    396         while (left > 0) {
    397                 now = 16384;
    398                 if (now > left) now = left;
    399 
    400                 rc = read(elf->fd, dp, now);
    401 
    402                 if (rc != (ssize_t) now) {
    403                         DPRINTF("Read error.\n");
    404                         return EE_INVALID;
    405                 }
    406 
    407                 left -= now;
    408                 dp += now;
    409         }
    410 
    411         /*
    412          * The caller wants to modify the segments first. He will then
    413          * need to set the right access mode and ensure SMC coherence.
    414          */
    415         if ((elf->flags & ELDF_RW) != 0) return EE_OK;
    416 
    417 //      printf("set area flags to %d\n", flags);
    418         rc = as_area_change_flags(seg_ptr, flags);
    419         if (rc != 0) {
    420                 DPRINTF("Failed to set memory area flags.\n");
    421                 return EE_MEMORY;
    422         }
    423 
    424         if (flags & AS_AREA_EXEC) {
    425                 /* Enforce SMC coherence for the segment */
    426                 if (smc_coherence(seg_ptr, entry->p_filesz))
    427                         return EE_MEMORY;
    428         }
    429 
    430         return EE_OK;
    431 }
    432 
    433 /** Process section header.
    434  *
    435  * @param elf   Loader state.
    436  * @param entry Segment header.
    437  *
    438  * @return EE_OK on success, error code otherwise.
    439  */
    440 static int section_header(elf_ld_t *elf, elf_section_header_t *entry)
    441 {
    442         switch (entry->sh_type) {
    443         case SHT_PROGBITS:
    444                 if (entry->sh_flags & SHF_TLS) {
    445                         /* .tdata */
    446                 }
    447                 break;
    448         case SHT_NOBITS:
    449                 if (entry->sh_flags & SHF_TLS) {
    450                         /* .tbss */
    451                 }
    452                 break;
    453         case SHT_DYNAMIC:
    454                 /* Record pointer to dynamic section into info structure */
    455                 elf->info->dynamic =
    456                     (void *)((uint8_t *)entry->sh_addr + elf->bias);
    457                 DPRINTF("Dynamic section found at %p.\n",
    458                     (void *) elf->info->dynamic);
    459                 break;
    460         default:
    461                 break;
    462         }
    463        
    464         return EE_OK;
     95        pcb->entry = info->finfo.entry;
     96        pcb->dynamic = info->finfo.dynamic;
     97        pcb->rtld_runtime = info->env;
    46598}
    46699
  • uspace/lib/c/generic/libc.c

    r13dfa3f9 r17341d4  
    8989        char **argv;
    9090       
    91 #ifdef __PIC__
     91#ifdef CONFIG_RTLD
    9292        if (__pcb != NULL && __pcb->rtld_runtime != NULL) {
    93                 runtime_env = (runtime_env_t *) __pcb->rtld_runtime;
     93                runtime_env = (rtld_t *) __pcb->rtld_runtime;
    9494        }
    9595#endif
  • uspace/lib/c/generic/rtld/module.c

    r13dfa3f9 r17341d4  
    9191 * path components are ignored.
    9292 */
    93 module_t *module_find(const char *name)
     93module_t *module_find(rtld_t *rtld, const char *name)
    9494{
    9595        const char *p, *soname;
     
    106106
    107107        /* Traverse list of all modules. Not extremely fast, but simple */
    108         list_foreach(runtime_env->modules, modules_link, module_t, m) {
     108        list_foreach(rtld->modules, modules_link, module_t, m) {
    109109                DPRINTF("m = %p\n", m);
    110110                if (str_cmp(m->dyn.soname, soname) == 0) {
     
    122122 * Currently this trivially tries to load '/<name>'.
    123123 */
    124 module_t *module_load(const char *name)
    125 {
    126         elf_info_t info;
     124module_t *module_load(rtld_t *rtld, const char *name)
     125{
     126        elf_finfo_t info;
    127127        char name_buf[NAME_BUF_SIZE];
    128128        module_t *m;
     
    135135        }
    136136
     137        m->rtld = rtld;
     138
    137139        if (str_size(name) > NAME_BUF_SIZE - 2) {
    138140                printf("soname too long. increase NAME_BUF_SIZE\n");
     
    145147
    146148        /* FIXME: need to real allocation of address space */
    147         m->bias = runtime_env->next_bias;
    148         runtime_env->next_bias += 0x100000;
     149        m->bias = rtld->next_bias;
     150        rtld->next_bias += 0x100000;
    149151
    150152        DPRINTF("filename:'%s'\n", name_buf);
     
    171173
    172174        /* Insert into the list of loaded modules */
    173         list_append(&m->modules_link, &runtime_env->modules);
     175        list_append(&m->modules_link, &rtld->modules);
    174176
    175177        return m;
     
    221223
    222224                        DPRINTF("%s needs %s\n", m->dyn.soname, dep_name);
    223                         dm = module_find(dep_name);
     225                        dm = module_find(m->rtld, dep_name);
    224226                        if (!dm) {
    225                                 dm = module_load(dep_name);
     227                                dm = module_load(m->rtld, dep_name);
    226228                                module_load_deps(dm);
    227229                        }
     
    241243 * @param       start   The module where to start from.
    242244 */
    243 void modules_process_relocs(module_t *start)
    244 {
    245         list_foreach(runtime_env->modules, modules_link, module_t, m) {
    246                 /* Skip rtld, since it has already been processed */
    247                 if (m != &runtime_env->rtld) {
     245void modules_process_relocs(rtld_t *rtld, module_t *start)
     246{
     247        list_foreach(rtld->modules, modules_link, module_t, m) {
     248                /* Skip rtld module, since it has already been processed */
     249                if (m != &rtld->rtld) {
    248250                        module_process_relocs(m);
    249251                }
     
    253255/** Clear BFS tags of all modules.
    254256 */
    255 void modules_untag(void)
    256 {
    257         list_foreach(runtime_env->modules, modules_link, module_t, m) {
     257void modules_untag(rtld_t *rtld)
     258{
     259        list_foreach(rtld->modules, modules_link, module_t, m) {
    258260                m->bfs_tag = false;
    259261        }
  • uspace/lib/c/generic/rtld/rtld.c

    r13dfa3f9 r17341d4  
    3535 */
    3636
     37#include <errno.h>
     38#include <rtld/module.h>
    3739#include <rtld/rtld.h>
     40#include <rtld/rtld_debug.h>
     41#include <stdlib.h>
    3842
    39 runtime_env_t *runtime_env;
    40 static runtime_env_t rt_env_static;
     43rtld_t *runtime_env;
     44static rtld_t rt_env_static;
     45static module_t prog_mod;
    4146
    42 /** Initialize the loder for use in a statically-linked binary. */
     47/** Initialize the runtime linker for use in a statically-linked executable. */
    4348void rtld_init_static(void)
    4449{
     
    4954}
    5055
     56/** Initialize and process a dynamically linked executable.
     57 *
     58 * @param p_info Program info
     59 * @return EOK on success or non-zero error code
     60 */
     61int rtld_prog_process(elf_finfo_t *p_info, rtld_t **rre)
     62{
     63        rtld_t *env;
     64
     65        DPRINTF("Load dynamically linked program.\n");
     66
     67        /* Allocate new RTLD environment to pass to the loaded program */
     68        env = calloc(1, sizeof(rtld_t));
     69        if (env == NULL)
     70                return ENOMEM;
     71
     72        /*
     73         * First we need to process dynamic sections of the executable
     74         * program and insert it into the module graph.
     75         */
     76
     77        DPRINTF("Parse program .dynamic section at %p\n", p_info->dynamic);
     78        dynamic_parse(p_info->dynamic, 0, &prog_mod.dyn);
     79        prog_mod.bias = 0;
     80        prog_mod.dyn.soname = "[program]";
     81        prog_mod.rtld = env;
     82
     83        /* Initialize list of loaded modules */
     84        list_initialize(&env->modules);
     85        list_append(&prog_mod.modules_link, &env->modules);
     86
     87        /* Pointer to program module. Used as root of the module graph. */
     88        env->program = &prog_mod;
     89
     90        /* Work around non-existent memory space allocation. */
     91        env->next_bias = 0x1000000;
     92
     93        /*
     94         * Now we can continue with loading all other modules.
     95         */
     96
     97        DPRINTF("Load all program dependencies\n");
     98        module_load_deps(&prog_mod);
     99
     100        /*
     101         * Now relocate/link all modules together.
     102         */
     103
     104        /* Process relocations in all modules */
     105        DPRINTF("Relocate all modules\n");
     106        modules_process_relocs(env, &prog_mod);
     107
     108        *rre = env;
     109        return EOK;
     110}
     111
    51112/** @}
    52113 */
  • uspace/lib/c/generic/rtld/symbol.c

    r13dfa3f9 r17341d4  
    3939
    4040#include <elf/elf.h>
     41#include <rtld/module.h>
    4142#include <rtld/rtld.h>
    4243#include <rtld/rtld_debug.h>
     
    132133
    133134        /* Mark all vertices (modules) as unvisited */ 
    134         modules_untag();
     135        modules_untag(start->rtld);
    135136
    136137        /* Insert root (the program) into the queue and tag it */
     
    219220        /* Not DT_SYMBOLIC or no match. Now try other locations. */
    220221
    221         if (runtime_env->program) {
     222        if (origin->rtld->program) {
    222223                /* Program is dynamic -- start with program as root. */
    223                 return symbol_bfs_find(name, runtime_env->program, flags, mod);
     224                return symbol_bfs_find(name, origin->rtld->program, flags, mod);
    224225        } else {
    225226                /* Program is static -- start with @a origin as root. */
  • uspace/lib/c/include/elf/elf_load.h

    r13dfa3f9 r17341d4  
    11/*
    2  * Copyright (c) 2006 Sergey Bondari
    3  * Copyright (c) 2008 Jiri Svoboda
     2 * Copyright (c) 2016 Jiri Svoboda
    43 * All rights reserved.
    54 *
     
    3231 */
    3332/** @file
    34  * @brief ELF loader structures and public functions.
     33 * @brief
    3534 */
    3635
     
    3837#define ELF_LOAD_H_
    3938
    40 #include <elf/elf.h>
    41 #include <sys/types.h>
    42 #include <loader/pcb.h>
     39#include <elf/elf_mod.h>
     40#include <rtld/rtld.h>
    4341
    44 /**
    45  * ELF error return codes
    46  */
    47 #define EE_OK                   0       /* No error */
    48 #define EE_INVALID              1       /* Invalid ELF image */
    49 #define EE_MEMORY               2       /* Cannot allocate address space */
    50 #define EE_INCOMPATIBLE         3       /* ELF image is not compatible with current architecture */
    51 #define EE_UNSUPPORTED          4       /* Non-supported ELF (e.g. dynamic ELFs) */
    52 #define EE_LOADER               5       /* The image is actually a program loader. */
    53 #define EE_IRRECOVERABLE        6
    54 
    55 typedef enum {
    56         /** Leave all segments in RW access mode. */
    57         ELDF_RW = 1
    58 } eld_flags_t;
    59 
    60 /**
    61  * Some data extracted from the headers are stored here
    62  */
     42/** Information on loaded ELF program */
    6343typedef struct {
    64         /** Entry point */
    65         entry_point_t entry;
    66 
    67         /** ELF interpreter name or NULL if statically-linked */
    68         const char *interp;
    69 
    70         /** Pointer to the dynamic section */
    71         void *dynamic;
     44        elf_finfo_t finfo;
     45        rtld_t *env;
    7246} elf_info_t;
    7347
    74 /**
    75  * Holds information about an ELF binary being loaded.
    76  */
    77 typedef struct {
    78         /** Filedescriptor of the file from which we are loading */
    79         int fd;
    80 
    81         /** Difference between run-time addresses and link-time addresses */
    82         uintptr_t bias;
    83 
    84         /** Flags passed to the ELF loader. */
    85         eld_flags_t flags;
    86 
    87         /** A copy of the ELF file header */
    88         elf_header_t *header;
    89 
    90         /** Store extracted info here */
    91         elf_info_t *info;
    92 } elf_ld_t;
    93 
    94 extern const char *elf_error(unsigned int);
    95 extern int elf_load_file(const char *, size_t, eld_flags_t, elf_info_t *);
    96 extern void elf_create_pcb(elf_info_t *, pcb_t *);
     48extern int elf_load(const char *, elf_info_t *);
     49extern void elf_set_pcb(elf_info_t *, pcb_t *);
    9750
    9851#endif
  • uspace/lib/c/include/loader/pcb.h

    r13dfa3f9 r17341d4  
    6969        /** Pointer to ELF dynamic section of the program. */
    7070        void *dynamic;
    71         /** Pointer to dynamic linker state structure (runtime_env_t). */
     71        /** Pointer to dynamic linker state structure (rtld_t). */
    7272        void *rtld_runtime;
    7373} pcb_t;
  • uspace/lib/c/include/rtld/module.h

    r13dfa3f9 r17341d4  
    3939#include <rtld/dynamic.h>
    4040#include <adt/list.h>
     41#include <types/rtld/module.h>
     42#include <types/rtld/rtld.h>
    4143
    42 typedef struct module {
    43         dyn_info_t dyn;
    44         size_t bias;
     44extern void module_process_relocs(module_t *);
     45extern module_t *module_find(rtld_t *, const char *);
     46extern module_t *module_load(rtld_t *, const char *);
     47extern void module_load_deps(module_t *);
    4548
    46         /** Array of pointers to directly dependent modules */
    47         struct module **deps;
    48         /** Number of fields in deps */
    49         size_t n_deps;
    50 
    51         /** True iff relocations have already been processed in this module. */
    52         bool relocated;
    53 
    54         /** Link to list of all modules in runtime environment */
    55         link_t modules_link;
    56 
    57         /** Link to BFS queue. Only used when doing a BFS of the module graph */
    58         link_t queue_link;
    59         /** Tag for modules already processed during a BFS */
    60         bool bfs_tag;
    61 } module_t;
    62 
    63 void module_process_relocs(module_t *m);
    64 module_t *module_find(const char *name);
    65 module_t *module_load(const char *name);
    66 void module_load_deps(module_t *m);
    67 
    68 void modules_process_relocs(module_t *start);
    69 void modules_untag(void);
     49extern void modules_process_relocs(rtld_t *, module_t *);
     50extern void modules_untag(rtld_t *);
    7051
    7152#endif
  • uspace/lib/c/include/rtld/rtld.h

    r13dfa3f9 r17341d4  
    3636#define LIBC_RTLD_H_
    3737
     38#include <adt/list.h>
     39#include <elf/elf_mod.h>
    3840#include <sys/types.h>
    39 #include <adt/list.h>
    4041
    4142#include <rtld/dynamic.h>
    42 #include <rtld/module.h>
     43#include <types/rtld/rtld.h>
    4344
    44 typedef struct {
    45         elf_dyn_t *rtld_dynamic;
    46         module_t rtld;
    47 
    48         module_t *program;
    49 
    50         /** List of all loaded modules including rtld and the program */
    51         list_t modules;
    52 
    53         /** Temporary hack to place each module at different address. */
    54         uintptr_t next_bias;
    55 } runtime_env_t;
    56 
    57 extern runtime_env_t *runtime_env;
     45extern rtld_t *runtime_env;
    5846
    5947extern void rtld_init_static(void);
     48extern int rtld_prog_process(elf_finfo_t *, rtld_t **);
    6049
    6150#endif
  • uspace/lib/c/include/rtld/rtld_debug.h

    r13dfa3f9 r17341d4  
    3636#define LIBC_RTLD_RTLD_DEBUG_H_
    3737
     38#include <stdio.h>
     39
    3840/* Define to enable debugging mode. */
    3941#undef RTLD_DEBUG
  • uspace/srv/loader/main.c

    r13dfa3f9 r17341d4  
    6363#include <vfs/vfs.h>
    6464
    65 #ifdef CONFIG_RTLD
    66 #include <rtld/rtld.h>
    67 #include <rtld/dynamic.h>
    68 #include <rtld/module.h>
    69 
    70 static int ldr_load_dyn_linked(elf_info_t *p_info);
    71 #endif
    72 
    7365#define DPRINTF(...)
    7466
     
    9688/** Used to limit number of connections to one. */
    9789static bool connected = false;
    98 
    99 #ifdef CONFIG_RTLD
    100 /** State structure of the dynamic linker. */
    101 runtime_env_t dload_re;
    102 static module_t prog_mod;
    103 #endif
    10490
    10591static void ldr_get_taskid(ipc_callid_t rid, ipc_call_t *request)
     
    268254        int rc;
    269255       
    270         rc = elf_load_file(pathname, 0, 0, &prog_info);
     256        rc = elf_load(pathname, &prog_info);
    271257        if (rc != EE_OK) {
    272258                DPRINTF("Failed to load executable '%s'.\n", pathname);
     
    275261        }
    276262       
    277         elf_create_pcb(&prog_info, &pcb);
     263        elf_set_pcb(&prog_info, &pcb);
    278264       
    279265        pcb.cwd = cwd;
     
    283269       
    284270        pcb.filc = filc;
    285        
    286         if (prog_info.interp == NULL) {
    287                 /* Statically linked program */
    288                 async_answer_0(rid, EOK);
    289                 return 0;
    290         }
    291        
    292         DPRINTF("Binary is dynamically linked.\n");
    293 #ifdef CONFIG_RTLD
    294         DPRINTF(" - pcb address: %p\n", &pcb);
    295         DPRINTF( "- prog dynamic: %p\n", prog_info.dynamic);
    296 
    297         rc = ldr_load_dyn_linked(&prog_info);
    298 #else
    299         rc = ENOTSUP;
    300 #endif
     271        printf("dynamic=%p rtld_env=%p\n", pcb.dynamic, pcb.rtld_runtime);
     272       
    301273        async_answer_0(rid, rc);
    302274        return 0;
    303275}
    304 
    305 #ifdef CONFIG_RTLD
    306 
    307 static int ldr_load_dyn_linked(elf_info_t *p_info)
    308 {
    309         runtime_env = &dload_re;
    310 
    311         DPRINTF("Load dynamically linked program.\n");
    312 
    313         /*
    314          * First we need to process dynamic sections of the executable
    315          * program and insert it into the module graph.
    316          */
    317 
    318         DPRINTF("Parse program .dynamic section at %p\n", p_info->dynamic);
    319         dynamic_parse(p_info->dynamic, 0, &prog_mod.dyn);
    320         prog_mod.bias = 0;
    321         prog_mod.dyn.soname = "[program]";
    322 
    323         /* Initialize list of loaded modules */
    324         list_initialize(&runtime_env->modules);
    325         list_append(&prog_mod.modules_link, &runtime_env->modules);
    326 
    327         /* Pointer to program module. Used as root of the module graph. */
    328         runtime_env->program = &prog_mod;
    329 
    330         /* Work around non-existent memory space allocation. */
    331         runtime_env->next_bias = 0x1000000;
    332 
    333         /*
    334          * Now we can continue with loading all other modules.
    335          */
    336 
    337         DPRINTF("Load all program dependencies\n");
    338         module_load_deps(&prog_mod);
    339 
    340         /*
    341          * Now relocate/link all modules together.
    342          */
    343 
    344         /* Process relocations in all modules */
    345         DPRINTF("Relocate all modules\n");
    346         modules_process_relocs(&prog_mod);
    347 
    348         /* Pass runtime evironment pointer through PCB. */
    349         pcb.rtld_runtime = (void *) runtime_env;
    350 
    351         return 0;
    352 }
    353 #endif
    354276
    355277/** Run the previously loaded program.
     
    374296        async_answer_0(rid, EOK);
    375297        DPRINTF("Jump to entry point at %p\n", pcb.entry);
    376         entry_point_jmp(prog_info.entry, &pcb);
     298        entry_point_jmp(prog_info.finfo.entry, &pcb);
    377299       
    378300        /* Not reached */
Note: See TracChangeset for help on using the changeset viewer.