Statistics
| Branch: | Revision:

root / dyngen.c @ 76d83bde

History | View | Annotate | Download (95.2 kB)

1 7d13299d bellard
/*
2 7d13299d bellard
 *  Generic Dynamic compiler generator
3 5fafdf24 ths
 *
4 7d13299d bellard
 *  Copyright (c) 2003 Fabrice Bellard
5 7d13299d bellard
 *
6 67b915a5 bellard
 *  The COFF object format support was extracted from Kazu's QEMU port
7 67b915a5 bellard
 *  to Win32.
8 67b915a5 bellard
 *
9 82eec0a1 bellard
 *  Mach-O Support by Matt Reda and Pierre d'Herbemont
10 82eec0a1 bellard
 *
11 7d13299d bellard
 *  This program is free software; you can redistribute it and/or modify
12 7d13299d bellard
 *  it under the terms of the GNU General Public License as published by
13 7d13299d bellard
 *  the Free Software Foundation; either version 2 of the License, or
14 7d13299d bellard
 *  (at your option) any later version.
15 7d13299d bellard
 *
16 7d13299d bellard
 *  This program is distributed in the hope that it will be useful,
17 7d13299d bellard
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
18 7d13299d bellard
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19 7d13299d bellard
 *  GNU General Public License for more details.
20 7d13299d bellard
 *
21 7d13299d bellard
 *  You should have received a copy of the GNU General Public License
22 7d13299d bellard
 *  along with this program; if not, write to the Free Software
23 7d13299d bellard
 *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
24 7d13299d bellard
 */
25 367e86e8 bellard
#include <stdlib.h>
26 367e86e8 bellard
#include <stdio.h>
27 04369ff2 bellard
#include <string.h>
28 367e86e8 bellard
#include <stdarg.h>
29 367e86e8 bellard
#include <inttypes.h>
30 367e86e8 bellard
#include <unistd.h>
31 367e86e8 bellard
#include <fcntl.h>
32 367e86e8 bellard
33 abcd5da7 bellard
#include "config-host.h"
34 ce11fedc bellard
35 11d9f695 bellard
/* NOTE: we test CONFIG_WIN32 instead of _WIN32 to enabled cross
36 11d9f695 bellard
   compilation */
37 11d9f695 bellard
#if defined(CONFIG_WIN32)
38 67b915a5 bellard
#define CONFIG_FORMAT_COFF
39 82eec0a1 bellard
#elif defined(CONFIG_DARWIN)
40 82eec0a1 bellard
#define CONFIG_FORMAT_MACH
41 67b915a5 bellard
#else
42 67b915a5 bellard
#define CONFIG_FORMAT_ELF
43 67b915a5 bellard
#endif
44 67b915a5 bellard
45 67b915a5 bellard
#ifdef CONFIG_FORMAT_ELF
46 67b915a5 bellard
47 ce11fedc bellard
/* elf format definitions. We use these macros to test the CPU to
48 ce11fedc bellard
   allow cross compilation (this tool must be ran on the build
49 ce11fedc bellard
   platform) */
50 ce11fedc bellard
#if defined(HOST_I386)
51 ce11fedc bellard
52 ce11fedc bellard
#define ELF_CLASS        ELFCLASS32
53 ce11fedc bellard
#define ELF_ARCH        EM_386
54 ce11fedc bellard
#define elf_check_arch(x) ( ((x) == EM_386) || ((x) == EM_486) )
55 ce11fedc bellard
#undef ELF_USES_RELOCA
56 ce11fedc bellard
57 c4687878 bellard
#elif defined(HOST_X86_64)
58 bc51c5c9 bellard
59 bc51c5c9 bellard
#define ELF_CLASS        ELFCLASS64
60 bc51c5c9 bellard
#define ELF_ARCH        EM_X86_64
61 bc51c5c9 bellard
#define elf_check_arch(x) ((x) == EM_X86_64)
62 bc51c5c9 bellard
#define ELF_USES_RELOCA
63 bc51c5c9 bellard
64 ce11fedc bellard
#elif defined(HOST_PPC)
65 ce11fedc bellard
66 ce11fedc bellard
#define ELF_CLASS        ELFCLASS32
67 ce11fedc bellard
#define ELF_ARCH        EM_PPC
68 ce11fedc bellard
#define elf_check_arch(x) ((x) == EM_PPC)
69 ce11fedc bellard
#define ELF_USES_RELOCA
70 ce11fedc bellard
71 ce11fedc bellard
#elif defined(HOST_S390)
72 ce11fedc bellard
73 ce11fedc bellard
#define ELF_CLASS        ELFCLASS32
74 ce11fedc bellard
#define ELF_ARCH        EM_S390
75 ce11fedc bellard
#define elf_check_arch(x) ((x) == EM_S390)
76 ce11fedc bellard
#define ELF_USES_RELOCA
77 367e86e8 bellard
78 ce11fedc bellard
#elif defined(HOST_ALPHA)
79 ce11fedc bellard
80 ce11fedc bellard
#define ELF_CLASS        ELFCLASS64
81 ce11fedc bellard
#define ELF_ARCH        EM_ALPHA
82 ce11fedc bellard
#define elf_check_arch(x) ((x) == EM_ALPHA)
83 ce11fedc bellard
#define ELF_USES_RELOCA
84 ce11fedc bellard
85 efdea7bf bellard
#elif defined(HOST_IA64)
86 efdea7bf bellard
87 efdea7bf bellard
#define ELF_CLASS        ELFCLASS64
88 efdea7bf bellard
#define ELF_ARCH        EM_IA_64
89 efdea7bf bellard
#define elf_check_arch(x) ((x) == EM_IA_64)
90 efdea7bf bellard
#define ELF_USES_RELOCA
91 efdea7bf bellard
92 d014c98c bellard
#elif defined(HOST_SPARC)
93 d014c98c bellard
94 d014c98c bellard
#define ELF_CLASS        ELFCLASS32
95 d014c98c bellard
#define ELF_ARCH        EM_SPARC
96 d014c98c bellard
#define elf_check_arch(x) ((x) == EM_SPARC || (x) == EM_SPARC32PLUS)
97 d014c98c bellard
#define ELF_USES_RELOCA
98 d014c98c bellard
99 d014c98c bellard
#elif defined(HOST_SPARC64)
100 d014c98c bellard
101 d014c98c bellard
#define ELF_CLASS        ELFCLASS64
102 d014c98c bellard
#define ELF_ARCH        EM_SPARCV9
103 d014c98c bellard
#define elf_check_arch(x) ((x) == EM_SPARCV9)
104 d014c98c bellard
#define ELF_USES_RELOCA
105 d014c98c bellard
106 ff1f20a3 bellard
#elif defined(HOST_ARM)
107 ff1f20a3 bellard
108 ff1f20a3 bellard
#define ELF_CLASS        ELFCLASS32
109 ff1f20a3 bellard
#define ELF_ARCH        EM_ARM
110 ff1f20a3 bellard
#define elf_check_arch(x) ((x) == EM_ARM)
111 ff1f20a3 bellard
#define ELF_USES_RELOC
112 ff1f20a3 bellard
113 38e584a0 bellard
#elif defined(HOST_M68K)
114 38e584a0 bellard
115 38e584a0 bellard
#define ELF_CLASS        ELFCLASS32
116 38e584a0 bellard
#define ELF_ARCH        EM_68K
117 38e584a0 bellard
#define elf_check_arch(x) ((x) == EM_68K)
118 38e584a0 bellard
#define ELF_USES_RELOCA
119 38e584a0 bellard
120 c4b89d18 ths
#elif defined(HOST_MIPS)
121 c4b89d18 ths
122 c4b89d18 ths
#define ELF_CLASS        ELFCLASS32
123 c4b89d18 ths
#define ELF_ARCH        EM_MIPS
124 c4b89d18 ths
#define elf_check_arch(x) ((x) == EM_MIPS)
125 c4b89d18 ths
#define ELF_USES_RELOC
126 c4b89d18 ths
127 9617efe8 ths
#elif defined(HOST_MIPS64)
128 9617efe8 ths
129 9617efe8 ths
/* Assume n32 ABI here, which is ELF32. */
130 9617efe8 ths
#define ELF_CLASS        ELFCLASS32
131 9617efe8 ths
#define ELF_ARCH        EM_MIPS
132 9617efe8 ths
#define elf_check_arch(x) ((x) == EM_MIPS)
133 9617efe8 ths
#define ELF_USES_RELOCA
134 9617efe8 ths
135 ce11fedc bellard
#else
136 ce11fedc bellard
#error unsupported CPU - please update the code
137 ce11fedc bellard
#endif
138 ce11fedc bellard
139 efdea7bf bellard
#include "elf.h"
140 efdea7bf bellard
141 ce11fedc bellard
#if ELF_CLASS == ELFCLASS32
142 ce11fedc bellard
typedef int32_t host_long;
143 ce11fedc bellard
typedef uint32_t host_ulong;
144 efdea7bf bellard
#define swabls(x) swab32s(x)
145 a86c8f29 ths
#define swablss(x) swab32ss(x)
146 ce11fedc bellard
#else
147 ce11fedc bellard
typedef int64_t host_long;
148 ce11fedc bellard
typedef uint64_t host_ulong;
149 efdea7bf bellard
#define swabls(x) swab64s(x)
150 a86c8f29 ths
#define swablss(x) swab64ss(x)
151 fb3e5849 bellard
#endif
152 fb3e5849 bellard
153 fe319756 bellard
#ifdef ELF_USES_RELOCA
154 fe319756 bellard
#define SHT_RELOC SHT_RELA
155 fe319756 bellard
#else
156 fe319756 bellard
#define SHT_RELOC SHT_REL
157 fe319756 bellard
#endif
158 fe319756 bellard
159 67b915a5 bellard
#define EXE_RELOC ELF_RELOC
160 67b915a5 bellard
#define EXE_SYM ElfW(Sym)
161 67b915a5 bellard
162 67b915a5 bellard
#endif /* CONFIG_FORMAT_ELF */
163 67b915a5 bellard
164 67b915a5 bellard
#ifdef CONFIG_FORMAT_COFF
165 67b915a5 bellard
166 67b915a5 bellard
typedef int32_t host_long;
167 67b915a5 bellard
typedef uint32_t host_ulong;
168 67b915a5 bellard
169 7a2d6d96 pbrook
#include "a.out.h"
170 7a2d6d96 pbrook
171 67b915a5 bellard
#define FILENAMELEN 256
172 67b915a5 bellard
173 67b915a5 bellard
typedef struct coff_sym {
174 67b915a5 bellard
    struct external_syment *st_syment;
175 67b915a5 bellard
    char st_name[FILENAMELEN];
176 67b915a5 bellard
    uint32_t st_value;
177 67b915a5 bellard
    int  st_size;
178 67b915a5 bellard
    uint8_t st_type;
179 67b915a5 bellard
    uint8_t st_shndx;
180 67b915a5 bellard
} coff_Sym;
181 67b915a5 bellard
182 67b915a5 bellard
typedef struct coff_rel {
183 67b915a5 bellard
    struct external_reloc *r_reloc;
184 67b915a5 bellard
    int  r_offset;
185 67b915a5 bellard
    uint8_t r_type;
186 67b915a5 bellard
} coff_Rel;
187 67b915a5 bellard
188 67b915a5 bellard
#define EXE_RELOC struct coff_rel
189 67b915a5 bellard
#define EXE_SYM struct coff_sym
190 67b915a5 bellard
191 67b915a5 bellard
#endif /* CONFIG_FORMAT_COFF */
192 67b915a5 bellard
193 82eec0a1 bellard
#ifdef CONFIG_FORMAT_MACH
194 82eec0a1 bellard
195 82eec0a1 bellard
#include <mach-o/loader.h>
196 82eec0a1 bellard
#include <mach-o/nlist.h>
197 82eec0a1 bellard
#include <mach-o/reloc.h>
198 82eec0a1 bellard
#include <mach-o/ppc/reloc.h>
199 82eec0a1 bellard
200 82eec0a1 bellard
# define check_mach_header(x) (x.magic == MH_MAGIC)
201 82eec0a1 bellard
typedef int32_t host_long;
202 82eec0a1 bellard
typedef uint32_t host_ulong;
203 82eec0a1 bellard
204 82eec0a1 bellard
struct nlist_extended
205 82eec0a1 bellard
{
206 82eec0a1 bellard
   union {
207 5fafdf24 ths
   char *n_name;
208 5fafdf24 ths
   long  n_strx;
209 82eec0a1 bellard
   } n_un;
210 5fafdf24 ths
   unsigned char n_type;
211 5fafdf24 ths
   unsigned char n_sect;
212 82eec0a1 bellard
   short st_desc;
213 82eec0a1 bellard
   unsigned long st_value;
214 82eec0a1 bellard
   unsigned long st_size;
215 82eec0a1 bellard
};
216 82eec0a1 bellard
217 82eec0a1 bellard
#define EXE_RELOC struct relocation_info
218 82eec0a1 bellard
#define EXE_SYM struct nlist_extended
219 82eec0a1 bellard
220 82eec0a1 bellard
#endif /* CONFIG_FORMAT_MACH */
221 82eec0a1 bellard
222 abcd5da7 bellard
#include "bswap.h"
223 ce11fedc bellard
224 d219f7e7 bellard
enum {
225 d219f7e7 bellard
    OUT_GEN_OP,
226 d219f7e7 bellard
    OUT_CODE,
227 d219f7e7 bellard
    OUT_INDEX_OP,
228 d219f7e7 bellard
};
229 d219f7e7 bellard
230 367e86e8 bellard
/* all dynamically generated functions begin with this code */
231 dc99065b bellard
#define OP_PREFIX "op_"
232 367e86e8 bellard
233 67b915a5 bellard
int do_swap;
234 67b915a5 bellard
235 9596ebb7 pbrook
static void __attribute__((noreturn)) __attribute__((format (printf, 1, 2))) error(const char *fmt, ...)
236 367e86e8 bellard
{
237 67b915a5 bellard
    va_list ap;
238 67b915a5 bellard
    va_start(ap, fmt);
239 67b915a5 bellard
    fprintf(stderr, "dyngen: ");
240 67b915a5 bellard
    vfprintf(stderr, fmt, ap);
241 67b915a5 bellard
    fprintf(stderr, "\n");
242 67b915a5 bellard
    va_end(ap);
243 67b915a5 bellard
    exit(1);
244 67b915a5 bellard
}
245 367e86e8 bellard
246 9596ebb7 pbrook
static void *load_data(int fd, long offset, unsigned int size)
247 67b915a5 bellard
{
248 67b915a5 bellard
    char *data;
249 67b915a5 bellard
250 67b915a5 bellard
    data = malloc(size);
251 67b915a5 bellard
    if (!data)
252 67b915a5 bellard
        return NULL;
253 67b915a5 bellard
    lseek(fd, offset, SEEK_SET);
254 67b915a5 bellard
    if (read(fd, data, size) != size) {
255 67b915a5 bellard
        free(data);
256 67b915a5 bellard
        return NULL;
257 67b915a5 bellard
    }
258 67b915a5 bellard
    return data;
259 367e86e8 bellard
}
260 67b915a5 bellard
261 67b915a5 bellard
int strstart(const char *str, const char *val, const char **ptr)
262 67b915a5 bellard
{
263 67b915a5 bellard
    const char *p, *q;
264 67b915a5 bellard
    p = str;
265 67b915a5 bellard
    q = val;
266 67b915a5 bellard
    while (*q != '\0') {
267 67b915a5 bellard
        if (*p != *q)
268 67b915a5 bellard
            return 0;
269 67b915a5 bellard
        p++;
270 67b915a5 bellard
        q++;
271 67b915a5 bellard
    }
272 67b915a5 bellard
    if (ptr)
273 67b915a5 bellard
        *ptr = p;
274 67b915a5 bellard
    return 1;
275 67b915a5 bellard
}
276 67b915a5 bellard
277 67b915a5 bellard
void pstrcpy(char *buf, int buf_size, const char *str)
278 67b915a5 bellard
{
279 67b915a5 bellard
    int c;
280 67b915a5 bellard
    char *q = buf;
281 67b915a5 bellard
282 67b915a5 bellard
    if (buf_size <= 0)
283 67b915a5 bellard
        return;
284 67b915a5 bellard
285 67b915a5 bellard
    for(;;) {
286 67b915a5 bellard
        c = *str++;
287 67b915a5 bellard
        if (c == 0 || q >= buf + buf_size - 1)
288 67b915a5 bellard
            break;
289 67b915a5 bellard
        *q++ = c;
290 67b915a5 bellard
    }
291 67b915a5 bellard
    *q = '\0';
292 67b915a5 bellard
}
293 67b915a5 bellard
294 367e86e8 bellard
void swab16s(uint16_t *p)
295 367e86e8 bellard
{
296 367e86e8 bellard
    *p = bswap16(*p);
297 367e86e8 bellard
}
298 367e86e8 bellard
299 367e86e8 bellard
void swab32s(uint32_t *p)
300 367e86e8 bellard
{
301 367e86e8 bellard
    *p = bswap32(*p);
302 367e86e8 bellard
}
303 367e86e8 bellard
304 a86c8f29 ths
void swab32ss(int32_t *p)
305 a86c8f29 ths
{
306 a86c8f29 ths
    *p = bswap32(*p);
307 a86c8f29 ths
}
308 a86c8f29 ths
309 ce11fedc bellard
void swab64s(uint64_t *p)
310 367e86e8 bellard
{
311 367e86e8 bellard
    *p = bswap64(*p);
312 367e86e8 bellard
}
313 367e86e8 bellard
314 a86c8f29 ths
void swab64ss(int64_t *p)
315 a86c8f29 ths
{
316 a86c8f29 ths
    *p = bswap64(*p);
317 a86c8f29 ths
}
318 a86c8f29 ths
319 67b915a5 bellard
uint16_t get16(uint16_t *p)
320 67b915a5 bellard
{
321 67b915a5 bellard
    uint16_t val;
322 67b915a5 bellard
    val = *p;
323 67b915a5 bellard
    if (do_swap)
324 67b915a5 bellard
        val = bswap16(val);
325 67b915a5 bellard
    return val;
326 67b915a5 bellard
}
327 67b915a5 bellard
328 67b915a5 bellard
uint32_t get32(uint32_t *p)
329 67b915a5 bellard
{
330 67b915a5 bellard
    uint32_t val;
331 67b915a5 bellard
    val = *p;
332 67b915a5 bellard
    if (do_swap)
333 67b915a5 bellard
        val = bswap32(val);
334 67b915a5 bellard
    return val;
335 67b915a5 bellard
}
336 67b915a5 bellard
337 67b915a5 bellard
void put16(uint16_t *p, uint16_t val)
338 67b915a5 bellard
{
339 67b915a5 bellard
    if (do_swap)
340 67b915a5 bellard
        val = bswap16(val);
341 67b915a5 bellard
    *p = val;
342 67b915a5 bellard
}
343 67b915a5 bellard
344 67b915a5 bellard
void put32(uint32_t *p, uint32_t val)
345 67b915a5 bellard
{
346 67b915a5 bellard
    if (do_swap)
347 67b915a5 bellard
        val = bswap32(val);
348 67b915a5 bellard
    *p = val;
349 67b915a5 bellard
}
350 67b915a5 bellard
351 67b915a5 bellard
/* executable information */
352 67b915a5 bellard
EXE_SYM *symtab;
353 67b915a5 bellard
int nb_syms;
354 67b915a5 bellard
int text_shndx;
355 67b915a5 bellard
uint8_t *text;
356 67b915a5 bellard
EXE_RELOC *relocs;
357 67b915a5 bellard
int nb_relocs;
358 67b915a5 bellard
359 67b915a5 bellard
#ifdef CONFIG_FORMAT_ELF
360 67b915a5 bellard
361 67b915a5 bellard
/* ELF file info */
362 67b915a5 bellard
struct elf_shdr *shdr;
363 67b915a5 bellard
uint8_t **sdata;
364 67b915a5 bellard
struct elfhdr ehdr;
365 67b915a5 bellard
char *strtab;
366 67b915a5 bellard
367 67b915a5 bellard
int elf_must_swap(struct elfhdr *h)
368 67b915a5 bellard
{
369 67b915a5 bellard
  union {
370 67b915a5 bellard
      uint32_t i;
371 67b915a5 bellard
      uint8_t b[4];
372 67b915a5 bellard
  } swaptest;
373 67b915a5 bellard
374 67b915a5 bellard
  swaptest.i = 1;
375 5fafdf24 ths
  return (h->e_ident[EI_DATA] == ELFDATA2MSB) !=
376 67b915a5 bellard
      (swaptest.b[0] == 0);
377 67b915a5 bellard
}
378 3b46e624 ths
379 ce11fedc bellard
void elf_swap_ehdr(struct elfhdr *h)
380 367e86e8 bellard
{
381 367e86e8 bellard
    swab16s(&h->e_type);                        /* Object file type */
382 367e86e8 bellard
    swab16s(&h->        e_machine);                /* Architecture */
383 367e86e8 bellard
    swab32s(&h->        e_version);                /* Object file version */
384 ce11fedc bellard
    swabls(&h->        e_entry);                /* Entry point virtual address */
385 ce11fedc bellard
    swabls(&h->        e_phoff);                /* Program header table file offset */
386 ce11fedc bellard
    swabls(&h->        e_shoff);                /* Section header table file offset */
387 367e86e8 bellard
    swab32s(&h->        e_flags);                /* Processor-specific flags */
388 367e86e8 bellard
    swab16s(&h->        e_ehsize);                /* ELF header size in bytes */
389 367e86e8 bellard
    swab16s(&h->        e_phentsize);                /* Program header table entry size */
390 367e86e8 bellard
    swab16s(&h->        e_phnum);                /* Program header table entry count */
391 367e86e8 bellard
    swab16s(&h->        e_shentsize);                /* Section header table entry size */
392 367e86e8 bellard
    swab16s(&h->        e_shnum);                /* Section header table entry count */
393 367e86e8 bellard
    swab16s(&h->        e_shstrndx);                /* Section header string table index */
394 367e86e8 bellard
}
395 367e86e8 bellard
396 ce11fedc bellard
void elf_swap_shdr(struct elf_shdr *h)
397 367e86e8 bellard
{
398 367e86e8 bellard
  swab32s(&h->        sh_name);                /* Section name (string tbl index) */
399 367e86e8 bellard
  swab32s(&h->        sh_type);                /* Section type */
400 ce11fedc bellard
  swabls(&h->        sh_flags);                /* Section flags */
401 ce11fedc bellard
  swabls(&h->        sh_addr);                /* Section virtual addr at execution */
402 ce11fedc bellard
  swabls(&h->        sh_offset);                /* Section file offset */
403 ce11fedc bellard
  swabls(&h->        sh_size);                /* Section size in bytes */
404 367e86e8 bellard
  swab32s(&h->        sh_link);                /* Link to another section */
405 367e86e8 bellard
  swab32s(&h->        sh_info);                /* Additional section information */
406 ce11fedc bellard
  swabls(&h->        sh_addralign);                /* Section alignment */
407 ce11fedc bellard
  swabls(&h->        sh_entsize);                /* Entry size if section holds table */
408 367e86e8 bellard
}
409 367e86e8 bellard
410 ce11fedc bellard
void elf_swap_phdr(struct elf_phdr *h)
411 367e86e8 bellard
{
412 367e86e8 bellard
    swab32s(&h->p_type);                        /* Segment type */
413 ce11fedc bellard
    swabls(&h->p_offset);                /* Segment file offset */
414 ce11fedc bellard
    swabls(&h->p_vaddr);                /* Segment virtual address */
415 ce11fedc bellard
    swabls(&h->p_paddr);                /* Segment physical address */
416 ce11fedc bellard
    swabls(&h->p_filesz);                /* Segment size in file */
417 ce11fedc bellard
    swabls(&h->p_memsz);                /* Segment size in memory */
418 367e86e8 bellard
    swab32s(&h->p_flags);                /* Segment flags */
419 ce11fedc bellard
    swabls(&h->p_align);                /* Segment alignment */
420 367e86e8 bellard
}
421 367e86e8 bellard
422 fe319756 bellard
void elf_swap_rel(ELF_RELOC *rel)
423 fe319756 bellard
{
424 fe319756 bellard
    swabls(&rel->r_offset);
425 fe319756 bellard
    swabls(&rel->r_info);
426 fe319756 bellard
#ifdef ELF_USES_RELOCA
427 a86c8f29 ths
    swablss(&rel->r_addend);
428 fe319756 bellard
#endif
429 fe319756 bellard
}
430 fe319756 bellard
431 5fafdf24 ths
struct elf_shdr *find_elf_section(struct elf_shdr *shdr, int shnum, const char *shstr,
432 67b915a5 bellard
                                  const char *name)
