Subversion Repositories HelenOS

Rev

Rev 3131 | Rev 3157 | Go to most recent revision | Only display areas with differences | Ignore whitespace | Details | Blame | Last modification | View Log | RSS feed

Rev 3131 Rev 3155
1
/*
1
/*
2
 * Copyright (c) 2006 Sergey Bondari
2
 * Copyright (c) 2006 Sergey Bondari
3
 * Copyright (c) 2006 Jakub Jermar
3
 * Copyright (c) 2006 Jakub Jermar
4
 * Copyright (c) 2008 Jiri Svoboda
4
 * Copyright (c) 2008 Jiri Svoboda
5
 * All rights reserved.
5
 * All rights reserved.
6
 *
6
 *
7
 * Redistribution and use in source and binary forms, with or without
7
 * Redistribution and use in source and binary forms, with or without
8
 * modification, are permitted provided that the following conditions
8
 * modification, are permitted provided that the following conditions
9
 * are met:
9
 * are met:
10
 *
10
 *
11
 * - Redistributions of source code must retain the above copyright
11
 * - Redistributions of source code must retain the above copyright
12
 *   notice, this list of conditions and the following disclaimer.
12
 *   notice, this list of conditions and the following disclaimer.
13
 * - Redistributions in binary form must reproduce the above copyright
13
 * - Redistributions in binary form must reproduce the above copyright
14
 *   notice, this list of conditions and the following disclaimer in the
14
 *   notice, this list of conditions and the following disclaimer in the
15
 *   documentation and/or other materials provided with the distribution.
15
 *   documentation and/or other materials provided with the distribution.
16
 * - The name of the author may not be used to endorse or promote products
16
 * - The name of the author may not be used to endorse or promote products
17
 *   derived from this software without specific prior written permission.
17
 *   derived from this software without specific prior written permission.
18
 *
18
 *
19
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
19
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
20
 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
20
 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
21
 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
21
 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
22
 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
22
 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
23
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
23
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
24
 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
24
 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
25
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
25
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
26
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
27
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
28
 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28
 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29
 */
29
 */
30
 
30
 
31
/** @addtogroup generic
31
/** @addtogroup generic
32
 * @{
32
 * @{
33
 */
33
 */
34
 
34
 
35
/**
35
/**
36
 * @file
36
 * @file
37
 * @brief   Userspace ELF loader.
37
 * @brief   Userspace ELF loader.
38
 *
38
 *
39
 * This module allows loading ELF binaries (both executables and
39
 * This module allows loading ELF binaries (both executables and
40
 * shared objects) from VFS. The current implementation allocates
40
 * shared objects) from VFS. The current implementation allocates
41
 * anonymous memory, fills it with segment data and then adjusts
41
 * anonymous memory, fills it with segment data and then adjusts
42
 * the memory areas' flags to the final value. In the future,
42
 * the memory areas' flags to the final value. In the future,
43
 * the segments will be mapped directly from the file.
43
 * the segments will be mapped directly from the file.
44
 */
44
 */
45
 
45
 
46
#include <stdio.h>
46
#include <stdio.h>
47
#include <sys/types.h>
47
#include <sys/types.h>
48
#include <align.h>
48
#include <align.h>
49
#include <assert.h>
49
#include <assert.h>
50
#include <as.h>
50
#include <as.h>
51
#include <unistd.h>
51
#include <unistd.h>
52
#include <fcntl.h>
52
#include <fcntl.h>
53
 
53
 
54
#include "elf.h"
54
#include "elf.h"
55
#include "pcb.h"
55
#include "pcb.h"
56
#include "elf_load.h"
56
#include "elf_load.h"
57
#include "arch.h"
57
#include "arch.h"
58
 
58
 
59
static char *error_codes[] = {
59
static char *error_codes[] = {
60
    "no error",
60
    "no error",
61
    "invalid image",
61
    "invalid image",
62
    "address space error",
62
    "address space error",
63
    "incompatible image",
63
    "incompatible image",
64
    "unsupported image type",
64
    "unsupported image type",
65
    "irrecoverable error"
65
    "irrecoverable error"
66
};
66
};
67
 
