Revision 5fafdf24 dyngen.c
b/dyngen.c | ||
---|---|---|
1 | 1 |
/* |
2 | 2 |
* Generic Dynamic compiler generator |
3 |
*
|
|
3 |
* |
|
4 | 4 |
* Copyright (c) 2003 Fabrice Bellard |
5 | 5 |
* |
6 | 6 |
* The COFF object format support was extracted from Kazu's QEMU port |
... | ... | |
204 | 204 |
struct nlist_extended |
205 | 205 |
{ |
206 | 206 |
union { |
207 |
char *n_name;
|
|
208 |
long n_strx;
|
|
207 |
char *n_name; |
|
208 |
long n_strx; |
|
209 | 209 |
} n_un; |
210 |
unsigned char n_type;
|
|
211 |
unsigned char n_sect;
|
|
210 |
unsigned char n_type; |
|
211 |
unsigned char n_sect; |
|
212 | 212 |
short st_desc; |
213 | 213 |
unsigned long st_value; |
214 | 214 |
unsigned long st_size; |
... | ... | |
372 | 372 |
} swaptest; |
373 | 373 |
|
374 | 374 |
swaptest.i = 1; |
375 |
return (h->e_ident[EI_DATA] == ELFDATA2MSB) !=
|
|
375 |
return (h->e_ident[EI_DATA] == ELFDATA2MSB) != |
|
376 | 376 |
(swaptest.b[0] == 0); |
377 | 377 |
} |
378 |
|
|
378 |
|
|
379 | 379 |
void elf_swap_ehdr(struct elfhdr *h) |
380 | 380 |
{ |
381 | 381 |
swab16s(&h->e_type); /* Object file type */ |
... | ... | |
428 | 428 |
#endif |
429 | 429 |
} |
430 | 430 |
|
431 |
struct elf_shdr *find_elf_section(struct elf_shdr *shdr, int shnum, const char *shstr,
|
|
431 |
struct elf_shdr *find_elf_section(struct elf_shdr *shdr, int shnum, const char *shstr, |
|
432 | 432 |
const char *name) |
433 | 433 |
{ |
434 | 434 |
int i; |
... | ... | |
453 | 453 |
|
454 | 454 |
for(i = 0; i < ehdr.e_shnum; i++) { |
455 | 455 |
sec = &shdr[i]; |
456 |
if (sec->sh_type == SHT_RELOC && sec->sh_info == sh_index)
|
|
456 |
if (sec->sh_type == SHT_RELOC && sec->sh_info == sh_index) |
|
457 | 457 |
return i; |
458 | 458 |
} |
459 | 459 |
return 0; |
... | ... | |
483 | 483 |
ElfW(Sym) *sym; |
484 | 484 |
char *shstr; |
485 | 485 |
ELF_RELOC *rel; |
486 |
|
|
486 |
|
|
487 | 487 |
fd = open(filename, O_RDONLY); |
488 |
if (fd < 0)
|
|
488 |
if (fd < 0) |
|
489 | 489 |
error("can't open file '%s'", filename); |
490 |
|
|
490 |
|
|
491 | 491 |
/* Read ELF header. */ |
492 | 492 |
if (read(fd, &ehdr, sizeof (ehdr)) != sizeof (ehdr)) |
493 | 493 |
error("unable to read file header"); |
... | ... | |
524 | 524 |
/* read all section data */ |
525 | 525 |
sdata = malloc(sizeof(void *) * ehdr.e_shnum); |
526 | 526 |
memset(sdata, 0, sizeof(void *) * ehdr.e_shnum); |
527 |
|
|
527 |
|
|
528 | 528 |
for(i = 0;i < ehdr.e_shnum; i++) { |
529 | 529 |
sec = &shdr[i]; |
530 | 530 |
if (sec->sh_type != SHT_NOBITS) |
... | ... | |
569 | 569 |
|
570 | 570 |
symtab = (ElfW(Sym) *)sdata[symtab_sec - shdr]; |
571 | 571 |
strtab = (char *)sdata[symtab_sec->sh_link]; |
572 |
|
|
572 |
|
|
573 | 573 |
nb_syms = symtab_sec->sh_size / sizeof(ElfW(Sym)); |
574 | 574 |
if (do_swap) { |
575 | 575 |
for(i = 0, sym = symtab; i < nb_syms; i++, sym++) { |
... | ... | |
609 | 609 |
{ |
610 | 610 |
char *q; |
611 | 611 |
int c, i, len; |
612 |
|
|
612 |
|
|
613 | 613 |
if (ext_sym->e.e.e_zeroes != 0) { |
614 | 614 |
q = sym->st_name; |
615 | 615 |
for(i = 0; i < 8; i++) { |
... | ... | |
643 | 643 |
if (sym->st_syment->e_scnum == data_shndx && |
644 | 644 |
text_data >= sym->st_value && |
645 | 645 |
text_data < sym->st_value + sym->st_size) { |
646 |
|
|
646 |
|
|
647 | 647 |
return sym->st_name; |
648 | 648 |
|
649 | 649 |
} |
... | ... | |
701 | 701 |
uint32_t *n_strtab; |
702 | 702 |
EXE_SYM *sym; |
703 | 703 |
EXE_RELOC *rel; |
704 |
|
|
705 |
fd = open(filename, O_RDONLY
|
|
704 |
|
|
705 |
fd = open(filename, O_RDONLY |
|
706 | 706 |
#ifdef _WIN32 |
707 | 707 |
| O_BINARY |
708 | 708 |
#endif |
709 | 709 |
); |
710 |
if (fd < 0)
|
|
710 |
if (fd < 0) |
|
711 | 711 |
error("can't open file '%s'", filename); |
712 |
|
|
712 |
|
|
713 | 713 |
/* Read COFF header. */ |
714 | 714 |
if (read(fd, &fhdr, sizeof (fhdr)) != sizeof (fhdr)) |
715 | 715 |
error("unable to read file header"); |
... | ... | |
722 | 722 |
|
723 | 723 |
/* read section headers */ |
724 | 724 |
shdr = load_data(fd, sizeof(struct external_filehdr) + fhdr.f_opthdr, fhdr.f_nscns * sizeof(struct external_scnhdr)); |
725 |
|
|
725 |
|
|
726 | 726 |
/* read all section data */ |
727 | 727 |
sdata = malloc(sizeof(void *) * fhdr.f_nscns); |
728 | 728 |
memset(sdata, 0, sizeof(void *) * fhdr.f_nscns); |
729 |
|
|
729 |
|
|
730 | 730 |
const char *p; |
731 | 731 |
for(i = 0;i < fhdr.f_nscns; i++) { |
732 | 732 |
sec = &shdr[i]; |
... | ... | |
747 | 747 |
if (!data_sec) |
748 | 748 |
error("could not find .data section"); |
749 | 749 |
coff_data_shndx = data_sec - shdr; |
750 |
|
|
750 |
|
|
751 | 751 |
coff_symtab = load_data(fd, fhdr.f_symptr, fhdr.f_nsyms*SYMESZ); |
752 | 752 |
for (i = 0, ext_sym = coff_symtab; i < nb_syms; i++, ext_sym++) { |
753 | 753 |
for(i=0;i<8;i++) |
... | ... | |
757 | 757 |
|
758 | 758 |
|
759 | 759 |
n_strtab = load_data(fd, (fhdr.f_symptr + fhdr.f_nsyms*SYMESZ), STRTAB_SIZE); |
760 |
strtab = load_data(fd, (fhdr.f_symptr + fhdr.f_nsyms*SYMESZ), *n_strtab);
|
|
761 |
|
|
760 |
strtab = load_data(fd, (fhdr.f_symptr + fhdr.f_nsyms*SYMESZ), *n_strtab); |
|
761 |
|
|
762 | 762 |
nb_syms = fhdr.f_nsyms; |
763 | 763 |
|
764 | 764 |
for (i = 0, ext_sym = coff_symtab; i < nb_syms; i++, ext_sym++) { |
... | ... | |
805 | 805 |
} else { |
806 | 806 |
sym->st_size = 0; |
807 | 807 |
} |
808 |
|
|
808 |
|
|
809 | 809 |
sym->st_type = ext_sym->e_type; |
810 | 810 |
sym->st_shndx = ext_sym->e_scnum; |
811 | 811 |
} |
812 | 812 |
|
813 |
|
|
813 |
|
|
814 | 814 |
/* find text relocations, if any */ |
815 | 815 |
sec = &shdr[coff_text_shndx]; |
816 | 816 |
coff_relocs = load_data(fd, sec->s_relptr, sec->s_nreloc*RELSZ); |
... | ... | |
818 | 818 |
|
819 | 819 |
/* set coff relocation */ |
820 | 820 |
relocs = malloc(sizeof(struct coff_rel) * nb_relocs); |
821 |
for (i = 0, ext_rel = coff_relocs, rel = relocs; i < nb_relocs;
|
|
821 |
for (i = 0, ext_rel = coff_relocs, rel = relocs; i < nb_relocs; |
|
822 | 822 |
i++, ext_rel++, rel++) { |
823 | 823 |
memset(rel, 0, sizeof(*rel)); |
824 | 824 |
rel->r_reloc = ext_rel; |
... | ... | |
847 | 847 |
|
848 | 848 |
/* relocs */ |
849 | 849 |
struct relocation_info *relocs; |
850 |
|
|
850 |
|
|
851 | 851 |
/* symbols */ |
852 | 852 |
EXE_SYM *symtab; |
853 | 853 |
struct nlist *symtab_std; |
... | ... | |
867 | 867 |
static char *get_sym_name(EXE_SYM *sym) |
868 | 868 |
{ |
869 | 869 |
char *name = find_str_by_index(sym->n_un.n_strx); |
870 |
|
|
870 |
|
|
871 | 871 |
if ( sym->n_type & N_STAB ) /* Debug symbols are ignored */ |
872 | 872 |
return "debug"; |
873 |
|
|
873 |
|
|
874 | 874 |
if(!name) |
875 | 875 |
return name; |
876 | 876 |
if(name[0]=='_') |
... | ... | |
880 | 880 |
} |
881 | 881 |
|
882 | 882 |
/* find a section index given its segname, sectname */ |
883 |
static int find_mach_sec_index(struct section *section_hdr, int shnum, const char *segname,
|
|
883 |
static int find_mach_sec_index(struct section *section_hdr, int shnum, const char *segname, |
|
884 | 884 |
const char *sectname) |
885 | 885 |
{ |
886 | 886 |
int i; |
... | ... | |
896 | 896 |
} |
897 | 897 |
|
898 | 898 |
/* find a section header given its segname, sectname */ |
899 |
struct section *find_mach_sec_hdr(struct section *section_hdr, int shnum, const char *segname,
|
|
899 |
struct section *find_mach_sec_hdr(struct section *section_hdr, int shnum, const char *segname, |
|
900 | 900 |
const char *sectname) |
901 | 901 |
{ |
902 | 902 |
int index = find_mach_sec_index(section_hdr, shnum, segname, sectname); |
... | ... | |
909 | 909 |
static inline void fetch_next_pair_value(struct relocation_info * rel, unsigned int *value) |
910 | 910 |
{ |
911 | 911 |
struct scattered_relocation_info * scarel; |
912 |
|
|
912 |
|
|
913 | 913 |
if(R_SCATTERED & rel->r_address) { |
914 | 914 |
scarel = (struct scattered_relocation_info*)rel; |
915 | 915 |
if(scarel->r_type != PPC_RELOC_PAIR) |
... | ... | |
926 | 926 |
static const char * find_sym_with_value_and_sec_number( int value, int sectnum, int * offset ) |
927 | 927 |
{ |
928 | 928 |
int i, ret = -1; |
929 |
|
|
929 |
|
|
930 | 930 |
for( i = 0 ; i < nb_syms; i++ ) |
931 | 931 |
{ |
932 | 932 |
if( !(symtab[i].n_type & N_STAB) && (symtab[i].n_type & N_SECT) && |
... | ... | |
945 | 945 |
} |
946 | 946 |
} |
947 | 947 |
|
948 |
/*
|
|
949 |
* Find symbol name given a (virtual) address, and a section which is of type
|
|
948 |
/* |
|
949 |
* Find symbol name given a (virtual) address, and a section which is of type |
|
950 | 950 |
* S_NON_LAZY_SYMBOL_POINTERS or S_LAZY_SYMBOL_POINTERS or S_SYMBOL_STUBS |
951 | 951 |
*/ |
952 | 952 |
static const char * find_reloc_name_in_sec_ptr(int address, struct section * sec_hdr) |
953 | 953 |
{ |
954 | 954 |
unsigned int tocindex, symindex, size; |
955 | 955 |
const char *name = 0; |
956 |
|
|
956 |
|
|
957 | 957 |
/* Sanity check */ |
958 | 958 |
if(!( address >= sec_hdr->addr && address < (sec_hdr->addr + sec_hdr->size) ) ) |
959 | 959 |
return (char*)0; |
960 |
|
|
960 |
|
|
961 | 961 |
if( sec_hdr->flags & S_SYMBOL_STUBS ){ |
962 | 962 |
size = sec_hdr->reserved2; |
963 | 963 |
if(size == 0) |
964 | 964 |
error("size = 0"); |
965 |
|
|
965 |
|
|
966 | 966 |
} |
967 | 967 |
else if( sec_hdr->flags & S_LAZY_SYMBOL_POINTERS || |
968 | 968 |
sec_hdr->flags & S_NON_LAZY_SYMBOL_POINTERS) |
969 | 969 |
size = sizeof(unsigned long); |
970 | 970 |
else |
971 | 971 |
return 0; |
972 |
|
|
972 |
|
|
973 | 973 |
/* Compute our index in toc */ |
974 | 974 |
tocindex = (address - sec_hdr->addr)/size; |
975 | 975 |
symindex = tocdylib[sec_hdr->reserved1 + tocindex]; |
976 |
|
|
976 |
|
|
977 | 977 |
name = get_sym_name(&symtab[symindex]); |
978 | 978 |
|
979 | 979 |
return name; |
... | ... | |
998 | 998 |
int sectnum = rel->r_symbolnum; |
999 | 999 |
int sectoffset; |
1000 | 1000 |
int other_half=0; |
1001 |
|
|
1001 |
|
|
1002 | 1002 |
/* init the slide value */ |
1003 | 1003 |
*sslide = 0; |
1004 |
|
|
1004 |
|
|
1005 | 1005 |
if(R_SCATTERED & rel->r_address) |
1006 | 1006 |
return (char *)find_reloc_name_given_its_address(sca_rel->r_value); |
1007 | 1007 |
|
1008 | 1008 |
if(rel->r_extern) |
1009 | 1009 |
{ |
1010 | 1010 |
/* ignore debug sym */ |
1011 |
if ( symtab[rel->r_symbolnum].n_type & N_STAB )
|
|
1011 |
if ( symtab[rel->r_symbolnum].n_type & N_STAB ) |
|
1012 | 1012 |
return 0; |
1013 | 1013 |
return get_sym_name(&symtab[rel->r_symbolnum]); |
1014 | 1014 |
} |
1015 | 1015 |
|
1016 | 1016 |
/* Intruction contains an offset to the symbols pointed to, in the rel->r_symbolnum section */ |
1017 | 1017 |
sectoffset = *(uint32_t *)(text + rel->r_address) & 0xffff; |
1018 |
|
|
1018 |
|
|
1019 | 1019 |
if(sectnum==0xffffff) |
1020 | 1020 |
return 0; |
1021 | 1021 |
|
... | ... | |
1041 | 1041 |
|
1042 | 1042 |
if(rel->r_pcrel) |
1043 | 1043 |
sectoffset += rel->r_address; |
1044 |
|
|
1044 |
|
|
1045 | 1045 |
if (rel->r_type == PPC_RELOC_BR24) |
1046 | 1046 |
name = (char *)find_reloc_name_in_sec_ptr((int)sectoffset, §ion_hdr[sectnum-1]); |
1047 | 1047 |
|
1048 | 1048 |
/* search it in the full symbol list, if not found */ |
1049 | 1049 |
if(!name) |
1050 | 1050 |
name = (char *)find_sym_with_value_and_sec_number(sectoffset, sectnum, sslide); |
1051 |
|
|
1051 |
|
|
1052 | 1052 |
return name; |
1053 | 1053 |
} |
1054 | 1054 |
|
... | ... | |
1080 | 1080 |
unsigned int i, j; |
1081 | 1081 |
EXE_SYM *sym; |
1082 | 1082 |
struct nlist *syment; |
1083 |
|
|
1083 |
|
|
1084 | 1084 |
fd = open(filename, O_RDONLY); |
1085 |
if (fd < 0)
|
|
1085 |
if (fd < 0) |
|
1086 | 1086 |
error("can't open file '%s'", filename); |
1087 |
|
|
1087 |
|
|
1088 | 1088 |
/* Read Mach header. */ |
1089 | 1089 |
if (read(fd, &mach_hdr, sizeof (mach_hdr)) != sizeof (mach_hdr)) |
1090 | 1090 |
error("unable to read file header"); |
... | ... | |
1093 | 1093 |
if (!check_mach_header(mach_hdr)) { |
1094 | 1094 |
error("bad Mach header"); |
1095 | 1095 |
} |
1096 |
|
|
1096 |
|
|
1097 | 1097 |
if (mach_hdr.cputype != CPU_TYPE_POWERPC) |
1098 | 1098 |
error("Unsupported CPU"); |
1099 |
|
|
1099 |
|
|
1100 | 1100 |
if (mach_hdr.filetype != MH_OBJECT) |
1101 | 1101 |
error("Unsupported Mach Object"); |
1102 |
|
|
1102 |
|
|
1103 | 1103 |
/* read segment headers */ |
1104 | 1104 |
for(i=0, j=sizeof(mach_hdr); i<mach_hdr.ncmds ; i++) |
1105 | 1105 |
{ |
... | ... | |
1143 | 1143 |
/* read all section data */ |
1144 | 1144 |
sdata = (uint8_t **)malloc(sizeof(void *) * segment->nsects); |
1145 | 1145 |
memset(sdata, 0, sizeof(void *) * segment->nsects); |
1146 |
|
|
1146 |
|
|
1147 | 1147 |
/* Load the data in section data */ |
1148 | 1148 |
for(i = 0; i < segment->nsects; i++) { |
1149 | 1149 |
sdata[i] = load_data(fd, section_hdr[i].offset, section_hdr[i].size); |
1150 | 1150 |
} |
1151 |
|
|
1151 |
|
|
1152 | 1152 |
/* text section */ |
1153 | 1153 |
text_sec_hdr = find_mach_sec_hdr(section_hdr, segment->nsects, SEG_TEXT, SECT_TEXT); |
1154 | 1154 |
i = find_mach_sec_index(section_hdr, segment->nsects, SEG_TEXT, SECT_TEXT); |
1155 | 1155 |
if (i == -1 || !text_sec_hdr) |
1156 | 1156 |
error("could not find __TEXT,__text section"); |
1157 | 1157 |
text = sdata[i]; |
1158 |
|
|
1158 |
|
|
1159 | 1159 |
/* Make sure dysym was loaded */ |
1160 | 1160 |
if(!(int)dysymtabcmd) |
1161 | 1161 |
error("could not find __DYSYMTAB segment"); |
1162 |
|
|
1162 |
|
|
1163 | 1163 |
/* read the table of content of the indirect sym */ |
1164 | 1164 |
tocdylib = load_data( fd, dysymtabcmd->indirectsymoff, dysymtabcmd->nindirectsyms * sizeof(uint32_t) ); |
1165 |
|
|
1165 |
|
|
1166 | 1166 |
/* Make sure symtab was loaded */ |
1167 | 1167 |
if(!(int)symtabcmd) |
1168 | 1168 |
error("could not find __SYMTAB segment"); |
... | ... | |
1170 | 1170 |
|
1171 | 1171 |
symtab_std = load_data(fd, symtabcmd->symoff, symtabcmd->nsyms * sizeof(struct nlist)); |
1172 | 1172 |
strtab = load_data(fd, symtabcmd->stroff, symtabcmd->strsize); |
1173 |
|
|
1173 |
|
|
1174 | 1174 |
symtab = malloc(sizeof(EXE_SYM) * nb_syms); |
1175 |
|
|
1175 |
|
|
1176 | 1176 |
/* Now transform the symtab, to an extended version, with the sym size, and the C name */ |
1177 | 1177 |
for(i = 0, sym = symtab, syment = symtab_std; i < nb_syms; i++, sym++, syment++) { |
1178 | 1178 |
struct nlist *sym_follow, *sym_next = 0; |
1179 | 1179 |
unsigned int j; |
1180 | 1180 |
memset(sym, 0, sizeof(*sym)); |
1181 |
|
|
1181 |
|
|
1182 | 1182 |
if ( syment->n_type & N_STAB ) /* Debug symbols are skipped */ |
1183 | 1183 |
continue; |
1184 |
|
|
1184 |
|
|
1185 | 1185 |
memcpy(sym, syment, sizeof(*syment)); |
1186 |
|
|
1186 |
|
|
1187 | 1187 |
/* Find the following symbol in order to get the current symbol size */ |
1188 | 1188 |
for(j = 0, sym_follow = symtab_std; j < nb_syms; j++, sym_follow++) { |
1189 | 1189 |
if ( sym_follow->n_sect != 1 || sym_follow->n_type & N_STAB || !(sym_follow->n_value > sym->st_value)) |
... | ... | |
1201 | 1201 |
else |
1202 | 1202 |
sym->st_size = text_sec_hdr->size - sym->st_value; |
1203 | 1203 |
} |
1204 |
|
|
1204 |
|
|
1205 | 1205 |
/* Find Reloc */ |
1206 | 1206 |
relocs = load_data(fd, text_sec_hdr->reloff, text_sec_hdr->nreloc * sizeof(struct relocation_info)); |
1207 | 1207 |
nb_relocs = text_sec_hdr->nreloc; |
... | ... | |
1286 | 1286 |
uint8_t data_allocated[1024]; |
1287 | 1287 |
unsigned int data_index; |
1288 | 1288 |
int type; |
1289 |
|
|
1289 |
|
|
1290 | 1290 |
memset(data_allocated, 0, sizeof(data_allocated)); |
1291 |
|
|
1291 |
|
|
1292 | 1292 |
p = p_start; |
1293 | 1293 |
min_offset = p_end - p_start; |
1294 | 1294 |
spare = 0x7fffffff; |
... | ... | |
1331 | 1331 |
if (spare > max_pool - offset) |
1332 | 1332 |
spare = max_pool - offset; |
1333 | 1333 |
if ((offset & 3) !=0) |
1334 |
error("%s:%04x: pc offset must be 32 bit aligned",
|
|
1334 |
error("%s:%04x: pc offset must be 32 bit aligned", |
|
1335 | 1335 |
name, start_offset + p - p_start); |
1336 | 1336 |
if (offset < 0) |
1337 | 1337 |
error("%s:%04x: Embedded literal value", |
1338 | 1338 |
name, start_offset + p - p_start); |
1339 | 1339 |
pc_offset = p - p_start + offset + 8; |
1340 |
if (pc_offset <= (p - p_start) ||
|
|
1340 |
if (pc_offset <= (p - p_start) || |
|
1341 | 1341 |
pc_offset >= (p_end - p_start)) |
1342 |
error("%s:%04x: pc offset must point inside the function code",
|
|
1342 |
error("%s:%04x: pc offset must point inside the function code", |
|
1343 | 1343 |
name, start_offset + p - p_start); |
1344 | 1344 |
if (pc_offset < min_offset) |
1345 | 1345 |
min_offset = pc_offset; |
1346 | 1346 |
if (outfile) { |
1347 | 1347 |
/* The intruction position */ |
1348 |
fprintf(outfile, " arm_ldr_ptr->ptr = gen_code_ptr + %d;\n",
|
|
1348 |
fprintf(outfile, " arm_ldr_ptr->ptr = gen_code_ptr + %d;\n", |
|
1349 | 1349 |
p - p_start); |
1350 | 1350 |
/* The position of the constant pool data. */ |
1351 | 1351 |
data_index = ((p_end - p_start) - pc_offset) >> 2; |
1352 |
fprintf(outfile, " arm_ldr_ptr->data_ptr = arm_data_ptr - %d;\n",
|
|
1352 |
fprintf(outfile, " arm_ldr_ptr->data_ptr = arm_data_ptr - %d;\n", |
|
1353 | 1353 |
data_index); |
1354 | 1354 |
fprintf(outfile, " arm_ldr_ptr->type = %d;\n", type); |
1355 | 1355 |
fprintf(outfile, " arm_ldr_ptr++;\n"); |
... | ... | |
1432 | 1432 |
#define MAX_ARGS 3 |
1433 | 1433 |
|
1434 | 1434 |
/* generate op code */ |
1435 |
void gen_code(const char *name, host_ulong offset, host_ulong size,
|
|
1435 |
void gen_code(const char *name, host_ulong offset, host_ulong size, |
|
1436 | 1436 |
FILE *outfile, int gen_switch) |
1437 | 1437 |
{ |
1438 | 1438 |
int copy_size = 0; |
... | ... | |
1478 | 1478 |
} |
1479 | 1479 |
copy_size = len; |
1480 | 1480 |
} |
1481 |
#endif
|
|
1481 |
#endif |
|
1482 | 1482 |
#elif defined(HOST_PPC) |
1483 | 1483 |
{ |
1484 | 1484 |
uint8_t *p; |
... | ... | |
1510 | 1510 |
#endif |
1511 | 1511 |
if (get32((uint32_t *)p) != 0x6bfa8001) |
1512 | 1512 |
error("ret expected at the end of %s", name); |
1513 |
copy_size = p - p_start;
|
|
1513 |
copy_size = p - p_start; |
|
1514 | 1514 |
} |
1515 | 1515 |
#elif defined(HOST_IA64) |
1516 | 1516 |
{ |
... | ... | |
1611 | 1611 |
} else { |
1612 | 1612 |
error("No save at the beginning of %s", name); |
1613 | 1613 |
} |
1614 |
|
|
1614 |
|
|
1615 | 1615 |
/* Skip a preceeding nop, if present. */ |
1616 | 1616 |
if (p > p_start) { |
1617 | 1617 |
skip_insn = get32((uint32_t *)(p - 0x4)); |
1618 | 1618 |
if (skip_insn == 0x01000000) |
1619 | 1619 |
p -= 4; |
1620 | 1620 |
} |
1621 |
|
|
1621 |
|
|
1622 | 1622 |
copy_size = p - p_start; |
1623 | 1623 |
} |
1624 | 1624 |
#elif defined(HOST_ARM) |
... | ... | |
1639 | 1639 |
p_start -= 4; |
1640 | 1640 |
start_offset -= 4; |
1641 | 1641 |
} |
1642 |
copy_size = arm_emit_ldr_info(name, start_offset, NULL, p_start, p_end,
|
|
1642 |
copy_size = arm_emit_ldr_info(name, start_offset, NULL, p_start, p_end, |
|
1643 | 1643 |
relocs, nb_relocs); |
1644 | 1644 |
} |
1645 | 1645 |
#elif defined(HOST_M68K) |
... | ... | |
1650 | 1650 |
error("empty code for %s", name); |
1651 | 1651 |
// remove NOP's, probably added for alignment |
1652 | 1652 |
while ((get16((uint16_t *)p) == 0x4e71) && |
1653 |
(p>p_start))
|
|
1653 |
(p>p_start)) |
|
1654 | 1654 |
p -= 2; |
1655 | 1655 |
if (get16((uint16_t *)p) != 0x4e75) |
1656 | 1656 |
error("rts expected at the end of %s", name); |
... | ... | |
1700 | 1700 |
} |
1701 | 1701 |
} |
1702 | 1702 |
} |
1703 |
|
|
1703 |
|
|
1704 | 1704 |
nb_args = 0; |
1705 | 1705 |
while (nb_args < MAX_ARGS && args_present[nb_args]) |
1706 | 1706 |
nb_args++; |
... | ... | |
1737 | 1737 |
sym_name = get_rel_sym_name(rel); |
1738 | 1738 |
if(!sym_name) |
1739 | 1739 |
continue; |
1740 |
if (*sym_name &&
|
|
1740 |
if (*sym_name && |
|
1741 | 1741 |
!strstart(sym_name, "__op_param", NULL) && |
1742 | 1742 |
!strstart(sym_name, "__op_jmp", NULL) && |
1743 | 1743 |
!strstart(sym_name, "__op_gen_label", NULL)) { |
... | ... | |
1784 | 1784 |
if (strstart(sym_name, "__op_label", &p)) { |
1785 | 1785 |
uint8_t *ptr; |
1786 | 1786 |
unsigned long offset; |
1787 |
|
|
1787 |
|
|
1788 | 1788 |
/* test if the variable refers to a label inside |
1789 | 1789 |
the code we are generating */ |
1790 | 1790 |
#ifdef CONFIG_FORMAT_COFF |
... | ... | |
1816 | 1816 |
/* try to find a matching relocation */ |
1817 | 1817 |
reloc_shndx = find_reloc(sym->st_shndx); |
1818 | 1818 |
if (reloc_shndx) { |
1819 |
nb_relocs1 = shdr[reloc_shndx].sh_size /
|
|
1819 |
nb_relocs1 = shdr[reloc_shndx].sh_size / |
|
1820 | 1820 |
shdr[reloc_shndx].sh_entsize; |
1821 | 1821 |
rel = (ELF_RELOC *)sdata[reloc_shndx]; |
1822 | 1822 |
for(j = 0; j < nb_relocs1; j++) { |
... | ... | |
1828 | 1828 |
} |
1829 | 1829 |
} |
1830 | 1830 |
} |
1831 |
#endif
|
|
1831 |
#endif |
|
1832 | 1832 |
if (val >= start_offset && val <= start_offset + copy_size) { |
1833 | 1833 |
n = strtol(p, NULL, 10); |
1834 | 1834 |
fprintf(outfile, " label_offsets[%d] = %ld + (gen_code_ptr - gen_code_buf);\n", n, (long)(val - start_offset)); |
... | ... | |
1874 | 1874 |
type = ELF32_R_TYPE(rel->r_info); |
1875 | 1875 |
switch(type) { |
1876 | 1876 |
case R_386_32: |
1877 |
fprintf(outfile, " *(uint32_t *)(gen_code_ptr + %d) = %s + %d;\n",
|
|
1877 |
fprintf(outfile, " *(uint32_t *)(gen_code_ptr + %d) = %s + %d;\n", |
|
1878 | 1878 |
reloc_offset, relname, addend); |
1879 | 1879 |
break; |
1880 | 1880 |
case R_386_PC32: |
1881 |
fprintf(outfile, " *(uint32_t *)(gen_code_ptr + %d) = %s - (long)(gen_code_ptr + %d) + %d;\n",
|
|
1881 |
fprintf(outfile, " *(uint32_t *)(gen_code_ptr + %d) = %s - (long)(gen_code_ptr + %d) + %d;\n", |
|
1882 | 1882 |
reloc_offset, relname, reloc_offset, addend); |
1883 | 1883 |
break; |
1884 | 1884 |
default: |
... | ... | |
1901 | 1901 |
type = rel->r_type; |
1902 | 1902 |
switch(type) { |
1903 | 1903 |
case DIR32: |
1904 |
fprintf(outfile, " *(uint32_t *)(gen_code_ptr + %d) = %s + %d;\n",
|
|
1904 |
fprintf(outfile, " *(uint32_t *)(gen_code_ptr + %d) = %s + %d;\n", |
|
1905 | 1905 |
reloc_offset, relname, addend); |
1906 | 1906 |
break; |
1907 | 1907 |
case DISP32: |
1908 |
fprintf(outfile, " *(uint32_t *)(gen_code_ptr + %d) = %s - (long)(gen_code_ptr + %d) + %d -4;\n",
|
|
1908 |
fprintf(outfile, " *(uint32_t *)(gen_code_ptr + %d) = %s - (long)(gen_code_ptr + %d) + %d -4;\n", |
|
1909 | 1909 |
reloc_offset, relname, reloc_offset, addend); |
1910 | 1910 |
break; |
1911 | 1911 |
default: |
... | ... | |
1933 | 1933 |
reloc_offset = rel->r_offset - start_offset; |
1934 | 1934 |
switch(type) { |
1935 | 1935 |
case R_X86_64_32: |
1936 |
fprintf(outfile, " *(uint32_t *)(gen_code_ptr + %d) = (uint32_t)%s + %d;\n",
|
|
1936 |
fprintf(outfile, " *(uint32_t *)(gen_code_ptr + %d) = (uint32_t)%s + %d;\n", |
|
1937 | 1937 |
reloc_offset, relname, addend); |
1938 | 1938 |
break; |
1939 | 1939 |
case R_X86_64_32S: |
1940 |
fprintf(outfile, " *(uint32_t *)(gen_code_ptr + %d) = (int32_t)%s + %d;\n",
|
|
1940 |
fprintf(outfile, " *(uint32_t *)(gen_code_ptr + %d) = (int32_t)%s + %d;\n", |
|
1941 | 1941 |
reloc_offset, relname, addend); |
1942 | 1942 |
break; |
1943 | 1943 |
case R_X86_64_PC32: |
1944 |
fprintf(outfile, " *(uint32_t *)(gen_code_ptr + %d) = %s - (long)(gen_code_ptr + %d) + %d;\n",
|
|
1944 |
fprintf(outfile, " *(uint32_t *)(gen_code_ptr + %d) = %s - (long)(gen_code_ptr + %d) + %d;\n", |
|
1945 | 1945 |
reloc_offset, relname, reloc_offset, addend); |
1946 | 1946 |
break; |
1947 | 1947 |
default: |
... | ... | |
1973 | 1973 |
n, reloc_offset); |
1974 | 1974 |
continue; |
1975 | 1975 |
} |
1976 |
|
|
1976 |
|
|
1977 | 1977 |
get_reloc_expr(relname, sizeof(relname), sym_name); |
1978 | 1978 |
type = ELF32_R_TYPE(rel->r_info); |
1979 | 1979 |
addend = rel->r_addend; |
1980 | 1980 |
switch(type) { |
1981 | 1981 |
case R_PPC_ADDR32: |
1982 |
fprintf(outfile, " *(uint32_t *)(gen_code_ptr + %d) = %s + %d;\n",
|
|
1982 |
fprintf(outfile, " *(uint32_t *)(gen_code_ptr + %d) = %s + %d;\n", |
|
1983 | 1983 |
reloc_offset, relname, addend); |
1984 | 1984 |
break; |
1985 | 1985 |
case R_PPC_ADDR16_LO: |
1986 |
fprintf(outfile, " *(uint16_t *)(gen_code_ptr + %d) = (%s + %d);\n",
|
|
1986 |
fprintf(outfile, " *(uint16_t *)(gen_code_ptr + %d) = (%s + %d);\n", |
|
1987 | 1987 |
reloc_offset, relname, addend); |
1988 | 1988 |
break; |
1989 | 1989 |
case R_PPC_ADDR16_HI: |
1990 |
fprintf(outfile, " *(uint16_t *)(gen_code_ptr + %d) = (%s + %d) >> 16;\n",
|
|
1990 |
fprintf(outfile, " *(uint16_t *)(gen_code_ptr + %d) = (%s + %d) >> 16;\n", |
|
1991 | 1991 |
reloc_offset, relname, addend); |
1992 | 1992 |
break; |
1993 | 1993 |
case R_PPC_ADDR16_HA: |
1994 |
fprintf(outfile, " *(uint16_t *)(gen_code_ptr + %d) = (%s + %d + 0x8000) >> 16;\n",
|
|
1994 |
fprintf(outfile, " *(uint16_t *)(gen_code_ptr + %d) = (%s + %d + 0x8000) >> 16;\n", |
|
1995 | 1995 |
reloc_offset, relname, addend); |
1996 | 1996 |
break; |
1997 | 1997 |
case R_PPC_REL24: |
1998 | 1998 |
/* warning: must be at 32 MB distancy */ |
1999 |
fprintf(outfile, " *(uint32_t *)(gen_code_ptr + %d) = (*(uint32_t *)(gen_code_ptr + %d) & ~0x03fffffc) | ((%s - (long)(gen_code_ptr + %d) + %d) & 0x03fffffc);\n",
|
|
1999 |
fprintf(outfile, " *(uint32_t *)(gen_code_ptr + %d) = (*(uint32_t *)(gen_code_ptr + %d) & ~0x03fffffc) | ((%s - (long)(gen_code_ptr + %d) + %d) & 0x03fffffc);\n", |
|
2000 | 2000 |
reloc_offset, reloc_offset, relname, reloc_offset, addend); |
2001 | 2001 |
break; |
2002 | 2002 |
default: |
... | ... | |
2036 | 2036 |
|
2037 | 2037 |
slide = offset - start_offset; |
2038 | 2038 |
|
2039 |
if (!(offset >= start_offset && offset < start_offset + size))
|
|
2039 |
if (!(offset >= start_offset && offset < start_offset + size)) |
|
2040 | 2040 |
continue; /* not in our range */ |
2041 | 2041 |
|
2042 | 2042 |
sym_name = get_reloc_name(rel, &sslide); |
... | ... | |
2058 | 2058 |
continue; /* dunno how to handle without final_sym_name */ |
2059 | 2059 |
} |
2060 | 2060 |
|
2061 |
get_reloc_expr(final_sym_name, sizeof(final_sym_name),
|
|
2061 |
get_reloc_expr(final_sym_name, sizeof(final_sym_name), |
|
2062 | 2062 |
sym_name); |
2063 | 2063 |
switch(type) { |
2064 | 2064 |
case PPC_RELOC_BR24: |
... | ... | |
2074 | 2074 |
} |
2075 | 2075 |
break; |
2076 | 2076 |
case PPC_RELOC_HI16: |
2077 |
fprintf(outfile, " *(uint16_t *)(gen_code_ptr + %d + 2) = (%s + %d) >> 16;\n",
|
|
2077 |
fprintf(outfile, " *(uint16_t *)(gen_code_ptr + %d + 2) = (%s + %d) >> 16;\n", |
|
2078 | 2078 |
slide, final_sym_name, sslide); |
2079 | 2079 |
break; |
2080 | 2080 |
case PPC_RELOC_LO16: |
2081 |
fprintf(outfile, " *(uint16_t *)(gen_code_ptr + %d + 2) = (%s + %d);\n",
|
|
2081 |
fprintf(outfile, " *(uint16_t *)(gen_code_ptr + %d + 2) = (%s + %d);\n", |
|
2082 | 2082 |
slide, final_sym_name, sslide); |
2083 | 2083 |
break; |
2084 | 2084 |
case PPC_RELOC_HA16: |
2085 |
fprintf(outfile, " *(uint16_t *)(gen_code_ptr + %d + 2) = (%s + %d + 0x8000) >> 16;\n",
|
|
2085 |
fprintf(outfile, " *(uint16_t *)(gen_code_ptr + %d + 2) = (%s + %d + 0x8000) >> 16;\n", |
|
2086 | 2086 |
slide, final_sym_name, sslide); |
2087 | 2087 |
break; |
2088 | 2088 |
default: |
... | ... | |
2109 | 2109 |
reloc_offset = rel->r_offset - start_offset; |
2110 | 2110 |
switch(type) { |
2111 | 2111 |
case R_390_32: |
2112 |
fprintf(outfile, " *(uint32_t *)(gen_code_ptr + %d) = %s + %d;\n",
|
|
2112 |
fprintf(outfile, " *(uint32_t *)(gen_code_ptr + %d) = %s + %d;\n", |
|
2113 | 2113 |
reloc_offset, relname, addend); |
2114 | 2114 |
break; |
2115 | 2115 |
case R_390_16: |
2116 |
fprintf(outfile, " *(uint16_t *)(gen_code_ptr + %d) = %s + %d;\n",
|
|
2116 |
fprintf(outfile, " *(uint16_t *)(gen_code_ptr + %d) = %s + %d;\n", |
|
2117 | 2117 |
reloc_offset, relname, addend); |
2118 | 2118 |
break; |
2119 | 2119 |
case R_390_8: |
2120 |
fprintf(outfile, " *(uint8_t *)(gen_code_ptr + %d) = %s + %d;\n",
|
|
2120 |
fprintf(outfile, " *(uint8_t *)(gen_code_ptr + %d) = %s + %d;\n", |
|
2121 | 2121 |
reloc_offset, relname, addend); |
2122 | 2122 |
break; |
2123 | 2123 |
default: |
... | ... | |
2273 | 2273 |
reloc_offset = rel->r_offset - start_offset; |
2274 | 2274 |
switch(type) { |
2275 | 2275 |
case R_SPARC_32: |
2276 |
fprintf(outfile, " *(uint32_t *)(gen_code_ptr + %d) = %s + %d;\n",
|
|
2276 |
fprintf(outfile, " *(uint32_t *)(gen_code_ptr + %d) = %s + %d;\n", |
|
2277 | 2277 |
reloc_offset, relname, addend); |
2278 | 2278 |
break; |
2279 | 2279 |
case R_SPARC_HI22: |
... | ... | |
2470 | 2470 |
reloc_offset = rel->r_offset - start_offset; |
2471 | 2471 |
switch(type) { |
2472 | 2472 |
case R_ARM_ABS32: |
2473 |
fprintf(outfile, " *(uint32_t *)(gen_code_ptr + %d) = %s + %d;\n",
|
|
2473 |
fprintf(outfile, " *(uint32_t *)(gen_code_ptr + %d) = %s + %d;\n", |
|
2474 | 2474 |
reloc_offset, relname, addend); |
2475 | 2475 |
break; |
2476 | 2476 |
case R_ARM_PC24: |
2477 | 2477 |
case R_ARM_JUMP24: |
2478 | 2478 |
case R_ARM_CALL: |
2479 |
fprintf(outfile, " arm_reloc_pc24((uint32_t *)(gen_code_ptr + %d), 0x%x, %s);\n",
|
|
2479 |
fprintf(outfile, " arm_reloc_pc24((uint32_t *)(gen_code_ptr + %d), 0x%x, %s);\n", |
|
2480 | 2480 |
reloc_offset, addend, relname); |
2481 | 2481 |
break; |
2482 | 2482 |
default: |
... | ... | |
2504 | 2504 |
switch(type) { |
2505 | 2505 |
case R_68K_32: |
2506 | 2506 |
fprintf(outfile, " /* R_68K_32 RELOC, offset %x */\n", rel->r_offset) ; |
2507 |
fprintf(outfile, " *(uint32_t *)(gen_code_ptr + %d) = %s + %#x;\n",
|
|
2507 |
fprintf(outfile, " *(uint32_t *)(gen_code_ptr + %d) = %s + %#x;\n", |
|
2508 | 2508 |
reloc_offset, relname, addend ); |
2509 | 2509 |
break; |
2510 | 2510 |
case R_68K_PC32: |
2511 | 2511 |
fprintf(outfile, " /* R_68K_PC32 RELOC, offset %x */\n", rel->r_offset); |
2512 |
fprintf(outfile, " *(uint32_t *)(gen_code_ptr + %d) = %s - (long)(gen_code_ptr + %#x) + %#x;\n",
|
|
2512 |
fprintf(outfile, " *(uint32_t *)(gen_code_ptr + %d) = %s - (long)(gen_code_ptr + %#x) + %#x;\n", |
|
2513 | 2513 |
reloc_offset, relname, reloc_offset, /*sym->st_value+*/ addend); |
2514 | 2514 |
break; |
2515 | 2515 |
default: |
... | ... | |
2652 | 2652 |
gen_code(name, sym->st_value, sym->st_size, outfile, 0); |
2653 | 2653 |
} |
2654 | 2654 |
} |
2655 |
|
|
2655 |
|
|
2656 | 2656 |
} else { |
2657 | 2657 |
/* generate big code generation switch */ |
2658 | 2658 |
|
... | ... | |
2695 | 2695 |
eliminating the neeed to jump around the pool. |
2696 | 2696 |
|
2697 | 2697 |
We currently generate: |
2698 |
|
|
2698 |
|
|
2699 | 2699 |
[ For this example we assume merging would move op1_pool out of range. |
2700 | 2700 |
In practice we should be able to combine many ops before the offset |
2701 | 2701 |
limits are reached. ] |
... | ... | |
2782 | 2782 |
" opc_ptr = opc_buf;\n" |
2783 | 2783 |
" opparam_ptr = opparam_buf;\n"); |
2784 | 2784 |
|
2785 |
/* Generate prologue, if needed. */
|
|
2785 |
/* Generate prologue, if needed. */ |
|
2786 | 2786 |
|
2787 | 2787 |
fprintf(outfile, |
2788 | 2788 |
" for(;;) {\n"); |
... | ... | |
2808 | 2808 |
name = get_sym_name(sym); |
2809 | 2809 |
if (strstart(name, OP_PREFIX, NULL)) { |
2810 | 2810 |
#if 0 |
2811 |
printf("%4d: %s pos=0x%08x len=%d\n",
|
|
2811 |
printf("%4d: %s pos=0x%08x len=%d\n", |
|
2812 | 2812 |
i, name, sym->st_value, sym->st_size); |
2813 | 2813 |
#endif |
2814 | 2814 |
#if defined(CONFIG_FORMAT_ELF) || defined(CONFIG_FORMAT_COFF) |
... | ... | |
2850 | 2850 |
"plt_target, plt_offset);\n }\n"); |
2851 | 2851 |
#endif |
2852 | 2852 |
|
2853 |
/* generate some code patching */
|
|
2853 |
/* generate some code patching */ |
|
2854 | 2854 |
#ifdef HOST_ARM |
2855 | 2855 |
fprintf(outfile, |
2856 | 2856 |
"if (arm_data_ptr != arm_data_table + ARM_LDR_TABLE_SIZE)\n" |
Also available in: Unified diff