+ const char *name;
+
+ if (!seg)
+ name = "";
+ else
+ {
+ const char * dollar;
+ const char * dot;
+
+ name = bfd_get_section_name (stdoutput, seg);
+
+ dollar = strchr (name, '$');
+ dot = strchr (name + 1, '.');
+
+ if (!dollar && !dot)
+ name = "";
+ else if (!dollar)
+ name = dot;
+ else if (!dot)
+ name = dollar;
+ else if (dot < dollar)
+ name = dot;
+ else
+ name = dollar;
+ }
+
+ return concat (base_name, name, NULL);
+}
+
+/* Allocate a dwcfi_seg_list structure. */
+
+static struct dwcfi_seg_list *
+alloc_debugseg_item (segT seg, int subseg, char *name)
+{
+ struct dwcfi_seg_list *r;
+
+ r = (struct dwcfi_seg_list *)
+ xmalloc (sizeof (struct dwcfi_seg_list) + strlen (name));
+ r->seg = seg;
+ r->subseg = subseg;
+ r->seg_name = name;
+ return r;
+}
+
+static segT
+is_now_linkonce_segment (void)
+{
+ if ((bfd_get_section_flags (stdoutput, now_seg)
+ & (SEC_LINK_ONCE | SEC_LINK_DUPLICATES_DISCARD
+ | SEC_LINK_DUPLICATES_ONE_ONLY | SEC_LINK_DUPLICATES_SAME_SIZE
+ | SEC_LINK_DUPLICATES_SAME_CONTENTS)) != 0)
+ return now_seg;
+ return NULL;
+}
+
+/* Generate debug... segment with same linkonce properties
+ of based segment. */
+
+static segT
+make_debug_seg (segT cseg, char *name, int sflags)
+{
+ segT save_seg = now_seg;
+ int save_subseg = now_subseg;
+ segT r;
+ flagword flags;
+
+ r = subseg_new (name, 0);
+
+ /* Check if code segment is marked as linked once. */
+ if (!cseg)
+ flags = 0;
+ else
+ flags = bfd_get_section_flags (stdoutput, cseg)
+ & (SEC_LINK_ONCE | SEC_LINK_DUPLICATES_DISCARD
+ | SEC_LINK_DUPLICATES_ONE_ONLY | SEC_LINK_DUPLICATES_SAME_SIZE
+ | SEC_LINK_DUPLICATES_SAME_CONTENTS);
+
+ /* Add standard section flags. */
+ flags |= sflags;
+
+ /* Apply possibly linked once flags to new generated segment, too. */
+ if (!bfd_set_section_flags (stdoutput, r, flags))
+ as_bad (_("bfd_set_section_flags: %s"),
+ bfd_errmsg (bfd_get_error ()));
+
+ /* Restore to previous segment. */
+ if (save_seg != NULL)
+ subseg_set (save_seg, save_subseg);
+ return r;
+}
+
+static void
+dwcfi_hash_insert (const char *name, struct dwcfi_seg_list *item)
+{
+ const char *error_string;
+
+ if ((error_string = hash_jam (dwcfi_hash, name, (char *) item)))
+ as_fatal (_("Inserting \"%s\" into structure table failed: %s"),
+ name, error_string);
+}
+
+static struct dwcfi_seg_list *
+dwcfi_hash_find (char *name)
+{
+ return (struct dwcfi_seg_list *) hash_find (dwcfi_hash, name);
+}
+
+static struct dwcfi_seg_list *
+dwcfi_hash_find_or_make (segT cseg, const char *base_name, int flags)
+{
+ struct dwcfi_seg_list *item;
+ char *name;
+
+ /* Initialize dwcfi_hash once. */
+ if (!dwcfi_hash)
+ dwcfi_hash = hash_new ();
+
+ name = get_debugseg_name (cseg, base_name);
+
+ item = dwcfi_hash_find (name);
+ if (!item)
+ {
+ item = alloc_debugseg_item (make_debug_seg (cseg, name, flags), 0, name);
+
+ dwcfi_hash_insert (item->seg_name, item);
+ }
+ else
+ free (name);
+
+ return item;
+}
+
+/* ??? Share this with dwarf2cfg.c. */
+#ifndef TC_DWARF2_EMIT_OFFSET
+#define TC_DWARF2_EMIT_OFFSET generic_dwarf2_emit_offset
+
+/* Create an offset to .dwarf2_*. */
+
+static void
+generic_dwarf2_emit_offset (symbolS *symbol, unsigned int size)
+{
+ expressionS exp;
+
+ exp.X_op = O_symbol;
+ exp.X_add_symbol = symbol;
+ exp.X_add_number = 0;
+ emit_expr (&exp, size);
+}
+#endif
+
+struct cfi_escape_data
+{
+ struct cfi_escape_data *next;
+ expressionS exp;