Statistics
| Branch: | Revision:

root / dyngen.c @ 1ae26a18

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