Annotation of qemu/elf_ops.h, revision 1.1.1.4

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;
        !            70:     } else if (key->st_value > sym->st_value + sym->st_size) {
        !            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));
        !            85:     if (sym != 0) {
        !            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;
                    188:     uint64_t addr, low = 0, 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.2   root      197:     if (ELF_MACHINE != ehdr.e_machine)
                    198:         goto fail;
                    199: 
1.1       root      200:     if (pentry)
1.1.1.3   root      201:        *pentry = (uint64_t)(elf_sword)ehdr.e_entry;
1.1       root      202: 
                    203:     glue(load_symbols, SZ)(&ehdr, fd, must_swab);
                    204: 
                    205:     size = ehdr.e_phnum * sizeof(phdr[0]);
                    206:     lseek(fd, ehdr.e_phoff, SEEK_SET);
                    207:     phdr = qemu_mallocz(size);
                    208:     if (!phdr)
                    209:         goto fail;
                    210:     if (read(fd, phdr, size) != size)
                    211:         goto fail;
                    212:     if (must_swab) {
                    213:         for(i = 0; i < ehdr.e_phnum; i++) {
                    214:             ph = &phdr[i];
                    215:             glue(bswap_phdr, SZ)(ph);
                    216:         }
                    217:     }
1.1.1.3   root      218: 
1.1       root      219:     total_size = 0;
                    220:     for(i = 0; i < ehdr.e_phnum; i++) {
                    221:         ph = &phdr[i];
                    222:         if (ph->p_type == PT_LOAD) {
                    223:             mem_size = ph->p_memsz;
                    224:             /* XXX: avoid allocating */
                    225:             data = qemu_mallocz(mem_size);
                    226:             if (ph->p_filesz > 0) {
                    227:                 if (lseek(fd, ph->p_offset, SEEK_SET) < 0)
                    228:                     goto fail;
                    229:                 if (read(fd, data, ph->p_filesz) != ph->p_filesz)
                    230:                     goto fail;
                    231:             }
1.1.1.4 ! root      232:             /* address_offset is hack for kernel images that are
        !           233:                linked at the wrong physical address.  */
        !           234:             addr = ph->p_paddr + address_offset;
1.1       root      235: 
                    236:             cpu_physical_memory_write_rom(addr, data, mem_size);
                    237: 
                    238:             total_size += mem_size;
1.1.1.3   root      239:             if (!low || addr < low)
                    240:                 low = addr;
                    241:             if (!high || (addr + mem_size) > high)
                    242:                 high = addr + mem_size;
1.1       root      243: 
                    244:             qemu_free(data);
                    245:             data = NULL;
                    246:         }
                    247:     }
                    248:     qemu_free(phdr);
1.1.1.3   root      249:     if (lowaddr)
                    250:         *lowaddr = (uint64_t)(elf_sword)low;
                    251:     if (highaddr)
                    252:         *highaddr = (uint64_t)(elf_sword)high;
1.1       root      253:     return total_size;
                    254:  fail:
                    255:     qemu_free(data);
                    256:     qemu_free(phdr);
                    257:     return -1;
                    258: }

unix.superglobalmegacorp.com