OpenCores
URL https://opencores.org/ocsvn/openrisc_me/openrisc_me/trunk

Subversion Repositories openrisc_me

[/] [openrisc/] [trunk/] [or1ksim/] [cpu/] [or32/] [dyngen-elf.c] - Blame information for rev 36

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 19 jeremybenn
/* dyngen-elf.c -- Elf parser for dyngen
2
   Copyright (C) 2005 György `nog' Jeney, nog@sdf.lonestar.org
3
 
4
This file is part of OpenRISC 1000 Architectural Simulator.
5
 
6
This program is free software; you can redistribute it and/or modify
7
it under the terms of the GNU General Public License as published by
8
the Free Software Foundation; either version 2 of the License, or
9
(at your option) any later version.
10
 
11
This program is distributed in the hope that it will be useful,
12
but WITHOUT ANY WARRANTY; without even the implied warranty of
13
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14
GNU General Public License for more details.
15
 
16
You should have received a copy of the GNU General Public License
17
along with this program; if not, write to the Free Software
18
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
19
 
20
 
21
#include <stdio.h>
22
#include <stdlib.h>
23
#include <stdint.h>
24
#include <assert.h>
25
 
26
#include <elf.h>
27
 
28
#include "dyngen.h"
29
 
30
struct elf_obj {
31
  Elf32_Ehdr e_hdr;
32
  Elf32_Shdr *e_shdrs;
33
  void **e_sections;
34
  Elf32_Sym *e_syms; /* The symbol table in the elf file */
35
  unsigned int e_sym_num; /* The number of symbols */
36
  unsigned int e_sym_str_tab; /* The string-table associated with symbols */
37
  Elf32_Rel *e_rels;
38
  unsigned int e_rel_num; /* The number of relocations (in e_rel) */
39
  unsigned int e_rel_sym;
40
  unsigned int e_rel_sec; /* The section to modify */
41
  Elf32_Rela *e_relas;
42
  unsigned int e_rela_num; /* The number of relocations (in e_rela) */
43
  unsigned int e_rela_sym;
44
  unsigned int e_rela_sec; /* The section to modify */
45
};
46
 