433 67b915a5 bellard
{
434 67b915a5 bellard
    int i;
435 67b915a5 bellard
    const char *shname;
436 67b915a5 bellard
    struct elf_shdr *sec;
437 367e86e8 bellard
438 67b915a5 bellard
    for(i = 0; i < shnum; i++) {
439 67b915a5 bellard
        sec = &shdr[i];
440 67b915a5 bellard
        if (!sec->sh_name)
441 67b915a5 bellard
            continue;
442 67b915a5 bellard
        shname = shstr + sec->sh_name;
443 67b915a5 bellard
        if (!strcmp(shname, name))
444 67b915a5 bellard
            return sec;
445 67b915a5 bellard
    }
446 67b915a5 bellard
    return NULL;
447 67b915a5 bellard
}
448 67b915a5 bellard
449 67b915a5 bellard
int find_reloc(int sh_index)
450 367e86e8 bellard
{
451 67b915a5 bellard
    struct elf_shdr *sec;
452 67b915a5 bellard
    int i;
453 67b915a5 bellard
454 67b915a5 bellard
    for(i = 0; i < ehdr.e_shnum; i++) {
455 67b915a5 bellard
        sec = &shdr[i];
456 5fafdf24 ths
        if (sec->sh_type == SHT_RELOC && sec->sh_info == sh_index)
457 67b915a5 bellard
            return i;
458 67b915a5 bellard
    }
459 67b915a5 bellard
    return 0;
460 367e86e8 bellard
}
461 367e86e8 bellard
462 82eec0a1 bellard
static host_ulong get_rel_offset(EXE_RELOC *rel)
463 82eec0a1 bellard
{
464 82eec0a1 bellard
    return rel->r_offset;
465 82eec0a1 bellard
}
466 82eec0a1 bellard
467 67b915a5 bellard
static char *get_rel_sym_name(EXE_RELOC *rel)
468 367e86e8 bellard
{
469 67b915a5 bellard
    return strtab + symtab[ELFW(R_SYM)(rel->r_info)].st_name;
470 67b915a5 bellard
}
471 67b915a5 bellard
472 67b915a5 bellard
static char *get_sym_name(EXE_SYM *sym)
473 67b915a5 bellard
{
474 67b915a5 bellard
    return strtab + sym->st_name;
475 67b915a5 bellard
}
476 67b915a5 bellard
477 67b915a5 bellard
/* load an elf object file */
478 67b915a5 bellard
int load_object(const char *filename)
479 67b915a5 bellard
{
480 67b915a5 bellard
    int fd;
481 67b915a5 bellard
    struct elf_shdr *sec, *symtab_sec, *strtab_sec, *text_sec;
482 67b915a5 bellard
    int i, j;
483 67b915a5 bellard
    ElfW(Sym) *sym;
484 67b915a5 bellard
    char *shstr;
485 67b915a5 bellard
    ELF_RELOC *rel;
486 3b46e624 ths
487 67b915a5 bellard
    fd = open(filename, O_RDONLY);
488 5fafdf24 ths
    if (fd < 0)
489 67b915a5 bellard
        error("can't open file '%s'", filename);
490 3b46e624 ths
491 67b915a5 bellard
    /* Read ELF header.  */
492 67b915a5 bellard
    if (read(fd, &ehdr, sizeof (ehdr)) != sizeof (ehdr))
493 67b915a5 bellard
        error("unable to read file header");
494 67b915a5 bellard
495 67b915a5 bellard
    /* Check ELF identification.  */
496 67b915a5 bellard
    if (ehdr.e_ident[EI_MAG0] != ELFMAG0
497 67b915a5 bellard
     || ehdr.e_ident[EI_MAG1] != ELFMAG1
498 67b915a5 bellard
     || ehdr.e_ident[EI_MAG2] != ELFMAG2
499 67b915a5 bellard
     || ehdr.e_ident[EI_MAG3] != ELFMAG3
500 67b915a5 bellard
     || ehdr.e_ident[EI_VERSION] != EV_CURRENT) {
501 67b915a5 bellard
        error("bad ELF header");
502 67b915a5 bellard
    }
503 67b915a5 bellard
504 67b915a5 bellard
    do_swap = elf_must_swap(&ehdr);
505 367e86e8 bellard
    if (do_swap)
506 67b915a5 bellard
        elf_swap_ehdr(&ehdr);
507 67b915a5 bellard
    if (ehdr.e_ident[EI_CLASS] != ELF_CLASS)
508 67b915a5 bellard
        error("Unsupported ELF class");
509 67b915a5 bellard
    if (ehdr.e_type != ET_REL)
510 67b915a5 bellard
        error("ELF object file expected");
511 67b915a5 bellard
    if (ehdr.e_version != EV_CURRENT)
512 67b915a5 bellard
        error("Invalid ELF version");
513 67b915a5 bellard
    if (!elf_check_arch(ehdr.e_machine))
514 67b915a5 bellard
        error("Unsupported CPU (e_machine=%d)", ehdr.e_machine);
515 67b915a5 bellard
516 67b915a5 bellard
    /* read section headers */
517 67b915a5 bellard
    shdr = load_data(fd, ehdr.e_shoff, ehdr.e_shnum * sizeof(struct elf_shdr));
518 67b915a5 bellard
    if (do_swap) {
519 67b915a5 bellard
        for(i = 0; i < ehdr.e_shnum; i++) {
520 67b915a5 bellard
            elf_swap_shdr(&shdr[i]);
521 67b915a5 bellard
        }
522 67b915a5 bellard
    }
523 67b915a5 bellard
524 67b915a5 bellard
    /* read all section data */
525 67b915a5 bellard
    sdata = malloc(sizeof(void *) * ehdr.e_shnum);
526 67b915a5 bellard
    memset(sdata, 0, sizeof(void *) * ehdr.e_shnum);
527 3b46e624 ths
528 67b915a5 bellard
    for(i = 0;i < ehdr.e_shnum; i++) {
529 67b915a5 bellard
        sec = &shdr[i];
530 67b915a5 bellard
        if (sec->sh_type != SHT_NOBITS)
531 67b915a5 bellard
            sdata[i] = load_data(fd, sec->sh_offset, sec->sh_size);
532 67b915a5 bellard
    }
533 67b915a5 bellard
534 67b915a5 bellard
    sec = &shdr[ehdr.e_shstrndx];
535 a86c8f29 ths
    shstr = (char *)sdata[ehdr.e_shstrndx];
536 67b915a5 bellard
537 67b915a5 bellard
    /* swap relocations */
538 67b915a5 bellard
    for(i = 0; i < ehdr.e_shnum; i++) {
539 67b915a5 bellard
        sec = &shdr[i];
540 67b915a5 bellard
        if (sec->sh_type == SHT_RELOC) {
541 67b915a5 bellard
            nb_relocs = sec->sh_size / sec->sh_entsize;
542 67b915a5 bellard
            if (do_swap) {
543 67b915a5 bellard
                for(j = 0, rel = (ELF_RELOC *)sdata[i]; j < nb_relocs; j++, rel++)
544 67b915a5 bellard
                    elf_swap_rel(rel);
545 67b915a5 bellard
            }
546 67b915a5 bellard
        }
547 67b915a5 bellard
    }
548 67b915a5 bellard
    /* text section */
549 67b915a5 bellard
550 67b915a5 bellard
    text_sec = find_elf_section(shdr, ehdr.e_shnum, shstr, ".text");
551 67b915a5 bellard
    if (!text_sec)
552 67b915a5 bellard
        error("could not find .text section");
553 67b915a5 bellard
    text_shndx = text_sec - shdr;
554 67b915a5 bellard
    text = sdata[text_shndx];
555 67b915a5 bellard
556 67b915a5 bellard
    /* find text relocations, if any */
557 67b915a5 bellard
    relocs = NULL;
558 67b915a5 bellard
    nb_relocs = 0;
559 67b915a5 bellard
    i = find_reloc(text_shndx);
560 67b915a5 bellard
    if (i != 0) {
561 67b915a5 bellard
        relocs = (ELF_RELOC *)sdata[i];
562 67b915a5 bellard
        nb_relocs = shdr[i].sh_size / shdr[i].sh_entsize;
563 67b915a5 bellard
    }
564 67b915a5 bellard
565 67b915a5 bellard
    symtab_sec = find_elf_section(shdr, ehdr.e_shnum, shstr, ".symtab");
566 67b915a5 bellard
    if (!symtab_sec)
567 67b915a5 bellard
        error("could not find .symtab section");
568 67b915a5 bellard
    strtab_sec = &shdr[symtab_sec->sh_link];
569 67b915a5 bellard
570 67b915a5 bellard
    symtab = (ElfW(Sym) *)sdata[symtab_sec - shdr];
571 a86c8f29 ths
    strtab = (char *)sdata[symtab_sec->sh_link];
572 3b46e624 ths
573 67b915a5 bellard
    nb_syms = symtab_sec->sh_size / sizeof(ElfW(Sym));
574 67b915a5 bellard
    if (do_swap) {
575 67b915a5 bellard
        for(i = 0, sym = symtab; i < nb_syms; i++, sym++) {
576 67b915a5 bellard
            swab32s(&sym->st_name);
577 67b915a5 bellard
            swabls(&sym->st_value);
578 67b915a5 bellard
            swabls(&sym->st_size);
579 67b915a5 bellard
            swab16s(&sym->st_shndx);
580 67b915a5 bellard
        }
581 67b915a5 bellard
    }
582 67b915a5 bellard
    close(fd);
583 67b915a5 bellard
    return 0;
584 67b915a5 bellard
}
585 67b915a5 bellard
586 67b915a5 bellard
#endif /* CONFIG_FORMAT_ELF */
587 67b915a5 bellard
588 67b915a5 bellard
#ifdef CONFIG_FORMAT_COFF
589 67b915a5 bellard
590 67b915a5 bellard
/* COFF file info */
591 67b915a5 bellard
struct external_scnhdr *shdr;
592 67b915a5 bellard
uint8_t **sdata;
593 67b915a5 bellard
struct external_filehdr fhdr;
594 67b915a5 bellard
struct external_syment *coff_symtab;
595 67b915a5 bellard
char *strtab;
596 67b915a5 bellard
int coff_text_shndx, coff_data_shndx;
597 67b915a5 bellard
598 67b915a5 bellard
int data_shndx;
599 67b915a5 bellard
600 67b915a5 bellard
#define STRTAB_SIZE 4
601 67b915a5 bellard
602 67b915a5 bellard
#define DIR32   0x06
603 67b915a5 bellard
#define DISP32  0x14
604 67b915a5 bellard
605 67b915a5 bellard
#define T_FUNCTION  0x20
606 67b915a5 bellard
#define C_EXTERNAL  2
607 67b915a5 bellard
608 67b915a5 bellard
void sym_ent_name(struct external_syment *ext_sym, EXE_SYM *sym)
609 67b915a5 bellard
{
610 67b915a5 bellard
    char *q;
611 67b915a5 bellard
    int c, i, len;
612 3b46e624 ths
613 67b915a5 bellard
    if (ext_sym->e.e.e_zeroes != 0) {
614 67b915a5 bellard
        q = sym->st_name;
615 67b915a5 bellard
        for(i = 0; i < 8; i++) {
616 67b915a5 bellard
            c = ext_sym->e.e_name[i];
617 67b915a5 bellard
            if (c == '\0')
618 67b915a5 bellard
                break;
619 67b915a5 bellard
            *q++ = c;
620 67b915a5 bellard
        }
621 67b915a5 bellard
        *q = '\0';
622 67b915a5 bellard
    } else {
623 67b915a5 bellard
        pstrcpy(sym->st_name, sizeof(sym->st_name), strtab + ext_sym->e.e.e_offset);
624 67b915a5 bellard
    }
625 67b915a5 bellard
626 67b915a5 bellard
    /* now convert the name to a C name (suppress the leading '_') */
627 67b915a5 bellard
    if (sym->st_name[0] == '_') {
628 67b915a5 bellard
        len = strlen(sym->st_name);
629 67b915a5 bellard
        memmove(sym->st_name, sym->st_name + 1, len - 1);
630 67b915a5 bellard
        sym->st_name[len - 1] = '\0';
631 67b915a5 bellard
    }
632 367e86e8 bellard
}
633 367e86e8 bellard
634 67b915a5 bellard
char *name_for_dotdata(struct coff_rel *rel)
635 367e86e8 bellard
{
636 67b915a5 bellard
        int i;
637 67b915a5 bellard
        struct coff_sym *sym;
638 67b915a5 bellard
        uint32_t text_data;
639 67b915a5 bellard
640 67b915a5 bellard
        text_data = *(uint32_t *)(text + rel->r_offset);
641 67b915a5 bellard
642 67b915a5 bellard
        for (i = 0, sym = symtab; i < nb_syms; i++, sym++) {
643 67b915a5 bellard
                if (sym->st_syment->e_scnum == data_shndx &&
644 67b915a5 bellard
                    text_data >= sym->st_value &&
645 67b915a5 bellard
                    text_data < sym->st_value + sym->st_size) {
646 3b46e624 ths
647 67b915a5 bellard
                    return sym->st_name;
648 67b915a5 bellard
649 67b915a5 bellard
                }
650 67b915a5 bellard
        }
651 67b915a5 bellard
        return NULL;
652 367e86e8 bellard
}
653 367e86e8 bellard
654 67b915a5 bellard
static char *get_sym_name(EXE_SYM *sym)
655 367e86e8 bellard
{
656 67b915a5 bellard
    return sym->st_name;
657 367e86e8 bellard
}
658 367e86e8 bellard
659 67b915a5 bellard
static char *get_rel_sym_name(EXE_RELOC *rel)
660 367e86e8 bellard
{
661 67b915a5 bellard
    char *name;
662 67b915a5 bellard
    name = get_sym_name(symtab + *(uint32_t *)(rel->r_reloc->r_symndx));
663 67b915a5 bellard
    if (!strcmp(name, ".data"))
664 67b915a5 bellard
        name = name_for_dotdata(rel);
665 b48a8bb6 bellard
    if (name[0] == '.')
666 b48a8bb6 bellard
        return NULL;
667 67b915a5 bellard
    return name;
668 367e86e8 bellard
}
669 367e86e8 bellard
670 82eec0a1 bellard
static host_ulong get_rel_offset(EXE_RELOC *rel)
671 82eec0a1 bellard
{
672 82eec0a1 bellard
    return rel->r_offset;
673 82eec0a1 bellard
}
674 82eec0a1 bellard
675 67b915a5 bellard
struct external_scnhdr *find_coff_section(struct external_scnhdr *shdr, int shnum, const char *name)
676 367e86e8 bellard
{
677 367e86e8 bellard
    int i;
678 367e86e8 bellard
    const char *shname;
679 67b915a5 bellard
    struct external_scnhdr *sec;
680 367e86e8 bellard
681 367e86e8 bellard
    for(i = 0; i < shnum; i++) {
682 367e86e8 bellard
        sec = &shdr[i];
683 67b915a5 bellard
        if (!sec->s_name)
684 367e86e8 bellard
            continue;
685 67b915a5 bellard
        shname = sec->s_name;
686 367e86e8 bellard
        if (!strcmp(shname, name))
687 367e86e8 bellard
            return sec;
688 367e86e8 bellard
    }
689 367e86e8 bellard
    return NULL;
690 367e86e8 bellard
}
691 367e86e8 bellard
692 67b915a5 bellard
/* load a coff object file */
693 67b915a5 bellard
int load_object(const char *filename)
694 fe319756 bellard
{
695 67b915a5 bellard
    int fd;
696 67b915a5 bellard
    struct external_scnhdr *sec, *text_sec, *data_sec;
697 fe319756 bellard
    int i;
698 67b915a5 bellard
    struct external_syment *ext_sym;
699 67b915a5 bellard
    struct external_reloc *coff_relocs;
700 67b915a5 bellard
    struct external_reloc *ext_rel;
701 67b915a5 bellard
    uint32_t *n_strtab;
702 67b915a5 bellard
    EXE_SYM *sym;
703 67b915a5 bellard
    EXE_RELOC *rel;
704 2331d91e bellard
    const char *p;
705 2331d91e bellard
    int aux_size, j;
706 5fafdf24 ths
707 5fafdf24 ths
    fd = open(filename, O_RDONLY
708 67b915a5 bellard
#ifdef _WIN32
709 67b915a5 bellard
              | O_BINARY
710 67b915a5 bellard
#endif
711 67b915a5 bellard
              );
712 5fafdf24 ths
    if (fd < 0)
713 67b915a5 bellard
        error("can't open file '%s'", filename);
714 3b46e624 ths
715 67b915a5 bellard
    /* Read COFF header.  */
716 67b915a5 bellard
    if (read(fd, &fhdr, sizeof (fhdr)) != sizeof (fhdr))
717 67b915a5 bellard
        error("unable to read file header");
718 fe319756 bellard
719 67b915a5 bellard
    /* Check COFF identification.  */
720 67b915a5 bellard
    if (fhdr.f_magic != I386MAGIC) {
721 67b915a5 bellard
        error("bad COFF header");
722 67b915a5 bellard
    }
723 67b915a5 bellard
    do_swap = 0;
724 67b915a5 bellard
725 67b915a5 bellard
    /* read section headers */
726 67b915a5 bellard
    shdr = load_data(fd, sizeof(struct external_filehdr) + fhdr.f_opthdr, fhdr.f_nscns * sizeof(struct external_scnhdr));
727 5fafdf24 ths
728 67b915a5 bellard
    /* read all section data */
729 67b915a5 bellard
    sdata = malloc(sizeof(void *) * fhdr.f_nscns);
730 67b915a5 bellard
    memset(sdata, 0, sizeof(void *) * fhdr.f_nscns);
731 3b46e624 ths
732 67b915a5 bellard
    for(i = 0;i < fhdr.f_nscns; i++) {
733 fe319756 bellard
        sec = &shdr[i];
734 67b915a5 bellard
        if (!strstart(sec->s_name,  ".bss", &p))
735 67b915a5 bellard
            sdata[i] = load_data(fd, sec->s_scnptr, sec->s_size);
736 fe319756 bellard
    }
737 fe319756 bellard
738 367e86e8 bellard
739 67b915a5 bellard
    /* text section */
740 67b915a5 bellard
    text_sec = find_coff_section(shdr, fhdr.f_nscns, ".text");
741 67b915a5 bellard
    if (!text_sec)
742 67b915a5 bellard
        error("could not find .text section");
743 67b915a5 bellard
    coff_text_shndx = text_sec - shdr;
744 67b915a5 bellard
    text = sdata[coff_text_shndx];
745 67b915a5 bellard
746 67b915a5 bellard
    /* data section */
747 67b915a5 bellard
    data_sec = find_coff_section(shdr, fhdr.f_nscns, ".data");
748 67b915a5 bellard
    if (!data_sec)
749 67b915a5 bellard
        error("could not find .data section");
750 67b915a5 bellard
    coff_data_shndx = data_sec - shdr;
751 3b46e624 ths
752 67b915a5 bellard
    coff_symtab = load_data(fd, fhdr.f_symptr, fhdr.f_nsyms*SYMESZ);
753 67b915a5 bellard
    for (i = 0, ext_sym = coff_symtab; i < nb_syms; i++, ext_sym++) {
754 67b915a5 bellard
        for(i=0;i<8;i++)
755 67b915a5 bellard
            printf(" %02x", ((uint8_t *)ext_sym->e.e_name)[i]);
756 67b915a5 bellard
        printf("\n");
757 367e86e8 bellard
    }
758 367e86e8 bellard
759 67b915a5 bellard
760 67b915a5 bellard
    n_strtab = load_data(fd, (fhdr.f_symptr + fhdr.f_nsyms*SYMESZ), STRTAB_SIZE);
761 5fafdf24 ths
    strtab = load_data(fd, (fhdr.f_symptr + fhdr.f_nsyms*SYMESZ), *n_strtab);
762 3b46e624 ths
763 67b915a5 bellard
    nb_syms = fhdr.f_nsyms;
764 67b915a5 bellard
765 67b915a5 bellard
    for (i = 0, ext_sym = coff_symtab; i < nb_syms; i++, ext_sym++) {
766 67b915a5 bellard
      if (strstart(ext_sym->e.e_name, ".text", NULL))
767 67b915a5 bellard
                  text_shndx = ext_sym->e_scnum;
768 67b915a5 bellard
          if (strstart(ext_sym->e.e_name, ".data", NULL))
769 67b915a5 bellard
                  data_shndx = ext_sym->e_scnum;
770 367e86e8 bellard
    }
771 67b915a5 bellard
772 67b915a5 bellard
        /* set coff symbol */
773 67b915a5 bellard
        symtab = malloc(sizeof(struct coff_sym) * nb_syms);
774 67b915a5 bellard
775 67b915a5 bellard
        for (i = 0, ext_sym = coff_symtab, sym = symtab; i < nb_syms; i++, ext_sym++, sym++) {
776 67b915a5 bellard
                memset(sym, 0, sizeof(*sym));
777 67b915a5 bellard
                sym->st_syment = ext_sym;
778 67b915a5 bellard
                sym_ent_name(ext_sym, sym);
779 67b915a5 bellard
                sym->st_value = ext_sym->e_value;
780 67b915a5 bellard
781 67b915a5 bellard
                aux_size = *(int8_t *)ext_sym->e_numaux;
782 67b915a5 bellard
                if (ext_sym->e_scnum == text_shndx && ext_sym->e_type == T_FUNCTION) {
783 67b915a5 bellard
                        for (j = aux_size + 1; j < nb_syms - i; j++) {
784 67b915a5 bellard
                                if ((ext_sym + j)->e_scnum == text_shndx &&
785 67b915a5 bellard
                                        (ext_sym + j)->e_type == T_FUNCTION ){
786 67b915a5 bellard
                                        sym->st_size = (ext_sym + j)->e_value - ext_sym->e_value;
787 67b915a5 bellard
                                        break;
788 67b915a5 bellard
                                } else if (j == nb_syms - i - 1) {
789 67b915a5 bellard
                                        sec = &shdr[coff_text_shndx];
790 67b915a5 bellard
                                        sym->st_size = sec->s_size - ext_sym->e_value;
791 67b915a5 bellard
                                        break;
792 67b915a5 bellard
                                }
793 67b915a5 bellard
                        }
794 67b915a5 bellard
                } else if (ext_sym->e_scnum == data_shndx && *(uint8_t *)ext_sym->e_sclass == C_EXTERNAL) {
795 67b915a5 bellard
                        for (j = aux_size + 1; j < nb_syms - i; j++) {
796 67b915a5 bellard
                                if ((ext_sym + j)->e_scnum == data_shndx) {
797 67b915a5 bellard
                                        sym->st_size = (ext_sym + j)->e_value - ext_sym->e_value;
798 67b915a5 bellard
                                        break;
799 67b915a5 bellard
                                } else if (j == nb_syms - i - 1) {
800 67b915a5 bellard
                                        sec = &shdr[coff_data_shndx];
801 67b915a5 bellard
                                        sym->st_size = sec->s_size - ext_sym->e_value;
802 67b915a5 bellard
                                        break;
803 67b915a5 bellard
                                }
804 67b915a5 bellard
                        }
805 67b915a5 bellard
                } else {
806 67b915a5 bellard
                        sym->st_size = 0;
807 67b915a5 bellard
                }
808 3b46e624 ths
809 67b915a5 bellard
                sym->st_type = ext_sym->e_type;
810 67b915a5 bellard
                sym->st_shndx = ext_sym->e_scnum;
811 67b915a5 bellard
        }
812 67b915a5 bellard
813 3b46e624 ths
814 67b915a5 bellard
    /* find text relocations, if any */
815 67b915a5 bellard
    sec = &shdr[coff_text_shndx];
816 67b915a5 bellard
    coff_relocs = load_data(fd, sec->s_relptr, sec->s_nreloc*RELSZ);
817 67b915a5 bellard
    nb_relocs = sec->s_nreloc;
818 67b915a5 bellard
819 67b915a5 bellard
    /* set coff relocation */
820 67b915a5 bellard
    relocs = malloc(sizeof(struct coff_rel) * nb_relocs);
821 5fafdf24 ths
    for (i = 0, ext_rel = coff_relocs, rel = relocs; i < nb_relocs;
822 67b915a5 bellard
         i++, ext_rel++, rel++) {
823 67b915a5 bellard
        memset(rel, 0, sizeof(*rel));
824 67b915a5 bellard
        rel->r_reloc = ext_rel;
825 67b915a5 bellard
        rel->r_offset = *(uint32_t *)ext_rel->r_vaddr;
826 67b915a5 bellard
        rel->r_type = *(uint16_t *)ext_rel->r_type;
827 67b915a5 bellard
    }
828 67b915a5 bellard
    return 0;
829 367e86e8 bellard
}
830 367e86e8 bellard
831 67b915a5 bellard
#endif /* CONFIG_FORMAT_COFF */
832 67b915a5 bellard
833 82eec0a1 bellard
#ifdef CONFIG_FORMAT_MACH
834 82eec0a1 bellard
835 82eec0a1 bellard
/* File Header */
836 82eec0a1 bellard
struct mach_header         mach_hdr;
837 82eec0a1 bellard
838 82eec0a1 bellard
/* commands */
839 82eec0a1 bellard
struct segment_command         *segment = 0;
840 82eec0a1 bellard
struct dysymtab_command *dysymtabcmd = 0;
841 82eec0a1 bellard
struct symtab_command         *symtabcmd = 0;
842 82eec0a1 bellard
843 82eec0a1 bellard
/* section */
844 82eec0a1 bellard
struct section         *section_hdr;
845 82eec0a1 bellard
struct section *text_sec_hdr;
846 82eec0a1 bellard
uint8_t         **sdata;
847 82eec0a1 bellard
848 82eec0a1 bellard
/* relocs */
849 82eec0a1 bellard
struct relocation_info *relocs;
850 5fafdf24 ths
851 82eec0a1 bellard
/* symbols */
852 82eec0a1 bellard
EXE_SYM                        *symtab;
853 82eec0a1 bellard
struct nlist         *symtab_std;
854 82eec0a1 bellard
char                        *strtab;
855 82eec0a1 bellard
856 82eec0a1 bellard
/* indirect symbols */
857 82eec0a1 bellard
uint32_t         *tocdylib;
858 82eec0a1 bellard
859 82eec0a1 bellard
/* Utility functions */
860 82eec0a1 bellard
861 82eec0a1 bellard
static inline char *find_str_by_index(int index)
862 82eec0a1 bellard
{
863 82eec0a1 bellard
    return strtab+index;
864 82eec0a1 bellard
}
865 82eec0a1 bellard
866 82eec0a1 bellard
/* Used by dyngen common code */
867 82eec0a1 bellard
static char *get_sym_name(EXE_SYM *sym)
868 82eec0a1 bellard
{
869 82eec0a1 bellard
        char *name = find_str_by_index(sym->n_un.n_strx);
870 5fafdf24 ths
871 82eec0a1 bellard
        if ( sym->n_type & N_STAB ) /* Debug symbols are ignored */
872 82eec0a1 bellard
                return "debug";
873 3b46e624 ths
874 82eec0a1 bellard
        if(!name)
875 82eec0a1 bellard
                return name;
876 82eec0a1 bellard
        if(name[0]=='_')
877 82eec0a1 bellard
                return name + 1;
878 82eec0a1 bellard
        else
879 82eec0a1 bellard
                return name;
880 82eec0a1 bellard
}
881 82eec0a1 bellard
882 82eec0a1 bellard
/* find a section index given its segname, sectname */
883 5fafdf24 ths
static int find_mach_sec_index(struct section *section_hdr, int shnum, const char *segname,
884 82eec0a1 bellard
                                  const char *sectname)
