Statistics
| Branch: | Revision:

root / dyngen.c @ 6191b059

History | View | Annotate | Download (101.5 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 b29d8ae4 aurel32
1763 b29d8ae4 aurel32
#if defined(HOST_HPPA)
1764 b29d8ae4 aurel32
        int op_size = copy_size;
1765 b29d8ae4 aurel32
        int has_stubs = 0;
1766 b29d8ae4 aurel32
        char relname[256];
1767 b29d8ae4 aurel32
        int type, is_label;
1768 b29d8ae4 aurel32
1769 b29d8ae4 aurel32
        for (i = 0, rel = relocs; i < nb_relocs; i++, rel++) {
1770 b29d8ae4 aurel32
            if (rel->r_offset >= start_offset &&
1771 b29d8ae4 aurel32
                rel->r_offset < start_offset + copy_size) {
1772 b29d8ae4 aurel32
                sym_name = get_rel_sym_name(rel);
1773 b29d8ae4 aurel32
                sym_name = strtab + symtab[ELF32_R_SYM(rel->r_info)].st_name;
1774 b29d8ae4 aurel32
                is_label = get_reloc_expr(relname, sizeof(relname), sym_name);
1775 b29d8ae4 aurel32
                type = ELF32_R_TYPE(rel->r_info);
1776 b29d8ae4 aurel32
1777 b29d8ae4 aurel32
                if (!is_label && type == R_PARISC_PCREL17F) {
1778 b29d8ae4 aurel32
                    has_stubs = 1;
1779 b29d8ae4 aurel32
                    op_size += 8; /* ldil and be,n instructions */
1780 b29d8ae4 aurel32
                }
1781 b29d8ae4 aurel32
            }
1782 b29d8ae4 aurel32
        }
1783 b29d8ae4 aurel32
1784 b29d8ae4 aurel32
        if (has_stubs)
1785 b29d8ae4 aurel32
            op_size += 4; /* b,l,n instruction, to skip past the stubs */
1786 b29d8ae4 aurel32
1787 b29d8ae4 aurel32
        fprintf(outfile, "DEF(%s, %d, %d)\n", name + 3, nb_args, op_size);
1788 b29d8ae4 aurel32
#else
1789 b29d8ae4 aurel32
        fprintf(outfile, "DEF(%s, %d, %d)\n", name + 3, nb_args, copy_size);
1790 b29d8ae4 aurel32
#endif
1791 b29d8ae4 aurel32
1792 0ea00c9a bellard
    } else if (gen_switch == 1) {
1793 dc99065b bellard
1794 dc99065b bellard
        /* output C code */
1795 dc99065b bellard
        fprintf(outfile, "case INDEX_%s: {\n", name);
1796 dc99065b bellard
        if (nb_args > 0) {
1797 dc99065b bellard
            fprintf(outfile, "    long ");
1798 dc99065b bellard
            for(i = 0; i < nb_args; i++) {
1799 dc99065b bellard
                if (i != 0)
1800 dc99065b bellard
                    fprintf(outfile, ", ");
1801 dc99065b bellard
                fprintf(outfile, "param%d", i + 1);
1802 dc99065b bellard
            }
1803 dc99065b bellard
            fprintf(outfile, ";\n");
1804 367e86e8 bellard
        }
1805 b8076a74 bellard
#if defined(HOST_IA64)
1806 b8076a74 bellard
        fprintf(outfile, "    extern char %s;\n", name);
1807 b8076a74 bellard
#else
1808 dc99065b bellard
        fprintf(outfile, "    extern void %s();\n", name);
1809 b8076a74 bellard
#endif
1810 dc99065b bellard
1811 ce11fedc bellard
        for(i = 0, rel = relocs;i < nb_relocs; i++, rel++) {
1812 82eec0a1 bellard
            host_ulong offset = get_rel_offset(rel);
1813 82eec0a1 bellard
            if (offset >= start_offset &&
1814 82eec0a1 bellard
                offset < start_offset + (p_end - p_start)) {
1815 67b915a5 bellard
                sym_name = get_rel_sym_name(rel);
1816 82eec0a1 bellard
                if(!sym_name)
1817 82eec0a1 bellard
                    continue;
1818 5fafdf24 ths
                if (*sym_name &&
1819 d4e8164f bellard
                    !strstart(sym_name, "__op_param", NULL) &&
1820 c4687878 bellard
                    !strstart(sym_name, "__op_jmp", NULL) &&
1821 c4687878 bellard
                    !strstart(sym_name, "__op_gen_label", NULL)) {
1822 f54b3f92 aurel32
#if defined(HOST_SPARC) || defined(HOST_HPPA)
1823 d014c98c bellard
                    if (sym_name[0] == '.') {
1824 d014c98c bellard
                        fprintf(outfile,
1825 d014c98c bellard
                                "extern char __dot_%s __asm__(\"%s\");\n",
1826 d014c98c bellard
                                sym_name+1, sym_name);
1827 d014c98c bellard
                        continue;
1828 d014c98c bellard
                    }
1829 d014c98c bellard
#endif
1830 b8076a74 bellard
#if defined(__APPLE__)
1831 85028e4d ths
                    /* Set __attribute((unused)) on darwin because we
1832 85028e4d ths
                       want to avoid warning when we don't use the symbol.  */
1833 85028e4d ths
                    fprintf(outfile, "    extern char %s __attribute__((unused));\n", sym_name);
1834 b8076a74 bellard
#elif defined(HOST_IA64)
1835 b8076a74 bellard
                        if (ELF64_R_TYPE(rel->r_info) != R_IA64_PCREL21B)
1836 b8076a74 bellard
                                /*
1837 b8076a74 bellard
                                 * PCREL21 br.call targets generally
1838 b8076a74 bellard
                                 * are out of range and need to go
1839 b8076a74 bellard
                                 * through an "import stub".
1840 b8076a74 bellard
                                 */
1841 b8076a74 bellard
                                fprintf(outfile, "    extern char %s;\n",
1842 b8076a74 bellard
                                        sym_name);
1843 82eec0a1 bellard
#else
1844 ce11fedc bellard
                    fprintf(outfile, "extern char %s;\n", sym_name);
1845 82eec0a1 bellard
#endif
1846 dc99065b bellard
                }
1847 dc99065b bellard
            }
1848 dc99065b bellard
        }
1849 dc99065b bellard
1850 f54b3f92 aurel32
#ifdef __hppa__
1851 f54b3f92 aurel32
        fprintf(outfile, "    memcpy(gen_code_ptr, (void *)((char *)__canonicalize_funcptr_for_compare(%s)+%d), %d);\n",
1852 f54b3f92 aurel32
                                        name, (int)(start_offset - offset), copy_size);
1853 f54b3f92 aurel32
#else
1854 82eec0a1 bellard
        fprintf(outfile, "    memcpy(gen_code_ptr, (void *)((char *)&%s+%d), %d);\n",
1855 82eec0a1 bellard
                                        name, (int)(start_offset - offset), copy_size);
1856 f54b3f92 aurel32
#endif
1857 d4e8164f bellard
1858 d4e8164f bellard
        /* emit code offset information */
1859 d4e8164f bellard
        {
1860 67b915a5 bellard
            EXE_SYM *sym;
1861 d4e8164f bellard
            const char *sym_name, *p;
1862 7a2d6d96 pbrook
            host_ulong val;
1863 d4e8164f bellard
            int n;
1864 d4e8164f bellard
1865 d4e8164f bellard
            for(i = 0, sym = symtab; i < nb_syms; i++, sym++) {
1866 67b915a5 bellard
                sym_name = get_sym_name(sym);
1867 d4e8164f bellard
                if (strstart(sym_name, "__op_label", &p)) {
1868 c1e42a13 bellard
                    uint8_t *ptr;
1869 fe319756 bellard
                    unsigned long offset;
1870 3b46e624 ths
1871 d4e8164f bellard
                    /* test if the variable refers to a label inside
1872 d4e8164f bellard
                       the code we are generating */
1873 67b915a5 bellard
#ifdef CONFIG_FORMAT_COFF
1874 67b915a5 bellard
                    if (sym->st_shndx == text_shndx) {
1875 67b915a5 bellard
                        ptr = sdata[coff_text_shndx];
1876 67b915a5 bellard
                    } else if (sym->st_shndx == data_shndx) {
1877 67b915a5 bellard
                        ptr = sdata[coff_data_shndx];
1878 67b915a5 bellard
                    } else {
1879 67b915a5 bellard
                        ptr = NULL;
1880 67b915a5 bellard
                    }
1881 82eec0a1 bellard
#elif defined(CONFIG_FORMAT_MACH)
1882 82eec0a1 bellard
                    if(!sym->n_sect)
1883 82eec0a1 bellard
                        continue;
1884 82eec0a1 bellard
                    ptr = sdata[sym->n_sect-1];
1885 67b915a5 bellard
#else
1886 fe319756 bellard
                    ptr = sdata[sym->st_shndx];
1887 67b915a5 bellard
#endif
1888 fe319756 bellard
                    if (!ptr)
1889 fe319756 bellard
                        error("__op_labelN in invalid section");
1890 fe319756 bellard
                    offset = sym->st_value;
1891 82eec0a1 bellard
#ifdef CONFIG_FORMAT_MACH
1892 82eec0a1 bellard
                    offset -= section_hdr[sym->n_sect-1].addr;
1893 82eec0a1 bellard
#endif
1894 7a2d6d96 pbrook
                    val = *(host_ulong *)(ptr + offset);
1895 fe319756 bellard
#ifdef ELF_USES_RELOCA
1896 fe319756 bellard
                    {
1897 fe319756 bellard
                        int reloc_shndx, nb_relocs1, j;
1898 fe319756 bellard
1899 fe319756 bellard
                        /* try to find a matching relocation */
1900 fe319756 bellard
                        reloc_shndx = find_reloc(sym->st_shndx);
1901 fe319756 bellard
                        if (reloc_shndx) {
1902 5fafdf24 ths
                            nb_relocs1 = shdr[reloc_shndx].sh_size /
1903 fe319756 bellard
                                shdr[reloc_shndx].sh_entsize;
1904 fe319756 bellard
                            rel = (ELF_RELOC *)sdata[reloc_shndx];
1905 fe319756 bellard
                            for(j = 0; j < nb_relocs1; j++) {
1906 fe319756 bellard
                                if (rel->r_offset == offset) {
1907 039de852 bellard
                                    val = rel->r_addend;
1908 fe319756 bellard
                                    break;
1909 fe319756 bellard
                                }
1910 fe319756 bellard
                                rel++;
1911 fe319756 bellard
                            }
1912 fe319756 bellard
                        }
1913 fe319756 bellard
                    }
1914 3b46e624 ths
#endif
1915 c4687878 bellard
                    if (val >= start_offset && val <= start_offset + copy_size) {
1916 d4e8164f bellard
                        n = strtol(p, NULL, 10);
1917 3442e896 pbrook
                        fprintf(outfile, "    label_offsets[%d] = %ld + (gen_code_ptr - gen_code_buf);\n", n, (long)(val - start_offset));
1918 d4e8164f bellard
                    }
1919 d4e8164f bellard
                }
1920 d4e8164f bellard
            }
1921 d4e8164f bellard
        }
1922 d4e8164f bellard
1923 85028e4d ths
        /* load parameters in variables */
1924 dc99065b bellard
        for(i = 0; i < nb_args; i++) {
1925 dc99065b bellard
            fprintf(outfile, "    param%d = *opparam_ptr++;\n", i + 1);
1926 dc99065b bellard
        }
1927 dc99065b bellard
1928 dc99065b bellard
        /* patch relocations */
1929 ce11fedc bellard
#if defined(HOST_I386)
1930 dc99065b bellard
            {
1931 4a1a1707 ths
                char relname[256];
1932 57fec1fe bellard
                int type, is_label;
1933 ce11fedc bellard
                int addend;
1934 3442e896 pbrook
                int reloc_offset;
1935 dc99065b bellard
                for(i = 0, rel = relocs;i < nb_relocs; i++, rel++) {
1936 ae228531 bellard
                if (rel->r_offset >= start_offset &&
1937 ae228531 bellard
                    rel->r_offset < start_offset + copy_size) {
1938 67b915a5 bellard
                    sym_name = get_rel_sym_name(rel);
1939 b48a8bb6 bellard
                    if (!sym_name)
1940 b48a8bb6 bellard
                        continue;
1941 3442e896 pbrook
                    reloc_offset = rel->r_offset - start_offset;
1942 ecd854fd bellard
                    if (strstart(sym_name, "__op_jmp", &p)) {
1943 ecd854fd bellard
                        int n;
1944 ecd854fd bellard
                        n = strtol(p, NULL, 10);
1945 ecd854fd bellard
                        /* __op_jmp relocations are done at
1946 ecd854fd bellard
                           runtime to do translated block
1947 ecd854fd bellard
                           chaining: the offset of the instruction
1948 ecd854fd bellard
                           needs to be stored */
1949 ecd854fd bellard
                        fprintf(outfile, "    jmp_offsets[%d] = %d + (gen_code_ptr - gen_code_buf);\n",
1950 3442e896 pbrook
                                n, reloc_offset);
1951 ecd854fd bellard
                        continue;
1952 ecd854fd bellard
                    }
1953 3442e896 pbrook
1954 57fec1fe bellard
                    is_label = get_reloc_expr(relname, sizeof(relname), sym_name);
1955 367e86e8 bellard
                    addend = get32((uint32_t *)(text + rel->r_offset));
1956 67b915a5 bellard
#ifdef CONFIG_FORMAT_ELF
1957 67b915a5 bellard
                    type = ELF32_R_TYPE(rel->r_info);
1958 57fec1fe bellard
                    if (is_label) {
1959 57fec1fe bellard
                        switch(type) {
1960 57fec1fe bellard
                        case R_386_32:
1961 57fec1fe bellard
                        case R_386_PC32:
1962 57fec1fe bellard
                            fprintf(outfile, "    tcg_out_reloc(s, gen_code_ptr + %d, %d, %s, %d);\n",
1963 57fec1fe bellard
                                    reloc_offset, type, relname, addend);
1964 57fec1fe bellard
                            break;
1965 57fec1fe bellard
                        default:
1966 57fec1fe bellard
                            error("unsupported i386 relocation (%d)", type);
1967 57fec1fe bellard
                        }
1968 57fec1fe bellard
                    } else {
1969 57fec1fe bellard
                        switch(type) {
1970 57fec1fe bellard
                        case R_386_32:
1971 57fec1fe bellard
                            fprintf(outfile, "    *(uint32_t *)(gen_code_ptr + %d) = %s + %d;\n",
1972 57fec1fe bellard
                                    reloc_offset, relname, addend);
1973 57fec1fe bellard
                            break;
1974 57fec1fe bellard
                        case R_386_PC32:
1975 57fec1fe bellard
                            fprintf(outfile, "    *(uint32_t *)(gen_code_ptr + %d) = %s - (long)(gen_code_ptr + %d) + %d;\n",
1976 57fec1fe bellard
                                    reloc_offset, relname, reloc_offset, addend);
1977 57fec1fe bellard
                            break;
1978 57fec1fe bellard
                        default:
1979 57fec1fe bellard
                            error("unsupported i386 relocation (%d)", type);
1980 57fec1fe bellard
                        }
1981 367e86e8 bellard
                    }
1982 67b915a5 bellard
#elif defined(CONFIG_FORMAT_COFF)
1983 40c3bac3 bellard
                    {
1984 40c3bac3 bellard
                        char *temp_name;
1985 40c3bac3 bellard
                        int j;
1986 40c3bac3 bellard
                        EXE_SYM *sym;
1987 40c3bac3 bellard
                        temp_name = get_sym_name(symtab + *(uint32_t *)(rel->r_reloc->r_symndx));
1988 40c3bac3 bellard
                        if (!strcmp(temp_name, ".data")) {
1989 40c3bac3 bellard
                            for (j = 0, sym = symtab; j < nb_syms; j++, sym++) {
1990 40c3bac3 bellard
                                if (strstart(sym->st_name, sym_name, NULL)) {
1991 40c3bac3 bellard
                                    addend -= sym->st_value;
1992 40c3bac3 bellard
                                }
1993 40c3bac3 bellard
                            }
1994 40c3bac3 bellard
                        }
1995 40c3bac3 bellard
                    }
1996 67b915a5 bellard
                    type = rel->r_type;
1997 a4d8670f bellard
                    if (is_label) {
1998 a4d8670f bellard
/* TCG uses elf relocation constants */
1999 a4d8670f bellard
#define R_386_32        1
2000 a4d8670f bellard
#define R_386_PC32        2
2001 a4d8670f bellard
                        switch(type) {
2002 a4d8670f bellard
                        case DIR32:
2003 a4d8670f bellard
                            type = R_386_32;
2004 a4d8670f bellard
                            goto do_reloc;
2005 a4d8670f bellard
                        case DISP32:
2006 a4d8670f bellard
                            type = R_386_PC32;
2007 a4d8670f bellard
                            addend -= 4;
2008 a4d8670f bellard
                        do_reloc:
2009 a4d8670f bellard
                            fprintf(outfile, "    tcg_out_reloc(s, gen_code_ptr + %d, %d, %s, %d);\n",
2010 a4d8670f bellard
                                    reloc_offset, type, relname, addend);
2011 a4d8670f bellard
                            break;
2012 a4d8670f bellard
                        default:
2013 a4d8670f bellard
                            error("unsupported i386 relocation (%d)", type);
2014 a4d8670f bellard
                        }
2015 a4d8670f bellard
                    } else {
2016 a4d8670f bellard
                        switch(type) {
2017 a4d8670f bellard
                        case DIR32:
2018 a4d8670f bellard
                            fprintf(outfile, "    *(uint32_t *)(gen_code_ptr + %d) = %s + %d;\n",
2019 a4d8670f bellard
                                    reloc_offset, relname, addend);
2020 a4d8670f bellard
                            break;
2021 a4d8670f bellard
                        case DISP32:
2022 a4d8670f bellard
                            fprintf(outfile, "    *(uint32_t *)(gen_code_ptr + %d) = %s - (long)(gen_code_ptr + %d) + %d -4;\n",
2023 a4d8670f bellard
                                    reloc_offset, relname, reloc_offset, addend);
2024 a4d8670f bellard
                            break;
2025 a4d8670f bellard
                        default:
2026 a4d8670f bellard
                            error("unsupported i386 relocation (%d)", type);
2027 a4d8670f bellard
                        }
2028 67b915a5 bellard
                    }
2029 67b915a5 bellard
#else
2030 67b915a5 bellard
#error unsupport object format
2031 67b915a5 bellard
#endif
2032 367e86e8 bellard
                }
2033 dc99065b bellard
                }
2034 dc99065b bellard
            }
2035 c4687878 bellard
#elif defined(HOST_X86_64)
2036 bc51c5c9 bellard
            {
2037 4a1a1707 ths
                char relname[256];
2038 57fec1fe bellard
                int type, is_label;
2039 bc51c5c9 bellard
                int addend;
2040 3442e896 pbrook
                int reloc_offset;
2041 bc51c5c9 bellard
                for(i = 0, rel = relocs;i < nb_relocs; i++, rel++) {
2042 bc51c5c9 bellard
                if (rel->r_offset >= start_offset &&
2043 bc51c5c9 bellard
                    rel->r_offset < start_offset + copy_size) {
2044 bc51c5c9 bellard
                    sym_name = strtab + symtab[ELFW(R_SYM)(rel->r_info)].st_name;
2045 57fec1fe bellard
                    is_label = get_reloc_expr(relname, sizeof(relname), sym_name);
2046 bc51c5c9 bellard
                    type = ELF32_R_TYPE(rel->r_info);
2047 bc51c5c9 bellard
                    addend = rel->r_addend;
2048 3442e896 pbrook
                    reloc_offset = rel->r_offset - start_offset;
2049 57fec1fe bellard
                    if (is_label) {
2050 57fec1fe bellard
                        switch(type) {
2051 57fec1fe bellard
                        case R_X86_64_32:
2052 57fec1fe bellard
                        case R_X86_64_32S:
2053 57fec1fe bellard
                        case R_X86_64_PC32:
2054 57fec1fe bellard
                            fprintf(outfile, "    tcg_out_reloc(s, gen_code_ptr + %d, %d, %s, %d);\n",
2055 57fec1fe bellard
                                    reloc_offset, type, relname, addend);
2056 57fec1fe bellard
                            break;
2057 57fec1fe bellard
                        default:
2058 57fec1fe bellard
                            error("unsupported X86_64 relocation (%d)", type);
2059 57fec1fe bellard
                        }
2060 57fec1fe bellard
                    } else {
2061 57fec1fe bellard
                        switch(type) {
2062 57fec1fe bellard
                        case R_X86_64_32:
2063 57fec1fe bellard
                            fprintf(outfile, "    *(uint32_t *)(gen_code_ptr + %d) = (uint32_t)%s + %d;\n",
2064 57fec1fe bellard
                                    reloc_offset, relname, addend);
2065 57fec1fe bellard
                            break;
2066 57fec1fe bellard
                        case R_X86_64_32S:
2067 57fec1fe bellard
                            fprintf(outfile, "    *(uint32_t *)(gen_code_ptr + %d) = (int32_t)%s + %d;\n",
2068 57fec1fe bellard
                                    reloc_offset, relname, addend);
2069 57fec1fe bellard
                            break;
2070 57fec1fe bellard
                        case R_X86_64_PC32:
2071 57fec1fe bellard
                            fprintf(outfile, "    *(uint32_t *)(gen_code_ptr + %d) = %s - (long)(gen_code_ptr + %d) + %d;\n",
2072 57fec1fe bellard
                                    reloc_offset, relname, reloc_offset, addend);
2073 57fec1fe bellard
                            break;
2074 57fec1fe bellard
                        default:
2075 57fec1fe bellard
                            error("unsupported X86_64 relocation (%d)", type);
2076 57fec1fe bellard
                        }
2077 bc51c5c9 bellard
                    }
2078 bc51c5c9 bellard
                }
2079 bc51c5c9 bellard
                }
2080 bc51c5c9 bellard
            }
2081 ce11fedc bellard
#elif defined(HOST_PPC)
2082 04369ff2 bellard
            {
2083 82eec0a1 bellard
#ifdef CONFIG_FORMAT_ELF
2084 4a1a1707 ths
                char relname[256];
2085 04369ff2 bellard
                int type;
2086 ce11fedc bellard
                int addend;
2087 3442e896 pbrook
                int reloc_offset;
2088 04369ff2 bellard
                for(i = 0, rel = relocs;i < nb_relocs; i++, rel++) {
2089 ae228531 bellard
                    if (rel->r_offset >= start_offset &&
2090 ae228531 bellard
                        rel->r_offset < start_offset + copy_size) {
2091 efdea7bf bellard
                        sym_name = strtab + symtab[ELFW(R_SYM)(rel->r_info)].st_name;
2092 3442e896 pbrook
                        reloc_offset = rel->r_offset - start_offset;
2093 d4e8164f bellard
                        if (strstart(sym_name, "__op_jmp", &p)) {
2094 d4e8164f bellard
                            int n;
2095 d4e8164f bellard
                            n = strtol(p, NULL, 10);
2096 d4e8164f bellard
                            /* __op_jmp relocations are done at
2097 d4e8164f bellard
                               runtime to do translated block
2098 d4e8164f bellard
                               chaining: the offset of the instruction
2099 d4e8164f bellard
                               needs to be stored */
2100 d4e8164f bellard
                            fprintf(outfile, "    jmp_offsets[%d] = %d + (gen_code_ptr - gen_code_buf);\n",
2101 3442e896 pbrook
                                    n, reloc_offset);
2102 d4e8164f bellard
                            continue;
2103 d4e8164f bellard
                        }
2104 3b46e624 ths
2105 4a1a1707 ths
                        get_reloc_expr(relname, sizeof(relname), sym_name);
2106 04369ff2 bellard
                        type = ELF32_R_TYPE(rel->r_info);
2107 04369ff2 bellard
                        addend = rel->r_addend;
2108 04369ff2 bellard
                        switch(type) {
2109 04369ff2 bellard
                        case R_PPC_ADDR32:
2110 5fafdf24 ths
                            fprintf(outfile, "    *(uint32_t *)(gen_code_ptr + %d) = %s + %d;\n",
2111 4a1a1707 ths
                                    reloc_offset, relname, addend);
2112 04369ff2 bellard
                            break;
2113 04369ff2 bellard
                        case R_PPC_ADDR16_LO:
2114 5fafdf24 ths
                            fprintf(outfile, "    *(uint16_t *)(gen_code_ptr + %d) = (%s + %d);\n",
2115 4a1a1707 ths
                                    reloc_offset, relname, addend);
2116 04369ff2 bellard
                            break;
2117 04369ff2 bellard
                        case R_PPC_ADDR16_HI:
2118 5fafdf24 ths
                            fprintf(outfile, "    *(uint16_t *)(gen_code_ptr + %d) = (%s + %d) >> 16;\n",
2119 4a1a1707 ths
                                    reloc_offset, relname, addend);
2120 04369ff2 bellard
                            break;
2121 04369ff2 bellard
                        case R_PPC_ADDR16_HA:
2122 5fafdf24 ths
                            fprintf(outfile, "    *(uint16_t *)(gen_code_ptr + %d) = (%s + %d + 0x8000) >> 16;\n",
2123 4a1a1707 ths
                                    reloc_offset, relname, addend);
2124 04369ff2 bellard
                            break;
2125 04369ff2 bellard
                        case R_PPC_REL24:
2126 04369ff2 bellard
                            /* warning: must be at 32 MB distancy */
2127 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",
2128 4a1a1707 ths
                                    reloc_offset, reloc_offset, relname, reloc_offset, addend);
2129 04369ff2 bellard
                            break;
2130 04369ff2 bellard
                        default:
2131 04369ff2 bellard
                            error("unsupported powerpc relocation (%d)", type);
2132 04369ff2 bellard
                        }
2133 04369ff2 bellard
                    }
2134 04369ff2 bellard
                }
2135 82eec0a1 bellard
#elif defined(CONFIG_FORMAT_MACH)
2136 a029baa4 ths
                struct scattered_relocation_info *scarel;
2137 a029baa4 ths
                struct relocation_info * rel;
2138 a029baa4 ths
                char final_sym_name[256];
2139 a029baa4 ths
                const char *sym_name;
2140 a029baa4 ths
                const char *p;
2141 a029baa4 ths
                int slide, sslide;
2142 a029baa4 ths
                int i;
2143 a029baa4 ths
2144 a029baa4 ths
                for(i = 0, rel = relocs; i < nb_relocs; i++, rel++) {
2145 a029baa4 ths
                    unsigned int offset, length, value = 0;
2146 a029baa4 ths
                    unsigned int type, pcrel, isym = 0;
2147 a029baa4 ths
                    unsigned int usesym = 0;
2148 a029baa4 ths
2149 a029baa4 ths
                    if(R_SCATTERED & rel->r_address) {
2150 a029baa4 ths
                        scarel = (struct scattered_relocation_info*)rel;
2151 a029baa4 ths
                        offset = (unsigned int)scarel->r_address;
2152 a029baa4 ths
                        length = scarel->r_length;
2153 a029baa4 ths
                        pcrel = scarel->r_pcrel;
2154 a029baa4 ths
                        type = scarel->r_type;
2155 a029baa4 ths
                        value = scarel->r_value;
2156 a029baa4 ths
                    } else {
2157 a029baa4 ths
                        value = isym = rel->r_symbolnum;
2158 a029baa4 ths
                        usesym = (rel->r_extern);
2159 a029baa4 ths
                        offset = rel->r_address;
2160 a029baa4 ths
                        length = rel->r_length;
2161 a029baa4 ths
                        pcrel = rel->r_pcrel;
2162 a029baa4 ths
                        type = rel->r_type;
2163 a029baa4 ths
                    }
2164 a029baa4 ths
2165 a029baa4 ths
                    slide = offset - start_offset;
2166 a029baa4 ths
2167 5fafdf24 ths
                    if (!(offset >= start_offset && offset < start_offset + size))
2168 a029baa4 ths
                        continue;  /* not in our range */
2169 a029baa4 ths
2170 a029baa4 ths
                        sym_name = get_reloc_name(rel, &sslide);
2171 a029baa4 ths
2172 a029baa4 ths
                        if(usesym && symtab[isym].n_type & N_STAB)
2173 a029baa4 ths
                            continue; /* don't handle STAB (debug sym) */
2174 a029baa4 ths
2175 a029baa4 ths
                        if (sym_name && strstart(sym_name, "__op_jmp", &p)) {
2176 a029baa4 ths
                            int n;
2177 a029baa4 ths
                            n = strtol(p, NULL, 10);
2178 a029baa4 ths
                            fprintf(outfile, "    jmp_offsets[%d] = %d + (gen_code_ptr - gen_code_buf);\n",
2179 a029baa4 ths
                                    n, slide);
2180 a029baa4 ths
                            continue; /* Nothing more to do */
2181 a029baa4 ths
                        }
2182 a029baa4 ths
2183 a029baa4 ths
                        if(!sym_name) {
2184 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",
2185 a029baa4 ths
                                    name, value, usesym ? "use sym" : "don't use sym", offset, length, pcrel ? "pcrel":"", type);
2186 a029baa4 ths
                            continue; /* dunno how to handle without final_sym_name */
2187 a029baa4 ths
                        }
2188 a029baa4 ths
2189 5fafdf24 ths
                        get_reloc_expr(final_sym_name, sizeof(final_sym_name),
2190 a029baa4 ths
                                       sym_name);
2191 a029baa4 ths
                        switch(type) {
2192 a029baa4 ths
                        case PPC_RELOC_BR24:
2193 a029baa4 ths
                            if (!strstart(sym_name,"__op_gen_label",&p)) {
2194 a029baa4 ths
                                fprintf(outfile, "{\n");
2195 a029baa4 ths
                                fprintf(outfile, "    uint32_t imm = *(uint32_t *)(gen_code_ptr + %d) & 0x3fffffc;\n", slide);
2196 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",
2197 a029baa4 ths
                                        slide, slide, name, sslide);
2198 a029baa4 ths
                                fprintf(outfile, "}\n");
2199 a029baa4 ths
                            } else {
2200 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",
2201 a029baa4 ths
                                        slide, slide, final_sym_name, slide);
2202 a029baa4 ths
                            }
