Statistics
| Branch: | Revision:

root / dyngen.c @ f54b3f92

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

2872 46152182 pbrook
   We currently generate:
2873 3b46e624 ths

2874 46152182 pbrook
   [ For this example we assume merging would move op1_pool out of range.
2875 46152182 pbrook
     In practice we should be able to combine many ops before the offset
2876 46152182 pbrook
     limits are reached. ]
2877 46152182 pbrook
   op1_code;
2878 46152182 pbrook
   op2_code;
2879 46152182 pbrook
   goto op3;
2880 46152182 pbrook
   op2_pool;
2881 46152182 pbrook
   op1_pool;
2882 46152182 pbrook
op3:
2883 46152182 pbrook
   op3_code;
2884 46152182 pbrook
   ret;
2885 46152182 pbrook
   op3_pool;
2886 46152182 pbrook

2887 46152182 pbrook
   Ideally we'd put op1_pool before op2_pool, but that requires two passes.
2888 46152182 pbrook
 */
2889 ff1f20a3 bellard
fprintf(outfile,
2890 ff1f20a3 bellard
"    uint8_t *last_gen_code_ptr = gen_code_buf;\n"
2891 ff1f20a3 bellard
"    LDREntry *arm_ldr_ptr = arm_ldr_table;\n"
2892 46152182 pbrook
"    uint32_t *arm_data_ptr = arm_data_table + ARM_LDR_TABLE_SIZE;\n"
2893 46152182 pbrook
/* Initialise the parmissible pool offset to an arbitary large value.  */
2894 46152182 pbrook
"    uint8_t *arm_pool_ptr = gen_code_buf + 0x1000000;\n");
2895 ff1f20a3 bellard
#endif
2896 b8076a74 bellard
#ifdef HOST_IA64
2897 57fec1fe bellard
#error broken
2898 b8076a74 bellard
    {
2899 b8076a74 bellard
        long addend, not_first = 0;
2900 b8076a74 bellard
        unsigned long sym_idx;
2901 b8076a74 bellard
        int index, max_index;
2902 b8076a74 bellard
        const char *sym_name;
2903 b8076a74 bellard
        EXE_RELOC *rel;
2904 b8076a74 bellard
2905 b8076a74 bellard
        max_index = -1;
2906 b8076a74 bellard
        for (i = 0, rel = relocs;i < nb_relocs; i++, rel++) {
2907 b8076a74 bellard
            sym_idx = ELF64_R_SYM(rel->r_info);
2908 b8076a74 bellard
            sym_name = (strtab + symtab[sym_idx].st_name);
2909 b8076a74 bellard
            if (strstart(sym_name, "__op_gen_label", NULL))
2910 b8076a74 bellard
                continue;
2911 b8076a74 bellard
            if (ELF64_R_TYPE(rel->r_info) != R_IA64_PCREL21B)
2912 b8076a74 bellard
                continue;
2913 b8076a74 bellard
2914 b8076a74 bellard
            addend = rel->r_addend;
2915 b8076a74 bellard
            index = get_plt_index(sym_name, addend);
2916 b8076a74 bellard
            if (index <= max_index)
2917 b8076a74 bellard
                continue;
2918 b8076a74 bellard
            max_index = index;
2919 b8076a74 bellard
            fprintf(outfile, "    extern void %s(void);\n", sym_name);
2920 b8076a74 bellard
        }
2921 b8076a74 bellard
2922 b8076a74 bellard
        fprintf(outfile,
2923 b8076a74 bellard
                "    struct ia64_fixup *plt_fixes = NULL, "
2924 b8076a74 bellard
                "*ltoff_fixes = NULL;\n"
2925 b8076a74 bellard
                "    static long plt_target[] = {\n\t");
2926 b8076a74 bellard
2927 b8076a74 bellard
        max_index = -1;
2928 b8076a74 bellard
        for (i = 0, rel = relocs;i < nb_relocs; i++, rel++) {
2929 b8076a74 bellard
            sym_idx = ELF64_R_SYM(rel->r_info);
2930 b8076a74 bellard
            sym_name = (strtab + symtab[sym_idx].st_name);
2931 b8076a74 bellard
            if (strstart(sym_name, "__op_gen_label", NULL))
2932 b8076a74 bellard
                continue;
2933 b8076a74 bellard
            if (ELF64_R_TYPE(rel->r_info) != R_IA64_PCREL21B)
2934 b8076a74 bellard
                continue;
2935 b8076a74 bellard
2936 b8076a74 bellard
            addend = rel->r_addend;
2937 b8076a74 bellard
            index = get_plt_index(sym_name, addend);
2938 b8076a74 bellard
            if (index <= max_index)
2939 b8076a74 bellard
                continue;
2940 b8076a74 bellard
            max_index = index;
2941 b8076a74 bellard
2942 b8076a74 bellard
            if (not_first)
2943 b8076a74 bellard
                fprintf(outfile, ",\n\t");
2944 b8076a74 bellard
            not_first = 1;
2945 b8076a74 bellard
            if (addend)
2946 b8076a74 bellard
                fprintf(outfile, "(long) &%s + %ld", sym_name, addend);
2947 b8076a74 bellard
            else
2948 b8076a74 bellard
                fprintf(outfile, "(long) &%s", sym_name);
2949 b8076a74 bellard
        }
2950 b8076a74 bellard
        fprintf(outfile, "\n    };\n"
2951 b8076a74 bellard
            "    unsigned int plt_offset[%u] = { 0 };\n", max_index + 1);
2952 b8076a74 bellard
    }
