Subversion Repositories HelenOS

Rev

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

Rev 3129 Rev 3131
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
 
58
 
58
static char *error_codes[] = {
59
static char *error_codes[] = {
59
    "no error",
60
    "no error",
60
    "invalid image",
61
    "invalid image",
61
    "address space error",
62
    "address space error",
62
    "incompatible image",
63
    "incompatible image",
63
    "unsupported image type",
64
    "unsupported image type",
64
    "irrecoverable error"
65
    "irrecoverable error"
65
};
66
};
66
 
67
 
67
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);
68
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);
69
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);
70
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);
71
 
72
 
72
/** Load ELF binary from a file.
73
/** Load ELF binary from a file.
73
 *
74
 *
74
 * 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
75
 * 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
76
 * 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
77
 * 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
78
 * pointed to by @a info.
79
 * pointed to by @a info.
79
 *
80
 *
80
 * @param file_name Path to the ELF file.
81
 * @param file_name Path to the ELF file.
81
 * @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.
82
 * @param info      Pointer to a structure for storing information
83
 * @param info      Pointer to a structure for storing information
83
 *          extracted from the binary.
84
 *          extracted from the binary.
84
 *
85
 *
85
 * @return EOK on success or negative error code.
86
 * @return EOK on success or negative error code.
86
 */
87
 */
87
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)
88
{
89
{
89
    elf_ld_t elf;
90
    elf_ld_t elf;
90
 
91
 
91
    int fd;
92
    int fd;
92
    int rc;
93
    int rc;
93
 
94
 
94
    printf("open and read '%s'...\n", file_name);
95
    printf("open and read '%s'...\n", file_name);
95
 
96
 
96
    fd = open(file_name, O_RDONLY);
97
    fd = open(file_name, O_RDONLY);
97
    if (fd < 0) {
98
    if (fd < 0) {
98
        printf("failed opening file\n");
99
        printf("failed opening file\n");
99
        return -1;
100
        return -1;
100
    }
101
    }
101
 
102
 
102
    elf.fd = fd;
103
    elf.fd = fd;
103
    elf.info = info;
104
    elf.info = info;
104
 
105
 
105
    rc = elf_load(&elf, so_bias);
106
    rc = elf_load(&elf, so_bias);
106
    printf("elf_load() -> %d\n", rc);
107
    printf("elf_load() -> %d\n", rc);
107
 
108
 
108
    close(fd);
109
    close(fd);
109
 
110
 
110
    return rc;
111
    return rc;
111
}
112
}
112
 
113
 
113
/** Run an ELF executable.
114
/** Run an ELF executable.
114
 *
115
 *
115
 * Transfers control to the entry point of an ELF executable loaded
116
 * Transfers control to the entry point of an ELF executable loaded
116
 * earlier with elf_load_file(). This function does not return.
117
 * earlier with elf_load_file(). This function does not return.
117
 *
118
 *
118
 * @param info  Info structure filled earlier by elf_load_file()
119
 * @param info  Info structure filled earlier by elf_load_file()
119
 */
120
 */
120
void elf_run(elf_info_t *info)
121
void elf_run(elf_info_t *info)
121
{
122
{
122
    printf("entry point: 0x%llx\n", info->entry);
123
    printf("entry point: 0x%llx\n", info->entry);
123
    (*info->entry)();
124
    //(*info->entry)();
-
 
125
    program_run(info->entry);
124
 
126
 
125
    /* not reached */
127
    /* not reached */
126
}
128
}
127
 
129
 
128
/** Create the program control block (PCB).
130
/** Create the program control block (PCB).
129
 *
131
 *
130
 * Create and install the program control block, initialising it
132
 * Create and install the program control block, initialising it
131
 * with program information from @a info.
133
 * with program information from @a info.
132
 *
134
 *
133
 * @param info  Program info structure
135
 * @param info  Program info structure
134
 * @return EOK on success or negative error code
136
 * @return EOK on success or negative error code
135
 */
137
 */
