This is the mail archive of the binutils@sources.redhat.com mailing list for the binutils project.
Index Nav: | [Date Index] [Subject Index] [Author Index] [Thread Index] | |
---|---|---|
Message Nav: | [Date Prev] [Date Next] | [Thread Prev] [Thread Next] |
Other format: | [Raw text] |
Hi there, The link editor can output empty (zero) ARM/THUMB interworking stubs. See the attached archive for the test case. Running ``arm-elf-objdump -S x'' produces x: file format elf32-littlearm Disassembly of section .text: 00008000 <__foo_from_thumb>: 8000: 0000 lsl r0, r0, #0 ... 00008004 <__foo_change_to_arm>: 8004: 00000000 andeq r0, r0, r0 00008008 <__foo1_from_thumb>: 8008: 4778 bx pc 800a: 46c0 nop (mov r8, r8) etc... The problem is that the glue sections are output by ``elf_link_input_bfd'' before the .text sections relocation has written the interworking stubs. My "solution" so far is to delay the output of the sections having SEC_IN_MEMORY flags set until all the other sections are relocated and output. The idea is that SEC_IN_MEMORY sections generally depend upon the other ones, thus it makes sense to delay writing them until all the other section's processing has finished. Patch against elfink.h attached. Comments ? Regards, -velco P.S. And there's another thing, relocations are not generated for glue sections, which is OK, unless the linker is to output relocateable executables file (--emit-relocs). I'd appreciate guidance how to fix this (or the fix itself :).
Attachment:
zero-stub.tar.gz
Description: Binary data
--- elflink.h.orig Mon Apr 15 10:35:28 2002 +++ elflink.h Mon Apr 15 10:43:10 2002 @@ -4519,6 +4519,8 @@ static boolean elf_link_sec_merge_syms PARAMS ((struct elf_link_hash_entry *, PTR)); static boolean elf_link_input_bfd PARAMS ((struct elf_final_link_info *, bfd *)); +static boolean elf_link_in_memory_sections + PARAMS ((struct elf_final_link_info *, bfd *)); static boolean elf_reloc_link_order PARAMS ((bfd *, struct bfd_link_info *, asection *, struct bfd_link_order *)); @@ -5383,6 +5385,38 @@ elf_bfd_final_link (abfd, info) } } + /* Traverse the input bfds again and write in-memory sections. */ + for (sub = info->input_bfds; sub != NULL; sub = sub->link_next) + sub->output_has_begun = false; + for (o = abfd->sections; o != NULL; o = o->next) + { + for (p = o->link_order_head; p != NULL; p = p->next) + { + Elf_Internal_Shdr *rhdr; + + if (p->type == bfd_indirect_link_order + && (bfd_get_flavour (p->u.indirect.section->owner) + == bfd_target_elf_flavour) + && (((rhdr = &elf_section_data (p->u.indirect.section)->rel_hdr) + ->sh_entsize == 0) + || rhdr->sh_entsize == sizeof (Elf_External_Rel) + || rhdr->sh_entsize == sizeof (Elf_External_Rela)) + && (((rhdr = elf_section_data (p->u.indirect.section)->rel_hdr2) + == NULL) + || rhdr->sh_entsize == sizeof (Elf_External_Rel) + || rhdr->sh_entsize == sizeof (Elf_External_Rela))) + { + sub = p->u.indirect.section->owner; + if (! sub->output_has_begun) + { + if (! elf_link_in_memory_sections (&finfo, sub)) + goto error_return; + sub->output_has_begun = true; + } + } + } + } + /* Output any global symbols that got converted to local in a version script or due to symbol visibility. We do this in a separate step since ELF requires all local symbols to appear @@ -6924,6 +6958,9 @@ elf_link_input_bfd (finfo, input_bfd) } } + if (o->flags & SEC_IN_MEMORY) + continue; + /* Write out the modified section contents. */ if (bed->elf_backend_write_section && (*bed->elf_backend_write_section) (output_bfd, o, contents)) @@ -6972,6 +7009,93 @@ elf_link_input_bfd (finfo, input_bfd) } } + return true; +} + +static boolean +elf_link_in_memory_sections (finfo, input_bfd) + struct elf_final_link_info *finfo; + bfd *input_bfd; +{ + struct elf_backend_data *bed; + bfd *output_bfd; + asection *o; + + output_bfd = finfo->output_bfd; + bed = get_elf_backend_data (output_bfd); + + for (o = input_bfd->sections; o != NULL; o = o->next) + { + if (! o->linker_mark) + { + /* This section was omitted from the link. */ + continue; + } + + if ((o->flags & SEC_HAS_CONTENTS) == 0 + || (o->_raw_size == 0 && (o->flags & SEC_RELOC) == 0)) + continue; + + if ((o->flags & SEC_LINKER_CREATED) != 0) + { + /* Section was created by elf_link_create_dynamic_sections + or somesuch. */ + continue; + } + + if ((o->flags & SEC_IN_MEMORY) == 0) + { + /* Already output. */ + continue; + } + + BFD_ASSERT (o->contents != NULL); + + if (bed->elf_backend_write_section + && (*bed->elf_backend_write_section) (output_bfd, o, o->contents)) + { + /* Section written out. */ + } + else switch (elf_section_data (o)->sec_info_type) + { + case ELF_INFO_TYPE_STABS: + if (! (_bfd_write_section_stabs (output_bfd, + &elf_hash_table (finfo->info)->stab_info, + o, &elf_section_data (o)->sec_info, + o->contents))) + return false; + break; + case ELF_INFO_TYPE_MERGE: + if (! (_bfd_write_merged_section (output_bfd, o, + elf_section_data (o)->sec_info))) + return false; + break; + case ELF_INFO_TYPE_EH_FRAME: + { + asection *ehdrsec; + + ehdrsec + = bfd_get_section_by_name (elf_hash_table (finfo->info)->dynobj, + ".eh_frame_hdr"); + if (! (_bfd_elf_write_section_eh_frame (output_bfd, o, ehdrsec, + o->contents))) + return false; + } + break; + default: + { + bfd_size_type sec_size; + + sec_size = (o->_cooked_size != 0 ? o->_cooked_size : o->_raw_size); + if (! (o->flags & SEC_EXCLUDE) + && ! bfd_set_section_contents (output_bfd, o->output_section, + o->contents, + (file_ptr) o->output_offset, + sec_size)) + return false; + } + } + } return true; }
Index Nav: | [Date Index] [Subject Index] [Author Index] [Thread Index] | |
---|---|---|
Message Nav: | [Date Prev] [Date Next] | [Thread Prev] [Thread Next] |