Statistics
| Branch: | Revision:

root / dyngen.c @ 36bb244b

History | View | Annotate | Download (89 kB)

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

2587 46152182 pbrook
   We currently generate:
2588 46152182 pbrook
   
2589 46152182 pbrook
   [ For this example we assume merging would move op1_pool out of range.
2590 46152182 pbrook
     In practice we should be able to combine many ops before the offset
2591 46152182 pbrook
     limits are reached. ]
2592 46152182 pbrook
   op1_code;
2593 46152182 pbrook
   op2_code;
2594 46152182 pbrook
   goto op3;
2595 46152182 pbrook
   op2_pool;
2596 46152182 pbrook
   op1_pool;
2597 46152182 pbrook
op3:
2598 46152182 pbrook
   op3_code;
2599 46152182 pbrook
   ret;
2600 46152182 pbrook
   op3_pool;
2601 46152182 pbrook

2602 46152182 pbrook
   Ideally we'd put op1_pool before op2_pool, but that requires two passes.
2603 46152182 pbrook
 */
2604 ff1f20a3 bellard
fprintf(outfile,
2605 ff1f20a3 bellard
"    uint8_t *last_gen_code_ptr = gen_code_buf;\n"
2606 ff1f20a3 bellard
"    LDREntry *arm_ldr_ptr = arm_ldr_table;\n"
2607 46152182 pbrook
"    uint32_t *arm_data_ptr = arm_data_table + ARM_LDR_TABLE_SIZE;\n"
2608 46152182 pbrook
/* Initialise the parmissible pool offset to an arbitary large value.  */
2609 46152182 pbrook
"    uint8_t *arm_pool_ptr = gen_code_buf + 0x1000000;\n");
2610 ff1f20a3 bellard
#endif
2611 b8076a74 bellard
#ifdef HOST_IA64
2612 b8076a74 bellard
    {
2613 b8076a74 bellard
        long addend, not_first = 0;
2614 b8076a74 bellard
        unsigned long sym_idx;
2615 b8076a74 bellard
        int index, max_index;
2616 b8076a74 bellard
        const char *sym_name;
2617 b8076a74 bellard
        EXE_RELOC *rel;
2618 b8076a74 bellard
2619 b8076a74 bellard
        max_index = -1;
2620 b8076a74 bellard
        for (i = 0, rel = relocs;i < nb_relocs; i++, rel++) {
2621 b8076a74 bellard
            sym_idx = ELF64_R_SYM(rel->r_info);
2622 b8076a74 bellard
            sym_name = (strtab + symtab[sym_idx].st_name);
2623 b8076a74 bellard
            if (strstart(sym_name, "__op_gen_label", NULL))
2624 b8076a74 bellard
                continue;
2625 b8076a74 bellard
            if (ELF64_R_TYPE(rel->r_info) != R_IA64_PCREL21B)
2626 b8076a74 bellard
                continue;
2627 b8076a74 bellard
2628 b8076a74 bellard
            addend = rel->r_addend;
2629 b8076a74 bellard
            index = get_plt_index(sym_name, addend);
2630 b8076a74 bellard
            if (index <= max_index)
2631 b8076a74 bellard
                continue;
2632 b8076a74 bellard
            max_index = index;
2633 b8076a74 bellard
            fprintf(outfile, "    extern void %s(void);\n", sym_name);
2634 b8076a74 bellard
        }
2635 b8076a74 bellard
2636 b8076a74 bellard
        fprintf(outfile,
2637 b8076a74 bellard
                "    struct ia64_fixup *plt_fixes = NULL, "
2638 b8076a74 bellard
                "*ltoff_fixes = NULL;\n"
2639 b8076a74 bellard
                "    static long plt_target[] = {\n\t");
2640 b8076a74 bellard
2641 b8076a74 bellard
        max_index = -1;
2642 b8076a74 bellard
        for (i = 0, rel = relocs;i < nb_relocs; i++, rel++) {
2643 b8076a74 bellard
            sym_idx = ELF64_R_SYM(rel->r_info);
2644 b8076a74 bellard
            sym_name = (strtab + symtab[sym_idx].st_name);
2645 b8076a74 bellard
            if (strstart(sym_name, "__op_gen_label", NULL))
2646 b8076a74 bellard
                continue;
2647 b8076a74 bellard
            if (ELF64_R_TYPE(rel->r_info) != R_IA64_PCREL21B)
2648 b8076a74 bellard
                continue;
2649 b8076a74 bellard
2650 b8076a74 bellard
            addend = rel->r_addend;
2651 b8076a74 bellard
            index = get_plt_index(sym_name, addend);
2652 b8076a74 bellard
            if (index <= max_index)
2653 b8076a74 bellard
                continue;
2654 b8076a74 bellard
            max_index = index;
2655 b8076a74 bellard
2656 b8076a74 bellard
            if (not_first)
2657 b8076a74 bellard
                fprintf(outfile, ",\n\t");
2658 b8076a74 bellard
            not_first = 1;
2659 b8076a74 bellard
            if (addend)
2660 b8076a74 bellard
                fprintf(outfile, "(long) &%s + %ld", sym_name, addend);
2661 b8076a74 bellard
            else
2662 b8076a74 bellard
                fprintf(outfile, "(long) &%s", sym_name);
2663 b8076a74 bellard
        }
2664 b8076a74 bellard
        fprintf(outfile, "\n    };\n"
2665 b8076a74 bellard
            "    unsigned int plt_offset[%u] = { 0 };\n", max_index + 1);
2666 b8076a74 bellard
    }
