This is the mail archive of the
binutils@sourceware.org
mailing list for the binutils project.
[ARM] undefined local symbols
- From: Nathan Sidwell <nathan at codesourcery dot com>
- To: binutils <binutils at sources dot redhat dot com>
- Date: Wed, 05 Aug 2009 17:17:04 +0100
- Subject: [ARM] undefined local symbols
The bug I recently fixed in the ARM assembler concerning missing expressions had
the artifact of emitting relocations against local undefined symbols. These
would cause the linker to segfault, which is unpleasant. Of course having such
an undefined symbol is a strange thing to do -- except for ARM_V4BX and ARM_NONE
relocs -- but we should emit some sensible error.
This patch does that. A weak undefined local symbol will decay to zero, and a
non-weak one will generate an error message.
tested on arm-eabi, ok?
nathan
--
Nathan Sidwell :: http://www.codesourcery.com :: CodeSourcery
2009-08-05 Nathan Sidwell <nathan@codesourcery.com>
* elf32-arm.c (elf32_arm_size_stubs): Don't die on undefined local
symbols.
(elf32_arm_final_link_relocate): Treat local undefined symbols the
same as global undefined symbols.
(elf32_arm_relocate_section): Give an error for local undefined
non-weak symbols, unless the reloc will not use the symbol.
Index: bfd/elf32-arm.c
===================================================================
RCS file: /cvs/src/src/bfd/elf32-arm.c,v
retrieving revision 1.207
diff -c -3 -p -r1.207 elf32-arm.c
*** bfd/elf32-arm.c 5 Aug 2009 12:36:14 -0000 1.207
--- bfd/elf32-arm.c 5 Aug 2009 16:11:00 -0000
*************** elf32_arm_size_stubs (bfd *output_bfd,
*** 4366,4371 ****
--- 4366,4376 ----
sym = local_syms + r_indx;
hdr = elf_elfsections (input_bfd)[sym->st_shndx];
sym_sec = hdr->bfd_section;
+ if (!sym_sec)
+ /* This is an undefined symbol. It can never
+ be resolved. */
+ continue;
+
if (ELF_ST_TYPE (sym->st_info) != STT_SECTION)
sym_value = sym->st_value;
destination = (sym_value + irela->r_addend
*************** elf32_arm_final_link_relocate (reloc_how
*** 6951,6957 ****
case R_ARM_PC24: /* Arm B/BL instruction. */
case R_ARM_PLT32:
{
- bfd_vma from;
bfd_signed_vma branch_offset;
struct elf32_arm_stub_hash_entry *stub_entry = NULL;
--- 6956,6961 ----
*************** elf32_arm_final_link_relocate (reloc_how
*** 6988,6993 ****
--- 6992,6999 ----
|| r_type == R_ARM_JUMP24
|| r_type == R_ARM_PLT32)
{
+ bfd_vma from;
+
/* If the call goes through a PLT entry, make sure to
check distance to the right destination address. */
if (h != NULL && splt != NULL && h->plt.offset != (bfd_vma) -1)
*************** elf32_arm_final_link_relocate (reloc_how
*** 7056,7064 ****
signed_addend >>= howto->rightshift;
/* A branch to an undefined weak symbol is turned into a jump to
! the next instruction unless a PLT entry will be created. */
! if (h && h->root.type == bfd_link_hash_undefweak
! && !(splt != NULL && h->plt.offset != (bfd_vma) -1))
{
value = (bfd_get_32 (input_bfd, hit_data) & 0xf0000000)
| 0x0affffff;
--- 7062,7072 ----
signed_addend >>= howto->rightshift;
/* A branch to an undefined weak symbol is turned into a jump to
! the next instruction unless a PLT entry will be created.
! Do the same for local undefined symbols. */
! if (h ? (h->root.type == bfd_link_hash_undefweak
! && !(splt != NULL && h->plt.offset != (bfd_vma) -1))
! : bfd_is_und_section (sym_sec))
{
value = (bfd_get_32 (input_bfd, hit_data) & 0xf0000000)
| 0x0affffff;
*************** elf32_arm_relocate_section (bfd *
*** 8704,8709 ****
--- 8712,8736 ----
sym = local_syms + r_symndx;
sym_type = ELF32_ST_TYPE (sym->st_info);
sec = local_sections[r_symndx];
+
+ /* An object file might have a reference to a local
+ undefined symbol. This is a daft object file, but we
+ should at least do something about it. V4BX & NONE
+ relocations do not use the symbol and are explicitly
+ allowed to use the undefined symbol, so allow those. */
+ if (r_type != R_ARM_V4BX
+ && r_type != R_ARM_NONE
+ && bfd_is_und_section (sec)
+ && ELF_ST_BIND (sym->st_info) != STB_WEAK)
+ {
+ if (!info->callbacks->undefined_symbol
+ (info, bfd_elf_string_from_elf_section
+ (input_bfd, symtab_hdr->sh_link, sym->st_name),
+ input_bfd, input_section,
+ rel->r_offset, TRUE))
+ return FALSE;
+ }
+
if (globals->use_rel)
{
relocation = (sec->output_section->vma