67
 
68
static unsigned int elf_load(elf_ld_t *elf, size_t so_bias);
68
static unsigned int elf_load(elf_ld_t *elf, size_t so_bias);
69
static int segment_header(elf_ld_t *elf, elf_segment_header_t *entry);
69
static int segment_header(elf_ld_t *elf, elf_segment_header_t *entry);
70
static int section_header(elf_ld_t *elf, elf_section_header_t *entry);
70
static int section_header(elf_ld_t *elf, elf_section_header_t *entry);
71
static int load_segment(elf_ld_t *elf, elf_segment_header_t *entry);
71
static int load_segment(elf_ld_t *elf, elf_segment_header_t *entry);
72
 
72
 
73
/** Load ELF binary from a file.
73
/** Load ELF binary from a file.
74
 *
74
 *
75
 * Load an ELF binary from the specified file. If the file is
75
 * Load an ELF binary from the specified file. If the file is
76
 * an executable program, it is loaded unbiased. If it is a shared
76
 * an executable program, it is loaded unbiased. If it is a shared
77
 * object, it is loaded with the bias @a so_bias. Some information
77
 * object, it is loaded with the bias @a so_bias. Some information
78
 * extracted from the binary is stored in a elf_info_t structure
78
 * extracted from the binary is stored in a elf_info_t structure
79
 * pointed to by @a info.
79
 * pointed to by @a info.
80
 *
80
 *
81
 * @param file_name Path to the ELF file.
81
 * @param file_name Path to the ELF file.
82
 * @param so_bias   Bias to use if the file is a shared object.
82
 * @param so_bias   Bias to use if the file is a shared object.
83
 * @param info      Pointer to a structure for storing information
83
 * @param info      Pointer to a structure for storing information
84
 *          extracted from the binary.
84
 *          extracted from the binary.
85
 *
85
 *
86
 * @return EOK on success or negative error code.
86
 * @return EOK on success or negative error code.
87
 */
87
 */
88
int elf_load_file(char *file_name, size_t so_bias, elf_info_t *info)
88
int elf_load_file(char *file_name, size_t so_bias, elf_info_t *info)
89
{
89
{
90
    elf_ld_t elf;
90
    elf_ld_t elf;
91
 
91
 
92
    int fd;
92
    int fd;
93
    int rc;
93
    int rc;
94
 
94
 
95
    printf("open and read '%s'...\n", file_name);
95
//  printf("open and read '%s'...\n", file_name);
96
 
96
 
97
    fd = open(file_name, O_RDONLY);
97
    fd = open(file_name, O_RDONLY);
98
    if (fd < 0) {
98
    if (fd < 0) {
99
        printf("failed opening file\n");
99
        printf("failed opening file\n");
100
        return -1;
100
        return -1;
101
    }
101
    }
102
 
102
 
103
    elf.fd = fd;
103
    elf.fd = fd;
104
    elf.info = info;
104
    elf.info = info;
105
 
105
 
106
    rc = elf_load(&elf, so_bias);
106
    rc = elf_load(&elf, so_bias);
107
    printf("elf_load() -> %d\n", rc);
-
 
108
 
107
 
109
    close(fd);
108
    close(fd);
110
 
109
 
111
    return rc;
110
    return rc;
112
}
111
}
113
 
112
 
114
/** Run an ELF executable.
113
/** Run an ELF executable.
115
 *
114
 *
116
 * Transfers control to the entry point of an ELF executable loaded
115
 * Transfers control to the entry point of an ELF executable loaded
117
 * earlier with elf_load_file(). This function does not return.
116
 * earlier with elf_load_file(). This function does not return.
118
 *
117
 *
119
 * @param info  Info structure filled earlier by elf_load_file()
118
 * @param info  Info structure filled earlier by elf_load_file()
120
 */
119
 */
