[DWARF] Support for .debug_addr (consumer)

  This patch implements basic support for parsing
  and dumping DWARFv5 .debug_addr section.

llvm-svn: 338447
diff --git a/llvm/test/tools/llvm-dwarfdump/X86/debug_addr.s b/llvm/test/tools/llvm-dwarfdump/X86/debug_addr.s
new file mode 100644
index 0000000..b0ee8be
--- /dev/null
+++ b/llvm/test/tools/llvm-dwarfdump/X86/debug_addr.s
@@ -0,0 +1,38 @@
+# RUN: llvm-mc %s -filetype obj -triple i386-pc-linux -o %t.o
+# RUN: llvm-dwarfdump -debug-addr %t.o | FileCheck %s
+
+# CHECK:          .debug_addr contents
+
+# CHECK-NEXT:     length = 0x0000000c, version = 0x0005, addr_size = 0x04, seg_size = 0x00
+# CHECK-NEXT:     Addrs: [
+# CHECK-NEXT:     0x00000000
+# CHECK-NEXT:     0x00000001
+# CHECK-NEXT:     ]
+# CHECK-NEXT:     length = 0x00000004, version = 0x0005, addr_size = 0x04, seg_size = 0x00
+# CHECK-NOT:      {{.}}
+
+	.section	.debug_abbrev,"",@progbits
+	.byte	1                       # Abbreviation Code
+	.section	.debug_info,"",@progbits
+.Lcu_begin0:
+	.long 8	                      # Length of Unit
+	.short	5                     # DWARF version number
+  .byte 1                       # DWARF unit type
+	.byte	4                       # Address Size (in bytes)
+	.long	.debug_abbrev           # Offset Into Abbrev. Section
+
+  .section  .debug_addr,"",@progbits
+.Ldebug_addr0:
+  .long 12 # unit_length = .short + .byte + .byte + .long + .long
+  .short 5 # version
+  .byte 4  # address_size
+  .byte 0  # segment_selector_size
+  .long 0x00000000
+  .long 0x00000001
+
+  .section  .debug_addr,"",@progbits
+.Ldebug_addr1:
+  .long 4  # unit_length = .short + .byte + .byte
+  .short 5 # version
+  .byte 4  # address_size
+  .byte 0  # segment_selector_size
diff --git a/llvm/test/tools/llvm-dwarfdump/X86/debug_addr_64bit_address.s b/llvm/test/tools/llvm-dwarfdump/X86/debug_addr_64bit_address.s
new file mode 100644
index 0000000..616d726
--- /dev/null
+++ b/llvm/test/tools/llvm-dwarfdump/X86/debug_addr_64bit_address.s
@@ -0,0 +1,29 @@
+# RUN: llvm-mc %s -filetype obj -triple x86_64-pc-linux -o %t.o
+# RUN: llvm-dwarfdump -debug-addr %t.o | FileCheck %s
+
+# CHECK:          .debug_addr contents
+# CHECK-NEXT:     length = 0x00000014, version = 0x0005, addr_size = 0x08, seg_size = 0x00
+# CHECK-NEXT:     Addrs: [
+# CHECK-NEXT:     0x0000000100000000
+# CHECK-NEXT:     0x0000000100000001
+# CHECK-NEXT:     ]
+# CHECK-NOT:      {{.}}
+
+	.section	.debug_abbrev,"",@progbits
+	.byte	1                       # Abbreviation Code
+	.section	.debug_info,"",@progbits
+.Lcu_begin0:
+	.long 8	                      # Length of Unit
+	.short	5                     # DWARF version number
+  .byte 1                       # DWARF unit type
+	.byte	8                       # Address Size (in bytes)
+	.long	.debug_abbrev           # Offset Into Abbrev. Section
+
+  .section  .debug_addr,"",@progbits
+.Ldebug_addr0:
+  .long 20 # unit_length = .short + .byte + .byte + .quad + .quad
+  .short 5 # version
+  .byte 8  # address_size
+  .byte 0  # segment_selector_size
+  .quad 0x0000000100000000
+  .quad 0x0000000100000001
diff --git a/llvm/test/tools/llvm-dwarfdump/X86/debug_addr_absent.s b/llvm/test/tools/llvm-dwarfdump/X86/debug_addr_absent.s
new file mode 100644
index 0000000..1965fef
--- /dev/null
+++ b/llvm/test/tools/llvm-dwarfdump/X86/debug_addr_absent.s
@@ -0,0 +1,4 @@
+# RUN: llvm-mc %s -filetype obj -triple i386-pc-linux -o - | \
+# RUN: llvm-dwarfdump -debug-addr - 2>&1 | FileCheck %s
+# CHECK: .debug_addr contents:
+# CHECK-NOT: {{.}}
diff --git a/llvm/test/tools/llvm-dwarfdump/X86/debug_addr_address_size_mismatch.s b/llvm/test/tools/llvm-dwarfdump/X86/debug_addr_address_size_mismatch.s
new file mode 100644
index 0000000..49e694a
--- /dev/null
+++ b/llvm/test/tools/llvm-dwarfdump/X86/debug_addr_address_size_mismatch.s
@@ -0,0 +1,42 @@
+# RUN: llvm-mc %s -filetype obj -triple i386-pc-linux -o - | \
+# RUN: llvm-dwarfdump -debug-addr - 2> %t.err | FileCheck %s
+# RUN: FileCheck %s -input-file %t.err -check-prefix=ERR
+
+# ERR: .debug_addr table at offset 0x0 has address size 8 which is different from CU address size 4
+# ERR-NOT: {{.}}
+
+# CHECK: .debug_addr contents
+# CHECK-NEXT:     length = 0x0000000c, version = 0x0005, addr_size = 0x04, seg_size = 0x00
+# CHECK-NEXT:     Addrs: [
+# CHECK-NEXT:     0x00000000
+# CHECK-NEXT:     0x00000001
+# CHECK-NEXT:     ]
+# CHECK-NOT:      {{.}}
+
+	.section	.debug_abbrev,"",@progbits
+	.byte	1                       # Abbreviation Code
+	.section	.debug_info,"",@progbits
+.Lcu_begin0:
+	.long 8	                      # Length of Unit
+	.short	5                     # DWARF version number
+  .byte 1                       # DWARF unit type
+	.byte	4                       # Address Size (in bytes)
+	.long	.debug_abbrev           # Offset Into Abbrev. Section
+
+	.section	.debug_addr,"",@progbits
+.Ldebug_addr0:
+  .long 12 # unit_length = .short + .byte + .byte + .long + .long
+  .short 5 # version
+  .byte 8  # address_size
+  .byte 0  # segment_selector_size
+  .long 0x00000000
+  .long 0x00000001
+
+	.section	.debug_addr,"",@progbits
+.Ldebug_addr1:
+  .long 12 # unit_length = .short + .byte + .byte + .long + .long
+  .short 5 # version
+  .byte 4  # address_size
+  .byte 0  # segment_selector_size
+  .long 0x00000000
+  .long 0x00000001
diff --git a/llvm/test/tools/llvm-dwarfdump/X86/debug_addr_address_size_not_multiple.s b/llvm/test/tools/llvm-dwarfdump/X86/debug_addr_address_size_not_multiple.s
new file mode 100644
index 0000000..e8835e0
--- /dev/null
+++ b/llvm/test/tools/llvm-dwarfdump/X86/debug_addr_address_size_not_multiple.s
@@ -0,0 +1,18 @@
+# RUN: llvm-mc %s -filetype obj -triple i386-pc-linux -o - | \
+# RUN: llvm-dwarfdump -debug-addr - 2> %t.err | FileCheck %s
+# RUN: FileCheck %s -input-file %t.err -check-prefix=ERR
+
+# CHECK: .debug_addr contents:
+# CHECK-NOT: {{.}}
+# ERR: .debug_addr table at offset 0x0 contains data of size 7 which is not a multiple of addr size 4
+# ERR-NOT: {{.}}
+
+# data size is not multiple of address_size
+  .section  .debug_addr,"",@progbits
+.Ldebug_addr0:
+  .long 11 # unit_length = .short + .byte + .byte + .long + .long - 1
+  .short 5 # version
+  .byte 4  # address_size
+  .byte 0  # segment_selector_size
+  .long 0x00000000
+  .long 0x00000001
diff --git a/llvm/test/tools/llvm-dwarfdump/X86/debug_addr_dwarf4.s b/llvm/test/tools/llvm-dwarfdump/X86/debug_addr_dwarf4.s
new file mode 100644
index 0000000..57e9dd3
--- /dev/null
+++ b/llvm/test/tools/llvm-dwarfdump/X86/debug_addr_dwarf4.s
@@ -0,0 +1,20 @@
+# RUN: llvm-mc %s -filetype obj -triple i386-pc-linux -o %t.o
+# RUN: llvm-dwarfdump --debug-addr %t.o | FileCheck %s
+
+# CHECK: .debug_addr contents
+# CHECK-NEXT:     length = 0x00000000, version = 0x0004, addr_size = 0x04, seg_size = 0x00
+# CHECK-NEXT:     Addrs: [
+# CHECK-NEXT:     0x00000000
+# CHECK-NEXT:     0x00000001
+
+	.section	.debug_abbrev,"",@progbits
+	.byte	1                       # Abbreviation Code
+	.section	.debug_info,"",@progbits
+.Lcu_begin0:
+	.long 7	                      # Length of Unit
+	.short	4                     # DWARF version number
+	.long	.debug_abbrev           # Offset Into Abbrev. Section
+	.byte	4                       # Address Size (in bytes)
+	.section	.debug_addr,"",@progbits
+  .long 0x00000000
+  .long 0x00000001
diff --git a/llvm/test/tools/llvm-dwarfdump/X86/debug_addr_dwarf64.s b/llvm/test/tools/llvm-dwarfdump/X86/debug_addr_dwarf64.s
new file mode 100644
index 0000000..bed4195
--- /dev/null
+++ b/llvm/test/tools/llvm-dwarfdump/X86/debug_addr_dwarf64.s
@@ -0,0 +1,19 @@
+# RUN: llvm-mc %s -filetype obj -triple i386-pc-linux -o - | \
+# RUN: llvm-dwarfdump -debug-addr - 2> %t.err | FileCheck %s
+# RUN: FileCheck %s -input-file %t.err -check-prefix=ERR
+
+# CHECK: .debug_addr contents:
+# CHECK-NOT: {{.}}
+# ERR: DWARF64 is not supported in .debug_addr at offset 0x0
+# ERR-NOT: {{.}}
+
+# DWARF64 table
+  .section  .debug_addr,"",@progbits
+.Ldebug_addr0:
+  .long 0xffffffff # unit_length DWARF64 mark
+  .quad 12         # unit_length
+  .short 5         # version
+  .byte 3          # address_size
+  .byte 0          # segment_selector_size
+  .long 0x00000000
+  .long 0x00000001
diff --git a/llvm/test/tools/llvm-dwarfdump/X86/debug_addr_empty.s b/llvm/test/tools/llvm-dwarfdump/X86/debug_addr_empty.s
new file mode 100644
index 0000000..e80cf8f
--- /dev/null
+++ b/llvm/test/tools/llvm-dwarfdump/X86/debug_addr_empty.s
@@ -0,0 +1,7 @@
+# RUN: llvm-mc %s -filetype obj -triple i386-pc-linux -o - | \
+# RUN: llvm-dwarfdump -debug-addr - | FileCheck %s
+# CHECK: .debug_addr contents:
+# CHECK-NOT: Addr
+# CHECK-NOT: error:
+
+.section .debug_addr,"",@progbits
diff --git a/llvm/test/tools/llvm-dwarfdump/X86/debug_addr_invalid_addr_size.s b/llvm/test/tools/llvm-dwarfdump/X86/debug_addr_invalid_addr_size.s
new file mode 100644
index 0000000..1ba1afe
--- /dev/null
+++ b/llvm/test/tools/llvm-dwarfdump/X86/debug_addr_invalid_addr_size.s
@@ -0,0 +1,18 @@
+# RUN: llvm-mc %s -filetype obj -triple i386-pc-linux -o - | \
+# RUN: llvm-dwarfdump -debug-addr - 2> %t.err | FileCheck %s
+# RUN: FileCheck %s -input-file %t.err -check-prefix=ERR
+
+# CHECK: .debug_addr contents:
+# CHECK-NOT: {{.}}
+# ERR: unsupported address size 3
+# ERR-NOT: {{.}}
+
+# invalid addr size
+  .section  .debug_addr,"",@progbits
+.Ldebug_addr0:
+  .long 12 # unit_length = .short + .byte + .byte + .long + .long
+  .short 5 # version
+  .byte 3  # address_size
+  .byte 0  # segment_selector_size
+  .long 0x00000000
+  .long 0x00000001
diff --git a/llvm/test/tools/llvm-dwarfdump/X86/debug_addr_segment_selector.s b/llvm/test/tools/llvm-dwarfdump/X86/debug_addr_segment_selector.s
new file mode 100644
index 0000000..21f0322
--- /dev/null
+++ b/llvm/test/tools/llvm-dwarfdump/X86/debug_addr_segment_selector.s
@@ -0,0 +1,17 @@
+# RUN: llvm-mc %s -filetype obj -triple i386-pc-linux -o - | \
+# RUN: llvm-dwarfdump -debug-addr - 2> %t.err | FileCheck %s
+# RUN: FileCheck %s -input-file %t.err -check-prefix=ERR
+
+# CHECK: .debug_addr contents:
+# CHECK-NOT: {{.}}
+# ERR: .debug_addr table at offset 0x0 has unsupported segment selector size 1
+# ERR-NOT: {{.}}
+
+# non-zero segment_selector_size
+# TODO: make this valid
+  .section  .debug_addr,"",@progbits
+.Ldebug_addr0:
+  .long 4  # unit_length = .short + .byte + .byte
+  .short 5 # version
+  .byte 4  # address_size
+  .byte 1  # segment_selector_size
diff --git a/llvm/test/tools/llvm-dwarfdump/X86/debug_addr_small_length_field.s b/llvm/test/tools/llvm-dwarfdump/X86/debug_addr_small_length_field.s
new file mode 100644
index 0000000..cbecb98
--- /dev/null
+++ b/llvm/test/tools/llvm-dwarfdump/X86/debug_addr_small_length_field.s
@@ -0,0 +1,18 @@
+# RUN: llvm-mc %s -filetype obj -triple i386-pc-linux -o - | \
+# RUN: llvm-dwarfdump -debug-addr - 2> %t.err | FileCheck %s
+# RUN: FileCheck %s -input-file %t.err -check-prefix=ERR
+
+# CHECK: .debug_addr contents:
+# CHECK-NOT: {{.}}
+# ERR: .debug_addr table at offset 0x0 has too small length (0x5) to contain a complete header
+# ERR-NOT: {{.}}
+
+# too small length value
+  .section  .debug_addr,"",@progbits
+.Ldebug_addr0:
+  .long 1  # unit_length
+  .short 5 # version
+  .byte 4  # address_size
+  .byte 0  # segment_selector_size
+  .long 0x00000000
+  .long 0x00000001
diff --git a/llvm/test/tools/llvm-dwarfdump/X86/debug_addr_too_small_for_length_field.s b/llvm/test/tools/llvm-dwarfdump/X86/debug_addr_too_small_for_length_field.s
new file mode 100644
index 0000000..c26bfcb
--- /dev/null
+++ b/llvm/test/tools/llvm-dwarfdump/X86/debug_addr_too_small_for_length_field.s
@@ -0,0 +1,13 @@
+# RUN: llvm-mc %s -filetype obj -triple i386-pc-linux -o - | \
+# RUN: llvm-dwarfdump -debug-addr - 2> %t.err | FileCheck %s
+# RUN: FileCheck %s -input-file %t.err -check-prefix=ERR
+
+# CHECK: .debug_addr contents:
+# CHECK-NOT: {{.}}
+# ERR: section is not large enough to contain a .debug_addr table length at offset 0x0
+# ERR-NOT: {{.}}
+
+# too small section to contain length field
+  .section  .debug_addr,"",@progbits
+.Ldebug_addr0:
+  .short 1 # unit_length
diff --git a/llvm/test/tools/llvm-dwarfdump/X86/debug_addr_too_small_for_section.s b/llvm/test/tools/llvm-dwarfdump/X86/debug_addr_too_small_for_section.s
new file mode 100644
index 0000000..facffee
--- /dev/null
+++ b/llvm/test/tools/llvm-dwarfdump/X86/debug_addr_too_small_for_section.s
@@ -0,0 +1,16 @@
+# RUN: llvm-mc %s -filetype obj -triple i386-pc-linux -o - | \
+# RUN: llvm-dwarfdump -debug-addr - 2> %t.err | FileCheck %s
+# RUN: FileCheck %s -input-file %t.err -check-prefix=ERR
+
+# CHECK: .debug_addr contents:
+# CHECK-NOT: {{.}}
+# ERR: section is not large enough to contain a .debug_addr table of length 0x10 at offset 0x0
+# ERR-NOT: {{.}}
+
+# too small section to contain section of given length
+  .section  .debug_addr,"",@progbits
+.Ldebug_addr0:
+  .long 12 # unit_length
+  .short 5 # version
+  .byte 4  # address_size
+  .byte 0  # segment_selector_size
diff --git a/llvm/test/tools/llvm-dwarfdump/X86/debug_addr_unsupported_version.s b/llvm/test/tools/llvm-dwarfdump/X86/debug_addr_unsupported_version.s
new file mode 100644
index 0000000..f30dd8f
--- /dev/null
+++ b/llvm/test/tools/llvm-dwarfdump/X86/debug_addr_unsupported_version.s
@@ -0,0 +1,42 @@
+# RUN: llvm-mc %s -filetype obj -triple i386-pc-linux -o - | \
+# RUN: llvm-dwarfdump -debug-addr - 2> %t.err | FileCheck %s
+# RUN: FileCheck %s -input-file %t.err -check-prefix=ERR
+
+# ERR: version 6 of .debug_addr section at offset 0x0 is not supported
+# ERR-NOT: {{.}}
+
+# CHECK: .debug_addr contents
+# CHECK-NEXT:     length = 0x0000000c, version = 0x0005, addr_size = 0x04, seg_size = 0x00
+# CHECK-NEXT:     Addrs: [
+# CHECK-NEXT:     0x00000002
+# CHECK-NEXT:     0x00000003
+# CHECK-NEXT:     ]
+# CHECK-NOT:      {{.}}
+
+	.section	.debug_abbrev,"",@progbits
+	.byte	1                       # Abbreviation Code
+	.section	.debug_info,"",@progbits
+.Lcu_begin0:
+	.long 8	                      # Length of Unit
+	.short	5                     # DWARF version number
+  .byte 1                       # DWARF unit type
+	.byte	4                       # Address Size (in bytes)
+	.long	.debug_abbrev           # Offset Into Abbrev. Section
+
+	.section	.debug_addr,"",@progbits
+.Ldebug_addr0:
+  .long 12 # unit_length = .short + .byte + .byte + .long + .long
+  .short 6 # version
+  .byte 4  # address_size
+  .byte 0  # segment_selector_size
+  .long 0x00000000
+  .long 0x00000001
+
+	.section	.debug_addr,"",@progbits
+.Ldebug_addr1:
+  .long 12 # unit_length = .short + .byte + .byte + .long + .long
+  .short 5 # version
+  .byte 4  # address_size
+  .byte 0  # segment_selector_size
+  .long 0x00000002
+  .long 0x00000003
diff --git a/llvm/test/tools/llvm-dwarfdump/X86/debug_addr_version_mismatch.s b/llvm/test/tools/llvm-dwarfdump/X86/debug_addr_version_mismatch.s
new file mode 100644
index 0000000..e349f33
--- /dev/null
+++ b/llvm/test/tools/llvm-dwarfdump/X86/debug_addr_version_mismatch.s
@@ -0,0 +1,42 @@
+# RUN: llvm-mc %s -filetype obj -triple i386-pc-linux -o - | \
+# RUN: llvm-dwarfdump -debug-addr - 2> %t.err | FileCheck %s
+# RUN: FileCheck %s -input-file %t.err -check-prefix=ERR
+
+# ERR: .debug_addr table at offset 0x0 has version 4 which is different from the version suggested by the DWARF unit header: 5
+# ERR-NOT: {{.}}
+
+# CHECK: .debug_addr contents
+# CHECK-NEXT:     length = 0x0000000c, version = 0x0005, addr_size = 0x04, seg_size = 0x00
+# CHECK-NEXT:     Addrs: [
+# CHECK-NEXT:     0x00000000
+# CHECK-NEXT:     0x00000001
+# CHECK-NEXT:     ]
+# CHECK-NOT:      {{.}}
+
+	.section	.debug_abbrev,"",@progbits
+	.byte	1                       # Abbreviation Code
+	.section	.debug_info,"",@progbits
+.Lcu_begin0:
+	.long 8	                      # Length of Unit
+	.short	5                     # DWARF version number
+  .byte 1                       # DWARF unit type
+	.byte	4                       # Address Size (in bytes)
+	.long	.debug_abbrev           # Offset Into Abbrev. Section
+
+	.section	.debug_addr,"",@progbits
+.Ldebug_addr0:
+  .long 12 # unit_length = .short + .byte + .byte + .long + .long
+  .short 4 # version
+  .byte 4  # address_size
+  .byte 0  # segment_selector_size
+  .long 0x00000000
+  .long 0x00000001
+
+	.section	.debug_addr,"",@progbits
+.Ldebug_addr1:
+  .long 12 # unit_length = .short + .byte + .byte + .long + .long
+  .short 5 # version
+  .byte 4  # address_size
+  .byte 0  # segment_selector_size
+  .long 0x00000000
+  .long 0x00000001