Subversion Repositories HelenOS

Rev

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

Rev 3403 Rev 3552
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. */
74
/** Read until the buffer is read in its entirety. */
75
static int my_read(int fd, char *buf, size_t len)
75
static int my_read(int fd, char *buf, size_t len)
76
{
76
{
77
    int cnt = 0;
77
    int cnt = 0;
78
    do {
78
    do {
79
        buf += cnt;
79
        buf += cnt;
80
        len -= cnt;
80
        len -= cnt;
81
        cnt = read(fd, buf, len);
81
        cnt = read(fd, buf, len);
82
    } while ((cnt > 0) && ((len - cnt) > 0));
82
    } while ((cnt > 0) && ((len - cnt) > 0));
83
 
83
 
84
    return cnt;
84
    return cnt;
85
}
85
}
86
 
86
 
87
/** Load ELF binary from a file.
87
/** Load ELF binary from a file.
88
 *
88
 *
89
 * 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
90
 * 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
91
 * 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
92
 * 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
93
 * pointed to by @a info.
93
 * pointed to by @a info.
94
 *
94
 *
95
 * @param file_name Path to the ELF file.
95
 * @param file_name Path to the ELF file.
96
 * @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.
97
 * @param info      Pointer to a structure for storing information
97
 * @param info      Pointer to a structure for storing information
98
 *          extracted from the binary.
98
 *          extracted from the binary.
99
 *
99
 *
100
 * @return EOK on success or negative error code.
100
 * @return EOK on success or negative error code.
101
 */
101
 */
102
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, eld_flags_t flags,
-
 
103
    elf_info_t *info)
103
{
104
{
104
    elf_ld_t elf;
105
    elf_ld_t elf;
105
 
106
 
106
    int fd;
107
    int fd;
107
    int rc;
108
    int rc;
108
 
109
 
109
//  printf("open and read '%s'...\n", file_name);
110
//  printf("open and read '%s'...\n", file_name);
110
 
111
 
111
    fd = open(file_name, O_RDONLY);
112
    fd = open(file_name, O_RDONLY);
112
    if (fd < 0) {
113
    if (fd < 0) {
113
        printf("failed opening file (error %d)\n", fd);
114
        printf("failed opening file (error %d)\n", fd);
114
        return -1;
115
        return -1;
115
    }
116
    }
116
 
117
 
117
    elf.fd = fd;
118
    elf.fd = fd;
118
    elf.info = info;
119
    elf.info = info;
-
 
120
    elf.flags = flags;
119
 
121
 
120
    rc = elf_load(&elf, so_bias);
122
    rc = elf_load(&elf, so_bias);
121
 
123
 
122
    close(fd);
124
    close(fd);
123
 
125
 
124
    return rc;
126
    return rc;
125
}
127
}
126
 
128
 
127
/** Run an ELF executable.
129
/** Run an ELF executable.
128
 *
130
 *
129
 * Transfers control to the entry point of an ELF executable loaded
131
 * Transfers control to the entry point of an ELF executable loaded
130
 * earlier with elf_load_file(). This function does not return.
132
 * earlier with elf_load_file(). This function does not return.
131
 *
133
 *
132
 * @param info  Info structure filled earlier by elf_load_file()
134
 * @param info  Info structure filled earlier by elf_load_file()
133
 */
135
 */
134
void elf_run(elf_info_t *info, pcb_t *pcb)
136
void elf_run(elf_info_t *info, pcb_t *pcb)
135
{
137
{
136
    program_run(info->entry, pcb);
138
    program_run(info->entry, pcb);
137
 
139
 
138
    /* not reached */
140
    /* not reached */
139
}
141
}
140
 
142
 
141
/** Create the program control block (PCB).
143
/** Create the program control block (PCB).
142
 *
144
 *
143
 * Fills the program control block @a pcb with information from
145
 * Fills the program control block @a pcb with information from
144
 * @a info.
146
 * @a info.
145
 *
147
 *
146
 * @param info  Program info structure
148
 * @param info  Program info structure
147
 * @return EOK on success or negative error code
149
 * @return EOK on success or negative error code
148
 */
150
 */