121
void elf_run(elf_info_t *info)
120
void elf_run(elf_info_t *info)
122
{
121
{
123
    printf("entry point: 0x%llx\n", info->entry);
-
 
124
    //(*info->entry)();
-
 
125
    program_run(info->entry);
122
    program_run(info->entry);
126
 
123
 
127
    /* not reached */
124
    /* not reached */
128
}
125
}
129
 
126
 
130
/** Create the program control block (PCB).
127
/** Create the program control block (PCB).
131
 *
128
 *
132
 * Create and install the program control block, initialising it
129
 * Create and install the program control block, initialising it
133
 * with program information from @a info.
130
 * with program information from @a info.
134
 *
131
 *
135
 * @param info  Program info structure
132
 * @param info  Program info structure
136
 * @return EOK on success or negative error code
133
 * @return EOK on success or negative error code
137
 */
134
 */
138
int elf_create_pcb(elf_info_t *info)
135
int elf_create_pcb(elf_info_t *info)
139
{
136
{
140
    pcb_t *pcb;
137
    pcb_t *pcb;
141
    void *a;
138
    void *a;
142
 
139
 
143
    pcb = __pcb_get();
140
    pcb = __pcb_get();
144
 
141
 
145
    a = as_area_create(pcb, sizeof(pcb_t), AS_AREA_READ | AS_AREA_WRITE);
142
    a = as_area_create(pcb, sizeof(pcb_t), AS_AREA_READ | AS_AREA_WRITE);
146
    if (a == (void *)(-1)) {
143
    if (a == (void *)(-1)) {
147
        printf("elf_create_pcb: memory mapping failed\n");
144
        printf("elf_create_pcb: memory mapping failed\n");
148
        return EE_MEMORY;
145
        return EE_MEMORY;
149
    }
146
    }
150
 
147
 
151
    pcb->entry = info->entry;
148
    pcb->entry = info->entry;
152
    pcb->dynamic = info->dynamic;
149
    pcb->dynamic = info->dynamic;
153
 
150
 
154
    return 0;
151
    return 0;
155
}
152
}
156
 
153
 
157
 
154
 
158
/** Load an ELF binary.
155
/** Load an ELF binary.
159
 *
156
 *
160
 * The @a elf structure contains the loader state, including
157
 * The @a elf structure contains the loader state, including
161
 * an open file, from which the binary will be loaded,
158
 * an open file, from which the binary will be loaded,
162
 * a pointer to the @c info structure etc.
159
 * a pointer to the @c info structure etc.
163
 *
160
 *
164
 * @param elf       Pointer to loader state buffer.
161
 * @param elf       Pointer to loader state buffer.
165
 * @param so_bias   Bias to use if the file is a shared object.
162
 * @param so_bias   Bias to use if the file is a shared object.
166
 * @return EE_OK on success or EE_xx error code.
163
 * @return EE_OK on success or EE_xx error code.
167
 */
164
 */
