Statistics
| Branch: | Revision:

root / hw / elf_ops.h @ 09b26c5e

History | View | Annotate | Download (5.7 kB)

1 3475187d bellard
#ifdef BSWAP_NEEDED
2 3475187d bellard
static void glue(bswap_ehdr, SZ)(struct elfhdr *ehdr)
3 3475187d bellard
{
4 3475187d bellard
    bswap16s(&ehdr->e_type);                        /* Object file type */
5 3475187d bellard
    bswap16s(&ehdr->e_machine);                /* Architecture */
6 3475187d bellard
    bswap32s(&ehdr->e_version);                /* Object file version */
7 3475187d bellard
    bswapSZs(&ehdr->e_entry);                /* Entry point virtual address */
8 3475187d bellard
    bswapSZs(&ehdr->e_phoff);                /* Program header table file offset */
9 3475187d bellard
    bswapSZs(&ehdr->e_shoff);                /* Section header table file offset */
10 3475187d bellard
    bswap32s(&ehdr->e_flags);                /* Processor-specific flags */
11 3475187d bellard
    bswap16s(&ehdr->e_ehsize);                /* ELF header size in bytes */
12 3475187d bellard
    bswap16s(&ehdr->e_phentsize);                /* Program header table entry size */
13 3475187d bellard
    bswap16s(&ehdr->e_phnum);                /* Program header table entry count */
14 3475187d bellard
    bswap16s(&ehdr->e_shentsize);                /* Section header table entry size */
15 3475187d bellard
    bswap16s(&ehdr->e_shnum);                /* Section header table entry count */
16 3475187d bellard
    bswap16s(&ehdr->e_shstrndx);                /* Section header string table index */
17 3475187d bellard
}
18 3475187d bellard
19 3475187d bellard
static void glue(bswap_phdr, SZ)(struct elf_phdr *phdr)
20 3475187d bellard
{
21 3475187d bellard
    bswap32s(&phdr->p_type);                        /* Segment type */
22 3475187d bellard
    bswapSZs(&phdr->p_offset);                /* Segment file offset */
23 3475187d bellard
    bswapSZs(&phdr->p_vaddr);                /* Segment virtual address */
24 3475187d bellard
    bswapSZs(&phdr->p_paddr);                /* Segment physical address */
25 3475187d bellard
    bswapSZs(&phdr->p_filesz);                /* Segment size in file */
26 3475187d bellard
    bswapSZs(&phdr->p_memsz);                /* Segment size in memory */
27 3475187d bellard
    bswap32s(&phdr->p_flags);                /* Segment flags */
28 3475187d bellard
    bswapSZs(&phdr->p_align);                /* Segment alignment */
29 3475187d bellard
}
30 3475187d bellard
31 3475187d bellard
static void glue(bswap_shdr, SZ)(struct elf_shdr *shdr)
32 3475187d bellard
{
33 3475187d bellard
    bswap32s(&shdr->sh_name);
34 3475187d bellard
    bswap32s(&shdr->sh_type);
35 3475187d bellard
    bswapSZs(&shdr->sh_flags);
36 3475187d bellard
    bswapSZs(&shdr->sh_addr);
37 3475187d bellard
    bswapSZs(&shdr->sh_offset);
38 3475187d bellard
    bswapSZs(&shdr->sh_size);
39 3475187d bellard
    bswap32s(&shdr->sh_link);
40 3475187d bellard
    bswap32s(&shdr->sh_info);
41 3475187d bellard
    bswapSZs(&shdr->sh_addralign);
42 3475187d bellard
    bswapSZs(&shdr->sh_entsize);
43 3475187d bellard
}
44 3475187d bellard
45 3475187d bellard
static void glue(bswap_sym, SZ)(struct elf_sym *sym)
46 3475187d bellard
{
47 3475187d bellard
    bswap32s(&sym->st_name);
48 3475187d bellard
    bswapSZs(&sym->st_value);
49 3475187d bellard
    bswapSZs(&sym->st_size);
50 3475187d bellard
    bswap16s(&sym->st_shndx);
51 3475187d bellard
}
52 3475187d bellard
#endif
53 3475187d bellard
54 3475187d bellard
static int glue(find_phdr, SZ)(struct elfhdr *ehdr, int fd, struct elf_phdr *phdr, elf_word type)
55 3475187d bellard
{
56 3475187d bellard
    int i, retval;
57 3475187d bellard
58 3475187d bellard
    retval = lseek(fd, ehdr->e_phoff, SEEK_SET);
59 3475187d bellard
    if (retval < 0)
60 3475187d bellard
        return -1;
61 3475187d bellard
62 3475187d bellard
    for (i = 0; i < ehdr->e_phnum; i++) {
63 3475187d bellard
        retval = read(fd, phdr, sizeof(*phdr));
64 3475187d bellard
        if (retval < 0)
65 3475187d bellard
            return -1;
66 3475187d bellard
        glue(bswap_phdr, SZ)(phdr);
67 3475187d bellard
        if (phdr->p_type == type)
68 3475187d bellard
            return 0;
69 3475187d bellard
    }
70 3475187d bellard
    return -1;
71 3475187d bellard
}
72 3475187d bellard
73 3475187d bellard
static void * glue(find_shdr, SZ)(struct elfhdr *ehdr, int fd, struct elf_shdr *shdr, elf_word type)
74 3475187d bellard
{
75 3475187d bellard
    int i, retval;
76 3475187d bellard
77 3475187d bellard
    retval = lseek(fd, ehdr->e_shoff, SEEK_SET);
78 3475187d bellard
    if (retval < 0)
79 3475187d bellard
        return NULL;
80 3475187d bellard
81 3475187d bellard
    for (i = 0; i < ehdr->e_shnum; i++) {
82 3475187d bellard
        retval = read(fd, shdr, sizeof(*shdr));
83 3475187d bellard
        if (retval < 0)
84 3475187d bellard
            return NULL;
85 3475187d bellard
        glue(bswap_shdr, SZ)(shdr);
86 3475187d bellard
        if (shdr->sh_type == type)
87 3475187d bellard
            return qemu_malloc(shdr->sh_size);
88 3475187d bellard
    }
89 3475187d bellard
    return NULL;
90 3475187d bellard
}
91 3475187d bellard
92 3475187d bellard
static void * glue(find_strtab, SZ)(struct elfhdr *ehdr, int fd, struct elf_shdr *shdr, struct elf_shdr *symtab)
93 3475187d bellard
{
94 3475187d bellard
    int retval;
95 3475187d bellard
96 3475187d bellard
    retval = lseek(fd, ehdr->e_shoff + sizeof(struct elf_shdr) * symtab->sh_link, SEEK_SET);
97 3475187d bellard
    if (retval < 0)
98 3475187d bellard
        return NULL;
99 3475187d bellard
100 3475187d bellard
    retval = read(fd, shdr, sizeof(*shdr));
101 3475187d bellard
    if (retval < 0)
102 3475187d bellard
        return NULL;
103 3475187d bellard
    glue(bswap_shdr, SZ)(shdr);
104 3475187d bellard
    if (shdr->sh_type == SHT_STRTAB)
105 3475187d bellard
        return qemu_malloc(shdr->sh_size);;
106 3475187d bellard
    return NULL;
107 3475187d bellard
}
108 3475187d bellard
109 3475187d bellard
static int glue(read_program, SZ)(int fd, struct elf_phdr *phdr, void *dst, elf_word entry)
110 3475187d bellard
{
111 3475187d bellard
    int retval;
112 3475187d bellard
    retval = lseek(fd, phdr->p_offset + entry - phdr->p_vaddr, SEEK_SET);
113 3475187d bellard
    if (retval < 0)
114 3475187d bellard
        return -1;
115 3475187d bellard
    return read(fd, dst, phdr->p_filesz);
116 3475187d bellard
}
117 3475187d bellard
118 3475187d bellard
static int glue(read_section, SZ)(int fd, struct elf_shdr *s, void *dst)
119 3475187d bellard
{
120 3475187d bellard
    int retval;
121 3475187d bellard
122 3475187d bellard
    retval = lseek(fd, s->sh_offset, SEEK_SET);
123 3475187d bellard
    if (retval < 0)
124 3475187d bellard
        return -1;
125 3475187d bellard
    retval = read(fd, dst, s->sh_size);
126 3475187d bellard
    if (retval < 0)
127 3475187d bellard
        return -1;
128 3475187d bellard
    return 0;
129 3475187d bellard
}
130 3475187d bellard
131 3475187d bellard
static void * glue(process_section, SZ)(struct elfhdr *ehdr, int fd, struct elf_shdr *shdr, elf_word type)
132 3475187d bellard
{
133 3475187d bellard
    void *dst;
134 3475187d bellard
135 3475187d bellard
    dst = glue(find_shdr, SZ)(ehdr, fd, shdr, type);
136 3475187d bellard
    if (!dst)
137 3475187d bellard
        goto error;
138 3475187d bellard
139 3475187d bellard
    if (glue(read_section, SZ)(fd, shdr, dst))
140 3475187d bellard
        goto error;
141 3475187d bellard
    return dst;
142 3475187d bellard
 error:
143 3475187d bellard
    qemu_free(dst);
144 3475187d bellard
    return NULL;
145 3475187d bellard
}
146 3475187d bellard
147 3475187d bellard
static void * glue(process_strtab, SZ)(struct elfhdr *ehdr, int fd, struct elf_shdr *shdr, struct elf_shdr *symtab)
148 3475187d bellard
{
149 3475187d bellard
    void *dst;
150 3475187d bellard
151 3475187d bellard
    dst = glue(find_strtab, SZ)(ehdr, fd, shdr, symtab);
152 3475187d bellard
    if (!dst)
153 3475187d bellard
        goto error;
154 3475187d bellard
155 3475187d bellard
    if (glue(read_section, SZ)(fd, shdr, dst))
156 3475187d bellard
        goto error;
157 3475187d bellard
    return dst;
158 3475187d bellard
 error:
159 3475187d bellard
    qemu_free(dst);
160 3475187d bellard
    return NULL;
161 3475187d bellard
}
162 3475187d bellard
163 3475187d bellard
static void glue(load_symbols, SZ)(struct elfhdr *ehdr, int fd)
164 3475187d bellard
{
165 3475187d bellard
    struct elf_shdr symtab, strtab;
166 3475187d bellard
    struct elf_sym *syms;
167 3475187d bellard
#if (SZ == 64)
168 3475187d bellard
    struct elf32_sym *syms32;
169 3475187d bellard
#endif
170 3475187d bellard
    struct syminfo *s;
171 3475187d bellard
    int nsyms, i;
172 3475187d bellard
    char *str;
173 3475187d bellard
174 3475187d bellard
    /* Symbol table */
175 3475187d bellard
    syms = glue(process_section, SZ)(ehdr, fd, &symtab, SHT_SYMTAB);
176 3475187d bellard
    if (!syms)
177 3475187d bellard
        return;
178 3475187d bellard
179 3475187d bellard
    nsyms = symtab.sh_size / sizeof(struct elf_sym);
180 3475187d bellard
#if (SZ == 64)
181 3475187d bellard
    syms32 = qemu_mallocz(nsyms * sizeof(struct elf32_sym));
182 3475187d bellard
#endif
183 3475187d bellard
    for (i = 0; i < nsyms; i++) {
184 3475187d bellard
        glue(bswap_sym, SZ)(&syms[i]);
185 3475187d bellard
#if (SZ == 64)
186 3475187d bellard
        syms32[i].st_name = syms[i].st_name;
187 3475187d bellard
        syms32[i].st_info = syms[i].st_info;
188 3475187d bellard
        syms32[i].st_other = syms[i].st_other;
189 3475187d bellard
        syms32[i].st_shndx = syms[i].st_shndx;
190 3475187d bellard
        syms32[i].st_value = syms[i].st_value & 0xffffffff;
191 3475187d bellard
        syms32[i].st_size = syms[i].st_size & 0xffffffff;
192 3475187d bellard
#endif
193 3475187d bellard
    }
194 3475187d bellard
    /* String table */
195 3475187d bellard
    str = glue(process_strtab, SZ)(ehdr, fd, &strtab, &symtab);
196 3475187d bellard
    if (!str)
197 3475187d bellard
        goto error_freesyms;
198 3475187d bellard
199 3475187d bellard
    /* Commit */
200 3475187d bellard
    s = qemu_mallocz(sizeof(*s));
201 3475187d bellard
#if (SZ == 64)
202 3475187d bellard
    s->disas_symtab = syms32;
203 3475187d bellard
    qemu_free(syms);
204 3475187d bellard
#else
205 3475187d bellard
    s->disas_symtab = syms;
206 3475187d bellard
#endif
207 3475187d bellard
    s->disas_num_syms = nsyms;
208 3475187d bellard
    s->disas_strtab = str;
209 3475187d bellard
    s->next = syminfos;
210 3475187d bellard
    syminfos = s;
211 3475187d bellard
    return;
212 3475187d bellard
 error_freesyms:
213 3475187d bellard
#if (SZ == 64)
214 3475187d bellard
    qemu_free(syms32);
215 3475187d bellard
#endif
216 3475187d bellard
    qemu_free(syms);
217 3475187d bellard
    return;
218 3475187d bellard
}