149
void elf_create_pcb(elf_info_t *info, pcb_t *pcb)
151
void elf_create_pcb(elf_info_t *info, pcb_t *pcb)
150
{
152
{
151
    pcb->entry = info->entry;
153
    pcb->entry = info->entry;
152
    pcb->dynamic = info->dynamic;
154
    pcb->dynamic = info->dynamic;
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 = my_read(elf->fd, header, sizeof(elf_header_t));
174
    rc = my_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 = my_read(elf->fd, &segment_hdr,
241
        rc = my_read(elf->fd, &segment_hdr,
240
            sizeof(elf_segment_header_t));
242
            sizeof(elf_segment_header_t));
241
        if (rc < 0) {
243
        if (rc < 0) {
242
            printf("read error\n");
244
            printf("read error\n");
243
            return EE_INVALID;
245
            return EE_INVALID;
244
        }
246
        }
245
 
247
 
246
        rc = segment_header(elf, &segment_hdr);
248
        rc = segment_header(elf, &segment_hdr);
247
        if (rc != EE_OK)
249
        if (rc != EE_OK)
248
            return rc;
250
            return rc;
249
    }
251
    }
250
 
252
 
251
//  printf("parse sections\n");
253
//  printf("parse sections\n");
252
 
254
 
253
    /* Inspect all section headers and proccess them. */
255
    /* Inspect all section headers and proccess them. */
254
    for (i = 0; i < header->e_shnum; i++) {
256
    for (i = 0; i < header->e_shnum; i++) {
255
        elf_section_header_t section_hdr;
257
        elf_section_header_t section_hdr;
256
 
258
 
257
        /* Seek to start of section header */
259
        /* Seek to start of section header */
258
        lseek(elf->fd, header->e_shoff
260
        lseek(elf->fd, header->e_shoff
259
            + i * sizeof(elf_section_header_t), SEEK_SET);
261
            + i * sizeof(elf_section_header_t), SEEK_SET);
260
 
262
 
261
        rc = my_read(elf->fd, &section_hdr,
263
        rc = my_read(elf->fd, &section_hdr,
262
            sizeof(elf_section_header_t));
264
            sizeof(elf_section_header_t));
263
        if (rc < 0) {
265
        if (rc < 0) {
264
            printf("read error\n");
266
            printf("read error\n");
265
            return EE_INVALID;
267
            return EE_INVALID;
266
        }
268
        }
267
 
269
 
268
        rc = section_header(elf, &section_hdr);
270
        rc = section_header(elf, &section_hdr);
269
        if (rc != EE_OK)
271
        if (rc != EE_OK)
270
            return rc;
272
            return rc;
271
    }
273
    }
272
 
274
 
273
    elf->info->entry =
275
    elf->info->entry =
274
        (entry_point_t)((uint8_t *)header->e_entry + elf->bias);
276
        (entry_point_t)((uint8_t *)header->e_entry + elf->bias);
275
 
277
 
276
//  printf("done\n");
278
//  printf("done\n");
277
 
279
 
278
    return EE_OK;
280
    return EE_OK;
279
}
281
}
280
 
282
 
281
/** Print error message according to error code.
283
/** Print error message according to error code.
282
 *
284
 *
283
 * @param rc Return code returned by elf_load().
285
 * @param rc Return code returned by elf_load().
284
 *
286
 *
285
 * @return NULL terminated description of error.
287
 * @return NULL terminated description of error.
286
 */
288
 */
287
char *elf_error(unsigned int rc)
289
char *elf_error(unsigned int rc)
288
{
290
{
289
    assert(rc < sizeof(error_codes) / sizeof(char *));
291
    assert(rc < sizeof(error_codes) / sizeof(char *));
290
 
292
 
291
    return error_codes[rc];
293
    return error_codes[rc];
292
}
294
}
293
 
295
 
294
/** Process segment header.
296
/** Process segment header.
295
 *
297
 *
296
 * @param entry Segment header.
298
 * @param entry Segment header.
297
 *
299
 *
298
 * @return EE_OK on success, error code otherwise.
300
 * @return EE_OK on success, error code otherwise.
299
 */
301
 */
