This is the mail archive of the
binutils@sourceware.org
mailing list for the binutils project.
_bfd_elf_parse_eh_frame() should not assume relocation order?
- From: Alexey Neyman <stilor at att dot net>
- To: binutils at sourceware dot org
- Date: Tue, 17 Dec 2013 01:02:03 -0800
- Subject: _bfd_elf_parse_eh_frame() should not assume relocation order?
- Authentication-results: sourceware.org; auth=none
Hi all,
I've stumbled on something that looks like a bug in BFD when reading .eh_frame
sections that results in failure to create .eh_frame_hdr. The code in
_bfd_elf_parse_eh_frame() function in bfd/elf-eh-frame.c assumes the
relocations in cookie->rels are ordered by r_offset field; look at how the
ENSURE_NO_RELOCS, SKIP_RELOCS and GET_RELOC macros are defined, e.g:
/* FIXME: octets_per_byte. */
#define ENSURE_NO_RELOCS(buf) \
REQUIRE (!(cookie->rel < cookie->relend \
&& (cookie->rel->r_offset \
< (bfd_size_type) ((buf) - ehbuf)) \
&& cookie->rel->r_info != 0))
/* FIXME: octets_per_byte. */
#define SKIP_RELOCS(buf) \
while (cookie->rel < cookie->relend \
&& (cookie->rel->r_offset \
< (bfd_size_type) ((buf) - ehbuf))) \
cookie->rel++
/* FIXME: octets_per_byte. */
#define GET_RELOC(buf) \
((cookie->rel < cookie->relend \
&& (cookie->rel->r_offset \
== (bfd_size_type) ((buf) - ehbuf))) \
? cookie->rel : NULL)
The problem is that this assumption (cookie->rels being ordered by r_offset)
may not hold. For example, with the following two assembly files:
--- qq1.s ---
.text
baz: .cfi_startproc; ret; .cfi_endproc
--- qq2.s ---
.section .init,"ax",@progbits
.globl foo; foo: .cfi_startproc; ret; .cfi_endproc
.text;
bar: .cfi_startproc; ret; .cfi_endproc
the following commands:
$ as -o qq1.o qq1.s
$ as -o qq2.o qq2.s
$ ld -r -o qq.o qq1.o qq2.o
$ ld -o qq -e foo qq.o
trigger this error message (tried with the tip of the master branch):
/work/install/bin/ld: error in qq.o(.eh_frame); no .eh_frame_hdr table will be
created.
The problem is that after 'ld -r' linking, the resulting .rela.eh_frame is not
sorted by the r_offset:
$ readelf -r qq.o
Relocation section '.rela.eh_frame' at offset 0x380 contains 3 entries:
Offset Info Type Sym. Value Sym. Name +
Addend
000000000050 000100000002 R_X86_64_PC32 0000000000000000 .init + 0
000000000064 000200000002 R_X86_64_PC32 0000000000000000 .text + 1
000000000020 000200000002 R_X86_64_PC32 0000000000000000 .text + 0
As a result, the code in _bfd_elf_parse_eh_frame() fails at REQUIRE (GET_RELOC
(buf)) [near line 800], because cookie->rel[0] is the first relocation (with
r_offset 0x50) while the buf pointer is at offset 0x20 (i.e., pointed to by
cookie->rel[2]).
Is it a bug in BFD, or am I missing something?
Regards,
Alexey.