136
int elf_create_pcb(elf_info_t *info)
138
int elf_create_pcb(elf_info_t *info)
137
{
139
{
138
    pcb_t *pcb;
140
    pcb_t *pcb;
139
    void *a;
141
    void *a;
140
 
142
 
141
    pcb = __pcb_get();
143
    pcb = __pcb_get();
142
 
144
 
143
    a = as_area_create(pcb, sizeof(pcb_t), AS_AREA_READ | AS_AREA_WRITE);
145
    a = as_area_create(pcb, sizeof(pcb_t), AS_AREA_READ | AS_AREA_WRITE);
144
    if (a == (void *)(-1)) {
146
    if (a == (void *)(-1)) {
145
        printf("elf_create_pcb: memory mapping failed\n");
147
        printf("elf_create_pcb: memory mapping failed\n");
146
        return EE_MEMORY;
148
        return EE_MEMORY;
147
    }
149
    }
148
 
150
 
149
    pcb->entry = info->entry;
151
    pcb->entry = info->entry;
150
    pcb->dynamic = info->dynamic;
152
    pcb->dynamic = info->dynamic;
151
 
153
 
152
    return 0;
154
    return 0;
153
}
155
}
154
 
156
 
155
 
157
 
156
/** Load an ELF binary.
158
/** Load an ELF binary.
157
 *
159
 *
158
 * The @a elf structure contains the loader state, including
160
 * The @a elf structure contains the loader state, including
159
 * an open file, from which the binary will be loaded,
161
 * an open file, from which the binary will be loaded,
160
 * a pointer to the @c info structure etc.
162
 * a pointer to the @c info structure etc.
161
 *
163
 *
162
 * @param elf       Pointer to loader state buffer.
164
 * @param elf       Pointer to loader state buffer.
163
 * @param so_bias   Bias to use if the file is a shared object.
165
 * @param so_bias   Bias to use if the file is a shared object.
164
 * @return EE_OK on success or EE_xx error code.
166
 * @return EE_OK on success or EE_xx error code.
165
 */
167
 */
