Skip to content

clang cannot process intertwined assembly sections #146804

@amsen20

Description

@amsen20

assembly sections are allowed to be nested and intertwined if their associated sections are, for example, the following code:

.section A
.cfi_startproc
.cfi_def_cfa_offset 1
.section B
.cfi_startproc
.cfi_def_cfa_offset 2
.section A
.cfi_def_cfa_offset 3
.cfi_endproc
.section B
.cfi_def_cfa_offset 4
.cfi_endproc

Is equivalent to:

.section A
.cfi_startproc
.cfi_def_cfa_offset 1
.cfi_def_cfa_offset 3
.cfi_endproc
.section B
.cfi_startproc
.cfi_def_cfa_offset 2
.cfi_def_cfa_offset 4
.cfi_endproc

GNU assembler can process this code as intended:

$ as -g a.s -o a.o && objdump --dwarf=frames a.o

a.o:     file format elf64-x86-64

Contents of the .eh_frame section:


00000000 0000000000000018 00000000 CIE
  Version:               1
  Augmentation:          "zR"
  Code alignment factor: 1
  Data alignment factor: -8
  Return address column: 16
  Augmentation data:     1b
  DW_CFA_def_cfa: r7 (rsp) ofs 8
  DW_CFA_offset: r16 (rip) at cfa-8
  DW_CFA_def_cfa_offset: 1
  DW_CFA_def_cfa_offset: 3
  DW_CFA_nop
  DW_CFA_nop

0000001c 0000000000000010 00000020 FDE cie=00000000 pc=0000000000000000..0000000000000000
  DW_CFA_nop
  DW_CFA_nop
  DW_CFA_nop

00000030 0000000000000018 00000000 CIE
  Version:               1
  Augmentation:          "zR"
  Code alignment factor: 1
  Data alignment factor: -8
  Return address column: 16
  Augmentation data:     1b
  DW_CFA_def_cfa: r7 (rsp) ofs 8
  DW_CFA_offset: r16 (rip) at cfa-8
  DW_CFA_def_cfa_offset: 2
  DW_CFA_def_cfa_offset: 4
  DW_CFA_nop
  DW_CFA_nop

0000004c 0000000000000010 00000020 FDE cie=00000030 pc=0000000000000000..0000000000000000
  DW_CFA_nop
  DW_CFA_nop
  DW_CFA_nop

But LLVM just emits an error for it:

$ clang -c -g a.s -o a.o
<unknown>:0: error: invalid CFI advance_loc expression
<unknown>:0: error: invalid CFI advance_loc expression
<unknown>:0: error: Cannot represent a difference across sections
<unknown>:0: error: Cannot represent a difference across sections

This problem does not happen when the sections are intertwined like a stack, for example both of the following codes:

.section A
.cfi_startproc
.cfi_def_cfa_offset 1

.section B
.cfi_startproc
.cfi_def_cfa_offset 2
.cfi_def_cfa_offset 3
.cfi_endproc
.section A

.cfi_def_cfa_offset 4
.cfi_endproc

and

.pushsection A
.cfi_startproc
.cfi_def_cfa_offset 1

.pushsection B
.cfi_startproc
.cfi_def_cfa_offset 2
.cfi_def_cfa_offset 3
.cfi_endproc
.popsection

.cfi_def_cfa_offset 4
.cfi_endproc
.popsection

Are equal in the eye of clang, and the debug info in sections is correctly processed:

$  clang -c -g a.s -o a.o && llvm-objdump --dwarf=frames a.o
a.o:    file format elf64-x86-64

.debug_frame contents:


.eh_frame contents:

00000000 00000014 00000000 CIE
  Format:                DWARF32
  Version:               1
  Augmentation:          "zR"
  Code alignment factor: 1
  Data alignment factor: -8
  Return address column: 16
  Augmentation data:     1B

  DW_CFA_def_cfa: reg7 +8
  DW_CFA_offset: reg16 -8
  DW_CFA_nop:
  DW_CFA_nop:

  CFA=reg7+8: reg16=[CFA-8]

00000018 00000014 0000001c FDE cie=00000000 pc=00000000...00000000
  Format:       DWARF32
  DW_CFA_def_cfa_offset: +1
  DW_CFA_def_cfa_offset: +4
  DW_CFA_nop:
  DW_CFA_nop:
  DW_CFA_nop:

  0x0: CFA=reg7+4: reg16=[CFA-8]

00000030 00000014 00000034 FDE cie=00000000 pc=00000000...00000000
  Format:       DWARF32
  DW_CFA_def_cfa_offset: +2
  DW_CFA_def_cfa_offset: +3
  DW_CFA_nop:
  DW_CFA_nop:
  DW_CFA_nop:

  0x0: CFA=reg7+3: reg16=[CFA-8]

Metadata

Metadata

Assignees

No one assigned

    Labels

    clangClang issues not falling into any other categoryllvm:asmparser

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions