Annotation of qemu/elf_ops.h, revision 1.1.1.5

1.1       root        1: static void glue(bswap_ehdr, SZ)(struct elfhdr *ehdr)
                      2: {
                      3:     bswap16s(&ehdr->e_type);                   /* Object file type */
                      4:     bswap16s(&ehdr->e_machine);                /* Architecture */
                      5:     bswap32s(&ehdr->e_version);                /* Object file version */
                      6:     bswapSZs(&ehdr->e_entry);          /* Entry point virtual address */
                      7:     bswapSZs(&ehdr->e_phoff);          /* Program header table file offset */
                      8:     bswapSZs(&ehdr->e_shoff);          /* Section header table file offset */
                      9:     bswap32s(&ehdr->e_flags);          /* Processor-specific flags */
                     10:     bswap16s(&ehdr->e_ehsize);         /* ELF header size in bytes */
                     11:     bswap16s(&ehdr->e_phentsize);              /* Program header table entry size */
                     12:     bswap16s(&ehdr->e_phnum);          /* Program header table entry count */
                     13:     bswap16s(&ehdr->e_shentsize);              /* Section header table entry size */
                     14:     bswap16s(&ehdr->e_shnum);          /* Section header table entry count */
                     15:     bswap16s(&ehdr->e_shstrndx);               /* Section header string table index */
                     16: }
                     17: 
                     18: static void glue(bswap_phdr, SZ)(struct elf_phdr *phdr)
                     19: {
                     20:     bswap32s(&phdr->p_type);                   /* Segment type */
                     21:     bswapSZs(&phdr->p_offset);         /* Segment file offset */
                     22:     bswapSZs(&phdr->p_vaddr);          /* Segment virtual address */
                     23:     bswapSZs(&phdr->p_paddr);          /* Segment physical address */
                     24:     bswapSZs(&phdr->p_filesz);         /* Segment size in file */
                     25:     bswapSZs(&phdr->p_memsz);          /* Segment size in memory */
                     26:     bswap32s(&phdr->p_flags);          /* Segment flags */
                     27:     bswapSZs(&phdr->p_align);          /* Segment alignment */
                     28: }
                     29: 
                     30: static void glue(bswap_shdr, SZ)(struct elf_shdr *shdr)
                     31: {
                     32:     bswap32s(&shdr->sh_name);
                     33:     bswap32s(&shdr->sh_type);
                     34:     bswapSZs(&shdr->sh_flags);
                     35:     bswapSZs(&shdr->sh_addr);
                     36:     bswapSZs(&shdr->sh_offset);
                     37:     bswapSZs(&shdr->sh_size);
                     38:     bswap32s(&shdr->sh_link);
                     39:     bswap32s(&shdr->sh_info);
                     40:     bswapSZs(&shdr->sh_addralign);
                     41:     bswapSZs(&shdr->sh_entsize);
                     42: }
                     43: 
                     44: static void glue(bswap_sym, SZ)(struct elf_sym *sym)
                     45: {
                     46:     bswap32s(&sym->st_name);
                     47:     bswapSZs(&sym->st_value);
                     48:     bswapSZs(&sym->st_size);
                     49:     bswap16s(&sym->st_shndx);
                     50: }
                     51: 
1.1.1.3   root       52: static struct elf_shdr *glue(find_section, SZ)(struct elf_shdr *shdr_table,
1.1       root       53:                                                int n, int type)
                     54: {
                     55:     int i;
                     56:     for(i=0;i<n;i++) {
                     57:         if (shdr_table[i].sh_type == type)
                     58:             return shdr_table + i;
                     59:     }
                     60:     return NULL;
                     61: }
                     62: 
1.1.1.4   root       63: static int glue(symfind, SZ)(const void *s0, const void *s1)
                     64: {
                     65:     struct elf_sym *key = (struct elf_sym *)s0;
                     66:     struct elf_sym *sym = (struct elf_sym *)s1;
                     67:     int result = 0;
                     68:     if (key->st_value < sym->st_value) {
                     69:         result = -1;
1.1.1.5 ! root       70:     } else if (key->st_value >= sym->st_value + sym->st_size) {
1.1.1.4   root       71:         result = 1;
                     72:     }
                     73:     return result;
                     74: }
                     75: 
                     76: static const char *glue(lookup_symbol, SZ)(struct syminfo *s, target_ulong orig_addr)
                     77: {
                     78:     struct elf_sym *syms = glue(s->disas_symtab.elf, SZ);
                     79:     struct elf_sym key;
                     80:     struct elf_sym *sym;
                     81: 
                     82:     key.st_value = orig_addr;
                     83: 
                     84:     sym = bsearch(&key, syms, s->disas_num_syms, sizeof(*syms), glue(symfind, SZ));
1.1.1.5 ! root       85:     if (sym != NULL) {
1.1.1.4   root       86:         return s->disas_strtab + sym->st_name;
                     87:     }
                     88: 
                     89:     return "";
                     90: }
                     91: 
                     92: static int glue(symcmp, SZ)(const void *s0, const void *s1)
                     93: {
                     94:     struct elf_sym *sym0 = (struct elf_sym *)s0;
                     95:     struct elf_sym *sym1 = (struct elf_sym *)s1;
                     96:     return (sym0->st_value < sym1->st_value)
                     97:         ? -1
                     98:         : ((sym0->st_value > sym1->st_value) ? 1 : 0);
                     99: }
                    100: 