166
static unsigned int elf_load(elf_ld_t *elf, size_t so_bias)
168
static unsigned int elf_load(elf_ld_t *elf, size_t so_bias)
167
{
169
{
168
    elf_header_t header_buf;
170
    elf_header_t header_buf;
169
    elf_header_t *header = &header_buf;
171
    elf_header_t *header = &header_buf;
170
    int i, rc;
172
    int i, rc;
171
 
173
 
172
    rc = read(elf->fd, header, sizeof(elf_header_t));
174
    rc = read(elf->fd, header, sizeof(elf_header_t));
173
    if (rc < 0) {
175
    if (rc < 0) {
174
        printf("read error\n");
176
        printf("read error\n");
175
        return EE_INVALID;
177
        return EE_INVALID;
176
    }
178
    }
177
 
179
 
178
    elf->header = header;
180
    elf->header = header;
179
 
181
 
180
    printf("ELF-load:");
182
    printf("ELF-load:");
181
    /* Identify ELF */
183
    /* Identify ELF */
182
    if (header->e_ident[EI_MAG0] != ELFMAG0 ||
184
    if (header->e_ident[EI_MAG0] != ELFMAG0 ||
183
        header->e_ident[EI_MAG1] != ELFMAG1 ||
185
        header->e_ident[EI_MAG1] != ELFMAG1 ||
184
        header->e_ident[EI_MAG2] != ELFMAG2 ||
186
        header->e_ident[EI_MAG2] != ELFMAG2 ||
185
        header->e_ident[EI_MAG3] != ELFMAG3) {
187
        header->e_ident[EI_MAG3] != ELFMAG3) {
186
        printf("invalid header\n");
188
        printf("invalid header\n");
187
        return EE_INVALID;
189
        return EE_INVALID;
188
    }
190
    }
189
   
191
   
190
    /* Identify ELF compatibility */
192
    /* Identify ELF compatibility */
191
    if (header->e_ident[EI_DATA] != ELF_DATA_ENCODING ||
193
    if (header->e_ident[EI_DATA] != ELF_DATA_ENCODING ||
192
        header->e_machine != ELF_MACHINE ||
194
        header->e_machine != ELF_MACHINE ||
193
        header->e_ident[EI_VERSION] != EV_CURRENT ||
195
        header->e_ident[EI_VERSION] != EV_CURRENT ||
194
        header->e_version != EV_CURRENT ||
196
        header->e_version != EV_CURRENT ||
195
        header->e_ident[EI_CLASS] != ELF_CLASS) {
197
        header->e_ident[EI_CLASS] != ELF_CLASS) {
196
        printf("incompatible data/version/class\n");
198
        printf("incompatible data/version/class\n");
197
        return EE_INCOMPATIBLE;
199
        return EE_INCOMPATIBLE;
198
    }
200
    }
199
 
201
 
200
    if (header->e_phentsize != sizeof(elf_segment_header_t)) {
202
    if (header->e_phentsize != sizeof(elf_segment_header_t)) {
201
        printf("e_phentsize:%d != %d\n", header->e_phentsize,
203
        printf("e_phentsize:%d != %d\n", header->e_phentsize,
202
            sizeof(elf_segment_header_t));
204
            sizeof(elf_segment_header_t));
203
        return EE_INCOMPATIBLE;
205
        return EE_INCOMPATIBLE;
204
    }
206
    }
205
 
207
 
206
    if (header->e_shentsize != sizeof(elf_section_header_t)) {
208
    if (header->e_shentsize != sizeof(elf_section_header_t)) {
207
        printf("e_shentsize:%d != %d\n", header->e_shentsize,
209
        printf("e_shentsize:%d != %d\n", header->e_shentsize,
208
            sizeof(elf_section_header_t));
210
            sizeof(elf_section_header_t));
209
        return EE_INCOMPATIBLE;
211
        return EE_INCOMPATIBLE;
210
    }
212
    }
211
 
213
 
212
    /* Check if the object type is supported. */
214
    /* Check if the object type is supported. */
213
    if (header->e_type != ET_EXEC && header->e_type != ET_DYN) {
215
    if (header->e_type != ET_EXEC && header->e_type != ET_DYN) {
214
        printf("Object type %d is not supported\n", header->e_type);
216
        printf("Object type %d is not supported\n", header->e_type);
215
        return EE_UNSUPPORTED;
217
        return EE_UNSUPPORTED;
216
    }
218
    }
217
 
219
 
218
    /* Shared objects can be loaded with a bias */
220
    /* Shared objects can be loaded with a bias */
219
    printf("Object type: %d\n", header->e_type);
221
    printf("Object type: %d\n", header->e_type);
220
    if (header->e_type == ET_DYN)
222
    if (header->e_type == ET_DYN)
221
        elf->bias = so_bias;
223
        elf->bias = so_bias;
222
    else
224
    else
223
        elf->bias = 0;
225
        elf->bias = 0;
224
 
226
 
225
    printf("Bias set to 0x%x\n", elf->bias);
227
    printf("Bias set to 0x%x\n", elf->bias);
226
    elf->info->interp = NULL;
228
    elf->info->interp = NULL;
227
    elf->info->dynamic = NULL;
229
    elf->info->dynamic = NULL;
228
 
230
 
229
    printf("parse segments\n");
231
    printf("parse segments\n");
230
 
232
 
231
    /* Walk through all segment headers and process them. */
233
    /* Walk through all segment headers and process them. */
232
    for (i = 0; i < header->e_phnum; i++) {
234
    for (i = 0; i < header->e_phnum; i++) {
233
        elf_segment_header_t segment_hdr;
235
        elf_segment_header_t segment_hdr;
234
 
236
 
235
        /* Seek to start of segment header */
237
        /* Seek to start of segment header */
236
        lseek(elf->fd, header->e_phoff
238
        lseek(elf->fd, header->e_phoff
237
                + i * sizeof(elf_segment_header_t), SEEK_SET);
239
                + i * sizeof(elf_segment_header_t), SEEK_SET);
238
 
240
 
239
        rc = read(elf->fd, &segment_hdr, sizeof(elf_segment_header_t));
241
        rc = read(elf->fd, &segment_hdr, sizeof(elf_segment_header_t));
240
        if (rc < 0) { printf("read error\n"); return EE_INVALID; }
242
        if (rc < 0) { printf("read error\n"); return EE_INVALID; }
241
 
243
 
242
        rc = segment_header(elf, &segment_hdr);
244
        rc = segment_header(elf, &segment_hdr);
243
        if (rc != EE_OK)
245
        if (rc != EE_OK)
244
            return rc;
246
            return rc;
245
    }
247
    }
246
 
248
 
247
    printf("parse sections\n");
249
    printf("parse sections\n");
248
 
250
 
249
    /* Inspect all section headers and proccess them. */
251
    /* Inspect all section headers and proccess them. */
250
    for (i = 0; i < header->e_shnum; i++) {
252
    for (i = 0; i < header->e_shnum; i++) {
251
        elf_section_header_t section_hdr;
253
        elf_section_header_t section_hdr;
252
 
254
 
253
        /* Seek to start of section header */
255
        /* Seek to start of section header */
254
        lseek(elf->fd, header->e_shoff
256
        lseek(elf->fd, header->e_shoff
255
            + i * sizeof(elf_section_header_t), SEEK_SET);
257
            + i * sizeof(elf_section_header_t), SEEK_SET);
256
 
258
 
257
        rc = read(elf->fd, &section_hdr, sizeof(elf_section_header_t));
259
        rc = read(elf->fd, &section_hdr, sizeof(elf_section_header_t));
258
        if (rc < 0) { printf("read error\n"); return EE_INVALID; }
260
        if (rc < 0) { printf("read error\n"); return EE_INVALID; }
259
 
261
 
260
        rc = section_header(elf, &section_hdr);
262
        rc = section_header(elf, &section_hdr);
261
        if (rc != EE_OK)
263
        if (rc != EE_OK)
262
            return rc;
264
            return rc;
263
    }
265
    }
264
 
266
 
265
    elf->info->entry =
267
    elf->info->entry =
266
        (entry_point_t)((uint8_t *)header->e_entry + elf->bias);
268
        (entry_point_t)((uint8_t *)header->e_entry + elf->bias);
267
 
269
 
268
    printf("done\n");
270
    printf("done\n");
269
 
271
 
270
    return EE_OK;
272
    return EE_OK;
271
}
273
}
272
 
