Changeset 7465910 in mainline


Ignore:
Timestamp:
2018-05-01T17:46:56Z (6 years ago)
Author:
Jiří Zárevúcky <jiri.zarevucky@…>
Parents:
9e5cc73
git-author:
Jiří Zárevúcky <jiri.zarevucky@…> (2018-05-01 17:31:49)
git-committer:
Jiří Zárevúcky <jiri.zarevucky@…> (2018-05-01 17:46:56)
Message:

Make some effort to allocate the memory area for shared objects.

Location:
uspace/lib/c
Files:
6 edited

Legend:

Unmodified
Added
Removed
  • uspace/lib/c/generic/elf/elf_load.c

    r9e5cc73 r7465910  
    6262        int rc;
    6363
    64         rc = elf_load_file(file, 0, 0, &info->finfo);
     64        rc = elf_load_file(file, 0, &info->finfo);
    6565        if (rc != EE_OK) {
    6666                DPRINTF("Failed to load executable '%s'.\n", file_name);
  • uspace/lib/c/generic/elf/elf_mod.c

    r9e5cc73 r7465910  
    5858#include <str_error.h>
    5959#include <stdlib.h>
     60#include <macros.h>
    6061
    6162#include <elf/elf_load.h>
     
    7374};
    7475
    75 static unsigned int elf_load_module(elf_ld_t *elf, size_t so_bias);
     76static unsigned int elf_load_module(elf_ld_t *elf);
    7677static int segment_header(elf_ld_t *elf, elf_segment_header_t *entry);
    7778static int load_segment(elf_ld_t *elf, elf_segment_header_t *entry);
     
    8687 *
    8788 * @param file      ELF file.
    88  * @param so_bias   Bias to use if the file is a shared object.
    8989 * @param info      Pointer to a structure for storing information
    9090 *                  extracted from the binary.
     
    9393 *
    9494 */
    95 int elf_load_file(int file, size_t so_bias, eld_flags_t flags, elf_finfo_t *info)
     95int elf_load_file(int file, eld_flags_t flags, elf_finfo_t *info)
    9696{
    9797        elf_ld_t elf;
     
    110110        elf.flags = flags;
    111111
    112         int ret = elf_load_module(&elf, so_bias);
     112        int ret = elf_load_module(&elf);
    113113
    114114        vfs_put(ofile);
     
    116116}
    117117
    118 int elf_load_file_name(const char *path, size_t so_bias, eld_flags_t flags,
    119     elf_finfo_t *info)
     118int elf_load_file_name(const char *path, eld_flags_t flags, elf_finfo_t *info)
    120119{
    121120        int file;
    122121        errno_t rc = vfs_lookup(path, 0, &file);
    123122        if (rc == EOK) {
    124                 int ret = elf_load_file(file, so_bias, flags, info);
     123                int ret = elf_load_file(file, flags, info);
    125124                vfs_put(file);
    126125                return ret;
     
    137136 *
    138137 * @param elf           Pointer to loader state buffer.
    139  * @param so_bias       Bias to use if the file is a shared object.
    140138 * @return EE_OK on success or EE_xx error code.
    141139 */
    142 static unsigned int elf_load_module(elf_ld_t *elf, size_t so_bias)
     140static unsigned int elf_load_module(elf_ld_t *elf)
    143141{
    144142        elf_header_t header_buf;
     
    154152                return EE_IO;
    155153        }
    156 
    157         elf->header = header;
    158154
    159155        /* Identify ELF */
     
    188184        }
    189185
     186        if (header->e_phoff == 0) {
     187                DPRINTF("Program header table is not present!\n");
     188                return EE_UNSUPPORTED;
     189        }
     190
     191        /* Read program header table.
     192         * Normally, there are very few program headers, so don't bother
     193         * with allocating memory dynamically.
     194         */
     195        const int phdr_cap = 16;
     196        elf_segment_header_t phdr[phdr_cap];
     197        size_t phdr_len = header->e_phnum * header->e_phentsize;
     198
     199        if (phdr_len > sizeof(phdr)) {
     200                DPRINTF("more than %d program headers\n", phdr_cap);
     201                return EE_UNSUPPORTED;
     202        }
     203
     204        pos = header->e_phoff;
     205        rc = vfs_read(elf->fd, &pos, phdr, phdr_len, &nr);
     206        if (rc != EOK || nr != phdr_len) {
     207                DPRINTF("Read error.\n");
     208                return EE_IO;
     209        }
     210
     211        uintptr_t module_base = UINTPTR_MAX;
     212        uintptr_t module_top = 0;
     213        uintptr_t base_offset = UINTPTR_MAX;
     214
     215        /* Walk through PT_LOAD headers, to find out the size of the module. */
     216        for (i = 0; i < header->e_phnum; i++) {
     217                if (phdr[i].p_type != PT_LOAD)
     218                        continue;
     219
     220                if (module_base > phdr[i].p_vaddr) {
     221                        module_base = phdr[i].p_vaddr;
     222                        base_offset = phdr[i].p_offset;
     223                }
     224                module_top = max(module_top, phdr[i].p_vaddr + phdr[i].p_memsz);
     225        }
     226
     227        if (base_offset != 0) {
     228                DPRINTF("ELF headers not present in the text segment.\n");
     229                return EE_INVALID;
     230        }
     231
    190232        /* Shared objects can be loaded with a bias */
    191         if (header->e_type == ET_DYN)
    192                 elf->bias = so_bias;
    193         else
     233        if (header->e_type != ET_DYN) {
    194234                elf->bias = 0;
     235        } else {
     236                if (module_base != 0) {
     237                        DPRINTF("Unexpected shared object format.\n");
     238                        return EE_INVALID;
     239                }
     240
     241                /* Attempt to allocate a span of memory large enough for the
     242                 * shared object.
     243                 */
     244                // FIXME: This is not reliable when we're running
     245                //        multi-threaded. Even if this part succeeds, later
     246                //        allocation can fail because another thread took the
     247                //        space in the meantime. This is only relevant for
     248                //        dlopen() though.
     249                void *area = as_area_create(AS_AREA_ANY, module_top,
     250                    AS_AREA_READ | AS_AREA_WRITE | AS_AREA_CACHEABLE |
     251                    AS_AREA_LATE_RESERVE, AS_AREA_UNPAGED);
     252
     253                if (area == AS_MAP_FAILED) {
     254                        DPRINTF("Can't find suitable memory area.\n");
     255                        return EE_MEMORY;
     256                }
     257
     258                elf->bias = (uintptr_t) area;
     259                as_area_destroy(area);
     260        }
     261
     262        /* Load all loadable segments. */
     263        for (i = 0; i < header->e_phnum; i++) {
     264                if (phdr[i].p_type != PT_LOAD)
     265                        continue;
     266
     267                ret = load_segment(elf, &phdr[i]);
     268                if (ret != EE_OK)
     269                        return ret;
     270        }
     271
     272        void *base = (void *) module_base + elf->bias;
     273        elf->info->base = base;
    195274
    196275        /* Ensure valid TLS info even if there is no TLS header. */
     
    205284        /* Walk through all segment headers and process them. */
    206285        for (i = 0; i < header->e_phnum; i++) {
    207                 elf_segment_header_t segment_hdr;
    208 
    209                 pos = header->e_phoff + i * sizeof(elf_segment_header_t);
    210                 rc = vfs_read(elf->fd, &pos, &segment_hdr,
    211                     sizeof(elf_segment_header_t), &nr);
    212                 if (rc != EOK || nr != sizeof(elf_segment_header_t)) {
    213                         DPRINTF("Read error.\n");
    214                         return EE_IO;
    215                 }
    216 
    217                 ret = segment_header(elf, &segment_hdr);
     286                if (phdr[i].p_type == PT_LOAD)
     287                        continue;
     288
     289                ret = segment_header(elf, &phdr[i]);
    218290                if (ret != EE_OK)
    219291                        return ret;
     
    270342        case PT_NOTE:
    271343                break;
    272         case PT_LOAD:
    273                 return load_segment(elf, entry);
    274                 break;
    275344        case PT_INTERP:
    276345                elf->info->interp =
    277346                    (void *)((uint8_t *)entry->p_vaddr + elf->bias);
    278347
    279                 // FIXME: This actually won't work, because the text segment is
    280                 // not loaded yet.
    281 #if 0
    282348                if (elf->info->interp[entry->p_filesz - 1] != '\0') {
    283349                        DPRINTF("Unterminated ELF interp string.\n");
     
    285351                }
    286352                DPRINTF("interpreter: \"%s\"\n", elf->info->interp);
    287 #endif
    288353                break;
    289354        case PT_DYNAMIC:
  • uspace/lib/c/generic/rtld/module.c

    r9e5cc73 r7465910  
    202202        str_cpy(name_buf + 5, NAME_BUF_SIZE - 5, name);
    203203
    204         /* FIXME: need to real allocation of address space */
    205         m->bias = rtld->next_bias;
    206         rtld->next_bias += 0x100000;
    207204
    208205        DPRINTF("filename:'%s'\n", name_buf);
    209         DPRINTF("load '%s' at 0x%zx\n", name_buf, m->bias);
    210 
    211         rc = elf_load_file_name(name_buf, m->bias, ELDF_RW, &info);
     206
     207        rc = elf_load_file_name(name_buf, ELDF_RW, &info);
    212208        if (rc != EE_OK) {
    213209                printf("Failed to load '%s'\n", name_buf);
    214210                exit(1);
    215211        }
     212
     213        m->bias = elf_get_bias(info.base);
     214
     215        DPRINTF("loaded '%s' at 0x%zx\n", name_buf, m->bias);
    216216
    217217        if (info.dynamic == NULL) {
  • uspace/lib/c/generic/rtld/rtld.c

    r9e5cc73 r7465910  
    5353        list_initialize(&runtime_env->modules);
    5454        list_initialize(&runtime_env->imodules);
    55         runtime_env->next_bias = 0x2000000;
    5655        runtime_env->program = NULL;
    5756        runtime_env->next_id = 1;
     
    121120        env->program = prog;
    122121
    123         /* Work around non-existent memory space allocation. */
    124         env->next_bias = 0x1000000;
    125 
    126122        /*
    127123         * Now we can continue with loading all other modules.
  • uspace/lib/c/include/elf/elf_mod.h

    r9e5cc73 r7465910  
    7878        entry_point_t entry;
    7979
     80        /** The base address where the file has been loaded.
     81         *  Points to the ELF file header.
     82         */
     83        void *base;
     84
    8085        /** ELF interpreter name or NULL if statically-linked */
    8186        const char *interp;
     
    101106        eld_flags_t flags;
    102107
    103         /** A copy of the ELF file header */
    104         elf_header_t *header;
    105 
    106108        /** Store extracted info here */
    107109        elf_finfo_t *info;
     
    109111
    110112extern const char *elf_error(unsigned int);
    111 extern int elf_load_file(int, size_t, eld_flags_t, elf_finfo_t *);
    112 extern int elf_load_file_name(const char *, size_t, eld_flags_t, elf_finfo_t *);
     113extern int elf_load_file(int, eld_flags_t, elf_finfo_t *);
     114extern int elf_load_file_name(const char *, eld_flags_t, elf_finfo_t *);
    113115
    114116#endif
  • uspace/lib/c/include/types/rtld/rtld.h

    r9e5cc73 r7465910  
    6161        /** List of initial modules */
    6262        list_t imodules;
    63 
    64         /** Temporary hack to place each module at different address. */
    65         uintptr_t next_bias;
    6663} rtld_t;
    6764
Note: See TracChangeset for help on using the changeset viewer.