--- /dev/null
+#!/bin/sh -e
+## 201-hjl-bfd-ref-addr.dpatch
+##
+## DP: Description: Support DW_FORM_ref_addr in Dwarf 2 reader in linker.
+## DP: Author: H.J. Lu <hongjiu.lu@intel.com>
+## DP: Upstream status: hjl post 2.17.50.0.18, PR ld/3191
+## DP: Original patch: bfd-ref_addr-6.patch
+
+if [ $# -ne 1 ]; then
+ echo >&2 "`basename $0`: script expects -patch|-unpatch as argument"
+ exit 1
+fi
+
+[ -f debian/patches/00patch-opts ] && . debian/patches/00patch-opts
+patch_opts="${patch_opts:--f --no-backup-if-mismatch}"
+
+case "$1" in
+ -patch) patch $patch_opts -p1 < $0;;
+ -unpatch) patch $patch_opts -p1 -R < $0;;
+ *)
+ echo >&2 "`basename $0`: script expects -patch|-unpatch as argument"
+ exit 1;;
+esac
+
+exit 0
+
+2006-09-29 H.J. Lu <hongjiu.lu@intel.com>
+
+ PR ld/3191
+ * dwarf2.c (find_abstract_instance_name): Pass a pointer to
+ attribute instead of offset. For DW_FORM_ref_addr, get the
+ entry at the offset from the .debug_info section.
+ (scan_unit_for_symbols): Updated.
+ (_bfd_dwarf2_find_nearest_line): Adjust debug_info
+ section vma when needed.
+
+@DPATCH@
+diff -urNad binutils-2.18~cvs20070812~/bfd/dwarf2.c binutils-2.18~cvs20070812/bfd/dwarf2.c
+--- binutils-2.18~cvs20070812~/bfd/dwarf2.c 2007-07-26 10:31:03.000000000 +0200
++++ binutils-2.18~cvs20070812/bfd/dwarf2.c 2007-08-12 13:15:54.000000000 +0200
+@@ -1710,16 +1710,30 @@
+ }
+
+ static char *
+-find_abstract_instance_name (struct comp_unit *unit, bfd_uint64_t die_ref)
++find_abstract_instance_name (struct comp_unit *unit,
++ struct attribute *attr_ptr)
+ {
+ bfd *abfd = unit->abfd;
+ bfd_byte *info_ptr;
+ unsigned int abbrev_number, bytes_read, i;
+ struct abbrev_info *abbrev;
++ bfd_uint64_t die_ref = attr_ptr->u.val;
+ struct attribute attr;
+ char *name = 0;
+
+- info_ptr = unit->info_ptr_unit + die_ref;
++ /* DW_FORM_ref_addr can reference an entry in a different CU. It
++ is an offset from the .debug_info section, not the current CU. */
++ if (attr_ptr->form == DW_FORM_ref_addr)
++ {
++ /* FIXME: How to handle DW_FORM_ref_addr references an entry in
++ a different file? */
++ if (!die_ref)
++ abort ();
++
++ info_ptr = unit->stash->sec_info_ptr + die_ref;
++ }
++ else
++ info_ptr = unit->info_ptr_unit + die_ref;
+ abbrev_number = read_unsigned_leb128 (abfd, info_ptr, &bytes_read);
+ info_ptr += bytes_read;
+
+@@ -1745,7 +1759,7 @@
+ name = attr.u.str;
+ break;
+ case DW_AT_specification:
+- name = find_abstract_instance_name (unit, attr.u.val);
++ name = find_abstract_instance_name (unit, &attr);
+ break;
+ case DW_AT_MIPS_linkage_name:
+ name = attr.u.str;
+@@ -1907,7 +1921,7 @@
+ break;
+
+ case DW_AT_abstract_origin:
+- func->name = find_abstract_instance_name (unit, attr.u.val);
++ func->name = find_abstract_instance_name (unit, &attr);
+ break;
+
+ case DW_AT_name:
+@@ -2876,6 +2890,11 @@
+ bfd *debug_bfd;
+ bfd_size_type total_size;
+ asection *msec;
++ bfd_vma last_vma;
++ bfd_size_type size;
++ asection *first_msec;
++ asection **msecs = NULL;
++ unsigned int i, count;
+
+ *pinfo = stash;
+
+@@ -2909,9 +2928,28 @@
+ Read them all in and produce one large stash. We do this in two
+ passes - in the first pass we just accumulate the section sizes.
+ In the second pass we read in the section's contents. The allows
+- us to avoid reallocing the data as we add sections to the stash. */
++ us to avoid reallocing the data as we add sections to the stash.
++
++ We may need to adjust debug_info section vmas since we will
++ concatenate them together. Otherwise relocations may be
++ incorrect. */
++ first_msec = msec;
++ last_vma = 0;
++ count = 0;
+ for (total_size = 0; msec; msec = find_debug_info (debug_bfd, msec))
+- total_size += msec->size;
++ {
++ size = msec->size;
++ if (size == 0)
++ continue;
++
++ total_size += size;
++
++ BFD_ASSERT (msec->vma == 0 && msec->alignment_power == 0);
++
++ msec->vma = last_vma;
++ last_vma += size;
++ count++;
++ }
+
+ stash->info_ptr = bfd_alloc (debug_bfd, total_size);
+ if (stash->info_ptr == NULL)
+@@ -2919,17 +2957,27 @@
+
+ stash->info_ptr_end = stash->info_ptr;
+
+- for (msec = find_debug_info (debug_bfd, NULL);
++ if (count > 1)
++ {
++ count--;
++ msecs = (asection **) bfd_malloc2 (count, sizeof (*msecs));
++ }
++
++ for (i = 0, msec = first_msec;
+ msec;
+ msec = find_debug_info (debug_bfd, msec))
+ {
+- bfd_size_type size;
+ bfd_size_type start;
+
+ size = msec->size;
+ if (size == 0)
+ continue;
+
++ if (i && msecs)
++ msecs [i - 1] = msec;
++
++ i++;
++
+ start = stash->info_ptr_end - stash->info_ptr;
+
+ if ((bfd_simple_get_relocated_section_contents
+@@ -2939,9 +2987,27 @@
+ stash->info_ptr_end = stash->info_ptr + start + size;
+ }
+
++ /* Restore section vma. */
++ if (count)
++ {
++ if (msecs)
++ {
++ for (i = 0; i < count; i++)
++ msecs [i]->vma = 0;
++ free (msecs);
++ }
++ else
++ {
++ for (msec = find_debug_info (debug_bfd, first_msec);
++ msec;
++ msec = find_debug_info (debug_bfd, msec))
++ msec->vma = 0;
++ }
++ }
++
+ BFD_ASSERT (stash->info_ptr_end == stash->info_ptr + total_size);
+
+- stash->sec = find_debug_info (debug_bfd, NULL);
++ stash->sec = first_msec;
+ stash->sec_info_ptr = stash->info_ptr;
+ stash->syms = symbols;
+ stash->bfd = debug_bfd;