2203 82eec0a1 bellard
                            break;
2204 a029baa4 ths
                        case PPC_RELOC_HI16:
2205 5fafdf24 ths
                            fprintf(outfile, "    *(uint16_t *)(gen_code_ptr + %d + 2) = (%s + %d) >> 16;\n",
2206 a029baa4 ths
                                    slide, final_sym_name, sslide);
2207 a029baa4 ths
                            break;
2208 a029baa4 ths
                        case PPC_RELOC_LO16:
2209 5fafdf24 ths
                            fprintf(outfile, "    *(uint16_t *)(gen_code_ptr + %d + 2) = (%s + %d);\n",
2210 a029baa4 ths
                                    slide, final_sym_name, sslide);
2211 a029baa4 ths
                            break;
2212 a029baa4 ths
                        case PPC_RELOC_HA16:
2213 5fafdf24 ths
                            fprintf(outfile, "    *(uint16_t *)(gen_code_ptr + %d + 2) = (%s + %d + 0x8000) >> 16;\n",
2214 a029baa4 ths
                                    slide, final_sym_name, sslide);
2215 a029baa4 ths
                            break;
2216 a029baa4 ths
                        default:
2217 a029baa4 ths
                            error("unsupported powerpc relocation (%d)", type);
2218 a029baa4 ths
                    }
