OpenCores
URL https://opencores.org/ocsvn/c0or1k/c0or1k/trunk

Subversion Repositories c0or1k

[/] [c0or1k/] [trunk/] [conts/] [posix/] [mm0/] [lib/] [elf/] [elf.c] - Blame information for rev 2

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 2 drasko
/*
2
 * ELF manipulation routines
3
 *
4
 * Copyright (C) 2008 Bahadir Balban
5
 */
6
#include <memory.h>
7
#include <vm_area.h>
8
#include <l4/api/errno.h>
9
#include <lib/elf/elf.h>
10
#include <lib/elf/elfprg.h>
11
#include <lib/elf/elfsym.h>
12
#include <lib/elf/elfsect.h>
13
 
14
 
15
int elf_probe(struct elf_header *header)
16
{
17
        /* Test that it is a 32-bit little-endian ELF file */
18
        if (header->e_ident[EI_MAG0] == ELFMAG0 &&
19
            header->e_ident[EI_MAG1] == ELFMAG1 &&
20
            header->e_ident[EI_MAG2] == ELFMAG2 &&
21
            header->e_ident[EI_MAG3] == ELFMAG3 &&
22
            header->e_ident[EI_CLASS] == ELFCLASS32 &&
23
            header->e_ident[EI_DATA] == ELFDATA2LSB)
24
                return 0;
25
        else
26
                return -1;
27
}
28
 
29
/*
30
 * Sets or expands a segment region if it has the given type and flags
31
 * For expansion we assume any new section must come consecutively
32
 * after the existing segment, otherwise we ignore it for simplicity.
33
 */
34
int elf_test_expand_segment(struct elf_section_header *section,
35
                            unsigned int sec_type, unsigned int sec_flags,
36
                            unsigned int sec_flmask, unsigned long *start,
37
                            unsigned long *end, unsigned long *offset)
38
{
39
        if (section->sh_type == sec_type &&
40
            (section->sh_flags & sec_flmask) == sec_flags) {
41
                /* Set new section */
42
                if (!*start) {
43
                        BUG_ON(*offset || *end);
44
                        *offset = section->sh_offset;
45
                        *start = section->sh_addr;
46
                        *end = section->sh_addr + section->sh_size;
47
                /* Expand existing section from the end */
48
                } else if (*end == section->sh_addr)
49
                        *end = section->sh_addr + section->sh_size;
50
        }
51
 
52
        return 0;
53
}
54
 
55
/*
56
 * Sift through sections and copy their marks to tcb and efd
57
 * if they are recognised and loadable sections. Test the
58
 * assigned segment marks and return an error if they're invalid.
59
 */
60
int elf_mark_segments(struct elf_section_header *sect_header, int nsections,
61
                      struct tcb *task, struct exec_file_desc *efd)
62
{
63
        for (int i = 0; i < nsections; i++) {
64
                struct elf_section_header *section = &sect_header[i];
65
 
66
                /* Text + read-only data segments */
67
                elf_test_expand_segment(section, SHT_PROGBITS,
68
                                        SHF_ALLOC, SHF_ALLOC | SHF_WRITE,
69
                                        &task->text_start, &task->text_end,
70
                                        &efd->text_offset);
71
 
72
                /* Data segment */
73
                elf_test_expand_segment(section, SHT_PROGBITS, SHF_ALLOC |
74
                                        SHF_WRITE, SHF_ALLOC | SHF_WRITE,
75
                                        &task->data_start, &task->data_end,
76
                                        &efd->data_offset);
77
 
78
                /* Bss segment */
79
                elf_test_expand_segment(section, SHT_NOBITS, SHF_ALLOC |
80
                                        SHF_WRITE, SHF_ALLOC | SHF_WRITE,
81
                                        &task->bss_start, &task->bss_end,
82
                                        &efd->bss_offset);
83
        }
84
 
85
        /* Test anomalies with the mappings */
86
 
87
        /* No text */
88
        if (!task->text_start) {
89
                printf("%s: Error: Could not find a text "
90
                       "segment in ELF file.\n", __FUNCTION__);
91
                return -ENOEXEC;
92
        }
93
 
94
        /* Warn if no data or bss but it's not an error */
95
        if (!task->data_start || !task->bss_start) {
96
                printf("%s: NOTE: Could not find a data and/or "
97
                       "bss segment in ELF file.\n", __FUNCTION__);
98
        }
99
 
100
        /* Data and text are on the same page and not on a page boundary */
101
        if (!((is_page_aligned(task->data_start) &&
102
              task->data_start == task->text_end) ||
103
              (page_align(task->data_start) > page_align(task->text_end))))
104
        if ((task->data_start - task->text_end) < PAGE_SIZE &&
105
            !is_page_aligned(task->text_end)) {
106
                printf("%s: Error: Distance between data and text"
107
                       " sections are less than page size (%d bytes)\n",
108
                       __FUNCTION__, PAGE_SIZE);
109
                return -ENOEXEC;
110
        }
111
 
112
        return 0;
113
}
114
 
115
/*
116
 * Loading an ELF file:
117
 *
118
 * This first probes and detects that the given file is a valid elf file.
119
 * Then it looks at the program header table to find the first (probably
120
 * only) segment that has type LOAD. Then it looks at the section header
121
 * table, to find out about every loadable section that is part of this
122
 * aforementioned loadable program segment. Each section is marked in the
123
 * efd and tcb structures for further memory mappings.
124
 */
125
int elf_parse_executable(struct tcb *task, struct vm_file *file,
126
                         struct exec_file_desc *efd)
127
{
128
        struct elf_header elf_header, *elf_headerp = pager_map_page(file, 0);
129
        struct elf_program_header *prg_header_start, *prg_header_load;
130
        struct elf_section_header *sect_header;
131
        unsigned long sect_offset, sect_size;
132
        unsigned long prg_offset, prg_size;
133
        int err = 0;
134
 
135
        /* Test that it is a valid elf file */
136
        if ((err = elf_probe(elf_headerp)) < 0)
137
                return err;
138
 
139
        /* Copy the elf header and unmap first page */
140
        memcpy(&elf_header, elf_headerp, sizeof(elf_header));
141
        pager_unmap_page(elf_headerp);
142
 
143
        /* Find the markers for section and program header tables */
144
        sect_offset = elf_header.e_shoff;
145
        sect_size = elf_header.e_shentsize * elf_header.e_shnum;
146
 
147
        prg_offset = elf_header.e_phoff;
148
        prg_size = elf_header.e_phentsize * elf_header.e_phnum;
149
 
150
        /* Get the program header table */
151
        prg_header_start = (struct elf_program_header *)
152
                           pager_map_file_range(file, prg_offset, prg_size);
153
 
154
        /* Get the first loadable segment. We currently just stare at it */
155
        for (int i = 0; i < elf_header.e_phnum; i++) {
156
                if (prg_header_start[i].p_type == PT_LOAD) {
157
                        prg_header_load = &prg_header_start[i];
158
                        break;
159
                }
160
        }
161
 
162
        /* Get the section header table */
163
        sect_header = (struct elf_section_header *)
164
                      pager_map_file_range(file, sect_offset, sect_size);
165
 
166
        /* Copy segment marks from ELF file to task + efd. Return errors */
167
        err = elf_mark_segments(sect_header, elf_header.e_shnum, task, efd);
168
 
169
        /* Unmap program header table */
170
        pager_unmap_pages(prg_header_start, __pfn(page_align_up(prg_size)));
171
 
172
        /* Unmap section header table */
173
        pager_unmap_pages(sect_header, __pfn(page_align_up(sect_size)));
174
 
175
        return err;
176
}
177
 

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.