Commit ce11fedc6ecb6c6bedcff28e2a5ab3a864267245
1 parent
43d4145a
64 bit support
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@76 c046a42c-6fe2-441c-8c8c-71466251a162
Showing
1 changed file
with
124 additions
and
145 deletions
dyngen.c
| @@ -22,25 +22,62 @@ | @@ -22,25 +22,62 @@ | ||
| 22 | #include <string.h> | 22 | #include <string.h> |
| 23 | #include <stdarg.h> | 23 | #include <stdarg.h> |
| 24 | #include <inttypes.h> | 24 | #include <inttypes.h> |
| 25 | -#include <elf.h> | ||
| 26 | #include <unistd.h> | 25 | #include <unistd.h> |
| 27 | #include <fcntl.h> | 26 | #include <fcntl.h> |
| 28 | 27 | ||
| 29 | -#include "thunk.h" | 28 | +#include "config.h" |
| 29 | + | ||
| 30 | +/* elf format definitions. We use these macros to test the CPU to | ||
| 31 | + allow cross compilation (this tool must be ran on the build | ||
| 32 | + platform) */ | ||
| 33 | +#if defined(HOST_I386) | ||
| 34 | + | ||
| 35 | +#define ELF_CLASS ELFCLASS32 | ||
| 36 | +#define ELF_ARCH EM_386 | ||
| 37 | +#define elf_check_arch(x) ( ((x) == EM_386) || ((x) == EM_486) ) | ||
| 38 | +#undef ELF_USES_RELOCA | ||
| 39 | + | ||
| 40 | +#elif defined(HOST_PPC) | ||
| 41 | + | ||
| 42 | +#define ELF_CLASS ELFCLASS32 | ||
| 43 | +#define ELF_ARCH EM_PPC | ||
| 44 | +#define elf_check_arch(x) ((x) == EM_PPC) | ||
| 45 | +#define ELF_USES_RELOCA | ||
| 46 | + | ||
| 47 | +#elif defined(HOST_S390) | ||
| 48 | + | ||
| 49 | +#define ELF_CLASS ELFCLASS32 | ||
| 50 | +#define ELF_ARCH EM_S390 | ||
| 51 | +#define elf_check_arch(x) ((x) == EM_S390) | ||
| 52 | +#define ELF_USES_RELOCA | ||
| 30 | 53 | ||
| 31 | -/* temporary fix to make it compile with old elf headers (XXX: use | ||
| 32 | - included elf.h in all cases) */ | ||
| 33 | -#ifndef EM_390 | ||
| 34 | -#define EM_S390 22 /* IBM S390 */ | ||
| 35 | -#define R_390_8 1 /* Direct 8 bit. */ | ||
| 36 | -#define R_390_16 3 /* Direct 16 bit. */ | ||
| 37 | -#define R_390_32 4 /* Direct 32 bit. */ | 54 | +#elif defined(HOST_ALPHA) |
| 55 | + | ||
| 56 | +#define ELF_CLASS ELFCLASS64 | ||
| 57 | +#define ELF_ARCH EM_ALPHA | ||
| 58 | +#define elf_check_arch(x) ((x) == EM_ALPHA) | ||
| 59 | +#define ELF_USES_RELOCA | ||
| 60 | + | ||
| 61 | +#else | ||
| 62 | +#error unsupported CPU - please update the code | ||
| 63 | +#endif | ||
| 64 | + | ||
| 65 | +#if ELF_CLASS == ELFCLASS32 | ||
| 66 | +typedef int32_t host_long; | ||
| 67 | +typedef uint32_t host_ulong; | ||
| 68 | +#else | ||
| 69 | +typedef int64_t host_long; | ||
| 70 | +typedef uint64_t host_ulong; | ||
| 38 | #endif | 71 | #endif |
| 39 | 72 | ||
| 73 | +#include "elf.h" | ||
| 74 | + | ||
| 75 | +#include "thunk.h" | ||
| 76 | + | ||
| 40 | /* all dynamically generated functions begin with this code */ | 77 | /* all dynamically generated functions begin with this code */ |
| 41 | #define OP_PREFIX "op_" | 78 | #define OP_PREFIX "op_" |
| 42 | 79 | ||
| 43 | -int elf_must_swap(Elf32_Ehdr *h) | 80 | +int elf_must_swap(struct elfhdr *h) |
| 44 | { | 81 | { |
| 45 | union { | 82 | union { |
| 46 | uint32_t i; | 83 | uint32_t i; |
| @@ -62,19 +99,25 @@ void swab32s(uint32_t *p) | @@ -62,19 +99,25 @@ void swab32s(uint32_t *p) | ||
| 62 | *p = bswap32(*p); | 99 | *p = bswap32(*p); |
| 63 | } | 100 | } |
| 64 | 101 | ||
| 65 | -void swab64s(uint32_t *p) | 102 | +void swab64s(uint64_t *p) |
| 66 | { | 103 | { |
| 67 | *p = bswap64(*p); | 104 | *p = bswap64(*p); |
| 68 | } | 105 | } |
| 69 | 106 | ||
| 70 | -void elf_swap_ehdr(Elf32_Ehdr *h) | 107 | +#if ELF_CLASS == ELFCLASS32 |
| 108 | +#define swabls(x) swab32s(x) | ||
| 109 | +#else | ||
| 110 | +#define swabls(x) swab64s(x) | ||
| 111 | +#endif | ||
| 112 | + | ||
| 113 | +void elf_swap_ehdr(struct elfhdr *h) | ||
| 71 | { | 114 | { |
| 72 | swab16s(&h->e_type); /* Object file type */ | 115 | swab16s(&h->e_type); /* Object file type */ |
| 73 | swab16s(&h-> e_machine); /* Architecture */ | 116 | swab16s(&h-> e_machine); /* Architecture */ |
| 74 | swab32s(&h-> e_version); /* Object file version */ | 117 | swab32s(&h-> e_version); /* Object file version */ |
| 75 | - swab32s(&h-> e_entry); /* Entry point virtual address */ | ||
| 76 | - swab32s(&h-> e_phoff); /* Program header table file offset */ | ||
| 77 | - swab32s(&h-> e_shoff); /* Section header table file offset */ | 118 | + swabls(&h-> e_entry); /* Entry point virtual address */ |
| 119 | + swabls(&h-> e_phoff); /* Program header table file offset */ | ||
| 120 | + swabls(&h-> e_shoff); /* Section header table file offset */ | ||
| 78 | swab32s(&h-> e_flags); /* Processor-specific flags */ | 121 | swab32s(&h-> e_flags); /* Processor-specific flags */ |
| 79 | swab16s(&h-> e_ehsize); /* ELF header size in bytes */ | 122 | swab16s(&h-> e_ehsize); /* ELF header size in bytes */ |
| 80 | swab16s(&h-> e_phentsize); /* Program header table entry size */ | 123 | swab16s(&h-> e_phentsize); /* Program header table entry size */ |
| @@ -84,34 +127,33 @@ void elf_swap_ehdr(Elf32_Ehdr *h) | @@ -84,34 +127,33 @@ void elf_swap_ehdr(Elf32_Ehdr *h) | ||
| 84 | swab16s(&h-> e_shstrndx); /* Section header string table index */ | 127 | swab16s(&h-> e_shstrndx); /* Section header string table index */ |
| 85 | } | 128 | } |
| 86 | 129 | ||
| 87 | -void elf_swap_shdr(Elf32_Shdr *h) | 130 | +void elf_swap_shdr(struct elf_shdr *h) |
| 88 | { | 131 | { |
| 89 | swab32s(&h-> sh_name); /* Section name (string tbl index) */ | 132 | swab32s(&h-> sh_name); /* Section name (string tbl index) */ |
| 90 | swab32s(&h-> sh_type); /* Section type */ | 133 | swab32s(&h-> sh_type); /* Section type */ |
| 91 | - swab32s(&h-> sh_flags); /* Section flags */ | ||
| 92 | - swab32s(&h-> sh_addr); /* Section virtual addr at execution */ | ||
| 93 | - swab32s(&h-> sh_offset); /* Section file offset */ | ||
| 94 | - swab32s(&h-> sh_size); /* Section size in bytes */ | 134 | + swabls(&h-> sh_flags); /* Section flags */ |
| 135 | + swabls(&h-> sh_addr); /* Section virtual addr at execution */ | ||
| 136 | + swabls(&h-> sh_offset); /* Section file offset */ | ||
| 137 | + swabls(&h-> sh_size); /* Section size in bytes */ | ||
| 95 | swab32s(&h-> sh_link); /* Link to another section */ | 138 | swab32s(&h-> sh_link); /* Link to another section */ |
| 96 | swab32s(&h-> sh_info); /* Additional section information */ | 139 | swab32s(&h-> sh_info); /* Additional section information */ |
| 97 | - swab32s(&h-> sh_addralign); /* Section alignment */ | ||
| 98 | - swab32s(&h-> sh_entsize); /* Entry size if section holds table */ | 140 | + swabls(&h-> sh_addralign); /* Section alignment */ |
| 141 | + swabls(&h-> sh_entsize); /* Entry size if section holds table */ | ||
| 99 | } | 142 | } |
| 100 | 143 | ||
| 101 | -void elf_swap_phdr(Elf32_Phdr *h) | 144 | +void elf_swap_phdr(struct elf_phdr *h) |
| 102 | { | 145 | { |
| 103 | swab32s(&h->p_type); /* Segment type */ | 146 | swab32s(&h->p_type); /* Segment type */ |
| 104 | - swab32s(&h->p_offset); /* Segment file offset */ | ||
| 105 | - swab32s(&h->p_vaddr); /* Segment virtual address */ | ||
| 106 | - swab32s(&h->p_paddr); /* Segment physical address */ | ||
| 107 | - swab32s(&h->p_filesz); /* Segment size in file */ | ||
| 108 | - swab32s(&h->p_memsz); /* Segment size in memory */ | 147 | + swabls(&h->p_offset); /* Segment file offset */ |
| 148 | + swabls(&h->p_vaddr); /* Segment virtual address */ | ||
| 149 | + swabls(&h->p_paddr); /* Segment physical address */ | ||
| 150 | + swabls(&h->p_filesz); /* Segment size in file */ | ||
| 151 | + swabls(&h->p_memsz); /* Segment size in memory */ | ||
| 109 | swab32s(&h->p_flags); /* Segment flags */ | 152 | swab32s(&h->p_flags); /* Segment flags */ |
| 110 | - swab32s(&h->p_align); /* Segment alignment */ | 153 | + swabls(&h->p_align); /* Segment alignment */ |
| 111 | } | 154 | } |
| 112 | 155 | ||
| 113 | int do_swap; | 156 | int do_swap; |
| 114 | -int e_machine; | ||
| 115 | 157 | ||
| 116 | uint16_t get16(uint16_t *p) | 158 | uint16_t get16(uint16_t *p) |
| 117 | { | 159 | { |
| @@ -157,12 +199,12 @@ void __attribute__((noreturn)) error(const char *fmt, ...) | @@ -157,12 +199,12 @@ void __attribute__((noreturn)) error(const char *fmt, ...) | ||
| 157 | } | 199 | } |
| 158 | 200 | ||
| 159 | 201 | ||
| 160 | -Elf32_Shdr *find_elf_section(Elf32_Shdr *shdr, int shnum, const char *shstr, | ||
| 161 | - const char *name) | 202 | +struct elf_shdr *find_elf_section(struct elf_shdr *shdr, int shnum, const char *shstr, |
| 203 | + const char *name) | ||
| 162 | { | 204 | { |
| 163 | int i; | 205 | int i; |
| 164 | const char *shname; | 206 | const char *shname; |
| 165 | - Elf32_Shdr *sec; | 207 | + struct elf_shdr *sec; |
| 166 | 208 | ||
| 167 | for(i = 0; i < shnum; i++) { | 209 | for(i = 0; i < shnum; i++) { |
| 168 | sec = &shdr[i]; | 210 | sec = &shdr[i]; |
| @@ -209,20 +251,21 @@ int strstart(const char *str, const char *val, const char **ptr) | @@ -209,20 +251,21 @@ int strstart(const char *str, const char *val, const char **ptr) | ||
| 209 | #define MAX_ARGS 3 | 251 | #define MAX_ARGS 3 |
| 210 | 252 | ||
| 211 | /* generate op code */ | 253 | /* generate op code */ |
| 212 | -void gen_code(const char *name, unsigned long offset, unsigned long size, | ||
| 213 | - FILE *outfile, uint8_t *text, void *relocs, int nb_relocs, int reloc_sh_type, | ||
| 214 | - Elf32_Sym *symtab, char *strtab, int gen_switch) | 254 | +void gen_code(const char *name, host_ulong offset, host_ulong size, |
| 255 | + FILE *outfile, uint8_t *text, ELF_RELOC *relocs, int nb_relocs, int reloc_sh_type, | ||
| 256 | + ElfW(Sym) *symtab, char *strtab, int gen_switch) | ||
| 215 | { | 257 | { |
| 216 | int copy_size = 0; | 258 | int copy_size = 0; |
| 217 | uint8_t *p_start, *p_end; | 259 | uint8_t *p_start, *p_end; |
| 218 | - int nb_args, i; | 260 | + int nb_args, i, n; |
| 219 | uint8_t args_present[MAX_ARGS]; | 261 | uint8_t args_present[MAX_ARGS]; |
| 220 | const char *sym_name, *p; | 262 | const char *sym_name, *p; |
| 263 | + ELF_RELOC *rel; | ||
| 221 | 264 | ||
| 222 | /* compute exact size excluding return instruction */ | 265 | /* compute exact size excluding return instruction */ |
| 223 | p_start = text + offset; | 266 | p_start = text + offset; |
| 224 | p_end = p_start + size; | 267 | p_end = p_start + size; |
| 225 | - switch(e_machine) { | 268 | + switch(ELF_ARCH) { |
| 226 | case EM_386: | 269 | case EM_386: |
| 227 | { | 270 | { |
| 228 | uint8_t *p; | 271 | uint8_t *p; |
| @@ -256,40 +299,20 @@ void gen_code(const char *name, unsigned long offset, unsigned long size, | @@ -256,40 +299,20 @@ void gen_code(const char *name, unsigned long offset, unsigned long size, | ||
| 256 | copy_size = p - p_start; | 299 | copy_size = p - p_start; |
| 257 | } | 300 | } |
| 258 | break; | 301 | break; |
| 259 | - default: | ||
| 260 | - error("unsupported CPU (%d)", e_machine); | ||
| 261 | } | 302 | } |
| 262 | 303 | ||
| 263 | /* compute the number of arguments by looking at the relocations */ | 304 | /* compute the number of arguments by looking at the relocations */ |
| 264 | for(i = 0;i < MAX_ARGS; i++) | 305 | for(i = 0;i < MAX_ARGS; i++) |
| 265 | args_present[i] = 0; | 306 | args_present[i] = 0; |
| 266 | 307 | ||
| 267 | - if (reloc_sh_type == SHT_REL) { | ||
| 268 | - Elf32_Rel *rel; | ||
| 269 | - int n; | ||
| 270 | - for(i = 0, rel = relocs;i < nb_relocs; i++, rel++) { | ||
| 271 | - if (rel->r_offset >= offset && rel->r_offset < offset + copy_size) { | ||
| 272 | - sym_name = strtab + symtab[ELF32_R_SYM(rel->r_info)].st_name; | ||
| 273 | - if (strstart(sym_name, "__op_param", &p)) { | ||
| 274 | - n = strtoul(p, NULL, 10); | ||
| 275 | - if (n >= MAX_ARGS) | ||
| 276 | - error("too many arguments in %s", name); | ||
| 277 | - args_present[n - 1] = 1; | ||
| 278 | - } | ||
| 279 | - } | ||
| 280 | - } | ||
| 281 | - } else { | ||
| 282 | - Elf32_Rela *rel; | ||
| 283 | - int n; | ||
| 284 | - for(i = 0, rel = relocs;i < nb_relocs; i++, rel++) { | ||
| 285 | - if (rel->r_offset >= offset && rel->r_offset < offset + copy_size) { | ||
| 286 | - sym_name = strtab + symtab[ELF32_R_SYM(rel->r_info)].st_name; | ||
| 287 | - if (strstart(sym_name, "__op_param", &p)) { | ||
| 288 | - n = strtoul(p, NULL, 10); | ||
| 289 | - if (n >= MAX_ARGS) | ||
| 290 | - error("too many arguments in %s", name); | ||
| 291 | - args_present[n - 1] = 1; | ||
| 292 | - } | 308 | + for(i = 0, rel = relocs;i < nb_relocs; i++, rel++) { |
| 309 | + if (rel->r_offset >= offset && rel->r_offset < offset + copy_size) { | ||
| 310 | + sym_name = strtab + symtab[ELFW(R_SYM)(rel->r_info)].st_name; | ||
| 311 | + if (strstart(sym_name, "__op_param", &p)) { | ||
| 312 | + n = strtoul(p, NULL, 10); | ||
| 313 | + if (n >= MAX_ARGS) | ||
| 314 | + error("too many arguments in %s", name); | ||
| 315 | + args_present[n - 1] = 1; | ||
| 293 | } | 316 | } |
| 294 | } | 317 | } |
| 295 | } | 318 | } |
| @@ -319,24 +342,11 @@ void gen_code(const char *name, unsigned long offset, unsigned long size, | @@ -319,24 +342,11 @@ void gen_code(const char *name, unsigned long offset, unsigned long size, | ||
| 319 | } | 342 | } |
| 320 | fprintf(outfile, " extern void %s();\n", name); | 343 | fprintf(outfile, " extern void %s();\n", name); |
| 321 | 344 | ||
| 322 | - if (reloc_sh_type == SHT_REL) { | ||
| 323 | - Elf32_Rel *rel; | ||
| 324 | - for(i = 0, rel = relocs;i < nb_relocs; i++, rel++) { | ||
| 325 | - if (rel->r_offset >= offset && rel->r_offset < offset + copy_size) { | ||
| 326 | - sym_name = strtab + symtab[ELF32_R_SYM(rel->r_info)].st_name; | ||
| 327 | - if (!strstart(sym_name, "__op_param", &p)) { | ||
| 328 | - fprintf(outfile, "extern char %s;\n", sym_name); | ||
| 329 | - } | ||
| 330 | - } | ||
| 331 | - } | ||
| 332 | - } else { | ||
| 333 | - Elf32_Rela *rel; | ||
| 334 | - for(i = 0, rel = relocs;i < nb_relocs; i++, rel++) { | ||
| 335 | - if (rel->r_offset >= offset && rel->r_offset < offset + copy_size) { | ||
| 336 | - sym_name = strtab + symtab[ELF32_R_SYM(rel->r_info)].st_name; | ||
| 337 | - if (!strstart(sym_name, "__op_param", &p)) { | ||
| 338 | - fprintf(outfile, "extern char %s;\n", sym_name); | ||
| 339 | - } | 345 | + for(i = 0, rel = relocs;i < nb_relocs; i++, rel++) { |
| 346 | + if (rel->r_offset >= offset && rel->r_offset < offset + copy_size) { | ||
| 347 | + sym_name = strtab + symtab[ELF32_R_SYM(rel->r_info)].st_name; | ||
| 348 | + if (!strstart(sym_name, "__op_param", &p)) { | ||
| 349 | + fprintf(outfile, "extern char %s;\n", sym_name); | ||
| 340 | } | 350 | } |
| 341 | } | 351 | } |
| 342 | } | 352 | } |
| @@ -347,13 +357,11 @@ void gen_code(const char *name, unsigned long offset, unsigned long size, | @@ -347,13 +357,11 @@ void gen_code(const char *name, unsigned long offset, unsigned long size, | ||
| 347 | } | 357 | } |
| 348 | 358 | ||
| 349 | /* patch relocations */ | 359 | /* patch relocations */ |
| 350 | - switch(e_machine) { | ||
| 351 | - case EM_386: | 360 | +#if defined(HOST_I386) |
| 352 | { | 361 | { |
| 353 | - Elf32_Rel *rel; | ||
| 354 | char name[256]; | 362 | char name[256]; |
| 355 | int type; | 363 | int type; |
| 356 | - long addend; | 364 | + int addend; |
| 357 | for(i = 0, rel = relocs;i < nb_relocs; i++, rel++) { | 365 | for(i = 0, rel = relocs;i < nb_relocs; i++, rel++) { |
| 358 | if (rel->r_offset >= offset && rel->r_offset < offset + copy_size) { | 366 | if (rel->r_offset >= offset && rel->r_offset < offset + copy_size) { |
| 359 | sym_name = strtab + symtab[ELF32_R_SYM(rel->r_info)].st_name; | 367 | sym_name = strtab + symtab[ELF32_R_SYM(rel->r_info)].st_name; |
| @@ -366,11 +374,11 @@ void gen_code(const char *name, unsigned long offset, unsigned long size, | @@ -366,11 +374,11 @@ void gen_code(const char *name, unsigned long offset, unsigned long size, | ||
| 366 | addend = get32((uint32_t *)(text + rel->r_offset)); | 374 | addend = get32((uint32_t *)(text + rel->r_offset)); |
| 367 | switch(type) { | 375 | switch(type) { |
| 368 | case R_386_32: | 376 | case R_386_32: |
| 369 | - fprintf(outfile, " *(uint32_t *)(gen_code_ptr + %ld) = %s + %ld;\n", | 377 | + fprintf(outfile, " *(uint32_t *)(gen_code_ptr + %d) = %s + %d;\n", |
| 370 | rel->r_offset - offset, name, addend); | 378 | rel->r_offset - offset, name, addend); |
| 371 | break; | 379 | break; |
| 372 | case R_386_PC32: | 380 | case R_386_PC32: |
| 373 | - fprintf(outfile, " *(uint32_t *)(gen_code_ptr + %ld) = %s - (long)(gen_code_ptr + %ld) + %ld;\n", | 381 | + fprintf(outfile, " *(uint32_t *)(gen_code_ptr + %d) = %s - (long)(gen_code_ptr + %d) + %d;\n", |
| 374 | rel->r_offset - offset, name, rel->r_offset - offset, addend); | 382 | rel->r_offset - offset, name, rel->r_offset - offset, addend); |
| 375 | break; | 383 | break; |
| 376 | default: | 384 | default: |
| @@ -379,13 +387,11 @@ void gen_code(const char *name, unsigned long offset, unsigned long size, | @@ -379,13 +387,11 @@ void gen_code(const char *name, unsigned long offset, unsigned long size, | ||
| 379 | } | 387 | } |
| 380 | } | 388 | } |
| 381 | } | 389 | } |
| 382 | - break; | ||
| 383 | - case EM_PPC: | 390 | +#elif defined(HOST_PPC) |
| 384 | { | 391 | { |
| 385 | - Elf32_Rela *rel; | ||
| 386 | char name[256]; | 392 | char name[256]; |
| 387 | int type; | 393 | int type; |
| 388 | - long addend; | 394 | + int addend; |
| 389 | for(i = 0, rel = relocs;i < nb_relocs; i++, rel++) { | 395 | for(i = 0, rel = relocs;i < nb_relocs; i++, rel++) { |
| 390 | if (rel->r_offset >= offset && rel->r_offset < offset + copy_size) { | 396 | if (rel->r_offset >= offset && rel->r_offset < offset + copy_size) { |
| 391 | sym_name = strtab + symtab[ELF32_R_SYM(rel->r_info)].st_name; | 397 | sym_name = strtab + symtab[ELF32_R_SYM(rel->r_info)].st_name; |
| @@ -398,24 +404,24 @@ void gen_code(const char *name, unsigned long offset, unsigned long size, | @@ -398,24 +404,24 @@ void gen_code(const char *name, unsigned long offset, unsigned long size, | ||
| 398 | addend = rel->r_addend; | 404 | addend = rel->r_addend; |
| 399 | switch(type) { | 405 | switch(type) { |
| 400 | case R_PPC_ADDR32: | 406 | case R_PPC_ADDR32: |
| 401 | - fprintf(outfile, " *(uint32_t *)(gen_code_ptr + %ld) = %s + %ld;\n", | 407 | + fprintf(outfile, " *(uint32_t *)(gen_code_ptr + %d) = %s + %d;\n", |
| 402 | rel->r_offset - offset, name, addend); | 408 | rel->r_offset - offset, name, addend); |
| 403 | break; | 409 | break; |
| 404 | case R_PPC_ADDR16_LO: | 410 | case R_PPC_ADDR16_LO: |
| 405 | - fprintf(outfile, " *(uint16_t *)(gen_code_ptr + %ld) = (%s + %ld);\n", | 411 | + fprintf(outfile, " *(uint16_t *)(gen_code_ptr + %d) = (%s + %d);\n", |
| 406 | rel->r_offset - offset, name, addend); | 412 | rel->r_offset - offset, name, addend); |
| 407 | break; | 413 | break; |
| 408 | case R_PPC_ADDR16_HI: | 414 | case R_PPC_ADDR16_HI: |
| 409 | - fprintf(outfile, " *(uint16_t *)(gen_code_ptr + %ld) = (%s + %ld) >> 16;\n", | 415 | + fprintf(outfile, " *(uint16_t *)(gen_code_ptr + %d) = (%s + %d) >> 16;\n", |
| 410 | rel->r_offset - offset, name, addend); | 416 | rel->r_offset - offset, name, addend); |
| 411 | break; | 417 | break; |
| 412 | case R_PPC_ADDR16_HA: | 418 | case R_PPC_ADDR16_HA: |
| 413 | - fprintf(outfile, " *(uint16_t *)(gen_code_ptr + %ld) = (%s + %ld + 0x8000) >> 16;\n", | 419 | + fprintf(outfile, " *(uint16_t *)(gen_code_ptr + %d) = (%s + %d + 0x8000) >> 16;\n", |
| 414 | rel->r_offset - offset, name, addend); | 420 | rel->r_offset - offset, name, addend); |
| 415 | break; | 421 | break; |
| 416 | case R_PPC_REL24: | 422 | case R_PPC_REL24: |
| 417 | /* warning: must be at 32 MB distancy */ | 423 | /* warning: must be at 32 MB distancy */ |
| 418 | - fprintf(outfile, " *(uint32_t *)(gen_code_ptr + %ld) = (*(uint32_t *)(gen_code_ptr + %ld) & ~0x03fffffc) | ((%s - (long)(gen_code_ptr + %ld) + %ld) & 0x03fffffc);\n", | 424 | + fprintf(outfile, " *(uint32_t *)(gen_code_ptr + %d) = (*(uint32_t *)(gen_code_ptr + %d) & ~0x03fffffc) | ((%s - (long)(gen_code_ptr + %d) + %d) & 0x03fffffc);\n", |
| 419 | rel->r_offset - offset, rel->r_offset - offset, name, rel->r_offset - offset, addend); | 425 | rel->r_offset - offset, rel->r_offset - offset, name, rel->r_offset - offset, addend); |
| 420 | break; | 426 | break; |
| 421 | default: | 427 | default: |
| @@ -424,13 +430,11 @@ void gen_code(const char *name, unsigned long offset, unsigned long size, | @@ -424,13 +430,11 @@ void gen_code(const char *name, unsigned long offset, unsigned long size, | ||
| 424 | } | 430 | } |
| 425 | } | 431 | } |
| 426 | } | 432 | } |
| 427 | - break; | ||
| 428 | - case EM_S390: | 433 | +#elif defined(HOST_S390) |
| 429 | { | 434 | { |
| 430 | - Elf32_Rela *rel; | ||
| 431 | char name[256]; | 435 | char name[256]; |
| 432 | int type; | 436 | int type; |
| 433 | - long addend; | 437 | + int addend; |
| 434 | for(i = 0, rel = relocs;i < nb_relocs; i++, rel++) { | 438 | for(i = 0, rel = relocs;i < nb_relocs; i++, rel++) { |
| 435 | if (rel->r_offset >= offset && rel->r_offset < offset + copy_size) { | 439 | if (rel->r_offset >= offset && rel->r_offset < offset + copy_size) { |
| 436 | sym_name = strtab + symtab[ELF32_R_SYM(rel->r_info)].st_name; | 440 | sym_name = strtab + symtab[ELF32_R_SYM(rel->r_info)].st_name; |
| @@ -443,15 +447,15 @@ void gen_code(const char *name, unsigned long offset, unsigned long size, | @@ -443,15 +447,15 @@ void gen_code(const char *name, unsigned long offset, unsigned long size, | ||
| 443 | addend = rel->r_addend; | 447 | addend = rel->r_addend; |
| 444 | switch(type) { | 448 | switch(type) { |
| 445 | case R_390_32: | 449 | case R_390_32: |
| 446 | - fprintf(outfile, " *(uint32_t *)(gen_code_ptr + %ld) = %s + %ld;\n", | 450 | + fprintf(outfile, " *(uint32_t *)(gen_code_ptr + %d) = %s + %d;\n", |
| 447 | rel->r_offset - offset, name, addend); | 451 | rel->r_offset - offset, name, addend); |
| 448 | break; | 452 | break; |
| 449 | case R_390_16: | 453 | case R_390_16: |
| 450 | - fprintf(outfile, " *(uint16_t *)(gen_code_ptr + %ld) = %s + %ld;\n", | 454 | + fprintf(outfile, " *(uint16_t *)(gen_code_ptr + %d) = %s + %d;\n", |
| 451 | rel->r_offset - offset, name, addend); | 455 | rel->r_offset - offset, name, addend); |
| 452 | break; | 456 | break; |
| 453 | case R_390_8: | 457 | case R_390_8: |
| 454 | - fprintf(outfile, " *(uint8_t *)(gen_code_ptr + %ld) = %s + %ld;\n", | 458 | + fprintf(outfile, " *(uint8_t *)(gen_code_ptr + %d) = %s + %d;\n", |
| 455 | rel->r_offset - offset, name, addend); | 459 | rel->r_offset - offset, name, addend); |
| 456 | break; | 460 | break; |
| 457 | default: | 461 | default: |
| @@ -460,10 +464,9 @@ void gen_code(const char *name, unsigned long offset, unsigned long size, | @@ -460,10 +464,9 @@ void gen_code(const char *name, unsigned long offset, unsigned long size, | ||
| 460 | } | 464 | } |
| 461 | } | 465 | } |
| 462 | } | 466 | } |
| 463 | - break; | ||
| 464 | - default: | ||
| 465 | - error("unsupported CPU for relocations (%d)", e_machine); | ||
| 466 | - } | 467 | +#else |
| 468 | +#error unsupported CPU | ||
| 469 | +#endif | ||
| 467 | fprintf(outfile, " gen_code_ptr += %d;\n", copy_size); | 470 | fprintf(outfile, " gen_code_ptr += %d;\n", copy_size); |
| 468 | fprintf(outfile, "}\n"); | 471 | fprintf(outfile, "}\n"); |
| 469 | fprintf(outfile, "break;\n\n"); | 472 | fprintf(outfile, "break;\n\n"); |
| @@ -492,11 +495,10 @@ void gen_code(const char *name, unsigned long offset, unsigned long size, | @@ -492,11 +495,10 @@ void gen_code(const char *name, unsigned long offset, unsigned long size, | ||
| 492 | int load_elf(const char *filename, FILE *outfile, int do_print_enum) | 495 | int load_elf(const char *filename, FILE *outfile, int do_print_enum) |
| 493 | { | 496 | { |
| 494 | int fd; | 497 | int fd; |
| 495 | - Elf32_Ehdr ehdr; | ||
| 496 | - Elf32_Shdr *sec, *shdr, *symtab_sec, *strtab_sec, *text_sec; | 498 | + struct elfhdr ehdr; |
| 499 | + struct elf_shdr *sec, *shdr, *symtab_sec, *strtab_sec, *text_sec; | ||
| 497 | int i, j, nb_syms; | 500 | int i, j, nb_syms; |
| 498 | - Elf32_Sym *symtab, *sym; | ||
| 499 | - const char *cpu_name; | 501 | + ElfW(Sym) *symtab, *sym; |
| 500 | char *shstr, *strtab; | 502 | char *shstr, *strtab; |
| 501 | uint8_t *text; | 503 | uint8_t *text; |
| 502 | void *relocs; | 504 | void *relocs; |
| @@ -515,7 +517,6 @@ int load_elf(const char *filename, FILE *outfile, int do_print_enum) | @@ -515,7 +517,6 @@ int load_elf(const char *filename, FILE *outfile, int do_print_enum) | ||
| 515 | || ehdr.e_ident[EI_MAG1] != ELFMAG1 | 517 | || ehdr.e_ident[EI_MAG1] != ELFMAG1 |
| 516 | || ehdr.e_ident[EI_MAG2] != ELFMAG2 | 518 | || ehdr.e_ident[EI_MAG2] != ELFMAG2 |
| 517 | || ehdr.e_ident[EI_MAG3] != ELFMAG3 | 519 | || ehdr.e_ident[EI_MAG3] != ELFMAG3 |
| 518 | - || ehdr.e_ident[EI_CLASS] != ELFCLASS32 | ||
| 519 | || ehdr.e_ident[EI_VERSION] != EV_CURRENT) { | 520 | || ehdr.e_ident[EI_VERSION] != EV_CURRENT) { |
| 520 | error("bad ELF header"); | 521 | error("bad ELF header"); |
| 521 | } | 522 | } |
| @@ -523,14 +524,17 @@ int load_elf(const char *filename, FILE *outfile, int do_print_enum) | @@ -523,14 +524,17 @@ int load_elf(const char *filename, FILE *outfile, int do_print_enum) | ||
| 523 | do_swap = elf_must_swap(&ehdr); | 524 | do_swap = elf_must_swap(&ehdr); |
| 524 | if (do_swap) | 525 | if (do_swap) |
| 525 | elf_swap_ehdr(&ehdr); | 526 | elf_swap_ehdr(&ehdr); |
| 527 | + if (ehdr.e_ident[EI_CLASS] != ELF_CLASS) | ||
| 528 | + error("Unsupported ELF class"); | ||
| 526 | if (ehdr.e_type != ET_REL) | 529 | if (ehdr.e_type != ET_REL) |
| 527 | error("ELF object file expected"); | 530 | error("ELF object file expected"); |
| 528 | if (ehdr.e_version != EV_CURRENT) | 531 | if (ehdr.e_version != EV_CURRENT) |
| 529 | error("Invalid ELF version"); | 532 | error("Invalid ELF version"); |
| 530 | - e_machine = ehdr.e_machine; | 533 | + if (!elf_check_arch(ehdr.e_machine)) |
| 534 | + error("Unsupported CPU (e_machine=%d)", ehdr.e_machine); | ||
| 531 | 535 | ||
| 532 | /* read section headers */ | 536 | /* read section headers */ |
| 533 | - shdr = load_data(fd, ehdr.e_shoff, ehdr.e_shnum * sizeof(Elf32_Shdr)); | 537 | + shdr = load_data(fd, ehdr.e_shoff, ehdr.e_shnum * sizeof(struct elf_shdr)); |
| 534 | if (do_swap) { | 538 | if (do_swap) { |
| 535 | for(i = 0; i < ehdr.e_shnum; i++) { | 539 | for(i = 0; i < ehdr.e_shnum; i++) { |
| 536 | elf_swap_shdr(&shdr[i]); | 540 | elf_swap_shdr(&shdr[i]); |
| @@ -590,35 +594,12 @@ int load_elf(const char *filename, FILE *outfile, int do_print_enum) | @@ -590,35 +594,12 @@ int load_elf(const char *filename, FILE *outfile, int do_print_enum) | ||
| 590 | if (do_swap) { | 594 | if (do_swap) { |
| 591 | for(i = 0, sym = symtab; i < nb_syms; i++, sym++) { | 595 | for(i = 0, sym = symtab; i < nb_syms; i++, sym++) { |
| 592 | swab32s(&sym->st_name); | 596 | swab32s(&sym->st_name); |
| 593 | - swab32s(&sym->st_value); | ||
| 594 | - swab32s(&sym->st_size); | 597 | + swabls(&sym->st_value); |
| 598 | + swabls(&sym->st_size); | ||
| 595 | swab16s(&sym->st_shndx); | 599 | swab16s(&sym->st_shndx); |
| 596 | } | 600 | } |
| 597 | } | 601 | } |
| 598 | 602 | ||
| 599 | - switch(e_machine) { | ||
| 600 | - case EM_386: | ||
| 601 | - cpu_name = "i386"; | ||
| 602 | - break; | ||
| 603 | - case EM_PPC: | ||
| 604 | - cpu_name = "ppc"; | ||
| 605 | - break; | ||
| 606 | - case EM_MIPS: | ||
| 607 | - cpu_name = "mips"; | ||
| 608 | - break; | ||
| 609 | - case EM_ARM: | ||
| 610 | - cpu_name = "arm"; | ||
| 611 | - break; | ||
| 612 | - case EM_SPARC: | ||
| 613 | - cpu_name = "sparc"; | ||
| 614 | - break; | ||
| 615 | - case EM_S390: | ||
| 616 | - cpu_name = "s390"; | ||
| 617 | - break; | ||
| 618 | - default: | ||
| 619 | - error("unsupported CPU (e_machine=%d)", e_machine); | ||
| 620 | - } | ||
| 621 | - | ||
| 622 | if (do_print_enum) { | 603 | if (do_print_enum) { |
| 623 | fprintf(outfile, "DEF(end, 0)\n"); | 604 | fprintf(outfile, "DEF(end, 0)\n"); |
| 624 | for(i = 0, sym = symtab; i < nb_syms; i++, sym++) { | 605 | for(i = 0, sym = symtab; i < nb_syms; i++, sym++) { |
| @@ -669,7 +650,7 @@ fprintf(outfile, | @@ -669,7 +650,7 @@ fprintf(outfile, | ||
| 669 | ); | 650 | ); |
| 670 | 651 | ||
| 671 | /* generate a return */ | 652 | /* generate a return */ |
| 672 | - switch(e_machine) { | 653 | + switch(ELF_ARCH) { |
| 673 | case EM_386: | 654 | case EM_386: |
| 674 | fprintf(outfile, "*gen_code_ptr++ = 0xc3; /* ret */\n"); | 655 | fprintf(outfile, "*gen_code_ptr++ = 0xc3; /* ret */\n"); |
| 675 | break; | 656 | break; |
| @@ -679,8 +660,6 @@ fprintf(outfile, | @@ -679,8 +660,6 @@ fprintf(outfile, | ||
| 679 | case EM_S390: | 660 | case EM_S390: |
| 680 | fprintf(outfile, "*((uint16_t *)gen_code_ptr)++ = 0x07fe; /* br %%r14 */\n"); | 661 | fprintf(outfile, "*((uint16_t *)gen_code_ptr)++ = 0x07fe; /* br %%r14 */\n"); |
| 681 | break; | 662 | break; |
| 682 | - default: | ||
| 683 | - error("no return generation for cpu '%s'", cpu_name); | ||
| 684 | } | 663 | } |
| 685 | 664 | ||
| 686 | fprintf(outfile, "return gen_code_ptr - gen_code_buf;\n"); | 665 | fprintf(outfile, "return gen_code_ptr - gen_code_buf;\n"); |