Subversion Repositories HelenOS

Rev

Rev 3772 | Go to most recent revision | Show entire file | Ignore whitespace | Details | Blame | Last modification | View Log | RSS feed

Rev 3772 Rev 4338
Line 55... Line 55...
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(...)
-
 
61
 
60
static char *error_codes[] = {
62
static char *error_codes[] = {
61
    "no error",
63
    "no error",
62
    "invalid image",
64
    "invalid image",
63
    "address space error",
65
    "address space error",
64
    "incompatible image",
66
    "incompatible image",
Line 105... Line 107...
105
    elf_ld_t elf;
107
    elf_ld_t elf;
106
 
108
 
107
    int fd;
109
    int fd;
108
    int rc;
110
    int rc;
109
 
111
 
110
//  printf("open and read '%s'...\n", file_name);
-
 
111
 
-
 
112
    fd = open(file_name, O_RDONLY);
112
    fd = open(file_name, O_RDONLY);
113
    if (fd < 0) {
113
    if (fd < 0) {
114
        printf("failed opening file (error %d)\n", fd);
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;
Line 158... Line 158...
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
        printf("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
//  printf("ELF-load:");
-
 
170
    /* Identify ELF */
169
    /* Identify ELF */
171
    if (header->e_ident[EI_MAG0] != ELFMAG0 ||
170
    if (header->e_ident[EI_MAG0] != ELFMAG0 ||
172
        header->e_ident[EI_MAG1] != ELFMAG1 ||
171
        header->e_ident[EI_MAG1] != ELFMAG1 ||
173
        header->e_ident[EI_MAG2] != ELFMAG2 ||
172
        header->e_ident[EI_MAG2] != ELFMAG2 ||
174
        header->e_ident[EI_MAG3] != ELFMAG3) {
173
        header->e_ident[EI_MAG3] != ELFMAG3) {
175
        printf("invalid header\n");
174
        DPRINTF("Invalid header.\n");
176
        return EE_INVALID;
175
        return EE_INVALID;
177
    }
176
    }
178
   
177
   
179
    /* Identify ELF compatibility */
178
    /* Identify ELF compatibility */
180
    if (header->e_ident[EI_DATA] != ELF_DATA_ENCODING ||
179
    if (header->e_ident[EI_DATA] != ELF_DATA_ENCODING ||
181
        header->e_machine != ELF_MACHINE ||
180
        header->e_machine != ELF_MACHINE ||
182
        header->e_ident[EI_VERSION] != EV_CURRENT ||
181
        header->e_ident[EI_VERSION] != EV_CURRENT ||
183
        header->e_version != EV_CURRENT ||
182
        header->e_version != EV_CURRENT ||
184
        header->e_ident[EI_CLASS] != ELF_CLASS) {
183
        header->e_ident[EI_CLASS] != ELF_CLASS) {
185
        printf("incompatible data/version/class\n");
184
        DPRINTF("Incompatible data/version/class.\n");
186
        return EE_INCOMPATIBLE;
185
        return EE_INCOMPATIBLE;
187
    }
186
    }
188
 
187
 
189
    if (header->e_phentsize != sizeof(elf_segment_header_t)) {
188
    if (header->e_phentsize != sizeof(elf_segment_header_t)) {
190
        printf("e_phentsize:%d != %d\n", header->e_phentsize,
189
        DPRINTF("e_phentsize:%d != %d\n", header->e_phentsize,
191
            sizeof(elf_segment_header_t));
190
            sizeof(elf_segment_header_t));
192
        return EE_INCOMPATIBLE;
191
        return EE_INCOMPATIBLE;
193
    }
192
    }
194
 
193
 
195
    if (header->e_shentsize != sizeof(elf_section_header_t)) {
194
    if (header->e_shentsize != sizeof(elf_section_header_t)) {
196
        printf("e_shentsize:%d != %d\n", header->e_shentsize,
195
        DPRINTF("e_shentsize:%d != %d\n", header->e_shentsize,
197
            sizeof(elf_section_header_t));
196
            sizeof(elf_section_header_t));
198
        return EE_INCOMPATIBLE;
197
        return EE_INCOMPATIBLE;
199
    }
198
    }
200
 
199
 
201
    /* Check if the object type is supported. */
200
    /* Check if the object type is supported. */
202
    if (header->e_type != ET_EXEC && header->e_type != ET_DYN) {
201
    if (header->e_type != ET_EXEC && header->e_type != ET_DYN) {
203
        printf("Object type %d is not supported\n", header->e_type);
202
        DPRINTF("Object type %d is not supported\n", header->e_type);
204
        return EE_UNSUPPORTED;
203
        return EE_UNSUPPORTED;
205
    }
204
    }
206
 
205
 
207
    /* Shared objects can be loaded with a bias */
206
    /* Shared objects can be loaded with a bias */
208
//  printf("Object type: %d\n", header->e_type);
-
 
209
    if (header->e_type == ET_DYN)
207
    if (header->e_type == ET_DYN)
210
        elf->bias = so_bias;
208
        elf->bias = so_bias;
211
    else
209
    else
212
        elf->bias = 0;
210
        elf->bias = 0;
213
 
211
 
214
//  printf("Bias set to 0x%x\n", elf->bias);
-
 
215
    elf->info->interp = NULL;
212
    elf->info->interp = NULL;
216
    elf->info->dynamic = NULL;
213
    elf->info->dynamic = NULL;
217
 
214
 
218
//  printf("parse segments\n");
-
 
219
 
-
 
220
    /* Walk through all segment headers and process them. */
215
    /* Walk through all segment headers and process them. */
221
    for (i = 0; i < header->e_phnum; i++) {
216
    for (i = 0; i < header->e_phnum; i++) {
222
        elf_segment_header_t segment_hdr;
217
        elf_segment_header_t segment_hdr;
223
 
218
 
224
        /* Seek to start of segment header */
219
        /* Seek to start of segment header */
Line 226... Line 221...
226
                + i * sizeof(elf_segment_header_t), SEEK_SET);
221
                + i * sizeof(elf_segment_header_t), SEEK_SET);
227
 
222
 
228
        rc = my_read(elf->fd, &segment_hdr,
223
        rc = my_read(elf->fd, &segment_hdr,
229
            sizeof(elf_segment_header_t));
224
            sizeof(elf_segment_header_t));
230
        if (rc < 0) {
225
        if (rc < 0) {
231
            printf("read error\n");
226
            DPRINTF("Read error.\n");
232
            return EE_INVALID;
227
            return EE_INVALID;
233
        }
228
        }
234
 
229
 
235
        rc = segment_header(elf, &segment_hdr);
230
        rc = segment_header(elf, &segment_hdr);
236
        if (rc != EE_OK)
231
        if (rc != EE_OK)
237
            return rc;
232
            return rc;
238
    }
233
    }
239
 
234
 
240
//  printf("parse sections\n");
235
    DPRINTF("Parse sections.\n");
241
 
236
 
242
    /* Inspect all section headers and proccess them. */
237
    /* Inspect all section headers and proccess them. */
243
    for (i = 0; i < header->e_shnum; i++) {
238
    for (i = 0; i < header->e_shnum; i++) {
244
        elf_section_header_t section_hdr;
239
        elf_section_header_t section_hdr;
245
 
240
 
Line 248... Line 243...
248
            + i * sizeof(elf_section_header_t), SEEK_SET);
243
            + i * sizeof(elf_section_header_t), SEEK_SET);
249
 
244
 
250
        rc = my_read(elf->fd, &section_hdr,
245
        rc = my_read(elf->fd, &section_hdr,
251
            sizeof(elf_section_header_t));
246
            sizeof(elf_section_header_t));
252
        if (rc < 0) {
247
        if (rc < 0) {
253
            printf("read error\n");
248
            DPRINTF("Read error.\n");
254
            return EE_INVALID;
249
            return EE_INVALID;
255
        }
250
        }
256
 
251
 
257
        rc = section_header(elf, &section_hdr);
252
        rc = section_header(elf, &section_hdr);
258
        if (rc != EE_OK)
253
        if (rc != EE_OK)
Line 260... Line 255...
260
    }
255
    }
261
 
256
 
262
    elf->info->entry =
257
    elf->info->entry =
263
        (entry_point_t)((uint8_t *)header->e_entry + elf->bias);
258
        (entry_point_t)((uint8_t *)header->e_entry + elf->bias);
264
 
259
 
265
//  printf("done\n");
260
    DPRINTF("Done.\n");
266
 
261
 
267
    return EE_OK;
262
    return EE_OK;
268
}
263
}
269
 
