Bug 2655 - Incorrrect padding for .eh_frame section
Summary: Incorrrect padding for .eh_frame section
Status: RESOLVED FIXED
Alias: None
Product: binutils
Classification: Unclassified
Component: ld (show other bugs)
Version: unspecified
: P2 normal
Target Milestone: ---
Assignee: unassigned
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2006-05-12 05:12 UTC by H.J. Lu
Modified: 2022-01-17 20:13 UTC (History)
2 users (show)

See Also:
Host:
Target:
Build:
Last reconfirmed:
fweimer: security-


Attachments
A testcase (593 bytes, application/octet-stream)
2006-05-12 05:14 UTC, H.J. Lu
Details

Note You need to log in before you can comment on or make changes to this bug.
Description H.J. Lu 2006-05-12 05:12:01 UTC
_bfd_elf_write_section_eh_frame has

    {
      unsigned int alignment = 1 << sec->alignment_power;
      unsigned int pad = sec->size % alignment;

      /* Don't pad beyond the raw size of the output section. It
         can happen at the last input section.  */
      if (pad
          && ((sec->output_offset + sec->size + pad)
              <= sec->output_section->size))
        {
          bfd_byte *buf;
          unsigned int new_size;

          /* Find the last CIE/FDE.  */
          ent = sec_info->entry + sec_info->count;
          while (--ent != sec_info->entry)
            if (!ent->removed)
              break;

          /* The size of the last CIE/FDE must be at least 4.  */
          if (ent->removed || ent->size < 4)
            abort ();

          pad = alignment - pad;
          buf = contents + ent->new_offset - sec->output_offset;
          new_size = size_of_output_cie_fde (ent, ptr_size);

          /* Pad it with DW_CFA_nop  */
          memset (buf + new_size, 0, pad);
          bfd_put_32 (abfd, new_size + pad - 4, buf);

          sec->size += pad;
        }
    }

It pads the current .eh_frame section to its section alignment. If the next
.eh_frame section has a different alignment, padding will be wrong. In the
case of x86-64, most of .eh_frame sections have 8 byte aligment. But the
last one in crtend.o from gcc has 4 byte alignment. As the result, the
last zero terminator may become the part of the previous FDE due to incorrect
padding.
Comment 1 H.J. Lu 2006-05-12 05:14:45 UTC
Created attachment 1017 [details]
A testcase

For x86-64:

as   -o x.o x.s
as   -o crtend.o crtend.s
ld -o foo x.o crtend.o
readelf -wf foo
The section .eh_frame contains:

00000000 00000014 00000000 CIE
  Version:		 1
  Augmentation: 	 ""
  Code alignment factor: 1
  Data alignment factor: -8
  Return address column: 16

  DW_CFA_def_cfa: r7 ofs 8
  DW_CFA_offset: r16 at cfa-8
  DW_CFA_nop
  DW_CFA_nop
  DW_CFA_nop
  DW_CFA_nop
  DW_CFA_nop
  DW_CFA_nop

00000018 00000020 0000001c FDE cie=00000000 pc=004000b0..004000b0
  DW_CFA_advance_loc: 0 to 004000b0
  DW_CFA_def_cfa_offset: 16
  DW_CFA_offset: r6 at cfa-16
  DW_CFA_advance_loc: 0 to 004000b0
  DW_CFA_def_cfa_reg: r6
  DW_CFA_nop
  DW_CFA_nop
  DW_CFA_nop
  DW_CFA_nop

There is no zero terminator.
Comment 2 H.J. Lu 2006-05-12 21:01:01 UTC
The gcc bug is

http://gcc.gnu.org/bugzilla/show_bug.cgi?id=27576
Comment 3 H.J. Lu 2006-05-24 15:42:00 UTC
Fixed by

http://sourceware.org/ml/binutils/2006-05/msg00242.html