2219 a029baa4 ths
                }
2220 82eec0a1 bellard
#else
2221 82eec0a1 bellard
#error unsupport object format
2222 82eec0a1 bellard
#endif
2223 04369ff2 bellard
            }
2224 ce11fedc bellard
#elif defined(HOST_S390)
2225 fb3e5849 bellard
            {
2226 4a1a1707 ths
                char relname[256];
2227 fb3e5849 bellard
                int type;
2228 ce11fedc bellard
                int addend;
2229 3442e896 pbrook
                int reloc_offset;
2230 fb3e5849 bellard
                for(i = 0, rel = relocs;i < nb_relocs; i++, rel++) {
2231 ae228531 bellard
                    if (rel->r_offset >= start_offset &&
2232 ae228531 bellard
                        rel->r_offset < start_offset + copy_size) {
2233 efdea7bf bellard
                        sym_name = strtab + symtab[ELFW(R_SYM)(rel->r_info)].st_name;
2234 4a1a1707 ths
                        get_reloc_expr(relname, sizeof(relname), sym_name);
2235 fb3e5849 bellard
                        type = ELF32_R_TYPE(rel->r_info);
2236 fb3e5849 bellard
                        addend = rel->r_addend;
2237 3442e896 pbrook
                        reloc_offset = rel->r_offset - start_offset;
2238 fb3e5849 bellard
                        switch(type) {
2239 fb3e5849 bellard
                        case R_390_32:
2240 5fafdf24 ths
                            fprintf(outfile, "    *(uint32_t *)(gen_code_ptr + %d) = %s + %d;\n",
2241 4a1a1707 ths
                                    reloc_offset, relname, addend);
2242 fb3e5849 bellard
                            break;
2243 fb3e5849 bellard
                        case R_390_16:
2244 5fafdf24 ths
                            fprintf(outfile, "    *(uint16_t *)(gen_code_ptr + %d) = %s + %d;\n",
2245 4a1a1707 ths
                                    reloc_offset, relname, addend);
2246 fb3e5849 bellard
                            break;
2247 fb3e5849 bellard
                        case R_390_8:
2248 5fafdf24 ths
                            fprintf(outfile, "    *(uint8_t *)(gen_code_ptr + %d) = %s + %d;\n",
2249 4a1a1707 ths
                                    reloc_offset, relname, addend);
2250 fb3e5849 bellard
                            break;
2251 76d83bde ths
                        case R_390_PC32DBL:
2252 76d83bde ths
                            if (ELF32_ST_TYPE(symtab[ELFW(R_SYM)(rel->r_info)].st_info) == STT_SECTION) {
2253 76d83bde ths
                                fprintf(outfile,
2254 76d83bde ths
                                        "    *(uint32_t *)(gen_code_ptr + %d) += "
2255 76d83bde ths
                                        "((long)&%s - (long)gen_code_ptr) >> 1;\n",
2256 76d83bde ths
                                        reloc_offset, name);
2257 76d83bde ths
                            }
2258 76d83bde ths
                            else
2259 76d83bde ths
                                fprintf(outfile,
2260 76d83bde ths
                                        "    *(uint32_t *)(gen_code_ptr + %d) = "
2261 76d83bde ths
                                        "(%s + %d - ((uint32_t)gen_code_ptr + %d)) >> 1;\n",
2262 76d83bde ths
                                        reloc_offset, relname, addend, reloc_offset);
2263 76d83bde ths
                            break;
2264 fb3e5849 bellard
                        default:
2265 fb3e5849 bellard
                            error("unsupported s390 relocation (%d)", type);
2266 fb3e5849 bellard
                        }
2267 fb3e5849 bellard
                    }
2268 fb3e5849 bellard
                }
2269 fb3e5849 bellard
            }