47
void *elf_open_obj(const char *file)
48
{
49
  struct elf_obj *obj;
50
  FILE *f;
51
  int i;
52
 
53
  if(!(obj = malloc(sizeof(struct elf_obj)))) {
54
    fprintf(stderr, "OOM\n");
55
    return NULL;
56
  }
57
 
58
  if(!(f = fopen(file, "r"))) {
59
    free(obj);
60
    return NULL;
61
  }
62
 
63
  fread(&obj->e_hdr, sizeof(Elf32_Ehdr), 1, f);
64
 
65
  /* Do some sanity checks */
66
  if((obj->e_hdr.e_ident[EI_MAG0] != ELFMAG0) ||
67
     (obj->e_hdr.e_ident[EI_MAG1] != ELFMAG1) ||
68
     (obj->e_hdr.e_ident[EI_MAG2] != ELFMAG2) ||
69
     (obj->e_hdr.e_ident[EI_MAG3] != ELFMAG3)) {
70
    fprintf(stderr, "%s is not an elf file!\n", file);
71
    goto error_load;
72
  }
73
 
74
  if(obj->e_hdr.e_ident[EI_CLASS] == ELFCLASSNONE) {
75
    fprintf(stderr, "Invalid class in ELF header\n");
76
    goto error_load;
77
  }
78
 
79
  if(obj->e_hdr.e_ident[EI_DATA] == ELFDATANONE) {
80
    fprintf(stderr, "Invalid data format in ELF header\n");
81
    goto error_load;
82
  }
83
 
84
  /* FIXME: Swap data as necessary */
85
 
86
  if((obj->e_hdr.e_ident[EI_VERSION] != 1) ||
87
     (obj->e_hdr.e_version != 1)) {
88
    fprintf(stderr, "Unexpected elf version found: %i (%li)\n",
89
            obj->e_hdr.e_ident[EI_VERSION], (long int)obj->e_hdr.e_version);
90
    goto error_load;
91
  }
92
 
93
  if(obj->e_hdr.e_type != ET_REL) {
94
    fprintf(stderr, "Appears that we did not receive a object file\n");
95
    goto error_load;
96
  }
97
 
98
  if(obj->e_hdr.e_phoff) {
99
    fprintf(stderr, "What am I supposed to do with a program header??\n");
100
    goto error_load;
101
  }
102
 
103
  if(obj->e_hdr.e_ehsize != sizeof(Elf32_Ehdr)) {
104
    fprintf(stderr, "Unknown size of elf header\n");
105
    goto error_load;
106
  }
107
 
108
  if(!obj->e_hdr.e_shoff || !obj->e_hdr.e_shnum) {
109
    fprintf(stderr, "The elf file contains no sections!\n");
110
    goto error_load;
111
  }
112
 
113
  if(obj->e_hdr.e_shentsize != sizeof(Elf32_Shdr)) {
114
    fprintf(stderr, "Unknown section header size %i\n", obj->e_hdr.e_shentsize);
115
    goto error_load;
116
  }
117
 
118
  /* Load the section headers */
119
  if(!(obj->e_shdrs = malloc(obj->e_hdr.e_shentsize * obj->e_hdr.e_shnum))){
120
    fprintf(stderr, "OOM\n");
121
    goto error_load;
122
  }
123
 
124
  fseek(f, obj->e_hdr.e_shoff, SEEK_SET);
125
  fread(obj->e_shdrs, obj->e_hdr.e_shentsize, obj->e_hdr.e_shnum, f);
126
 
127
  /* FIXME: swap data */
128
 
129
  /* Load the sections */
130
  if(!(obj->e_sections = calloc(obj->e_hdr.e_shnum, sizeof(void *)))) {
131
    fprintf(stderr, "OOM\n");
132
    free(obj->e_shdrs);
133
    goto error_load;
134
  }
135
 
136
  for(i = 0; i < obj->e_hdr.e_shnum; i++) {
137
    if(obj->e_shdrs[i].sh_type == SHT_NOBITS)
138
      continue;
139
    if(!(obj->e_sections[i] = malloc(obj->e_shdrs[i].sh_size))) {
140
      fprintf(stderr, "OOM\n");
141
      goto post_sec_error_load;
142
    }
143
    fseek(f, obj->e_shdrs[i].sh_offset, SEEK_SET);
144
    fread(obj->e_sections[i], obj->e_shdrs[i].sh_size, 1, f);
145
  }
146
 
147
  obj->e_rels = NULL;
148
  obj->e_syms = NULL;
149
  obj->e_relas = NULL;
150
 
151
  /* Find the symbol table and relocation table(s) */
152
  for(i = 0; i < obj->e_hdr.e_shnum; i++) {
153
    switch(obj->e_shdrs[i].sh_type) {
154
    case SHT_SYMTAB:
155
      if(obj->e_syms) {
156
        fprintf(stderr, "ELF file has more than one symbol table\n");
157
        goto post_sec_error_load;
158
      }
159
      if(obj->e_shdrs[i].sh_entsize != sizeof(Elf32_Sym)) {
160
        fprintf(stderr, "ELF symbol table entry size is unknown\n");
161
        goto post_sec_error_load;
162
      }
163
      if((obj->e_shdrs[i].sh_size % obj->e_shdrs[i].sh_entsize)) {
164
        fprintf(stderr, "Symbol table's length is not a multiple of sizeof(Elf32_Sym\n");
165
        goto post_sec_error_load;
166
      }
167
      obj->e_syms = obj->e_sections[i];
168
      obj->e_sym_num = obj->e_shdrs[i].sh_size / obj->e_shdrs[i].sh_entsize;
169
      obj->e_sym_str_tab = obj->e_shdrs[i].sh_link;
170
      break;
171
    case SHT_REL:
172
      if(obj->e_rels) {
173
        fprintf(stderr, "ELF file has more than one relocation table\n");
174
        goto post_sec_error_load;
175
      }
176
      if(obj->e_shdrs[i].sh_entsize != sizeof(Elf32_Rel)) {
177
        fprintf(stderr, "ELF relocation table entry size is unknown\n");
178
        goto post_sec_error_load;
179
      }
180
      if((obj->e_shdrs[i].sh_size % obj->e_shdrs[i].sh_entsize)) {
181
        fprintf(stderr, "Relocation table's length is not a multiple of sizeof(Elf32_Rel\n");
182
        goto post_sec_error_load;
183
      }
184
      obj->e_rels = obj->e_sections[i];
185
      obj->e_rel_sec = obj->e_shdrs[i].sh_info;
186
      obj->e_rel_sym = obj->e_shdrs[i].sh_link;
187
      obj->e_rel_num = obj->e_shdrs[i].sh_size / obj->e_shdrs[i].sh_entsize;
188
      break;
189
    case SHT_RELA:
190
      if(obj->e_relas) {
191
        fprintf(stderr, "ELF file has more than one a-relocation table\n");
192
        goto post_sec_error_load;
193
      }
194
      if(obj->e_shdrs[i].sh_entsize != sizeof(Elf32_Rela)) {
195
        fprintf(stderr, "ELF a-relocation table entry size is unknown\n");
196
        goto post_sec_error_load;
197
      }
198
      if((obj->e_shdrs[i].sh_size % obj->e_shdrs[i].sh_entsize)) {
199
        fprintf(stderr, "Relocation table's length is not a multiple of sizeof(Elf32_Rela)\n");
200
        goto post_sec_error_load;
201
      }
202
      obj->e_relas = obj->e_sections[i];
203
      obj->e_rela_sec = obj->e_shdrs[i].sh_info;
204
      obj->e_rela_sym = obj->e_shdrs[i].sh_link;
205
      obj->e_rela_num = obj->e_shdrs[i].sh_size / obj->e_shdrs[i].sh_entsize;
206
      break;
207
    }
208
  }
209
 
210
  fclose(f);
211
  return obj;
212
 
213
post_sec_error_load:
214
  for(i = 0; i < obj->e_hdr.e_shnum; i++) {
215
    if(obj->e_sections[i])
216
      free(obj->e_sections[i]);
217
  }
218
  free(obj->e_sections);
219
  free(obj->e_shdrs);
220
error_load:
221
  free(obj);
222
  fclose(f);
223
  return NULL;
224
}
225
 