300
static int segment_header(elf_ld_t *elf, elf_segment_header_t *entry)
302
static int segment_header(elf_ld_t *elf, elf_segment_header_t *entry)
301
{
303
{
302
    switch (entry->p_type) {
304
    switch (entry->p_type) {
303
    case PT_NULL:
305
    case PT_NULL:
304
    case PT_PHDR:
306
    case PT_PHDR:
305
        break;
307
        break;
306
    case PT_LOAD:
308
    case PT_LOAD:
307
        return load_segment(elf, entry);
309
        return load_segment(elf, entry);
308
        break;
310
        break;
309
    case PT_INTERP:
311
    case PT_INTERP:
310
        /* Assume silently interp == "/lib/rtld.so" */
312
        /* Assume silently interp == "/lib/rtld" */
311
        elf->info->interp = "/lib/rtld.so";
313
        elf->info->interp = "/lib/rtld";
312
        break;
314
        break;
313
    case PT_DYNAMIC:
315
    case PT_DYNAMIC:
314
    case PT_SHLIB:
316
    case PT_SHLIB:
315
    case PT_NOTE:
317
    case PT_NOTE:
316
    case PT_LOPROC:
318
    case PT_LOPROC:
317
    case PT_HIPROC:
319
    case PT_HIPROC:
318
    default:
320
    default:
319
        printf("segment p_type %d unknown\n", entry->p_type);
321
        printf("segment p_type %d unknown\n", entry->p_type);
320
        return EE_UNSUPPORTED;
322
        return EE_UNSUPPORTED;
321
        break;
323
        break;
322
    }
324
    }
323
    return EE_OK;
325
    return EE_OK;
324
}
326
}
325
 
327
 
326
/** Load segment described by program header entry.
328
/** Load segment described by program header entry.
327
 *
329
 *
328
 * @param elf   Loader state.
330
 * @param elf   Loader state.
329
 * @param entry Program header entry describing segment to be loaded.
331
 * @param entry Program header entry describing segment to be loaded.
330
 *
332
 *
331
 * @return EE_OK on success, error code otherwise.
333
 * @return EE_OK on success, error code otherwise.
332
 */
334
 */