885 82eec0a1 bellard
{
886 82eec0a1 bellard
    int i;
887 82eec0a1 bellard
    struct section *sec = section_hdr;
888 82eec0a1 bellard
889 82eec0a1 bellard
    for(i = 0; i < shnum; i++, sec++) {
890 82eec0a1 bellard
        if (!sec->segname || !sec->sectname)
891 82eec0a1 bellard
            continue;
892 82eec0a1 bellard
        if (!strcmp(sec->sectname, sectname) && !strcmp(sec->segname, segname))
893 82eec0a1 bellard
            return i;
894 82eec0a1 bellard
    }
895 82eec0a1 bellard
    return -1;
896 82eec0a1 bellard
}
897 82eec0a1 bellard
898 82eec0a1 bellard
/* find a section header given its segname, sectname */
899 5fafdf24 ths
struct section *find_mach_sec_hdr(struct section *section_hdr, int shnum, const char *segname,
900 82eec0a1 bellard
                                  const char *sectname)
901 82eec0a1 bellard
{
902 82eec0a1 bellard
    int index = find_mach_sec_index(section_hdr, shnum, segname, sectname);
903 82eec0a1 bellard
        if(index == -1)
904 82eec0a1 bellard
                return NULL;
905 82eec0a1 bellard
        return section_hdr+index;
906 82eec0a1 bellard
}
907 82eec0a1 bellard
908 82eec0a1 bellard
909 82eec0a1 bellard
static inline void fetch_next_pair_value(struct relocation_info * rel, unsigned int *value)
910 82eec0a1 bellard
{
911 82eec0a1 bellard
    struct scattered_relocation_info * scarel;
912 5fafdf24 ths
913 82eec0a1 bellard
    if(R_SCATTERED & rel->r_address) {
914 82eec0a1 bellard
        scarel = (struct scattered_relocation_info*)rel;
915 82eec0a1 bellard
        if(scarel->r_type != PPC_RELOC_PAIR)
916 82eec0a1 bellard
            error("fetch_next_pair_value: looking for a pair which was not found (1)");
917 82eec0a1 bellard
        *value = scarel->r_value;
918 82eec0a1 bellard
    } else {
919 82eec0a1 bellard
                if(rel->r_type != PPC_RELOC_PAIR)
920 82eec0a1 bellard
                        error("fetch_next_pair_value: looking for a pair which was not found (2)");
921 82eec0a1 bellard
                *value = rel->r_address;
922 82eec0a1 bellard
        }
923 82eec0a1 bellard
}
924 82eec0a1 bellard
925 82eec0a1 bellard
/* find a sym name given its value, in a section number */
926 82eec0a1 bellard
static const char * find_sym_with_value_and_sec_number( int value, int sectnum, int * offset )
927 82eec0a1 bellard
{
928 82eec0a1 bellard
        int i, ret = -1;
929 5fafdf24 ths
930 82eec0a1 bellard
        for( i = 0 ; i < nb_syms; i++ )
931 82eec0a1 bellard
        {
932 82eec0a1 bellard
            if( !(symtab[i].n_type & N_STAB) && (symtab[i].n_type & N_SECT) &&
933 82eec0a1 bellard
                         (symtab[i].n_sect ==  sectnum) && (symtab[i].st_value <= value) )
934 82eec0a1 bellard
                {
935 82eec0a1 bellard
                        if( (ret<0) || (symtab[i].st_value >= symtab[ret].st_value) )
936 82eec0a1 bellard
                                ret = i;
937 82eec0a1 bellard
                }
938 82eec0a1 bellard
        }
939 82eec0a1 bellard
        if( ret < 0 ) {
940 82eec0a1 bellard
                *offset = 0;
941 82eec0a1 bellard
                return 0;
942 82eec0a1 bellard
        } else {
943 82eec0a1 bellard
                *offset = value - symtab[ret].st_value;
944 82eec0a1 bellard
                return get_sym_name(&symtab[ret]);
945 82eec0a1 bellard
        }
946 82eec0a1 bellard
}
947 82eec0a1 bellard
948 5fafdf24 ths
/*
949 5fafdf24 ths
 *  Find symbol name given a (virtual) address, and a section which is of type
950 82eec0a1 bellard
 *  S_NON_LAZY_SYMBOL_POINTERS or S_LAZY_SYMBOL_POINTERS or S_SYMBOL_STUBS
951 82eec0a1 bellard
 */
952 82eec0a1 bellard
static const char * find_reloc_name_in_sec_ptr(int address, struct section * sec_hdr)
953 82eec0a1 bellard
{
954 82eec0a1 bellard
    unsigned int tocindex, symindex, size;
955 82eec0a1 bellard
    const char *name = 0;
956 3b46e624 ths
957 82eec0a1 bellard
    /* Sanity check */
958 82eec0a1 bellard
    if(!( address >= sec_hdr->addr && address < (sec_hdr->addr + sec_hdr->size) ) )
959 82eec0a1 bellard
        return (char*)0;
960 3b46e624 ths
961 82eec0a1 bellard
        if( sec_hdr->flags & S_SYMBOL_STUBS ){
962 82eec0a1 bellard
                size = sec_hdr->reserved2;
963 82eec0a1 bellard
                if(size == 0)
964 82eec0a1 bellard
                    error("size = 0");
965 3b46e624 ths
966 82eec0a1 bellard
        }
967 82eec0a1 bellard
        else if( sec_hdr->flags & S_LAZY_SYMBOL_POINTERS ||
968 82eec0a1 bellard
                    sec_hdr->flags & S_NON_LAZY_SYMBOL_POINTERS)
969 82eec0a1 bellard
                size = sizeof(unsigned long);
970 82eec0a1 bellard
        else
971 82eec0a1 bellard
                return 0;
972 3b46e624 ths
973 82eec0a1 bellard
    /* Compute our index in toc */
974 82eec0a1 bellard
        tocindex = (address - sec_hdr->addr)/size;
975 82eec0a1 bellard
        symindex = tocdylib[sec_hdr->reserved1 + tocindex];
976 5fafdf24 ths
977 82eec0a1 bellard
        name = get_sym_name(&symtab[symindex]);
978 82eec0a1 bellard
979 82eec0a1 bellard
    return name;
980 82eec0a1 bellard
}
981 82eec0a1 bellard
982 82eec0a1 bellard
static const char * find_reloc_name_given_its_address(int address)
983 82eec0a1 bellard
{
984 82eec0a1 bellard
    unsigned int i;
985 82eec0a1 bellard
    for(i = 0; i < segment->nsects ; i++)
986 82eec0a1 bellard
    {
987 82eec0a1 bellard
        const char * name = find_reloc_name_in_sec_ptr(address, &section_hdr[i]);
988 82eec0a1 bellard
        if((long)name != -1)
989 82eec0a1 bellard
            return name;
990 82eec0a1 bellard
    }
991 82eec0a1 bellard
    return 0;
992 82eec0a1 bellard
}
993 82eec0a1 bellard
994 82eec0a1 bellard
static const char * get_reloc_name(EXE_RELOC * rel, int * sslide)
995 82eec0a1 bellard
{
996 82eec0a1 bellard
        char * name = 0;
997 82eec0a1 bellard
        struct scattered_relocation_info * sca_rel = (struct scattered_relocation_info*)rel;
998 82eec0a1 bellard
        int sectnum = rel->r_symbolnum;
999 82eec0a1 bellard
        int sectoffset;
1000 82eec0a1 bellard
        int other_half=0;
1001 5fafdf24 ths
1002 82eec0a1 bellard
        /* init the slide value */
1003 82eec0a1 bellard
        *sslide = 0;
1004 5fafdf24 ths
1005 82eec0a1 bellard
        if(R_SCATTERED & rel->r_address)
1006 82eec0a1 bellard
                return (char *)find_reloc_name_given_its_address(sca_rel->r_value);
1007 82eec0a1 bellard
1008 82eec0a1 bellard
        if(rel->r_extern)
1009 82eec0a1 bellard
        {
1010 82eec0a1 bellard
                /* ignore debug sym */
1011 5fafdf24 ths
                if ( symtab[rel->r_symbolnum].n_type & N_STAB )
1012 82eec0a1 bellard
                        return 0;
1013 82eec0a1 bellard
                return get_sym_name(&symtab[rel->r_symbolnum]);
1014 82eec0a1 bellard
        }
1015 82eec0a1 bellard
1016 82eec0a1 bellard
        /* Intruction contains an offset to the symbols pointed to, in the rel->r_symbolnum section */
1017 82eec0a1 bellard
        sectoffset = *(uint32_t *)(text + rel->r_address) & 0xffff;
1018 3b46e624 ths
1019 82eec0a1 bellard
        if(sectnum==0xffffff)
1020 82eec0a1 bellard
                return 0;
1021 82eec0a1 bellard
1022 82eec0a1 bellard
        /* Sanity Check */
1023 82eec0a1 bellard
        if(sectnum > segment->nsects)
1024 82eec0a1 bellard
                error("sectnum > segment->nsects");
1025 82eec0a1 bellard
1026 82eec0a1 bellard
        switch(rel->r_type)
1027 82eec0a1 bellard
        {
1028 91aa5d49 bellard
                case PPC_RELOC_LO16: fetch_next_pair_value(rel+1, &other_half); sectoffset |= (other_half << 16);
1029 82eec0a1 bellard
                        break;
1030 91aa5d49 bellard
                case PPC_RELOC_HI16: fetch_next_pair_value(rel+1, &other_half); sectoffset = (sectoffset << 16) | (uint16_t)(other_half & 0xffff);
1031 82eec0a1 bellard
                        break;
1032 91aa5d49 bellard
                case PPC_RELOC_HA16: fetch_next_pair_value(rel+1, &other_half); sectoffset = (sectoffset << 16) + (int16_t)(other_half & 0xffff);
1033 82eec0a1 bellard
                        break;
1034 82eec0a1 bellard
                case PPC_RELOC_BR24:
1035 82eec0a1 bellard
                        sectoffset = ( *(uint32_t *)(text + rel->r_address) & 0x03fffffc );
1036 82eec0a1 bellard
                        if (sectoffset & 0x02000000) sectoffset |= 0xfc000000;
1037 82eec0a1 bellard
                        break;
1038 82eec0a1 bellard
                default:
1039 82eec0a1 bellard
                        error("switch(rel->type) not found");
1040 82eec0a1 bellard
        }
1041 82eec0a1 bellard
1042 82eec0a1 bellard
        if(rel->r_pcrel)
1043 82eec0a1 bellard
                sectoffset += rel->r_address;
1044 3b46e624 ths
1045 82eec0a1 bellard
        if (rel->r_type == PPC_RELOC_BR24)
1046 82eec0a1 bellard
                name = (char *)find_reloc_name_in_sec_ptr((int)sectoffset, &section_hdr[sectnum-1]);
1047 82eec0a1 bellard
1048 82eec0a1 bellard
        /* search it in the full symbol list, if not found */
1049 82eec0a1 bellard
        if(!name)
1050 82eec0a1 bellard
                name = (char *)find_sym_with_value_and_sec_number(sectoffset, sectnum, sslide);
1051 5fafdf24 ths
1052 82eec0a1 bellard
        return name;
1053 82eec0a1 bellard
}
1054 82eec0a1 bellard
1055 82eec0a1 bellard
/* Used by dyngen common code */
1056 82eec0a1 bellard
static const char * get_rel_sym_name(EXE_RELOC * rel)
1057 82eec0a1 bellard
{
1058 82eec0a1 bellard
        int sslide;
1059 82eec0a1 bellard
        return get_reloc_name( rel, &sslide);
1060 82eec0a1 bellard
}
1061 82eec0a1 bellard
1062 82eec0a1 bellard
/* Used by dyngen common code */
1063 82eec0a1 bellard
static host_ulong get_rel_offset(EXE_RELOC *rel)
1064 82eec0a1 bellard
{
1065 82eec0a1 bellard
        struct scattered_relocation_info * sca_rel = (struct scattered_relocation_info*)rel;
1066 82eec0a1 bellard
    if(R_SCATTERED & rel->r_address)
1067 82eec0a1 bellard
                return sca_rel->r_address;
1068 82eec0a1 bellard
        else
1069 82eec0a1 bellard
                return rel->r_address;
1070 82eec0a1 bellard
}
1071 82eec0a1 bellard
1072 82eec0a1 bellard
/* load a mach-o object file */
1073 82eec0a1 bellard
int load_object(const char *filename)
1074 82eec0a1 bellard
{
1075 82eec0a1 bellard
        int fd;
1076 82eec0a1 bellard
        unsigned int offset_to_segment = 0;
1077 82eec0a1 bellard
    unsigned int offset_to_dysymtab = 0;
1078 82eec0a1 bellard
    unsigned int offset_to_symtab = 0;
1079 82eec0a1 bellard
    struct load_command lc;
1080 82eec0a1 bellard
    unsigned int i, j;
1081 82eec0a1 bellard
        EXE_SYM *sym;
1082 82eec0a1 bellard
        struct nlist *syment;
1083 3b46e624 ths
1084 82eec0a1 bellard
        fd = open(filename, O_RDONLY);
1085 5fafdf24 ths
    if (fd < 0)
1086 82eec0a1 bellard
        error("can't open file '%s'", filename);
1087 3b46e624 ths
1088 82eec0a1 bellard
    /* Read Mach header.  */
1089 82eec0a1 bellard
    if (read(fd, &mach_hdr, sizeof (mach_hdr)) != sizeof (mach_hdr))
1090 82eec0a1 bellard
        error("unable to read file header");
1091 82eec0a1 bellard
1092 82eec0a1 bellard
    /* Check Mach identification.  */
1093 82eec0a1 bellard
    if (!check_mach_header(mach_hdr)) {
1094 82eec0a1 bellard
        error("bad Mach header");
1095 82eec0a1 bellard
    }
1096 3b46e624 ths
1097 82eec0a1 bellard
    if (mach_hdr.cputype != CPU_TYPE_POWERPC)
1098 82eec0a1 bellard
        error("Unsupported CPU");
1099 3b46e624 ths
1100 82eec0a1 bellard
    if (mach_hdr.filetype != MH_OBJECT)
1101 82eec0a1 bellard
        error("Unsupported Mach Object");
1102 3b46e624 ths
1103 82eec0a1 bellard
    /* read segment headers */
1104 82eec0a1 bellard
    for(i=0, j=sizeof(mach_hdr); i<mach_hdr.ncmds ; i++)
1105 82eec0a1 bellard
    {
1106 82eec0a1 bellard
        if(read(fd, &lc, sizeof(struct load_command)) != sizeof(struct load_command))
1107 82eec0a1 bellard
            error("unable to read load_command");
1108 82eec0a1 bellard
        if(lc.cmd == LC_SEGMENT)
1109 82eec0a1 bellard
        {
1110 82eec0a1 bellard
            offset_to_segment = j;
1111 82eec0a1 bellard
            lseek(fd, offset_to_segment, SEEK_SET);
1112 82eec0a1 bellard
            segment = malloc(sizeof(struct segment_command));
1113 82eec0a1 bellard
            if(read(fd, segment, sizeof(struct segment_command)) != sizeof(struct segment_command))
1114 82eec0a1 bellard
                error("unable to read LC_SEGMENT");
1115 82eec0a1 bellard
        }
1116 82eec0a1 bellard
        if(lc.cmd == LC_DYSYMTAB)
1117 82eec0a1 bellard
        {
1118 82eec0a1 bellard
            offset_to_dysymtab = j;
1119 82eec0a1 bellard
            lseek(fd, offset_to_dysymtab, SEEK_SET);
1120 82eec0a1 bellard
            dysymtabcmd = malloc(sizeof(struct dysymtab_command));
1121 82eec0a1 bellard
            if(read(fd, dysymtabcmd, sizeof(struct dysymtab_command)) != sizeof(struct dysymtab_command))
1122 82eec0a1 bellard
                error("unable to read LC_DYSYMTAB");
1123 82eec0a1 bellard
        }
1124 82eec0a1 bellard
        if(lc.cmd == LC_SYMTAB)
1125 82eec0a1 bellard
        {
1126 82eec0a1 bellard
            offset_to_symtab = j;
1127 82eec0a1 bellard
            lseek(fd, offset_to_symtab, SEEK_SET);
1128 82eec0a1 bellard
            symtabcmd = malloc(sizeof(struct symtab_command));
1129 82eec0a1 bellard
            if(read(fd, symtabcmd, sizeof(struct symtab_command)) != sizeof(struct symtab_command))
1130 82eec0a1 bellard
                error("unable to read LC_SYMTAB");
1131 82eec0a1 bellard
        }
1132 82eec0a1 bellard
        j+=lc.cmdsize;
1133 82eec0a1 bellard
1134 82eec0a1 bellard
        lseek(fd, j, SEEK_SET);
1135 82eec0a1 bellard
    }
1136 82eec0a1 bellard
1137 82eec0a1 bellard
    if(!segment)
1138 82eec0a1 bellard
        error("unable to find LC_SEGMENT");
1139 82eec0a1 bellard
1140 82eec0a1 bellard
    /* read section headers */
1141 82eec0a1 bellard
    section_hdr = load_data(fd, offset_to_segment + sizeof(struct segment_command), segment->nsects * sizeof(struct section));
1142 82eec0a1 bellard
1143 82eec0a1 bellard
    /* read all section data */
1144 82eec0a1 bellard
    sdata = (uint8_t **)malloc(sizeof(void *) * segment->nsects);
1145 82eec0a1 bellard
    memset(sdata, 0, sizeof(void *) * segment->nsects);
1146 3b46e624 ths
1147 82eec0a1 bellard
        /* Load the data in section data */
1148 82eec0a1 bellard
        for(i = 0; i < segment->nsects; i++) {
1149 82eec0a1 bellard
        sdata[i] = load_data(fd, section_hdr[i].offset, section_hdr[i].size);
1150 82eec0a1 bellard
    }
1151 5fafdf24 ths
1152 82eec0a1 bellard
    /* text section */
1153 82eec0a1 bellard
        text_sec_hdr = find_mach_sec_hdr(section_hdr, segment->nsects, SEG_TEXT, SECT_TEXT);
1154 82eec0a1 bellard
        i = find_mach_sec_index(section_hdr, segment->nsects, SEG_TEXT, SECT_TEXT);
1155 82eec0a1 bellard
        if (i == -1 || !text_sec_hdr)
1156 82eec0a1 bellard
        error("could not find __TEXT,__text section");
1157 82eec0a1 bellard
    text = sdata[i];
1158 5fafdf24 ths
1159 82eec0a1 bellard
    /* Make sure dysym was loaded */
1160 82eec0a1 bellard
    if(!(int)dysymtabcmd)
1161 82eec0a1 bellard
        error("could not find __DYSYMTAB segment");
1162 3b46e624 ths
1163 82eec0a1 bellard
    /* read the table of content of the indirect sym */
1164 82eec0a1 bellard
    tocdylib = load_data( fd, dysymtabcmd->indirectsymoff, dysymtabcmd->nindirectsyms * sizeof(uint32_t) );
1165 3b46e624 ths
1166 82eec0a1 bellard
    /* Make sure symtab was loaded  */
1167 82eec0a1 bellard
    if(!(int)symtabcmd)
1168 82eec0a1 bellard
        error("could not find __SYMTAB segment");
1169 82eec0a1 bellard
    nb_syms = symtabcmd->nsyms;
1170 82eec0a1 bellard
1171 82eec0a1 bellard
    symtab_std = load_data(fd, symtabcmd->symoff, symtabcmd->nsyms * sizeof(struct nlist));
1172 82eec0a1 bellard
    strtab = load_data(fd, symtabcmd->stroff, symtabcmd->strsize);
1173 5fafdf24 ths
1174 82eec0a1 bellard
        symtab = malloc(sizeof(EXE_SYM) * nb_syms);
1175 5fafdf24 ths
1176 82eec0a1 bellard
        /* Now transform the symtab, to an extended version, with the sym size, and the C name */
1177 82eec0a1 bellard
        for(i = 0, sym = symtab, syment = symtab_std; i < nb_syms; i++, sym++, syment++) {
1178 82eec0a1 bellard
        struct nlist *sym_follow, *sym_next = 0;
1179 82eec0a1 bellard
        unsigned int j;
1180 82eec0a1 bellard
                memset(sym, 0, sizeof(*sym));
1181 3b46e624 ths
1182 91aa5d49 bellard
                if ( syment->n_type & N_STAB ) /* Debug symbols are skipped */
1183 82eec0a1 bellard
            continue;
1184 3b46e624 ths
1185 82eec0a1 bellard
                memcpy(sym, syment, sizeof(*syment));
1186 3b46e624 ths
1187 82eec0a1 bellard
                /* Find the following symbol in order to get the current symbol size */
1188 82eec0a1 bellard
        for(j = 0, sym_follow = symtab_std; j < nb_syms; j++, sym_follow++) {
1189 82eec0a1 bellard
            if ( sym_follow->n_sect != 1 || sym_follow->n_type & N_STAB || !(sym_follow->n_value > sym->st_value))
1190 82eec0a1 bellard
                continue;
1191 82eec0a1 bellard
            if(!sym_next) {
1192 82eec0a1 bellard
                sym_next = sym_follow;
1193 82eec0a1 bellard
                continue;
1194 82eec0a1 bellard
            }
1195 82eec0a1 bellard
            if(!(sym_next->n_value > sym_follow->n_value))
1196 82eec0a1 bellard
                continue;
1197 82eec0a1 bellard
            sym_next = sym_follow;
1198 82eec0a1 bellard
        }
1199 82eec0a1 bellard
                if(sym_next)
1200 82eec0a1 bellard
            sym->st_size = sym_next->n_value - sym->st_value;
1201 82eec0a1 bellard
                else
1202 82eec0a1 bellard
            sym->st_size = text_sec_hdr->size - sym->st_value;
1203 82eec0a1 bellard
        }
1204 5fafdf24 ths
1205 82eec0a1 bellard
    /* Find Reloc */
1206 82eec0a1 bellard
    relocs = load_data(fd, text_sec_hdr->reloff, text_sec_hdr->nreloc * sizeof(struct relocation_info));
1207 82eec0a1 bellard
    nb_relocs = text_sec_hdr->nreloc;
1208 82eec0a1 bellard
1209 82eec0a1 bellard
        close(fd);
1210 82eec0a1 bellard
        return 0;
1211 82eec0a1 bellard
}
1212 82eec0a1 bellard
1213 82eec0a1 bellard
#endif /* CONFIG_FORMAT_MACH */
1214 82eec0a1 bellard
1215 bef79c34 bellard
void get_reloc_expr(char *name, int name_size, const char *sym_name)
1216 bef79c34 bellard
{
1217 bef79c34 bellard
    const char *p;
1218 bef79c34 bellard
1219 bef79c34 bellard
    if (strstart(sym_name, "__op_param", &p)) {
1220 bef79c34 bellard
        snprintf(name, name_size, "param%s", p);
1221 bef79c34 bellard
    } else if (strstart(sym_name, "__op_gen_label", &p)) {
1222 bef79c34 bellard
        snprintf(name, name_size, "gen_labels[param%s]", p);
1223 bef79c34 bellard
    } else {
1224 bef79c34 bellard
#ifdef HOST_SPARC
1225 bef79c34 bellard
        if (sym_name[0] == '.')
1226 4bb3973f bellard
            snprintf(name, name_size,
1227 bef79c34 bellard
                     "(long)(&__dot_%s)",
1228 bef79c34 bellard
                     sym_name + 1);
1229 bef79c34 bellard
        else
1230 bef79c34 bellard
#endif
1231 bef79c34 bellard
            snprintf(name, name_size, "(long)(&%s)", sym_name);
1232 bef79c34 bellard
    }
1233 bef79c34 bellard
}
1234 bef79c34 bellard
1235 b8076a74 bellard
#ifdef HOST_IA64
1236 b8076a74 bellard
1237 b8076a74 bellard
#define PLT_ENTRY_SIZE        16        /* 1 bundle containing "brl" */
1238 b8076a74 bellard
1239 b8076a74 bellard
struct plt_entry {
1240 b8076a74 bellard
    struct plt_entry *next;
1241 b8076a74 bellard
    const char *name;
1242 b8076a74 bellard
    unsigned long addend;
1243 b8076a74 bellard
} *plt_list;
1244 b8076a74 bellard
1245 b8076a74 bellard
static int
1246 b8076a74 bellard
get_plt_index (const char *name, unsigned long addend)
1247 b8076a74 bellard
{
1248 b8076a74 bellard
    struct plt_entry *plt, *prev= NULL;
1249 b8076a74 bellard
    int index = 0;
1250 b8076a74 bellard
1251 b8076a74 bellard
    /* see if we already have an entry for this target: */
1252 b8076a74 bellard
    for (plt = plt_list; plt; ++index, prev = plt, plt = plt->next)
1253 b8076a74 bellard
        if (strcmp(plt->name, name) == 0 && plt->addend == addend)
1254 b8076a74 bellard
            return index;
1255 b8076a74 bellard
1256 b8076a74 bellard
    /* nope; create a new PLT entry: */
1257 b8076a74 bellard
1258 b8076a74 bellard
    plt = malloc(sizeof(*plt));
1259 b8076a74 bellard
    if (!plt) {
1260 b8076a74 bellard
        perror("malloc");
1261 b8076a74 bellard
        exit(1);
1262 b8076a74 bellard
    }
1263 b8076a74 bellard
    memset(plt, 0, sizeof(*plt));
1264 b8076a74 bellard
    plt->name = strdup(name);
1265 b8076a74 bellard
    plt->addend = addend;
1266 b8076a74 bellard
1267 b8076a74 bellard
    /* append to plt-list: */
1268 b8076a74 bellard
    if (prev)
1269 b8076a74 bellard
        prev->next = plt;
1270 b8076a74 bellard
    else
1271 b8076a74 bellard
        plt_list = plt;
1272 b8076a74 bellard
    return index;
1273 b8076a74 bellard
}
1274 b8076a74 bellard
1275 b8076a74 bellard
#endif
1276 b8076a74 bellard
1277 ff1f20a3 bellard
#ifdef HOST_ARM
1278 ff1f20a3 bellard
1279 ff1f20a3 bellard
int arm_emit_ldr_info(const char *name, unsigned long start_offset,
1280 ff1f20a3 bellard
                      FILE *outfile, uint8_t *p_start, uint8_t *p_end,
1281 ff1f20a3 bellard
                      ELF_RELOC *relocs, int nb_relocs)
