Subversion Repositories HelenOS

Rev

Rev 3010 | Go to most recent revision | Show entire file | Ignore whitespace | Details | Blame | Last modification | View Log | RSS feed

Rev 3010 Rev 3101
Line 32... Line 32...
32
 * @{
32
 * @{
33
 */
33
 */
34
 
34
 
35
/**
35
/**
36
 * @file
36
 * @file
37
 * @brief   Kernel ELF loader.
37
 * @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.
38
 */
44
 */
39
 
45
 
40
#include <stdio.h>
46
#include <stdio.h>
41
#include <sys/types.h>
47
#include <sys/types.h>
42
#include <align.h>
48
#include <align.h>
Line 61... Line 67...
61
static unsigned int elf_load(elf_ld_t *elf, size_t so_bias);
67
static unsigned int elf_load(elf_ld_t *elf, size_t so_bias);
62
static int segment_header(elf_ld_t *elf, elf_segment_header_t *entry);
68
static int segment_header(elf_ld_t *elf, elf_segment_header_t *entry);
63
static int section_header(elf_ld_t *elf, elf_section_header_t *entry);
69
static int section_header(elf_ld_t *elf, elf_section_header_t *entry);
64
static int load_segment(elf_ld_t *elf, elf_segment_header_t *entry);
70
static int load_segment(elf_ld_t *elf, elf_segment_header_t *entry);
65
 
71
 
-
 
72
/** Load ELF binary from a file.
-
 
73
 *
-
 
74
 * Load an ELF binary from the specified file. If the file is
-
 
75
 * an executable program, it is loaded unbiased. If it is a shared
-
 
76
 * object, it is loaded with the bias @a so_bias. Some information
-
 
77
 * extracted from the binary is stored in a elf_info_t structure
-
 
78
 * pointed to by @a info.
-
 
79
 *
-
 
80
 * @param file_name Path to the ELF file.
-
 
81
 * @param so_bias   Bias to use if the file is a shared object.
-
 
82
 * @param info      Pointer to a structure for storing information
-
 
83
 *          extracted from the binary.
-
 
84
 *
-
 
85
 * @return EOK on success or negative error code.
-
 
86
 */
66
int elf_load_file(char *file_name, size_t so_bias, elf_info_t *info)
87
int elf_load_file(char *file_name, size_t so_bias, elf_info_t *info)
67
{
88
{
68
    elf_ld_t elf;
89
    elf_ld_t elf;
69
 
90
 
70
    int fd;
91
    int fd;
71
    int rc;
92
    int rc;
72
 
93
 
73
    printf("open and read '%s'...\n", file_name);
94
    printf("open and read '%s'...\n", file_name);
74
 
95
 
75
    fd = open(file_name, 0);
96
    fd = open(file_name, O_RDONLY);
76
    if (fd < 0) {
97
    if (fd < 0) {
77
        printf("failed opening file\n");
98
        printf("failed opening file\n");
78
        return -1;
99
        return -1;
79
    }
100
    }
80
 
101
 
Line 87... Line 108...
87
    close(fd);
108
    close(fd);
88
 
109
 
89
    return rc;
110
    return rc;
90
}
111
}
91
 
112
 
-
 
113
/** Run an ELF executable.
-
 
114
 *
-
 
115
 * Transfers control to the entry point of an ELF executable loaded
-
 
116
 * earlier with elf_load_file(). This function does not return.
-
 
117
 *
-
 
118
 * @param info  Info structure filled earlier by elf_load_file()
-
 
119
 */
92
void elf_run(elf_info_t *info)
120
void elf_run(elf_info_t *info)
93
{
121
{
94
    (*info->entry)();
122
    (*info->entry)();
95
 
123
 
96
    /* not reached */
124
    /* not reached */
97
}
125
}
98
 
126
 
-
 
127
/** Create the program control block (PCB).
-
 
128
 *
-
 
129
 * Create and install the program control block, initialising it
-
 
130
 * with program information from @a info.
-
 
131
 *
-
 
132
 * @param info  Program info structure
-
 
133
 * @return EOK on success or negative error code
-
 
134
 */
99
int elf_create_pcb(elf_info_t *info)
135
int elf_create_pcb(elf_info_t *info)
100
{
136
{
101
    pcb_t *pcb;
137
    pcb_t *pcb;
102
    void *a;
138
    void *a;
103
 
139
 
Line 114... Line 150...
114
 
150
 
115
    return 0;
151
    return 0;
116
}
152
}
117
 
153
 
118
 
154
 
119
/** ELF loader
155
/** Load an ELF binary.
-
 
156
 *
-
 
157
 * The @a elf structure contains the loader state, including
-
 
158
 * an open file, from which the binary will be loaded,
-
 
159
 * a pointer to the @c info structure etc.
120
 *
160
 *
121
 * @param header Pointer to ELF header in memory
161
 * @param elf       Pointer to loader state buffer.
-
 
162
 * @param so_bias   Bias to use if the file is a shared object.
122
 * @return EE_OK on success
163
 * @return EE_OK on success or EE_xx error code.
123
 */
164
 */
124
static unsigned int elf_load(elf_ld_t *elf, size_t so_bias)
165
static unsigned int elf_load(elf_ld_t *elf, size_t so_bias)
125
{
166
{
126
    elf_header_t header_buf;
167
    elf_header_t header_buf;
127
    elf_header_t *header = &header_buf;
168
    elf_header_t *header = &header_buf;
Line 241... Line 282...
241
    return error_codes[rc];
282
    return error_codes[rc];
242
}
283
}
243
 
284
 
244
/** Process segment header.
285
/** Process segment header.
245
 *
286
 *
246
 * @param entry Segment header.
287
 * @param entry Segment header.
247
 * @param elf ELF header.
-
 
248
 *
288
 *
249
 * @return EE_OK on success, error code otherwise.
289
 * @return EE_OK on success, error code otherwise.
250
 */
290
 */
251
static int segment_header(elf_ld_t *elf, elf_segment_header_t *entry)
291
static int segment_header(elf_ld_t *elf, elf_segment_header_t *entry)
252
{
292
{
Line 274... Line 314...
274
    return EE_OK;
314
    return EE_OK;
275
}
315
}
276
 
316
 
277
/** Load segment described by program header entry.
317
/** Load segment described by program header entry.
278
 *
318
 *
-
 
319
 * @param elf   Loader state.
279
 * @param entry Program header entry describing segment to be loaded.
320
 * @param entry Program header entry describing segment to be loaded.
280
 * @param elf ELF header.
-
 
281
 *
321
 *
282
 * @return EE_OK on success, error code otherwise.
322
 * @return EE_OK on success, error code otherwise.
283
 */
323
 */
284
int load_segment(elf_ld_t *elf, elf_segment_header_t *entry)
324
int load_segment(elf_ld_t *elf, elf_segment_header_t *entry)
285
{
325
{
Line 344... Line 384...
344
    if (rc < 0) { printf("seek error\n"); return EE_INVALID; }
384
    if (rc < 0) { printf("seek error\n"); return EE_INVALID; }
345
 
385
 
346
    printf("read 0x%x bytes to address 0x%x\n", entry->p_filesz, entry->p_vaddr+bias);
386
    printf("read 0x%x bytes to address 0x%x\n", entry->p_filesz, entry->p_vaddr+bias);
347
/*  rc = read(fd, (void *)(entry->p_vaddr + bias), entry->p_filesz);
387
/*  rc = read(fd, (void *)(entry->p_vaddr + bias), entry->p_filesz);
348
    if (rc < 0) { printf("read error\n"); return EE_INVALID; }*/
388
    if (rc < 0) { printf("read error\n"); return EE_INVALID; }*/
-
 
389
 
-
 
390
    /* Long reads are not possible yet. Load segment picewise */
-
 
391
 
349
    unsigned left, now;
392
    unsigned left, now;
350
    uint8_t *dp;
393
    uint8_t *dp;
351
 
394
 
352
    left = entry->p_filesz;
395
    left = entry->p_filesz;
353
    dp = (uint8_t *)(entry->p_vaddr + bias);
396
    dp = (uint8_t *)(entry->p_vaddr + bias);
354
 
397
 
355
    while (left > 0) {
398
    while (left > 0) {
356
        now = 16384;
399
        now = 16384;
357
        if (now > left) now=left;
400
        if (now > left) now = left;
-
 
401
 
358
        printf("read %d...", now);
402
        printf("read %d...", now);
359
        rc = read(elf->fd, dp, now);
403
        rc = read(elf->fd, dp, now);
360
        if (rc < 0) { printf("read error\n"); return EE_INVALID; }
-
 
361
        printf("->%d\n", rc);
404
        printf("->%d\n", rc);
-
 
405
 
-
 
406
        if (rc < 0) { printf("read error\n"); return EE_INVALID; }
-
 
407
 
362
        left -= now;
408
        left -= now;
363
        dp += now;
409
        dp += now;
364
    }
410
    }
365
 
411
 
366
    printf("set area flags to %d\n", flags);
412
    printf("set area flags to %d\n", flags);
Line 373... Line 419...
373
    return EE_OK;
419
    return EE_OK;
374
}
420
}
375
 
421
 
376
/** Process section header.
422
/** Process section header.
377
 *
423
 *
-
 
424
 * @param elf   Loader state.
378
 * @param entry Segment header.
425
 * @param entry Segment header.
379
 * @param elf ELF header.
-
 
380
 *
426
 *
381
 * @return EE_OK on success, error code otherwise.
427
 * @return EE_OK on success, error code otherwise.
382
 */
428
 */
383
static int section_header(elf_ld_t *elf, elf_section_header_t *entry)
429
static int section_header(elf_ld_t *elf, elf_section_header_t *entry)
384
{
430
{
Line 392... Line 438...
392
        if (entry->sh_flags & SHF_TLS) {
438
        if (entry->sh_flags & SHF_TLS) {
393
            /* .tbss */
439
            /* .tbss */
394
        }
440
        }
395
        break;
441
        break;
396
    case SHT_DYNAMIC:
442
    case SHT_DYNAMIC:
-
 
443
        /* Record pointer to dynamic section into info structure */
397
        elf->info->dynamic =
444
        elf->info->dynamic =
398
            (void *)((uint8_t *)entry->sh_addr + elf->bias);
445
            (void *)((uint8_t *)entry->sh_addr + elf->bias);
399
        printf("dynamic section found at 0x%x\n",
446
        printf("dynamic section found at 0x%x\n",
400
            (uintptr_t)elf->info->dynamic);
447
            (uintptr_t)elf->info->dynamic);
401
        break;
448
        break;