2667 b8076a74 bellard
#endif
2668 ff1f20a3 bellard
2669 ff1f20a3 bellard
fprintf(outfile,
2670 ff1f20a3 bellard
"\n"
2671 dc99065b bellard
"    gen_code_ptr = gen_code_buf;\n"
2672 dc99065b bellard
"    opc_ptr = opc_buf;\n"
2673 ae228531 bellard
"    opparam_ptr = opparam_buf;\n");
2674 ae228531 bellard
2675 ae228531 bellard
        /* Generate prologue, if needed. */ 
2676 ae228531 bellard
2677 ae228531 bellard
fprintf(outfile,
2678 46152182 pbrook
"    for(;;) {\n");
2679 46152182 pbrook
2680 46152182 pbrook
#ifdef HOST_ARM
2681 46152182 pbrook
/* Generate constant pool if needed */
2682 46152182 pbrook
fprintf(outfile,
2683 46152182 pbrook
"            if (gen_code_ptr + arm_opc_size[*opc_ptr] >= arm_pool_ptr) {\n"
2684 46152182 pbrook
"                gen_code_ptr = arm_flush_ldr(gen_code_ptr, arm_ldr_table, "
2685 46152182 pbrook
"arm_ldr_ptr, arm_data_ptr, arm_data_table + ARM_LDR_TABLE_SIZE, 1);\n"
2686 46152182 pbrook
"                last_gen_code_ptr = gen_code_ptr;\n"
2687 46152182 pbrook
"                arm_ldr_ptr = arm_ldr_table;\n"
2688 46152182 pbrook
"                arm_data_ptr = arm_data_table + ARM_LDR_TABLE_SIZE;\n"
2689 46152182 pbrook
"                arm_pool_ptr = gen_code_ptr + 0x1000000;\n"
2690 46152182 pbrook
"            }\n");
2691 46152182 pbrook
#endif
2692 46152182 pbrook
2693 46152182 pbrook
fprintf(outfile,
2694 46152182 pbrook
"        switch(*opc_ptr++) {\n");
2695 367e86e8 bellard
2696 dc99065b bellard
        for(i = 0, sym = symtab; i < nb_syms; i++, sym++) {
2697 dc99065b bellard
            const char *name;
2698 67b915a5 bellard
            name = get_sym_name(sym);
2699 dc99065b bellard
            if (strstart(name, OP_PREFIX, NULL)) {
2700 367e86e8 bellard
#if 0
2701 dc99065b bellard
                printf("%4d: %s pos=0x%08x len=%d\n", 
2702 dc99065b bellard
                       i, name, sym->st_value, sym->st_size);
2703 367e86e8 bellard
#endif
2704 82eec0a1 bellard
#if defined(CONFIG_FORMAT_ELF) || defined(CONFIG_FORMAT_COFF)
2705 67b915a5 bellard
                if (sym->st_shndx != text_shndx)
2706 dc99065b bellard
                    error("invalid section for opcode (0x%x)", sym->st_shndx);
2707 82eec0a1 bellard
#endif
2708 67b915a5 bellard
                gen_code(name, sym->st_value, sym->st_size, outfile, 1);
2709 dc99065b bellard
            }
2710 dc99065b bellard
        }
2711 dc99065b bellard
2712 dc99065b bellard
fprintf(outfile,
2713 8ef9a8ec bellard
"        case INDEX_op_nop:\n"
2714 8ef9a8ec bellard
"            break;\n"
2715 8ef9a8ec bellard
"        case INDEX_op_nop1:\n"
2716 8ef9a8ec bellard
"            opparam_ptr++;\n"
2717 8ef9a8ec bellard
"            break;\n"
2718 8ef9a8ec bellard
"        case INDEX_op_nop2:\n"
2719 8ef9a8ec bellard
"            opparam_ptr += 2;\n"
2720 8ef9a8ec bellard
"            break;\n"
2721 8ef9a8ec bellard
"        case INDEX_op_nop3:\n"
2722 8ef9a8ec bellard
"            opparam_ptr += 3;\n"
2723 8ef9a8ec bellard
"            break;\n"
2724 dc99065b bellard
"        default:\n"
2725 dc99065b bellard
"            goto the_end;\n"
2726 ff1f20a3 bellard
"        }\n");
2727 ff1f20a3 bellard
2728 ff1f20a3 bellard
2729 ff1f20a3 bellard
fprintf(outfile,
2730 dc99065b bellard
"    }\n"
2731 dc99065b bellard
" the_end:\n"
2732 dc99065b bellard
);
2733 b8076a74 bellard
#ifdef HOST_IA64
2734 b8076a74 bellard
    fprintf(outfile,
2735 fd4a43e4 bellard
            "    {\n"
2736 fd4a43e4 bellard
            "      extern char code_gen_buffer[];\n"
2737 fd4a43e4 bellard
            "      ia64_apply_fixes(&gen_code_ptr, ltoff_fixes, "
2738 b8076a74 bellard
            "(uint64_t) code_gen_buffer + 2*(1<<20), plt_fixes,\n\t\t\t"
2739 b8076a74 bellard
            "sizeof(plt_target)/sizeof(plt_target[0]),\n\t\t\t"
2740 fd4a43e4 bellard
            "plt_target, plt_offset);\n    }\n");