2953 b8076a74 bellard
#endif
2954 ff1f20a3 bellard
2955 46152182 pbrook
#ifdef HOST_ARM
2956 57fec1fe bellard
#error broken
2957 46152182 pbrook
/* Generate constant pool if needed */
2958 46152182 pbrook
fprintf(outfile,
2959 46152182 pbrook
"            if (gen_code_ptr + arm_opc_size[*opc_ptr] >= arm_pool_ptr) {\n"
2960 46152182 pbrook
"                gen_code_ptr = arm_flush_ldr(gen_code_ptr, arm_ldr_table, "
2961 46152182 pbrook
"arm_ldr_ptr, arm_data_ptr, arm_data_table + ARM_LDR_TABLE_SIZE, 1);\n"
2962 46152182 pbrook
"                last_gen_code_ptr = gen_code_ptr;\n"
2963 46152182 pbrook
"                arm_ldr_ptr = arm_ldr_table;\n"
2964 46152182 pbrook
"                arm_data_ptr = arm_data_table + ARM_LDR_TABLE_SIZE;\n"
2965 46152182 pbrook
"                arm_pool_ptr = gen_code_ptr + 0x1000000;\n"
2966 46152182 pbrook
"            }\n");
2967 46152182 pbrook
#endif
2968 46152182 pbrook
2969 dc99065b bellard
        for(i = 0, sym = symtab; i < nb_syms; i++, sym++) {
2970 dc99065b bellard
            const char *name;
2971 67b915a5 bellard
            name = get_sym_name(sym);
2972 dc99065b bellard
            if (strstart(name, OP_PREFIX, NULL)) {
2973 367e86e8 bellard
#if 0
2974 5fafdf24 ths
                printf("%4d: %s pos=0x%08x len=%d\n",
2975 dc99065b bellard
                       i, name, sym->st_value, sym->st_size);
2976 367e86e8 bellard
#endif
2977 82eec0a1 bellard
#if defined(CONFIG_FORMAT_ELF) || defined(CONFIG_FORMAT_COFF)
2978 67b915a5 bellard
                if (sym->st_shndx != text_shndx)
2979 dc99065b bellard
                    error("invalid section for opcode (0x%x)", sym->st_shndx);
2980 82eec0a1 bellard
#endif
2981 67b915a5 bellard
                gen_code(name, sym->st_value, sym->st_size, outfile, 1);
2982 dc99065b bellard
            }
2983 dc99065b bellard
        }
2984 367e86e8 bellard
    }
2985 367e86e8 bellard
2986 367e86e8 bellard
    return 0;
2987 367e86e8 bellard
}
2988 367e86e8 bellard
2989 367e86e8 bellard
void usage(void)
2990 367e86e8 bellard
{
2991 367e86e8 bellard
    printf("dyngen (c) 2003 Fabrice Bellard\n"
2992 dc99065b bellard
           "usage: dyngen [-o outfile] [-c] objfile\n"
2993 dc99065b bellard
           "Generate a dynamic code generator from an object file\n"
2994 dc99065b bellard
           "-c     output enum of operations\n"
2995 d219f7e7 bellard
           "-g     output gen_op_xx() functions\n"
2996 dc99065b bellard
           );
2997 367e86e8 bellard
    exit(1);
2998 367e86e8 bellard
}
2999 367e86e8 bellard
3000 367e86e8 bellard
int main(int argc, char **argv)
3001 367e86e8 bellard
{
3002 d219f7e7 bellard
    int c, out_type;
3003 367e86e8 bellard
    const char *filename, *outfilename;
3004 367e86e8 bellard
    FILE *outfile;
3005 367e86e8 bellard
3006 367e86e8 bellard
    outfilename = "out.c";
3007 d219f7e7 bellard
    out_type = OUT_CODE;
3008 367e86e8 bellard
    for(;;) {
3009 d219f7e7 bellard
        c = getopt(argc, argv, "ho:cg");
3010 367e86e8 bellard
        if (c == -1)
3011 367e86e8 bellard
            break;
3012 367e86e8 bellard
        switch(c) {
3013 367e86e8 bellard
        case 'h':
3014 367e86e8 bellard
            usage();
3015 367e86e8 bellard
            break;
3016 367e86e8 bellard
        case 'o':
3017 367e86e8 bellard
            outfilename = optarg;
3018 367e86e8 bellard
            break;
3019 dc99065b bellard
        case 'c':
3020 d219f7e7 bellard
            out_type = OUT_INDEX_OP;
3021 d219f7e7 bellard
            break;
3022 d219f7e7 bellard
        case 'g':
3023 d219f7e7 bellard
            out_type = OUT_GEN_OP;
3024 dc99065b bellard
            break;
3025 367e86e8 bellard
        }
3026 367e86e8 bellard
    }
3027 367e86e8 bellard
    if (optind >= argc)
3028 367e86e8 bellard
        usage();
3029 367e86e8 bellard
    filename = argv[optind];
3030 367e86e8 bellard
    outfile = fopen(outfilename, "w");
3031 367e86e8 bellard
    if (!outfile)
3032 367e86e8 bellard
        error("could not open '%s'", outfilename);
3033 67b915a5 bellard
3034 67b915a5 bellard
    load_object(filename);
3035 67b915a5 bellard
    gen_file(outfile, out_type);
3036 367e86e8 bellard
    fclose(outfile);
3037 367e86e8 bellard
    return 0;
3038 367e86e8 bellard
}