226
void elf_close_obj(void *e_obj)
227
{
228
  struct elf_obj *obj = e_obj;
229
  int i;
230
 
231
  for(i = 0; i < obj->e_hdr.e_shnum; i++) {
232
    if(obj->e_sections[i])
233
      free(obj->e_sections[i]);
234
  }
235
  free(obj->e_sections);
236
  free(obj->e_shdrs);
237
  free(obj);
238
}
239
 
240
static Elf32_Sym *elf_find_func(struct elf_obj *obj, unsigned int func)
241
{
242
  int i, j;
243
  Elf32_Sym *cur;
244
 
245
  for(i = 0, j = 0, cur = obj->e_syms; i < obj->e_sym_num; i++, cur++) {
246
    if(ELF32_ST_BIND(cur->st_info) != STB_GLOBAL)
247
      continue;
248
    if(ELF32_ST_TYPE(cur->st_info) != STT_FUNC)
249
      continue;
250
    if(j == func)
251
      return cur;
252
    j++;
253
  }
254
  return NULL;
255
}
256
 
257
char *elf_get_func_name(void *e_obj, unsigned int func)
258
{
259
  struct elf_obj *obj = e_obj;
260
  Elf32_Sym *func_sym = elf_find_func(obj, func);
261
 
262
  if(func_sym)
263
    return obj->e_sections[obj->e_sym_str_tab] + func_sym->st_name;
264
 
265
  return NULL;
266
}
267
 
268
unsigned int elf_get_func_len(void *e_obj, unsigned int func)
269
{
270
  struct elf_obj *obj = e_obj;
271
  Elf32_Sym *func_sym = elf_find_func(obj, func);
272
 
273
  if(func_sym)
274
    return func_sym->st_size;
275
  return 0;
276
}
277
 
278
void *elf_get_func_start(void *e_obj, unsigned int func)
279
{
280
  struct elf_obj *obj = e_obj;
281
  Elf32_Sym *func_sym = elf_find_func(obj, func);
282
 
283
  if(!func_sym)
284
    return NULL;
285
 
286
  if(func_sym->st_shndx == SHN_COMMON) {
287
    fprintf(stderr, "Don't know how to handle SHN_COMMON section header\n");
288
    return NULL;
289
  }
290
 
291
  return obj->e_sections[func_sym->st_shndx] + func_sym->st_value;
292
}
293
 
294
static char *elf_get_sym_name(struct elf_obj *obj, unsigned int sym)
295
{
296
  char *name;
297
 
298
  name = obj->e_sections[obj->e_sym_str_tab];
299
  name += obj->e_syms[sym].st_name;
300
 
301
  return name;
302
}
303
 
304
int elf_get_func_reloc(void *e_obj, unsigned int func, unsigned int relocn,
305
                       struct reloc *reloc)
306
{
307
  struct elf_obj *obj = e_obj;
308
  Elf32_Sym *func_sym = elf_find_func(obj, func);
309
  Elf32_Rel *cur;
310
  Elf32_Rela *cura;
311
  int i, j;
312
 
313
/*
314
  if(obj->e_rel_sec != func_sym->st_shndx) {
315
    fprintf(stderr, "Don't know what to do: Function does not have a relocation table\n");
316
    return 0;
317
  }
318
*/
319
 
320
  for(i = 0, j = 0, cur = obj->e_rels; i < obj->e_rel_num; i++, cur++) {
321
    if((cur->r_offset - func_sym->st_value) > func_sym->st_size)
322
      continue;
323
    if(relocn == j) {
324
      reloc->name = elf_get_sym_name(obj, ELF32_R_SYM(cur->r_info));
325
      reloc->func_offset = cur->r_offset - func_sym->st_value;
326
      reloc->type = ELF32_R_TYPE(cur->r_info);
327
      /* FIXME: Byte-swap */
328
      reloc->addend = *(uint32_t *)(obj->e_sections[obj->e_rel_sec] + cur->r_offset);
329
      return 1;
330
    }
331
    j++;
332
  }
333
 
334
  if(!obj->e_relas)
335
    return 0;
336
 
337
  for(i = 0, cura = obj->e_relas; i < obj->e_rela_num; i++, cura++) {
338
    if((cura->r_offset - func_sym->st_value) > func_sym->st_size)
339
      continue;
340
    if(relocn == j) {
341
      reloc->name = elf_get_sym_name(obj, ELF32_R_SYM(cur->r_info));
342
      reloc->func_offset = cura->r_offset - func_sym->st_value;
343
      reloc->type = ELF32_R_TYPE(cur->r_info);
344
      reloc->addend = cura->r_addend;
345
      return 1;
346
    }
347
    j++;
348
  }
349
 
350
  return 0;
351
}
352
 
353
const struct bff bffs = {
354
  elf_open_obj,
355
  elf_close_obj,
356
  elf_get_func_name,
357
  elf_get_func_start,
358
  elf_get_func_len,
359
  elf_get_func_reloc };

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.