2270 efdea7bf bellard
#elif defined(HOST_ALPHA)
2271 efdea7bf bellard
            {
2272 efdea7bf bellard
                for (i = 0, rel = relocs; i < nb_relocs; i++, rel++) {
2273 ae228531 bellard
                    if (rel->r_offset >= start_offset && rel->r_offset < start_offset + copy_size) {
2274 efdea7bf bellard
                        int type;
2275 3442e896 pbrook
                        long reloc_offset;
2276 74c95119 bellard
2277 efdea7bf bellard
                        type = ELF64_R_TYPE(rel->r_info);
2278 74c95119 bellard
                        sym_name = strtab + symtab[ELF64_R_SYM(rel->r_info)].st_name;
2279 3442e896 pbrook
                        reloc_offset = rel->r_offset - start_offset;
2280 efdea7bf bellard
                        switch (type) {
2281 efdea7bf bellard
                        case R_ALPHA_GPDISP:
2282 74c95119 bellard
                            /* The gp is just 32 bit, and never changes, so it's easiest to emit it
2283 74c95119 bellard
                               as an immediate instead of constructing it from the pv or ra.  */
2284 74c95119 bellard
                            fprintf(outfile, "    immediate_ldah(gen_code_ptr + %ld, gp);\n",
2285 3442e896 pbrook
                                    reloc_offset);
2286 74c95119 bellard
                            fprintf(outfile, "    immediate_lda(gen_code_ptr + %ld, gp);\n",
2287 3442e896 pbrook
                                    reloc_offset + (int)rel->r_addend);
2288 efdea7bf bellard
                            break;
2289 efdea7bf bellard
                        case R_ALPHA_LITUSE:
2290 efdea7bf bellard
                            /* jsr to literal hint. Could be used to optimize to bsr. Ignore for
2291 efdea7bf bellard
                               now, since some called functions (libc) need pv to be set up.  */
2292 efdea7bf bellard
                            break;
2293 efdea7bf bellard
                        case R_ALPHA_HINT:
2294 efdea7bf bellard
                            /* Branch target prediction hint. Ignore for now.  Should be already
2295 efdea7bf bellard
                               correct for in-function jumps.  */
2296 efdea7bf bellard
                            break;
2297 efdea7bf bellard
                        case R_ALPHA_LITERAL:
2298 74c95119 bellard
                            /* Load a literal from the GOT relative to the gp.  Since there's only a
2299 74c95119 bellard
                               single gp, nothing is to be done.  */
2300 74c95119 bellard
                            break;
2301 74c95119 bellard
                        case R_ALPHA_GPRELHIGH:
2302 74c95119 bellard
                            /* Handle fake relocations against __op_param symbol.  Need to emit the
2303 74c95119 bellard
                               high part of the immediate value instead.  Other symbols need no
2304 74c95119 bellard
                               special treatment.  */
2305 74c95119 bellard
                            if (strstart(sym_name, "__op_param", &p))
2306 74c95119 bellard
                                fprintf(outfile, "    immediate_ldah(gen_code_ptr + %ld, param%s);\n",
2307 3442e896 pbrook
                                        reloc_offset, p);
2308 74c95119 bellard
                            break;
2309 74c95119 bellard
                        case R_ALPHA_GPRELLOW:
2310 74c95119 bellard
                            if (strstart(sym_name, "__op_param", &p))
2311 74c95119 bellard
                                fprintf(outfile, "    immediate_lda(gen_code_ptr + %ld, param%s);\n",
2312 3442e896 pbrook
                                        reloc_offset, p);
2313 74c95119 bellard
                            break;
2314 74c95119 bellard
                        case R_ALPHA_BRSGP:
2315 74c95119 bellard
                            /* PC-relative jump. Tweak offset to skip the two instructions that try to
2316 74c95119 bellard
                               set up the gp from the pv.  */
2317 2f87c607 bellard
                            fprintf(outfile, "    fix_bsr(gen_code_ptr + %ld, (uint8_t *) &%s - (gen_code_ptr + %ld + 4) + 8);\n",
2318 3442e896 pbrook
                                    reloc_offset, sym_name, reloc_offset);
2319 efdea7bf bellard
                            break;
2320 efdea7bf bellard
                        default:
2321 efdea7bf bellard
                            error("unsupported Alpha relocation (%d)", type);
2322 efdea7bf bellard
                        }
2323 efdea7bf bellard
                    }
2324 efdea7bf bellard
                }
2325 efdea7bf bellard
            }