168
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)
169
{
166
{
170
    elf_header_t header_buf;
167
    elf_header_t header_buf;
171
    elf_header_t *header = &header_buf;
168
    elf_header_t *header = &header_buf;
172
    int i, rc;
169
    int i, rc;
173
 
170
 
174
    rc = read(elf->fd, header, sizeof(elf_header_t));
171
    rc = read(elf->fd, header, sizeof(elf_header_t));
175
    if (rc < 0) {
172
    if (rc < 0) {
176
        printf("read error\n");
173
        printf("read error\n");
177
        return EE_INVALID;
174
        return EE_INVALID;
178
    }
175
    }
179
 
176
 
180
    elf->header = header;
177
    elf->header = header;
181
 
178
 
182
    printf("ELF-load:");
179
//  printf("ELF-load:");
183
    /* Identify ELF */
180
    /* Identify ELF */
184
    if (header->e_ident[EI_MAG0] != ELFMAG0 ||
181
    if (header->e_ident[EI_MAG0] != ELFMAG0 ||
185
        header->e_ident[EI_MAG1] != ELFMAG1 ||
182
        header->e_ident[EI_MAG1] != ELFMAG1 ||
186
        header->e_ident[EI_MAG2] != ELFMAG2 ||
183
        header->e_ident[EI_MAG2] != ELFMAG2 ||
187
        header->e_ident[EI_MAG3] != ELFMAG3) {
184
        header->e_ident[EI_MAG3] != ELFMAG3) {
188
        printf("invalid header\n");
185
        printf("invalid header\n");
189
        return EE_INVALID;
186
        return EE_INVALID;
190
    }
187
    }
191
   
188
   
192
    /* Identify ELF compatibility */
189
    /* Identify ELF compatibility */
193
    if (header->e_ident[EI_DATA] != ELF_DATA_ENCODING ||
190
    if (header->e_ident[EI_DATA] != ELF_DATA_ENCODING ||
194
        header->e_machine != ELF_MACHINE ||
191
        header->e_machine != ELF_MACHINE ||
195
        header->e_ident[EI_VERSION] != EV_CURRENT ||
192
        header->e_ident[EI_VERSION] != EV_CURRENT ||
196
        header->e_version != EV_CURRENT ||
193
        header->e_version != EV_CURRENT ||
197
        header->e_ident[EI_CLASS] != ELF_CLASS) {
194
        header->e_ident[EI_CLASS] != ELF_CLASS) {
198
        printf("incompatible data/version/class\n");
195
        printf("incompatible data/version/class\n");
199
        return EE_INCOMPATIBLE;
196
        return EE_INCOMPATIBLE;
200
    }
197
    }
201
 
198
 
202
    if (header->e_phentsize != sizeof(elf_segment_header_t)) {
199
    if (header->e_phentsize != sizeof(elf_segment_header_t)) {
203
        printf("e_phentsize:%d != %d\n", header->e_phentsize,
200
        printf("e_phentsize:%d != %d\n", header->e_phentsize,
204
            sizeof(elf_segment_header_t));
201
            sizeof(elf_segment_header_t));
205
        return EE_INCOMPATIBLE;
202
        return EE_INCOMPATIBLE;
206
    }
203
    }
207
 
204
 
208
    if (header->e_shentsize != sizeof(elf_section_header_t)) {
205
    if (header->e_shentsize != sizeof(elf_section_header_t)) {
209
        printf("e_shentsize:%d != %d\n", header->e_shentsize,
206
        printf("e_shentsize:%d != %d\n", header->e_shentsize,
210
            sizeof(elf_section_header_t));
207
            sizeof(elf_section_header_t));
211
        return EE_INCOMPATIBLE;
208
        return EE_INCOMPATIBLE;
212
    }
209
    }
213
 
210
 
214
    /* Check if the object type is supported. */
211
    /* Check if the object type is supported. */
215
    if (header->e_type != ET_EXEC && header->e_type != ET_DYN) {
212
    if (header->e_type != ET_EXEC && header->e_type != ET_DYN) {
216
        printf("Object type %d is not supported\n", header->e_type);
213
        printf("Object type %d is not supported\n", header->e_type);
217
        return EE_UNSUPPORTED;
214
        return EE_UNSUPPORTED;
218
    }
215
    }
219
 
216
 
220
    /* Shared objects can be loaded with a bias */
217
    /* Shared objects can be loaded with a bias */
221
    printf("Object type: %d\n", header->e_type);
218
//  printf("Object type: %d\n", header->e_type);
222
    if (header->e_type == ET_DYN)
219
    if (header->e_type == ET_DYN)
223
        elf->bias = so_bias;
220
        elf->bias = so_bias;
224
    else
221
    else
225
        elf->bias = 0;
222
        elf->bias = 0;
226
 
223
 
227
    printf("Bias set to 0x%x\n", elf->bias);
224
//  printf("Bias set to 0x%x\n", elf->bias);
228
    elf->info->interp = NULL;
225
    elf->info->interp = NULL;
229
    elf->info->dynamic = NULL;
226
    elf->info->dynamic = NULL;
230
 
227
 
231
    printf("parse segments\n");
228
//  printf("parse segments\n");
232
 
229
 
233
    /* Walk through all segment headers and process them. */
230
    /* Walk through all segment headers and process them. */
234
    for (i = 0; i < header->e_phnum; i++) {
231
    for (i = 0; i < header->e_phnum; i++) {
235
        elf_segment_header_t segment_hdr;
232
        elf_segment_header_t segment_hdr;
236
 
233
 
237
        /* Seek to start of segment header */
234
        /* Seek to start of segment header */
238
        lseek(elf->fd, header->e_phoff
235
        lseek(elf->fd, header->e_phoff
239
                + i * sizeof(elf_segment_header_t), SEEK_SET);
236
                + i * sizeof(elf_segment_header_t), SEEK_SET);
240
 
237
 
241
        rc = read(elf->fd, &segment_hdr, sizeof(elf_segment_header_t));
238
        rc = read(elf->fd, &segment_hdr, sizeof(elf_segment_header_t));
242
        if (rc < 0) { printf("read error\n"); return EE_INVALID; }
239
        if (rc < 0) { printf("read error\n"); return EE_INVALID; }
243
 
240
 
244
        rc = segment_header(elf, &segment_hdr);
241
        rc = segment_header(elf, &segment_hdr);
245
        if (rc != EE_OK)
242
        if (rc != EE_OK)
246
            return rc;
243
            return rc;
247
    }
244
    }
248
 
245
 
249
    printf("parse sections\n");
246
//  printf("parse sections\n");
250
 
247
 
251
    /* Inspect all section headers and proccess them. */
248
    /* Inspect all section headers and proccess them. */
252
    for (i = 0; i < header->e_shnum; i++) {
249
    for (i = 0; i < header->e_shnum; i++) {
253
        elf_section_header_t section_hdr;
250
        elf_section_header_t section_hdr;
254
 
251
 
255
        /* Seek to start of section header */
252
        /* Seek to start of section header */
256
        lseek(elf->fd, header->e_shoff
253
        lseek(elf->fd, header->e_shoff
257
            + i * sizeof(elf_section_header_t), SEEK_SET);
254
            + i * sizeof(elf_section_header_t), SEEK_SET);
258
 
255
 
259
        rc = read(elf->fd, &section_hdr, sizeof(elf_section_header_t));
256
        rc = read(elf->fd, &section_hdr, sizeof(elf_section_header_t));
260
        if (rc < 0) { printf("read error\n"); return EE_INVALID; }
257
        if (rc < 0) { printf("read error\n"); return EE_INVALID; }
261
 
258
 
262
        rc = section_header(elf, &section_hdr);
259
        rc = section_header(elf, &section_hdr);
263
        if (rc != EE_OK)
260
        if (rc != EE_OK)
264
            return rc;
261
            return rc;
265
    }
262
    }
266
 
263
 
267
    elf->info->entry =
264
    elf->info->entry =
268
        (entry_point_t)((uint8_t *)header->e_entry + elf->bias);
265
        (entry_point_t)((uint8_t *)header->e_entry + elf->bias);
269
 
266
 
270
    printf("done\n");
267
//  printf("done\n");
271
 
268
 
272
    return EE_OK;
269
    return EE_OK;
273
}
270
}
274
 
