+2015-01-12  Jan Beulich  <jbeulich@suse.com>
+
+       * gas/dw2gencfi.c (cfi_add_label, dot_cfi_label): New.
+       (cfi_pseudo_table): Add "cfi_label".
+       (output_cfi_insn): Handle CFI_label.
+       (select_cie_for_fde): Als terminate CIE when encountering
+       CFI_label.
+       * dw2gencfi.h (cfi_add_label): Declare.
+       (struct cfi_insn_data): New member "sym_name".
+       (CFI_label): New.
+       * read.c (read_symbol_name): Drop "static".
+       * read.h (read_symbol_name): Declare.
+
 2015-01-12  Jan Beulich  <jbeulich@suse.com>
 
        * gas/config/tc-arm.c (do_neon_shl_imm): Check immediate range.
 
   frchain_now->frch_cfi_data->last_address = label;
 }
 
+/* Add a CFI insn to label the current position in the CFI segment.  */
+
+void
+cfi_add_label (const char *name)
+{
+  unsigned int len = strlen (name) + 1;
+  struct cfi_insn_data *insn = alloc_cfi_insn_data ();
+
+  insn->insn = CFI_label;
+  obstack_grow (¬es, name, len);
+  insn->u.sym_name = (char *) obstack_finish (¬es);
+}
+
 /* Add a DW_CFA_offset record to the CFI data.  */
 
 void
 static void dot_cfi_personality (int);
 static void dot_cfi_lsda (int);
 static void dot_cfi_val_encoded_addr (int);
+static void dot_cfi_label (int);
 
 const pseudo_typeS cfi_pseudo_table[] =
   {
     { "cfi_personality", dot_cfi_personality, 0 },
     { "cfi_lsda", dot_cfi_lsda, 0 },
     { "cfi_val_encoded_addr", dot_cfi_val_encoded_addr, 0 },
+    { "cfi_label", dot_cfi_label, 0 },
     { NULL, NULL, 0 }
   };
 
   demand_empty_rest_of_line ();
 }
 
+static void
+dot_cfi_label (int ignored ATTRIBUTE_UNUSED)
+{
+  char *name = read_symbol_name ();
+
+  if (name == NULL)
+    return;
+
+  /* If the last address was not at the current PC, advance to current.  */
+  if (symbol_get_frag (frchain_now->frch_cfi_data->last_address) != frag_now
+      || S_GET_VALUE (frchain_now->frch_cfi_data->last_address)
+        != frag_now_fix ())
+    cfi_add_advance_loc (symbol_temp_new_now ());
+
+  cfi_add_label (name);
+
+  demand_empty_rest_of_line ();
+}
+
 /* By default emit .eh_frame only, not .debug_frame.  */
 #define CFI_EMIT_eh_frame      (1 << 0)
 #define CFI_EMIT_debug_frame   (1 << 1)
       }
       break;
 
+    case CFI_label:
+      colon (insn->u.sym_name);
+      break;
+
     default:
       abort ();
     }
     if (i->insn == DW_CFA_advance_loc
        || i->insn == DW_CFA_remember_state
        || i->insn == CFI_escape
-       || i->insn == CFI_val_encoded_addr)
+       || i->insn == CFI_val_encoded_addr
+       || i->insn == CFI_label)
       break;
 
   cie->last = i;
 
 extern void cfi_end_fde (struct symbol *);
 extern void cfi_set_return_column (unsigned);
 extern void cfi_add_advance_loc (struct symbol *);
+extern void cfi_add_label (const char *);
 
 extern void cfi_add_CFA_offset (unsigned, offsetT);
 extern void cfi_add_CFA_def_cfa (unsigned, offsetT);
       unsigned reg, encoding;
       expressionS exp;
     } ea;
+
+    const char *sym_name;
   } u;
 };
 
 #define CFI_escape             0x103
 #define CFI_signal_frame       0x104
 #define CFI_val_encoded_addr   0x105
+#define CFI_label              0x106
 
 #endif /* DW2GENCFI_H */
 
    If a symbol name could not be read, the routine issues an error
    messages, skips to the end of the line and returns NULL.  */
 
-static char *
+char *
 read_symbol_name (void)
 {
   char * name;
 
 extern void read_a_source_file (char *name);
 extern void read_begin (void);
 extern void read_print_statistics (FILE *);
+extern char *read_symbol_name (void);
 extern int sizeof_leb128 (valueT, int sign);
 extern void stabs_generate_asm_file (void);
 extern void stabs_generate_asm_lineno (void);
 
+2015-01-12  Jan Beulich  <jbeulich@suse.com>
+
+       gas/cfi/cfi-label.d, gas/cfi/cfi-label.s: New.
+       gas/cfi/cfi.exp: Run new tests.
+
 2015-01-12  Jan Beulich  <jbeulich@suse.com>
 
        * gas/arm/neon-addressing-bad.s: Add test for invalid VSHL,
 
--- /dev/null
+#objdump: -tWf
+#name: .cfi_label directive
+
+.*\.o:     file format elf.*
+
+SYMBOL TABLE:
+0*00 l    d  \.text    0*00 \.text
+0*00 l    d  \.data    0*00 \.data
+0*00 l    d  \.bss     0*00 \.bss
+0*00 l     F \.text    0*04 cfilabel
+0*2f l       \.eh_frame        0*00 cfi2
+0*00 l    d  \.eh_frame        0*00 \.eh_frame
+0*2b g       \.eh_frame        0*00 cfi1
+
+
+Contents of the .eh_frame section:
+
+0*00 0*14 0*00 CIE
+  Version:               1
+  Augmentation:          "zR"
+  Code alignment factor: 1
+  Data alignment factor: -[48]
+  Return address column: (8|16)
+  Augmentation data:     1b
+
+  DW_CFA_def_cfa: r.* \([er]sp\) ofs [48]
+  DW_CFA_offset: r.* \([er]ip\) at cfa-[48]
+  DW_CFA_nop
+  DW_CFA_nop
+
+0*18 0*1[8c] 0*1c FDE cie=0*00 pc=0*00..0*04
+  DW_CFA_remember_state
+  DW_CFA_advance_loc: 1 to 0*01
+  DW_CFA_nop
+  DW_CFA_nop
+  DW_CFA_nop
+  DW_CFA_advance_loc: 1 to 0*02
+  DW_CFA_nop
+  DW_CFA_nop
+  DW_CFA_advance_loc: 1 to 0*03
+  DW_CFA_nop
+  DW_CFA_restore_state
+#pass
 
--- /dev/null
+       .text
+cfilabel:
+       .cfi_startproc
+       .cfi_remember_state
+       nop
+       .globl cfi1
+       .cfi_label cfi1
+       .cfi_escape 0, 0, 0
+       nop
+       .cfi_label cfi2
+       .cfi_escape 0, 0
+       nop
+       .cfi_label .Lcfi3
+       .cfi_escape 0
+       .cfi_restore_state
+       ret
+       .cfi_endproc
+       .type cfilabel, STT_FUNC
+       .size cfilabel, . - cfilabel
 
        set ASFLAGS "$old_ASFLAGS"
     }
 
+    if { [is_elf_format] } then {
+       run_dump_test "cfi-label"
+    }
+
     if { [is_pecoff_format] } then {
        run_dump_test "reloc-pe-i386"
     }