root / hw / elf_ops.h @ f68c781c
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 | } |