271
 
275
/** Print error message according to error code.
272
/** Print error message according to error code.
276
 *
273
 *
277
 * @param rc Return code returned by elf_load().
274
 * @param rc Return code returned by elf_load().
278
 *
275
 *
279
 * @return NULL terminated description of error.
276
 * @return NULL terminated description of error.
280
 */
277
 */
281
char *elf_error(unsigned int rc)
278
char *elf_error(unsigned int rc)
282
{
279
{
283
    assert(rc < sizeof(error_codes) / sizeof(char *));
280
    assert(rc < sizeof(error_codes) / sizeof(char *));
284
 
281
 
285
    return error_codes[rc];
282
    return error_codes[rc];
286
}
283
}
287
 
284
 
288
/** Process segment header.
285
/** Process segment header.
289
 *
286
 *
290
 * @param entry Segment header.
287
 * @param entry Segment header.
291
 *
288
 *
292
 * @return EE_OK on success, error code otherwise.
289
 * @return EE_OK on success, error code otherwise.
293
 */
290
 */
294
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)
295
{
292
{
296
    switch (entry->p_type) {
293
    switch (entry->p_type) {
297
    case PT_NULL:
294
    case PT_NULL:
298
    case PT_PHDR:
295
    case PT_PHDR:
299
        break;
296
        break;
300
    case PT_LOAD:
297
    case PT_LOAD:
301
        return load_segment(elf, entry);
298
        return load_segment(elf, entry);
302
        break;
299
        break;
303
    case PT_INTERP:
300
    case PT_INTERP:
304
        /* Assume silently interp == "/rtld.so" */
301
        /* Assume silently interp == "/rtld.so" */
305
        elf->info->interp = "/rtld.so";
302
        elf->info->interp = "/rtld.so";
306
        break;
303
        break;
307
    case PT_DYNAMIC:
304
    case PT_DYNAMIC:
308
    case PT_SHLIB:
305
    case PT_SHLIB:
309
    case PT_NOTE:
306
    case PT_NOTE:
310
    case PT_LOPROC:
307
    case PT_LOPROC:
311
    case PT_HIPROC:
308
    case PT_HIPROC:
312
    default:
309
    default:
313
        printf("segment p_type %d unknown\n", entry->p_type);
310
        printf("segment p_type %d unknown\n", entry->p_type);
314
        return EE_UNSUPPORTED;
311
        return EE_UNSUPPORTED;
315
        break;
312
        break;
316
    }
313
    }
317
    return EE_OK;
314
    return EE_OK;
318
}
315
}
319
 
