Subversion Repositories HelenOS

Rev

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

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