2326 efdea7bf bellard
#elif defined(HOST_IA64)
2327 efdea7bf bellard
            {
2328 b8076a74 bellard
                unsigned long sym_idx;
2329 b8076a74 bellard
                long code_offset;
2330 4a1a1707 ths
                char relname[256];
2331 efdea7bf bellard
                int type;
2332 b8076a74 bellard
                long addend;
2333 b8076a74 bellard
2334 efdea7bf bellard
                for(i = 0, rel = relocs;i < nb_relocs; i++, rel++) {
2335 b8076a74 bellard
                    sym_idx = ELF64_R_SYM(rel->r_info);
2336 b8076a74 bellard
                    if (rel->r_offset < start_offset
2337 b8076a74 bellard
                        || rel->r_offset >= start_offset + copy_size)
2338 b8076a74 bellard
                        continue;
2339 b8076a74 bellard
                    sym_name = (strtab + symtab[sym_idx].st_name);
2340 3442e896 pbrook
                    code_offset = rel->r_offset - start_offset;
2341 b8076a74 bellard
                    if (strstart(sym_name, "__op_jmp", &p)) {
2342 b8076a74 bellard
                        int n;
2343 b8076a74 bellard
                        n = strtol(p, NULL, 10);
2344 b8076a74 bellard
                        /* __op_jmp relocations are done at
2345 b8076a74 bellard
                           runtime to do translated block
2346 b8076a74 bellard
                           chaining: the offset of the instruction
2347 b8076a74 bellard
                           needs to be stored */
2348 b8076a74 bellard
                        fprintf(outfile, "    jmp_offsets[%d] ="
2349 b8076a74 bellard
                                "%ld + (gen_code_ptr - gen_code_buf);\n",
2350 3442e896 pbrook
                                n, code_offset);
2351 b8076a74 bellard
                        continue;
2352 b8076a74 bellard
                    }
2353 4a1a1707 ths
                    get_reloc_expr(relname, sizeof(relname), sym_name);
2354 b8076a74 bellard
                    type = ELF64_R_TYPE(rel->r_info);
2355 b8076a74 bellard
                    addend = rel->r_addend;
2356 b8076a74 bellard
                    switch(type) {
2357 b8076a74 bellard
                      case R_IA64_IMM64:
2358 b8076a74 bellard
                          fprintf(outfile,
2359 b8076a74 bellard
                                  "    ia64_imm64(gen_code_ptr + %ld, "
2360 b8076a74 bellard
                                  "%s + %ld);\n",
2361 4a1a1707 ths
                                  code_offset, relname, addend);
2362 b8076a74 bellard
                          break;
2363 b8076a74 bellard
                      case R_IA64_LTOFF22X:
2364 b8076a74 bellard
                      case R_IA64_LTOFF22:
2365 b8076a74 bellard
                          fprintf(outfile, "    IA64_LTOFF(gen_code_ptr + %ld,"
2366 b8076a74 bellard
                                  " %s + %ld, %d);\n",
2367 4a1a1707 ths
                                  code_offset, relname, addend,
2368 b8076a74 bellard
                                  (type == R_IA64_LTOFF22X));
2369 b8076a74 bellard
                          break;
2370 b8076a74 bellard
                      case R_IA64_LDXMOV:
2371 b8076a74 bellard
                          fprintf(outfile,
2372 b8076a74 bellard
                                  "    ia64_ldxmov(gen_code_ptr + %ld,"
2373 4a1a1707 ths
                                  " %s + %ld);\n", code_offset, relname, addend);
2374 b8076a74 bellard
                          break;
2375 b8076a74 bellard
2376 b8076a74 bellard
                      case R_IA64_PCREL21B:
2377 b8076a74 bellard
                          if (strstart(sym_name, "__op_gen_label", NULL)) {
2378 b8076a74 bellard
                              fprintf(outfile,
2379 b8076a74 bellard
                                      "    ia64_imm21b(gen_code_ptr + %ld,"
2380 b8076a74 bellard
                                      " (long) (%s + %ld -\n\t\t"
2381 b8076a74 bellard
                                      "((long) gen_code_ptr + %ld)) >> 4);\n",
2382 4a1a1707 ths
                                      code_offset, relname, addend,
2383 b8076a74 bellard
                                      code_offset & ~0xfUL);
2384 b8076a74 bellard
                          } else {
2385 b8076a74 bellard
                              fprintf(outfile,
2386 b8076a74 bellard
                                      "    IA64_PLT(gen_code_ptr + %ld, "
2387 b8076a74 bellard
                                      "%d);\t/* %s + %ld */\n",
2388 b8076a74 bellard
                                      code_offset,
2389 b8076a74 bellard
                                      get_plt_index(sym_name, addend),
2390 b8076a74 bellard
                                      sym_name, addend);
2391 b8076a74 bellard
                          }
2392 b8076a74 bellard
                          break;
2393 b8076a74 bellard
                      default:
2394 b8076a74 bellard
                          error("unsupported ia64 relocation (0x%x)",
2395 b8076a74 bellard
                                type);
2396 b8076a74 bellard
                    }
2397 efdea7bf bellard
                }
2398 b8076a74 bellard
                fprintf(outfile, "    ia64_nop_b(gen_code_ptr + %d);\n",
2399 b8076a74 bellard
                        copy_size - 16 + 2);
2400 efdea7bf bellard
            }
2401 d014c98c bellard
#elif defined(HOST_SPARC)
2402 d014c98c bellard
            {
2403 4a1a1707 ths
                char relname[256];
2404 d014c98c bellard
                int type;
2405 d014c98c bellard
                int addend;
2406 3442e896 pbrook
                int reloc_offset;
2407 d014c98c bellard
                for(i = 0, rel = relocs;i < nb_relocs; i++, rel++) {
2408 ae228531 bellard
                    if (rel->r_offset >= start_offset &&
2409 ae228531 bellard
                        rel->r_offset < start_offset + copy_size) {
2410 d014c98c bellard
                        sym_name = strtab + symtab[ELF32_R_SYM(rel->r_info)].st_name;
2411 4a1a1707 ths
                        get_reloc_expr(relname, sizeof(relname), sym_name);
2412 d014c98c bellard
                        type = ELF32_R_TYPE(rel->r_info);
2413 d014c98c bellard
                        addend = rel->r_addend;
2414 3442e896 pbrook
                        reloc_offset = rel->r_offset - start_offset;
2415 d014c98c bellard
                        switch(type) {
2416 d014c98c bellard
                        case R_SPARC_32:
2417 5fafdf24 ths
                            fprintf(outfile, "    *(uint32_t *)(gen_code_ptr + %d) = %s + %d;\n",
2418 4a1a1707 ths
                                    reloc_offset, relname, addend);
2419 d014c98c bellard
                            break;
2420 d014c98c bellard
                        case R_SPARC_HI22:
2421 d014c98c bellard
                            fprintf(outfile,
2422 d014c98c bellard
                                    "    *(uint32_t *)(gen_code_ptr + %d) = "
2423 d014c98c bellard
                                    "((*(uint32_t *)(gen_code_ptr + %d)) "
2424 d014c98c bellard
                                    " & ~0x3fffff) "
2425 ae228531 bellard
                                    " | (((%s + %d) >> 10) & 0x3fffff);\n",
2426 4a1a1707 ths
                                    reloc_offset, reloc_offset, relname, addend);
2427 d014c98c bellard
                            break;
2428 d014c98c bellard
                        case R_SPARC_LO10:
2429 d014c98c bellard
                            fprintf(outfile,
2430 d014c98c bellard
                                    "    *(uint32_t *)(gen_code_ptr + %d) = "
2431 d014c98c bellard
                                    "((*(uint32_t *)(gen_code_ptr + %d)) "
2432 d014c98c bellard
                                    " & ~0x3ff) "
2433 d014c98c bellard
                                    " | ((%s + %d) & 0x3ff);\n",
2434 4a1a1707 ths
                                    reloc_offset, reloc_offset, relname, addend);
2435 d014c98c bellard
                            break;
2436 d014c98c bellard
                        case R_SPARC_WDISP30:
2437 d014c98c bellard
                            fprintf(outfile,
2438 d014c98c bellard
                                    "    *(uint32_t *)(gen_code_ptr + %d) = "
2439 d014c98c bellard
                                    "((*(uint32_t *)(gen_code_ptr + %d)) "
2440 d014c98c bellard
                                    " & ~0x3fffffff) "
2441 ae228531 bellard
                                    " | ((((%s + %d) - (long)(gen_code_ptr + %d))>>2) "
2442 d014c98c bellard
                                    "    & 0x3fffffff);\n",
2443 4a1a1707 ths
                                    reloc_offset, reloc_offset, relname, addend,
2444 3442e896 pbrook
                                    reloc_offset);
2445 d014c98c bellard
                            break;
2446 fdbb4691 bellard
                        case R_SPARC_WDISP22:
2447 fdbb4691 bellard
                            fprintf(outfile,
2448 fdbb4691 bellard
                                    "    *(uint32_t *)(gen_code_ptr + %d) = "
2449 fdbb4691 bellard
                                    "((*(uint32_t *)(gen_code_ptr + %d)) "
2450 fdbb4691 bellard
                                    " & ~0x3fffff) "
2451 fdbb4691 bellard
                                    " | ((((%s + %d) - (long)(gen_code_ptr + %d))>>2) "
2452 fdbb4691 bellard
                                    "    & 0x3fffff);\n",
2453 fdbb4691 bellard
                                    rel->r_offset - start_offset,
2454 fdbb4691 bellard
                                    rel->r_offset - start_offset,
2455 4a1a1707 ths
                                    relname, addend,
2456 fdbb4691 bellard
                                    rel->r_offset - start_offset);
2457 fdbb4691 bellard
                            break;
2458 d014c98c bellard
                        default:
2459 d014c98c bellard
                            error("unsupported sparc relocation (%d)", type);
2460 d014c98c bellard
                        }
2461 d014c98c bellard
                    }
2462 d014c98c bellard
                }
2463 d014c98c bellard
            }
