Changeset 64d38cd in mainline


Ignore:
Timestamp:
2018-04-30T20:09:49Z (6 years ago)
Author:
Jiří Zárevúcky <jiri.zarevucky@…>
Children:
40d3604
Parents:
4c5f04f
Message:

Make some effort to allocate space for libraries.

Location:
uspace/lib/c
Files:
15 edited

Legend:

Unmodified
Added
Removed
  • uspace/lib/c/arch/abs32le/_link.ld.in

    r4c5f04f r64d38cd  
    99
    1010SECTIONS {
     11#ifdef SHLIB
     12        . = SEGMENT_START("text-segment", 0);
     13#else
    1114        . = SEGMENT_START("text-segment", 0x400000);
    12 #ifndef SHLIB
    1315        PROVIDE (__executable_start = .);
    1416#endif
  • uspace/lib/c/arch/amd64/_link.ld.in

    r4c5f04f r64d38cd  
    1010
    1111SECTIONS {
     12#ifdef SHLIB
     13        . = SEGMENT_START("text-segment", 0);
     14#else
    1215        . = SEGMENT_START("text-segment", 0x400000);
    13 #ifndef SHLIB
    1416        PROVIDE (__executable_start = .);
    1517#endif
  • uspace/lib/c/arch/arm32/_link.ld.in

    r4c5f04f r64d38cd  
    99
    1010SECTIONS {
     11#ifdef SHLIB
     12        . = SEGMENT_START("text-segment", 0);
     13#else
    1114        . = SEGMENT_START("text-segment", 0x400000);
    12 #ifndef SHLIB
    1315        PROVIDE (__executable_start = .);
    1416#endif
  • uspace/lib/c/arch/ia32/_link.ld.in

    r4c5f04f r64d38cd  
    1818
    1919SECTIONS {
     20#ifdef SHLIB
     21        . = SEGMENT_START("text-segment", 0);
     22#else
    2023        . = SEGMENT_START("text-segment", 0x400000);
    21 #ifndef SHLIB
    2224        PROVIDE (__executable_start = .);
    2325#endif
  • uspace/lib/c/arch/ia64/_link.ld.in

    r4c5f04f r64d38cd  
    99
    1010SECTIONS {
     11#ifdef SHLIB
     12        . = SEGMENT_START("text-segment", 0);
     13#else
    1114        . = SEGMENT_START("text-segment", 0x400000);
    12 #ifndef SHLIB
    1315        PROVIDE (__executable_start = .);
    1416#endif
  • uspace/lib/c/arch/mips32/_link.ld.in

    r4c5f04f r64d38cd  
    99
    1010SECTIONS {
     11#ifdef SHLIB
     12        . = SEGMENT_START("text-segment", 0);
     13#else
    1114        . = SEGMENT_START("text-segment", 0x400000);
    12 #ifndef SHLIB
    1315        PROVIDE (__executable_start = .);
    1416#endif
  • uspace/lib/c/arch/ppc32/_link.ld.in

    r4c5f04f r64d38cd  
    1010
    1111SECTIONS {
     12#ifdef SHLIB
     13        . = SEGMENT_START("text-segment", 0);
     14#else
    1215        . = SEGMENT_START("text-segment", 0x400000);
    13 #ifndef SHLIB
    1416        PROVIDE (__executable_start = .);
    1517#endif
  • uspace/lib/c/arch/riscv64/_link.ld.in

    r4c5f04f r64d38cd  
    1010
    1111SECTIONS {
     12#ifdef SHLIB
     13        . = SEGMENT_START("text-segment", 0);
     14#else
    1215        . = SEGMENT_START("text-segment", 0x400000);
    13 #ifndef SHLIB
    1416        PROVIDE (__executable_start = .);
    1517#endif
  • uspace/lib/c/arch/sparc64/_link.ld.in

    r4c5f04f r64d38cd  
    1010
    1111SECTIONS {
     12#ifdef SHLIB
     13        . = SEGMENT_START("text-segment", 0);
     14#else
    1215        . = SEGMENT_START("text-segment", 0x400000);
    13 #ifndef SHLIB
    1416        PROVIDE (__executable_start = .);
    1517#endif
  • uspace/lib/c/generic/elf/elf_load.c

    r4c5f04f r64d38cd  
    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

    r4c5f04f r64d38cd  
    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);
    76 static int segment_header(elf_ld_t *elf, elf_segment_header_t *entry);
     76static unsigned int elf_load_module(elf_ld_t *elf);
    7777static int load_segment(elf_ld_t *elf, elf_segment_header_t *entry);
    7878
     
    8686 *
    8787 * @param file      ELF file.
    88  * @param so_bias   Bias to use if the file is a shared object.
    8988 * @param info      Pointer to a structure for storing information
    9089 *                  extracted from the binary.
     
    9392 *
    9493 */
    95 int elf_load_file(int file, size_t so_bias, eld_flags_t flags, elf_finfo_t *info)
     94int elf_load_file(int file, eld_flags_t flags, elf_finfo_t *info)
    9695{
    9796        elf_ld_t elf;
     
    110109        elf.flags = flags;
    111110
    112         int ret = elf_load_module(&elf, so_bias);
     111        int ret = elf_load_module(&elf);
    113112
    114113        vfs_put(ofile);
     
    116115}
    117116
    118 int elf_load_file_name(const char *path, size_t so_bias, eld_flags_t flags,
    119     elf_finfo_t *info)
     117int elf_load_file_name(const char *path, eld_flags_t flags, elf_finfo_t *info)
    120118{
    121119        int file;
    122120        errno_t rc = vfs_lookup(path, 0, &file);
    123121        if (rc == EOK) {
    124                 int ret = elf_load_file(file, so_bias, flags, info);
     122                int ret = elf_load_file(file, flags, info);
    125123                vfs_put(file);
    126124                return ret;
     
    130128}
    131129
     130/** Process TLS program header.
     131 *
     132 * @param elf  Pointer to loader state buffer.
     133 * @param hdr  TLS program header
     134 * @param info Place to store TLS info
     135 */
     136static void tls_program_header(void *base, elf_tls_info_t *info)
     137{
     138        const elf_segment_header_t *tls = elf_get_phdr(base, PT_TLS);
     139        size_t bias = elf_get_bias(base);
     140
     141        if (tls == NULL) {
     142                /* Ensure valid TLS info even if there is no TLS header. */
     143                info->tdata = NULL;
     144                info->tdata_size = 0;
     145                info->tbss_size = 0;
     146                info->tls_align = 1;
     147        } else {
     148                info->tdata = (void *) tls->p_vaddr + bias;
     149                info->tdata_size = tls->p_filesz;
     150                info->tbss_size = tls->p_memsz - tls->p_filesz;
     151                info->tls_align = tls->p_align;
     152        }
     153}
     154
    132155/** Load an ELF binary.
    133156 *
     
    137160 *
    138161 * @param elf           Pointer to loader state buffer.
    139  * @param so_bias       Bias to use if the file is a shared object.
    140162 * @return EE_OK on success or EE_xx error code.
    141163 */
    142 static unsigned int elf_load_module(elf_ld_t *elf, size_t so_bias)
     164static unsigned int elf_load_module(elf_ld_t *elf)
    143165{
    144166        elf_header_t header_buf;
     
    154176                return EE_IO;
    155177        }
    156 
    157         elf->header = header;
    158178
    159179        /* Identify ELF */
     
    188208        }
    189209
     210        if (header->e_phoff == 0) {
     211                DPRINTF("Program header table is not present!\n");
     212                return EE_INCOMPATIBLE;
     213        }
     214
     215        /* Read program header table.
     216         * Normally, there is very few program headers, so don't bother
     217         * with allocating memory dynamically.
     218         */
     219        const int phdr_cap = 16;
     220        elf_segment_header_t phdr[phdr_cap];
     221        size_t phdr_len = header->e_phnum * header->e_phentsize;
     222
     223        if (phdr_len > sizeof(phdr)) {
     224                DPRINTF("more than %d program headers\n", phdr_cap);
     225                return EE_UNSUPPORTED;
     226        }
     227
     228        pos = header->e_phoff;
     229        rc = vfs_read(elf->fd, &pos, phdr, phdr_len, &nr);
     230        if (rc != EOK || nr != phdr_len) {
     231                DPRINTF("Read error.\n");
     232                return EE_IO;
     233        }
     234
     235        uintptr_t module_base = UINTPTR_MAX;
     236        uintptr_t module_top = 0;
     237        uintptr_t base_offset = UINTPTR_MAX;
     238
     239        /* Walk through PT_LOAD headers, to find out the size of the module. */
     240        for (i = 0; i < header->e_phnum; i++) {
     241                if (phdr[i].p_type != PT_LOAD)
     242                        continue;
     243
     244                if (module_base > phdr[i].p_vaddr) {
     245                        module_base = phdr[i].p_vaddr;
     246                        base_offset = phdr[i].p_offset;
     247                }
     248                module_top = max(module_top, phdr[i].p_vaddr + phdr[i].p_memsz);
     249        }
     250
     251        if (base_offset != 0) {
     252                DPRINTF("ELF headers not present in the text segment.\n");
     253                return EE_INVALID;
     254        }
     255
    190256        /* Shared objects can be loaded with a bias */
    191         if (header->e_type == ET_DYN)
    192                 elf->bias = so_bias;
    193         else
     257        if (header->e_type != ET_DYN) {
    194258                elf->bias = 0;
    195 
    196         /* Ensure valid TLS info even if there is no TLS header. */
    197         elf->info->tls.tdata = NULL;
    198         elf->info->tls.tdata_size = 0;
    199         elf->info->tls.tbss_size = 0;
    200         elf->info->tls.tls_align = 1;
    201 
    202         elf->info->interp = NULL;
    203         elf->info->dynamic = NULL;
    204 
    205         /* Walk through all segment headers and process them. */
     259        } else {
     260                if (module_base != 0) {
     261                        DPRINTF("Unexpected shared object format.\n");
     262                        return EE_INVALID;
     263                }
     264
     265                /* Attempt to allocate a span of memory large enough for the
     266                 * shared object.
     267                 */
     268                // FIXME: This is not reliable when we're running
     269                //        multi-threaded. Even if this part succeeds, later
     270                //        allocation can fail because another thread took the
     271                //        space in the meantime. This is only relevant for
     272                //        dlopen() though.
     273                void *area = as_area_create(AS_AREA_ANY, module_top,
     274                    AS_AREA_READ | AS_AREA_WRITE | AS_AREA_CACHEABLE |
     275                    AS_AREA_LATE_RESERVE, AS_AREA_UNPAGED);
     276
     277                if (area == AS_MAP_FAILED) {
     278                        DPRINTF("Can't find suitable memory area.\n");
     279                        return EE_MEMORY;
     280                }
     281
     282                elf->bias = (uintptr_t) area;
     283                as_area_destroy(area);
     284        }
     285
     286        /* Load all loadable segments. */
    206287        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);
     288                if (phdr[i].p_type != PT_LOAD)
     289                        continue;
     290
     291                ret = load_segment(elf, &phdr[i]);
    218292                if (ret != EE_OK)
    219293                        return ret;
    220294        }
    221295
     296        void *base = (void *) module_base + elf->bias;
     297        elf->info->base = base;
     298
     299        /* Handle TLS. */
     300        tls_program_header(base, &elf->info->tls);
     301
     302        /* Handle PT_INTERP. */
     303
     304        const elf_segment_header_t *interphdr = elf_get_phdr(base, PT_INTERP);
     305
     306        if (interphdr == NULL) {
     307                interphdr = NULL;
     308        } else {
     309                elf->info->interp =
     310                    (const char *) (interphdr->p_vaddr + elf->bias);
     311                if (elf->info->interp[interphdr->p_filesz - 1] != '\0') {
     312                        DPRINTF("Unterminated ELF interp string.\n");
     313                        elf->info->interp = NULL;
     314                } else {
     315                        DPRINTF("interpreter: \"%s\"\n", elf->info->interp);
     316                }
     317        }
     318
     319        /* Handle PT_DYNAMIC. */
     320
     321        const elf_segment_header_t *dynphdr = elf_get_phdr(base, PT_DYNAMIC);
     322
     323        if (dynphdr == NULL) {
     324                elf->info->dynamic = NULL;
     325        } else {
     326                /* Record pointer to dynamic section into info structure */
     327                elf->info->dynamic = (void *) (dynphdr->p_vaddr + elf->bias);
     328                DPRINTF("dynamic section found at %p\n",
     329                    (void *)elf->info->dynamic);
     330        }
     331
    222332        elf->info->entry =
    223333            (entry_point_t)((uint8_t *)header->e_entry + elf->bias);
     
    239349
    240350        return error_codes[rc];
    241 }
    242 
    243 /** Process TLS program header.
    244  *
    245  * @param elf  Pointer to loader state buffer.
    246  * @param hdr  TLS program header
    247  * @param info Place to store TLS info
    248  */
    249 static void tls_program_header(elf_ld_t *elf, elf_segment_header_t *hdr,
    250     elf_tls_info_t *info)
    251 {
    252         info->tdata = (void *)((uint8_t *)hdr->p_vaddr + elf->bias);
    253         info->tdata_size = hdr->p_filesz;
    254         info->tbss_size = hdr->p_memsz - hdr->p_filesz;
    255         info->tls_align = hdr->p_align;
    256 }
    257 
    258 /** Process segment header.
    259  *
    260  * @param elf   Pointer to loader state buffer.
    261  * @param entry Segment header.
    262  *
    263  * @return EE_OK on success, error code otherwise.
    264  */
    265 static int segment_header(elf_ld_t *elf, elf_segment_header_t *entry)
    266 {
    267         switch (entry->p_type) {
    268         case PT_NULL:
    269         case PT_PHDR:
    270         case PT_NOTE:
    271                 break;
    272         case PT_LOAD:
    273                 return load_segment(elf, entry);
    274                 break;
    275         case PT_INTERP:
    276                 elf->info->interp =
    277                     (void *)((uint8_t *)entry->p_vaddr + elf->bias);
    278 
    279                 // FIXME: This actually won't work, because the text segment is
    280                 // not loaded yet.
    281 #if 0
    282                 if (elf->info->interp[entry->p_filesz - 1] != '\0') {
    283                         DPRINTF("Unterminated ELF interp string.\n");
    284                         return EE_INVALID;
    285                 }
    286                 DPRINTF("interpreter: \"%s\"\n", elf->info->interp);
    287 #endif
    288                 break;
    289         case PT_DYNAMIC:
    290                 /* Record pointer to dynamic section into info structure */
    291                 elf->info->dynamic =
    292                     (void *)((uint8_t *)entry->p_vaddr + elf->bias);
    293                 DPRINTF("dynamic section found at %p\n",
    294                     (void *)elf->info->dynamic);
    295                 break;
    296         case 0x70000000:
    297         case 0x70000001:
    298         case 0x70000002:
    299         case 0x70000003:
    300                 // FIXME: Architecture-specific headers.
    301                 /* PT_MIPS_REGINFO, PT_MIPS_ABIFLAGS, PT_ARM_UNWIND, ... */
    302                 break;
    303         case PT_TLS:
    304                 /* Parse TLS program header */
    305                 tls_program_header(elf, entry, &elf->info->tls);
    306                 DPRINTF("TLS header found at %p\n",
    307                     (void *)((uint8_t *)entry->p_vaddr + elf->bias));
    308                 break;
    309         case PT_SHLIB:
    310         default:
    311                 DPRINTF("Segment p_type %d unknown.\n", entry->p_type);
    312                 return EE_UNSUPPORTED;
    313                 break;
    314         }
    315         return EE_OK;
    316351}
    317352
  • uspace/lib/c/generic/rtld/module.c

    r4c5f04f r64d38cd  
    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

    r4c5f04f r64d38cd  
    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

    r4c5f04f r64d38cd  
    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

    r4c5f04f r64d38cd  
    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.