274
 
273
/** Print error message according to error code.
275
/** Print error message according to error code.
274
 *
276
 *
275
 * @param rc Return code returned by elf_load().
277
 * @param rc Return code returned by elf_load().
276
 *
278
 *
277
 * @return NULL terminated description of error.
279
 * @return NULL terminated description of error.
278
 */
280
 */
279
char *elf_error(unsigned int rc)
281
char *elf_error(unsigned int rc)
280
{
282
{
281
    assert(rc < sizeof(error_codes) / sizeof(char *));
283
    assert(rc < sizeof(error_codes) / sizeof(char *));
282
 
284
 
283
    return error_codes[rc];
285
    return error_codes[rc];
284
}
286
}
285
 
287
 
286
/** Process segment header.
288
/** Process segment header.
287
 *
289
 *
288
 * @param entry Segment header.
290
 * @param entry Segment header.
289
 *
291
 *
290
 * @return EE_OK on success, error code otherwise.
292
 * @return EE_OK on success, error code otherwise.
291
 */
293
 */
292
static int segment_header(elf_ld_t *elf, elf_segment_header_t *entry)
294
static int segment_header(elf_ld_t *elf, elf_segment_header_t *entry)
293
{
295
{
294
    switch (entry->p_type) {
296
    switch (entry->p_type) {
295
    case PT_NULL:
297
    case PT_NULL:
296
    case PT_PHDR:
298
    case PT_PHDR:
297
        break;
299
        break;
298
    case PT_LOAD:
300
    case PT_LOAD:
299
        return load_segment(elf, entry);
301
        return load_segment(elf, entry);
300
        break;
302
        break;
301
    case PT_INTERP:
303
    case PT_INTERP:
302
        /* Assume silently interp == "/rtld.so" */
304
        /* Assume silently interp == "/rtld.so" */
303
        elf->info->interp = "/rtld.so";
305
        elf->info->interp = "/rtld.so";
304
        break;
306
        break;
305
    case PT_DYNAMIC:
307
    case PT_DYNAMIC:
306
    case PT_SHLIB:
308
    case PT_SHLIB:
307
    case PT_NOTE:
309
    case PT_NOTE:
308
    case PT_LOPROC:
310
    case PT_LOPROC:
309
    case PT_HIPROC:
311
    case PT_HIPROC:
310
    default:
312
    default:
311
        printf("segment p_type %d unknown\n", entry->p_type);
313
        printf("segment p_type %d unknown\n", entry->p_type);
312
        return EE_UNSUPPORTED;
314
        return EE_UNSUPPORTED;
313
        break;
315
        break;
314
    }
316
    }
315
    return EE_OK;
317
    return EE_OK;
316
}
318
}
317
 
