Subversion Repositories HelenOS

Rev

Rev 3223 | Rev 3787 | Go to most recent revision | Only display areas with differences | Regard whitespace | Details | Blame | Last modification | View Log | RSS feed

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