2464 d014c98c bellard
#elif defined(HOST_SPARC64)
2465 d014c98c bellard
            {
2466 4a1a1707 ths
                char relname[256];
2467 d014c98c bellard
                int type;
2468 d014c98c bellard
                int addend;
2469 3442e896 pbrook
                int reloc_offset;
2470 d014c98c bellard
                for(i = 0, rel = relocs;i < nb_relocs; i++, rel++) {
2471 ae228531 bellard
                    if (rel->r_offset >= start_offset &&
2472 ae228531 bellard
                        rel->r_offset < start_offset + copy_size) {
2473 d014c98c bellard
                        sym_name = strtab + symtab[ELF64_R_SYM(rel->r_info)].st_name;
2474 4a1a1707 ths
                        get_reloc_expr(relname, sizeof(relname), sym_name);
2475 74ccb34e bellard
                        type = ELF32_R_TYPE(rel->r_info);
2476 d014c98c bellard
                        addend = rel->r_addend;
2477 3442e896 pbrook
                        reloc_offset = rel->r_offset - start_offset;
2478 d014c98c bellard
                        switch(type) {
2479 d014c98c bellard
                        case R_SPARC_32:
2480 d014c98c bellard
                            fprintf(outfile, "    *(uint32_t *)(gen_code_ptr + %d) = %s + %d;\n",
2481 4a1a1707 ths
                                    reloc_offset, relname, addend);
2482 d014c98c bellard
                            break;
2483 d014c98c bellard
                        case R_SPARC_HI22:
2484 d014c98c bellard
                            fprintf(outfile,
2485 d014c98c bellard
                                    "    *(uint32_t *)(gen_code_ptr + %d) = "
2486 d014c98c bellard
                                    "((*(uint32_t *)(gen_code_ptr + %d)) "
2487 d014c98c bellard
                                    " & ~0x3fffff) "
2488 ae228531 bellard
                                    " | (((%s + %d) >> 10) & 0x3fffff);\n",
2489 4a1a1707 ths
                                    reloc_offset, reloc_offset, relname, addend);
2490 d014c98c bellard
                            break;
2491 d014c98c bellard
                        case R_SPARC_LO10:
2492 d014c98c bellard
                            fprintf(outfile,
2493 d014c98c bellard
                                    "    *(uint32_t *)(gen_code_ptr + %d) = "
2494 d014c98c bellard
                                    "((*(uint32_t *)(gen_code_ptr + %d)) "
2495 d014c98c bellard
                                    " & ~0x3ff) "
2496 d014c98c bellard
                                    " | ((%s + %d) & 0x3ff);\n",
2497 4a1a1707 ths
                                    reloc_offset, reloc_offset, relname, addend);
2498 d014c98c bellard
                            break;
2499 74ccb34e bellard
                        case R_SPARC_OLO10:
2500 74ccb34e bellard
                            addend += ELF64_R_TYPE_DATA (rel->r_info);
2501 74ccb34e bellard
                            fprintf(outfile,
2502 74ccb34e bellard
                                    "    *(uint32_t *)(gen_code_ptr + %d) = "
2503 74ccb34e bellard
                                    "((*(uint32_t *)(gen_code_ptr + %d)) "
2504 74ccb34e bellard
                                    " & ~0x3ff) "
2505 74ccb34e bellard
                                    " | ((%s + %d) & 0x3ff);\n",
2506 4a1a1707 ths
                                    reloc_offset, reloc_offset, relname, addend);
2507 74ccb34e bellard
                            break;
2508 d014c98c bellard
                        case R_SPARC_WDISP30:
2509 d014c98c bellard
                            fprintf(outfile,
2510 d014c98c bellard
                                    "    *(uint32_t *)(gen_code_ptr + %d) = "
2511 d014c98c bellard
                                    "((*(uint32_t *)(gen_code_ptr + %d)) "
2512 d014c98c bellard
                                    " & ~0x3fffffff) "
2513 ae228531 bellard
                                    " | ((((%s + %d) - (long)(gen_code_ptr + %d))>>2) "
2514 d014c98c bellard
                                    "    & 0x3fffffff);\n",
2515 4a1a1707 ths
                                    reloc_offset, reloc_offset, relname, addend,
2516 3442e896 pbrook
                                    reloc_offset);
2517 d014c98c bellard
                            break;
2518 74ccb34e bellard
                        case R_SPARC_WDISP22:
2519 74ccb34e bellard
                            fprintf(outfile,
2520 74ccb34e bellard
                                    "    *(uint32_t *)(gen_code_ptr + %d) = "
2521 74ccb34e bellard
                                    "((*(uint32_t *)(gen_code_ptr + %d)) "
2522 74ccb34e bellard
                                    " & ~0x3fffff) "
2523 74ccb34e bellard
                                    " | ((((%s + %d) - (long)(gen_code_ptr + %d))>>2) "
2524 74ccb34e bellard
                                    "    & 0x3fffff);\n",
2525 4a1a1707 ths
                                    reloc_offset, reloc_offset, relname, addend,
2526 74ccb34e bellard
                                    reloc_offset);
2527 74ccb34e bellard
                            break;
2528 b80029ca ths
                        case R_SPARC_HH22:
2529 b80029ca ths
                            fprintf(outfile,
2530 b80029ca ths
                                    "    *(uint32_t *)(gen_code_ptr + %d) = "
2531 b80029ca ths
                                    "((*(uint32_t *)(gen_code_ptr + %d)) "
2532 b80029ca ths
                                    " & ~0x00000000) "
2533 b80029ca ths
                                    " | (((%s + %d) >> 42) & 0x00000000);\n",
2534 4a1a1707 ths
                                    reloc_offset, reloc_offset, relname, addend);
2535 b80029ca ths
                             break;
2536 b80029ca ths
2537 b80029ca ths
                        case R_SPARC_LM22:
2538 b80029ca ths
                            fprintf(outfile,
2539 b80029ca ths
                                    "    *(uint32_t *)(gen_code_ptr + %d) = "
2540 b80029ca ths
                                    "((*(uint32_t *)(gen_code_ptr + %d)) "
2541 b80029ca ths
                                    " & ~0x00000000) "
2542 b80029ca ths
                                    " | (((%s + %d) >> 10) & 0x00000000);\n",
2543 4a1a1707 ths
                                    reloc_offset, reloc_offset, relname, addend);
2544 b80029ca ths
                            break;
2545 b80029ca ths
2546 b80029ca ths
                        case R_SPARC_HM10:
2547 b80029ca ths
                            fprintf(outfile,
2548 b80029ca ths
                                    "    *(uint32_t *)(gen_code_ptr + %d) = "
2549 b80029ca ths
                                    "((*(uint32_t *)(gen_code_ptr + %d)) "
2550 b80029ca ths
                                    " & ~0x00000000) "
2551 b80029ca ths
                                    " | ((((%s + %d) >> 32 & 0x3ff)) & 0x00000000);\n",
2552 4a1a1707 ths
                                    reloc_offset, reloc_offset, relname, addend);
2553 b80029ca ths
                            break;
2554 b80029ca ths
2555 d014c98c bellard
                        default:
2556 4a1a1707 ths
                            error("unsupported sparc64 relocation (%d) for symbol %s", type, relname);
2557 d014c98c bellard
                        }
2558 d014c98c bellard
                    }
2559 d014c98c bellard
                }
2560 d014c98c bellard
            }
2561 ff1f20a3 bellard
#elif defined(HOST_ARM)
2562 ff1f20a3 bellard
            {
2563 4a1a1707 ths
                char relname[256];
2564 ff1f20a3 bellard
                int type;
2565 ff1f20a3 bellard
                int addend;
2566 3442e896 pbrook
                int reloc_offset;
2567 46152182 pbrook
                uint32_t insn;
2568 46152182 pbrook
2569 46152182 pbrook
                insn = get32((uint32_t *)(p_start + 4));
2570 46152182 pbrook
                /* If prologue ends in sub sp, sp, #const then assume
2571 46152182 pbrook
                   op has a stack frame and needs the frame pointer.  */
2572 46152182 pbrook
                if ((insn & 0xffffff00) == 0xe24dd000) {
2573 46152182 pbrook
                    int i;
2574 46152182 pbrook
                    uint32_t opcode;
2575 46152182 pbrook
                    opcode = 0xe28db000; /* add fp, sp, #0.  */
2576 46152182 pbrook
#if 0
2577 46152182 pbrook
/* ??? Need to undo the extra stack adjustment at the end of the op.
2578 46152182 pbrook
   For now just leave the stack misaligned and hope it doesn't break anything
2579 46152182 pbrook
   too important.  */
2580 46152182 pbrook
                    if ((insn & 4) != 0) {
2581 46152182 pbrook
                        /* Preserve doubleword stack alignment.  */
2582 46152182 pbrook
                        fprintf(outfile,
2583 46152182 pbrook
                                "    *(uint32_t *)(gen_code_ptr + 4)= 0x%x;\n",
2584 46152182 pbrook
                                insn + 4);
2585 46152182 pbrook
                        opcode -= 4;
2586 46152182 pbrook
                    }
2587 46152182 pbrook
#endif
2588 46152182 pbrook
                    insn = get32((uint32_t *)(p_start - 4));
2589 46152182 pbrook
                    /* Calculate the size of the saved registers,
2590 46152182 pbrook
                       excluding pc.  */
2591 46152182 pbrook
                    for (i = 0; i < 15; i++) {
2592 46152182 pbrook
                        if (insn & (1 << i))
2593 46152182 pbrook
                            opcode += 4;
2594 46152182 pbrook
                    }
2595 46152182 pbrook
                    fprintf(outfile,
2596 46152182 pbrook
                            "    *(uint32_t *)gen_code_ptr = 0x%x;\n", opcode);
2597 46152182 pbrook
                }
2598 4a1a1707 ths
                arm_emit_ldr_info(relname, start_offset, outfile, p_start, p_end,
2599 ff1f20a3 bellard
                                  relocs, nb_relocs);
2600 ff1f20a3 bellard
2601 ff1f20a3 bellard
                for(i = 0, rel = relocs;i < nb_relocs; i++, rel++) {
2602 ff1f20a3 bellard
                if (rel->r_offset >= start_offset &&
2603 ff1f20a3 bellard
                    rel->r_offset < start_offset + copy_size) {
2604 ff1f20a3 bellard
                    sym_name = strtab + symtab[ELFW(R_SYM)(rel->r_info)].st_name;
2605 ff1f20a3 bellard
                    /* the compiler leave some unnecessary references to the code */
2606 ff1f20a3 bellard
                    if (sym_name[0] == '\0')
2607 ff1f20a3 bellard
                        continue;
2608 4a1a1707 ths
                    get_reloc_expr(relname, sizeof(relname), sym_name);
2609 ff1f20a3 bellard
                    type = ELF32_R_TYPE(rel->r_info);
2610 ff1f20a3 bellard
                    addend = get32((uint32_t *)(text + rel->r_offset));
2611 3442e896 pbrook
                    reloc_offset = rel->r_offset - start_offset;
2612 ff1f20a3 bellard
                    switch(type) {
2613 ff1f20a3 bellard
                    case R_ARM_ABS32:
2614 5fafdf24 ths
                        fprintf(outfile, "    *(uint32_t *)(gen_code_ptr + %d) = %s + %d;\n",
2615 4a1a1707 ths
                                reloc_offset, relname, addend);
2616 ff1f20a3 bellard
                        break;
2617 ff1f20a3 bellard
                    case R_ARM_PC24:
2618 46152182 pbrook
                    case R_ARM_JUMP24:
2619 46152182 pbrook
                    case R_ARM_CALL:
2620 5fafdf24 ths
                        fprintf(outfile, "    arm_reloc_pc24((uint32_t *)(gen_code_ptr + %d), 0x%x, %s);\n",
2621 4a1a1707 ths
                                reloc_offset, addend, relname);
2622 ff1f20a3 bellard
                        break;
2623 ff1f20a3 bellard
                    default:
2624 ff1f20a3 bellard
                        error("unsupported arm relocation (%d)", type);
2625 ff1f20a3 bellard
                    }
2626 ff1f20a3 bellard
                }
2627 ff1f20a3 bellard
                }
2628 38e584a0 bellard
            }