319
 
318
/** Load segment described by program header entry.
320
/** Load segment described by program header entry.
319
 *
321
 *
320
 * @param elf   Loader state.
322
 * @param elf   Loader state.
321
 * @param entry Program header entry describing segment to be loaded.
323
 * @param entry Program header entry describing segment to be loaded.
322
 *
324
 *
323
 * @return EE_OK on success, error code otherwise.
325
 * @return EE_OK on success, error code otherwise.
324
 */
326
 */
325
int load_segment(elf_ld_t *elf, elf_segment_header_t *entry)
327
int load_segment(elf_ld_t *elf, elf_segment_header_t *entry)
326
{
328
{
327
    void *a;
329
    void *a;
328
    int flags = 0;
330
    int flags = 0;
329
    uintptr_t bias;
331
    uintptr_t bias;
330
    uintptr_t base;
332
    uintptr_t base;
331
    size_t mem_sz;
333
    size_t mem_sz;
332
    int rc;
334
    int rc;
333
 
335
 
334
    printf("load segment at addr 0x%x, size 0x%x\n", entry->p_vaddr,
336
    printf("load segment at addr 0x%x, size 0x%x\n", entry->p_vaddr,
335
        entry->p_memsz);
337
        entry->p_memsz);
336
   
338
   
337
    bias = elf->bias;
339
    bias = elf->bias;
338
 
340
 
339
    if (entry->p_align > 1) {
341
    if (entry->p_align > 1) {
340
        if ((entry->p_offset % entry->p_align) !=
342
        if ((entry->p_offset % entry->p_align) !=
341
            (entry->p_vaddr % entry->p_align)) {
343
            (entry->p_vaddr % entry->p_align)) {
342
            printf("align check 1 failed offset%%align=%d, vaddr%%align=%d\n",
344
            printf("align check 1 failed offset%%align=%d, vaddr%%align=%d\n",
343
            entry->p_offset % entry->p_align,
345
            entry->p_offset % entry->p_align,
344
            entry->p_vaddr % entry->p_align
346
            entry->p_vaddr % entry->p_align
345
            );
347
            );
346
            return EE_INVALID;
348
            return EE_INVALID;
347
        }
349
        }
348
    }
350
    }
349
 
351
 
350
    /* Final flags that will be set for the memory area */
352
    /* Final flags that will be set for the memory area */
351
 
353
 
352
    if (entry->p_flags & PF_X)
354
    if (entry->p_flags & PF_X)
353
        flags |= AS_AREA_EXEC;
355
        flags |= AS_AREA_EXEC;
354
    if (entry->p_flags & PF_W)
356
    if (entry->p_flags & PF_W)
355
        flags |= AS_AREA_WRITE;
357
        flags |= AS_AREA_WRITE;
356
    if (entry->p_flags & PF_R)
358
    if (entry->p_flags & PF_R)
357
        flags |= AS_AREA_READ;
359
        flags |= AS_AREA_READ;
358
    flags |= AS_AREA_CACHEABLE;
360
    flags |= AS_AREA_CACHEABLE;
359
   
361
   
360
    base = ALIGN_DOWN(entry->p_vaddr, PAGE_SIZE);
362
    base = ALIGN_DOWN(entry->p_vaddr, PAGE_SIZE);
361
    mem_sz = entry->p_memsz + (entry->p_vaddr - base);
363
    mem_sz = entry->p_memsz + (entry->p_vaddr - base);
362
 
364
 
363
    printf("map to p_vaddr=0x%x-0x%x...\n", entry->p_vaddr + bias,
365
    printf("map to p_vaddr=0x%x-0x%x...\n", entry->p_vaddr + bias,
364
    entry->p_vaddr + bias + ALIGN_UP(entry->p_memsz, PAGE_SIZE));
366
    entry->p_vaddr + bias + ALIGN_UP(entry->p_memsz, PAGE_SIZE));
365
 
367
 
366
    /*
368
    /*
367
     * For the course of loading, the area needs to be readable
369
     * For the course of loading, the area needs to be readable
368
     * and writeable.
370
     * and writeable.
369
     */
371
     */
370
    a = as_area_create((uint8_t *)base + bias,
372
    a = as_area_create((uint8_t *)base + bias,
371
        mem_sz, AS_AREA_READ | AS_AREA_WRITE | AS_AREA_CACHEABLE);
373
        mem_sz, AS_AREA_READ | AS_AREA_WRITE | AS_AREA_CACHEABLE);
372
    if (a == (void *)(-1)) {
374
    if (a == (void *)(-1)) {
373
        printf("memory mapping failed\n");
375
        printf("memory mapping failed\n");
374
        return EE_MEMORY;
376
        return EE_MEMORY;
375
    }
377
    }
376
 
378
 
377
    printf("as_area_create(0x%lx, 0x%x, %d) -> 0x%lx\n",
379
    printf("as_area_create(0x%lx, 0x%x, %d) -> 0x%lx\n",
378
        entry->p_vaddr+bias, entry->p_memsz, flags, (uintptr_t)a);
380
        entry->p_vaddr+bias, entry->p_memsz, flags, (uintptr_t)a);
379
 
381
 
380
    /*
382
    /*
381
     * Load segment data
383
     * Load segment data
382
     */
384
     */
383
    printf("seek to %d\n", entry->p_offset);
385
    printf("seek to %d\n", entry->p_offset);
384
    rc = lseek(elf->fd, entry->p_offset, SEEK_SET);
386
    rc = lseek(elf->fd, entry->p_offset, SEEK_SET);
385
    if (rc < 0) { printf("seek error\n"); return EE_INVALID; }
387
    if (rc < 0) { printf("seek error\n"); return EE_INVALID; }
386
 
388
 
387
    printf("read 0x%x bytes to address 0x%x\n", entry->p_filesz, entry->p_vaddr+bias);
389
    printf("read 0x%x bytes to address 0x%x\n", entry->p_filesz, entry->p_vaddr+bias);
388
/*  rc = read(fd, (void *)(entry->p_vaddr + bias), entry->p_filesz);
390
/*  rc = read(fd, (void *)(entry->p_vaddr + bias), entry->p_filesz);
389
    if (rc < 0) { printf("read error\n"); return EE_INVALID; }*/
391
    if (rc < 0) { printf("read error\n"); return EE_INVALID; }*/
390
 
392
 
391
    /* Long reads are not possible yet. Load segment picewise */
393
    /* Long reads are not possible yet. Load segment picewise */
392
 
394
 
393
    unsigned left, now;
395
    unsigned left, now;
394
    uint8_t *dp;
396
    uint8_t *dp;
395
 
397
 
396
    left = entry->p_filesz;
398
    left = entry->p_filesz;
397
    dp = (uint8_t *)(entry->p_vaddr + bias);
399
    dp = (uint8_t *)(entry->p_vaddr + bias);
398
 
400
 
399
    while (left > 0) {
401
    while (left > 0) {
400
        now = 16384;
402
        now = 16384;
401
        if (now > left) now = left;
403
        if (now > left) now = left;
402
 
404
 
403
        printf("read %d...", now);
405
        printf("read %d...", now);
404
        rc = read(elf->fd, dp, now);
406
        rc = read(elf->fd, dp, now);
405
        printf("->%d\n", rc);
407
        printf("->%d\n", rc);
406
 
408
 
407
        if (rc < 0) { printf("read error\n"); return EE_INVALID; }
409
        if (rc < 0) { printf("read error\n"); return EE_INVALID; }
408
 
410
 
409
        left -= now;
411
        left -= now;
410
        dp += now;
412
        dp += now;
411
    }
413
    }
412
 
414
 
413
    printf("set area flags to %d\n", flags);
415
    printf("set area flags to %d\n", flags);
414
    rc = as_area_change_flags((uint8_t *)entry->p_vaddr + bias, flags);
416
    rc = as_area_change_flags((uint8_t *)entry->p_vaddr + bias, flags);
415
    if (rc != 0) {
417
    if (rc != 0) {
416
        printf("failed to set memory area flags\n");
418
        printf("failed to set memory area flags\n");
417
        return EE_MEMORY;
419
        return EE_MEMORY;
418
    }
420
    }
419
 
421
 
420
    return EE_OK;
422
    return EE_OK;
421
}
423
}
422
 
