/[qemu]/qemu/dyngen.c
ViewVC logotype

Diff of /qemu/dyngen.c

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

revision 1.17 by bellard, Mon Jun 2 20:38:08 2003 UTC revision 1.18 by bellard, Thu Jun 5 00:56:05 2003 UTC
# Line 95  typedef uint64_t host_ulong; Line 95  typedef uint64_t host_ulong;
95  #define swabls(x) swab64s(x)  #define swabls(x) swab64s(x)
96  #endif  #endif
97    
98    #ifdef ELF_USES_RELOCA
99    #define SHT_RELOC SHT_RELA
100    #else
101    #define SHT_RELOC SHT_REL
102    #endif
103    
104  #include "thunk.h"  #include "thunk.h"
105    
106  /* all dynamically generated functions begin with this code */  /* all dynamically generated functions begin with this code */
# Line 170  void elf_swap_phdr(struct elf_phdr *h) Line 176  void elf_swap_phdr(struct elf_phdr *h)
176      swabls(&h->p_align);                /* Segment alignment */      swabls(&h->p_align);                /* Segment alignment */
177  }  }
178    
179    void elf_swap_rel(ELF_RELOC *rel)
180    {
181        swabls(&rel->r_offset);
182        swabls(&rel->r_info);
183    #ifdef ELF_USES_RELOCA
184        swabls(&rel->r_addend);
185    #endif
186    }
187    
188  /* ELF file info */  /* ELF file info */
189  int do_swap;  int do_swap;
190  struct elf_shdr *shdr;  struct elf_shdr *shdr;
191    uint8_t **sdata;
192  struct elfhdr ehdr;  struct elfhdr ehdr;
193  ElfW(Sym) *symtab;  ElfW(Sym) *symtab;
194  int nb_syms;  int nb_syms;
195  char *strtab;  char *strtab;
196  /* data section */  int text_shndx;
 uint8_t *data_data, *sdata_data;  
 int data_shndx, sdata_shndx;  
