Statistics
| Branch: | Revision:

root / hw / elf_ops.h @ 3475187d

History | View | Annotate | Download (5.7 kB)

1
#ifdef BSWAP_NEEDED
2
static void glue(bswap_ehdr, SZ)(struct elfhdr *ehdr)
3
{
4
    bswap16s(&ehdr->e_type);                        /* Object file type */
5
    bswap16s(&ehdr->e_machine);                /* Architecture */
6
    bswap32s(&ehdr->e_version);                /* Object file version */
7
    bswapSZs(&ehdr->e_entry);                /* Entry point virtual address */
8
    bswapSZs(&ehdr->e_phoff);                /* Program header table file offset */
9
    bswapSZs(&ehdr->e_shoff);                /* Section header table file offset */
10
    bswap32s(&ehdr->e_flags);                /* Processor-specific flags */
11
    bswap16s(&ehdr->e_ehsize);                /* ELF header size in bytes */
12
    bswap16s(&ehdr->e_phentsize);                /* Program header table entry size */
13
    bswap16s(&ehdr->e_phnum);                /* Program header table entry count */
14
    bswap16s(&ehdr->e_shentsize);                /* Section header table entry size */
15
    bswap16s(&ehdr->e_shnum);                /* Section header table entry count */
16
    bswap16s(&ehdr->e_shstrndx);                /* Section header string table index */
17
}
18

    
19
static void glue(bswap_phdr, SZ)(struct elf_phdr *phdr)
20
{
21
    bswap32s(&phdr->p_type);                        /* Segment type */
22
    bswapSZs(&phdr->p_offset);                /* Segment file offset */
23
    bswapSZs(&phdr->p_vaddr);                /* Segment virtual address */
24
    bswapSZs(&phdr->p_paddr);                /* Segment physical address */
25
    bswapSZs(&phdr->p_filesz);                /* Segment size in file */
26
    bswapSZs(&phdr->p_memsz);                /* Segment size in memory */
27
    bswap32s(&phdr->p_flags);                /* Segment flags */
28
    bswapSZs(&phdr->p_align);                /* Segment alignment */
29
}
30

    
31
static void glue(bswap_shdr, SZ)(struct elf_shdr *shdr)
32
{
33
    bswap32s(&shdr->sh_name);
34
    bswap32s(&shdr->sh_type);
35
    bswapSZs(&shdr->sh_flags);
36
    bswapSZs(&shdr->sh_addr);
37
    bswapSZs(&shdr->sh_offset);
38
    bswapSZs(&shdr->sh_size);
39
    bswap32s(&shdr->sh_link);
40
    bswap32s(&shdr->sh_info);
41
    bswapSZs(&shdr->sh_addralign);
42
    bswapSZs(&shdr->sh_entsize);
43
}
44

    
45
static void glue(bswap_sym, SZ)(struct elf_sym *sym)
46
{
47
    bswap32s(&sym->st_name);
48
    bswapSZs(&sym->st_value);
49
    bswapSZs(&sym->st_size);
50
    bswap16s(&sym->st_shndx);
51
}
52
#endif
53

    
54
static int glue(find_phdr, SZ)(struct elfhdr *ehdr, int fd, struct elf_phdr *phdr, elf_word type)
55
{
56
    int i, retval;
57

    
58
    retval = lseek(fd, ehdr->e_phoff, SEEK_SET);
59
    if (retval < 0)
60
        return -1;
61

    
62
    for (i = 0; i < ehdr->e_phnum; i++) {
63
        retval = read(fd, phdr, sizeof(*phdr));
64
        if (retval < 0)
65
            return -1;
66
        glue(bswap_phdr, SZ)(phdr);
67
        if (phdr->p_type == type)
68
            return 0;
69
    }
70
    return -1;
71
}
72

    
73
static void * glue(find_shdr, SZ)(struct elfhdr *ehdr, int fd, struct elf_shdr *shdr, elf_word type)
74
{
75
    int i, retval;
76

    
77
    retval = lseek(fd, ehdr->e_shoff, SEEK_SET);
78
    if (retval < 0)
79
        return NULL;
80

    
81
    for (i = 0; i < ehdr->e_shnum; i++) {
82
        retval = read(fd, shdr, sizeof(*shdr));
83
        if (retval < 0)
84
            return NULL;
85
        glue(bswap_shdr, SZ)(shdr);
86
        if (shdr->sh_type == type)
87
            return qemu_malloc(shdr->sh_size);
88
    }
89
    return NULL;
90
}
91

    
92
static void * glue(find_strtab, SZ)(struct elfhdr *ehdr, int fd, struct elf_shdr *shdr, struct elf_shdr *symtab)
93
{
94
    int retval;
95

    
96
    retval = lseek(fd, ehdr->e_shoff + sizeof(struct elf_shdr) * symtab->sh_link, SEEK_SET);
97
    if (retval < 0)
98
        return NULL;
99

    
100
    retval = read(fd, shdr, sizeof(*shdr));
101
    if (retval < 0)
102
        return NULL;
103
    glue(bswap_shdr, SZ)(shdr);
104
    if (shdr->sh_type == SHT_STRTAB)
105
        return qemu_malloc(shdr->sh_size);;
106
    return NULL;
107
}
108

    
109
static int glue(read_program, SZ)(int fd, struct elf_phdr *phdr, void *dst, elf_word entry)
110
{
111
    int retval;
112
    retval = lseek(fd, phdr->p_offset + entry - phdr->p_vaddr, SEEK_SET);
113
    if (retval < 0)
114
        return -1;
115
    return read(fd, dst, phdr->p_filesz);
116
}
117

    
118
static int glue(read_section, SZ)(int fd, struct elf_shdr *s, void *dst)
119
{
120
    int retval;
121

    
122
    retval = lseek(fd, s->sh_offset, SEEK_SET);
123
    if (retval < 0)
124
        return -1;
125
    retval = read(fd, dst, s->sh_size);
126
    if (retval < 0)
127
        return -1;
128
    return 0;
129
}
130

    
131
static void * glue(process_section, SZ)(struct elfhdr *ehdr, int fd, struct elf_shdr *shdr, elf_word type)
132
{
133
    void *dst;
134

    
135
    dst = glue(find_shdr, SZ)(ehdr, fd, shdr, type);
136
    if (!dst)
137
        goto error;
138

    
139
    if (glue(read_section, SZ)(fd, shdr, dst))
140
        goto error;
141
    return dst;
142
 error:
143
    qemu_free(dst);
144
    return NULL;
145
}
146

    
147
static void * glue(process_strtab, SZ)(struct elfhdr *ehdr, int fd, struct elf_shdr *shdr, struct elf_shdr *symtab)
148
{
149
    void *dst;
150

    
151
    dst = glue(find_strtab, SZ)(ehdr, fd, shdr, symtab);
152
    if (!dst)
153
        goto error;
154

    
155
    if (glue(read_section, SZ)(fd, shdr, dst))
156
        goto error;
157
    return dst;
158
 error:
159
    qemu_free(dst);
160
    return NULL;
161
}
162

    
163
static void glue(load_symbols, SZ)(struct elfhdr *ehdr, int fd)
164
{
165
    struct elf_shdr symtab, strtab;
166
    struct elf_sym *syms;
167
#if (SZ == 64)
168
    struct elf32_sym *syms32;
169
#endif
170
    struct syminfo *s;
171
    int nsyms, i;
172
    char *str;
173

    
174
    /* Symbol table */
175
    syms = glue(process_section, SZ)(ehdr, fd, &symtab, SHT_SYMTAB);
176
    if (!syms)
177
        return;
178

    
179
    nsyms = symtab.sh_size / sizeof(struct elf_sym);
180
#if (SZ == 64)
181
    syms32 = qemu_mallocz(nsyms * sizeof(struct elf32_sym));
182
#endif
183
    for (i = 0; i < nsyms; i++) {
184
        glue(bswap_sym, SZ)(&syms[i]);
185
#if (SZ == 64)
186
        syms32[i].st_name = syms[i].st_name;
187
        syms32[i].st_info = syms[i].st_info;
188
        syms32[i].st_other = syms[i].st_other;
189
        syms32[i].st_shndx = syms[i].st_shndx;
190
        syms32[i].st_value = syms[i].st_value & 0xffffffff;
191
        syms32[i].st_size = syms[i].st_size & 0xffffffff;
192
#endif
193
    }
194
    /* String table */
195
    str = glue(process_strtab, SZ)(ehdr, fd, &strtab, &symtab);
196
    if (!str)
197
        goto error_freesyms;
198

    
199
    /* Commit */
200
    s = qemu_mallocz(sizeof(*s));
201
#if (SZ == 64)
202
    s->disas_symtab = syms32;
203
    qemu_free(syms);
204
#else
205
    s->disas_symtab = syms;
206
#endif
207
    s->disas_num_syms = nsyms;
208
    s->disas_strtab = str;
209
    s->next = syminfos;
210
    syminfos = s;
211
    return;
212
 error_freesyms:
213
#if (SZ == 64)
214
    qemu_free(syms32);
215
#endif
216
    qemu_free(syms);
217
    return;
218
}