1.1       root      101: static int glue(load_symbols, SZ)(struct elfhdr *ehdr, int fd, int must_swab)
                    102: {
                    103:     struct elf_shdr *symtab, *strtab, *shdr_table = NULL;
                    104:     struct elf_sym *syms = NULL;
                    105:     struct syminfo *s;
                    106:     int nsyms, i;
                    107:     char *str = NULL;
                    108: 
1.1.1.3   root      109:     shdr_table = load_at(fd, ehdr->e_shoff,
1.1       root      110:                          sizeof(struct elf_shdr) * ehdr->e_shnum);
                    111:     if (!shdr_table)
                    112:         return -1;
1.1.1.3   root      113: 
1.1       root      114:     if (must_swab) {
                    115:         for (i = 0; i < ehdr->e_shnum; i++) {
                    116:             glue(bswap_shdr, SZ)(shdr_table + i);
                    117:         }
                    118:     }
1.1.1.3   root      119: 
1.1       root      120:     symtab = glue(find_section, SZ)(shdr_table, ehdr->e_shnum, SHT_SYMTAB);
                    121:     if (!symtab)
                    122:         goto fail;
                    123:     syms = load_at(fd, symtab->sh_offset, symtab->sh_size);
                    124:     if (!syms)
                    125:         goto fail;
                    126: 
                    127:     nsyms = symtab->sh_size / sizeof(struct elf_sym);
1.1.1.4   root      128: 
                    129:     i = 0;
                    130:     while (i < nsyms) {
1.1       root      131:         if (must_swab)
                    132:             glue(bswap_sym, SZ)(&syms[i]);
1.1.1.4   root      133:         /* We are only interested in function symbols.
                    134:            Throw everything else away.  */
                    135:         if (syms[i].st_shndx == SHN_UNDEF ||
                    136:                 syms[i].st_shndx >= SHN_LORESERVE ||
                    137:                 ELF_ST_TYPE(syms[i].st_info) != STT_FUNC) {
                    138:             nsyms--;
                    139:             if (i < nsyms) {
                    140:                 syms[i] = syms[nsyms];
                    141:             }
                    142:             continue;
                    143:         }
                    144: #if defined(TARGET_ARM) || defined (TARGET_MIPS)
                    145:         /* The bottom address bit marks a Thumb or MIPS16 symbol.  */
                    146:         syms[i].st_value &= ~(target_ulong)1;
1.1       root      147: #endif
1.1.1.4   root      148:         i++;
1.1       root      149:     }
1.1.1.4   root      150:     syms = qemu_realloc(syms, nsyms * sizeof(*syms));
                    151: 
                    152:     qsort(syms, nsyms, sizeof(*syms), glue(symcmp, SZ));
                    153: 
1.1       root      154:     /* String table */
                    155:     if (symtab->sh_link >= ehdr->e_shnum)
                    156:         goto fail;
                    157:     strtab = &shdr_table[symtab->sh_link];
                    158: 
                    159:     str = load_at(fd, strtab->sh_offset, strtab->sh_size);
                    160:     if (!str)
1.1.1.4   root      161:         goto fail;
1.1       root      162: 
                    163:     /* Commit */
                    164:     s = qemu_mallocz(sizeof(*s));
1.1.1.4   root      165:     s->lookup_symbol = glue(lookup_symbol, SZ);
                    166:     glue(s->disas_symtab.elf, SZ) = syms;
1.1       root      167:     s->disas_num_syms = nsyms;
                    168:     s->disas_strtab = str;
                    169:     s->next = syminfos;
                    170:     syminfos = s;
                    171:     qemu_free(shdr_table);
                    172:     return 0;
                    173:  fail:
                    174:     qemu_free(syms);
                    175:     qemu_free(str);
                    176:     qemu_free(shdr_table);
                    177:     return -1;
                    178: }
                    179: 