333
int load_segment(elf_ld_t *elf, elf_segment_header_t *entry)
335
int load_segment(elf_ld_t *elf, elf_segment_header_t *entry)
334
{
336
{
335
    void *a;
337
    void *a;
336
    int flags = 0;
338
    int flags = 0;
337
    uintptr_t bias;
339
    uintptr_t bias;
338
    uintptr_t base;
340
    uintptr_t base;
339
    size_t mem_sz;
341
    size_t mem_sz;
340
    int rc;
342
    int rc;
341
 
343
 
342
//  printf("load segment at addr 0x%x, size 0x%x\n", entry->p_vaddr,
344
//  printf("load segment at addr 0x%x, size 0x%x\n", entry->p_vaddr,
343
//      entry->p_memsz);
345
//      entry->p_memsz);
344
   
346
   
345
    bias = elf->bias;
347
    bias = elf->bias;
346
 
348
 
347
    if (entry->p_align > 1) {
349
    if (entry->p_align > 1) {
348
        if ((entry->p_offset % entry->p_align) !=
350
        if ((entry->p_offset % entry->p_align) !=
349
            (entry->p_vaddr % entry->p_align)) {
351
            (entry->p_vaddr % entry->p_align)) {
350
            printf("align check 1 failed offset%%align=%d, "
352
            printf("align check 1 failed offset%%align=%d, "
351
                "vaddr%%align=%d\n",
353
                "vaddr%%align=%d\n",
352
                entry->p_offset % entry->p_align,
354
                entry->p_offset % entry->p_align,
353
                entry->p_vaddr % entry->p_align
355
                entry->p_vaddr % entry->p_align
354
            );
356
            );
355
            return EE_INVALID;
357
            return EE_INVALID;
356
        }
358
        }
357
    }
359
    }
358
 
360
 
359
    /* Final flags that will be set for the memory area */
361
    /* Final flags that will be set for the memory area */
360
 
362
 
361
    if (entry->p_flags & PF_X)
363
    if (entry->p_flags & PF_X)
362
        flags |= AS_AREA_EXEC;
364
        flags |= AS_AREA_EXEC;
363
    if (entry->p_flags & PF_W)
365
    if (entry->p_flags & PF_W)
364
        flags |= AS_AREA_WRITE;
366
        flags |= AS_AREA_WRITE;
365
    if (entry->p_flags & PF_R)
367
    if (entry->p_flags & PF_R)
366
        flags |= AS_AREA_READ;
368
        flags |= AS_AREA_READ;
367
    flags |= AS_AREA_CACHEABLE;
369
    flags |= AS_AREA_CACHEABLE;
368
   
370
   
369
    base = ALIGN_DOWN(entry->p_vaddr, PAGE_SIZE);
371
    base = ALIGN_DOWN(entry->p_vaddr, PAGE_SIZE);
370
    mem_sz = entry->p_memsz + (entry->p_vaddr - base);
372
    mem_sz = entry->p_memsz + (entry->p_vaddr - base);
371
 
373
 
372
//  printf("map to p_vaddr=0x%x-0x%x...\n", entry->p_vaddr + bias,
374
//  printf("map to p_vaddr=0x%x-0x%x...\n", entry->p_vaddr + bias,
373
//  entry->p_vaddr + bias + ALIGN_UP(entry->p_memsz, PAGE_SIZE));
375
//  entry->p_vaddr + bias + ALIGN_UP(entry->p_memsz, PAGE_SIZE));
374
 
376
 
375
    /*
377
    /*
376
     * For the course of loading, the area needs to be readable
378
     * For the course of loading, the area needs to be readable
377
     * and writeable.
379
     * and writeable.
378
     */
380
     */
379
    a = as_area_create((uint8_t *)base + bias, mem_sz,
381
    a = as_area_create((uint8_t *)base + bias, mem_sz,
380
        AS_AREA_READ | AS_AREA_WRITE | AS_AREA_CACHEABLE);
382
        AS_AREA_READ | AS_AREA_WRITE | AS_AREA_CACHEABLE);
381
    if (a == (void *)(-1)) {
383
    if (a == (void *)(-1)) {
382
        printf("memory mapping failed\n");
384
        printf("memory mapping failed\n");
383
        return EE_MEMORY;
385
        return EE_MEMORY;
384
    }
386
    }
385
 
387
 
386
//  printf("as_area_create(0x%lx, 0x%x, %d) -> 0x%lx\n",
388
//  printf("as_area_create(0x%lx, 0x%x, %d) -> 0x%lx\n",
387
//      entry->p_vaddr+bias, entry->p_memsz, flags, (uintptr_t)a);
389
//      entry->p_vaddr+bias, entry->p_memsz, flags, (uintptr_t)a);
388
 
390
 
389
    /*
391
    /*
390
     * Load segment data
392
     * Load segment data
391
     */
393
     */
392
//  printf("seek to %d\n", entry->p_offset);
394
//  printf("seek to %d\n", entry->p_offset);
393
    rc = lseek(elf->fd, entry->p_offset, SEEK_SET);
395
    rc = lseek(elf->fd, entry->p_offset, SEEK_SET);
394
    if (rc < 0) {
396
    if (rc < 0) {
395
        printf("seek error\n");
397
        printf("seek error\n");
396
        return EE_INVALID;
398
        return EE_INVALID;
397
    }
399
    }
398
 
400
 
399
//  printf("read 0x%x bytes to address 0x%x\n", entry->p_filesz, entry->p_vaddr+bias);
401
//  printf("read 0x%x bytes to address 0x%x\n", entry->p_filesz, entry->p_vaddr+bias);
400
/*  rc = read(fd, (void *)(entry->p_vaddr + bias), entry->p_filesz);
402
/*  rc = read(fd, (void *)(entry->p_vaddr + bias), entry->p_filesz);
401
    if (rc < 0) { printf("read error\n"); return EE_INVALID; }*/
403
    if (rc < 0) { printf("read error\n"); return EE_INVALID; }*/
402
 
404
 
403
    /* Long reads are not possible yet. Load segment picewise */
405
    /* Long reads are not possible yet. Load segment picewise */
404
 
406
 
405
    unsigned left, now;
407
    unsigned left, now;
406
    uint8_t *dp;
408
    uint8_t *dp;
407
 
409
 
408
    left = entry->p_filesz;
410
    left = entry->p_filesz;
409
    dp = (uint8_t *)(entry->p_vaddr + bias);
411
    dp = (uint8_t *)(entry->p_vaddr + bias);
410
 
412
 
411
    while (left > 0) {
413
    while (left > 0) {
412
        now = 16384;
414
        now = 16384;
413
        if (now > left) now = left;
415
        if (now > left) now = left;
414
 
416
 
415
//      printf("read %d...", now);
417
//      printf("read %d...", now);
416
        rc = my_read(elf->fd, dp, now);
418
        rc = my_read(elf->fd, dp, now);
417
//      printf("->%d\n", rc);
419
//      printf("->%d\n", rc);
418
 
420
 
419
        if (rc < 0) {
421
        if (rc < 0) {
420
            printf("read error\n");
422
            printf("read error\n");
421
            return EE_INVALID;
423
            return EE_INVALID;
422
        }
424
        }
423
 
425
 
424
        left -= now;
426
        left -= now;
425
        dp += now;
427
        dp += now;
426
    }
428
    }
427
 
429
 
-
 
430
    /*
-
 
431
     * The caller wants to modify the segments first. He will then
-
 
432
     * need to set the right access mode and ensure SMC coherence.
-
 
433
     */
-
 
434
    if ((elf->flags & ELDF_RW) != 0) return EE_OK;
-
 
435
 
428
//  printf("set area flags to %d\n", flags);
436
    printf("set area flags to %d\n", flags);
429
    rc = as_area_change_flags((uint8_t *)entry->p_vaddr + bias, flags);
437
    rc = as_area_change_flags((uint8_t *)entry->p_vaddr + bias, flags);
430
    if (rc != 0) {
438
    if (rc != 0) {
431
        printf("failed to set memory area flags\n");
439
        printf("failed to set memory area flags\n");
432
        return EE_MEMORY;
440
        return EE_MEMORY;
433
    }
441
    }
434
 
442
 
435
    if (flags & AS_AREA_EXEC) {
443
    if (flags & AS_AREA_EXEC) {
436
        /* Enforce SMC coherence for the segment */
444
        /* Enforce SMC coherence for the segment */
437
        if (smc_coherence(entry->p_vaddr + bias, entry->p_filesz))
445
        if (smc_coherence(entry->p_vaddr + bias, entry->p_filesz))
438
            return EE_MEMORY;
446
            return EE_MEMORY;
439
    }
447
    }
440
 
448
 
441
    return EE_OK;
449
    return EE_OK;
442
}
450
}
443
 