2629 38e584a0 bellard
#elif defined(HOST_M68K)
2630 38e584a0 bellard
            {
2631 4a1a1707 ths
                char relname[256];
2632 38e584a0 bellard
                int type;
2633 38e584a0 bellard
                int addend;
2634 3442e896 pbrook
                int reloc_offset;
2635 38e584a0 bellard
                Elf32_Sym *sym;
2636 38e584a0 bellard
                for(i = 0, rel = relocs;i < nb_relocs; i++, rel++) {
2637 38e584a0 bellard
                if (rel->r_offset >= start_offset &&
2638 38e584a0 bellard
                    rel->r_offset < start_offset + copy_size) {
2639 38e584a0 bellard
                    sym = &(symtab[ELFW(R_SYM)(rel->r_info)]);
2640 38e584a0 bellard
                    sym_name = strtab + symtab[ELFW(R_SYM)(rel->r_info)].st_name;
2641 4a1a1707 ths
                    get_reloc_expr(relname, sizeof(relname), sym_name);
2642 38e584a0 bellard
                    type = ELF32_R_TYPE(rel->r_info);
2643 38e584a0 bellard
                    addend = get32((uint32_t *)(text + rel->r_offset)) + rel->r_addend;
2644 3442e896 pbrook
                    reloc_offset = rel->r_offset - start_offset;
2645 38e584a0 bellard
                    switch(type) {
2646 38e584a0 bellard
                    case R_68K_32:
2647 38e584a0 bellard
                        fprintf(outfile, "    /* R_68K_32 RELOC, offset %x */\n", rel->r_offset) ;
2648 5fafdf24 ths
                        fprintf(outfile, "    *(uint32_t *)(gen_code_ptr + %d) = %s + %#x;\n",
2649 4a1a1707 ths
                                reloc_offset, relname, addend );
2650 38e584a0 bellard
                        break;
2651 38e584a0 bellard
                    case R_68K_PC32:
2652 38e584a0 bellard
                        fprintf(outfile, "    /* R_68K_PC32 RELOC, offset %x */\n", rel->r_offset);
2653 5fafdf24 ths
                        fprintf(outfile, "    *(uint32_t *)(gen_code_ptr + %d) = %s - (long)(gen_code_ptr + %#x) + %#x;\n",
2654 4a1a1707 ths
                                reloc_offset, relname, reloc_offset, /*sym->st_value+*/ addend);
2655 38e584a0 bellard
                        break;
2656 38e584a0 bellard
                    default:
2657 38e584a0 bellard
                        error("unsupported m68k relocation (%d)", type);
2658 38e584a0 bellard
                    }
2659 38e584a0 bellard
                }
2660 38e584a0 bellard
                }
2661 ff1f20a3 bellard
            }
2662 f54b3f92 aurel32
#elif defined(HOST_HPPA)
2663 f54b3f92 aurel32
            {
2664 f54b3f92 aurel32
                char relname[256];
2665 f54b3f92 aurel32
                int type, is_label;
2666 f54b3f92 aurel32
                int addend;
2667 f54b3f92 aurel32
                int reloc_offset;
2668 f54b3f92 aurel32
                for (i = 0, rel = relocs; i < nb_relocs; i++, rel++) {
2669 f54b3f92 aurel32
                if (rel->r_offset >= start_offset &&
2670 f54b3f92 aurel32
                    rel->r_offset < start_offset + copy_size) {
2671 f54b3f92 aurel32
                    sym_name = get_rel_sym_name(rel);
2672 f54b3f92 aurel32
                    sym_name = strtab + symtab[ELF32_R_SYM(rel->r_info)].st_name;
2673 f54b3f92 aurel32
                    is_label = get_reloc_expr(relname, sizeof(relname), sym_name);
2674 f54b3f92 aurel32
                    type = ELF32_R_TYPE(rel->r_info);
2675 f54b3f92 aurel32
                    addend = rel->r_addend;
2676 f54b3f92 aurel32
                    reloc_offset = rel->r_offset - start_offset;
2677 f54b3f92 aurel32
2678 f54b3f92 aurel32
                    if (is_label) {
2679 f54b3f92 aurel32
                        switch (type) {
2680 f54b3f92 aurel32
                        case R_PARISC_PCREL17F:
2681 f54b3f92 aurel32
                            fprintf(outfile,
2682 f54b3f92 aurel32
"    tcg_out_reloc(s, gen_code_ptr + %d, %d, %s, %d);\n",
2683 f54b3f92 aurel32
                                    reloc_offset, type, relname, addend);
2684 f54b3f92 aurel32
                            break;
2685 f54b3f92 aurel32
                        default:
2686 f54b3f92 aurel32
                            error("unsupported hppa label relocation (%d)", type);
2687 f54b3f92 aurel32
                        }
2688 f54b3f92 aurel32
                    } else {
2689 f54b3f92 aurel32
                        switch (type) {
2690 f54b3f92 aurel32
                        case R_PARISC_DIR21L:
2691 f54b3f92 aurel32
                            fprintf(outfile,
2692 f54b3f92 aurel32
"    hppa_patch21l((uint32_t *)(gen_code_ptr + %d), %s, %d);\n",
2693 f54b3f92 aurel32
                                    reloc_offset, relname, addend);
2694 f54b3f92 aurel32
                            break;
2695 f54b3f92 aurel32
                        case R_PARISC_DIR14R:
2696 f54b3f92 aurel32
                            fprintf(outfile,
2697 f54b3f92 aurel32
"    hppa_patch14r((uint32_t *)(gen_code_ptr + %d), %s, %d);\n",
2698 f54b3f92 aurel32
                                    reloc_offset, relname, addend);
2699 f54b3f92 aurel32
                            break;
2700 f54b3f92 aurel32
                        case R_PARISC_PCREL17F:
2701 f54b3f92 aurel32
                            if (strstart(sym_name, "__op_gen_label", NULL)) {
2702 f54b3f92 aurel32
                                fprintf(outfile,
2703 f54b3f92 aurel32
"    hppa_patch17f((uint32_t *)(gen_code_ptr + %d), %s, %d);\n",
2704 f54b3f92 aurel32
                                        reloc_offset, relname, addend);
2705 f54b3f92 aurel32
                            } else {
2706 f54b3f92 aurel32
                                fprintf(outfile,
2707 f54b3f92 aurel32
"    HPPA_RECORD_BRANCH(hppa_stubs, (uint32_t *)(gen_code_ptr + %d), %s);\n",
2708 f54b3f92 aurel32
                                        reloc_offset, relname);
2709 f54b3f92 aurel32
                            }
2710 f54b3f92 aurel32
                            break;
2711 f54b3f92 aurel32
                        case R_PARISC_DPREL21L:
2712 f54b3f92 aurel32
                            if (strstart(sym_name, "__op_param", &p))
2713 f54b3f92 aurel32
                                fprintf(outfile,
2714 f54b3f92 aurel32
"    hppa_load_imm21l((uint32_t *)(gen_code_ptr + %d), param%s, %d);\n",
2715 f54b3f92 aurel32
                                        reloc_offset, p, addend);
2716 f54b3f92 aurel32
                            else
2717 f54b3f92 aurel32
                                fprintf(outfile,
2718 f54b3f92 aurel32
"    hppa_patch21l_dprel((uint32_t *)(gen_code_ptr + %d), %s, %d);\n",
2719 f54b3f92 aurel32
                                        reloc_offset, relname, addend);
2720 f54b3f92 aurel32
                            break;
2721 f54b3f92 aurel32
                        case R_PARISC_DPREL14R:
2722 f54b3f92 aurel32
                            if (strstart(sym_name, "__op_param", &p))
2723 f54b3f92 aurel32
                                fprintf(outfile,
2724 f54b3f92 aurel32
"    hppa_load_imm14r((uint32_t *)(gen_code_ptr + %d), param%s, %d);\n",
2725 f54b3f92 aurel32
                                        reloc_offset, p, addend);
2726 f54b3f92 aurel32
                            else
2727 f54b3f92 aurel32
                                fprintf(outfile,
2728 f54b3f92 aurel32
"    hppa_patch14r_dprel((uint32_t *)(gen_code_ptr + %d), %s, %d);\n",
2729 f54b3f92 aurel32
                                        reloc_offset, relname, addend);
2730 f54b3f92 aurel32
                            break;
2731 f54b3f92 aurel32
                        default:
2732 f54b3f92 aurel32
                            error("unsupported hppa relocation (%d)", type);
2733 f54b3f92 aurel32
                        }
2734 f54b3f92 aurel32
                    }
2735 f54b3f92 aurel32
                }
2736 f54b3f92 aurel32
                }
2737 f54b3f92 aurel32
            }