316
 
320
/** Load segment described by program header entry.
317
/** Load segment described by program header entry.
321
 *
318
 *
322
 * @param elf   Loader state.
319
 * @param elf   Loader state.
323
 * @param entry Program header entry describing segment to be loaded.
320
 * @param entry Program header entry describing segment to be loaded.
324
 *
321
 *
325
 * @return EE_OK on success, error code otherwise.
322
 * @return EE_OK on success, error code otherwise.
326
 */
323
 */
327
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)
328
{
325
{
329
    void *a;
326
    void *a;
330
    int flags = 0;
327
    int flags = 0;
331
    uintptr_t bias;
328
    uintptr_t bias;
332
    uintptr_t base;
329
    uintptr_t base;
333
    size_t mem_sz;
330
    size_t mem_sz;
334
    int rc;
331
    int rc;
335
 
332
 
336
    printf("load segment at addr 0x%x, size 0x%x\n", entry->p_vaddr,
333
//  printf("load segment at addr 0x%x, size 0x%x\n", entry->p_vaddr,
337
        entry->p_memsz);
334
//      entry->p_memsz);
338
   
335
   
339
    bias = elf->bias;
336
    bias = elf->bias;
340
 
337
 
341
    if (entry->p_align > 1) {
338
    if (entry->p_align > 1) {
342
        if ((entry->p_offset % entry->p_align) !=
339
        if ((entry->p_offset % entry->p_align) !=
343
            (entry->p_vaddr % entry->p_align)) {
340
            (entry->p_vaddr % entry->p_align)) {
344
            printf("align check 1 failed offset%%align=%d, vaddr%%align=%d\n",
341
            printf("align check 1 failed offset%%align=%d, vaddr%%align=%d\n",
345
            entry->p_offset % entry->p_align,
342
            entry->p_offset % entry->p_align,
346
            entry->p_vaddr % entry->p_align
343
            entry->p_vaddr % entry->p_align
347
            );
344
            );
348
            return EE_INVALID;
345
            return EE_INVALID;
349
        }
346
        }
350
    }
347
    }
351
 
348
 
352
    /* Final flags that will be set for the memory area */
349
    /* Final flags that will be set for the memory area */
353
 
350
 
354
    if (entry->p_flags & PF_X)
351
    if (entry->p_flags & PF_X)
355
        flags |= AS_AREA_EXEC;
352
        flags |= AS_AREA_EXEC;
356
    if (entry->p_flags & PF_W)
353
    if (entry->p_flags & PF_W)
357
        flags |= AS_AREA_WRITE;
354
        flags |= AS_AREA_WRITE;
358
    if (entry->p_flags & PF_R)
355
    if (entry->p_flags & PF_R)
359
        flags |= AS_AREA_READ;
356
        flags |= AS_AREA_READ;
360
    flags |= AS_AREA_CACHEABLE;
357
    flags |= AS_AREA_CACHEABLE;
361
   
358
   
362
    base = ALIGN_DOWN(entry->p_vaddr, PAGE_SIZE);
359
    base = ALIGN_DOWN(entry->p_vaddr, PAGE_SIZE);
363
    mem_sz = entry->p_memsz + (entry->p_vaddr - base);
360
    mem_sz = entry->p_memsz + (entry->p_vaddr - base);
364
 
361
 
365
    printf("map to p_vaddr=0x%x-0x%x...\n", entry->p_vaddr + bias,
362
//  printf("map to p_vaddr=0x%x-0x%x...\n", entry->p_vaddr + bias,
366
    entry->p_vaddr + bias + ALIGN_UP(entry->p_memsz, PAGE_SIZE));
363
//  entry->p_vaddr + bias + ALIGN_UP(entry->p_memsz, PAGE_SIZE));
367
 
364
 
368
    /*
365
    /*
369
     * For the course of loading, the area needs to be readable
366
     * For the course of loading, the area needs to be readable
370
     * and writeable.
367
     * and writeable.
371
     */
368
     */
372
    a = as_area_create((uint8_t *)base + bias,
369
    a = as_area_create((uint8_t *)base + bias,
373
        mem_sz, AS_AREA_READ | AS_AREA_WRITE | AS_AREA_CACHEABLE);
370
        mem_sz, AS_AREA_READ | AS_AREA_WRITE | AS_AREA_CACHEABLE);
374
    if (a == (void *)(-1)) {
371
    if (a == (void *)(-1)) {
375
        printf("memory mapping failed\n");
372
        printf("memory mapping failed\n");
376
        return EE_MEMORY;
373
        return EE_MEMORY;
377
    }
374
    }
378
 
375
 
379
    printf("as_area_create(0x%lx, 0x%x, %d) -> 0x%lx\n",
376
//  printf("as_area_create(0x%lx, 0x%x, %d) -> 0x%lx\n",
380
        entry->p_vaddr+bias, entry->p_memsz, flags, (uintptr_t)a);
377
//      entry->p_vaddr+bias, entry->p_memsz, flags, (uintptr_t)a);
381
 
378
 
382
    /*
379
    /*
383
     * Load segment data
380
     * Load segment data
384
     */
381
     */
385
    printf("seek to %d\n", entry->p_offset);
382
//  printf("seek to %d\n", entry->p_offset);
386
    rc = lseek(elf->fd, entry->p_offset, SEEK_SET);
383
    rc = lseek(elf->fd, entry->p_offset, SEEK_SET);
387
    if (rc < 0) { printf("seek error\n"); return EE_INVALID; }
384
    if (rc < 0) { printf("seek error\n"); return EE_INVALID; }
388
 
385
 
389
    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);
390
/*  rc = read(fd, (void *)(entry->p_vaddr + bias), entry->p_filesz);
387
/*  rc = read(fd, (void *)(entry->p_vaddr + bias), entry->p_filesz);
391
    if (rc < 0) { printf("read error\n"); return EE_INVALID; }*/
388
    if (rc < 0) { printf("read error\n"); return EE_INVALID; }*/
392
 
389
 
393
    /* Long reads are not possible yet. Load segment picewise */
390
    /* Long reads are not possible yet. Load segment picewise */
394
 
391
 
395
    unsigned left, now;
392
    unsigned left, now;
396
    uint8_t *dp;
393
    uint8_t *dp;
397
 
394
 
398
    left = entry->p_filesz;
395
    left = entry->p_filesz;
399
    dp = (uint8_t *)(entry->p_vaddr + bias);
396
    dp = (uint8_t *)(entry->p_vaddr + bias);
400
 
397
 
401
    while (left > 0) {
398
    while (left > 0) {
402
        now = 16384;
399
        now = 16384;
403
        if (now > left) now = left;
400
        if (now > left) now = left;
404
 
401
 
405
        printf("read %d...", now);
402
//      printf("read %d...", now);
406
        rc = read(elf->fd, dp, now);
403
        rc = read(elf->fd, dp, now);
407
        printf("->%d\n", rc);
404
//      printf("->%d\n", rc);
408
 
405
 
409
        if (rc < 0) { printf("read error\n"); return EE_INVALID; }
406
        if (rc < 0) { printf("read error\n"); return EE_INVALID; }
410
 
407
 
411
        left -= now;
408
        left -= now;
412
        dp += now;
409
        dp += now;
413
    }
410
    }
414
 
411
 
415
    printf("set area flags to %d\n", flags);
412
//  printf("set area flags to %d\n", flags);
416
    rc = as_area_change_flags((uint8_t *)entry->p_vaddr + bias, flags);
413
    rc = as_area_change_flags((uint8_t *)entry->p_vaddr + bias, flags);
417
    if (rc != 0) {
414
    if (rc != 0) {
418
        printf("failed to set memory area flags\n");
415
        printf("failed to set memory area flags\n");
419
        return EE_MEMORY;
416
        return EE_MEMORY;
420
    }
417
    }
421
 
418
 
422
    return EE_OK;
419
    return EE_OK;
423
}
420
}
424
 
