Statistics
| Branch: | Revision:

root / dyngen.c @ 8d7b0fbb

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

2548 46152182 pbrook
   We currently generate:
2549 46152182 pbrook
   
2550 46152182 pbrook
   [ For this example we assume merging would move op1_pool out of range.
2551 46152182 pbrook
     In practice we should be able to combine many ops before the offset
2552 46152182 pbrook
     limits are reached. ]
2553 46152182 pbrook
   op1_code;
2554 46152182 pbrook
   op2_code;
2555 46152182 pbrook
   goto op3;
2556 46152182 pbrook
   op2_pool;
2557 46152182 pbrook
   op1_pool;
2558 46152182 pbrook
op3:
2559 46152182 pbrook
   op3_code;
2560 46152182 pbrook
   ret;
2561 46152182 pbrook
   op3_pool;
2562 46152182 pbrook

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