Subversion Repositories HelenOS

Rev

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

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