1.1.1.4   root      180: static int glue(load_elf, SZ)(int fd, int64_t address_offset,
1.1.1.3   root      181:                               int must_swab, uint64_t *pentry,
                    182:                               uint64_t *lowaddr, uint64_t *highaddr)
1.1       root      183: {
                    184:     struct elfhdr ehdr;
                    185:     struct elf_phdr *phdr = NULL, *ph;
                    186:     int size, i, total_size;
1.1.1.3   root      187:     elf_word mem_size;
1.1.1.5 ! root      188:     uint64_t addr, low = (uint64_t)-1, high = 0;
1.1       root      189:     uint8_t *data = NULL;
                    190: 
                    191:     if (read(fd, &ehdr, sizeof(ehdr)) != sizeof(ehdr))
                    192:         goto fail;
                    193:     if (must_swab) {
                    194:         glue(bswap_ehdr, SZ)(&ehdr);
                    195:     }
                    196: 
1.1.1.5 ! root      197:     switch (ELF_MACHINE) {
        !           198:         case EM_PPC64:
        !           199:             if (EM_PPC64 != ehdr.e_machine)
        !           200:                 if (EM_PPC != ehdr.e_machine)
        !           201:                     goto fail;
        !           202:             break;
        !           203:         case EM_X86_64:
        !           204:             if (EM_X86_64 != ehdr.e_machine)
        !           205:                 if (EM_386 != ehdr.e_machine)
        !           206:                     goto fail;
        !           207:             break;
        !           208:         default:
        !           209:             if (ELF_MACHINE != ehdr.e_machine)
        !           210:                 goto fail;
        !           211:     }
1.1.1.2   root      212: 
1.1       root      213:     if (pentry)
1.1.1.3   root      214:        *pentry = (uint64_t)(elf_sword)ehdr.e_entry;
1.1       root      215: 
                    216:     glue(load_symbols, SZ)(&ehdr, fd, must_swab);
                    217: 
                    218:     size = ehdr.e_phnum * sizeof(phdr[0]);
                    219:     lseek(fd, ehdr.e_phoff, SEEK_SET);
                    220:     phdr = qemu_mallocz(size);
                    221:     if (!phdr)
                    222:         goto fail;
                    223:     if (read(fd, phdr, size) != size)
                    224:         goto fail;
                    225:     if (must_swab) {
                    226:         for(i = 0; i < ehdr.e_phnum; i++) {
                    227:             ph = &phdr[i];
                    228:             glue(bswap_phdr, SZ)(ph);
                    229:         }
                    230:     }
1.1.1.3   root      231: 
1.1       root      232:     total_size = 0;
                    233:     for(i = 0; i < ehdr.e_phnum; i++) {
                    234:         ph = &phdr[i];
                    235:         if (ph->p_type == PT_LOAD) {
                    236:             mem_size = ph->p_memsz;
                    237:             /* XXX: avoid allocating */
                    238:             data = qemu_mallocz(mem_size);
                    239:             if (ph->p_filesz > 0) {
                    240:                 if (lseek(fd, ph->p_offset, SEEK_SET) < 0)
                    241:                     goto fail;
                    242:                 if (read(fd, data, ph->p_filesz) != ph->p_filesz)
                    243:                     goto fail;
                    244:             }
1.1.1.4   root      245:             /* address_offset is hack for kernel images that are
                    246:                linked at the wrong physical address.  */
                    247:             addr = ph->p_paddr + address_offset;
1.1       root      248: 
                    249:             cpu_physical_memory_write_rom(addr, data, mem_size);
                    250: 
                    251:             total_size += mem_size;
1.1.1.5 ! root      252:             if (addr < low)
1.1.1.3   root      253:                 low = addr;
1.1.1.5 ! root      254:             if ((addr + mem_size) > high)
1.1.1.3   root      255:                 high = addr + mem_size;
1.1       root      256: 
                    257:             qemu_free(data);
                    258:             data = NULL;
                    259:         }
                    260:     }
                    261:     qemu_free(phdr);
1.1.1.3   root      262:     if (lowaddr)
                    263:         *lowaddr = (uint64_t)(elf_sword)low;
                    264:     if (highaddr)
                    265:         *highaddr = (uint64_t)(elf_sword)high;
1.1       root      266:     return total_size;
                    267:  fail:
                    268:     qemu_free(data);
                    269:     qemu_free(phdr);
                    270:     return -1;
                    271: }

unix.superglobalmegacorp.com