Subversion Repositories HelenOS

Rev

Rev 4338 | Only display areas with differences | Ignore whitespace | Details | Blame | Last modification | View Log | RSS feed

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