451
 
444
/** Process section header.
452
/** Process section header.
445
 *
453
 *
446
 * @param elf   Loader state.
454
 * @param elf   Loader state.
447
 * @param entry Segment header.
455
 * @param entry Segment header.
448
 *
456
 *
449
 * @return EE_OK on success, error code otherwise.
457
 * @return EE_OK on success, error code otherwise.
450
 */
458
 */
451
static int section_header(elf_ld_t *elf, elf_section_header_t *entry)
459
static int section_header(elf_ld_t *elf, elf_section_header_t *entry)
452
{
460
{
453
    switch (entry->sh_type) {
461
    switch (entry->sh_type) {
454
    case SHT_PROGBITS:
462
    case SHT_PROGBITS:
455
        if (entry->sh_flags & SHF_TLS) {
463
        if (entry->sh_flags & SHF_TLS) {
456
            /* .tdata */
464
            /* .tdata */
457
        }
465
        }
458
        break;
466
        break;
459
    case SHT_NOBITS:
467
    case SHT_NOBITS:
460
        if (entry->sh_flags & SHF_TLS) {
468
        if (entry->sh_flags & SHF_TLS) {
461
            /* .tbss */
469
            /* .tbss */
462
        }
470
        }
463
        break;
471
        break;
464
    case SHT_DYNAMIC:
472
    case SHT_DYNAMIC:
465
        /* Record pointer to dynamic section into info structure */
473
        /* Record pointer to dynamic section into info structure */
466
        elf->info->dynamic =
474
        elf->info->dynamic =
467
            (void *)((uint8_t *)entry->sh_addr + elf->bias);
475
            (void *)((uint8_t *)entry->sh_addr + elf->bias);
468
        printf("dynamic section found at 0x%x\n",
476
        printf("dynamic section found at 0x%x\n",
469
            (uintptr_t)elf->info->dynamic);
477
            (uintptr_t)elf->info->dynamic);
470
        break;
478
        break;
471
    default:
479
    default:
472
        break;
480
        break;
473
    }
481
    }
474
   
482
   
475
    return EE_OK;
483
    return EE_OK;
476
}
484
}
477
 
485
 
478
/** @}
486
/** @}
479
 */
487
 */
480
 
488