This is the mail archive of the binutils@sourceware.org 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] |
Hello! The ELF standard says that STN_UNDEF (symbol index zero, the undefined symbol index) is to be marked as SHN_UNDEF, undefined symbol. There is one exception however: during relocations processing, a relocation against STN_UNDEF shall be treated as a symbol value of zero. The BFD code makes use of this, for example when it is writing out all relocations in bfd/elfcode.h:elf_write_relocs: [...] 1000 for (idx = 0; idx < sec->reloc_count; idx++, dst_rela += extsize) 1001 { 1002 Elf_Internal_Rela src_rela; 1003 arelent *ptr; 1004 asymbol *sym; 1005 int n; 1006 1007 ptr = sec->orelocation[idx]; 1008 sym = *ptr->sym_ptr_ptr; 1009 if (sym == last_sym) 1010 n = last_sym_idx; 1011 else if (bfd_is_abs_section (sym->section) && sym->value == 0) 1012 n = STN_UNDEF; 1013 else 1014 { 1015 last_sym = sym; 1016 n = _bfd_elf_symbol_from_bfd_symbol (abfd, &sym); [...] That is, if the symbol is (internally) listed in the absolute sections and it has a value of zero, simply a relocation against STN_UNDEF is emitted. For example on ARM, the bl instruction does a PC-relative jump, so to jump to an absolute value of 0x10000, ``bl 0x10000'' has to keep its relocation until the final linking is done, to be converted to the proper PC-relative offset. $ cat < ~/sgxx/issue8612/bl_ABS.s bl 0x10000 $ "$PWD"_install/bin/*-as -o bl_ABS.o ~/sgxx/issue8612/bl_ABS.s $ "$PWD"_install/bin/*-readelf -r bl_ABS.o Relocation section '.rel.text' at offset 0x25c contains 1 entries: Offset Info Type Sym.Value Sym. Name 00000000 0000001c R_ARM_CALL This info value translates to relocation type 28 (R_ARM_CALL) against symbol index zero (STN_UNDEF). objdump even translates this that it's an ABSolut value, and no longer STN_UNDEF: $ "$PWD"_install/bin/*-objdump -dr bl_ABS.o bl_ABS.o: file format elf32-littlearm Disassembly of section .text: 00000000 <.text>: 0: eb003ffe bl 10000 <.text+0x10000> 0: R_ARM_CALL *ABS* This STN_UNDEF -> *ABS* conversion is done when reading in the relocations, in bfd/elfcode.h:elf_slurp_reloc_table_from_section: 1469 if (ELF_R_SYM (rela.r_info) == 0) 1470 relent->sym_ptr_ptr = bfd_abs_section_ptr->symbol_ptr_ptr; That is, if the index is zero -- should use STN_UNDEF here instead of the zero constant, I'd say? -- then this relocation is marked as being in BFD's absolute section, instead of undefined, as it'd be from the symbol table. This is important, as relocations against undefined symbols will be processed differently from those against absolute values, etc. However, this function elf_slurp_reloc_table_from_section for reading in relocations is not being used in case of LD linking an executable -- the STN_UNDEF symbol remains in BFD's internal undefined section, and linking thus fails: $ "$PWD"_install/bin/*-ld -o bl_ABS bl_ABS.o /scratch/thomas/binutils/HEAD_build_arm-none-eabi_install/bin/arm-none-eabi-ld: warning: cannot find entry symbol _start; defaulting to 0000000000008000 bl_ABS.o:(.text+0x0): undefined reference to `no symbol' I wonder why we need this code duplicated in (at least) two places; why do objdump and ld use different code paths for reading in relocations? Here is a patch to fix this issue for the ld code path. There are no regressions with a --target=arm-none-eabi config. What other testing should be done, as this is against a generic (not target-dependent) file? Index: bfd/elflink.c =================================================================== RCS file: /cvs/src/src/bfd/elflink.c,v retrieving revision 1.378 diff -u -p -r1.378 elflink.c --- bfd/elflink.c 9 Sep 2010 09:55:03 -0000 1.378 +++ bfd/elflink.c 11 Sep 2010 07:32:44 -0000 @@ -9135,6 +9135,13 @@ elf_link_input_bfd (struct elf_final_lin return FALSE; } + /* STN_UNDEF is symbol index zero. During relocations processing it shall + resolve to a symbol value of zero. + + For that to happen, we have to make sure that it will be registered with + the "absolute" section. */ + set_symbol_value (input_bfd, isymbuf, locsymcount, STN_UNDEF, 0); + /* Find local symbol sections and adjust values of symbols in SEC_MERGE sections. Write out those local symbols we know are going into the output file. */ Success with patched BFD: $ "$PWD"_install/bin/*-ld -o bl_ABS bl_ABS.o /scratch/thomas/binutils/HEAD_build_arm-none-eabi_install/bin/arm-none-eabi-ld: warning: cannot find entry symbol _start; defaulting to 0000000000008000 $ "$PWD"_install/bin/*-readelf -r bl_ABS There are no relocations in this file. $ "$PWD"_install/bin/*-objdump -dr bl_ABS bl_ABS: file format elf32-littlearm Disassembly of section .text: 00008000 <__data_start-0x8004>: 8000: eb001ffe bl 10000 <__bss_end__-0x4> This was my first encounter with BFD code, and apart from the time I have now spent on it, I don't know much about how / where it originated, so I'd like your input on this matter: is my patch the correct one, or should this issue be solved differently? Should the two code paths of reading in relocations be unified, or is there perhaps a reason they're different? Regards, Thomas
Attachment:
pgp00000.pgp
Description: PGP signature
Index Nav: | [Date Index] [Subject Index] [Author Index] [Thread Index] | |
---|---|---|
Message Nav: | [Date Prev] [Date Next] | [Thread Prev] [Thread Next] |