424
 
423
/** Process section header.
425
/** Process section header.
424
 *
426
 *
425
 * @param elf   Loader state.
427
 * @param elf   Loader state.
426
 * @param entry Segment header.
428
 * @param entry Segment header.
427
 *
429
 *
428
 * @return EE_OK on success, error code otherwise.
430
 * @return EE_OK on success, error code otherwise.
429
 */
431
 */
430
static int section_header(elf_ld_t *elf, elf_section_header_t *entry)
432
static int section_header(elf_ld_t *elf, elf_section_header_t *entry)
431
{
433
{
432
    switch (entry->sh_type) {
434
    switch (entry->sh_type) {
433
    case SHT_PROGBITS:
435
    case SHT_PROGBITS:
434
        if (entry->sh_flags & SHF_TLS) {
436
        if (entry->sh_flags & SHF_TLS) {
435
            /* .tdata */
437
            /* .tdata */
436
        }
438
        }
437
        break;
439
        break;
438
    case SHT_NOBITS:
440
    case SHT_NOBITS:
439
        if (entry->sh_flags & SHF_TLS) {
441
        if (entry->sh_flags & SHF_TLS) {
440
            /* .tbss */
442
            /* .tbss */
441
        }
443
        }
442
        break;
444
        break;
443
    case SHT_DYNAMIC:
445
    case SHT_DYNAMIC:
444
        /* Record pointer to dynamic section into info structure */
446
        /* Record pointer to dynamic section into info structure */
445
        elf->info->dynamic =
447
        elf->info->dynamic =
446
            (void *)((uint8_t *)entry->sh_addr + elf->bias);
448
            (void *)((uint8_t *)entry->sh_addr + elf->bias);
447
        printf("dynamic section found at 0x%x\n",
449
        printf("dynamic section found at 0x%x\n",
448
            (uintptr_t)elf->info->dynamic);
450
            (uintptr_t)elf->info->dynamic);
449
        break;
451
        break;
450
    default:
452
    default:
451
        break;
453
        break;
452
    }
454
    }
453
   
455
   
454
    return EE_OK;
456
    return EE_OK;
455
}
457
}
456
 
458
 
457
/** @}
459
/** @}
458
 */
460
 */
459
 
461