2741 b8076a74 bellard
#endif
2742 dc99065b bellard
2743 9621339d bellard
/* generate some code patching */ 
2744 9621339d bellard
#ifdef HOST_ARM
2745 46152182 pbrook
fprintf(outfile,
2746 46152182 pbrook
"if (arm_data_ptr != arm_data_table + ARM_LDR_TABLE_SIZE)\n"
2747 46152182 pbrook
"    gen_code_ptr = arm_flush_ldr(gen_code_ptr, arm_ldr_table, "
2748 46152182 pbrook
"arm_ldr_ptr, arm_data_ptr, arm_data_table + ARM_LDR_TABLE_SIZE, 0);\n");
2749 9621339d bellard
#endif
2750 d219f7e7 bellard
    /* flush instruction cache */
2751 d219f7e7 bellard
    fprintf(outfile, "flush_icache_range((unsigned long)gen_code_buf, (unsigned long)gen_code_ptr);\n");
2752 d219f7e7 bellard
2753 dc99065b bellard
    fprintf(outfile, "return gen_code_ptr -  gen_code_buf;\n");
2754 dc99065b bellard
    fprintf(outfile, "}\n\n");
2755 dc99065b bellard
2756 367e86e8 bellard
    }
2757 367e86e8 bellard
2758 367e86e8 bellard
    return 0;
2759 367e86e8 bellard
}
2760 367e86e8 bellard
2761 367e86e8 bellard
void usage(void)
2762 367e86e8 bellard
{
2763 367e86e8 bellard
    printf("dyngen (c) 2003 Fabrice Bellard\n"
2764 dc99065b bellard
           "usage: dyngen [-o outfile] [-c] objfile\n"
2765 dc99065b bellard
           "Generate a dynamic code generator from an object file\n"
2766 dc99065b bellard
           "-c     output enum of operations\n"
2767 d219f7e7 bellard
           "-g     output gen_op_xx() functions\n"
2768 dc99065b bellard
           );
2769 367e86e8 bellard
    exit(1);
2770 367e86e8 bellard
}
2771 367e86e8 bellard
2772 367e86e8 bellard
int main(int argc, char **argv)
2773 367e86e8 bellard
{
2774 d219f7e7 bellard
    int c, out_type;
2775 367e86e8 bellard
    const char *filename, *outfilename;
2776 367e86e8 bellard
    FILE *outfile;
2777 367e86e8 bellard
2778 367e86e8 bellard
    outfilename = "out.c";
2779 d219f7e7 bellard
    out_type = OUT_CODE;
2780 367e86e8 bellard
    for(;;) {
2781 d219f7e7 bellard
        c = getopt(argc, argv, "ho:cg");
2782 367e86e8 bellard
        if (c == -1)
2783 367e86e8 bellard
            break;
2784 367e86e8 bellard
        switch(c) {
2785 367e86e8 bellard
        case 'h':
2786 367e86e8 bellard
            usage();
2787 367e86e8 bellard
            break;
2788 367e86e8 bellard
        case 'o':
2789 367e86e8 bellard
            outfilename = optarg;
2790 367e86e8 bellard
            break;
2791 dc99065b bellard
        case 'c':
2792 d219f7e7 bellard
            out_type = OUT_INDEX_OP;
2793 d219f7e7 bellard
            break;
2794 d219f7e7 bellard
        case 'g':
2795 d219f7e7 bellard
            out_type = OUT_GEN_OP;
2796 dc99065b bellard
            break;
2797 367e86e8 bellard
        }
2798 367e86e8 bellard
    }
2799 367e86e8 bellard
    if (optind >= argc)
2800 367e86e8 bellard
        usage();
2801 367e86e8 bellard
    filename = argv[optind];
2802 367e86e8 bellard
    outfile = fopen(outfilename, "w");
2803 367e86e8 bellard
    if (!outfile)
2804 367e86e8 bellard
        error("could not open '%s'", outfilename);
2805 67b915a5 bellard
2806 67b915a5 bellard
    load_object(filename);
2807 67b915a5 bellard
    gen_file(outfile, out_type);
2808 367e86e8 bellard
    fclose(outfile);
2809 367e86e8 bellard
    return 0;
2810 367e86e8 bellard
}