197    
198  uint16_t get16(uint16_t *p)  uint16_t get16(uint16_t *p)
199  {  {
# Line 243  struct elf_shdr *find_elf_section(struct Line 257  struct elf_shdr *find_elf_section(struct
257      return NULL;      return NULL;
258  }  }
259    
260    int find_reloc(int sh_index)
261    {
262        struct elf_shdr *sec;
263        int i;
264    
265        for(i = 0; i < ehdr.e_shnum; i++) {
266            sec = &shdr[i];
267            if (sec->sh_type == SHT_RELOC && sec->sh_info == sh_index)
268                return i;
269        }
270        return 0;
271    }
272    
273  void *load_data(int fd, long offset, unsigned int size)  void *load_data(int fd, long offset, unsigned int size)
274  {  {
275      char *data;      char *data;
# Line 278  int strstart(const char *str, const char Line 305  int strstart(const char *str, const char
305    
306  /* generate op code */  /* generate op code */
307  void gen_code(const char *name, host_ulong offset, host_ulong size,  void gen_code(const char *name, host_ulong offset, host_ulong size,
308                FILE *outfile, uint8_t *text, ELF_RELOC *relocs, int nb_relocs, int reloc_sh_type,                FILE *outfile, uint8_t *text, ELF_RELOC *relocs, int nb_relocs,
309                int gen_switch)                int gen_switch)
310  {  {
311      int copy_size = 0;      int copy_size = 0;
# Line 500  void gen_code(const char *name, host_ulo Line 527  void gen_code(const char *name, host_ulo
527                  sym_name = strtab + sym->st_name;                  sym_name = strtab + sym->st_name;
528                  if (strstart(sym_name, "__op_label", &p)) {                  if (strstart(sym_name, "__op_label", &p)) {
529                      uint8_t *ptr;                      uint8_t *ptr;
530                        int addend;
531                        unsigned long offset;
532                        
533                      /* test if the variable refers to a label inside                      /* test if the variable refers to a label inside
534                         the code we are generating */                         the code we are generating */
535                      if (sym->st_shndx == data_shndx)                      ptr = sdata[sym->st_shndx];
536                          ptr = data_data;                      if (!ptr)
537                      else if (sym->st_shndx == sdata_shndx)                          error("__op_labelN in invalid section");
538                          ptr = sdata_data;                      offset = sym->st_value;
539                      else                      addend = 0;
540                          error("__op_labelN symbols must be in .data or .sdata section");  #ifdef ELF_USES_RELOCA
541                      val = *(target_ulong *)(ptr + sym->st_value);                      {
542                            int reloc_shndx, nb_relocs1, j;
543    
544                            /* try to find a matching relocation */
545                            reloc_shndx = find_reloc(sym->st_shndx);
546                            if (reloc_shndx) {
547                                nb_relocs1 = shdr[reloc_shndx].sh_size /
548                                    shdr[reloc_shndx].sh_entsize;
549                                rel = (ELF_RELOC *)sdata[reloc_shndx];
550                                for(j = 0; j < nb_relocs1; j++) {
551                                    if (rel->r_offset == offset) {
552                                        addend = rel->r_addend;
553                                        break;
554                                    }
555                                    rel++;
556                                }
557                            }
558                        }
559    #endif                    
560                        val = *(target_ulong *)(ptr + offset);
561                        val += addend;
562    
563                      if (val >= start_offset && val < start_offset + copy_size) {                      if (val >= start_offset && val < start_offset + copy_size) {
564                          n = strtol(p, NULL, 10);                          n = strtol(p, NULL, 10);
565                          fprintf(outfile, "    label_offsets[%d] = %d + (gen_code_ptr - gen_code_buf);\n", n, val - start_offset);                          fprintf(outfile, "    label_offsets[%d] = %d + (gen_code_ptr - gen_code_buf);\n", n, val - start_offset);
# Line 886  int load_elf(const char *filename, FILE Line 936  int load_elf(const char *filename, FILE
936      ElfW(Sym) *sym;      ElfW(Sym) *sym;
937      char *shstr;      char *shstr;
938      uint8_t *text;      uint8_t *text;
939      void *relocs;      ELF_RELOC *relocs;
940      int nb_relocs, reloc_sh_type;      int nb_relocs;
941        ELF_RELOC *rel;
942            
943      fd = open(filename, O_RDONLY);      fd = open(filename, O_RDONLY);
944      if (fd < 0)      if (fd < 0)
# Line 926  int load_elf(const char *filename, FILE Line 977  int load_elf(const char *filename, FILE
977          }          }
978      }      }
979    
980        /* read all section data */
981        sdata = malloc(sizeof(void *) * ehdr.e_shnum);
982        memset(sdata, 0, sizeof(void *) * ehdr.e_shnum);
983        
984        for(i = 0;i < ehdr.e_shnum; i++) {
985            sec = &shdr[i];
986            if (sec->sh_type != SHT_NOBITS)
987                sdata[i] = load_data(fd, sec->sh_offset, sec->sh_size);
988        }
989    
990      sec = &shdr[ehdr.e_shstrndx];      sec = &shdr[ehdr.e_shstrndx];
991      shstr = load_data(fd, sec->sh_offset, sec->sh_size);      shstr = sdata[ehdr.e_shstrndx];
992    
993        /* swap relocations */
994        for(i = 0; i < ehdr.e_shnum; i++) {
995            sec = &shdr[i];
996            if (sec->sh_type == SHT_RELOC) {
997                nb_relocs = sec->sh_size / sec->sh_entsize;
998                if (do_swap) {
999                    for(j = 0, rel = (ELF_RELOC *)sdata[i]; j < nb_relocs; j++, rel++)
1000                        elf_swap_rel(rel);
1001                }
1002            }
1003        }
1004      /* text section */      /* text section */
1005    
1006      text_sec = find_elf_section(shdr, ehdr.e_shnum, shstr, ".text");      text_sec = find_elf_section(shdr, ehdr.e_shnum, shstr, ".text");
1007      if (!text_sec)      if (!text_sec)
1008          error("could not find .text section");          error("could not find .text section");
1009      text = load_data(fd, text_sec->sh_offset, text_sec->sh_size);      text_shndx = text_sec - shdr;
1010        text = sdata[text_shndx];
1011    
     data_shndx = -1;  
     sec = find_elf_section(shdr, ehdr.e_shnum, shstr, ".data");  
     if (sec) {  
         data_shndx = sec - shdr;  
         data_data = load_data(fd, sec->sh_offset, sec->sh_size);  
     }  
     sdata_shndx = -1;  
     sec = find_elf_section(shdr, ehdr.e_shnum, shstr, ".sdata");  
     if (sec) {  
         sdata_shndx = sec - shdr;  
         sdata_data = load_data(fd, sec->sh_offset, sec->sh_size);  
     }  
       
1012      /* find text relocations, if any */      /* find text relocations, if any */
     nb_relocs = 0;  
1013      relocs = NULL;      relocs = NULL;
1014      reloc_sh_type = 0;      nb_relocs = 0;
1015      for(i = 0; i < ehdr.e_shnum; i++) {      i = find_reloc(text_shndx);
1016          sec = &shdr[i];      if (i != 0) {
1017          if ((sec->sh_type == SHT_REL || sec->sh_type == SHT_RELA) &&          relocs = (ELF_RELOC *)sdata[i];
1018              sec->sh_info == (text_sec - shdr)) {          nb_relocs = shdr[i].sh_size / shdr[i].sh_entsize;
             reloc_sh_type = sec->sh_type;  
             relocs = load_data(fd, sec->sh_offset, sec->sh_size);  
             nb_relocs = sec->sh_size / sec->sh_entsize;  
             if (do_swap) {  
                 if (sec->sh_type == SHT_REL) {  
                     ElfW(Rel) *rel = relocs;  
                     for(j = 0, rel = relocs; j < nb_relocs; j++, rel++) {  
                         swabls(&rel->r_offset);  
                         swabls(&rel->r_info);  
                     }  
                 } else {  
                     ElfW(Rela) *rel = relocs;  
                     for(j = 0, rel = relocs; j < nb_relocs; j++, rel++) {  
                         swabls(&rel->r_offset);  
                         swabls(&rel->r_info);  
                         swabls(&rel->r_addend);  
                     }  
                 }  
             }  
             break;  
         }  
1019      }      }
1020    
1021      symtab_sec = find_elf_section(shdr, ehdr.e_shnum, shstr, ".symtab");      symtab_sec = find_elf_section(shdr, ehdr.e_shnum, shstr, ".symtab");
# Line 985  int load_elf(const char *filename, FILE Line 1023  int load_elf(const char *filename, FILE
1023          error("could not find .symtab section");          error("could not find .symtab section");
1024      strtab_sec = &shdr[symtab_sec->sh_link];      strtab_sec = &shdr[symtab_sec->sh_link];
1025    
1026      symtab = load_data(fd, symtab_sec->sh_offset, symtab_sec->sh_size);      symtab = (ElfW(Sym) *)sdata[symtab_sec - shdr];
1027      strtab = load_data(fd, strtab_sec->sh_offset, strtab_sec->sh_size);      strtab = sdata[symtab_sec->sh_link];
1028            
1029      nb_syms = symtab_sec->sh_size / sizeof(ElfW(Sym));      nb_syms = symtab_sec->sh_size / sizeof(ElfW(Sym));
1030      if (do_swap) {      if (do_swap) {
# Line 1005  int load_elf(const char *filename, FILE Line 1043  int load_elf(const char *filename, FILE
1043              name = strtab + sym->st_name;              name = strtab + sym->st_name;
1044              if (strstart(name, OP_PREFIX, &p)) {              if (strstart(name, OP_PREFIX, &p)) {
1045                  gen_code(name, sym->st_value, sym->st_size, outfile,                  gen_code(name, sym->st_value, sym->st_size, outfile,
1046                           text, relocs, nb_relocs, reloc_sh_type, 2);                           text, relocs, nb_relocs, 2);
1047              }              }
1048          }          }
1049      } else {      } else {
# Line 1071  fprintf(outfile, Line 1109  fprintf(outfile,
1109                  if (sym->st_shndx != (text_sec - shdr))                  if (sym->st_shndx != (text_sec - shdr))
1110                      error("invalid section for opcode (0x%x)", sym->st_shndx);                      error("invalid section for opcode (0x%x)", sym->st_shndx);
1111                  gen_code(name, sym->st_value, sym->st_size, outfile,                  gen_code(name, sym->st_value, sym->st_size, outfile,
1112                           text, relocs, nb_relocs, reloc_sh_type, 1);                           text, relocs, nb_relocs, 1);
1113              }              }
1114          }          }
1115    
# Line 1126  fprintf(outfile, Line 1164  fprintf(outfile,
1164                  if (sym->st_shndx != (text_sec - shdr))                  if (sym->st_shndx != (text_sec - shdr))
1165                      error("invalid section for opcode (0x%x)", sym->st_shndx);                      error("invalid section for opcode (0x%x)", sym->st_shndx);
1166                  gen_code(name, sym->st_value, sym->st_size, outfile,                  gen_code(name, sym->st_value, sym->st_size, outfile,
1167                           text, relocs, nb_relocs, reloc_sh_type, 0);                           text, relocs, nb_relocs, 0);
1168              }              }
1169          }          }
1170      }      }

Legend:
Removed from v.1.17  
changed lines
  Added in v.1.18

savannah-hackers-public@gnu.org
ViewVC Help
Powered by ViewVC 1.1.26