~vcs-imports/qemu/git

« back to all changes in this revision

Viewing changes to elf_ops.h

  • Committer: Blue Swirl
  • Date: 2009-08-31 15:14:40 UTC
  • Revision ID: git-v1:528e93a9787ccfc59582a44035f5f342caf5b84f
Fix breakage due to __thread

Thread-local storage is not supported on all hosts.

Signed-off-by: Blue Swirl <blauwirbel@gmail.com>

Show diffs side-by-side

added added

removed removed

Lines of Context:
60
60
    return NULL;
61
61
}
62
62
 
 
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 != NULL) {
 
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
 
63
101
static int glue(load_symbols, SZ)(struct elfhdr *ehdr, int fd, int must_swab)
64
102
{
65
103
    struct elf_shdr *symtab, *strtab, *shdr_table = NULL;
66
104
    struct elf_sym *syms = NULL;
67
 
#if (SZ == 64)
68
 
    struct elf32_sym *syms32 = NULL;
69
 
#endif
70
105
    struct syminfo *s;
71
106
    int nsyms, i;
72
107
    char *str = NULL;
90
125
        goto fail;
91
126
 
92
127
    nsyms = symtab->sh_size / sizeof(struct elf_sym);
93
 
#if (SZ == 64)
94
 
    syms32 = qemu_mallocz(nsyms * sizeof(struct elf32_sym));
95
 
#endif
96
 
    for (i = 0; i < nsyms; i++) {
 
128
 
 
129
    i = 0;
 
130
    while (i < nsyms) {
97
131
        if (must_swab)
98
132
            glue(bswap_sym, SZ)(&syms[i]);
99
 
#if (SZ == 64)
100
 
        syms32[i].st_name = syms[i].st_name;
101
 
        syms32[i].st_info = syms[i].st_info;
102
 
        syms32[i].st_other = syms[i].st_other;
103
 
        syms32[i].st_shndx = syms[i].st_shndx;
104
 
        syms32[i].st_value = syms[i].st_value & 0xffffffff;
105
 
        syms32[i].st_size = syms[i].st_size & 0xffffffff;
 
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;
106
147
#endif
 
148
        i++;
107
149
    }
 
150
    syms = qemu_realloc(syms, nsyms * sizeof(*syms));
 
151
 
 
152
    qsort(syms, nsyms, sizeof(*syms), glue(symcmp, SZ));
 
153
 
108
154
    /* String table */
109
155
    if (symtab->sh_link >= ehdr->e_shnum)
110
156
        goto fail;
112
158
 
113
159
    str = load_at(fd, strtab->sh_offset, strtab->sh_size);
114
160
    if (!str)
115
 
        goto fail;
 
161
        goto fail;
116
162
 
117
163
    /* Commit */
118
164
    s = qemu_mallocz(sizeof(*s));
119
 
#if (SZ == 64)
120
 
    s->disas_symtab = syms32;
121
 
    qemu_free(syms);
122
 
#else
123
 
    s->disas_symtab = syms;
124
 
#endif
 
165
    s->lookup_symbol = glue(lookup_symbol, SZ);
 
166
    glue(s->disas_symtab.elf, SZ) = syms;
125
167
    s->disas_num_syms = nsyms;
126
168
    s->disas_strtab = str;
127
169
    s->next = syminfos;
129
171
    qemu_free(shdr_table);
130
172
    return 0;
131
173
 fail:
132
 
#if (SZ == 64)
133
 
    qemu_free(syms32);
134
 
#endif
135
174
    qemu_free(syms);
136
175
    qemu_free(str);
137
176
    qemu_free(shdr_table);
138
177
    return -1;
139
178
}
140
179
 
141
 
static int glue(load_elf, SZ)(int fd, int64_t virt_to_phys_addend,
 
180
static int glue(load_elf, SZ)(int fd, int64_t address_offset,
142
181
                              int must_swab, uint64_t *pentry,
143
182
                              uint64_t *lowaddr, uint64_t *highaddr)
144
183
{
146
185
    struct elf_phdr *phdr = NULL, *ph;
147
186
    int size, i, total_size;
148
187
    elf_word mem_size;
149
 
    uint64_t addr, low = 0, high = 0;
 
188
    uint64_t addr, low = (uint64_t)-1, high = 0;
150
189
    uint8_t *data = NULL;
151
190
 
152
191
    if (read(fd, &ehdr, sizeof(ehdr)) != sizeof(ehdr))
155
194
        glue(bswap_ehdr, SZ)(&ehdr);
156
195
    }
157
196
 
158
 
    if (ELF_MACHINE != ehdr.e_machine)
159
 
        goto fail;
 
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
    }
160
212
 
161
213
    if (pentry)
162
214
        *pentry = (uint64_t)(elf_sword)ehdr.e_entry;
190
242
                if (read(fd, data, ph->p_filesz) != ph->p_filesz)
191
243
                    goto fail;
192
244
            }
193
 
            addr = ph->p_vaddr + virt_to_phys_addend;
 
245
            /* address_offset is hack for kernel images that are
 
246
               linked at the wrong physical address.  */
 
247
            addr = ph->p_paddr + address_offset;
194
248
 
195
249
            cpu_physical_memory_write_rom(addr, data, mem_size);
196
250
 
197
251
            total_size += mem_size;
198
 
            if (!low || addr < low)
 
252
            if (addr < low)
199
253
                low = addr;
200
 
            if (!high || (addr + mem_size) > high)
 
254
            if ((addr + mem_size) > high)
201
255
                high = addr + mem_size;
202
256
 
203
257
            qemu_free(data);