1282 ff1f20a3 bellard
{
1283 ff1f20a3 bellard
    uint8_t *p;
1284 ff1f20a3 bellard
    uint32_t insn;
1285 46152182 pbrook
    int offset, min_offset, pc_offset, data_size, spare, max_pool;
1286 ff1f20a3 bellard
    uint8_t data_allocated[1024];
1287 ff1f20a3 bellard
    unsigned int data_index;
1288 46152182 pbrook
    int type;
1289 3b46e624 ths
1290 ff1f20a3 bellard
    memset(data_allocated, 0, sizeof(data_allocated));
1291 3b46e624 ths
1292 ff1f20a3 bellard
    p = p_start;
1293 ff1f20a3 bellard
    min_offset = p_end - p_start;
1294 46152182 pbrook
    spare = 0x7fffffff;
1295 ff1f20a3 bellard
    while (p < p_start + min_offset) {
1296 ff1f20a3 bellard
        insn = get32((uint32_t *)p);
1297 46152182 pbrook
        /* TODO: Armv5e ldrd.  */
1298 46152182 pbrook
        /* TODO: VFP load.  */
1299 ff1f20a3 bellard
        if ((insn & 0x0d5f0000) == 0x051f0000) {
1300 ff1f20a3 bellard
            /* ldr reg, [pc, #im] */
1301 ff1f20a3 bellard
            offset = insn & 0xfff;
1302 ff1f20a3 bellard
            if (!(insn & 0x00800000))
1303 46152182 pbrook
                offset = -offset;
1304 46152182 pbrook
            max_pool = 4096;
1305 46152182 pbrook
            type = 0;
1306 46152182 pbrook
        } else if ((insn & 0x0e5f0f00) == 0x0c1f0100) {
1307 46152182 pbrook
            /* FPA ldf.  */
1308 46152182 pbrook
            offset = (insn & 0xff) << 2;
1309 46152182 pbrook
            if (!(insn & 0x00800000))
1310 46152182 pbrook
                offset = -offset;
1311 46152182 pbrook
            max_pool = 1024;
1312 46152182 pbrook
            type = 1;
1313 46152182 pbrook
        } else if ((insn & 0x0fff0000) == 0x028f0000) {
1314 46152182 pbrook
            /* Some gcc load a doubleword immediate with
1315 46152182 pbrook
               add regN, pc, #imm
1316 46152182 pbrook
               ldmia regN, {regN, regM}
1317 46152182 pbrook
               Hope and pray the compiler never generates somethin like
1318 46152182 pbrook
               add reg, pc, #imm1; ldr reg, [reg, #-imm2]; */
1319 46152182 pbrook
            int r;
1320 46152182 pbrook
1321 46152182 pbrook
            r = (insn & 0xf00) >> 7;
1322 46152182 pbrook
            offset = ((insn & 0xff) >> r) | ((insn & 0xff) << (32 - r));
1323 46152182 pbrook
            max_pool = 1024;
1324 46152182 pbrook
            type = 2;
1325 46152182 pbrook
        } else {
1326 46152182 pbrook
            max_pool = 0;
1327 46152182 pbrook
            type = -1;
1328 46152182 pbrook
        }
1329 46152182 pbrook
        if (type >= 0) {
1330 46152182 pbrook
            /* PC-relative load needs fixing up.  */
1331 46152182 pbrook
            if (spare > max_pool - offset)
1332 46152182 pbrook
                spare = max_pool - offset;
1333 ff1f20a3 bellard
            if ((offset & 3) !=0)
1334 5fafdf24 ths
                error("%s:%04x: pc offset must be 32 bit aligned",
1335 46152182 pbrook
                      name, start_offset + p - p_start);
1336 46152182 pbrook
            if (offset < 0)
1337 46152182 pbrook
                error("%s:%04x: Embedded literal value",
1338 ff1f20a3 bellard
                      name, start_offset + p - p_start);
1339 ff1f20a3 bellard
            pc_offset = p - p_start + offset + 8;
1340 5fafdf24 ths
            if (pc_offset <= (p - p_start) ||
1341 ff1f20a3 bellard
                pc_offset >= (p_end - p_start))
1342 5fafdf24 ths
                error("%s:%04x: pc offset must point inside the function code",
1343 ff1f20a3 bellard
                      name, start_offset + p - p_start);
1344 ff1f20a3 bellard
            if (pc_offset < min_offset)
1345 ff1f20a3 bellard
                min_offset = pc_offset;
1346 ff1f20a3 bellard
            if (outfile) {
1347 46152182 pbrook
                /* The intruction position */
1348 5fafdf24 ths
                fprintf(outfile, "    arm_ldr_ptr->ptr = gen_code_ptr + %d;\n",
1349 ff1f20a3 bellard
                        p - p_start);
1350 46152182 pbrook
                /* The position of the constant pool data.  */
1351 46152182 pbrook
                data_index = ((p_end - p_start) - pc_offset) >> 2;
1352 5fafdf24 ths
                fprintf(outfile, "    arm_ldr_ptr->data_ptr = arm_data_ptr - %d;\n",
1353 ff1f20a3 bellard
                        data_index);
1354 46152182 pbrook
                fprintf(outfile, "    arm_ldr_ptr->type = %d;\n", type);
1355 ff1f20a3 bellard
                fprintf(outfile, "    arm_ldr_ptr++;\n");
1356 ff1f20a3 bellard
            }
1357 ff1f20a3 bellard
        }
1358 ff1f20a3 bellard
        p += 4;
1359 ff1f20a3 bellard
    }
1360 46152182 pbrook
1361 46152182 pbrook
    /* Copy and relocate the constant pool data.  */
1362 ff1f20a3 bellard
    data_size = (p_end - p_start) - min_offset;
1363 ff1f20a3 bellard
    if (data_size > 0 && outfile) {
1364 46152182 pbrook
        spare += min_offset;
1365 46152182 pbrook
        fprintf(outfile, "    arm_data_ptr -= %d;\n", data_size >> 2);
1366 46152182 pbrook
        fprintf(outfile, "    arm_pool_ptr -= %d;\n", data_size);
1367 46152182 pbrook
        fprintf(outfile, "    if (arm_pool_ptr > gen_code_ptr + %d)\n"
1368 46152182 pbrook
                         "        arm_pool_ptr = gen_code_ptr + %d;\n",
1369 46152182 pbrook
                         spare, spare);
1370 46152182 pbrook
1371 46152182 pbrook
        data_index = 0;
1372 46152182 pbrook
        for (pc_offset = min_offset;
1373 46152182 pbrook
             pc_offset < p_end - p_start;
1374 46152182 pbrook
             pc_offset += 4) {
1375 46152182 pbrook
1376 46152182 pbrook
            ELF_RELOC *rel;
1377 46152182 pbrook
            int i, addend, type;
1378 46152182 pbrook
            const char *sym_name;
1379 46152182 pbrook
            char relname[1024];
1380 46152182 pbrook
1381 46152182 pbrook
            /* data value */
1382 46152182 pbrook
            addend = get32((uint32_t *)(p_start + pc_offset));
1383 46152182 pbrook
            relname[0] = '\0';
1384 46152182 pbrook
            for(i = 0, rel = relocs;i < nb_relocs; i++, rel++) {
1385 46152182 pbrook
                if (rel->r_offset == (pc_offset + start_offset)) {
1386 46152182 pbrook
                    sym_name = get_rel_sym_name(rel);
1387 46152182 pbrook
                    /* the compiler leave some unnecessary references to the code */
1388 46152182 pbrook
                    get_reloc_expr(relname, sizeof(relname), sym_name);
1389 46152182 pbrook
                    type = ELF32_R_TYPE(rel->r_info);
1390 46152182 pbrook
                    if (type != R_ARM_ABS32)
1391 46152182 pbrook
                        error("%s: unsupported data relocation", name);
1392 46152182 pbrook
                    break;
1393 46152182 pbrook
                }
1394 46152182 pbrook
            }
1395 46152182 pbrook
            fprintf(outfile, "    arm_data_ptr[%d] = 0x%x",
1396 46152182 pbrook
                    data_index, addend);
1397 46152182 pbrook
            if (relname[0] != '\0')
1398 46152182 pbrook
                fprintf(outfile, " + %s", relname);
1399 46152182 pbrook
            fprintf(outfile, ";\n");
1400 46152182 pbrook
1401 46152182 pbrook
            data_index++;
1402 46152182 pbrook
        }
1403 ff1f20a3 bellard
    }
1404 ff1f20a3 bellard
1405 ff1f20a3 bellard
    if (p == p_start)
1406 ff1f20a3 bellard
        goto arm_ret_error;
1407 ff1f20a3 bellard
    p -= 4;
1408 ff1f20a3 bellard
    insn = get32((uint32_t *)p);
1409 46152182 pbrook
    /* The last instruction must be an ldm instruction.  There are several
1410 46152182 pbrook
       forms generated by gcc:
1411 46152182 pbrook
        ldmib sp, {..., pc}  (implies a sp adjustment of +4)
1412 46152182 pbrook
        ldmia sp, {..., pc}
1413 46152182 pbrook
        ldmea fp, {..., pc} */
1414 46152182 pbrook
    if ((insn & 0xffff8000) == 0xe99d8000) {
1415 46152182 pbrook
        if (outfile) {
1416 46152182 pbrook
            fprintf(outfile,
1417 46152182 pbrook
                    "    *(uint32_t *)(gen_code_ptr + %d) = 0xe28dd004;\n",
1418 46152182 pbrook
                    p - p_start);
1419 46152182 pbrook
        }
1420 46152182 pbrook
        p += 4;
1421 46152182 pbrook
    } else if ((insn & 0xffff8000) != 0xe89d8000
1422 46152182 pbrook
        && (insn & 0xffff8000) != 0xe91b8000) {
1423 ff1f20a3 bellard
    arm_ret_error:
1424 ff1f20a3 bellard
        if (!outfile)
1425 ff1f20a3 bellard
            printf("%s: invalid epilog\n", name);
1426 ff1f20a3 bellard
    }
1427 46152182 pbrook
    return p - p_start;
1428 ff1f20a3 bellard
}
1429 ff1f20a3 bellard
#endif
1430 ff1f20a3 bellard
1431 ff1f20a3 bellard
1432 367e86e8 bellard
#define MAX_ARGS 3
1433 367e86e8 bellard
1434 367e86e8 bellard
/* generate op code */
1435 5fafdf24 ths
void gen_code(const char *name, host_ulong offset, host_ulong size,
1436 67b915a5 bellard
              FILE *outfile, int gen_switch)
