1 |
/* ELF executable support for BFD. |
/* ELF executable support for BFD. |
2 |
Copyright 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, |
Copyright 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, |
3 |
2001, 2002 Free Software Foundation, Inc. |
2001, 2002, 2003, 2004, 2005 Free Software Foundation, Inc. |
4 |
|
|
5 |
Written by Fred Fish @ Cygnus Support, from information published |
Written by Fred Fish @ Cygnus Support, from information published |
6 |
in "UNIX System V Release 4, Programmers Guide: ANSI C and |
in "UNIX System V Release 4, Programmers Guide: ANSI C and |
33 |
/* Problems and other issues to resolve. |
/* Problems and other issues to resolve. |
34 |
|
|
35 |
(1) BFD expects there to be some fixed number of "sections" in |
(1) BFD expects there to be some fixed number of "sections" in |
36 |
the object file. I.E. there is a "section_count" variable in the |
the object file. I.E. there is a "section_count" variable in the |
37 |
bfd structure which contains the number of sections. However, ELF |
bfd structure which contains the number of sections. However, ELF |
38 |
supports multiple "views" of a file. In particular, with current |
supports multiple "views" of a file. In particular, with current |
39 |
implementations, executable files typically have two tables, a |
implementations, executable files typically have two tables, a |
102 |
#define elf_get_reloc_upper_bound NAME(bfd_elf,get_reloc_upper_bound) |
#define elf_get_reloc_upper_bound NAME(bfd_elf,get_reloc_upper_bound) |
103 |
#define elf_canonicalize_reloc NAME(bfd_elf,canonicalize_reloc) |
#define elf_canonicalize_reloc NAME(bfd_elf,canonicalize_reloc) |
104 |
#define elf_slurp_symbol_table NAME(bfd_elf,slurp_symbol_table) |
#define elf_slurp_symbol_table NAME(bfd_elf,slurp_symbol_table) |
105 |
#define elf_get_symtab NAME(bfd_elf,get_symtab) |
#define elf_canonicalize_symtab NAME(bfd_elf,canonicalize_symtab) |
106 |
#define elf_canonicalize_dynamic_symtab \ |
#define elf_canonicalize_dynamic_symtab \ |
107 |
NAME(bfd_elf,canonicalize_dynamic_symtab) |
NAME(bfd_elf,canonicalize_dynamic_symtab) |
108 |
|
#define elf_get_synthetic_symtab \ |
109 |
|
NAME(bfd_elf,get_synthetic_symtab) |
110 |
#define elf_make_empty_symbol NAME(bfd_elf,make_empty_symbol) |
#define elf_make_empty_symbol NAME(bfd_elf,make_empty_symbol) |
111 |
#define elf_get_symbol_info NAME(bfd_elf,get_symbol_info) |
#define elf_get_symbol_info NAME(bfd_elf,get_symbol_info) |
112 |
#define elf_get_lineno NAME(bfd_elf,get_lineno) |
#define elf_get_lineno NAME(bfd_elf,get_lineno) |
117 |
#define elf_no_info_to_howto NAME(bfd_elf,no_info_to_howto) |
#define elf_no_info_to_howto NAME(bfd_elf,no_info_to_howto) |
118 |
#define elf_no_info_to_howto_rel NAME(bfd_elf,no_info_to_howto_rel) |
#define elf_no_info_to_howto_rel NAME(bfd_elf,no_info_to_howto_rel) |
119 |
#define elf_find_section NAME(bfd_elf,find_section) |
#define elf_find_section NAME(bfd_elf,find_section) |
|
#define elf_bfd_link_add_symbols NAME(bfd_elf,bfd_link_add_symbols) |
|
|
#define elf_add_dynamic_entry NAME(bfd_elf,add_dynamic_entry) |
|
120 |
#define elf_write_shdrs_and_ehdr NAME(bfd_elf,write_shdrs_and_ehdr) |
#define elf_write_shdrs_and_ehdr NAME(bfd_elf,write_shdrs_and_ehdr) |
121 |
#define elf_write_out_phdrs NAME(bfd_elf,write_out_phdrs) |
#define elf_write_out_phdrs NAME(bfd_elf,write_out_phdrs) |
122 |
#define elf_write_relocs NAME(bfd_elf,write_relocs) |
#define elf_write_relocs NAME(bfd_elf,write_relocs) |
123 |
#define elf_slurp_reloc_table NAME(bfd_elf,slurp_reloc_table) |
#define elf_slurp_reloc_table NAME(bfd_elf,slurp_reloc_table) |
|
#define elf_link_create_dynamic_sections \ |
|
|
NAME(bfd_elf,link_create_dynamic_sections) |
|
|
#define elf_bfd_discard_info NAME(bfd_elf,discard_info) |
|
|
#define elf_reloc_symbol_deleted_p NAME(_bfd_elf,reloc_symbol_deleted_p) |
|
|
#define elf_link_record_dynamic_symbol _bfd_elf_link_record_dynamic_symbol |
|
|
#define elf_bfd_final_link NAME(bfd_elf,bfd_final_link) |
|
|
#define elf_create_pointer_linker_section NAME(bfd_elf,create_pointer_linker_section) |
|
|
#define elf_finish_pointer_linker_section NAME(bfd_elf,finish_pointer_linker_section) |
|
|
#define elf_gc_sections NAME(_bfd_elf,gc_sections) |
|
|
#define elf_gc_common_finalize_got_offsets \ |
|
|
NAME(_bfd_elf,gc_common_finalize_got_offsets) |
|
|
#define elf_gc_common_final_link NAME(_bfd_elf,gc_common_final_link) |
|
|
#define elf_gc_record_vtinherit NAME(_bfd_elf,gc_record_vtinherit) |
|
|
#define elf_gc_record_vtentry NAME(_bfd_elf,gc_record_vtentry) |
|
|
#define elf_link_record_local_dynamic_symbol \ |
|
|
NAME(_bfd_elf,link_record_local_dynamic_symbol) |
|
124 |
|
|
125 |
#if ARCH_SIZE == 64 |
#if ARCH_SIZE == 64 |
126 |
#define ELF_R_INFO(X,Y) ELF64_R_INFO(X,Y) |
#define ELF_R_INFO(X,Y) ELF64_R_INFO(X,Y) |
139 |
#define LOG_FILE_ALIGN 2 |
#define LOG_FILE_ALIGN 2 |
140 |
#endif |
#endif |
141 |
|
|
|
/* Static functions */ |
|
|
|
|
|
static void elf_swap_ehdr_in |
|
|
PARAMS ((bfd *, const Elf_External_Ehdr *, Elf_Internal_Ehdr *)); |
|
|
static void elf_swap_ehdr_out |
|
|
PARAMS ((bfd *, const Elf_Internal_Ehdr *, Elf_External_Ehdr *)); |
|
|
static void elf_swap_shdr_in |
|
|
PARAMS ((bfd *, const Elf_External_Shdr *, Elf_Internal_Shdr *)); |
|
|
static void elf_swap_shdr_out |
|
|
PARAMS ((bfd *, const Elf_Internal_Shdr *, Elf_External_Shdr *)); |
|
|
|
|
|
#define elf_stringtab_init _bfd_elf_stringtab_init |
|
|
|
|
|
#define section_from_elf_index bfd_section_from_elf_index |
|
|
|
|
|
static boolean elf_slurp_reloc_table_from_section |
|
|
PARAMS ((bfd *, asection *, Elf_Internal_Shdr *, bfd_size_type, |
|
|
arelent *, asymbol **, boolean)); |
|
|
|
|
|
static boolean elf_file_p PARAMS ((Elf_External_Ehdr *)); |
|
|
|
|
142 |
#ifdef DEBUG |
#ifdef DEBUG |
143 |
static void elf_debug_section PARAMS ((int, Elf_Internal_Shdr *)); |
static void elf_debug_section (int, Elf_Internal_Shdr *); |
144 |
static void elf_debug_file PARAMS ((Elf_Internal_Ehdr *)); |
static void elf_debug_file (Elf_Internal_Ehdr *); |
145 |
static char *elf_symbol_flags PARAMS ((flagword)); |
static char *elf_symbol_flags (flagword); |
146 |
#endif |
#endif |
147 |
|
|
148 |
/* Structure swapping routines */ |
/* Structure swapping routines */ |
166 |
format. */ |
format. */ |
167 |
|
|
168 |
void |
void |
169 |
elf_swap_symbol_in (abfd, psrc, pshn, dst) |
elf_swap_symbol_in (bfd *abfd, |
170 |
bfd *abfd; |
const void *psrc, |
171 |
const PTR psrc; |
const void *pshn, |
172 |
const PTR pshn; |
Elf_Internal_Sym *dst) |
|
Elf_Internal_Sym *dst; |
|
173 |
{ |
{ |
174 |
const Elf_External_Sym *src = (const Elf_External_Sym *) psrc; |
const Elf_External_Sym *src = psrc; |
175 |
const Elf_External_Sym_Shndx *shndx = (const Elf_External_Sym_Shndx *) pshn; |
const Elf_External_Sym_Shndx *shndx = pshn; |
176 |
int signed_vma = get_elf_backend_data (abfd)->sign_extend_vma; |
int signed_vma = get_elf_backend_data (abfd)->sign_extend_vma; |
177 |
|
|
178 |
dst->st_name = H_GET_32 (abfd, src->st_name); |
dst->st_name = H_GET_32 (abfd, src->st_name); |
196 |
format. */ |
format. */ |
197 |
|
|
198 |
void |
void |
199 |
elf_swap_symbol_out (abfd, src, cdst, shndx) |
elf_swap_symbol_out (bfd *abfd, |
200 |
bfd *abfd; |
const Elf_Internal_Sym *src, |
201 |
const Elf_Internal_Sym *src; |
void *cdst, |
202 |
PTR cdst; |
void *shndx) |
|
PTR shndx; |
|
203 |
{ |
{ |
204 |
unsigned int tmp; |
unsigned int tmp; |
205 |
Elf_External_Sym *dst = (Elf_External_Sym *) cdst; |
Elf_External_Sym *dst = cdst; |
206 |
H_PUT_32 (abfd, src->st_name, dst->st_name); |
H_PUT_32 (abfd, src->st_name, dst->st_name); |
207 |
H_PUT_WORD (abfd, src->st_value, dst->st_value); |
H_PUT_WORD (abfd, src->st_value, dst->st_value); |
208 |
H_PUT_WORD (abfd, src->st_size, dst->st_size); |
H_PUT_WORD (abfd, src->st_size, dst->st_size); |
223 |
internal format. */ |
internal format. */ |
224 |
|
|
225 |
static void |
static void |
226 |
elf_swap_ehdr_in (abfd, src, dst) |
elf_swap_ehdr_in (bfd *abfd, |
227 |
bfd *abfd; |
const Elf_External_Ehdr *src, |
228 |
const Elf_External_Ehdr *src; |
Elf_Internal_Ehdr *dst) |
|
Elf_Internal_Ehdr *dst; |
|
229 |
{ |
{ |
230 |
int signed_vma = get_elf_backend_data (abfd)->sign_extend_vma; |
int signed_vma = get_elf_backend_data (abfd)->sign_extend_vma; |
231 |
memcpy (dst->e_ident, src->e_ident, EI_NIDENT); |
memcpy (dst->e_ident, src->e_ident, EI_NIDENT); |
251 |
external format. */ |
external format. */ |
252 |
|
|
253 |
static void |
static void |
254 |
elf_swap_ehdr_out (abfd, src, dst) |
elf_swap_ehdr_out (bfd *abfd, |
255 |
bfd *abfd; |
const Elf_Internal_Ehdr *src, |
256 |
const Elf_Internal_Ehdr *src; |
Elf_External_Ehdr *dst) |
|
Elf_External_Ehdr *dst; |
|
257 |
{ |
{ |
258 |
unsigned int tmp; |
unsigned int tmp; |
259 |
int signed_vma = get_elf_backend_data (abfd)->sign_extend_vma; |
int signed_vma = get_elf_backend_data (abfd)->sign_extend_vma; |
287 |
ELF section header table entry in internal format. */ |
ELF section header table entry in internal format. */ |
288 |
|
|
289 |
static void |
static void |
290 |
elf_swap_shdr_in (abfd, src, dst) |
elf_swap_shdr_in (bfd *abfd, |
291 |
bfd *abfd; |
const Elf_External_Shdr *src, |
292 |
const Elf_External_Shdr *src; |
Elf_Internal_Shdr *dst) |
|
Elf_Internal_Shdr *dst; |
|
293 |
{ |
{ |
294 |
int signed_vma = get_elf_backend_data (abfd)->sign_extend_vma; |
int signed_vma = get_elf_backend_data (abfd)->sign_extend_vma; |
295 |
|
|
314 |
ELF section header table entry in external format. */ |
ELF section header table entry in external format. */ |
315 |
|
|
316 |
static void |
static void |
317 |
elf_swap_shdr_out (abfd, src, dst) |
elf_swap_shdr_out (bfd *abfd, |
318 |
bfd *abfd; |
const Elf_Internal_Shdr *src, |
319 |
const Elf_Internal_Shdr *src; |
Elf_External_Shdr *dst) |
|
Elf_External_Shdr *dst; |
|
320 |
{ |
{ |
321 |
/* note that all elements of dst are *arrays of unsigned char* already... */ |
/* note that all elements of dst are *arrays of unsigned char* already... */ |
322 |
H_PUT_32 (abfd, src->sh_name, dst->sh_name); |
H_PUT_32 (abfd, src->sh_name, dst->sh_name); |
335 |
ELF program header table entry in internal format. */ |
ELF program header table entry in internal format. */ |
336 |
|
|
337 |
void |
void |
338 |
elf_swap_phdr_in (abfd, src, dst) |
elf_swap_phdr_in (bfd *abfd, |
339 |
bfd *abfd; |
const Elf_External_Phdr *src, |
340 |
const Elf_External_Phdr *src; |
Elf_Internal_Phdr *dst) |
|
Elf_Internal_Phdr *dst; |
|
341 |
{ |
{ |
342 |
int signed_vma = get_elf_backend_data (abfd)->sign_extend_vma; |
int signed_vma = get_elf_backend_data (abfd)->sign_extend_vma; |
343 |
|
|
360 |
} |
} |
361 |
|
|
362 |
void |
void |
363 |
elf_swap_phdr_out (abfd, src, dst) |
elf_swap_phdr_out (bfd *abfd, |
364 |
bfd *abfd; |
const Elf_Internal_Phdr *src, |
365 |
const Elf_Internal_Phdr *src; |
Elf_External_Phdr *dst) |
|
Elf_External_Phdr *dst; |
|
366 |
{ |
{ |
367 |
/* note that all elements of dst are *arrays of unsigned char* already... */ |
/* note that all elements of dst are *arrays of unsigned char* already... */ |
368 |
H_PUT_32 (abfd, src->p_type, dst->p_type); |
H_PUT_32 (abfd, src->p_type, dst->p_type); |
376 |
} |
} |
377 |
|
|
378 |
/* Translate an ELF reloc from external format to internal format. */ |
/* Translate an ELF reloc from external format to internal format. */ |
379 |
INLINE void |
void |
380 |
elf_swap_reloc_in (abfd, src, dst) |
elf_swap_reloc_in (bfd *abfd, |
381 |
bfd *abfd; |
const bfd_byte *s, |
382 |
const Elf_External_Rel *src; |
Elf_Internal_Rela *dst) |
|
Elf_Internal_Rel *dst; |
|
383 |
{ |
{ |
384 |
|
const Elf_External_Rel *src = (const Elf_External_Rel *) s; |
385 |
dst->r_offset = H_GET_WORD (abfd, src->r_offset); |
dst->r_offset = H_GET_WORD (abfd, src->r_offset); |
386 |
dst->r_info = H_GET_WORD (abfd, src->r_info); |
dst->r_info = H_GET_WORD (abfd, src->r_info); |
387 |
|
dst->r_addend = 0; |
388 |
} |
} |
389 |
|
|
390 |
INLINE void |
void |
391 |
elf_swap_reloca_in (abfd, src, dst) |
elf_swap_reloca_in (bfd *abfd, |
392 |
bfd *abfd; |
const bfd_byte *s, |
393 |
const Elf_External_Rela *src; |
Elf_Internal_Rela *dst) |
|
Elf_Internal_Rela *dst; |
|
394 |
{ |
{ |
395 |
|
const Elf_External_Rela *src = (const Elf_External_Rela *) s; |
396 |
dst->r_offset = H_GET_WORD (abfd, src->r_offset); |
dst->r_offset = H_GET_WORD (abfd, src->r_offset); |
397 |
dst->r_info = H_GET_WORD (abfd, src->r_info); |
dst->r_info = H_GET_WORD (abfd, src->r_info); |
398 |
dst->r_addend = H_GET_SIGNED_WORD (abfd, src->r_addend); |
dst->r_addend = H_GET_SIGNED_WORD (abfd, src->r_addend); |
399 |
} |
} |
400 |
|
|
401 |
/* Translate an ELF reloc from internal format to external format. */ |
/* Translate an ELF reloc from internal format to external format. */ |
402 |
INLINE void |
void |
403 |
elf_swap_reloc_out (abfd, src, dst) |
elf_swap_reloc_out (bfd *abfd, |
404 |
bfd *abfd; |
const Elf_Internal_Rela *src, |
405 |
const Elf_Internal_Rel *src; |
bfd_byte *d) |
|
Elf_External_Rel *dst; |
|
406 |
{ |
{ |
407 |
|
Elf_External_Rel *dst = (Elf_External_Rel *) d; |
408 |
H_PUT_WORD (abfd, src->r_offset, dst->r_offset); |
H_PUT_WORD (abfd, src->r_offset, dst->r_offset); |
409 |
H_PUT_WORD (abfd, src->r_info, dst->r_info); |
H_PUT_WORD (abfd, src->r_info, dst->r_info); |
410 |
} |
} |
411 |
|
|
412 |
INLINE void |
void |
413 |
elf_swap_reloca_out (abfd, src, dst) |
elf_swap_reloca_out (bfd *abfd, |
414 |
bfd *abfd; |
const Elf_Internal_Rela *src, |
415 |
const Elf_Internal_Rela *src; |
bfd_byte *d) |
|
Elf_External_Rela *dst; |
|
416 |
{ |
{ |
417 |
|
Elf_External_Rela *dst = (Elf_External_Rela *) d; |
418 |
H_PUT_WORD (abfd, src->r_offset, dst->r_offset); |
H_PUT_WORD (abfd, src->r_offset, dst->r_offset); |
419 |
H_PUT_WORD (abfd, src->r_info, dst->r_info); |
H_PUT_WORD (abfd, src->r_info, dst->r_info); |
420 |
H_PUT_SIGNED_WORD (abfd, src->r_addend, dst->r_addend); |
H_PUT_SIGNED_WORD (abfd, src->r_addend, dst->r_addend); |
421 |
} |
} |
422 |
|
|
423 |
INLINE void |
void |
424 |
elf_swap_dyn_in (abfd, p, dst) |
elf_swap_dyn_in (bfd *abfd, |
425 |
bfd *abfd; |
const void *p, |
426 |
const PTR p; |
Elf_Internal_Dyn *dst) |
|
Elf_Internal_Dyn *dst; |
|
427 |
{ |
{ |
428 |
const Elf_External_Dyn *src = (const Elf_External_Dyn *) p; |
const Elf_External_Dyn *src = p; |
429 |
|
|
430 |
dst->d_tag = H_GET_WORD (abfd, src->d_tag); |
dst->d_tag = H_GET_WORD (abfd, src->d_tag); |
431 |
dst->d_un.d_val = H_GET_WORD (abfd, src->d_un.d_val); |
dst->d_un.d_val = H_GET_WORD (abfd, src->d_un.d_val); |
432 |
} |
} |
433 |
|
|
434 |
INLINE void |
void |
435 |
elf_swap_dyn_out (abfd, src, p) |
elf_swap_dyn_out (bfd *abfd, |
436 |
bfd *abfd; |
const Elf_Internal_Dyn *src, |
437 |
const Elf_Internal_Dyn *src; |
void *p) |
|
PTR p; |
|
438 |
{ |
{ |
439 |
Elf_External_Dyn *dst = (Elf_External_Dyn *) p; |
Elf_External_Dyn *dst = p; |
440 |
|
|
441 |
H_PUT_WORD (abfd, src->d_tag, dst->d_tag); |
H_PUT_WORD (abfd, src->d_tag, dst->d_tag); |
442 |
H_PUT_WORD (abfd, src->d_un.d_val, dst->d_un.d_val); |
H_PUT_WORD (abfd, src->d_un.d_val, dst->d_un.d_val); |
449 |
First we validate the file by reading in the ELF header and checking |
First we validate the file by reading in the ELF header and checking |
450 |
the magic number. */ |
the magic number. */ |
451 |
|
|
452 |
static INLINE boolean |
static inline bfd_boolean |
453 |
elf_file_p (x_ehdrp) |
elf_file_p (Elf_External_Ehdr *x_ehdrp) |
|
Elf_External_Ehdr *x_ehdrp; |
|
454 |
{ |
{ |
455 |
return ((x_ehdrp->e_ident[EI_MAG0] == ELFMAG0) |
return ((x_ehdrp->e_ident[EI_MAG0] == ELFMAG0) |
456 |
&& (x_ehdrp->e_ident[EI_MAG1] == ELFMAG1) |
&& (x_ehdrp->e_ident[EI_MAG1] == ELFMAG1) |
458 |
&& (x_ehdrp->e_ident[EI_MAG3] == ELFMAG3)); |
&& (x_ehdrp->e_ident[EI_MAG3] == ELFMAG3)); |
459 |
} |
} |
460 |
|
|
|
struct bfd_preserve |
|
|
{ |
|
|
const struct bfd_arch_info *arch_info; |
|
|
struct elf_obj_tdata *tdata; |
|
|
struct bfd_hash_table section_htab; |
|
|
struct sec *sections; |
|
|
struct sec **section_tail; |
|
|
unsigned int section_count; |
|
|
}; |
|
|
|
|
461 |
/* Check to see if the file associated with ABFD matches the target vector |
/* Check to see if the file associated with ABFD matches the target vector |
462 |
that ABFD points to. |
that ABFD points to. |
463 |
|
|
467 |
file does not match the target vector. */ |
file does not match the target vector. */ |
468 |
|
|
469 |
const bfd_target * |
const bfd_target * |
470 |
elf_object_p (abfd) |
elf_object_p (bfd *abfd) |
|
bfd *abfd; |
|
471 |
{ |
{ |
472 |
Elf_External_Ehdr x_ehdr; /* Elf file header, external form */ |
Elf_External_Ehdr x_ehdr; /* Elf file header, external form */ |
473 |
Elf_Internal_Ehdr *i_ehdrp; /* Elf file header, internal form */ |
Elf_Internal_Ehdr *i_ehdrp; /* Elf file header, internal form */ |
475 |
Elf_Internal_Shdr i_shdr; |
Elf_Internal_Shdr i_shdr; |
476 |
Elf_Internal_Shdr *i_shdrp; /* Section header table, internal form */ |
Elf_Internal_Shdr *i_shdrp; /* Section header table, internal form */ |
477 |
unsigned int shindex; |
unsigned int shindex; |
478 |
char *shstrtab; /* Internal copy of section header stringtab */ |
const struct elf_backend_data *ebd; |
|
struct elf_backend_data *ebd; |
|
479 |
struct bfd_preserve preserve; |
struct bfd_preserve preserve; |
|
struct elf_obj_tdata *new_tdata = NULL; |
|
480 |
asection *s; |
asection *s; |
481 |
bfd_size_type amt; |
bfd_size_type amt; |
482 |
|
|
483 |
preserve.arch_info = abfd->arch_info; |
preserve.marker = NULL; |
484 |
|
|
485 |
/* Read in the ELF header in external format. */ |
/* Read in the ELF header in external format. */ |
486 |
|
|
487 |
if (bfd_bread ((PTR) & x_ehdr, (bfd_size_type) sizeof (x_ehdr), abfd) |
if (bfd_bread (&x_ehdr, sizeof (x_ehdr), abfd) != sizeof (x_ehdr)) |
|
!= sizeof (x_ehdr)) |
|
488 |
{ |
{ |
489 |
if (bfd_get_error () != bfd_error_system_call) |
if (bfd_get_error () != bfd_error_system_call) |
490 |
goto got_wrong_format_error; |
goto got_wrong_format_error; |
519 |
goto got_wrong_format_error; |
goto got_wrong_format_error; |
520 |
} |
} |
521 |
|
|
522 |
|
if (!bfd_preserve_save (abfd, &preserve)) |
523 |
|
goto got_no_match; |
524 |
|
|
525 |
/* Allocate an instance of the elf_obj_tdata structure and hook it up to |
/* Allocate an instance of the elf_obj_tdata structure and hook it up to |
526 |
the tdata pointer in the bfd. */ |
the tdata pointer in the bfd. */ |
527 |
|
|
528 |
amt = sizeof (struct elf_obj_tdata); |
if (! (*abfd->xvec->_bfd_set_format[bfd_object]) (abfd)) |
|
new_tdata = (struct elf_obj_tdata *) bfd_zalloc (abfd, amt); |
|
|
if (new_tdata == NULL) |
|
|
goto got_no_match; |
|
|
preserve.tdata = elf_tdata (abfd); |
|
|
elf_tdata (abfd) = new_tdata; |
|
|
|
|
|
/* Clear section information, since there might be a recognized bfd that |
|
|
we now check if we can replace, and we don't want to append to it. */ |
|
|
preserve.sections = abfd->sections; |
|
|
preserve.section_tail = abfd->section_tail; |
|
|
preserve.section_count = abfd->section_count; |
|
|
preserve.section_htab = abfd->section_htab; |
|
|
abfd->sections = NULL; |
|
|
abfd->section_tail = &abfd->sections; |
|
|
abfd->section_count = 0; |
|
|
if (!bfd_hash_table_init (&abfd->section_htab, bfd_section_hash_newfunc)) |
|
529 |
goto got_no_match; |
goto got_no_match; |
530 |
|
preserve.marker = elf_tdata (abfd); |
531 |
|
|
532 |
/* Now that we know the byte order, swap in the rest of the header */ |
/* Now that we know the byte order, swap in the rest of the header */ |
533 |
i_ehdrp = elf_elfheader (abfd); |
i_ehdrp = elf_elfheader (abfd); |
560 |
/* Check that the ELF e_machine field matches what this particular |
/* Check that the ELF e_machine field matches what this particular |
561 |
BFD format expects. */ |
BFD format expects. */ |
562 |
if (ebd->elf_machine_code != i_ehdrp->e_machine |
if (ebd->elf_machine_code != i_ehdrp->e_machine |
563 |
&& (ebd->elf_machine_alt1 == 0 || i_ehdrp->e_machine != ebd->elf_machine_alt1) |
&& (ebd->elf_machine_alt1 == 0 |
564 |
&& (ebd->elf_machine_alt2 == 0 || i_ehdrp->e_machine != ebd->elf_machine_alt2)) |
|| i_ehdrp->e_machine != ebd->elf_machine_alt1) |
565 |
|
&& (ebd->elf_machine_alt2 == 0 |
566 |
|
|| i_ehdrp->e_machine != ebd->elf_machine_alt2)) |
567 |
{ |
{ |
568 |
const bfd_target * const *target_ptr; |
const bfd_target * const *target_ptr; |
569 |
|
|
574 |
for which we do not have a specific backend. */ |
for which we do not have a specific backend. */ |
575 |
for (target_ptr = bfd_target_vector; *target_ptr != NULL; target_ptr++) |
for (target_ptr = bfd_target_vector; *target_ptr != NULL; target_ptr++) |
576 |
{ |
{ |
577 |
struct elf_backend_data *back; |
const struct elf_backend_data *back; |
578 |
|
|
579 |
if ((*target_ptr)->flavour != bfd_target_elf_flavour) |
if ((*target_ptr)->flavour != bfd_target_elf_flavour) |
580 |
continue; |
continue; |
581 |
back = (struct elf_backend_data *) (*target_ptr)->backend_data; |
back = (const struct elf_backend_data *) (*target_ptr)->backend_data; |
582 |
if (back->elf_machine_code == i_ehdrp->e_machine |
if (back->elf_machine_code == i_ehdrp->e_machine |
583 |
|| (back->elf_machine_alt1 != 0 |
|| (back->elf_machine_alt1 != 0 |
584 |
&& back->elf_machine_alt1 == i_ehdrp->e_machine) |
&& back->elf_machine_alt1 == i_ehdrp->e_machine) |
612 |
|
|
613 |
if (i_ehdrp->e_shoff != 0) |
if (i_ehdrp->e_shoff != 0) |
614 |
{ |
{ |
615 |
|
bfd_signed_vma where = i_ehdrp->e_shoff; |
616 |
|
|
617 |
|
if (where != (file_ptr) where) |
618 |
|
goto got_wrong_format_error; |
619 |
|
|
620 |
/* Seek to the section header table in the file. */ |
/* Seek to the section header table in the file. */ |
621 |
if (bfd_seek (abfd, (file_ptr) i_ehdrp->e_shoff, SEEK_SET) != 0) |
if (bfd_seek (abfd, (file_ptr) where, SEEK_SET) != 0) |
622 |
goto got_no_match; |
goto got_no_match; |
623 |
|
|
624 |
/* Read the first section header at index 0, and convert to internal |
/* Read the first section header at index 0, and convert to internal |
625 |
form. */ |
form. */ |
626 |
if (bfd_bread ((PTR) & x_shdr, (bfd_size_type) sizeof x_shdr, abfd) |
if (bfd_bread (&x_shdr, sizeof x_shdr, abfd) != sizeof (x_shdr)) |
|
!= sizeof (x_shdr)) |
|
627 |
goto got_no_match; |
goto got_no_match; |
628 |
elf_swap_shdr_in (abfd, &x_shdr, &i_shdr); |
elf_swap_shdr_in (abfd, &x_shdr, &i_shdr); |
629 |
|
|
630 |
/* If the section count is zero, the actual count is in the first |
/* If the section count is zero, the actual count is in the first |
631 |
section header. */ |
section header. */ |
632 |
if (i_ehdrp->e_shnum == SHN_UNDEF) |
if (i_ehdrp->e_shnum == SHN_UNDEF) |
633 |
i_ehdrp->e_shnum = i_shdr.sh_size; |
{ |
634 |
|
i_ehdrp->e_shnum = i_shdr.sh_size; |
635 |
|
if (i_ehdrp->e_shnum != i_shdr.sh_size |
636 |
|
|| i_ehdrp->e_shnum == 0) |
637 |
|
goto got_wrong_format_error; |
638 |
|
} |
639 |
|
|
640 |
/* And similarly for the string table index. */ |
/* And similarly for the string table index. */ |
641 |
if (i_ehdrp->e_shstrndx == SHN_XINDEX) |
if (i_ehdrp->e_shstrndx == SHN_XINDEX) |
642 |
i_ehdrp->e_shstrndx = i_shdr.sh_link; |
{ |
643 |
|
i_ehdrp->e_shstrndx = i_shdr.sh_link; |
644 |
|
if (i_ehdrp->e_shstrndx != i_shdr.sh_link) |
645 |
|
goto got_wrong_format_error; |
646 |
|
} |
647 |
|
|
648 |
|
/* Sanity check that we can read all of the section headers. |
649 |
|
It ought to be good enough to just read the last one. */ |
650 |
|
if (i_ehdrp->e_shnum != 1) |
651 |
|
{ |
652 |
|
/* Check that we don't have a totally silly number of sections. */ |
653 |
|
if (i_ehdrp->e_shnum > (unsigned int) -1 / sizeof (x_shdr) |
654 |
|
|| i_ehdrp->e_shnum > (unsigned int) -1 / sizeof (i_shdr)) |
655 |
|
goto got_wrong_format_error; |
656 |
|
|
657 |
|
where += (i_ehdrp->e_shnum - 1) * sizeof (x_shdr); |
658 |
|
if (where != (file_ptr) where) |
659 |
|
goto got_wrong_format_error; |
660 |
|
if ((bfd_size_type) where <= i_ehdrp->e_shoff) |
661 |
|
goto got_wrong_format_error; |
662 |
|
|
663 |
|
if (bfd_seek (abfd, (file_ptr) where, SEEK_SET) != 0) |
664 |
|
goto got_no_match; |
665 |
|
if (bfd_bread (&x_shdr, sizeof x_shdr, abfd) != sizeof (x_shdr)) |
666 |
|
goto got_no_match; |
667 |
|
|
668 |
|
/* Back to where we were. */ |
669 |
|
where = i_ehdrp->e_shoff + sizeof (x_shdr); |
670 |
|
if (bfd_seek (abfd, (file_ptr) where, SEEK_SET) != 0) |
671 |
|
goto got_no_match; |
672 |
|
} |
673 |
} |
} |
674 |
|
|
675 |
/* Allocate space for a copy of the section header table in |
/* Allocate space for a copy of the section header table in |
680 |
unsigned int num_sec; |
unsigned int num_sec; |
681 |
|
|
682 |
amt = sizeof (*i_shdrp) * i_ehdrp->e_shnum; |
amt = sizeof (*i_shdrp) * i_ehdrp->e_shnum; |
683 |
i_shdrp = (Elf_Internal_Shdr *) bfd_alloc (abfd, amt); |
i_shdrp = bfd_alloc (abfd, amt); |
684 |
if (!i_shdrp) |
if (!i_shdrp) |
685 |
goto got_no_match; |
goto got_no_match; |
686 |
num_sec = i_ehdrp->e_shnum; |
num_sec = i_ehdrp->e_shnum; |
688 |
num_sec += SHN_HIRESERVE + 1 - SHN_LORESERVE; |
num_sec += SHN_HIRESERVE + 1 - SHN_LORESERVE; |
689 |
elf_numsections (abfd) = num_sec; |
elf_numsections (abfd) = num_sec; |
690 |
amt = sizeof (i_shdrp) * num_sec; |
amt = sizeof (i_shdrp) * num_sec; |
691 |
elf_elfsections (abfd) = (Elf_Internal_Shdr **) bfd_alloc (abfd, amt); |
elf_elfsections (abfd) = bfd_alloc (abfd, amt); |
692 |
if (!elf_elfsections (abfd)) |
if (!elf_elfsections (abfd)) |
693 |
goto got_no_match; |
goto got_no_match; |
694 |
|
|
709 |
to internal form. */ |
to internal form. */ |
710 |
for (shindex = 1; shindex < i_ehdrp->e_shnum; shindex++) |
for (shindex = 1; shindex < i_ehdrp->e_shnum; shindex++) |
711 |
{ |
{ |
712 |
if (bfd_bread ((PTR) & x_shdr, (bfd_size_type) sizeof x_shdr, abfd) |
if (bfd_bread (&x_shdr, sizeof x_shdr, abfd) != sizeof (x_shdr)) |
|
!= sizeof (x_shdr)) |
|
713 |
goto got_no_match; |
goto got_no_match; |
714 |
elf_swap_shdr_in (abfd, &x_shdr, i_shdrp + shindex); |
elf_swap_shdr_in (abfd, &x_shdr, i_shdrp + shindex); |
715 |
|
|
716 |
|
/* Sanity check sh_link and sh_info. */ |
717 |
|
if (i_shdrp[shindex].sh_link >= num_sec |
718 |
|
|| (i_shdrp[shindex].sh_link >= SHN_LORESERVE |
719 |
|
&& i_shdrp[shindex].sh_link <= SHN_HIRESERVE)) |
720 |
|
goto got_wrong_format_error; |
721 |
|
|
722 |
|
if (((i_shdrp[shindex].sh_flags & SHF_INFO_LINK) |
723 |
|
|| i_shdrp[shindex].sh_type == SHT_RELA |
724 |
|
|| i_shdrp[shindex].sh_type == SHT_REL) |
725 |
|
&& (i_shdrp[shindex].sh_info >= num_sec |
726 |
|
|| (i_shdrp[shindex].sh_info >= SHN_LORESERVE |
727 |
|
&& i_shdrp[shindex].sh_info <= SHN_HIRESERVE))) |
728 |
|
goto got_wrong_format_error; |
729 |
|
|
730 |
/* If the section is loaded, but not page aligned, clear |
/* If the section is loaded, but not page aligned, clear |
731 |
D_PAGED. */ |
D_PAGED. */ |
732 |
if (i_shdrp[shindex].sh_size != 0 |
if (i_shdrp[shindex].sh_size != 0 |
733 |
&& (i_shdrp[shindex].sh_flags & SHF_ALLOC) != 0 |
&& (i_shdrp[shindex].sh_flags & SHF_ALLOC) != 0 |
734 |
&& i_shdrp[shindex].sh_type != SHT_NOBITS |
&& i_shdrp[shindex].sh_type != SHT_NOBITS |
735 |
&& (((i_shdrp[shindex].sh_addr - i_shdrp[shindex].sh_offset) |
&& (((i_shdrp[shindex].sh_addr - i_shdrp[shindex].sh_offset) |
736 |
% ebd->maxpagesize) |
% ebd->minpagesize) |
737 |
!= 0)) |
!= 0)) |
738 |
abfd->flags &= ~D_PAGED; |
abfd->flags &= ~D_PAGED; |
739 |
} |
} |
740 |
} |
} |
741 |
|
|
742 |
if (i_ehdrp->e_shstrndx && i_ehdrp->e_shoff) |
/* A further sanity check. */ |
743 |
|
if (i_ehdrp->e_shnum != 0) |
744 |
{ |
{ |
745 |
if (! bfd_section_from_shdr (abfd, i_ehdrp->e_shstrndx)) |
if (i_ehdrp->e_shstrndx >= elf_numsections (abfd) |
746 |
goto got_no_match; |
|| (i_ehdrp->e_shstrndx >= SHN_LORESERVE |
747 |
|
&& i_ehdrp->e_shstrndx <= SHN_HIRESERVE)) |
748 |
|
goto got_wrong_format_error; |
749 |
} |
} |
750 |
|
else if (i_ehdrp->e_shstrndx != 0) |
751 |
|
goto got_wrong_format_error; |
752 |
|
|
753 |
/* Read in the program headers. */ |
/* Read in the program headers. */ |
754 |
if (i_ehdrp->e_phnum == 0) |
if (i_ehdrp->e_phnum == 0) |
759 |
unsigned int i; |
unsigned int i; |
760 |
|
|
761 |
amt = i_ehdrp->e_phnum * sizeof (Elf_Internal_Phdr); |
amt = i_ehdrp->e_phnum * sizeof (Elf_Internal_Phdr); |
762 |
elf_tdata (abfd)->phdr = (Elf_Internal_Phdr *) bfd_alloc (abfd, amt); |
elf_tdata (abfd)->phdr = bfd_alloc (abfd, amt); |
763 |
if (elf_tdata (abfd)->phdr == NULL) |
if (elf_tdata (abfd)->phdr == NULL) |
764 |
goto got_no_match; |
goto got_no_match; |
765 |
if (bfd_seek (abfd, (file_ptr) i_ehdrp->e_phoff, SEEK_SET) != 0) |
if (bfd_seek (abfd, (file_ptr) i_ehdrp->e_phoff, SEEK_SET) != 0) |
769 |
{ |
{ |
770 |
Elf_External_Phdr x_phdr; |
Elf_External_Phdr x_phdr; |
771 |
|
|
772 |
if (bfd_bread ((PTR) &x_phdr, (bfd_size_type) sizeof x_phdr, abfd) |
if (bfd_bread (&x_phdr, sizeof x_phdr, abfd) != sizeof x_phdr) |
|
!= sizeof x_phdr) |
|
773 |
goto got_no_match; |
goto got_no_match; |
774 |
elf_swap_phdr_in (abfd, &x_phdr, i_phdr); |
elf_swap_phdr_in (abfd, &x_phdr, i_phdr); |
775 |
} |
} |
776 |
} |
} |
777 |
|
|
778 |
/* Read in the string table containing the names of the sections. We |
if (i_ehdrp->e_shstrndx != 0 && i_ehdrp->e_shoff != 0) |
|
will need the base pointer to this table later. */ |
|
|
/* We read this inline now, so that we don't have to go through |
|
|
bfd_section_from_shdr with it (since this particular strtab is |
|
|
used to find all of the ELF section names.) */ |
|
|
|
|
|
if (i_ehdrp->e_shstrndx != 0 && i_ehdrp->e_shoff) |
|
779 |
{ |
{ |
780 |
unsigned int num_sec; |
unsigned int num_sec; |
781 |
|
|
|
shstrtab = bfd_elf_get_str_section (abfd, i_ehdrp->e_shstrndx); |
|
|
if (!shstrtab) |
|
|
goto got_no_match; |
|
|
|
|
782 |
/* Once all of the section headers have been read and converted, we |
/* Once all of the section headers have been read and converted, we |
783 |
can start processing them. Note that the first section header is |
can start processing them. Note that the first section header is |
784 |
a dummy placeholder entry, so we ignore it. */ |
a dummy placeholder entry, so we ignore it. */ |
790 |
if (shindex == SHN_LORESERVE - 1) |
if (shindex == SHN_LORESERVE - 1) |
791 |
shindex += SHN_HIRESERVE + 1 - SHN_LORESERVE; |
shindex += SHN_HIRESERVE + 1 - SHN_LORESERVE; |
792 |
} |
} |
793 |
|
|
794 |
|
/* Set up group pointers. */ |
795 |
|
if (! _bfd_elf_setup_group_pointers (abfd)) |
796 |
|
goto got_wrong_format_error; |
797 |
} |
} |
798 |
|
|
799 |
/* Let the backend double check the format and override global |
/* Let the backend double check the format and override global |
823 |
} |
} |
824 |
} |
} |
825 |
|
|
826 |
/* It would be nice to be able to free more memory here, eg. old |
bfd_preserve_finish (abfd, &preserve); |
827 |
elf_elfsections, old tdata, but that's not possible since these |
return abfd->xvec; |
|
blocks are sitting inside obj_alloc'd memory. */ |
|
|
bfd_hash_table_free (&preserve.section_htab); |
|
|
return (abfd->xvec); |
|
828 |
|
|
829 |
got_wrong_format_error: |
got_wrong_format_error: |
830 |
/* There is way too much undoing of half-known state here. The caller, |
/* There is way too much undoing of half-known state here. The caller, |
839 |
bfd_set_error (bfd_error_wrong_format); |
bfd_set_error (bfd_error_wrong_format); |
840 |
|
|
841 |
got_no_match: |
got_no_match: |
842 |
abfd->arch_info = preserve.arch_info; |
if (preserve.marker != NULL) |
843 |
if (new_tdata != NULL) |
bfd_preserve_restore (abfd, &preserve); |
|
{ |
|
|
/* bfd_release frees all memory more recently bfd_alloc'd than |
|
|
its arg, as well as its arg. */ |
|
|
bfd_release (abfd, new_tdata); |
|
|
elf_tdata (abfd) = preserve.tdata; |
|
|
abfd->section_htab = preserve.section_htab; |
|
|
abfd->sections = preserve.sections; |
|
|
abfd->section_tail = preserve.section_tail; |
|
|
abfd->section_count = preserve.section_count; |
|
|
} |
|
844 |
return NULL; |
return NULL; |
845 |
} |
} |
846 |
|
|
849 |
/* Write out the relocs. */ |
/* Write out the relocs. */ |
850 |
|
|
851 |
void |
void |
852 |
elf_write_relocs (abfd, sec, data) |
elf_write_relocs (bfd *abfd, asection *sec, void *data) |
|
bfd *abfd; |
|
|
asection *sec; |
|
|
PTR data; |
|
853 |
{ |
{ |
854 |
boolean *failedp = (boolean *) data; |
bfd_boolean *failedp = data; |
855 |
Elf_Internal_Shdr *rela_hdr; |
Elf_Internal_Shdr *rela_hdr; |
856 |
Elf_External_Rela *outbound_relocas; |
bfd_vma addr_offset; |
857 |
Elf_External_Rel *outbound_relocs; |
void (*swap_out) (bfd *, const Elf_Internal_Rela *, bfd_byte *); |
858 |
|
size_t extsize; |
859 |
|
bfd_byte *dst_rela; |
860 |
unsigned int idx; |
unsigned int idx; |
861 |
int use_rela_p; |
asymbol *last_sym; |
862 |
asymbol *last_sym = 0; |
int last_sym_idx; |
|
int last_sym_idx = 0; |
|
863 |
|
|
864 |
/* If we have already failed, don't do anything. */ |
/* If we have already failed, don't do anything. */ |
865 |
if (*failedp) |
if (*failedp) |
878 |
rela_hdr = &elf_section_data (sec)->rel_hdr; |
rela_hdr = &elf_section_data (sec)->rel_hdr; |
879 |
|
|
880 |
rela_hdr->sh_size = rela_hdr->sh_entsize * sec->reloc_count; |
rela_hdr->sh_size = rela_hdr->sh_entsize * sec->reloc_count; |
881 |
rela_hdr->contents = (PTR) bfd_alloc (abfd, rela_hdr->sh_size); |
rela_hdr->contents = bfd_alloc (abfd, rela_hdr->sh_size); |
882 |
if (rela_hdr->contents == NULL) |
if (rela_hdr->contents == NULL) |
883 |
{ |
{ |
884 |
*failedp = true; |
*failedp = TRUE; |
885 |
return; |
return; |
886 |
} |
} |
887 |
|
|
888 |
/* Figure out whether the relocations are RELA or REL relocations. */ |
/* Figure out whether the relocations are RELA or REL relocations. */ |
889 |
if (rela_hdr->sh_type == SHT_RELA) |
if (rela_hdr->sh_type == SHT_RELA) |
890 |
use_rela_p = true; |
{ |
891 |
|
swap_out = elf_swap_reloca_out; |
892 |
|
extsize = sizeof (Elf_External_Rela); |
893 |
|
} |
894 |
else if (rela_hdr->sh_type == SHT_REL) |
else if (rela_hdr->sh_type == SHT_REL) |
895 |
use_rela_p = false; |
{ |
896 |
|
swap_out = elf_swap_reloc_out; |
897 |
|
extsize = sizeof (Elf_External_Rel); |
898 |
|
} |
899 |
else |
else |
900 |
/* Every relocation section should be either an SHT_RELA or an |
/* Every relocation section should be either an SHT_RELA or an |
901 |
SHT_REL section. */ |
SHT_REL section. */ |
902 |
abort (); |
abort (); |
903 |
|
|
904 |
/* orelocation has the data, reloc_count has the count... */ |
/* The address of an ELF reloc is section relative for an object |
905 |
if (use_rela_p) |
file, and absolute for an executable file or shared library. |
906 |
{ |
The address of a BFD reloc is always section relative. */ |
907 |
outbound_relocas = (Elf_External_Rela *) rela_hdr->contents; |
addr_offset = 0; |
908 |
|
if ((abfd->flags & (EXEC_P | DYNAMIC)) != 0) |
909 |
|
addr_offset = sec->vma; |
910 |
|
|
911 |
for (idx = 0; idx < sec->reloc_count; idx++) |
/* orelocation has the data, reloc_count has the count... */ |
912 |
|
last_sym = 0; |
913 |
|
last_sym_idx = 0; |
914 |
|
dst_rela = rela_hdr->contents; |
915 |
|
|
916 |
|
for (idx = 0; idx < sec->reloc_count; idx++, dst_rela += extsize) |
917 |
|
{ |
918 |
|
Elf_Internal_Rela src_rela; |
919 |
|
arelent *ptr; |
920 |
|
asymbol *sym; |
921 |
|
int n; |
922 |
|
|
923 |
|
ptr = sec->orelocation[idx]; |
924 |
|
sym = *ptr->sym_ptr_ptr; |
925 |
|
if (sym == last_sym) |
926 |
|
n = last_sym_idx; |
927 |
|
else if (bfd_is_abs_section (sym->section) && sym->value == 0) |
928 |
|
n = STN_UNDEF; |
929 |
|
else |
930 |
{ |
{ |
931 |
Elf_Internal_Rela dst_rela; |
last_sym = sym; |
932 |
Elf_External_Rela *src_rela; |
n = _bfd_elf_symbol_from_bfd_symbol (abfd, &sym); |
933 |
arelent *ptr; |
if (n < 0) |
|
asymbol *sym; |
|
|
int n; |
|
|
|
|
|
ptr = sec->orelocation[idx]; |
|
|
src_rela = outbound_relocas + idx; |
|
|
|
|
|
/* The address of an ELF reloc is section relative for an object |
|
|
file, and absolute for an executable file or shared library. |
|
|
The address of a BFD reloc is always section relative. */ |
|
|
if ((abfd->flags & (EXEC_P | DYNAMIC)) == 0) |
|
|
dst_rela.r_offset = ptr->address; |
|
|
else |
|
|
dst_rela.r_offset = ptr->address + sec->vma; |
|
|
|
|
|
sym = *ptr->sym_ptr_ptr; |
|
|
if (sym == last_sym) |
|
|
n = last_sym_idx; |
|
|
else if (bfd_is_abs_section (sym->section) && sym->value == 0) |
|
|
n = STN_UNDEF; |
|
|
else |
|
934 |
{ |
{ |
935 |
last_sym = sym; |
*failedp = TRUE; |
|
n = _bfd_elf_symbol_from_bfd_symbol (abfd, &sym); |
|
|
if (n < 0) |
|
|
{ |
|
|
*failedp = true; |
|
|
return; |
|
|
} |
|
|
last_sym_idx = n; |
|
|
} |
|
|
|
|
|
if ((*ptr->sym_ptr_ptr)->the_bfd != NULL |
|
|
&& (*ptr->sym_ptr_ptr)->the_bfd->xvec != abfd->xvec |
|
|
&& ! _bfd_elf_validate_reloc (abfd, ptr)) |
|
|
{ |
|
|
*failedp = true; |
|
936 |
return; |
return; |
937 |
} |
} |
938 |
|
last_sym_idx = n; |
|
dst_rela.r_info = ELF_R_INFO (n, ptr->howto->type); |
|
|
|
|
|
dst_rela.r_addend = ptr->addend; |
|
|
elf_swap_reloca_out (abfd, &dst_rela, src_rela); |
|
939 |
} |
} |
|
} |
|
|
else |
|
|
/* REL relocations */ |
|
|
{ |
|
|
outbound_relocs = (Elf_External_Rel *) rela_hdr->contents; |
|
940 |
|
|
941 |
for (idx = 0; idx < sec->reloc_count; idx++) |
if ((*ptr->sym_ptr_ptr)->the_bfd != NULL |
942 |
|
&& (*ptr->sym_ptr_ptr)->the_bfd->xvec != abfd->xvec |
943 |
|
&& ! _bfd_elf_validate_reloc (abfd, ptr)) |
944 |
{ |
{ |
945 |
Elf_Internal_Rel dst_rel; |
*failedp = TRUE; |
946 |
Elf_External_Rel *src_rel; |
return; |
|
arelent *ptr; |
|
|
int n; |
|
|
asymbol *sym; |
|
|
|
|
|
ptr = sec->orelocation[idx]; |
|
|
sym = *ptr->sym_ptr_ptr; |
|
|
src_rel = outbound_relocs + idx; |
|
|
|
|
|
/* The address of an ELF reloc is section relative for an object |
|
|
file, and absolute for an executable file or shared library. |
|
|
The address of a BFD reloc is always section relative. */ |
|
|
if ((abfd->flags & (EXEC_P | DYNAMIC)) == 0) |
|
|
dst_rel.r_offset = ptr->address; |
|
|
else |
|
|
dst_rel.r_offset = ptr->address + sec->vma; |
|
|
|
|
|
if (sym == last_sym) |
|
|
n = last_sym_idx; |
|
|
else if (bfd_is_abs_section (sym->section) && sym->value == 0) |
|
|
n = STN_UNDEF; |
|
|
else |
|
|
{ |
|
|
last_sym = sym; |
|
|
n = _bfd_elf_symbol_from_bfd_symbol (abfd, &sym); |
|
|
if (n < 0) |
|
|
{ |
|
|
*failedp = true; |
|
|
return; |
|
|
} |
|
|
last_sym_idx = n; |
|
|
} |
|
|
|
|
|
if ((*ptr->sym_ptr_ptr)->the_bfd != NULL |
|
|
&& (*ptr->sym_ptr_ptr)->the_bfd->xvec != abfd->xvec |
|
|
&& ! _bfd_elf_validate_reloc (abfd, ptr)) |
|
|
{ |
|
|
*failedp = true; |
|
|
return; |
|
|
} |
|
|
|
|
|
dst_rel.r_info = ELF_R_INFO (n, ptr->howto->type); |
|
|
|
|
|
elf_swap_reloc_out (abfd, &dst_rel, src_rel); |
|
947 |
} |
} |
948 |
|
|
949 |
|
src_rela.r_offset = ptr->address + addr_offset; |
950 |
|
src_rela.r_info = ELF_R_INFO (n, ptr->howto->type); |
951 |
|
src_rela.r_addend = ptr->addend; |
952 |
|
(*swap_out) (abfd, &src_rela, dst_rela); |
953 |
} |
} |
954 |
} |
} |
955 |
|
|
956 |
/* Write out the program headers. */ |
/* Write out the program headers. */ |
957 |
|
|
958 |
int |
int |
959 |
elf_write_out_phdrs (abfd, phdr, count) |
elf_write_out_phdrs (bfd *abfd, |
960 |
bfd *abfd; |
const Elf_Internal_Phdr *phdr, |
961 |
const Elf_Internal_Phdr *phdr; |
unsigned int count) |
|
unsigned int count; |
|
962 |
{ |
{ |
963 |
while (count--) |
while (count--) |
964 |
{ |
{ |
965 |
Elf_External_Phdr extphdr; |
Elf_External_Phdr extphdr; |
966 |
elf_swap_phdr_out (abfd, phdr, &extphdr); |
elf_swap_phdr_out (abfd, phdr, &extphdr); |
967 |
if (bfd_bwrite (&extphdr, (bfd_size_type) sizeof (Elf_External_Phdr), |
if (bfd_bwrite (&extphdr, sizeof (Elf_External_Phdr), abfd) |
968 |
abfd) != sizeof (Elf_External_Phdr)) |
!= sizeof (Elf_External_Phdr)) |
969 |
return -1; |
return -1; |
970 |
phdr++; |
phdr++; |
971 |
} |
} |
974 |
|
|
975 |
/* Write out the section headers and the ELF file header. */ |
/* Write out the section headers and the ELF file header. */ |
976 |
|
|
977 |
boolean |
bfd_boolean |
978 |
elf_write_shdrs_and_ehdr (abfd) |
elf_write_shdrs_and_ehdr (bfd *abfd) |
|
bfd *abfd; |
|
979 |
{ |
{ |
980 |
Elf_External_Ehdr x_ehdr; /* Elf file header, external form */ |
Elf_External_Ehdr x_ehdr; /* Elf file header, external form */ |
981 |
Elf_Internal_Ehdr *i_ehdrp; /* Elf file header, internal form */ |
Elf_Internal_Ehdr *i_ehdrp; /* Elf file header, internal form */ |
995 |
elf_swap_ehdr_out (abfd, i_ehdrp, &x_ehdr); |
elf_swap_ehdr_out (abfd, i_ehdrp, &x_ehdr); |
996 |
amt = sizeof (x_ehdr); |
amt = sizeof (x_ehdr); |
997 |
if (bfd_seek (abfd, (file_ptr) 0, SEEK_SET) != 0 |
if (bfd_seek (abfd, (file_ptr) 0, SEEK_SET) != 0 |
998 |
|| bfd_bwrite ((PTR) & x_ehdr, amt, abfd) != amt) |
|| bfd_bwrite (&x_ehdr, amt, abfd) != amt) |
999 |
return false; |
return FALSE; |
1000 |
|
|
1001 |
/* Some fields in the first section header handle overflow of ehdr |
/* Some fields in the first section header handle overflow of ehdr |
1002 |
fields. */ |
fields. */ |
1008 |
/* at this point we've concocted all the ELF sections... */ |
/* at this point we've concocted all the ELF sections... */ |
1009 |
amt = i_ehdrp->e_shnum; |
amt = i_ehdrp->e_shnum; |
1010 |
amt *= sizeof (*x_shdrp); |
amt *= sizeof (*x_shdrp); |
1011 |
x_shdrp = (Elf_External_Shdr *) bfd_alloc (abfd, amt); |
x_shdrp = bfd_alloc (abfd, amt); |
1012 |
if (!x_shdrp) |
if (!x_shdrp) |
1013 |
return false; |
return FALSE; |
1014 |
|
|
1015 |
for (count = 0; count < i_ehdrp->e_shnum; i_shdrp++, count++) |
for (count = 0; count < i_ehdrp->e_shnum; i_shdrp++, count++) |
1016 |
{ |
{ |
1018 |
elf_debug_section (count, *i_shdrp); |
elf_debug_section (count, *i_shdrp); |
1019 |
#endif |
#endif |
1020 |
elf_swap_shdr_out (abfd, *i_shdrp, x_shdrp + count); |
elf_swap_shdr_out (abfd, *i_shdrp, x_shdrp + count); |
1021 |
|
|
1022 |
if (count == SHN_LORESERVE - 1) |
if (count == SHN_LORESERVE - 1) |
1023 |
i_shdrp += SHN_HIRESERVE + 1 - SHN_LORESERVE; |
i_shdrp += SHN_HIRESERVE + 1 - SHN_LORESERVE; |
1024 |
} |
} |
1025 |
if (bfd_seek (abfd, (file_ptr) i_ehdrp->e_shoff, SEEK_SET) != 0 |
if (bfd_seek (abfd, (file_ptr) i_ehdrp->e_shoff, SEEK_SET) != 0 |
1026 |
|| bfd_bwrite ((PTR) x_shdrp, amt, abfd) != amt) |
|| bfd_bwrite (x_shdrp, amt, abfd) != amt) |
1027 |
return false; |
return FALSE; |
1028 |
|
|
1029 |
/* need to dump the string table too... */ |
/* need to dump the string table too... */ |
1030 |
|
|
1031 |
return true; |
return TRUE; |
1032 |
} |
} |
1033 |
|
|
1034 |
long |
long |
1035 |
elf_slurp_symbol_table (abfd, symptrs, dynamic) |
elf_slurp_symbol_table (bfd *abfd, asymbol **symptrs, bfd_boolean dynamic) |
|
bfd *abfd; |
|
|
asymbol **symptrs; /* Buffer for generated bfd symbols */ |
|
|
boolean dynamic; |
|
1036 |
{ |
{ |
1037 |
Elf_Internal_Shdr *hdr; |
Elf_Internal_Shdr *hdr; |
1038 |
Elf_Internal_Shdr *verhdr; |
Elf_Internal_Shdr *verhdr; |
1044 |
Elf_Internal_Sym *isymbuf = NULL; |
Elf_Internal_Sym *isymbuf = NULL; |
1045 |
Elf_External_Versym *xver; |
Elf_External_Versym *xver; |
1046 |
Elf_External_Versym *xverbuf = NULL; |
Elf_External_Versym *xverbuf = NULL; |
1047 |
struct elf_backend_data *ebd; |
const struct elf_backend_data *ebd; |
1048 |
bfd_size_type amt; |
bfd_size_type amt; |
1049 |
|
|
1050 |
/* Read each raw ELF symbol, converting from external ELF form to |
/* Read each raw ELF symbol, converting from external ELF form to |
1074 |
|| (elf_tdata (abfd)->dynverref_section != 0 |
|| (elf_tdata (abfd)->dynverref_section != 0 |
1075 |
&& elf_tdata (abfd)->verref == NULL)) |
&& elf_tdata (abfd)->verref == NULL)) |
1076 |
{ |
{ |
1077 |
if (! _bfd_elf_slurp_version_tables (abfd)) |
if (!_bfd_elf_slurp_version_tables (abfd, FALSE)) |
1078 |
return -1; |
return -1; |
1079 |
} |
} |
1080 |
} |
} |
1092 |
|
|
1093 |
amt = symcount; |
amt = symcount; |
1094 |
amt *= sizeof (elf_symbol_type); |
amt *= sizeof (elf_symbol_type); |
1095 |
symbase = (elf_symbol_type *) bfd_zalloc (abfd, amt); |
symbase = bfd_zalloc (abfd, amt); |
1096 |
if (symbase == (elf_symbol_type *) NULL) |
if (symbase == (elf_symbol_type *) NULL) |
1097 |
goto error_return; |
goto error_return; |
1098 |
|
|
1107 |
symcount); |
symcount); |
1108 |
|
|
1109 |
/* Slurp in the symbols without the version information, |
/* Slurp in the symbols without the version information, |
1110 |
since that is more helpful than just quitting. */ |
since that is more helpful than just quitting. */ |
1111 |
verhdr = NULL; |
verhdr = NULL; |
1112 |
} |
} |
1113 |
|
|
1116 |
if (bfd_seek (abfd, verhdr->sh_offset, SEEK_SET) != 0) |
if (bfd_seek (abfd, verhdr->sh_offset, SEEK_SET) != 0) |
1117 |
goto error_return; |
goto error_return; |
1118 |
|
|
1119 |
xverbuf = (Elf_External_Versym *) bfd_malloc (verhdr->sh_size); |
xverbuf = bfd_malloc (verhdr->sh_size); |
1120 |
if (xverbuf == NULL && verhdr->sh_size != 0) |
if (xverbuf == NULL && verhdr->sh_size != 0) |
1121 |
goto error_return; |
goto error_return; |
1122 |
|
|
1123 |
if (bfd_bread ((PTR) xverbuf, verhdr->sh_size, abfd) |
if (bfd_bread (xverbuf, verhdr->sh_size, abfd) != verhdr->sh_size) |
|
!= verhdr->sh_size) |
|
1124 |
goto error_return; |
goto error_return; |
1125 |
} |
} |
1126 |
|
|
1134 |
memcpy (&sym->internal_elf_sym, isym, sizeof (Elf_Internal_Sym)); |
memcpy (&sym->internal_elf_sym, isym, sizeof (Elf_Internal_Sym)); |
1135 |
sym->symbol.the_bfd = abfd; |
sym->symbol.the_bfd = abfd; |
1136 |
|
|
1137 |
sym->symbol.name = bfd_elf_string_from_elf_section (abfd, |
sym->symbol.name = bfd_elf_sym_name (abfd, hdr, isym); |
|
hdr->sh_link, |
|
|
isym->st_name); |
|
1138 |
|
|
1139 |
sym->symbol.value = isym->st_value; |
sym->symbol.value = isym->st_value; |
1140 |
|
|
1145 |
else if (isym->st_shndx < SHN_LORESERVE |
else if (isym->st_shndx < SHN_LORESERVE |
1146 |
|| isym->st_shndx > SHN_HIRESERVE) |
|| isym->st_shndx > SHN_HIRESERVE) |
1147 |
{ |
{ |
1148 |
sym->symbol.section = section_from_elf_index (abfd, |
sym->symbol.section = bfd_section_from_elf_index (abfd, |
1149 |
isym->st_shndx); |
isym->st_shndx); |
1150 |
if (sym->symbol.section == NULL) |
if (sym->symbol.section == NULL) |
1151 |
{ |
{ |
1152 |
/* This symbol is in a section for which we did not |
/* This symbol is in a section for which we did not |
1171 |
else |
else |
1172 |
sym->symbol.section = bfd_abs_section_ptr; |
sym->symbol.section = bfd_abs_section_ptr; |
1173 |
|
|
1174 |
/* If this is a relocateable file, then the symbol value is |
/* If this is a relocatable file, then the symbol value is |
1175 |
already section relative. */ |
already section relative. */ |
1176 |
if ((abfd->flags & (EXEC_P | DYNAMIC)) != 0) |
if ((abfd->flags & (EXEC_P | DYNAMIC)) != 0) |
1177 |
sym->symbol.value -= sym->symbol.section->vma; |
sym->symbol.value -= sym->symbol.section->vma; |
1178 |
|
|
1204 |
case STT_OBJECT: |
case STT_OBJECT: |
1205 |
sym->symbol.flags |= BSF_OBJECT; |
sym->symbol.flags |= BSF_OBJECT; |
1206 |
break; |
break; |
1207 |
|
case STT_TLS: |
1208 |
|
sym->symbol.flags |= BSF_THREAD_LOCAL; |
1209 |
|
break; |
1210 |
} |
} |
1211 |
|
|
1212 |
if (dynamic) |
if (dynamic) |
1263 |
return -1; |
return -1; |
1264 |
} |
} |
1265 |
|
|
1266 |
/* Read relocations for ASECT from REL_HDR. There are RELOC_COUNT of |
/* Read relocations for ASECT from REL_HDR. There are RELOC_COUNT of |
1267 |
them. */ |
them. */ |
1268 |
|
|
1269 |
static boolean |
static bfd_boolean |
1270 |
elf_slurp_reloc_table_from_section (abfd, asect, rel_hdr, reloc_count, |
elf_slurp_reloc_table_from_section (bfd *abfd, |
1271 |
relents, symbols, dynamic) |
asection *asect, |
1272 |
bfd *abfd; |
Elf_Internal_Shdr *rel_hdr, |
1273 |
asection *asect; |
bfd_size_type reloc_count, |
1274 |
Elf_Internal_Shdr *rel_hdr; |
arelent *relents, |
1275 |
bfd_size_type reloc_count; |
asymbol **symbols, |
1276 |
arelent *relents; |
bfd_boolean dynamic) |
|
asymbol **symbols; |
|
|
boolean dynamic; |
|
1277 |
{ |
{ |
1278 |
struct elf_backend_data * const ebd = get_elf_backend_data (abfd); |
const struct elf_backend_data * const ebd = get_elf_backend_data (abfd); |
1279 |
PTR allocated = NULL; |
void *allocated = NULL; |
1280 |
bfd_byte *native_relocs; |
bfd_byte *native_relocs; |
1281 |
arelent *relent; |
arelent *relent; |
1282 |
unsigned int i; |
unsigned int i; |
1283 |
int entsize; |
int entsize; |
1284 |
|
unsigned int symcount; |
1285 |
|
|
1286 |
allocated = (PTR) bfd_malloc (rel_hdr->sh_size); |
allocated = bfd_malloc (rel_hdr->sh_size); |
1287 |
if (allocated == NULL) |
if (allocated == NULL) |
1288 |
goto error_return; |
goto error_return; |
1289 |
|
|
1292 |
!= rel_hdr->sh_size)) |
!= rel_hdr->sh_size)) |
1293 |
goto error_return; |
goto error_return; |
1294 |
|
|
1295 |
native_relocs = (bfd_byte *) allocated; |
native_relocs = allocated; |
1296 |
|
|
1297 |
entsize = rel_hdr->sh_entsize; |
entsize = rel_hdr->sh_entsize; |
1298 |
BFD_ASSERT (entsize == sizeof (Elf_External_Rel) |
BFD_ASSERT (entsize == sizeof (Elf_External_Rel) |
1299 |
|| entsize == sizeof (Elf_External_Rela)); |
|| entsize == sizeof (Elf_External_Rela)); |
1300 |
|
|
1301 |
|
if (dynamic) |
1302 |
|
symcount = bfd_get_dynamic_symcount (abfd); |
1303 |
|
else |
1304 |
|
symcount = bfd_get_symcount (abfd); |
1305 |
|
|
1306 |
for (i = 0, relent = relents; |
for (i = 0, relent = relents; |
1307 |
i < reloc_count; |
i < reloc_count; |
1308 |
i++, relent++, native_relocs += entsize) |
i++, relent++, native_relocs += entsize) |
1309 |
{ |
{ |
1310 |
Elf_Internal_Rela rela; |
Elf_Internal_Rela rela; |
|
Elf_Internal_Rel rel; |
|
1311 |
|
|
1312 |
if (entsize == sizeof (Elf_External_Rela)) |
if (entsize == sizeof (Elf_External_Rela)) |
1313 |
elf_swap_reloca_in (abfd, (Elf_External_Rela *) native_relocs, &rela); |
elf_swap_reloca_in (abfd, native_relocs, &rela); |
1314 |
else |
else |
1315 |
{ |
elf_swap_reloc_in (abfd, native_relocs, &rela); |
|
elf_swap_reloc_in (abfd, (Elf_External_Rel *) native_relocs, &rel); |
|
|
rela.r_offset = rel.r_offset; |
|
|
rela.r_info = rel.r_info; |
|
|
rela.r_addend = 0; |
|
|
} |
|
1316 |
|
|
1317 |
/* The address of an ELF reloc is section relative for an object |
/* The address of an ELF reloc is section relative for an object |
1318 |
file, and absolute for an executable file or shared library. |
file, and absolute for an executable file or shared library. |
1325 |
|
|
1326 |
if (ELF_R_SYM (rela.r_info) == 0) |
if (ELF_R_SYM (rela.r_info) == 0) |
1327 |
relent->sym_ptr_ptr = bfd_abs_section_ptr->symbol_ptr_ptr; |
relent->sym_ptr_ptr = bfd_abs_section_ptr->symbol_ptr_ptr; |
1328 |
|
else if (ELF_R_SYM (rela.r_info) > symcount) |
1329 |
|
{ |
1330 |
|
(*_bfd_error_handler) |
1331 |
|
(_("%s(%s): relocation %d has invalid symbol index %ld"), |
1332 |
|
abfd->filename, asect->name, i, ELF_R_SYM (rela.r_info)); |
1333 |
|
relent->sym_ptr_ptr = bfd_abs_section.symbol_ptr_ptr; |
1334 |
|
} |
1335 |
else |
else |
1336 |
{ |
{ |
1337 |
asymbol **ps, *s; |
asymbol **ps, *s; |
1339 |
ps = symbols + ELF_R_SYM (rela.r_info) - 1; |
ps = symbols + ELF_R_SYM (rela.r_info) - 1; |
1340 |
s = *ps; |
s = *ps; |
1341 |
|
|
1342 |
/* Canonicalize ELF section symbols. FIXME: Why? */ |
relent->sym_ptr_ptr = ps; |
|
if ((s->flags & BSF_SECTION_SYM) == 0) |
|
|
relent->sym_ptr_ptr = ps; |
|
|
else |
|
|
relent->sym_ptr_ptr = s->section->symbol_ptr_ptr; |
|
1343 |
} |
} |
1344 |
|
|
1345 |
relent->addend = rela.r_addend; |
relent->addend = rela.r_addend; |
1346 |
|
|
1347 |
if (entsize == sizeof (Elf_External_Rela)) |
if ((entsize == sizeof (Elf_External_Rela) |
1348 |
|
&& ebd->elf_info_to_howto != NULL) |
1349 |
|
|| ebd->elf_info_to_howto_rel == NULL) |
1350 |
(*ebd->elf_info_to_howto) (abfd, relent, &rela); |
(*ebd->elf_info_to_howto) (abfd, relent, &rela); |
1351 |
else |
else |
1352 |
(*ebd->elf_info_to_howto_rel) (abfd, relent, &rel); |
(*ebd->elf_info_to_howto_rel) (abfd, relent, &rela); |
1353 |
} |
} |
1354 |
|
|
1355 |
if (allocated != NULL) |
if (allocated != NULL) |
1356 |
free (allocated); |
free (allocated); |
1357 |
|
|
1358 |
return true; |
return TRUE; |
1359 |
|
|
1360 |
error_return: |
error_return: |
1361 |
if (allocated != NULL) |
if (allocated != NULL) |
1362 |
free (allocated); |
free (allocated); |
1363 |
return false; |
return FALSE; |
1364 |
} |
} |
1365 |
|
|
1366 |
/* Read in and swap the external relocs. */ |
/* Read in and swap the external relocs. */ |
1367 |
|
|
1368 |
boolean |
bfd_boolean |
1369 |
elf_slurp_reloc_table (abfd, asect, symbols, dynamic) |
elf_slurp_reloc_table (bfd *abfd, |
1370 |
bfd *abfd; |
asection *asect, |
1371 |
asection *asect; |
asymbol **symbols, |
1372 |
asymbol **symbols; |
bfd_boolean dynamic) |
|
boolean dynamic; |
|
1373 |
{ |
{ |
1374 |
struct bfd_elf_section_data * const d = elf_section_data (asect); |
struct bfd_elf_section_data * const d = elf_section_data (asect); |
1375 |
Elf_Internal_Shdr *rel_hdr; |
Elf_Internal_Shdr *rel_hdr; |
1380 |
bfd_size_type amt; |
bfd_size_type amt; |
1381 |
|
|
1382 |
if (asect->relocation != NULL) |
if (asect->relocation != NULL) |
1383 |
return true; |
return TRUE; |
1384 |
|
|
1385 |
if (! dynamic) |
if (! dynamic) |
1386 |
{ |
{ |
1387 |
if ((asect->flags & SEC_RELOC) == 0 |
if ((asect->flags & SEC_RELOC) == 0 |
1388 |
|| asect->reloc_count == 0) |
|| asect->reloc_count == 0) |
1389 |
return true; |
return TRUE; |
1390 |
|
|
1391 |
rel_hdr = &d->rel_hdr; |
rel_hdr = &d->rel_hdr; |
1392 |
reloc_count = NUM_SHDR_ENTRIES (rel_hdr); |
reloc_count = NUM_SHDR_ENTRIES (rel_hdr); |
1404 |
case because relocations against this section may use the |
case because relocations against this section may use the |
1405 |
dynamic symbol table, and in that case bfd_section_from_shdr |
dynamic symbol table, and in that case bfd_section_from_shdr |
1406 |
in elf.c does not update the RELOC_COUNT. */ |
in elf.c does not update the RELOC_COUNT. */ |
1407 |
if (asect->_raw_size == 0) |
if (asect->size == 0) |
1408 |
return true; |
return TRUE; |
1409 |
|
|
1410 |
rel_hdr = &d->this_hdr; |
rel_hdr = &d->this_hdr; |
1411 |
reloc_count = NUM_SHDR_ENTRIES (rel_hdr); |
reloc_count = NUM_SHDR_ENTRIES (rel_hdr); |
1414 |
} |
} |
1415 |
|
|
1416 |
amt = (reloc_count + reloc_count2) * sizeof (arelent); |
amt = (reloc_count + reloc_count2) * sizeof (arelent); |
1417 |
relents = (arelent *) bfd_alloc (abfd, amt); |
relents = bfd_alloc (abfd, amt); |
1418 |
if (relents == NULL) |
if (relents == NULL) |
1419 |
return false; |
return FALSE; |
1420 |
|
|
1421 |
if (!elf_slurp_reloc_table_from_section (abfd, asect, |
if (!elf_slurp_reloc_table_from_section (abfd, asect, |
1422 |
rel_hdr, reloc_count, |
rel_hdr, reloc_count, |
1423 |
relents, |
relents, |
1424 |
symbols, dynamic)) |
symbols, dynamic)) |
1425 |
return false; |
return FALSE; |
1426 |
|
|
1427 |
if (rel_hdr2 |
if (rel_hdr2 |
1428 |
&& !elf_slurp_reloc_table_from_section (abfd, asect, |
&& !elf_slurp_reloc_table_from_section (abfd, asect, |
1429 |
rel_hdr2, reloc_count2, |
rel_hdr2, reloc_count2, |
1430 |
relents + reloc_count, |
relents + reloc_count, |
1431 |
symbols, dynamic)) |
symbols, dynamic)) |
1432 |
return false; |
return FALSE; |
1433 |
|
|
1434 |
asect->relocation = relents; |
asect->relocation = relents; |
1435 |
return true; |
return TRUE; |
1436 |
} |
} |
1437 |
|
|
1438 |
#ifdef DEBUG |
#ifdef DEBUG |
1439 |
static void |
static void |
1440 |
elf_debug_section (num, hdr) |
elf_debug_section (int num, Elf_Internal_Shdr *hdr) |
|
int num; |
|
|
Elf_Internal_Shdr *hdr; |
|
1441 |
{ |
{ |
1442 |
fprintf (stderr, "\nSection#%d '%s' 0x%.8lx\n", num, |
fprintf (stderr, "\nSection#%d '%s' 0x%.8lx\n", num, |
1443 |
hdr->bfd_section != NULL ? hdr->bfd_section->name : "", |
hdr->bfd_section != NULL ? hdr->bfd_section->name : "", |
1463 |
} |
} |
1464 |
|
|
1465 |
static void |
static void |
1466 |
elf_debug_file (ehdrp) |
elf_debug_file (Elf_Internal_Ehdr *ehdrp) |
|
Elf_Internal_Ehdr *ehdrp; |
|
1467 |
{ |
{ |
1468 |
fprintf (stderr, "e_entry = 0x%.8lx\n", (long) ehdrp->e_entry); |
fprintf (stderr, "e_entry = 0x%.8lx\n", (long) ehdrp->e_entry); |
1469 |
fprintf (stderr, "e_phoff = %ld\n", (long) ehdrp->e_phoff); |
fprintf (stderr, "e_phoff = %ld\n", (long) ehdrp->e_phoff); |
1475 |
} |
} |
1476 |
|
|
1477 |
static char * |
static char * |
1478 |
elf_symbol_flags (flags) |
elf_symbol_flags (flagword flags) |
|
flagword flags; |
|
1479 |
{ |
{ |
1480 |
static char buffer[1024]; |
static char buffer[1024]; |
1481 |
|
|
1546 |
} |
} |
1547 |
#endif |
#endif |
1548 |
|
|
1549 |
|
/* Create a new BFD as if by bfd_openr. Rather than opening a file, |
1550 |
|
reconstruct an ELF file by reading the segments out of remote memory |
1551 |
|
based on the ELF file header at EHDR_VMA and the ELF program headers it |
1552 |
|
points to. If not null, *LOADBASEP is filled in with the difference |
1553 |
|
between the VMAs from which the segments were read, and the VMAs the |
1554 |
|
file headers (and hence BFD's idea of each section's VMA) put them at. |
1555 |
|
|
1556 |
|
The function TARGET_READ_MEMORY is called to copy LEN bytes from the |
1557 |
|
remote memory at target address VMA into the local buffer at MYADDR; it |
1558 |
|
should return zero on success or an `errno' code on failure. TEMPL must |
1559 |
|
be a BFD for a target with the word size and byte order found in the |
1560 |
|
remote memory. */ |
1561 |
|
|
1562 |
|
bfd * |
1563 |
|
NAME(_bfd_elf,bfd_from_remote_memory) |
1564 |
|
(bfd *templ, |
1565 |
|
bfd_vma ehdr_vma, |
1566 |
|
bfd_vma *loadbasep, |
1567 |
|
int (*target_read_memory) (bfd_vma, bfd_byte *, int)) |
1568 |
|
{ |
1569 |
|
Elf_External_Ehdr x_ehdr; /* Elf file header, external form */ |
1570 |
|
Elf_Internal_Ehdr i_ehdr; /* Elf file header, internal form */ |
1571 |
|
Elf_External_Phdr *x_phdrs; |
1572 |
|
Elf_Internal_Phdr *i_phdrs, *last_phdr; |
1573 |
|
bfd *nbfd; |
1574 |
|
struct bfd_in_memory *bim; |
1575 |
|
int contents_size; |
1576 |
|
bfd_byte *contents; |
1577 |
|
int err; |
1578 |
|
unsigned int i; |
1579 |
|
bfd_vma loadbase; |
1580 |
|
|
1581 |
|
/* Read in the ELF header in external format. */ |
1582 |
|
err = target_read_memory (ehdr_vma, (bfd_byte *) &x_ehdr, sizeof x_ehdr); |
1583 |
|
if (err) |
1584 |
|
{ |
1585 |
|
bfd_set_error (bfd_error_system_call); |
1586 |
|
errno = err; |
1587 |
|
return NULL; |
1588 |
|
} |
1589 |
|
|
1590 |
|
/* Now check to see if we have a valid ELF file, and one that BFD can |
1591 |
|
make use of. The magic number must match, the address size ('class') |
1592 |
|
and byte-swapping must match our XVEC entry. */ |
1593 |
|
|
1594 |
|
if (! elf_file_p (&x_ehdr) |
1595 |
|
|| x_ehdr.e_ident[EI_VERSION] != EV_CURRENT |
1596 |
|
|| x_ehdr.e_ident[EI_CLASS] != ELFCLASS) |
1597 |
|
{ |
1598 |
|
bfd_set_error (bfd_error_wrong_format); |
1599 |
|
return NULL; |
1600 |
|
} |
1601 |
|
|
1602 |
|
/* Check that file's byte order matches xvec's */ |
1603 |
|
switch (x_ehdr.e_ident[EI_DATA]) |
1604 |
|
{ |
1605 |
|
case ELFDATA2MSB: /* Big-endian */ |
1606 |
|
if (! bfd_header_big_endian (templ)) |
1607 |
|
{ |
1608 |
|
bfd_set_error (bfd_error_wrong_format); |
1609 |
|
return NULL; |
1610 |
|
} |
1611 |
|
break; |
1612 |
|
case ELFDATA2LSB: /* Little-endian */ |
1613 |
|
if (! bfd_header_little_endian (templ)) |
1614 |
|
{ |
1615 |
|
bfd_set_error (bfd_error_wrong_format); |
1616 |
|
return NULL; |
1617 |
|
} |
1618 |
|
break; |
1619 |
|
case ELFDATANONE: /* No data encoding specified */ |
1620 |
|
default: /* Unknown data encoding specified */ |
1621 |
|
bfd_set_error (bfd_error_wrong_format); |
1622 |
|
return NULL; |
1623 |
|
} |
1624 |
|
|
1625 |
|
elf_swap_ehdr_in (templ, &x_ehdr, &i_ehdr); |
1626 |
|
|
1627 |
|
/* The file header tells where to find the program headers. |
1628 |
|
These are what we use to actually choose what to read. */ |
1629 |
|
|
1630 |
|
if (i_ehdr.e_phentsize != sizeof (Elf_External_Phdr) || i_ehdr.e_phnum == 0) |
1631 |
|
{ |
1632 |
|
bfd_set_error (bfd_error_wrong_format); |
1633 |
|
return NULL; |
1634 |
|
} |
1635 |
|
|
1636 |
|
x_phdrs = bfd_malloc (i_ehdr.e_phnum * (sizeof *x_phdrs + sizeof *i_phdrs)); |
1637 |
|
if (x_phdrs == NULL) |
1638 |
|
{ |
1639 |
|
bfd_set_error (bfd_error_no_memory); |
1640 |
|
return NULL; |
1641 |
|
} |
1642 |
|
err = target_read_memory (ehdr_vma + i_ehdr.e_phoff, (bfd_byte *) x_phdrs, |
1643 |
|
i_ehdr.e_phnum * sizeof x_phdrs[0]); |
1644 |
|
if (err) |
1645 |
|
{ |
1646 |
|
free (x_phdrs); |
1647 |
|
bfd_set_error (bfd_error_system_call); |
1648 |
|
errno = err; |
1649 |
|
return NULL; |
1650 |
|
} |
1651 |
|
i_phdrs = (Elf_Internal_Phdr *) &x_phdrs[i_ehdr.e_phnum]; |
1652 |
|
|
1653 |
|
contents_size = 0; |
1654 |
|
last_phdr = NULL; |
1655 |
|
loadbase = ehdr_vma; |
1656 |
|
for (i = 0; i < i_ehdr.e_phnum; ++i) |
1657 |
|
{ |
1658 |
|
elf_swap_phdr_in (templ, &x_phdrs[i], &i_phdrs[i]); |
1659 |
|
if (i_phdrs[i].p_type == PT_LOAD) |
1660 |
|
{ |
1661 |
|
bfd_vma segment_end; |
1662 |
|
segment_end = (i_phdrs[i].p_offset + i_phdrs[i].p_filesz |
1663 |
|
+ i_phdrs[i].p_align - 1) & -i_phdrs[i].p_align; |
1664 |
|
if (segment_end > (bfd_vma) contents_size) |
1665 |
|
contents_size = segment_end; |
1666 |
|
|
1667 |
|
if ((i_phdrs[i].p_offset & -i_phdrs[i].p_align) == 0) |
1668 |
|
loadbase = ehdr_vma - (i_phdrs[i].p_vaddr & -i_phdrs[i].p_align); |
1669 |
|
|
1670 |
|
last_phdr = &i_phdrs[i]; |
1671 |
|
} |
1672 |
|
} |
1673 |
|
if (last_phdr == NULL) |
1674 |
|
{ |
1675 |
|
/* There were no PT_LOAD segments, so we don't have anything to read. */ |
1676 |
|
free (x_phdrs); |
1677 |
|
bfd_set_error (bfd_error_wrong_format); |
1678 |
|
return NULL; |
1679 |
|
} |
1680 |
|
|
1681 |
|
/* Trim the last segment so we don't bother with zeros in the last page |
1682 |
|
that are off the end of the file. However, if the extra bit in that |
1683 |
|
page includes the section headers, keep them. */ |
1684 |
|
if ((bfd_vma) contents_size > last_phdr->p_offset + last_phdr->p_filesz |
1685 |
|
&& (bfd_vma) contents_size >= (i_ehdr.e_shoff |
1686 |
|
+ i_ehdr.e_shnum * i_ehdr.e_shentsize)) |
1687 |
|
{ |
1688 |
|
contents_size = last_phdr->p_offset + last_phdr->p_filesz; |
1689 |
|
if ((bfd_vma) contents_size < (i_ehdr.e_shoff |
1690 |
|
+ i_ehdr.e_shnum * i_ehdr.e_shentsize)) |
1691 |
|
contents_size = i_ehdr.e_shoff + i_ehdr.e_shnum * i_ehdr.e_shentsize; |
1692 |
|
} |
1693 |
|
else |
1694 |
|
contents_size = last_phdr->p_offset + last_phdr->p_filesz; |
1695 |
|
|
1696 |
|
/* Now we know the size of the whole image we want read in. */ |
1697 |
|
contents = bfd_zmalloc (contents_size); |
1698 |
|
if (contents == NULL) |
1699 |
|
{ |
1700 |
|
free (x_phdrs); |
1701 |
|
bfd_set_error (bfd_error_no_memory); |
1702 |
|
return NULL; |
1703 |
|
} |
1704 |
|
|
1705 |
|
for (i = 0; i < i_ehdr.e_phnum; ++i) |
1706 |
|
if (i_phdrs[i].p_type == PT_LOAD) |
1707 |
|
{ |
1708 |
|
bfd_vma start = i_phdrs[i].p_offset & -i_phdrs[i].p_align; |
1709 |
|
bfd_vma end = (i_phdrs[i].p_offset + i_phdrs[i].p_filesz |
1710 |
|
+ i_phdrs[i].p_align - 1) & -i_phdrs[i].p_align; |
1711 |
|
if (end > (bfd_vma) contents_size) |
1712 |
|
end = contents_size; |
1713 |
|
err = target_read_memory ((loadbase + i_phdrs[i].p_vaddr) |
1714 |
|
& -i_phdrs[i].p_align, |
1715 |
|
contents + start, end - start); |
1716 |
|
if (err) |
1717 |
|
{ |
1718 |
|
free (x_phdrs); |
1719 |
|
free (contents); |
1720 |
|
bfd_set_error (bfd_error_system_call); |
1721 |
|
errno = err; |
1722 |
|
return NULL; |
1723 |
|
} |
1724 |
|
} |
1725 |
|
free (x_phdrs); |
1726 |
|
|
1727 |
|
/* If the segments visible in memory didn't include the section headers, |
1728 |
|
then clear them from the file header. */ |
1729 |
|
if ((bfd_vma) contents_size < (i_ehdr.e_shoff |
1730 |
|
+ i_ehdr.e_shnum * i_ehdr.e_shentsize)) |
1731 |
|
{ |
1732 |
|
memset (&x_ehdr.e_shoff, 0, sizeof x_ehdr.e_shoff); |
1733 |
|
memset (&x_ehdr.e_shnum, 0, sizeof x_ehdr.e_shnum); |
1734 |
|
memset (&x_ehdr.e_shstrndx, 0, sizeof x_ehdr.e_shstrndx); |
1735 |
|
} |
1736 |
|
|
1737 |
|
/* This will normally have been in the first PT_LOAD segment. But it |
1738 |
|
conceivably could be missing, and we might have just changed it. */ |
1739 |
|
memcpy (contents, &x_ehdr, sizeof x_ehdr); |
1740 |
|
|
1741 |
|
/* Now we have a memory image of the ELF file contents. Make a BFD. */ |
1742 |
|
bim = bfd_malloc (sizeof (struct bfd_in_memory)); |
1743 |
|
if (bim == NULL) |
1744 |
|
{ |
1745 |
|
free (contents); |
1746 |
|
bfd_set_error (bfd_error_no_memory); |
1747 |
|
return NULL; |
1748 |
|
} |
1749 |
|
nbfd = _bfd_new_bfd (); |
1750 |
|
if (nbfd == NULL) |
1751 |
|
{ |
1752 |
|
free (bim); |
1753 |
|
free (contents); |
1754 |
|
bfd_set_error (bfd_error_no_memory); |
1755 |
|
return NULL; |
1756 |
|
} |
1757 |
|
nbfd->filename = "<in-memory>"; |
1758 |
|
nbfd->xvec = templ->xvec; |
1759 |
|
bim->size = contents_size; |
1760 |
|
bim->buffer = contents; |
1761 |
|
nbfd->iostream = bim; |
1762 |
|
nbfd->flags = BFD_IN_MEMORY; |
1763 |
|
nbfd->direction = read_direction; |
1764 |
|
nbfd->mtime = time (NULL); |
1765 |
|
nbfd->mtime_set = TRUE; |
1766 |
|
|
1767 |
|
if (loadbasep) |
1768 |
|
*loadbasep = loadbase; |
1769 |
|
return nbfd; |
1770 |
|
} |
1771 |
|
|
1772 |
#include "elfcore.h" |
#include "elfcore.h" |
|
#include "elflink.h" |
|
1773 |
|
|
1774 |
/* Size-dependent data and functions. */ |
/* Size-dependent data and functions. */ |
1775 |
const struct elf_size_info NAME(_bfd_elf,size_info) = { |
const struct elf_size_info NAME(_bfd_elf,size_info) = { |
1783 |
sizeof (Elf_External_Note), |
sizeof (Elf_External_Note), |
1784 |
4, |
4, |
1785 |
1, |
1, |
1786 |
ARCH_SIZE, FILE_ALIGN, |
ARCH_SIZE, LOG_FILE_ALIGN, |
1787 |
ELFCLASS, EV_CURRENT, |
ELFCLASS, EV_CURRENT, |
1788 |
elf_write_out_phdrs, |
elf_write_out_phdrs, |
1789 |
elf_write_shdrs_and_ehdr, |
elf_write_shdrs_and_ehdr, |
1794 |
elf_slurp_symbol_table, |
elf_slurp_symbol_table, |
1795 |
elf_swap_dyn_in, |
elf_swap_dyn_in, |
1796 |
elf_swap_dyn_out, |
elf_swap_dyn_out, |
1797 |
NULL, |
elf_swap_reloc_in, |
1798 |
NULL, |
elf_swap_reloc_out, |
1799 |
NULL, |
elf_swap_reloca_in, |
1800 |
NULL |
elf_swap_reloca_out |
1801 |
}; |
}; |