Statistics
| Branch: | Revision:

root / dyngen.c @ 8c5e95d8

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