1437 367e86e8 bellard
{
1438 367e86e8 bellard
    int copy_size = 0;
1439 367e86e8 bellard
    uint8_t *p_start, *p_end;
1440 ae228531 bellard
    host_ulong start_offset;
1441 ce11fedc bellard
    int nb_args, i, n;
1442 367e86e8 bellard
    uint8_t args_present[MAX_ARGS];
1443 367e86e8 bellard
    const char *sym_name, *p;
1444 67b915a5 bellard
    EXE_RELOC *rel;
1445 367e86e8 bellard
1446 ae228531 bellard
    /* Compute exact size excluding prologue and epilogue instructions.
1447 ae228531 bellard
     * Increment start_offset to skip epilogue instructions, then compute
1448 ae228531 bellard
     * copy_size the indicate the size of the remaining instructions (in
1449 ae228531 bellard
     * bytes).
1450 ae228531 bellard
     */
1451 367e86e8 bellard
    p_start = text + offset;
1452 367e86e8 bellard
    p_end = p_start + size;
1453 ae228531 bellard
    start_offset = offset;
1454 c4687878 bellard
#if defined(HOST_I386) || defined(HOST_X86_64)
1455 67b915a5 bellard
#ifdef CONFIG_FORMAT_COFF
1456 67b915a5 bellard
    {
1457 67b915a5 bellard
        uint8_t *p;
1458 67b915a5 bellard
        p = p_end - 1;
1459 67b915a5 bellard
        if (p == p_start)
1460 67b915a5 bellard
            error("empty code for %s", name);
1461 67b915a5 bellard
        while (*p != 0xc3) {
1462 67b915a5 bellard
            p--;
1463 67b915a5 bellard
            if (p <= p_start)
1464 d4e8164f bellard
                error("ret or jmp expected at the end of %s", name);
1465 367e86e8 bellard
        }
1466 67b915a5 bellard
        copy_size = p - p_start;
1467 67b915a5 bellard
    }
1468 67b915a5 bellard
#else
1469 67b915a5 bellard
    {
1470 67b915a5 bellard
        int len;
1471 67b915a5 bellard
        len = p_end - p_start;
1472 67b915a5 bellard
        if (len == 0)
1473 67b915a5 bellard
            error("empty code for %s", name);
1474 67b915a5 bellard
        if (p_end[-1] == 0xc3) {
1475 67b915a5 bellard
            len--;
1476 67b915a5 bellard
        } else {
1477 67b915a5 bellard
            error("ret or jmp expected at the end of %s", name);
1478 367e86e8 bellard
        }
1479 67b915a5 bellard
        copy_size = len;
1480 67b915a5 bellard
    }
1481 3b46e624 ths
#endif
1482 67b915a5 bellard
#elif defined(HOST_PPC)
1483 67b915a5 bellard
    {
1484 67b915a5 bellard
        uint8_t *p;
1485 67b915a5 bellard
        p = (void *)(p_end - 4);
1486 67b915a5 bellard
        if (p == p_start)
1487 67b915a5 bellard
            error("empty code for %s", name);
1488 67b915a5 bellard
        if (get32((uint32_t *)p) != 0x4e800020)
1489 67b915a5 bellard
            error("blr expected at the end of %s", name);
1490 67b915a5 bellard
        copy_size = p - p_start;
1491 67b915a5 bellard
    }
1492 67b915a5 bellard
#elif defined(HOST_S390)
1493 67b915a5 bellard
    {
1494 67b915a5 bellard
        uint8_t *p;
1495 67b915a5 bellard
        p = (void *)(p_end - 2);
1496 67b915a5 bellard
        if (p == p_start)
1497 67b915a5 bellard
            error("empty code for %s", name);
1498 76d83bde ths
        if ((get16((uint16_t *)p) & 0xfff0) != 0x07f0)
1499 76d83bde ths
            error("br expected at the end of %s", name);
1500 67b915a5 bellard
        copy_size = p - p_start;
1501 67b915a5 bellard
    }
1502 67b915a5 bellard
#elif defined(HOST_ALPHA)
1503 67b915a5 bellard
    {
1504 67b915a5 bellard
        uint8_t *p;
1505 67b915a5 bellard
        p = p_end - 4;
1506 630be16f bellard
#if 0
1507 67b915a5 bellard
        /* XXX: check why it occurs */
1508 67b915a5 bellard
        if (p == p_start)
1509 67b915a5 bellard
            error("empty code for %s", name);
1510 630be16f bellard
#endif
1511 67b915a5 bellard
        if (get32((uint32_t *)p) != 0x6bfa8001)
1512 67b915a5 bellard
            error("ret expected at the end of %s", name);
1513 3b46e624 ths
        copy_size = p - p_start;
1514 67b915a5 bellard
    }
1515 67b915a5 bellard
#elif defined(HOST_IA64)
1516 67b915a5 bellard
    {
1517 67b915a5 bellard
        uint8_t *p;
1518 67b915a5 bellard
        p = (void *)(p_end - 4);
1519 67b915a5 bellard
        if (p == p_start)
1520 67b915a5 bellard
            error("empty code for %s", name);
1521 67b915a5 bellard
        /* br.ret.sptk.many b0;; */
1522 67b915a5 bellard
        /* 08 00 84 00 */
1523 67b915a5 bellard
        if (get32((uint32_t *)p) != 0x00840008)
1524 67b915a5 bellard
            error("br.ret.sptk.many b0;; expected at the end of %s", name);
1525 b8076a74 bellard
        copy_size = p_end - p_start;
1526 67b915a5 bellard
    }
1527 67b915a5 bellard
#elif defined(HOST_SPARC)
1528 67b915a5 bellard
    {
1529 fdbb4691 bellard
#define INSN_SAVE       0x9de3a000
1530 fdbb4691 bellard
#define INSN_RET        0x81c7e008
1531 74ccb34e bellard
#define INSN_RETL       0x81c3e008
1532 fdbb4691 bellard
#define INSN_RESTORE    0x81e80000
1533 fdbb4691 bellard
#define INSN_RETURN     0x81cfe008
1534 fdbb4691 bellard
#define INSN_NOP        0x01000000
1535 74ccb34e bellard
#define INSN_ADD_SP     0x9c03a000 // add %sp, nn, %sp
1536 74ccb34e bellard
#define INSN_SUB_SP     0x9c23a000 // sub %sp, nn, %sp
1537 fdbb4691 bellard
1538 67b915a5 bellard
        uint32_t start_insn, end_insn1, end_insn2;
1539 67b915a5 bellard
        uint8_t *p;
1540 67b915a5 bellard
        p = (void *)(p_end - 8);
1541 67b915a5 bellard
        if (p <= p_start)
1542 67b915a5 bellard
            error("empty code for %s", name);
1543 67b915a5 bellard
        start_insn = get32((uint32_t *)(p_start + 0x0));
1544 67b915a5 bellard
        end_insn1 = get32((uint32_t *)(p + 0x0));
1545 67b915a5 bellard
        end_insn2 = get32((uint32_t *)(p + 0x4));
1546 74ccb34e bellard
        if (((start_insn & ~0x1fff) == INSN_SAVE) ||
1547 74ccb34e bellard
            (start_insn & ~0x1fff) == INSN_ADD_SP) {
1548 67b915a5 bellard
            p_start += 0x4;
1549 67b915a5 bellard
            start_offset += 0x4;
1550 fdbb4691 bellard
            if (end_insn1 == INSN_RET && end_insn2 == INSN_RESTORE)
1551 fdbb4691 bellard
                /* SPARC v7: ret; restore; */ ;
1552 fdbb4691 bellard
            else if (end_insn1 == INSN_RETURN && end_insn2 == INSN_NOP)
1553 fdbb4691 bellard
                /* SPARC v9: return; nop; */ ;
1554 74ccb34e bellard
            else if (end_insn1 == INSN_RETL && (end_insn2 & ~0x1fff) == INSN_SUB_SP)
1555 74ccb34e bellard
                /* SPARC v7: retl; sub %sp, nn, %sp; */ ;
1556 fdbb4691 bellard
            else
1557 fdbb4691 bellard
1558 67b915a5 bellard
                error("ret; restore; not found at end of %s", name);
1559 74ccb34e bellard
        } else if (end_insn1 == INSN_RETL && end_insn2 == INSN_NOP) {
1560 74ccb34e bellard
            ;
1561 67b915a5 bellard
        } else {
1562 67b915a5 bellard
            error("No save at the beginning of %s", name);
1563 67b915a5 bellard
        }
1564 ff1f20a3 bellard
#if 0
1565 67b915a5 bellard
        /* Skip a preceeding nop, if present.  */
1566 67b915a5 bellard
        if (p > p_start) {
1567 67b915a5 bellard
            skip_insn = get32((uint32_t *)(p - 0x4));
1568 fdbb4691 bellard
            if (skip_insn == INSN_NOP)
1569 67b915a5 bellard
                p -= 4;
1570 67b915a5 bellard
        }
1571 ff1f20a3 bellard
#endif
1572 67b915a5 bellard
        copy_size = p - p_start;
1573 67b915a5 bellard
    }
1574 67b915a5 bellard
#elif defined(HOST_SPARC64)
1575 67b915a5 bellard
    {
1576 74ccb34e bellard
#define INSN_SAVE       0x9de3a000
1577 74ccb34e bellard
#define INSN_RET        0x81c7e008
1578 74ccb34e bellard
#define INSN_RETL       0x81c3e008
1579 74ccb34e bellard
#define INSN_RESTORE    0x81e80000
1580 74ccb34e bellard
#define INSN_RETURN     0x81cfe008
1581 74ccb34e bellard
#define INSN_NOP        0x01000000
1582 74ccb34e bellard
#define INSN_ADD_SP     0x9c03a000 // add %sp, nn, %sp
1583 74ccb34e bellard
#define INSN_SUB_SP     0x9c23a000 // sub %sp, nn, %sp
1584 74ccb34e bellard
1585 67b915a5 bellard
        uint32_t start_insn, end_insn1, end_insn2, skip_insn;
1586 67b915a5 bellard
        uint8_t *p;
1587 67b915a5 bellard
        p = (void *)(p_end - 8);
1588 74ccb34e bellard
#if 0
1589 74ccb34e bellard
        /* XXX: check why it occurs */
1590 67b915a5 bellard
        if (p <= p_start)
1591 67b915a5 bellard
            error("empty code for %s", name);
1592 74ccb34e bellard
#endif
1593 67b915a5 bellard
        start_insn = get32((uint32_t *)(p_start + 0x0));
1594 67b915a5 bellard
        end_insn1 = get32((uint32_t *)(p + 0x0));
1595 67b915a5 bellard
        end_insn2 = get32((uint32_t *)(p + 0x4));
1596 74ccb34e bellard
        if (((start_insn & ~0x1fff) == INSN_SAVE) ||
1597 74ccb34e bellard
            (start_insn & ~0x1fff) == INSN_ADD_SP) {
1598 67b915a5 bellard
            p_start += 0x4;
1599 67b915a5 bellard
            start_offset += 0x4;
1600 74ccb34e bellard
            if (end_insn1 == INSN_RET && end_insn2 == INSN_RESTORE)
1601 74ccb34e bellard
                /* SPARC v7: ret; restore; */ ;
1602 74ccb34e bellard
            else if (end_insn1 == INSN_RETURN && end_insn2 == INSN_NOP)
1603 74ccb34e bellard
                /* SPARC v9: return; nop; */ ;
1604 74ccb34e bellard
            else if (end_insn1 == INSN_RETL && (end_insn2 & ~0x1fff) == INSN_SUB_SP)
1605 74ccb34e bellard
                /* SPARC v7: retl; sub %sp, nn, %sp; */ ;
1606 74ccb34e bellard
            else
1607 74ccb34e bellard
1608 67b915a5 bellard
                error("ret; restore; not found at end of %s", name);
1609 74ccb34e bellard
        } else if (end_insn1 == INSN_RETL && end_insn2 == INSN_NOP) {
1610 74ccb34e bellard
            ;
1611 67b915a5 bellard
        } else {
1612 67b915a5 bellard
            error("No save at the beginning of %s", name);
1613 67b915a5 bellard
        }
1614 3b46e624 ths
1615 67b915a5 bellard
        /* Skip a preceeding nop, if present.  */
1616 67b915a5 bellard
        if (p > p_start) {
1617 67b915a5 bellard
            skip_insn = get32((uint32_t *)(p - 0x4));
1618 67b915a5 bellard
            if (skip_insn == 0x01000000)
1619 67b915a5 bellard
                p -= 4;
1620 67b915a5 bellard
        }
1621 3b46e624 ths
1622 67b915a5 bellard
        copy_size = p - p_start;
1623 67b915a5 bellard
    }
1624 67b915a5 bellard
#elif defined(HOST_ARM)
1625 67b915a5 bellard
    {
1626 46152182 pbrook
        uint32_t insn;
1627 46152182 pbrook
1628 ff1f20a3 bellard
        if ((p_end - p_start) <= 16)
1629 ff1f20a3 bellard
            error("%s: function too small", name);
1630 ff1f20a3 bellard
        if (get32((uint32_t *)p_start) != 0xe1a0c00d ||
1631 ff1f20a3 bellard
            (get32((uint32_t *)(p_start + 4)) & 0xffff0000) != 0xe92d0000 ||
1632 ff1f20a3 bellard
            get32((uint32_t *)(p_start + 8)) != 0xe24cb004)
1633 ff1f20a3 bellard
            error("%s: invalid prolog", name);
1634 ff1f20a3 bellard
        p_start += 12;
1635 ff1f20a3 bellard
        start_offset += 12;
1636 46152182 pbrook
        insn = get32((uint32_t *)p_start);
1637 46152182 pbrook
        if ((insn & 0xffffff00) == 0xe24dd000) {
1638 46152182 pbrook
            /* Stack adjustment.  Assume op uses the frame pointer.  */
1639 46152182 pbrook
            p_start -= 4;
1640 46152182 pbrook
            start_offset -= 4;
1641 46152182 pbrook
        }
1642 5fafdf24 ths
        copy_size = arm_emit_ldr_info(name, start_offset, NULL, p_start, p_end,
1643 ff1f20a3 bellard
                                      relocs, nb_relocs);
1644 367e86e8 bellard
    }
1645 67b915a5 bellard
#elif defined(HOST_M68K)
1646 67b915a5 bellard
    {
1647 67b915a5 bellard
        uint8_t *p;
1648 67b915a5 bellard
        p = (void *)(p_end - 2);
1649 67b915a5 bellard
        if (p == p_start)
1650 67b915a5 bellard
            error("empty code for %s", name);
1651 67b915a5 bellard
        // remove NOP's, probably added for alignment
1652 67b915a5 bellard
        while ((get16((uint16_t *)p) == 0x4e71) &&
1653 5fafdf24 ths
               (p>p_start))
1654 67b915a5 bellard
            p -= 2;
1655 67b915a5 bellard
        if (get16((uint16_t *)p) != 0x4e75)
1656 67b915a5 bellard
            error("rts expected at the end of %s", name);
1657 67b915a5 bellard
        copy_size = p - p_start;
1658 67b915a5 bellard
    }
1659 9617efe8 ths
#elif defined(HOST_MIPS) || defined(HOST_MIPS64)
1660 c4b89d18 ths
    {
1661 c4b89d18 ths
#define INSN_RETURN     0x03e00008
1662 c4b89d18 ths
#define INSN_NOP        0x00000000
1663 c4b89d18 ths
1664 c4b89d18 ths
        uint8_t *p = p_end;
1665 c4b89d18 ths
1666 c4b89d18 ths
        if (p < (p_start + 0x8)) {
1667 c4b89d18 ths
            error("empty code for %s", name);
1668 c4b89d18 ths
        } else {
1669 c4b89d18 ths
            uint32_t end_insn1, end_insn2;
1670 c4b89d18 ths
1671 c4b89d18 ths
            p -= 0x8;
1672 c4b89d18 ths
            end_insn1 = get32((uint32_t *)(p + 0x0));
1673 c4b89d18 ths
            end_insn2 = get32((uint32_t *)(p + 0x4));
1674 c4b89d18 ths
            if (end_insn1 != INSN_RETURN && end_insn2 != INSN_NOP)
1675 c4b89d18 ths
                error("jr ra not found at end of %s", name);
1676 c4b89d18 ths
        }
1677 c4b89d18 ths
        copy_size = p - p_start;
1678 c4b89d18 ths
    }
1679 67b915a5 bellard
#else
1680 67b915a5 bellard
#error unsupported CPU
1681 67b915a5 bellard
#endif
1682 367e86e8 bellard
1683 367e86e8 bellard
    /* compute the number of arguments by looking at the relocations */
1684 367e86e8 bellard
    for(i = 0;i < MAX_ARGS; i++)
1685 367e86e8 bellard
        args_present[i] = 0;
1686 367e86e8 bellard
1687 ce11fedc bellard
    for(i = 0, rel = relocs;i < nb_relocs; i++, rel++) {
1688 82eec0a1 bellard
        host_ulong offset = get_rel_offset(rel);
1689 82eec0a1 bellard
        if (offset >= start_offset &&
1690 82eec0a1 bellard
            offset < start_offset + (p_end - p_start)) {
1691 67b915a5 bellard
            sym_name = get_rel_sym_name(rel);
1692 82eec0a1 bellard
            if(!sym_name)
1693 82eec0a1 bellard
                continue;
1694 c4687878 bellard
            if (strstart(sym_name, "__op_param", &p) ||
1695 c4687878 bellard
                strstart(sym_name, "__op_gen_label", &p)) {
1696 ce11fedc bellard
                n = strtoul(p, NULL, 10);
1697 d4e8164f bellard
                if (n > MAX_ARGS)
1698 ce11fedc bellard
                    error("too many arguments in %s", name);
1699 ce11fedc bellard
                args_present[n - 1] = 1;
1700 367e86e8 bellard
            }
1701 367e86e8 bellard
        }
1702 367e86e8 bellard
    }
1703 3b46e624 ths
1704 367e86e8 bellard
    nb_args = 0;
1705 367e86e8 bellard
    while (nb_args < MAX_ARGS && args_present[nb_args])
1706 367e86e8 bellard
        nb_args++;
1707 367e86e8 bellard
    for(i = nb_args; i < MAX_ARGS; i++) {
1708 367e86e8 bellard
        if (args_present[i])
1709 367e86e8 bellard
            error("inconsistent argument numbering in %s", name);
1710 367e86e8 bellard
    }
1711 367e86e8 bellard
1712 0ea00c9a bellard
    if (gen_switch == 2) {
1713 a513fe19 bellard
        fprintf(outfile, "DEF(%s, %d, %d)\n", name + 3, nb_args, copy_size);
1714 0ea00c9a bellard
    } else if (gen_switch == 1) {
1715 dc99065b bellard
1716 dc99065b bellard
        /* output C code */
1717 dc99065b bellard
        fprintf(outfile, "case INDEX_%s: {\n", name);
1718 dc99065b bellard
        if (nb_args > 0) {
1719 dc99065b bellard
            fprintf(outfile, "    long ");
1720 dc99065b bellard
            for(i = 0; i < nb_args; i++) {
1721 dc99065b bellard
                if (i != 0)
1722 dc99065b bellard
                    fprintf(outfile, ", ");
1723 dc99065b bellard
                fprintf(outfile, "param%d", i + 1);
1724 dc99065b bellard
            }
1725 dc99065b bellard
            fprintf(outfile, ";\n");
1726 367e86e8 bellard
        }
1727 b8076a74 bellard
#if defined(HOST_IA64)
1728 b8076a74 bellard
        fprintf(outfile, "    extern char %s;\n", name);
1729 b8076a74 bellard
#else
1730 dc99065b bellard
        fprintf(outfile, "    extern void %s();\n", name);
1731 b8076a74 bellard
#endif
1732 dc99065b bellard
1733 ce11fedc bellard
        for(i = 0, rel = relocs;i < nb_relocs; i++, rel++) {
1734 82eec0a1 bellard
            host_ulong offset = get_rel_offset(rel);
1735 82eec0a1 bellard
            if (offset >= start_offset &&
1736 82eec0a1 bellard
                offset < start_offset + (p_end - p_start)) {
1737 67b915a5 bellard
                sym_name = get_rel_sym_name(rel);
1738 82eec0a1 bellard
                if(!sym_name)
1739 82eec0a1 bellard
                    continue;
1740 5fafdf24 ths
                if (*sym_name &&
1741 d4e8164f bellard
                    !strstart(sym_name, "__op_param", NULL) &&
1742 c4687878 bellard
                    !strstart(sym_name, "__op_jmp", NULL) &&
1743 c4687878 bellard
                    !strstart(sym_name, "__op_gen_label", NULL)) {
1744 d014c98c bellard
#if defined(HOST_SPARC)
1745 d014c98c bellard
                    if (sym_name[0] == '.') {
1746 d014c98c bellard
                        fprintf(outfile,
1747 d014c98c bellard
                                "extern char __dot_%s __asm__(\"%s\");\n",
1748 d014c98c bellard
                                sym_name+1, sym_name);
1749 d014c98c bellard
                        continue;
1750 d014c98c bellard
                    }
1751 d014c98c bellard
#endif
1752 b8076a74 bellard
#if defined(__APPLE__)
1753 85028e4d ths
                    /* Set __attribute((unused)) on darwin because we
1754 85028e4d ths
                       want to avoid warning when we don't use the symbol.  */
1755 85028e4d ths
                    fprintf(outfile, "    extern char %s __attribute__((unused));\n", sym_name);
1756 b8076a74 bellard
#elif defined(HOST_IA64)
1757 b8076a74 bellard
                        if (ELF64_R_TYPE(rel->r_info) != R_IA64_PCREL21B)
1758 b8076a74 bellard
                                /*
1759 b8076a74 bellard
                                 * PCREL21 br.call targets generally
1760 b8076a74 bellard
                                 * are out of range and need to go
1761 b8076a74 bellard
                                 * through an "import stub".
1762 b8076a74 bellard
                                 */
1763 b8076a74 bellard
                                fprintf(outfile, "    extern char %s;\n",
1764 b8076a74 bellard
                                        sym_name);
1765 82eec0a1 bellard
#else
1766 ce11fedc bellard
                    fprintf(outfile, "extern char %s;\n", sym_name);
1767 82eec0a1 bellard
#endif
1768 dc99065b bellard
                }
1769 dc99065b bellard
            }
1770 dc99065b bellard
        }
1771 dc99065b bellard
1772 82eec0a1 bellard
        fprintf(outfile, "    memcpy(gen_code_ptr, (void *)((char *)&%s+%d), %d);\n",
1773 82eec0a1 bellard
                                        name, (int)(start_offset - offset), copy_size);
1774 d4e8164f bellard
1775 d4e8164f bellard
        /* emit code offset information */
1776 d4e8164f bellard
        {
1777 67b915a5 bellard
            EXE_SYM *sym;
1778 d4e8164f bellard
            const char *sym_name, *p;
1779 7a2d6d96 pbrook
            host_ulong val;
1780 d4e8164f bellard
            int n;
1781 d4e8164f bellard
1782 d4e8164f bellard
            for(i = 0, sym = symtab; i < nb_syms; i++, sym++) {
1783 67b915a5 bellard
                sym_name = get_sym_name(sym);
1784 d4e8164f bellard
                if (strstart(sym_name, "__op_label", &p)) {
1785 c1e42a13 bellard
                    uint8_t *ptr;
1786 fe319756 bellard
                    unsigned long offset;
1787 3b46e624 ths
1788 d4e8164f bellard
                    /* test if the variable refers to a label inside
1789 d4e8164f bellard
                       the code we are generating */
1790 67b915a5 bellard
#ifdef CONFIG_FORMAT_COFF
1791 67b915a5 bellard
                    if (sym->st_shndx == text_shndx) {
1792 67b915a5 bellard
                        ptr = sdata[coff_text_shndx];
1793 67b915a5 bellard
                    } else if (sym->st_shndx == data_shndx) {
1794 67b915a5 bellard
                        ptr = sdata[coff_data_shndx];
1795 67b915a5 bellard
                    } else {
1796 67b915a5 bellard
                        ptr = NULL;
1797 67b915a5 bellard
                    }
1798 82eec0a1 bellard
#elif defined(CONFIG_FORMAT_MACH)
1799 82eec0a1 bellard
                    if(!sym->n_sect)
1800 82eec0a1 bellard
                        continue;
1801 82eec0a1 bellard
                    ptr = sdata[sym->n_sect-1];
1802 67b915a5 bellard
#else
1803 fe319756 bellard
                    ptr = sdata[sym->st_shndx];
1804 67b915a5 bellard
#endif
1805 fe319756 bellard
                    if (!ptr)
1806 fe319756 bellard
                        error("__op_labelN in invalid section");
1807 fe319756 bellard
                    offset = sym->st_value;
1808 82eec0a1 bellard
#ifdef CONFIG_FORMAT_MACH
1809 82eec0a1 bellard
                    offset -= section_hdr[sym->n_sect-1].addr;
1810 82eec0a1 bellard
#endif
1811 7a2d6d96 pbrook
                    val = *(host_ulong *)(ptr + offset);
1812 fe319756 bellard
#ifdef ELF_USES_RELOCA
1813 fe319756 bellard
                    {
1814 fe319756 bellard
                        int reloc_shndx, nb_relocs1, j;
1815 fe319756 bellard
1816 fe319756 bellard
                        /* try to find a matching relocation */
1817 fe319756 bellard
                        reloc_shndx = find_reloc(sym->st_shndx);
1818 fe319756 bellard
                        if (reloc_shndx) {
1819 5fafdf24 ths
                            nb_relocs1 = shdr[reloc_shndx].sh_size /
1820 fe319756 bellard
                                shdr[reloc_shndx].sh_entsize;
1821 fe319756 bellard
                            rel = (ELF_RELOC *)sdata[reloc_shndx];
1822 fe319756 bellard
                            for(j = 0; j < nb_relocs1; j++) {
1823 fe319756 bellard
                                if (rel->r_offset == offset) {
1824 039de852 bellard
                                    val = rel->r_addend;
1825 fe319756 bellard
                                    break;
1826 fe319756 bellard
                                }
1827 fe319756 bellard
                                rel++;
1828 fe319756 bellard
                            }
1829 fe319756 bellard
                        }
1830 fe319756 bellard
                    }
1831 3b46e624 ths
#endif
1832 c4687878 bellard
                    if (val >= start_offset && val <= start_offset + copy_size) {
1833 d4e8164f bellard
                        n = strtol(p, NULL, 10);
1834 3442e896 pbrook
                        fprintf(outfile, "    label_offsets[%d] = %ld + (gen_code_ptr - gen_code_buf);\n", n, (long)(val - start_offset));
1835 d4e8164f bellard
                    }
1836 d4e8164f bellard
                }
1837 d4e8164f bellard
            }
1838 d4e8164f bellard
        }
1839 d4e8164f bellard
1840 85028e4d ths
        /* load parameters in variables */
1841 dc99065b bellard
        for(i = 0; i < nb_args; i++) {
1842 dc99065b bellard
            fprintf(outfile, "    param%d = *opparam_ptr++;\n", i + 1);
1843 dc99065b bellard
        }
1844 dc99065b bellard
1845 dc99065b bellard
        /* patch relocations */
1846 ce11fedc bellard
#if defined(HOST_I386)
1847 dc99065b bellard
            {
1848 4a1a1707 ths
                char relname[256];
1849 dc99065b bellard
                int type;
1850 ce11fedc bellard
                int addend;
1851 3442e896 pbrook
                int reloc_offset;
1852 dc99065b bellard
                for(i = 0, rel = relocs;i < nb_relocs; i++, rel++) {
1853 ae228531 bellard
                if (rel->r_offset >= start_offset &&
1854 ae228531 bellard
                    rel->r_offset < start_offset + copy_size) {
1855 67b915a5 bellard
                    sym_name = get_rel_sym_name(rel);
1856 b48a8bb6 bellard
                    if (!sym_name)
1857 b48a8bb6 bellard
                        continue;
1858 3442e896 pbrook
                    reloc_offset = rel->r_offset - start_offset;
1859 ecd854fd bellard
                    if (strstart(sym_name, "__op_jmp", &p)) {
1860 ecd854fd bellard
                        int n;
1861 ecd854fd bellard
                        n = strtol(p, NULL, 10);
1862 ecd854fd bellard
                        /* __op_jmp relocations are done at
1863 ecd854fd bellard
                           runtime to do translated block
1864 ecd854fd bellard
                           chaining: the offset of the instruction
1865 ecd854fd bellard
                           needs to be stored */
1866 ecd854fd bellard
                        fprintf(outfile, "    jmp_offsets[%d] = %d + (gen_code_ptr - gen_code_buf);\n",
1867 3442e896 pbrook
                                n, reloc_offset);
1868 ecd854fd bellard
                        continue;
1869 ecd854fd bellard
                    }
1870 3442e896 pbrook
1871 4a1a1707 ths
                    get_reloc_expr(relname, sizeof(relname), sym_name);
1872 367e86e8 bellard
                    addend = get32((uint32_t *)(text + rel->r_offset));
1873 67b915a5 bellard
#ifdef CONFIG_FORMAT_ELF
1874 67b915a5 bellard
                    type = ELF32_R_TYPE(rel->r_info);
1875 367e86e8 bellard
                    switch(type) {
1876 367e86e8 bellard
                    case R_386_32:
1877 5fafdf24 ths
                        fprintf(outfile, "    *(uint32_t *)(gen_code_ptr + %d) = %s + %d;\n",
1878 4a1a1707 ths
                                reloc_offset, relname, addend);
1879 367e86e8 bellard
                        break;
1880 367e86e8 bellard
                    case R_386_PC32:
1881 5fafdf24 ths
                        fprintf(outfile, "    *(uint32_t *)(gen_code_ptr + %d) = %s - (long)(gen_code_ptr + %d) + %d;\n",
1882 4a1a1707 ths
                                reloc_offset, relname, reloc_offset, addend);
1883 367e86e8 bellard
                        break;
1884 367e86e8 bellard
                    default:
1885 367e86e8 bellard
                        error("unsupported i386 relocation (%d)", type);
1886 367e86e8 bellard
                    }
1887 67b915a5 bellard
#elif defined(CONFIG_FORMAT_COFF)
1888 40c3bac3 bellard
                    {
1889 40c3bac3 bellard
                        char *temp_name;
1890 40c3bac3 bellard
                        int j;
1891 40c3bac3 bellard
                        EXE_SYM *sym;
1892 40c3bac3 bellard
                        temp_name = get_sym_name(symtab + *(uint32_t *)(rel->r_reloc->r_symndx));
1893 40c3bac3 bellard
                        if (!strcmp(temp_name, ".data")) {
1894 40c3bac3 bellard
                            for (j = 0, sym = symtab; j < nb_syms; j++, sym++) {
1895 40c3bac3 bellard
                                if (strstart(sym->st_name, sym_name, NULL)) {
1896 40c3bac3 bellard
                                    addend -= sym->st_value;
1897 40c3bac3 bellard
                                }
1898 40c3bac3 bellard
                            }
1899 40c3bac3 bellard
                        }
1900 40c3bac3 bellard
                    }
1901 67b915a5 bellard
                    type = rel->r_type;
1902 67b915a5 bellard
                    switch(type) {
1903 67b915a5 bellard
                    case DIR32:
1904 5fafdf24 ths
                        fprintf(outfile, "    *(uint32_t *)(gen_code_ptr + %d) = %s + %d;\n",
1905 4a1a1707 ths
                                reloc_offset, relname, addend);
1906 67b915a5 bellard
                        break;
1907 67b915a5 bellard
                    case DISP32:
1908 5fafdf24 ths
                        fprintf(outfile, "    *(uint32_t *)(gen_code_ptr + %d) = %s - (long)(gen_code_ptr + %d) + %d -4;\n",
1909 4a1a1707 ths
                                reloc_offset, relname, reloc_offset, addend);
1910 67b915a5 bellard
                        break;
1911 67b915a5 bellard
                    default:
1912 67b915a5 bellard
                        error("unsupported i386 relocation (%d)", type);
1913 67b915a5 bellard
                    }
1914 67b915a5 bellard
#else
1915 67b915a5 bellard
#error unsupport object format
1916 67b915a5 bellard
#endif
1917 367e86e8 bellard
                }
1918 dc99065b bellard
                }
1919 dc99065b bellard
            }
1920 c4687878 bellard
#elif defined(HOST_X86_64)
1921 bc51c5c9 bellard
            {
1922 4a1a1707 ths
                char relname[256];
1923 bc51c5c9 bellard
                int type;
1924 bc51c5c9 bellard
                int addend;
1925 3442e896 pbrook
                int reloc_offset;
1926 bc51c5c9 bellard
                for(i = 0, rel = relocs;i < nb_relocs; i++, rel++) {
1927 bc51c5c9 bellard
                if (rel->r_offset >= start_offset &&
1928 bc51c5c9 bellard
                    rel->r_offset < start_offset + copy_size) {
1929 bc51c5c9 bellard
                    sym_name = strtab + symtab[ELFW(R_SYM)(rel->r_info)].st_name;
1930 4a1a1707 ths
                    get_reloc_expr(relname, sizeof(relname), sym_name);
1931 bc51c5c9 bellard
                    type = ELF32_R_TYPE(rel->r_info);
1932 bc51c5c9 bellard
                    addend = rel->r_addend;
1933 3442e896 pbrook
                    reloc_offset = rel->r_offset - start_offset;
1934 bc51c5c9 bellard
                    switch(type) {
1935 bc51c5c9 bellard
                    case R_X86_64_32:
1936 5fafdf24 ths
                        fprintf(outfile, "    *(uint32_t *)(gen_code_ptr + %d) = (uint32_t)%s + %d;\n",
1937 4a1a1707 ths
                                reloc_offset, relname, addend);
1938 bc51c5c9 bellard
                        break;
1939 bc51c5c9 bellard
                    case R_X86_64_32S:
1940 5fafdf24 ths
                        fprintf(outfile, "    *(uint32_t *)(gen_code_ptr + %d) = (int32_t)%s + %d;\n",
1941 4a1a1707 ths
                                reloc_offset, relname, addend);
1942 bc51c5c9 bellard
                        break;
1943 bc51c5c9 bellard
                    case R_X86_64_PC32:
1944 5fafdf24 ths
                        fprintf(outfile, "    *(uint32_t *)(gen_code_ptr + %d) = %s - (long)(gen_code_ptr + %d) + %d;\n",
1945 4a1a1707 ths
                                reloc_offset, relname, reloc_offset, addend);
1946 bc51c5c9 bellard
                        break;
1947 bc51c5c9 bellard
                    default:
1948 c4687878 bellard
                        error("unsupported X86_64 relocation (%d)", type);
1949 bc51c5c9 bellard
                    }
1950 bc51c5c9 bellard
                }
1951 bc51c5c9 bellard
                }
1952 bc51c5c9 bellard
            }
1953 ce11fedc bellard
#elif defined(HOST_PPC)
1954 04369ff2 bellard
            {
1955 82eec0a1 bellard
#ifdef CONFIG_FORMAT_ELF
1956 4a1a1707 ths
                char relname[256];
1957 04369ff2 bellard
                int type;
1958 ce11fedc bellard
                int addend;
1959 3442e896 pbrook
                int reloc_offset;
1960 04369ff2 bellard
                for(i = 0, rel = relocs;i < nb_relocs; i++, rel++) {
1961 ae228531 bellard
                    if (rel->r_offset >= start_offset &&
1962 ae228531 bellard
                        rel->r_offset < start_offset + copy_size) {
1963 efdea7bf bellard
                        sym_name = strtab + symtab[ELFW(R_SYM)(rel->r_info)].st_name;
1964 3442e896 pbrook
                        reloc_offset = rel->r_offset - start_offset;
1965 d4e8164f bellard
                        if (strstart(sym_name, "__op_jmp", &p)) {
1966 d4e8164f bellard
                            int n;
1967 d4e8164f bellard
                            n = strtol(p, NULL, 10);
1968 d4e8164f bellard
                            /* __op_jmp relocations are done at
1969 d4e8164f bellard
                               runtime to do translated block
1970 d4e8164f bellard
                               chaining: the offset of the instruction
1971 d4e8164f bellard
                               needs to be stored */
1972 d4e8164f bellard
                            fprintf(outfile, "    jmp_offsets[%d] = %d + (gen_code_ptr - gen_code_buf);\n",
1973 3442e896 pbrook
                                    n, reloc_offset);
1974 d4e8164f bellard
                            continue;
1975 d4e8164f bellard
                        }
1976 3b46e624 ths
1977 4a1a1707 ths
                        get_reloc_expr(relname, sizeof(relname), sym_name);
1978 04369ff2 bellard
                        type = ELF32_R_TYPE(rel->r_info);
1979 04369ff2 bellard
                        addend = rel->r_addend;
1980 04369ff2 bellard
                        switch(type) {
1981 04369ff2 bellard
                        case R_PPC_ADDR32:
1982 5fafdf24 ths
                            fprintf(outfile, "    *(uint32_t *)(gen_code_ptr + %d) = %s + %d;\n",
1983 4a1a1707 ths
                                    reloc_offset, relname, addend);
1984 04369ff2 bellard
                            break;
1985 04369ff2 bellard
                        case R_PPC_ADDR16_LO:
1986 5fafdf24 ths
                            fprintf(outfile, "    *(uint16_t *)(gen_code_ptr + %d) = (%s + %d);\n",
1987 4a1a1707 ths
                                    reloc_offset, relname, addend);
1988 04369ff2 bellard
                            break;
1989 04369ff2 bellard
                        case R_PPC_ADDR16_HI:
1990 5fafdf24 ths
                            fprintf(outfile, "    *(uint16_t *)(gen_code_ptr + %d) = (%s + %d) >> 16;\n",
1991 4a1a1707 ths
                                    reloc_offset, relname, addend);
1992 04369ff2 bellard
                            break;
1993 04369ff2 bellard
                        case R_PPC_ADDR16_HA:
1994 5fafdf24 ths
                            fprintf(outfile, "    *(uint16_t *)(gen_code_ptr + %d) = (%s + %d + 0x8000) >> 16;\n",
1995 4a1a1707 ths
                                    reloc_offset, relname, addend);
1996 04369ff2 bellard
                            break;
1997 04369ff2 bellard
                        case R_PPC_REL24:
1998 04369ff2 bellard
                            /* warning: must be at 32 MB distancy */
1999 5fafdf24 ths
                            fprintf(outfile, "    *(uint32_t *)(gen_code_ptr + %d) = (*(uint32_t *)(gen_code_ptr + %d) & ~0x03fffffc) | ((%s - (long)(gen_code_ptr + %d) + %d) & 0x03fffffc);\n",
2000 4a1a1707 ths
                                    reloc_offset, reloc_offset, relname, reloc_offset, addend);
2001 04369ff2 bellard
                            break;
2002 04369ff2 bellard
                        default:
2003 04369ff2 bellard
                            error("unsupported powerpc relocation (%d)", type);
2004 04369ff2 bellard
                        }
2005 04369ff2 bellard
                    }
2006 04369ff2 bellard
                }
2007 82eec0a1 bellard
#elif defined(CONFIG_FORMAT_MACH)
2008 a029baa4 ths
                struct scattered_relocation_info *scarel;
2009 a029baa4 ths
                struct relocation_info * rel;
2010 a029baa4 ths
                char final_sym_name[256];
2011 a029baa4 ths
                const char *sym_name;
2012 a029baa4 ths
                const char *p;
2013 a029baa4 ths
                int slide, sslide;
2014 a029baa4 ths
                int i;
2015 a029baa4 ths
2016 a029baa4 ths
                for(i = 0, rel = relocs; i < nb_relocs; i++, rel++) {
2017 a029baa4 ths
                    unsigned int offset, length, value = 0;
2018 a029baa4 ths
                    unsigned int type, pcrel, isym = 0;
2019 a029baa4 ths
                    unsigned int usesym = 0;
2020 a029baa4 ths
2021 a029baa4 ths
                    if(R_SCATTERED & rel->r_address) {
2022 a029baa4 ths
                        scarel = (struct scattered_relocation_info*)rel;
2023 a029baa4 ths
                        offset = (unsigned int)scarel->r_address;
2024 a029baa4 ths
                        length = scarel->r_length;
2025 a029baa4 ths
                        pcrel = scarel->r_pcrel;
2026 a029baa4 ths
                        type = scarel->r_type;
2027 a029baa4 ths
                        value = scarel->r_value;
2028 a029baa4 ths
                    } else {
2029 a029baa4 ths
                        value = isym = rel->r_symbolnum;
2030 a029baa4 ths
                        usesym = (rel->r_extern);
2031 a029baa4 ths
                        offset = rel->r_address;
2032 a029baa4 ths
                        length = rel->r_length;
2033 a029baa4 ths
                        pcrel = rel->r_pcrel;
2034 a029baa4 ths
                        type = rel->r_type;
2035 a029baa4 ths
                    }
2036 a029baa4 ths
2037 a029baa4 ths
                    slide = offset - start_offset;
2038 a029baa4 ths
2039 5fafdf24 ths
                    if (!(offset >= start_offset && offset < start_offset + size))
2040 a029baa4 ths
                        continue;  /* not in our range */
2041 a029baa4 ths
2042 a029baa4 ths
                        sym_name = get_reloc_name(rel, &sslide);
2043 a029baa4 ths
2044 a029baa4 ths
                        if(usesym && symtab[isym].n_type & N_STAB)
2045 a029baa4 ths
                            continue; /* don't handle STAB (debug sym) */
2046 a029baa4 ths
2047 a029baa4 ths
                        if (sym_name && strstart(sym_name, "__op_jmp", &p)) {
2048 a029baa4 ths
                            int n;
2049 a029baa4 ths
                            n = strtol(p, NULL, 10);
2050 a029baa4 ths
                            fprintf(outfile, "    jmp_offsets[%d] = %d + (gen_code_ptr - gen_code_buf);\n",
2051 a029baa4 ths
                                    n, slide);
2052 a029baa4 ths
                            continue; /* Nothing more to do */
2053 a029baa4 ths
                        }
2054 a029baa4 ths
2055 a029baa4 ths
                        if(!sym_name) {
2056 a029baa4 ths
                            fprintf(outfile, "/* #warning relocation not handled in %s (value 0x%x, %s, offset 0x%x, length 0x%x, %s, type 0x%x) */\n",
2057 a029baa4 ths
                                    name, value, usesym ? "use sym" : "don't use sym", offset, length, pcrel ? "pcrel":"", type);
2058 a029baa4 ths
                            continue; /* dunno how to handle without final_sym_name */
2059 a029baa4 ths
                        }
2060 a029baa4 ths
2061 5fafdf24 ths
                        get_reloc_expr(final_sym_name, sizeof(final_sym_name),
2062 a029baa4 ths
                                       sym_name);
2063 a029baa4 ths
                        switch(type) {
2064 a029baa4 ths
                        case PPC_RELOC_BR24:
2065 a029baa4 ths
                            if (!strstart(sym_name,"__op_gen_label",&p)) {
2066 a029baa4 ths
                                fprintf(outfile, "{\n");
2067 a029baa4 ths
                                fprintf(outfile, "    uint32_t imm = *(uint32_t *)(gen_code_ptr + %d) & 0x3fffffc;\n", slide);
2068 a029baa4 ths
                                fprintf(outfile, "    *(uint32_t *)(gen_code_ptr + %d) = (*(uint32_t *)(gen_code_ptr + %d) & ~0x03fffffc) | ((imm + ((long)%s - (long)gen_code_ptr) + %d) & 0x03fffffc);\n",
2069 a029baa4 ths
                                        slide, slide, name, sslide);
2070 a029baa4 ths
                                fprintf(outfile, "}\n");
2071 a029baa4 ths
                            } else {
2072 a029baa4 ths
                                fprintf(outfile, "    *(uint32_t *)(gen_code_ptr + %d) = (*(uint32_t *)(gen_code_ptr + %d) & ~0x03fffffc) | (((long)%s - (long)gen_code_ptr - %d) & 0x03fffffc);\n",
2073 a029baa4 ths
                                        slide, slide, final_sym_name, slide);
2074 a029baa4 ths
                            }
2075 82eec0a1 bellard
                            break;
2076 a029baa4 ths
                        case PPC_RELOC_HI16:
2077 5fafdf24 ths
                            fprintf(outfile, "    *(uint16_t *)(gen_code_ptr + %d + 2) = (%s + %d) >> 16;\n",
2078 a029baa4 ths
                                    slide, final_sym_name, sslide);
2079 a029baa4 ths
                            break;
2080 a029baa4 ths
                        case PPC_RELOC_LO16:
2081 5fafdf24 ths
                            fprintf(outfile, "    *(uint16_t *)(gen_code_ptr + %d + 2) = (%s + %d);\n",
2082 a029baa4 ths
                                    slide, final_sym_name, sslide);
2083 a029baa4 ths
                            break;
2084 a029baa4 ths
                        case PPC_RELOC_HA16:
2085 5fafdf24 ths
                            fprintf(outfile, "    *(uint16_t *)(gen_code_ptr + %d + 2) = (%s + %d + 0x8000) >> 16;\n",
2086 a029baa4 ths
                                    slide, final_sym_name, sslide);
2087 a029baa4 ths
                            break;
2088 a029baa4 ths
                        default:
2089 a029baa4 ths
                            error("unsupported powerpc relocation (%d)", type);
2090 a029baa4 ths
                    }
2091 a029baa4 ths
                }
2092 82eec0a1 bellard
#else
2093 82eec0a1 bellard
#error unsupport object format
2094 82eec0a1 bellard
#endif
2095 04369ff2 bellard
            }
2096 ce11fedc bellard
#elif defined(HOST_S390)
2097 fb3e5849 bellard
            {
2098 4a1a1707 ths
                char relname[256];
2099 fb3e5849 bellard
                int type;
2100 ce11fedc bellard
                int addend;
2101 3442e896 pbrook
                int reloc_offset;
2102 fb3e5849 bellard
                for(i = 0, rel = relocs;i < nb_relocs; i++, rel++) {
2103 ae228531 bellard
                    if (rel->r_offset >= start_offset &&
2104 ae228531 bellard
                        rel->r_offset < start_offset + copy_size) {
2105 efdea7bf bellard
                        sym_name = strtab + symtab[ELFW(R_SYM)(rel->r_info)].st_name;
2106 4a1a1707 ths
                        get_reloc_expr(relname, sizeof(relname), sym_name);
2107 fb3e5849 bellard
                        type = ELF32_R_TYPE(rel->r_info);
2108 fb3e5849 bellard
                        addend = rel->r_addend;
2109 3442e896 pbrook
                        reloc_offset = rel->r_offset - start_offset;
2110 fb3e5849 bellard
                        switch(type) {
2111 fb3e5849 bellard
                        case R_390_32:
2112 5fafdf24 ths
                            fprintf(outfile, "    *(uint32_t *)(gen_code_ptr + %d) = %s + %d;\n",
2113 4a1a1707 ths
                                    reloc_offset, relname, addend);
2114 fb3e5849 bellard
                            break;
2115 fb3e5849 bellard
                        case R_390_16:
2116 5fafdf24 ths
                            fprintf(outfile, "    *(uint16_t *)(gen_code_ptr + %d) = %s + %d;\n",
2117 4a1a1707 ths
                                    reloc_offset, relname, addend);
2118 fb3e5849 bellard
                            break;
2119 fb3e5849 bellard
                        case R_390_8:
2120 5fafdf24 ths
                            fprintf(outfile, "    *(uint8_t *)(gen_code_ptr + %d) = %s + %d;\n",
2121 4a1a1707 ths
                                    reloc_offset, relname, addend);
2122 fb3e5849 bellard
                            break;
2123 76d83bde ths
                        case R_390_PC32DBL:
2124 76d83bde ths
                            if (ELF32_ST_TYPE(symtab[ELFW(R_SYM)(rel->r_info)].st_info) == STT_SECTION) {
2125 76d83bde ths
                                fprintf(outfile,
2126 76d83bde ths
                                        "    *(uint32_t *)(gen_code_ptr + %d) += "
2127 76d83bde ths
                                        "((long)&%s - (long)gen_code_ptr) >> 1;\n",
2128 76d83bde ths
                                        reloc_offset, name);
2129 76d83bde ths
                            }
2130 76d83bde ths
                            else
2131 76d83bde ths
                                fprintf(outfile,
2132 76d83bde ths
                                        "    *(uint32_t *)(gen_code_ptr + %d) = "
2133 76d83bde ths
                                        "(%s + %d - ((uint32_t)gen_code_ptr + %d)) >> 1;\n",
2134 76d83bde ths
                                        reloc_offset, relname, addend, reloc_offset);
2135 76d83bde ths
                            break;
2136 fb3e5849 bellard
                        default:
2137 fb3e5849 bellard
                            error("unsupported s390 relocation (%d)", type);
2138 fb3e5849 bellard
                        }
2139 fb3e5849 bellard
                    }
2140 fb3e5849 bellard
                }
2141 fb3e5849 bellard
            }
2142 efdea7bf bellard
#elif defined(HOST_ALPHA)
2143 efdea7bf bellard
            {
2144 efdea7bf bellard
                for (i = 0, rel = relocs; i < nb_relocs; i++, rel++) {
2145 ae228531 bellard
                    if (rel->r_offset >= start_offset && rel->r_offset < start_offset + copy_size) {
2146 efdea7bf bellard
                        int type;
2147 3442e896 pbrook
                        long reloc_offset;
2148 74c95119 bellard
2149 efdea7bf bellard
                        type = ELF64_R_TYPE(rel->r_info);
2150 74c95119 bellard
                        sym_name = strtab + symtab[ELF64_R_SYM(rel->r_info)].st_name;
2151 3442e896 pbrook
                        reloc_offset = rel->r_offset - start_offset;
2152 efdea7bf bellard
                        switch (type) {
2153 efdea7bf bellard
                        case R_ALPHA_GPDISP:
2154 74c95119 bellard
                            /* The gp is just 32 bit, and never changes, so it's easiest to emit it
2155 74c95119 bellard
                               as an immediate instead of constructing it from the pv or ra.  */
2156 74c95119 bellard
                            fprintf(outfile, "    immediate_ldah(gen_code_ptr + %ld, gp);\n",
2157 3442e896 pbrook
                                    reloc_offset);
2158 74c95119 bellard
                            fprintf(outfile, "    immediate_lda(gen_code_ptr + %ld, gp);\n",
2159 3442e896 pbrook
                                    reloc_offset + (int)rel->r_addend);
2160 efdea7bf bellard
                            break;
2161 efdea7bf bellard
                        case R_ALPHA_LITUSE:
2162 efdea7bf bellard
                            /* jsr to literal hint. Could be used to optimize to bsr. Ignore for
2163 efdea7bf bellard
                               now, since some called functions (libc) need pv to be set up.  */
2164 efdea7bf bellard
                            break;
2165 efdea7bf bellard
                        case R_ALPHA_HINT:
2166 efdea7bf bellard
                            /* Branch target prediction hint. Ignore for now.  Should be already
2167 efdea7bf bellard
                               correct for in-function jumps.  */
2168 efdea7bf bellard
                            break;
2169 efdea7bf bellard
                        case R_ALPHA_LITERAL:
2170 74c95119 bellard
                            /* Load a literal from the GOT relative to the gp.  Since there's only a
2171 74c95119 bellard
                               single gp, nothing is to be done.  */
2172 74c95119 bellard
                            break;
2173 74c95119 bellard
                        case R_ALPHA_GPRELHIGH:
2174 74c95119 bellard
                            /* Handle fake relocations against __op_param symbol.  Need to emit the
2175 74c95119 bellard
                               high part of the immediate value instead.  Other symbols need no
2176 74c95119 bellard
                               special treatment.  */
2177 74c95119 bellard
                            if (strstart(sym_name, "__op_param", &p))
2178 74c95119 bellard
                                fprintf(outfile, "    immediate_ldah(gen_code_ptr + %ld, param%s);\n",
2179 3442e896 pbrook
                                        reloc_offset, p);
2180 74c95119 bellard
                            break;
2181 74c95119 bellard
                        case R_ALPHA_GPRELLOW:
2182 74c95119 bellard
                            if (strstart(sym_name, "__op_param", &p))
2183 74c95119 bellard
                                fprintf(outfile, "    immediate_lda(gen_code_ptr + %ld, param%s);\n",
2184 3442e896 pbrook
                                        reloc_offset, p);
2185 74c95119 bellard
                            break;
2186 74c95119 bellard
                        case R_ALPHA_BRSGP:
2187 74c95119 bellard
                            /* PC-relative jump. Tweak offset to skip the two instructions that try to
2188 74c95119 bellard
                               set up the gp from the pv.  */
2189 2f87c607 bellard
                            fprintf(outfile, "    fix_bsr(gen_code_ptr + %ld, (uint8_t *) &%s - (gen_code_ptr + %ld + 4) + 8);\n",
2190 3442e896 pbrook
                                    reloc_offset, sym_name, reloc_offset);
2191 efdea7bf bellard
                            break;
2192 efdea7bf bellard
                        default:
2193 efdea7bf bellard
                            error("unsupported Alpha relocation (%d)", type);
2194 efdea7bf bellard
                        }
2195 efdea7bf bellard
                    }
2196 efdea7bf bellard
                }
2197 efdea7bf bellard
            }
2198 efdea7bf bellard
#elif defined(HOST_IA64)
2199 efdea7bf bellard
            {
2200 b8076a74 bellard
                unsigned long sym_idx;
2201 b8076a74 bellard
                long code_offset;
2202 4a1a1707 ths
                char relname[256];
2203 efdea7bf bellard
                int type;
2204 b8076a74 bellard
                long addend;
2205 b8076a74 bellard
2206 efdea7bf bellard
                for(i = 0, rel = relocs;i < nb_relocs; i++, rel++) {
2207 b8076a74 bellard
                    sym_idx = ELF64_R_SYM(rel->r_info);
2208 b8076a74 bellard
                    if (rel->r_offset < start_offset
2209 b8076a74 bellard
                        || rel->r_offset >= start_offset + copy_size)
2210 b8076a74 bellard
                        continue;
2211 b8076a74 bellard
                    sym_name = (strtab + symtab[sym_idx].st_name);
2212 3442e896 pbrook
                    code_offset = rel->r_offset - start_offset;
2213 b8076a74 bellard
                    if (strstart(sym_name, "__op_jmp", &p)) {
2214 b8076a74 bellard
                        int n;
2215 b8076a74 bellard
                        n = strtol(p, NULL, 10);
2216 b8076a74 bellard
                        /* __op_jmp relocations are done at
2217 b8076a74 bellard
                           runtime to do translated block
2218 b8076a74 bellard
                           chaining: the offset of the instruction
2219 b8076a74 bellard
                           needs to be stored */
2220 b8076a74 bellard
                        fprintf(outfile, "    jmp_offsets[%d] ="
2221 b8076a74 bellard
                                "%ld + (gen_code_ptr - gen_code_buf);\n",
2222 3442e896 pbrook
                                n, code_offset);
2223 b8076a74 bellard
                        continue;
2224 b8076a74 bellard
                    }
2225 4a1a1707 ths
                    get_reloc_expr(relname, sizeof(relname), sym_name);
2226 b8076a74 bellard
                    type = ELF64_R_TYPE(rel->r_info);
2227 b8076a74 bellard
                    addend = rel->r_addend;
2228 b8076a74 bellard
                    switch(type) {
2229 b8076a74 bellard
                      case R_IA64_IMM64:
2230 b8076a74 bellard
                          fprintf(outfile,
2231 b8076a74 bellard
                                  "    ia64_imm64(gen_code_ptr + %ld, "
2232 b8076a74 bellard
                                  "%s + %ld);\n",
2233 4a1a1707 ths
                                  code_offset, relname, addend);
2234 b8076a74 bellard
                          break;
2235 b8076a74 bellard
                      case R_IA64_LTOFF22X:
2236 b8076a74 bellard
                      case R_IA64_LTOFF22:
2237 b8076a74 bellard
                          fprintf(outfile, "    IA64_LTOFF(gen_code_ptr + %ld,"
2238 b8076a74 bellard
                                  " %s + %ld, %d);\n",
2239 4a1a1707 ths
                                  code_offset, relname, addend,
2240 b8076a74 bellard
                                  (type == R_IA64_LTOFF22X));
2241 b8076a74 bellard
                          break;
2242 b8076a74 bellard
                      case R_IA64_LDXMOV:
2243 b8076a74 bellard
                          fprintf(outfile,
2244 b8076a74 bellard
                                  "    ia64_ldxmov(gen_code_ptr + %ld,"
2245 4a1a1707 ths
                                  " %s + %ld);\n", code_offset, relname, addend);
2246 b8076a74 bellard
                          break;
2247 b8076a74 bellard
2248 b8076a74 bellard
                      case R_IA64_PCREL21B:
2249 b8076a74 bellard
                          if (strstart(sym_name, "__op_gen_label", NULL)) {
2250 b8076a74 bellard
                              fprintf(outfile,
2251 b8076a74 bellard
                                      "    ia64_imm21b(gen_code_ptr + %ld,"
2252 b8076a74 bellard
                                      " (long) (%s + %ld -\n\t\t"
2253 b8076a74 bellard
                                      "((long) gen_code_ptr + %ld)) >> 4);\n",
2254 4a1a1707 ths
                                      code_offset, relname, addend,
2255 b8076a74 bellard
                                      code_offset & ~0xfUL);
2256 b8076a74 bellard
                          } else {
2257 b8076a74 bellard
                              fprintf(outfile,
2258 b8076a74 bellard
                                      "    IA64_PLT(gen_code_ptr + %ld, "
2259 b8076a74 bellard
                                      "%d);\t/* %s + %ld */\n",
2260 b8076a74 bellard
                                      code_offset,
2261 b8076a74 bellard
                                      get_plt_index(sym_name, addend),
2262 b8076a74 bellard
                                      sym_name, addend);
2263 b8076a74 bellard
                          }
2264 b8076a74 bellard
                          break;
2265 b8076a74 bellard
                      default:
2266 b8076a74 bellard
                          error("unsupported ia64 relocation (0x%x)",
2267 b8076a74 bellard
                                type);
2268 b8076a74 bellard
                    }
2269 efdea7bf bellard
                }
2270 b8076a74 bellard
                fprintf(outfile, "    ia64_nop_b(gen_code_ptr + %d);\n",
2271 b8076a74 bellard
                        copy_size - 16 + 2);
2272 efdea7bf bellard
            }
2273 d014c98c bellard
#elif defined(HOST_SPARC)
2274 d014c98c bellard
            {
2275 4a1a1707 ths
                char relname[256];
2276 d014c98c bellard
                int type;
2277 d014c98c bellard
                int addend;
2278 3442e896 pbrook
                int reloc_offset;
2279 d014c98c bellard
                for(i = 0, rel = relocs;i < nb_relocs; i++, rel++) {
2280 ae228531 bellard
                    if (rel->r_offset >= start_offset &&
2281 ae228531 bellard
                        rel->r_offset < start_offset + copy_size) {
2282 d014c98c bellard
                        sym_name = strtab + symtab[ELF32_R_SYM(rel->r_info)].st_name;
2283 4a1a1707 ths
                        get_reloc_expr(relname, sizeof(relname), sym_name);
2284 d014c98c bellard
                        type = ELF32_R_TYPE(rel->r_info);
2285 d014c98c bellard
                        addend = rel->r_addend;
2286 3442e896 pbrook
                        reloc_offset = rel->r_offset - start_offset;
2287 d014c98c bellard
                        switch(type) {
2288 d014c98c bellard
                        case R_SPARC_32:
2289 5fafdf24 ths
                            fprintf(outfile, "    *(uint32_t *)(gen_code_ptr + %d) = %s + %d;\n",
2290 4a1a1707 ths
                                    reloc_offset, relname, addend);
2291 d014c98c bellard
                            break;
2292 d014c98c bellard
                        case R_SPARC_HI22:
2293 d014c98c bellard
                            fprintf(outfile,
2294 d014c98c bellard
                                    "    *(uint32_t *)(gen_code_ptr + %d) = "
2295 d014c98c bellard
                                    "((*(uint32_t *)(gen_code_ptr + %d)) "
2296 d014c98c bellard
                                    " & ~0x3fffff) "
2297 ae228531 bellard
                                    " | (((%s + %d) >> 10) & 0x3fffff);\n",
2298 4a1a1707 ths
                                    reloc_offset, reloc_offset, relname, addend);
2299 d014c98c bellard
                            break;
2300 d014c98c bellard
                        case R_SPARC_LO10:
2301 d014c98c bellard
                            fprintf(outfile,
2302 d014c98c bellard
                                    "    *(uint32_t *)(gen_code_ptr + %d) = "
2303 d014c98c bellard
                                    "((*(uint32_t *)(gen_code_ptr + %d)) "
2304 d014c98c bellard
                                    " & ~0x3ff) "
2305 d014c98c bellard
                                    " | ((%s + %d) & 0x3ff);\n",
2306 4a1a1707 ths
                                    reloc_offset, reloc_offset, relname, addend);
2307 d014c98c bellard
                            break;
2308 d014c98c bellard
                        case R_SPARC_WDISP30:
2309 d014c98c bellard
                            fprintf(outfile,
2310 d014c98c bellard
                                    "    *(uint32_t *)(gen_code_ptr + %d) = "
2311 d014c98c bellard
                                    "((*(uint32_t *)(gen_code_ptr + %d)) "
2312 d014c98c bellard
                                    " & ~0x3fffffff) "
2313 ae228531 bellard
                                    " | ((((%s + %d) - (long)(gen_code_ptr + %d))>>2) "
2314 d014c98c bellard
                                    "    & 0x3fffffff);\n",
2315 4a1a1707 ths
                                    reloc_offset, reloc_offset, relname, addend,
2316 3442e896 pbrook
                                    reloc_offset);
2317 d014c98c bellard
                            break;
2318 fdbb4691 bellard
                        case R_SPARC_WDISP22:
2319 fdbb4691 bellard
                            fprintf(outfile,
2320 fdbb4691 bellard
                                    "    *(uint32_t *)(gen_code_ptr + %d) = "
2321 fdbb4691 bellard
                                    "((*(uint32_t *)(gen_code_ptr + %d)) "
2322 fdbb4691 bellard
                                    " & ~0x3fffff) "
2323 fdbb4691 bellard
                                    " | ((((%s + %d) - (long)(gen_code_ptr + %d))>>2) "
2324 fdbb4691 bellard
                                    "    & 0x3fffff);\n",
2325 fdbb4691 bellard
                                    rel->r_offset - start_offset,
2326 fdbb4691 bellard
                                    rel->r_offset - start_offset,
2327 4a1a1707 ths
                                    relname, addend,
2328 fdbb4691 bellard
                                    rel->r_offset - start_offset);
2329 fdbb4691 bellard
                            break;
2330 d014c98c bellard
                        default:
2331 d014c98c bellard
                            error("unsupported sparc relocation (%d)", type);
2332 d014c98c bellard
                        }
2333 d014c98c bellard
                    }
2334 d014c98c bellard
                }
2335 d014c98c bellard
            }
2336 d014c98c bellard
#elif defined(HOST_SPARC64)
2337 d014c98c bellard
            {
2338 4a1a1707 ths
                char relname[256];
2339 d014c98c bellard
                int type;
2340 d014c98c bellard
                int addend;
2341 3442e896 pbrook
                int reloc_offset;
2342 d014c98c bellard
                for(i = 0, rel = relocs;i < nb_relocs; i++, rel++) {
2343 ae228531 bellard
                    if (rel->r_offset >= start_offset &&
2344 ae228531 bellard
                        rel->r_offset < start_offset + copy_size) {
2345 d014c98c bellard
                        sym_name = strtab + symtab[ELF64_R_SYM(rel->r_info)].st_name;
2346 4a1a1707 ths
                        get_reloc_expr(relname, sizeof(relname), sym_name);
2347 74ccb34e bellard
                        type = ELF32_R_TYPE(rel->r_info);
2348 d014c98c bellard
                        addend = rel->r_addend;
2349 3442e896 pbrook
                        reloc_offset = rel->r_offset - start_offset;
2350 d014c98c bellard
                        switch(type) {
2351 d014c98c bellard
                        case R_SPARC_32:
2352 d014c98c bellard
                            fprintf(outfile, "    *(uint32_t *)(gen_code_ptr + %d) = %s + %d;\n",
2353 4a1a1707 ths
                                    reloc_offset, relname, addend);
2354 d014c98c bellard
                            break;
2355 d014c98c bellard
                        case R_SPARC_HI22:
2356 d014c98c bellard
                            fprintf(outfile,
2357 d014c98c bellard
                                    "    *(uint32_t *)(gen_code_ptr + %d) = "
2358 d014c98c bellard
                                    "((*(uint32_t *)(gen_code_ptr + %d)) "
2359 d014c98c bellard
                                    " & ~0x3fffff) "
2360 ae228531 bellard
                                    " | (((%s + %d) >> 10) & 0x3fffff);\n",
2361 4a1a1707 ths
                                    reloc_offset, reloc_offset, relname, addend);
2362 d014c98c bellard
                            break;
2363 d014c98c bellard
                        case R_SPARC_LO10:
2364 d014c98c bellard
                            fprintf(outfile,
2365 d014c98c bellard
                                    "    *(uint32_t *)(gen_code_ptr + %d) = "
2366 d014c98c bellard
                                    "((*(uint32_t *)(gen_code_ptr + %d)) "
2367 d014c98c bellard
                                    " & ~0x3ff) "
2368 d014c98c bellard
                                    " | ((%s + %d) & 0x3ff);\n",
2369 4a1a1707 ths
                                    reloc_offset, reloc_offset, relname, addend);
2370 d014c98c bellard
                            break;
2371 74ccb34e bellard
                        case R_SPARC_OLO10:
2372 74ccb34e bellard
                            addend += ELF64_R_TYPE_DATA (rel->r_info);
2373 74ccb34e bellard
                            fprintf(outfile,
2374 74ccb34e bellard
                                    "    *(uint32_t *)(gen_code_ptr + %d) = "
2375 74ccb34e bellard
                                    "((*(uint32_t *)(gen_code_ptr + %d)) "
2376 74ccb34e bellard
                                    " & ~0x3ff) "
2377 74ccb34e bellard
                                    " | ((%s + %d) & 0x3ff);\n",
2378 4a1a1707 ths
                                    reloc_offset, reloc_offset, relname, addend);
2379 74ccb34e bellard
                            break;
2380 d014c98c bellard
                        case R_SPARC_WDISP30:
2381 d014c98c bellard
                            fprintf(outfile,
2382 d014c98c bellard
                                    "    *(uint32_t *)(gen_code_ptr + %d) = "
2383 d014c98c bellard
                                    "((*(uint32_t *)(gen_code_ptr + %d)) "
2384 d014c98c bellard
                                    " & ~0x3fffffff) "
2385 ae228531 bellard
                                    " | ((((%s + %d) - (long)(gen_code_ptr + %d))>>2) "
2386 d014c98c bellard
                                    "    & 0x3fffffff);\n",
2387 4a1a1707 ths
                                    reloc_offset, reloc_offset, relname, addend,
2388 3442e896 pbrook
                                    reloc_offset);
2389 d014c98c bellard
                            break;
2390 74ccb34e bellard
                        case R_SPARC_WDISP22:
2391 74ccb34e bellard
                            fprintf(outfile,
2392 74ccb34e bellard
                                    "    *(uint32_t *)(gen_code_ptr + %d) = "
2393 74ccb34e bellard
                                    "((*(uint32_t *)(gen_code_ptr + %d)) "
2394 74ccb34e bellard
                                    " & ~0x3fffff) "
2395 74ccb34e bellard
                                    " | ((((%s + %d) - (long)(gen_code_ptr + %d))>>2) "
2396 74ccb34e bellard
                                    "    & 0x3fffff);\n",
2397 4a1a1707 ths
                                    reloc_offset, reloc_offset, relname, addend,
2398 74ccb34e bellard
                                    reloc_offset);
2399 74ccb34e bellard
                            break;
2400 b80029ca ths
                        case R_SPARC_HH22:
2401 b80029ca ths
                            fprintf(outfile,
2402 b80029ca ths
                                    "    *(uint32_t *)(gen_code_ptr + %d) = "
2403 b80029ca ths
                                    "((*(uint32_t *)(gen_code_ptr + %d)) "
2404 b80029ca ths
                                    " & ~0x00000000) "
2405 b80029ca ths
                                    " | (((%s + %d) >> 42) & 0x00000000);\n",
2406 4a1a1707 ths
                                    reloc_offset, reloc_offset, relname, addend);
2407 b80029ca ths
                             break;
2408 b80029ca ths
2409 b80029ca ths
                        case R_SPARC_LM22:
2410 b80029ca ths
                            fprintf(outfile,
2411 b80029ca ths
                                    "    *(uint32_t *)(gen_code_ptr + %d) = "
2412 b80029ca ths
                                    "((*(uint32_t *)(gen_code_ptr + %d)) "
2413 b80029ca ths
                                    " & ~0x00000000) "
2414 b80029ca ths
                                    " | (((%s + %d) >> 10) & 0x00000000);\n",
2415 4a1a1707 ths
                                    reloc_offset, reloc_offset, relname, addend);
2416 b80029ca ths
                            break;
2417 b80029ca ths
2418 b80029ca ths
                        case R_SPARC_HM10:
2419 b80029ca ths
                            fprintf(outfile,
2420 b80029ca ths
                                    "    *(uint32_t *)(gen_code_ptr + %d) = "
2421 b80029ca ths
                                    "((*(uint32_t *)(gen_code_ptr + %d)) "
2422 b80029ca ths
                                    " & ~0x00000000) "
2423 b80029ca ths
                                    " | ((((%s + %d) >> 32 & 0x3ff)) & 0x00000000);\n",
2424 4a1a1707 ths
                                    reloc_offset, reloc_offset, relname, addend);
2425 b80029ca ths
                            break;
2426 b80029ca ths
2427 d014c98c bellard
                        default:
2428 4a1a1707 ths
                            error("unsupported sparc64 relocation (%d) for symbol %s", type, relname);
2429 d014c98c bellard
                        }
2430 d014c98c bellard
                    }
2431 d014c98c bellard
                }
2432 d014c98c bellard
            }
2433 ff1f20a3 bellard
#elif defined(HOST_ARM)
2434 ff1f20a3 bellard
            {
2435 4a1a1707 ths
                char relname[256];
2436 ff1f20a3 bellard
                int type;
2437 ff1f20a3 bellard
                int addend;
2438 3442e896 pbrook
                int reloc_offset;
2439 46152182 pbrook
                uint32_t insn;
2440 46152182 pbrook
2441 46152182 pbrook
                insn = get32((uint32_t *)(p_start + 4));
2442 46152182 pbrook
                /* If prologue ends in sub sp, sp, #const then assume
2443 46152182 pbrook
                   op has a stack frame and needs the frame pointer.  */
2444 46152182 pbrook
                if ((insn & 0xffffff00) == 0xe24dd000) {
2445 46152182 pbrook
                    int i;
2446 46152182 pbrook
                    uint32_t opcode;
2447 46152182 pbrook
                    opcode = 0xe28db000; /* add fp, sp, #0.  */
2448 46152182 pbrook
#if 0
2449 46152182 pbrook
/* ??? Need to undo the extra stack adjustment at the end of the op.
2450 46152182 pbrook
   For now just leave the stack misaligned and hope it doesn't break anything
2451 46152182 pbrook
   too important.  */
2452 46152182 pbrook
                    if ((insn & 4) != 0) {
2453 46152182 pbrook
                        /* Preserve doubleword stack alignment.  */
2454 46152182 pbrook
                        fprintf(outfile,
2455 46152182 pbrook
                                "    *(uint32_t *)(gen_code_ptr + 4)= 0x%x;\n",
2456 46152182 pbrook
                                insn + 4);
2457 46152182 pbrook
                        opcode -= 4;
2458 46152182 pbrook
                    }
2459 46152182 pbrook
#endif
2460 46152182 pbrook
                    insn = get32((uint32_t *)(p_start - 4));
2461 46152182 pbrook
                    /* Calculate the size of the saved registers,
2462 46152182 pbrook
                       excluding pc.  */
2463 46152182 pbrook
                    for (i = 0; i < 15; i++) {
2464 46152182 pbrook
                        if (insn & (1 << i))
2465 46152182 pbrook
                            opcode += 4;
2466 46152182 pbrook
                    }
2467 46152182 pbrook
                    fprintf(outfile,
2468 46152182 pbrook
                            "    *(uint32_t *)gen_code_ptr = 0x%x;\n", opcode);
2469 46152182 pbrook
                }
2470 4a1a1707 ths
                arm_emit_ldr_info(relname, start_offset, outfile, p_start, p_end,
2471 ff1f20a3 bellard
                                  relocs, nb_relocs);
2472 ff1f20a3 bellard
2473 ff1f20a3 bellard
                for(i = 0, rel = relocs;i < nb_relocs; i++, rel++) {
2474 ff1f20a3 bellard
                if (rel->r_offset >= start_offset &&
2475 ff1f20a3 bellard
                    rel->r_offset < start_offset + copy_size) {
2476 ff1f20a3 bellard
                    sym_name = strtab + symtab[ELFW(R_SYM)(rel->r_info)].st_name;
2477 ff1f20a3 bellard
                    /* the compiler leave some unnecessary references to the code */
2478 ff1f20a3 bellard
                    if (sym_name[0] == '\0')
2479 ff1f20a3 bellard
                        continue;
2480 4a1a1707 ths
                    get_reloc_expr(relname, sizeof(relname), sym_name);
2481 ff1f20a3 bellard
                    type = ELF32_R_TYPE(rel->r_info);
2482 ff1f20a3 bellard
                    addend = get32((uint32_t *)(text + rel->r_offset));
2483 3442e896 pbrook
                    reloc_offset = rel->r_offset - start_offset;
2484 ff1f20a3 bellard
                    switch(type) {
2485 ff1f20a3 bellard
                    case R_ARM_ABS32:
2486 5fafdf24 ths
                        fprintf(outfile, "    *(uint32_t *)(gen_code_ptr + %d) = %s + %d;\n",
2487 4a1a1707 ths
                                reloc_offset, relname, addend);
2488 ff1f20a3 bellard
                        break;
2489 ff1f20a3 bellard
                    case R_ARM_PC24:
2490 46152182 pbrook
                    case R_ARM_JUMP24:
2491 46152182 pbrook
                    case R_ARM_CALL:
2492 5fafdf24 ths
                        fprintf(outfile, "    arm_reloc_pc24((uint32_t *)(gen_code_ptr + %d), 0x%x, %s);\n",
2493 4a1a1707 ths
                                reloc_offset, addend, relname);
2494 ff1f20a3 bellard
                        break;
2495 ff1f20a3 bellard
                    default:
2496 ff1f20a3 bellard
                        error("unsupported arm relocation (%d)", type);
2497 ff1f20a3 bellard
                    }
2498 ff1f20a3 bellard
                }
2499 ff1f20a3 bellard
                }
2500 38e584a0 bellard
            }
2501 38e584a0 bellard
#elif defined(HOST_M68K)
2502 38e584a0 bellard
            {
2503 4a1a1707 ths
                char relname[256];
2504 38e584a0 bellard
                int type;
2505 38e584a0 bellard
                int addend;
2506 3442e896 pbrook
                int reloc_offset;
2507 38e584a0 bellard
                Elf32_Sym *sym;
2508 38e584a0 bellard
                for(i = 0, rel = relocs;i < nb_relocs; i++, rel++) {
2509 38e584a0 bellard
                if (rel->r_offset >= start_offset &&
2510 38e584a0 bellard
                    rel->r_offset < start_offset + copy_size) {
2511 38e584a0 bellard
                    sym = &(symtab[ELFW(R_SYM)(rel->r_info)]);
2512 38e584a0 bellard
                    sym_name = strtab + symtab[ELFW(R_SYM)(rel->r_info)].st_name;
2513 4a1a1707 ths
                    get_reloc_expr(relname, sizeof(relname), sym_name);
2514 38e584a0 bellard
                    type = ELF32_R_TYPE(rel->r_info);
2515 38e584a0 bellard
                    addend = get32((uint32_t *)(text + rel->r_offset)) + rel->r_addend;
2516 3442e896 pbrook
                    reloc_offset = rel->r_offset - start_offset;
2517 38e584a0 bellard
                    switch(type) {
2518 38e584a0 bellard
                    case R_68K_32:
2519 38e584a0 bellard
                        fprintf(outfile, "    /* R_68K_32 RELOC, offset %x */\n", rel->r_offset) ;
2520 5fafdf24 ths
                        fprintf(outfile, "    *(uint32_t *)(gen_code_ptr + %d) = %s + %#x;\n",
2521 4a1a1707 ths
                                reloc_offset, relname, addend );
2522 38e584a0 bellard
                        break;
2523 38e584a0 bellard
                    case R_68K_PC32:
2524 38e584a0 bellard
                        fprintf(outfile, "    /* R_68K_PC32 RELOC, offset %x */\n", rel->r_offset);
2525 5fafdf24 ths
                        fprintf(outfile, "    *(uint32_t *)(gen_code_ptr + %d) = %s - (long)(gen_code_ptr + %#x) + %#x;\n",
2526 4a1a1707 ths
                                reloc_offset, relname, reloc_offset, /*sym->st_value+*/ addend);
2527 38e584a0 bellard
                        break;
2528 38e584a0 bellard
                    default:
2529 38e584a0 bellard
                        error("unsupported m68k relocation (%d)", type);
2530 38e584a0 bellard
                    }
2531 38e584a0 bellard
                }
2532 38e584a0 bellard
                }
2533 ff1f20a3 bellard
            }
2534 9617efe8 ths
#elif defined(HOST_MIPS) || defined(HOST_MIPS64)
2535 c4b89d18 ths
            {
2536 c4b89d18 ths
                for (i = 0, rel = relocs; i < nb_relocs; i++, rel++) {
2537 c4b89d18 ths
                    if (rel->r_offset >= start_offset && rel->r_offset < start_offset + copy_size) {
2538 4a1a1707 ths
                        char relname[256];
2539 c4b89d18 ths
                        int type;
2540 c4b89d18 ths
                        int addend;
2541 c4b89d18 ths
                        int reloc_offset;
2542 c4b89d18 ths
2543 c4b89d18 ths
                        sym_name = strtab + symtab[ELF32_R_SYM(rel->r_info)].st_name;
2544 c4b89d18 ths
                        /* the compiler leave some unnecessary references to the code */
2545 c4b89d18 ths
                        if (sym_name[0] == '\0')
2546 c4b89d18 ths
                            continue;
2547 4a1a1707 ths
                        get_reloc_expr(relname, sizeof(relname), sym_name);
2548 c4b89d18 ths
                        type = ELF32_R_TYPE(rel->r_info);
2549 c4b89d18 ths
                        addend = get32((uint32_t *)(text + rel->r_offset));
2550 c4b89d18 ths
                        reloc_offset = rel->r_offset - start_offset;
2551 c4b89d18 ths
                        switch (type) {
2552 9617efe8 ths
                        case R_MIPS_26:
2553 9617efe8 ths
                            fprintf(outfile, "    /* R_MIPS_26 RELOC, offset 0x%x, name %s */\n",
2554 9617efe8 ths
                                    rel->r_offset, sym_name);
2555 9617efe8 ths
                            fprintf(outfile,
2556 9617efe8 ths
                                    "    *(uint32_t *)(gen_code_ptr + 0x%x) = "
2557 9617efe8 ths
                                    "(0x%x & ~0x3fffff) "
2558 9617efe8 ths
                                    "| ((0x%x + ((%s - (*(uint32_t *)(gen_code_ptr + 0x%x))) >> 2)) "
2559 9617efe8 ths
                                    "   & 0x3fffff);\n",
2560 4a1a1707 ths
                                    reloc_offset, addend, addend, relname, reloc_offset);
2561 9617efe8 ths
                            break;
2562 c4b89d18 ths
                        case R_MIPS_HI16:
2563 c4b89d18 ths
                            fprintf(outfile, "    /* R_MIPS_HI16 RELOC, offset 0x%x, name %s */\n",
2564 c4b89d18 ths
                                    rel->r_offset, sym_name);
2565 c4b89d18 ths
                            fprintf(outfile,
2566 c4b89d18 ths
                                    "    *(uint32_t *)(gen_code_ptr + 0x%x) = "
2567 c4b89d18 ths
                                    "((*(uint32_t *)(gen_code_ptr + 0x%x)) "
2568 c4b89d18 ths
                                    " & ~0xffff) "
2569 c4b89d18 ths
                                    " | (((%s - 0x8000) >> 16) & 0xffff);\n",
2570 4a1a1707 ths
                                    reloc_offset, reloc_offset, relname);
2571 c4b89d18 ths
                            break;
2572 c4b89d18 ths
                        case R_MIPS_LO16:
2573 c4b89d18 ths
                            fprintf(outfile, "    /* R_MIPS_LO16 RELOC, offset 0x%x, name %s */\n",
2574 c4b89d18 ths
                                    rel->r_offset, sym_name);
2575 c4b89d18 ths
                            fprintf(outfile,
2576 c4b89d18 ths
                                    "    *(uint32_t *)(gen_code_ptr + 0x%x) = "
2577 c4b89d18 ths
                                    "((*(uint32_t *)(gen_code_ptr + 0x%x)) "
2578 c4b89d18 ths
                                    " & ~0xffff) "
2579 c4b89d18 ths
                                    " | (%s & 0xffff);\n",
2580 4a1a1707 ths
                                    reloc_offset, reloc_offset, relname);
2581 c4b89d18 ths
                            break;
2582 c4b89d18 ths
                        case R_MIPS_PC16:
2583 c4b89d18 ths
                            fprintf(outfile, "    /* R_MIPS_PC16 RELOC, offset 0x%x, name %s */\n",
2584 c4b89d18 ths
                                    rel->r_offset, sym_name);
2585 c4b89d18 ths
                            fprintf(outfile,
2586 c4b89d18 ths
                                    "    *(uint32_t *)(gen_code_ptr + 0x%x) = "
2587 c4b89d18 ths
                                    "(0x%x & ~0xffff) "
2588 c4b89d18 ths
                                    "| ((0x%x + ((%s - (*(uint32_t *)(gen_code_ptr + 0x%x))) >> 2)) "
2589 c4b89d18 ths
                                    "   & 0xffff);\n",
2590 4a1a1707 ths
                                    reloc_offset, addend, addend, relname, reloc_offset);
2591 c4b89d18 ths
                            break;
2592 c4b89d18 ths
                        case R_MIPS_GOT16:
2593 c4b89d18 ths
                        case R_MIPS_CALL16:
2594 c4b89d18 ths
                            fprintf(outfile, "    /* R_MIPS_GOT16 RELOC, offset 0x%x, name %s */\n",
2595 c4b89d18 ths
                                    rel->r_offset, sym_name);
2596 c4b89d18 ths
                            fprintf(outfile,
2597 c4b89d18 ths
                                    "    *(uint32_t *)(gen_code_ptr + 0x%x) = "
2598 c4b89d18 ths
                                    "((*(uint32_t *)(gen_code_ptr + 0x%x)) "
2599 c4b89d18 ths
                                    " & ~0xffff) "
2600 c4b89d18 ths
                                    " | (((%s - 0x8000) >> 16) & 0xffff);\n",
2601 4a1a1707 ths
                                    reloc_offset, reloc_offset, relname);
2602 c4b89d18 ths
                            break;
2603 c4b89d18 ths
                        default:
2604 c4b89d18 ths
                            error("unsupported MIPS relocation (%d)", type);
2605 c4b89d18 ths
                        }
2606 c4b89d18 ths
                    }
2607 c4b89d18 ths
                }
2608 c4b89d18 ths
            }
2609 ce11fedc bellard
#else
2610 ce11fedc bellard
#error unsupported CPU
2611 ce11fedc bellard
#endif
2612 dc99065b bellard
        fprintf(outfile, "    gen_code_ptr += %d;\n", copy_size);
2613 dc99065b bellard
        fprintf(outfile, "}\n");
2614 dc99065b bellard
        fprintf(outfile, "break;\n\n");
2615 dc99065b bellard
    } else {
2616 dc99065b bellard
        fprintf(outfile, "static inline void gen_%s(", name);
2617 dc99065b bellard
        if (nb_args == 0) {
2618 dc99065b bellard
            fprintf(outfile, "void");
2619 dc99065b bellard
        } else {
2620 dc99065b bellard
            for(i = 0; i < nb_args; i++) {
2621 dc99065b bellard
                if (i != 0)
2622 dc99065b bellard
                    fprintf(outfile, ", ");
2623 dc99065b bellard
                fprintf(outfile, "long param%d", i + 1);
2624 367e86e8 bellard
            }
2625 367e86e8 bellard
        }
2626 dc99065b bellard
        fprintf(outfile, ")\n");
2627 dc99065b bellard
        fprintf(outfile, "{\n");
2628 dc99065b bellard
        for(i = 0; i < nb_args; i++) {
2629 dc99065b bellard
            fprintf(outfile, "    *gen_opparam_ptr++ = param%d;\n", i + 1);
2630 dc99065b bellard
        }
2631 dc99065b bellard
        fprintf(outfile, "    *gen_opc_ptr++ = INDEX_%s;\n", name);
2632 dc99065b bellard
        fprintf(outfile, "}\n\n");
2633 367e86e8 bellard
    }
2634 367e86e8 bellard
}
2635 367e86e8 bellard
2636 67b915a5 bellard
int gen_file(FILE *outfile, int out_type)
2637 367e86e8 bellard
{
2638 67b915a5 bellard
    int i;
2639 67b915a5 bellard
    EXE_SYM *sym;
2640 367e86e8 bellard
2641 d219f7e7 bellard
    if (out_type == OUT_INDEX_OP) {
2642 a513fe19 bellard
        fprintf(outfile, "DEF(end, 0, 0)\n");
2643 e477b8b8 bellard
        fprintf(outfile, "DEF(nop, 0, 0)\n");
2644 e477b8b8 bellard
        fprintf(outfile, "DEF(nop1, 1, 0)\n");
2645 e477b8b8 bellard
        fprintf(outfile, "DEF(nop2, 2, 0)\n");
2646 e477b8b8 bellard
        fprintf(outfile, "DEF(nop3, 3, 0)\n");
2647 dc99065b bellard
        for(i = 0, sym = symtab; i < nb_syms; i++, sym++) {
2648 82eec0a1 bellard
            const char *name;
2649 67b915a5 bellard
            name = get_sym_name(sym);
2650 82eec0a1 bellard
            if (strstart(name, OP_PREFIX, NULL)) {
2651 67b915a5 bellard
                gen_code(name, sym->st_value, sym->st_size, outfile, 2);
2652 dc99065b bellard
            }
2653 dc99065b bellard
        }
2654 d219f7e7 bellard
    } else if (out_type == OUT_GEN_OP) {
2655 d219f7e7 bellard
        /* generate gen_xxx functions */
2656 c4687878 bellard
        fprintf(outfile, "#include \"dyngen-op.h\"\n");
2657 d219f7e7 bellard
        for(i = 0, sym = symtab; i < nb_syms; i++, sym++) {
2658 d219f7e7 bellard
            const char *name;
2659 67b915a5 bellard
            name = get_sym_name(sym);
2660 d219f7e7 bellard
            if (strstart(name, OP_PREFIX, NULL)) {
2661 82eec0a1 bellard
#if defined(CONFIG_FORMAT_ELF) || defined(CONFIG_FORMAT_COFF)
2662 67b915a5 bellard
                if (sym->st_shndx != text_shndx)
2663 d219f7e7 bellard
                    error("invalid section for opcode (0x%x)", sym->st_shndx);
2664 82eec0a1 bellard
#endif
2665 67b915a5 bellard
                gen_code(name, sym->st_value, sym->st_size, outfile, 0);
2666 d219f7e7 bellard
            }
2667 d219f7e7 bellard
        }
2668 3b46e624 ths
2669 dc99065b bellard
    } else {
2670 dc99065b bellard
        /* generate big code generation switch */
2671 46152182 pbrook
2672 46152182 pbrook
#ifdef HOST_ARM
2673 46152182 pbrook
        /* We need to know the size of all the ops so we can figure out when
2674 46152182 pbrook
           to emit constant pools.  This must be consistent with opc.h.  */
2675 46152182 pbrook
fprintf(outfile,
2676 46152182 pbrook
"static const uint32_t arm_opc_size[] = {\n"
2677 46152182 pbrook
"  0,\n" /* end */
2678 46152182 pbrook
"  0,\n" /* nop */
2679 46152182 pbrook
"  0,\n" /* nop1 */
2680 46152182 pbrook
"  0,\n" /* nop2 */
2681 46152182 pbrook
"  0,\n"); /* nop3 */
2682 46152182 pbrook
        for(i = 0, sym = symtab; i < nb_syms; i++, sym++) {
2683 46152182 pbrook
            const char *name;
2684 46152182 pbrook
            name = get_sym_name(sym);
2685 46152182 pbrook
            if (strstart(name, OP_PREFIX, NULL)) {
2686 46152182 pbrook
                fprintf(outfile, "  %d,\n", sym->st_size);
2687 46152182 pbrook
            }
2688 46152182 pbrook
        }
2689 46152182 pbrook
fprintf(outfile,
2690 46152182 pbrook
"};\n");
2691 46152182 pbrook
#endif
2692 46152182 pbrook
2693 dc99065b bellard
fprintf(outfile,
2694 dc99065b bellard
"int dyngen_code(uint8_t *gen_code_buf,\n"
2695 d4e8164f bellard
"                uint16_t *label_offsets, uint16_t *jmp_offsets,\n"
2696 c4687878 bellard
"                const uint16_t *opc_buf, const uint32_t *opparam_buf, const long *gen_labels)\n"
2697 dc99065b bellard
"{\n"
2698 dc99065b bellard
"    uint8_t *gen_code_ptr;\n"
2699 dc99065b bellard
"    const uint16_t *opc_ptr;\n"
2700 ff1f20a3 bellard
"    const uint32_t *opparam_ptr;\n");
2701 ff1f20a3 bellard
2702 ff1f20a3 bellard
#ifdef HOST_ARM
2703 46152182 pbrook
/* Arm is tricky because it uses constant pools for loading immediate values.
2704 46152182 pbrook
   We assume (and require) each function is code followed by a constant pool.
2705 46152182 pbrook
   All the ops are small so this should be ok.  For each op we figure
2706 46152182 pbrook
   out how much "spare" range we have in the load instructions.  This allows
2707 46152182 pbrook
   us to insert subsequent ops in between the op and the constant pool,
2708 46152182 pbrook
   eliminating the neeed to jump around the pool.
2709 46152182 pbrook

2710 46152182 pbrook
   We currently generate:
2711 3b46e624 ths

2712 46152182 pbrook
   [ For this example we assume merging would move op1_pool out of range.
2713 46152182 pbrook
     In practice we should be able to combine many ops before the offset
2714 46152182 pbrook
     limits are reached. ]
2715 46152182 pbrook
   op1_code;
2716 46152182 pbrook
   op2_code;
2717 46152182 pbrook
   goto op3;
2718 46152182 pbrook
   op2_pool;
2719 46152182 pbrook
   op1_pool;
2720 46152182 pbrook
op3:
2721 46152182 pbrook
   op3_code;
2722 46152182 pbrook
   ret;
2723 46152182 pbrook
   op3_pool;
2724 46152182 pbrook

2725 46152182 pbrook
   Ideally we'd put op1_pool before op2_pool, but that requires two passes.
2726 46152182 pbrook
 */
2727 ff1f20a3 bellard
fprintf(outfile,
2728 ff1f20a3 bellard
"    uint8_t *last_gen_code_ptr = gen_code_buf;\n"
2729 ff1f20a3 bellard
"    LDREntry *arm_ldr_ptr = arm_ldr_table;\n"
2730 46152182 pbrook
"    uint32_t *arm_data_ptr = arm_data_table + ARM_LDR_TABLE_SIZE;\n"
2731 46152182 pbrook
/* Initialise the parmissible pool offset to an arbitary large value.  */
2732 46152182 pbrook
"    uint8_t *arm_pool_ptr = gen_code_buf + 0x1000000;\n");
2733 ff1f20a3 bellard
#endif
2734 b8076a74 bellard
#ifdef HOST_IA64
2735 b8076a74 bellard
    {
2736 b8076a74 bellard
        long addend, not_first = 0;
2737 b8076a74 bellard
        unsigned long sym_idx;
2738 b8076a74 bellard
        int index, max_index;
2739 b8076a74 bellard
        const char *sym_name;
2740 b8076a74 bellard
        EXE_RELOC *rel;
2741 b8076a74 bellard
2742 b8076a74 bellard
        max_index = -1;
2743 b8076a74 bellard
        for (i = 0, rel = relocs;i < nb_relocs; i++, rel++) {
2744 b8076a74 bellard
            sym_idx = ELF64_R_SYM(rel->r_info);
2745 b8076a74 bellard
            sym_name = (strtab + symtab[sym_idx].st_name);
2746 b8076a74 bellard
            if (strstart(sym_name, "__op_gen_label", NULL))
2747 b8076a74 bellard
                continue;
2748 b8076a74 bellard
            if (ELF64_R_TYPE(rel->r_info) != R_IA64_PCREL21B)
2749 b8076a74 bellard
                continue;
2750 b8076a74 bellard
2751 b8076a74 bellard
            addend = rel->r_addend;
2752 b8076a74 bellard
            index = get_plt_index(sym_name, addend);
2753 b8076a74 bellard
            if (index <= max_index)
2754 b8076a74 bellard
                continue;
2755 b8076a74 bellard
            max_index = index;
2756 b8076a74 bellard
            fprintf(outfile, "    extern void %s(void);\n", sym_name);
2757 b8076a74 bellard
        }
2758 b8076a74 bellard
2759 b8076a74 bellard
        fprintf(outfile,
2760 b8076a74 bellard
                "    struct ia64_fixup *plt_fixes = NULL, "
2761 b8076a74 bellard
                "*ltoff_fixes = NULL;\n"
2762 b8076a74 bellard
                "    static long plt_target[] = {\n\t");
2763 b8076a74 bellard
2764 b8076a74 bellard
        max_index = -1;
2765 b8076a74 bellard
        for (i = 0, rel = relocs;i < nb_relocs; i++, rel++) {
2766 b8076a74 bellard
            sym_idx = ELF64_R_SYM(rel->r_info);
2767 b8076a74 bellard
            sym_name = (strtab + symtab[sym_idx].st_name);
2768 b8076a74 bellard
            if (strstart(sym_name, "__op_gen_label", NULL))
2769 b8076a74 bellard
                continue;
2770 b8076a74 bellard
            if (ELF64_R_TYPE(rel->r_info) != R_IA64_PCREL21B)
2771 b8076a74 bellard
                continue;
2772 b8076a74 bellard
2773 b8076a74 bellard
            addend = rel->r_addend;
2774 b8076a74 bellard
            index = get_plt_index(sym_name, addend);
2775 b8076a74 bellard
            if (index <= max_index)
2776 b8076a74 bellard
                continue;
2777 b8076a74 bellard
            max_index = index;
2778 b8076a74 bellard
2779 b8076a74 bellard
            if (not_first)
2780 b8076a74 bellard
                fprintf(outfile, ",\n\t");
2781 b8076a74 bellard
            not_first = 1;
2782 b8076a74 bellard
            if (addend)
2783 b8076a74 bellard
                fprintf(outfile, "(long) &%s + %ld", sym_name, addend);
2784 b8076a74 bellard
            else
2785 b8076a74 bellard
                fprintf(outfile, "(long) &%s", sym_name);
2786 b8076a74 bellard
        }
2787 b8076a74 bellard
        fprintf(outfile, "\n    };\n"
2788 b8076a74 bellard
            "    unsigned int plt_offset[%u] = { 0 };\n", max_index + 1);
2789 b8076a74 bellard
    }
2790 b8076a74 bellard
#endif
2791 ff1f20a3 bellard
2792 ff1f20a3 bellard
fprintf(outfile,
2793 ff1f20a3 bellard
"\n"
2794 dc99065b bellard
"    gen_code_ptr = gen_code_buf;\n"
2795 dc99065b bellard
"    opc_ptr = opc_buf;\n"
2796 ae228531 bellard
"    opparam_ptr = opparam_buf;\n");
2797 ae228531 bellard
2798 5fafdf24 ths
        /* Generate prologue, if needed. */
2799 ae228531 bellard
2800 ae228531 bellard
fprintf(outfile,
2801 46152182 pbrook
"    for(;;) {\n");
2802 46152182 pbrook
2803 46152182 pbrook
#ifdef HOST_ARM
2804 46152182 pbrook
/* Generate constant pool if needed */
2805 46152182 pbrook
fprintf(outfile,
2806 46152182 pbrook
"            if (gen_code_ptr + arm_opc_size[*opc_ptr] >= arm_pool_ptr) {\n"
2807 46152182 pbrook
"                gen_code_ptr = arm_flush_ldr(gen_code_ptr, arm_ldr_table, "
2808 46152182 pbrook
"arm_ldr_ptr, arm_data_ptr, arm_data_table + ARM_LDR_TABLE_SIZE, 1);\n"
2809 46152182 pbrook
"                last_gen_code_ptr = gen_code_ptr;\n"
2810 46152182 pbrook
"                arm_ldr_ptr = arm_ldr_table;\n"
2811 46152182 pbrook
"                arm_data_ptr = arm_data_table + ARM_LDR_TABLE_SIZE;\n"
2812 46152182 pbrook
"                arm_pool_ptr = gen_code_ptr + 0x1000000;\n"
2813 46152182 pbrook
"            }\n");
2814 46152182 pbrook
#endif
2815 46152182 pbrook
2816 46152182 pbrook
fprintf(outfile,
2817 46152182 pbrook
"        switch(*opc_ptr++) {\n");
2818 367e86e8 bellard
2819 dc99065b bellard
        for(i = 0, sym = symtab; i < nb_syms; i++, sym++) {
2820 dc99065b bellard
            const char *name;
2821 67b915a5 bellard
            name = get_sym_name(sym);
2822 dc99065b bellard
            if (strstart(name, OP_PREFIX, NULL)) {
2823 367e86e8 bellard
#if 0
2824 5fafdf24 ths
                printf("%4d: %s pos=0x%08x len=%d\n",
2825 dc99065b bellard
                       i, name, sym->st_value, sym->st_size);
2826 367e86e8 bellard
#endif
2827 82eec0a1 bellard
#if defined(CONFIG_FORMAT_ELF) || defined(CONFIG_FORMAT_COFF)
2828 67b915a5 bellard
                if (sym->st_shndx != text_shndx)
2829 dc99065b bellard
                    error("invalid section for opcode (0x%x)", sym->st_shndx);
2830 82eec0a1 bellard
#endif
2831 67b915a5 bellard
                gen_code(name, sym->st_value, sym->st_size, outfile, 1);
2832 dc99065b bellard
            }
2833 dc99065b bellard
        }
2834 dc99065b bellard
2835 dc99065b bellard
fprintf(outfile,
2836 8ef9a8ec bellard
"        case INDEX_op_nop:\n"
2837 8ef9a8ec bellard
"            break;\n"
2838 8ef9a8ec bellard
"        case INDEX_op_nop1:\n"
2839 8ef9a8ec bellard
"            opparam_ptr++;\n"
2840 8ef9a8ec bellard
"            break;\n"
2841 8ef9a8ec bellard
"        case INDEX_op_nop2:\n"
2842 8ef9a8ec bellard
"            opparam_ptr += 2;\n"
2843 8ef9a8ec bellard
"            break;\n"
2844 8ef9a8ec bellard
"        case INDEX_op_nop3:\n"
2845 8ef9a8ec bellard
"            opparam_ptr += 3;\n"
2846 8ef9a8ec bellard
"            break;\n"
2847 dc99065b bellard
"        default:\n"
2848 dc99065b bellard
"            goto the_end;\n"
2849 ff1f20a3 bellard
"        }\n");
2850 ff1f20a3 bellard
2851 ff1f20a3 bellard
2852 ff1f20a3 bellard
fprintf(outfile,
2853 dc99065b bellard
"    }\n"
2854 dc99065b bellard
" the_end:\n"
2855 dc99065b bellard
);
2856 b8076a74 bellard
#ifdef HOST_IA64
2857 b8076a74 bellard
    fprintf(outfile,
2858 fd4a43e4 bellard
            "    {\n"
2859 fd4a43e4 bellard
            "      extern char code_gen_buffer[];\n"
2860 fd4a43e4 bellard
            "      ia64_apply_fixes(&gen_code_ptr, ltoff_fixes, "
2861 b8076a74 bellard
            "(uint64_t) code_gen_buffer + 2*(1<<20), plt_fixes,\n\t\t\t"
2862 b8076a74 bellard
            "sizeof(plt_target)/sizeof(plt_target[0]),\n\t\t\t"
2863 fd4a43e4 bellard
            "plt_target, plt_offset);\n    }\n");
2864 b8076a74 bellard
#endif
2865 dc99065b bellard
2866 5fafdf24 ths
/* generate some code patching */
2867 9621339d bellard
#ifdef HOST_ARM
2868 46152182 pbrook
fprintf(outfile,
2869 46152182 pbrook
"if (arm_data_ptr != arm_data_table + ARM_LDR_TABLE_SIZE)\n"
2870 46152182 pbrook
"    gen_code_ptr = arm_flush_ldr(gen_code_ptr, arm_ldr_table, "
2871 46152182 pbrook
"arm_ldr_ptr, arm_data_ptr, arm_data_table + ARM_LDR_TABLE_SIZE, 0);\n");
2872 9621339d bellard
#endif
2873 d219f7e7 bellard
    /* flush instruction cache */
2874 d219f7e7 bellard
    fprintf(outfile, "flush_icache_range((unsigned long)gen_code_buf, (unsigned long)gen_code_ptr);\n");
2875 d219f7e7 bellard
2876 dc99065b bellard
    fprintf(outfile, "return gen_code_ptr -  gen_code_buf;\n");
2877 dc99065b bellard
    fprintf(outfile, "}\n\n");
2878 dc99065b bellard
2879 367e86e8 bellard
    }
2880 367e86e8 bellard
2881 367e86e8 bellard
    return 0;
2882 367e86e8 bellard
}
2883 367e86e8 bellard
2884 367e86e8 bellard
void usage(void)
2885 367e86e8 bellard
{
2886 367e86e8 bellard
    printf("dyngen (c) 2003 Fabrice Bellard\n"
2887 dc99065b bellard
           "usage: dyngen [-o outfile] [-c] objfile\n"
2888 dc99065b bellard
           "Generate a dynamic code generator from an object file\n"
2889 dc99065b bellard
           "-c     output enum of operations\n"
2890 d219f7e7 bellard
           "-g     output gen_op_xx() functions\n"
2891 dc99065b bellard
           );
2892 367e86e8 bellard
    exit(1);
2893 367e86e8 bellard
}
2894 367e86e8 bellard
2895 367e86e8 bellard
int main(int argc, char **argv)
2896 367e86e8 bellard
{
2897 d219f7e7 bellard
    int c, out_type;
2898 367e86e8 bellard
    const char *filename, *outfilename;
2899 367e86e8 bellard
    FILE *outfile;
2900 367e86e8 bellard
2901 367e86e8 bellard
    outfilename = "out.c";
2902 d219f7e7 bellard
    out_type = OUT_CODE;
2903 367e86e8 bellard
    for(;;) {
2904 d219f7e7 bellard
        c = getopt(argc, argv, "ho:cg");
2905 367e86e8 bellard
        if (c == -1)
2906 367e86e8 bellard
            break;
2907 367e86e8 bellard
        switch(c) {
2908 367e86e8 bellard
        case 'h':
2909 367e86e8 bellard
            usage();
2910 367e86e8 bellard
            break;
2911 367e86e8 bellard
        case 'o':
2912 367e86e8 bellard
            outfilename = optarg;
2913 367e86e8 bellard
            break;
2914 dc99065b bellard
        case 'c':
2915 d219f7e7 bellard
            out_type = OUT_INDEX_OP;
2916 d219f7e7 bellard
            break;
2917 d219f7e7 bellard
        case 'g':
2918 d219f7e7 bellard
            out_type = OUT_GEN_OP;
2919 dc99065b bellard
            break;
2920 367e86e8 bellard
        }
2921 367e86e8 bellard
    }
2922 367e86e8 bellard
    if (optind >= argc)
2923 367e86e8 bellard
        usage();
2924 367e86e8 bellard
    filename = argv[optind];
2925 367e86e8 bellard
    outfile = fopen(outfilename, "w");
2926 367e86e8 bellard
    if (!outfile)
2927 367e86e8 bellard
        error("could not open '%s'", outfilename);
2928 67b915a5 bellard
2929 67b915a5 bellard
    load_object(filename);
2930 67b915a5 bellard
    gen_file(outfile, out_type);
2931 367e86e8 bellard
    fclose(outfile);
2932 367e86e8 bellard
    return 0;
2933 367e86e8 bellard
}