264
 
270
/** Print error message according to error code.
265
/** Print error message according to error code.
Line 301... Line 296...
301
        break;
296
        break;
302
    case PT_DYNAMIC:
297
    case PT_DYNAMIC:
303
        /* Record pointer to dynamic section into info structure */
298
        /* Record pointer to dynamic section into info structure */
304
        elf->info->dynamic =
299
        elf->info->dynamic =
305
            (void *)((uint8_t *)entry->p_vaddr + elf->bias);
300
            (void *)((uint8_t *)entry->p_vaddr + elf->bias);
306
        printf("dynamic section found at 0x%x\n",
301
        DPRINTF("dynamic section found at 0x%x\n",
307
            (uintptr_t)elf->info->dynamic);
302
            (uintptr_t)elf->info->dynamic);
308
        break;
303
        break;
309
    case 0x70000000:
304
    case 0x70000000:
310
        /* FIXME: MIPS reginfo */
305
        /* FIXME: MIPS reginfo */
311
        break;
306
        break;
312
    case PT_SHLIB:
307
    case PT_SHLIB:
313
    case PT_NOTE:
308
    case PT_NOTE:
314
//  case PT_LOPROC:
309
//  case PT_LOPROC:
315
//  case PT_HIPROC:
310
//  case PT_HIPROC:
316
    default:
311
    default:
317
        printf("segment p_type %d unknown\n", entry->p_type);
312
        DPRINTF("Segment p_type %d unknown.\n", entry->p_type);
318
        return EE_UNSUPPORTED;
313
        return EE_UNSUPPORTED;
319
        break;
314
        break;
320
    }
315
    }
321
    return EE_OK;
316
    return EE_OK;
322
}
317
}
Line 335... Line 330...
335
    uintptr_t bias;
330
    uintptr_t bias;
336
    uintptr_t base;
331
    uintptr_t base;
337
    size_t mem_sz;
332
    size_t mem_sz;
338
    int rc;
333
    int rc;
339
 
334
 
340
//  printf("load segment at addr 0x%x, size 0x%x\n", entry->p_vaddr,
335
    DPRINTF("Load segment at addr 0x%x, size 0x%x\n", entry->p_vaddr,
341
//      entry->p_memsz);
336
        entry->p_memsz);
342
   
337
   
343
    bias = elf->bias;
338
    bias = elf->bias;
344
 
339
 
345
    if (entry->p_align > 1) {
340
    if (entry->p_align > 1) {
346
        if ((entry->p_offset % entry->p_align) !=
341
        if ((entry->p_offset % entry->p_align) !=
347
            (entry->p_vaddr % entry->p_align)) {
342
            (entry->p_vaddr % entry->p_align)) {
348
            printf("align check 1 failed offset%%align=%d, "
343
            DPRINTF("Align check 1 failed offset%%align=%d, "
349
                "vaddr%%align=%d\n",
344
                "vaddr%%align=%d\n",
350
                entry->p_offset % entry->p_align,
345
                entry->p_offset % entry->p_align,
351
                entry->p_vaddr % entry->p_align
346
                entry->p_vaddr % entry->p_align
352
            );
347
            );
353
            return EE_INVALID;
348
            return EE_INVALID;
Line 365... Line 360...
365
    flags |= AS_AREA_CACHEABLE;
360
    flags |= AS_AREA_CACHEABLE;
366
   
361
   
367
    base = ALIGN_DOWN(entry->p_vaddr, PAGE_SIZE);
362
    base = ALIGN_DOWN(entry->p_vaddr, PAGE_SIZE);
368
    mem_sz = entry->p_memsz + (entry->p_vaddr - base);
363
    mem_sz = entry->p_memsz + (entry->p_vaddr - base);
369
 
364
 
370
//  printf("map to p_vaddr=0x%x-0x%x...\n", entry->p_vaddr + bias,
365
    DPRINTF("Map to p_vaddr=0x%x-0x%x.\n", entry->p_vaddr + bias,
371
//  entry->p_vaddr + bias + ALIGN_UP(entry->p_memsz, PAGE_SIZE));
366
    entry->p_vaddr + bias + ALIGN_UP(entry->p_memsz, PAGE_SIZE));
372
 
367
 
373
    /*
368
    /*
374
     * For the course of loading, the area needs to be readable
369
     * For the course of loading, the area needs to be readable
375
     * and writeable.
370
     * and writeable.
376
     */
371
     */
377
    a = as_area_create((uint8_t *)base + bias, mem_sz,
372
    a = as_area_create((uint8_t *)base + bias, mem_sz,
378
        AS_AREA_READ | AS_AREA_WRITE | AS_AREA_CACHEABLE);
373
        AS_AREA_READ | AS_AREA_WRITE | AS_AREA_CACHEABLE);
379
    if (a == (void *)(-1)) {
374
    if (a == (void *)(-1)) {
380
        printf("memory mapping failed (0x%x, %d)\n",
375
        DPRINTF("memory mapping failed (0x%x, %d)\n",
381
            base+bias, mem_sz);
376
            base+bias, mem_sz);
382
        return EE_MEMORY;
377
        return EE_MEMORY;
383
    }
378
    }
384
 
379
 
385
//  printf("as_area_create(0x%lx, 0x%x, %d) -> 0x%lx\n",
380
    DPRINTF("as_area_create(0x%lx, 0x%x, %d) -> 0x%lx\n",
386
//      entry->p_vaddr+bias, entry->p_memsz, flags, (uintptr_t)a);
381
        entry->p_vaddr+bias, entry->p_memsz, flags, (uintptr_t)a);
387
 
382
 
388
    /*
383
    /*
389
     * Load segment data
384
     * Load segment data
390
     */
385
     */
391
//  printf("seek to %d\n", entry->p_offset);
-
 
392
    rc = lseek(elf->fd, entry->p_offset, SEEK_SET);
386
    rc = lseek(elf->fd, entry->p_offset, SEEK_SET);
393
    if (rc < 0) {
387
    if (rc < 0) {
394
        printf("seek error\n");
388
        printf("seek error\n");
395
        return EE_INVALID;
389
        return EE_INVALID;
396
    }
390
    }
397
 
391
 
398
//  printf("read 0x%x bytes to address 0x%x\n", entry->p_filesz, entry->p_vaddr+bias);
-
 
399
/*  rc = read(fd, (void *)(entry->p_vaddr + bias), entry->p_filesz);
392
/*  rc = read(fd, (void *)(entry->p_vaddr + bias), entry->p_filesz);
400
    if (rc < 0) { printf("read error\n"); return EE_INVALID; }*/
393
    if (rc < 0) { printf("read error\n"); return EE_INVALID; }*/
401
 
394
 
402
    /* Long reads are not possible yet. Load segment picewise */
395
    /* Long reads are not possible yet. Load segment piecewise. */
403
 
396
 
404
    unsigned left, now;
397
    unsigned left, now;
405
    uint8_t *dp;
398
    uint8_t *dp;
406
 
399
 
407
    left = entry->p_filesz;
400
    left = entry->p_filesz;
Line 409... Line 402...
409
 
402
 
410
    while (left > 0) {
403
    while (left > 0) {
411
        now = 16384;
404
        now = 16384;
412
        if (now > left) now = left;
405
        if (now > left) now = left;
413
 
406
 
414
//      printf("read %d...", now);
-
 
415
        rc = my_read(elf->fd, dp, now);
407
        rc = my_read(elf->fd, dp, now);
416
//      printf("->%d\n", rc);
-
 
417
 
408
 
418
        if (rc < 0) {
409
        if (rc < 0) {
419
            printf("read error\n");
410
            DPRINTF("Read error.\n");
420
            return EE_INVALID;
411
            return EE_INVALID;
421
        }
412
        }
422
 
413
 
423
        left -= now;
414
        left -= now;
424
        dp += now;
415
        dp += now;
Line 431... Line 422...
431
    if ((elf->flags & ELDF_RW) != 0) return EE_OK;
422
    if ((elf->flags & ELDF_RW) != 0) return EE_OK;
432
 
423
 
433
//  printf("set area flags to %d\n", flags);
424
//  printf("set area flags to %d\n", flags);
434
    rc = as_area_change_flags((uint8_t *)entry->p_vaddr + bias, flags);
425
    rc = as_area_change_flags((uint8_t *)entry->p_vaddr + bias, flags);
435
    if (rc != 0) {
426
    if (rc != 0) {
436
        printf("failed to set memory area flags\n");
427
        DPRINTF("Failed to set memory area flags.\n");
437
        return EE_MEMORY;
428
        return EE_MEMORY;
438
    }
429
    }
439
 
430
 
440
    if (flags & AS_AREA_EXEC) {
431
    if (flags & AS_AREA_EXEC) {
441
        /* Enforce SMC coherence for the segment */
432
        /* Enforce SMC coherence for the segment */