421
 
425
/** Process section header.
422
/** Process section header.
426
 *
423
 *
427
 * @param elf   Loader state.
424
 * @param elf   Loader state.
428
 * @param entry Segment header.
425
 * @param entry Segment header.
429
 *
426
 *
430
 * @return EE_OK on success, error code otherwise.
427
 * @return EE_OK on success, error code otherwise.
431
 */
428
 */
432
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)
433
{
430
{
434
    switch (entry->sh_type) {
431
    switch (entry->sh_type) {
435
    case SHT_PROGBITS:
432
    case SHT_PROGBITS:
436
        if (entry->sh_flags & SHF_TLS) {
433
        if (entry->sh_flags & SHF_TLS) {
437
            /* .tdata */
434
            /* .tdata */
438
        }
435
        }
439
        break;
436
        break;
440
    case SHT_NOBITS:
437
    case SHT_NOBITS:
441
        if (entry->sh_flags & SHF_TLS) {
438
        if (entry->sh_flags & SHF_TLS) {
442
            /* .tbss */
439
            /* .tbss */
443
        }
440
        }
444
        break;
441
        break;
445
    case SHT_DYNAMIC:
442
    case SHT_DYNAMIC:
446
        /* Record pointer to dynamic section into info structure */
443
        /* Record pointer to dynamic section into info structure */
447
        elf->info->dynamic =
444
        elf->info->dynamic =
448
            (void *)((uint8_t *)entry->sh_addr + elf->bias);
445
            (void *)((uint8_t *)entry->sh_addr + elf->bias);
449
        printf("dynamic section found at 0x%x\n",
446
        printf("dynamic section found at 0x%x\n",
450
            (uintptr_t)elf->info->dynamic);
447
            (uintptr_t)elf->info->dynamic);
451
        break;
448
        break;
452
    default:
449
    default:
453
        break;
450
        break;
454
    }
451
    }
455
   
452
   
456
    return EE_OK;
453
    return EE_OK;
457
}
454
}
458
 
455
 
459
/** @}
456
/** @}
460
 */
457
 */
461
 
458