2738 9617efe8 ths
#elif defined(HOST_MIPS) || defined(HOST_MIPS64)
2739 c4b89d18 ths
            {
2740 c4b89d18 ths
                for (i = 0, rel = relocs; i < nb_relocs; i++, rel++) {
2741 c4b89d18 ths
                    if (rel->r_offset >= start_offset && rel->r_offset < start_offset + copy_size) {
2742 4a1a1707 ths
                        char relname[256];
2743 c4b89d18 ths
                        int type;
2744 c4b89d18 ths
                        int addend;
2745 c4b89d18 ths
                        int reloc_offset;
2746 c4b89d18 ths
2747 c4b89d18 ths
                        sym_name = strtab + symtab[ELF32_R_SYM(rel->r_info)].st_name;
2748 c4b89d18 ths
                        /* the compiler leave some unnecessary references to the code */
2749 c4b89d18 ths
                        if (sym_name[0] == '\0')
2750 c4b89d18 ths
                            continue;
2751 4a1a1707 ths
                        get_reloc_expr(relname, sizeof(relname), sym_name);
2752 c4b89d18 ths
                        type = ELF32_R_TYPE(rel->r_info);
2753 c4b89d18 ths
                        addend = get32((uint32_t *)(text + rel->r_offset));
2754 c4b89d18 ths
                        reloc_offset = rel->r_offset - start_offset;
2755 c4b89d18 ths
                        switch (type) {
2756 9617efe8 ths
                        case R_MIPS_26:
2757 9617efe8 ths
                            fprintf(outfile, "    /* R_MIPS_26 RELOC, offset 0x%x, name %s */\n",
2758 9617efe8 ths
                                    rel->r_offset, sym_name);
2759 9617efe8 ths
                            fprintf(outfile,
2760 9617efe8 ths
                                    "    *(uint32_t *)(gen_code_ptr + 0x%x) = "
2761 9617efe8 ths
                                    "(0x%x & ~0x3fffff) "
2762 9617efe8 ths
                                    "| ((0x%x + ((%s - (*(uint32_t *)(gen_code_ptr + 0x%x))) >> 2)) "
2763 9617efe8 ths
                                    "   & 0x3fffff);\n",
2764 4a1a1707 ths
                                    reloc_offset, addend, addend, relname, reloc_offset);
2765 9617efe8 ths
                            break;
2766 c4b89d18 ths
                        case R_MIPS_HI16:
2767 c4b89d18 ths
                            fprintf(outfile, "    /* R_MIPS_HI16 RELOC, offset 0x%x, name %s */\n",
2768 c4b89d18 ths
                                    rel->r_offset, sym_name);
2769 c4b89d18 ths
                            fprintf(outfile,
2770 c4b89d18 ths
                                    "    *(uint32_t *)(gen_code_ptr + 0x%x) = "
2771 c4b89d18 ths
                                    "((*(uint32_t *)(gen_code_ptr + 0x%x)) "
2772 c4b89d18 ths
                                    " & ~0xffff) "
2773 c4b89d18 ths
                                    " | (((%s - 0x8000) >> 16) & 0xffff);\n",
2774 4a1a1707 ths
                                    reloc_offset, reloc_offset, relname);
2775 c4b89d18 ths
                            break;
2776 c4b89d18 ths
                        case R_MIPS_LO16:
2777 c4b89d18 ths
                            fprintf(outfile, "    /* R_MIPS_LO16 RELOC, offset 0x%x, name %s */\n",
2778 c4b89d18 ths
                                    rel->r_offset, sym_name);
2779 c4b89d18 ths
                            fprintf(outfile,
2780 c4b89d18 ths
                                    "    *(uint32_t *)(gen_code_ptr + 0x%x) = "
2781 c4b89d18 ths
                                    "((*(uint32_t *)(gen_code_ptr + 0x%x)) "
2782 c4b89d18 ths
                                    " & ~0xffff) "
2783 c4b89d18 ths
                                    " | (%s & 0xffff);\n",
2784 4a1a1707 ths
                                    reloc_offset, reloc_offset, relname);
2785 c4b89d18 ths
                            break;
2786 c4b89d18 ths
                        case R_MIPS_PC16:
2787 c4b89d18 ths
                            fprintf(outfile, "    /* R_MIPS_PC16 RELOC, offset 0x%x, name %s */\n",
2788 c4b89d18 ths
                                    rel->r_offset, sym_name);
2789 c4b89d18 ths
                            fprintf(outfile,
2790 c4b89d18 ths
                                    "    *(uint32_t *)(gen_code_ptr + 0x%x) = "
2791 c4b89d18 ths
                                    "(0x%x & ~0xffff) "
2792 c4b89d18 ths
                                    "| ((0x%x + ((%s - (*(uint32_t *)(gen_code_ptr + 0x%x))) >> 2)) "
2793 c4b89d18 ths
                                    "   & 0xffff);\n",
2794 4a1a1707 ths
                                    reloc_offset, addend, addend, relname, reloc_offset);
2795 c4b89d18 ths
                            break;
2796 c4b89d18 ths
                        case R_MIPS_GOT16:
2797 c4b89d18 ths
                        case R_MIPS_CALL16:
2798 c4b89d18 ths
                            fprintf(outfile, "    /* R_MIPS_GOT16 RELOC, offset 0x%x, name %s */\n",
2799 c4b89d18 ths
                                    rel->r_offset, sym_name);
2800 c4b89d18 ths
                            fprintf(outfile,
2801 c4b89d18 ths
                                    "    *(uint32_t *)(gen_code_ptr + 0x%x) = "
2802 c4b89d18 ths
                                    "((*(uint32_t *)(gen_code_ptr + 0x%x)) "
2803 c4b89d18 ths
                                    " & ~0xffff) "
2804 c4b89d18 ths
                                    " | (((%s - 0x8000) >> 16) & 0xffff);\n",
2805 4a1a1707 ths
                                    reloc_offset, reloc_offset, relname);
2806 c4b89d18 ths
                            break;
2807 c4b89d18 ths
                        default:
2808 c4b89d18 ths
                            error("unsupported MIPS relocation (%d)", type);
2809 c4b89d18 ths
                        }
2810 c4b89d18 ths
                    }
2811 c4b89d18 ths
                }
2812 c4b89d18 ths
            }
2813 ce11fedc bellard
#else
2814 ce11fedc bellard
#error unsupported CPU
2815 ce11fedc bellard
#endif
2816 dc99065b bellard
        fprintf(outfile, "    gen_code_ptr += %d;\n", copy_size);
2817 dc99065b bellard
        fprintf(outfile, "}\n");
2818 dc99065b bellard
        fprintf(outfile, "break;\n\n");
2819 dc99065b bellard
    } else {
2820 dc99065b bellard
        fprintf(outfile, "static inline void gen_%s(", name);
2821 dc99065b bellard
        if (nb_args == 0) {
2822 dc99065b bellard
            fprintf(outfile, "void");
2823 dc99065b bellard
        } else {
2824 dc99065b bellard
            for(i = 0; i < nb_args; i++) {
2825 dc99065b bellard
                if (i != 0)
2826 dc99065b bellard
                    fprintf(outfile, ", ");
2827 dc99065b bellard
                fprintf(outfile, "long param%d", i + 1);
2828 367e86e8 bellard
            }
2829 367e86e8 bellard
        }
2830 dc99065b bellard
        fprintf(outfile, ")\n");
2831 dc99065b bellard
        fprintf(outfile, "{\n");
2832 dc99065b bellard
        for(i = 0; i < nb_args; i++) {
2833 dc99065b bellard
            fprintf(outfile, "    *gen_opparam_ptr++ = param%d;\n", i + 1);
2834 dc99065b bellard
        }
2835 dc99065b bellard
        fprintf(outfile, "    *gen_opc_ptr++ = INDEX_%s;\n", name);
2836 dc99065b bellard
        fprintf(outfile, "}\n\n");
2837 367e86e8 bellard
    }
2838 367e86e8 bellard
}
2839 367e86e8 bellard
2840 67b915a5 bellard
int gen_file(FILE *outfile, int out_type)
2841 367e86e8 bellard
{
2842 67b915a5 bellard
    int i;
2843 67b915a5 bellard
    EXE_SYM *sym;
2844 367e86e8 bellard
2845 d219f7e7 bellard
    if (out_type == OUT_INDEX_OP) {
2846 dc99065b bellard
        for(i = 0, sym = symtab; i < nb_syms; i++, sym++) {
2847 82eec0a1 bellard
            const char *name;
2848 67b915a5 bellard
            name = get_sym_name(sym);
2849 82eec0a1 bellard
            if (strstart(name, OP_PREFIX, NULL)) {
2850 67b915a5 bellard
                gen_code(name, sym->st_value, sym->st_size, outfile, 2);
2851 dc99065b bellard
            }
2852 dc99065b bellard
        }
2853 d219f7e7 bellard
    } else if (out_type == OUT_GEN_OP) {
2854 d219f7e7 bellard
        /* generate gen_xxx functions */
2855 d219f7e7 bellard
        for(i = 0, sym = symtab; i < nb_syms; i++, sym++) {
2856 d219f7e7 bellard
            const char *name;
2857 67b915a5 bellard
            name = get_sym_name(sym);
2858 d219f7e7 bellard
            if (strstart(name, OP_PREFIX, NULL)) {
2859 82eec0a1 bellard
#if defined(CONFIG_FORMAT_ELF) || defined(CONFIG_FORMAT_COFF)
2860 67b915a5 bellard
                if (sym->st_shndx != text_shndx)
2861 d219f7e7 bellard
                    error("invalid section for opcode (0x%x)", sym->st_shndx);
2862 82eec0a1 bellard
#endif
2863 67b915a5 bellard
                gen_code(name, sym->st_value, sym->st_size, outfile, 0);
2864 d219f7e7 bellard
            }
2865 d219f7e7 bellard
        }
2866 3b46e624 ths
2867 dc99065b bellard
    } else {
2868 dc99065b bellard
        /* generate big code generation switch */
2869 46152182 pbrook
2870 46152182 pbrook
#ifdef HOST_ARM
2871 57fec1fe bellard
#error broken
2872 46152182 pbrook
        /* We need to know the size of all the ops so we can figure out when
2873 46152182 pbrook
           to emit constant pools.  This must be consistent with opc.h.  */
2874 46152182 pbrook
fprintf(outfile,
2875 46152182 pbrook
"static const uint32_t arm_opc_size[] = {\n"
2876 46152182 pbrook
"  0,\n" /* end */
2877 46152182 pbrook
"  0,\n" /* nop */
2878 46152182 pbrook
"  0,\n" /* nop1 */
2879 46152182 pbrook
"  0,\n" /* nop2 */
2880 46152182 pbrook
"  0,\n"); /* nop3 */
2881 46152182 pbrook
        for(i = 0, sym = symtab; i < nb_syms; i++, sym++) {
2882 46152182 pbrook
            const char *name;
2883 46152182 pbrook
            name = get_sym_name(sym);
2884 46152182 pbrook
            if (strstart(name, OP_PREFIX, NULL)) {
2885 46152182 pbrook
                fprintf(outfile, "  %d,\n", sym->st_size);
2886 46152182 pbrook
            }
2887 46152182 pbrook
        }
2888 46152182 pbrook
fprintf(outfile,
2889 46152182 pbrook
"};\n");
2890 46152182 pbrook
#endif
2891 46152182 pbrook
2892 ff1f20a3 bellard
#ifdef HOST_ARM
2893 57fec1fe bellard
#error broken
2894 46152182 pbrook
/* Arm is tricky because it uses constant pools for loading immediate values.
2895 46152182 pbrook
   We assume (and require) each function is code followed by a constant pool.
2896 46152182 pbrook
   All the ops are small so this should be ok.  For each op we figure
2897 46152182 pbrook
   out how much "spare" range we have in the load instructions.  This allows
2898 46152182 pbrook
   us to insert subsequent ops in between the op and the constant pool,
2899 46152182 pbrook
   eliminating the neeed to jump around the pool.
2900 46152182 pbrook

2901 46152182 pbrook
   We currently generate:
2902 3b46e624 ths

2903 46152182 pbrook
   [ For this example we assume merging would move op1_pool out of range.
2904 46152182 pbrook
     In practice we should be able to combine many ops before the offset
2905 46152182 pbrook
     limits are reached. ]
2906 46152182 pbrook
   op1_code;
2907 46152182 pbrook
   op2_code;
2908 46152182 pbrook
   goto op3;
2909 46152182 pbrook
   op2_pool;
2910 46152182 pbrook
   op1_pool;
2911 46152182 pbrook
op3:
2912 46152182 pbrook
   op3_code;
2913 46152182 pbrook
   ret;
2914 46152182 pbrook
   op3_pool;
2915 46152182 pbrook

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