github.com/dannin/go@v0.0.0-20161031215817-d35dfd405eaa/src/debug/elf/file_test.go (about)

     1  // Copyright 2009 The Go Authors. All rights reserved.
     2  // Use of this source code is governed by a BSD-style
     3  // license that can be found in the LICENSE file.
     4  
     5  package elf
     6  
     7  import (
     8  	"bytes"
     9  	"compress/gzip"
    10  	"debug/dwarf"
    11  	"encoding/binary"
    12  	"io"
    13  	"math/rand"
    14  	"net"
    15  	"os"
    16  	"path"
    17  	"reflect"
    18  	"runtime"
    19  	"testing"
    20  )
    21  
    22  type fileTest struct {
    23  	file     string
    24  	hdr      FileHeader
    25  	sections []SectionHeader
    26  	progs    []ProgHeader
    27  	needed   []string
    28  }
    29  
    30  var fileTests = []fileTest{
    31  	{
    32  		"testdata/gcc-386-freebsd-exec",
    33  		FileHeader{ELFCLASS32, ELFDATA2LSB, EV_CURRENT, ELFOSABI_FREEBSD, 0, binary.LittleEndian, ET_EXEC, EM_386, 0x80483cc},
    34  		[]SectionHeader{
    35  			{"", SHT_NULL, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0},
    36  			{".interp", SHT_PROGBITS, SHF_ALLOC, 0x80480d4, 0xd4, 0x15, 0x0, 0x0, 0x1, 0x0, 0x15},
    37  			{".hash", SHT_HASH, SHF_ALLOC, 0x80480ec, 0xec, 0x90, 0x3, 0x0, 0x4, 0x4, 0x90},
    38  			{".dynsym", SHT_DYNSYM, SHF_ALLOC, 0x804817c, 0x17c, 0x110, 0x4, 0x1, 0x4, 0x10, 0x110},
    39  			{".dynstr", SHT_STRTAB, SHF_ALLOC, 0x804828c, 0x28c, 0xbb, 0x0, 0x0, 0x1, 0x0, 0xbb},
    40  			{".rel.plt", SHT_REL, SHF_ALLOC, 0x8048348, 0x348, 0x20, 0x3, 0x7, 0x4, 0x8, 0x20},
    41  			{".init", SHT_PROGBITS, SHF_ALLOC + SHF_EXECINSTR, 0x8048368, 0x368, 0x11, 0x0, 0x0, 0x4, 0x0, 0x11},
    42  			{".plt", SHT_PROGBITS, SHF_ALLOC + SHF_EXECINSTR, 0x804837c, 0x37c, 0x50, 0x0, 0x0, 0x4, 0x4, 0x50},
    43  			{".text", SHT_PROGBITS, SHF_ALLOC + SHF_EXECINSTR, 0x80483cc, 0x3cc, 0x180, 0x0, 0x0, 0x4, 0x0, 0x180},
    44  			{".fini", SHT_PROGBITS, SHF_ALLOC + SHF_EXECINSTR, 0x804854c, 0x54c, 0xc, 0x0, 0x0, 0x4, 0x0, 0xc},
    45  			{".rodata", SHT_PROGBITS, SHF_ALLOC, 0x8048558, 0x558, 0xa3, 0x0, 0x0, 0x1, 0x0, 0xa3},
    46  			{".data", SHT_PROGBITS, SHF_WRITE + SHF_ALLOC, 0x80495fc, 0x5fc, 0xc, 0x0, 0x0, 0x4, 0x0, 0xc},
    47  			{".eh_frame", SHT_PROGBITS, SHF_ALLOC, 0x8049608, 0x608, 0x4, 0x0, 0x0, 0x4, 0x0, 0x4},
    48  			{".dynamic", SHT_DYNAMIC, SHF_WRITE + SHF_ALLOC, 0x804960c, 0x60c, 0x98, 0x4, 0x0, 0x4, 0x8, 0x98},
    49  			{".ctors", SHT_PROGBITS, SHF_WRITE + SHF_ALLOC, 0x80496a4, 0x6a4, 0x8, 0x0, 0x0, 0x4, 0x0, 0x8},
    50  			{".dtors", SHT_PROGBITS, SHF_WRITE + SHF_ALLOC, 0x80496ac, 0x6ac, 0x8, 0x0, 0x0, 0x4, 0x0, 0x8},
    51  			{".jcr", SHT_PROGBITS, SHF_WRITE + SHF_ALLOC, 0x80496b4, 0x6b4, 0x4, 0x0, 0x0, 0x4, 0x0, 0x4},
    52  			{".got", SHT_PROGBITS, SHF_WRITE + SHF_ALLOC, 0x80496b8, 0x6b8, 0x1c, 0x0, 0x0, 0x4, 0x4, 0x1c},
    53  			{".bss", SHT_NOBITS, SHF_WRITE + SHF_ALLOC, 0x80496d4, 0x6d4, 0x20, 0x0, 0x0, 0x4, 0x0, 0x20},
    54  			{".comment", SHT_PROGBITS, 0x0, 0x0, 0x6d4, 0x12d, 0x0, 0x0, 0x1, 0x0, 0x12d},
    55  			{".debug_aranges", SHT_PROGBITS, 0x0, 0x0, 0x801, 0x20, 0x0, 0x0, 0x1, 0x0, 0x20},
    56  			{".debug_pubnames", SHT_PROGBITS, 0x0, 0x0, 0x821, 0x1b, 0x0, 0x0, 0x1, 0x0, 0x1b},
    57  			{".debug_info", SHT_PROGBITS, 0x0, 0x0, 0x83c, 0x11d, 0x0, 0x0, 0x1, 0x0, 0x11d},
    58  			{".debug_abbrev", SHT_PROGBITS, 0x0, 0x0, 0x959, 0x41, 0x0, 0x0, 0x1, 0x0, 0x41},
    59  			{".debug_line", SHT_PROGBITS, 0x0, 0x0, 0x99a, 0x35, 0x0, 0x0, 0x1, 0x0, 0x35},
    60  			{".debug_frame", SHT_PROGBITS, 0x0, 0x0, 0x9d0, 0x30, 0x0, 0x0, 0x4, 0x0, 0x30},
    61  			{".debug_str", SHT_PROGBITS, 0x0, 0x0, 0xa00, 0xd, 0x0, 0x0, 0x1, 0x0, 0xd},
    62  			{".shstrtab", SHT_STRTAB, 0x0, 0x0, 0xa0d, 0xf8, 0x0, 0x0, 0x1, 0x0, 0xf8},
    63  			{".symtab", SHT_SYMTAB, 0x0, 0x0, 0xfb8, 0x4b0, 0x1d, 0x38, 0x4, 0x10, 0x4b0},
    64  			{".strtab", SHT_STRTAB, 0x0, 0x0, 0x1468, 0x206, 0x0, 0x0, 0x1, 0x0, 0x206},
    65  		},
    66  		[]ProgHeader{
    67  			{PT_PHDR, PF_R + PF_X, 0x34, 0x8048034, 0x8048034, 0xa0, 0xa0, 0x4},
    68  			{PT_INTERP, PF_R, 0xd4, 0x80480d4, 0x80480d4, 0x15, 0x15, 0x1},
    69  			{PT_LOAD, PF_R + PF_X, 0x0, 0x8048000, 0x8048000, 0x5fb, 0x5fb, 0x1000},
    70  			{PT_LOAD, PF_R + PF_W, 0x5fc, 0x80495fc, 0x80495fc, 0xd8, 0xf8, 0x1000},
    71  			{PT_DYNAMIC, PF_R + PF_W, 0x60c, 0x804960c, 0x804960c, 0x98, 0x98, 0x4},
    72  		},
    73  		[]string{"libc.so.6"},
    74  	},
    75  	{
    76  		"testdata/gcc-amd64-linux-exec",
    77  		FileHeader{ELFCLASS64, ELFDATA2LSB, EV_CURRENT, ELFOSABI_NONE, 0, binary.LittleEndian, ET_EXEC, EM_X86_64, 0x4003e0},
    78  		[]SectionHeader{
    79  			{"", SHT_NULL, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0},
    80  			{".interp", SHT_PROGBITS, SHF_ALLOC, 0x400200, 0x200, 0x1c, 0x0, 0x0, 0x1, 0x0, 0x1c},
    81  			{".note.ABI-tag", SHT_NOTE, SHF_ALLOC, 0x40021c, 0x21c, 0x20, 0x0, 0x0, 0x4, 0x0, 0x20},
    82  			{".hash", SHT_HASH, SHF_ALLOC, 0x400240, 0x240, 0x24, 0x5, 0x0, 0x8, 0x4, 0x24},
    83  			{".gnu.hash", SHT_LOOS + 268435446, SHF_ALLOC, 0x400268, 0x268, 0x1c, 0x5, 0x0, 0x8, 0x0, 0x1c},
    84  			{".dynsym", SHT_DYNSYM, SHF_ALLOC, 0x400288, 0x288, 0x60, 0x6, 0x1, 0x8, 0x18, 0x60},
    85  			{".dynstr", SHT_STRTAB, SHF_ALLOC, 0x4002e8, 0x2e8, 0x3d, 0x0, 0x0, 0x1, 0x0, 0x3d},
    86  			{".gnu.version", SHT_HIOS, SHF_ALLOC, 0x400326, 0x326, 0x8, 0x5, 0x0, 0x2, 0x2, 0x8},
    87  			{".gnu.version_r", SHT_LOOS + 268435454, SHF_ALLOC, 0x400330, 0x330, 0x20, 0x6, 0x1, 0x8, 0x0, 0x20},
    88  			{".rela.dyn", SHT_RELA, SHF_ALLOC, 0x400350, 0x350, 0x18, 0x5, 0x0, 0x8, 0x18, 0x18},
    89  			{".rela.plt", SHT_RELA, SHF_ALLOC, 0x400368, 0x368, 0x30, 0x5, 0xc, 0x8, 0x18, 0x30},
    90  			{".init", SHT_PROGBITS, SHF_ALLOC + SHF_EXECINSTR, 0x400398, 0x398, 0x18, 0x0, 0x0, 0x4, 0x0, 0x18},
    91  			{".plt", SHT_PROGBITS, SHF_ALLOC + SHF_EXECINSTR, 0x4003b0, 0x3b0, 0x30, 0x0, 0x0, 0x4, 0x10, 0x30},
    92  			{".text", SHT_PROGBITS, SHF_ALLOC + SHF_EXECINSTR, 0x4003e0, 0x3e0, 0x1b4, 0x0, 0x0, 0x10, 0x0, 0x1b4},
    93  			{".fini", SHT_PROGBITS, SHF_ALLOC + SHF_EXECINSTR, 0x400594, 0x594, 0xe, 0x0, 0x0, 0x4, 0x0, 0xe},
    94  			{".rodata", SHT_PROGBITS, SHF_ALLOC, 0x4005a4, 0x5a4, 0x11, 0x0, 0x0, 0x4, 0x0, 0x11},
    95  			{".eh_frame_hdr", SHT_PROGBITS, SHF_ALLOC, 0x4005b8, 0x5b8, 0x24, 0x0, 0x0, 0x4, 0x0, 0x24},
    96  			{".eh_frame", SHT_PROGBITS, SHF_ALLOC, 0x4005e0, 0x5e0, 0xa4, 0x0, 0x0, 0x8, 0x0, 0xa4},
    97  			{".ctors", SHT_PROGBITS, SHF_WRITE + SHF_ALLOC, 0x600688, 0x688, 0x10, 0x0, 0x0, 0x8, 0x0, 0x10},
    98  			{".dtors", SHT_PROGBITS, SHF_WRITE + SHF_ALLOC, 0x600698, 0x698, 0x10, 0x0, 0x0, 0x8, 0x0, 0x10},
    99  			{".jcr", SHT_PROGBITS, SHF_WRITE + SHF_ALLOC, 0x6006a8, 0x6a8, 0x8, 0x0, 0x0, 0x8, 0x0, 0x8},
   100  			{".dynamic", SHT_DYNAMIC, SHF_WRITE + SHF_ALLOC, 0x6006b0, 0x6b0, 0x1a0, 0x6, 0x0, 0x8, 0x10, 0x1a0},
   101  			{".got", SHT_PROGBITS, SHF_WRITE + SHF_ALLOC, 0x600850, 0x850, 0x8, 0x0, 0x0, 0x8, 0x8, 0x8},
   102  			{".got.plt", SHT_PROGBITS, SHF_WRITE + SHF_ALLOC, 0x600858, 0x858, 0x28, 0x0, 0x0, 0x8, 0x8, 0x28},
   103  			{".data", SHT_PROGBITS, SHF_WRITE + SHF_ALLOC, 0x600880, 0x880, 0x18, 0x0, 0x0, 0x8, 0x0, 0x18},
   104  			{".bss", SHT_NOBITS, SHF_WRITE + SHF_ALLOC, 0x600898, 0x898, 0x8, 0x0, 0x0, 0x4, 0x0, 0x8},
   105  			{".comment", SHT_PROGBITS, 0x0, 0x0, 0x898, 0x126, 0x0, 0x0, 0x1, 0x0, 0x126},
   106  			{".debug_aranges", SHT_PROGBITS, 0x0, 0x0, 0x9c0, 0x90, 0x0, 0x0, 0x10, 0x0, 0x90},
   107  			{".debug_pubnames", SHT_PROGBITS, 0x0, 0x0, 0xa50, 0x25, 0x0, 0x0, 0x1, 0x0, 0x25},
   108  			{".debug_info", SHT_PROGBITS, 0x0, 0x0, 0xa75, 0x1a7, 0x0, 0x0, 0x1, 0x0, 0x1a7},
   109  			{".debug_abbrev", SHT_PROGBITS, 0x0, 0x0, 0xc1c, 0x6f, 0x0, 0x0, 0x1, 0x0, 0x6f},
   110  			{".debug_line", SHT_PROGBITS, 0x0, 0x0, 0xc8b, 0x13f, 0x0, 0x0, 0x1, 0x0, 0x13f},
   111  			{".debug_str", SHT_PROGBITS, SHF_MERGE + SHF_STRINGS, 0x0, 0xdca, 0xb1, 0x0, 0x0, 0x1, 0x1, 0xb1},
   112  			{".debug_ranges", SHT_PROGBITS, 0x0, 0x0, 0xe80, 0x90, 0x0, 0x0, 0x10, 0x0, 0x90},
   113  			{".shstrtab", SHT_STRTAB, 0x0, 0x0, 0xf10, 0x149, 0x0, 0x0, 0x1, 0x0, 0x149},
   114  			{".symtab", SHT_SYMTAB, 0x0, 0x0, 0x19a0, 0x6f0, 0x24, 0x39, 0x8, 0x18, 0x6f0},
   115  			{".strtab", SHT_STRTAB, 0x0, 0x0, 0x2090, 0x1fc, 0x0, 0x0, 0x1, 0x0, 0x1fc},
   116  		},
   117  		[]ProgHeader{
   118  			{PT_PHDR, PF_R + PF_X, 0x40, 0x400040, 0x400040, 0x1c0, 0x1c0, 0x8},
   119  			{PT_INTERP, PF_R, 0x200, 0x400200, 0x400200, 0x1c, 0x1c, 1},
   120  			{PT_LOAD, PF_R + PF_X, 0x0, 0x400000, 0x400000, 0x684, 0x684, 0x200000},
   121  			{PT_LOAD, PF_R + PF_W, 0x688, 0x600688, 0x600688, 0x210, 0x218, 0x200000},
   122  			{PT_DYNAMIC, PF_R + PF_W, 0x6b0, 0x6006b0, 0x6006b0, 0x1a0, 0x1a0, 0x8},
   123  			{PT_NOTE, PF_R, 0x21c, 0x40021c, 0x40021c, 0x20, 0x20, 0x4},
   124  			{PT_LOOS + 0x474E550, PF_R, 0x5b8, 0x4005b8, 0x4005b8, 0x24, 0x24, 0x4},
   125  			{PT_LOOS + 0x474E551, PF_R + PF_W, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8},
   126  		},
   127  		[]string{"libc.so.6"},
   128  	},
   129  	{
   130  		"testdata/hello-world-core.gz",
   131  		FileHeader{ELFCLASS64, ELFDATA2LSB, EV_CURRENT, ELFOSABI_NONE, 0x0, binary.LittleEndian, ET_CORE, EM_X86_64, 0x0},
   132  		[]SectionHeader{},
   133  		[]ProgHeader{
   134  			{Type: PT_NOTE, Flags: 0x0, Off: 0x3f8, Vaddr: 0x0, Paddr: 0x0, Filesz: 0x8ac, Memsz: 0x0, Align: 0x0},
   135  			{Type: PT_LOAD, Flags: PF_X + PF_R, Off: 0x1000, Vaddr: 0x400000, Paddr: 0x0, Filesz: 0x0, Memsz: 0x1000, Align: 0x1000},
   136  			{Type: PT_LOAD, Flags: PF_R, Off: 0x1000, Vaddr: 0x401000, Paddr: 0x0, Filesz: 0x1000, Memsz: 0x1000, Align: 0x1000},
   137  			{Type: PT_LOAD, Flags: PF_W + PF_R, Off: 0x2000, Vaddr: 0x402000, Paddr: 0x0, Filesz: 0x1000, Memsz: 0x1000, Align: 0x1000},
   138  			{Type: PT_LOAD, Flags: PF_X + PF_R, Off: 0x3000, Vaddr: 0x7f54078b8000, Paddr: 0x0, Filesz: 0x0, Memsz: 0x1b5000, Align: 0x1000},
   139  			{Type: PT_LOAD, Flags: 0x0, Off: 0x3000, Vaddr: 0x7f5407a6d000, Paddr: 0x0, Filesz: 0x0, Memsz: 0x1ff000, Align: 0x1000},
   140  			{Type: PT_LOAD, Flags: PF_R, Off: 0x3000, Vaddr: 0x7f5407c6c000, Paddr: 0x0, Filesz: 0x4000, Memsz: 0x4000, Align: 0x1000},
   141  			{Type: PT_LOAD, Flags: PF_W + PF_R, Off: 0x7000, Vaddr: 0x7f5407c70000, Paddr: 0x0, Filesz: 0x2000, Memsz: 0x2000, Align: 0x1000},
   142  			{Type: PT_LOAD, Flags: PF_W + PF_R, Off: 0x9000, Vaddr: 0x7f5407c72000, Paddr: 0x0, Filesz: 0x5000, Memsz: 0x5000, Align: 0x1000},
   143  			{Type: PT_LOAD, Flags: PF_X + PF_R, Off: 0xe000, Vaddr: 0x7f5407c77000, Paddr: 0x0, Filesz: 0x0, Memsz: 0x22000, Align: 0x1000},
   144  			{Type: PT_LOAD, Flags: PF_W + PF_R, Off: 0xe000, Vaddr: 0x7f5407e81000, Paddr: 0x0, Filesz: 0x3000, Memsz: 0x3000, Align: 0x1000},
   145  			{Type: PT_LOAD, Flags: PF_W + PF_R, Off: 0x11000, Vaddr: 0x7f5407e96000, Paddr: 0x0, Filesz: 0x3000, Memsz: 0x3000, Align: 0x1000},
   146  			{Type: PT_LOAD, Flags: PF_R, Off: 0x14000, Vaddr: 0x7f5407e99000, Paddr: 0x0, Filesz: 0x1000, Memsz: 0x1000, Align: 0x1000},
   147  			{Type: PT_LOAD, Flags: PF_W + PF_R, Off: 0x15000, Vaddr: 0x7f5407e9a000, Paddr: 0x0, Filesz: 0x2000, Memsz: 0x2000, Align: 0x1000},
   148  			{Type: PT_LOAD, Flags: PF_W + PF_R, Off: 0x17000, Vaddr: 0x7fff79972000, Paddr: 0x0, Filesz: 0x23000, Memsz: 0x23000, Align: 0x1000},
   149  			{Type: PT_LOAD, Flags: PF_X + PF_R, Off: 0x3a000, Vaddr: 0x7fff799f8000, Paddr: 0x0, Filesz: 0x1000, Memsz: 0x1000, Align: 0x1000},
   150  			{Type: PT_LOAD, Flags: PF_X + PF_R, Off: 0x3b000, Vaddr: 0xffffffffff600000, Paddr: 0x0, Filesz: 0x1000, Memsz: 0x1000, Align: 0x1000},
   151  		},
   152  		nil,
   153  	},
   154  	{
   155  		"testdata/compressed-32.obj",
   156  		FileHeader{ELFCLASS32, ELFDATA2LSB, EV_CURRENT, ELFOSABI_NONE, 0x0, binary.LittleEndian, ET_REL, EM_386, 0x0},
   157  		[]SectionHeader{
   158  			{"", SHT_NULL, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0},
   159  			{".text", SHT_PROGBITS, SHF_ALLOC | SHF_EXECINSTR, 0x0, 0x34, 0x17, 0x0, 0x0, 0x1, 0x0, 0x17},
   160  			{".rel.text", SHT_REL, SHF_INFO_LINK, 0x0, 0x3dc, 0x10, 0x13, 0x1, 0x4, 0x8, 0x10},
   161  			{".data", SHT_PROGBITS, SHF_WRITE | SHF_ALLOC, 0x0, 0x4b, 0x0, 0x0, 0x0, 0x1, 0x0, 0x0},
   162  			{".bss", SHT_NOBITS, SHF_WRITE | SHF_ALLOC, 0x0, 0x4b, 0x0, 0x0, 0x0, 0x1, 0x0, 0x0},
   163  			{".rodata", SHT_PROGBITS, SHF_ALLOC, 0x0, 0x4b, 0xd, 0x0, 0x0, 0x1, 0x0, 0xd},
   164  			{".debug_info", SHT_PROGBITS, SHF_COMPRESSED, 0x0, 0x58, 0xb4, 0x0, 0x0, 0x1, 0x0, 0x84},
   165  			{".rel.debug_info", SHT_REL, SHF_INFO_LINK, 0x0, 0x3ec, 0xa0, 0x13, 0x6, 0x4, 0x8, 0xa0},
   166  			{".debug_abbrev", SHT_PROGBITS, 0x0, 0x0, 0xdc, 0x5a, 0x0, 0x0, 0x1, 0x0, 0x5a},
   167  			{".debug_aranges", SHT_PROGBITS, 0x0, 0x0, 0x136, 0x20, 0x0, 0x0, 0x1, 0x0, 0x20},
   168  			{".rel.debug_aranges", SHT_REL, SHF_INFO_LINK, 0x0, 0x48c, 0x10, 0x13, 0x9, 0x4, 0x8, 0x10},
   169  			{".debug_line", SHT_PROGBITS, 0x0, 0x0, 0x156, 0x5c, 0x0, 0x0, 0x1, 0x0, 0x5c},
   170  			{".rel.debug_line", SHT_REL, SHF_INFO_LINK, 0x0, 0x49c, 0x8, 0x13, 0xb, 0x4, 0x8, 0x8},
   171  			{".debug_str", SHT_PROGBITS, SHF_MERGE | SHF_STRINGS | SHF_COMPRESSED, 0x0, 0x1b2, 0x10f, 0x0, 0x0, 0x1, 0x1, 0xb3},
   172  			{".comment", SHT_PROGBITS, SHF_MERGE | SHF_STRINGS, 0x0, 0x265, 0x2a, 0x0, 0x0, 0x1, 0x1, 0x2a},
   173  			{".note.GNU-stack", SHT_PROGBITS, 0x0, 0x0, 0x28f, 0x0, 0x0, 0x0, 0x1, 0x0, 0x0},
   174  			{".eh_frame", SHT_PROGBITS, SHF_ALLOC, 0x0, 0x290, 0x38, 0x0, 0x0, 0x4, 0x0, 0x38},
   175  			{".rel.eh_frame", SHT_REL, SHF_INFO_LINK, 0x0, 0x4a4, 0x8, 0x13, 0x10, 0x4, 0x8, 0x8},
   176  			{".shstrtab", SHT_STRTAB, 0x0, 0x0, 0x4ac, 0xab, 0x0, 0x0, 0x1, 0x0, 0xab},
   177  			{".symtab", SHT_SYMTAB, 0x0, 0x0, 0x2c8, 0x100, 0x14, 0xe, 0x4, 0x10, 0x100},
   178  			{".strtab", SHT_STRTAB, 0x0, 0x0, 0x3c8, 0x13, 0x0, 0x0, 0x1, 0x0, 0x13},
   179  		},
   180  		[]ProgHeader{},
   181  		nil,
   182  	},
   183  	{
   184  		"testdata/compressed-64.obj",
   185  		FileHeader{ELFCLASS64, ELFDATA2LSB, EV_CURRENT, ELFOSABI_NONE, 0x0, binary.LittleEndian, ET_REL, EM_X86_64, 0x0},
   186  		[]SectionHeader{
   187  			{"", SHT_NULL, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0},
   188  			{".text", SHT_PROGBITS, SHF_ALLOC | SHF_EXECINSTR, 0x0, 0x40, 0x1b, 0x0, 0x0, 0x1, 0x0, 0x1b},
   189  			{".rela.text", SHT_RELA, SHF_INFO_LINK, 0x0, 0x488, 0x30, 0x13, 0x1, 0x8, 0x18, 0x30},
   190  			{".data", SHT_PROGBITS, SHF_WRITE | SHF_ALLOC, 0x0, 0x5b, 0x0, 0x0, 0x0, 0x1, 0x0, 0x0},
   191  			{".bss", SHT_NOBITS, SHF_WRITE | SHF_ALLOC, 0x0, 0x5b, 0x0, 0x0, 0x0, 0x1, 0x0, 0x0},
   192  			{".rodata", SHT_PROGBITS, SHF_ALLOC, 0x0, 0x5b, 0xd, 0x0, 0x0, 0x1, 0x0, 0xd},
   193  			{".debug_info", SHT_PROGBITS, SHF_COMPRESSED, 0x0, 0x68, 0xba, 0x0, 0x0, 0x1, 0x0, 0x72},
   194  			{".rela.debug_info", SHT_RELA, SHF_INFO_LINK, 0x0, 0x4b8, 0x1c8, 0x13, 0x6, 0x8, 0x18, 0x1c8},
   195  			{".debug_abbrev", SHT_PROGBITS, 0x0, 0x0, 0xda, 0x5c, 0x0, 0x0, 0x1, 0x0, 0x5c},
   196  			{".debug_aranges", SHT_PROGBITS, SHF_COMPRESSED, 0x0, 0x136, 0x30, 0x0, 0x0, 0x1, 0x0, 0x2f},
   197  			{".rela.debug_aranges", SHT_RELA, SHF_INFO_LINK, 0x0, 0x680, 0x30, 0x13, 0x9, 0x8, 0x18, 0x30},
   198  			{".debug_line", SHT_PROGBITS, 0x0, 0x0, 0x165, 0x60, 0x0, 0x0, 0x1, 0x0, 0x60},
   199  			{".rela.debug_line", SHT_RELA, SHF_INFO_LINK, 0x0, 0x6b0, 0x18, 0x13, 0xb, 0x8, 0x18, 0x18},
   200  			{".debug_str", SHT_PROGBITS, SHF_MERGE | SHF_STRINGS | SHF_COMPRESSED, 0x0, 0x1c5, 0x104, 0x0, 0x0, 0x1, 0x1, 0xc3},
   201  			{".comment", SHT_PROGBITS, SHF_MERGE | SHF_STRINGS, 0x0, 0x288, 0x2a, 0x0, 0x0, 0x1, 0x1, 0x2a},
   202  			{".note.GNU-stack", SHT_PROGBITS, 0x0, 0x0, 0x2b2, 0x0, 0x0, 0x0, 0x1, 0x0, 0x0},
   203  			{".eh_frame", SHT_PROGBITS, SHF_ALLOC, 0x0, 0x2b8, 0x38, 0x0, 0x0, 0x8, 0x0, 0x38},
   204  			{".rela.eh_frame", SHT_RELA, SHF_INFO_LINK, 0x0, 0x6c8, 0x18, 0x13, 0x10, 0x8, 0x18, 0x18},
   205  			{".shstrtab", SHT_STRTAB, 0x0, 0x0, 0x6e0, 0xb0, 0x0, 0x0, 0x1, 0x0, 0xb0},
   206  			{".symtab", SHT_SYMTAB, 0x0, 0x0, 0x2f0, 0x180, 0x14, 0xe, 0x8, 0x18, 0x180},
   207  			{".strtab", SHT_STRTAB, 0x0, 0x0, 0x470, 0x13, 0x0, 0x0, 0x1, 0x0, 0x13},
   208  		},
   209  		[]ProgHeader{},
   210  		nil,
   211  	},
   212  }
   213  
   214  func TestOpen(t *testing.T) {
   215  	for i := range fileTests {
   216  		tt := &fileTests[i]
   217  
   218  		var f *File
   219  		var err error
   220  		if path.Ext(tt.file) == ".gz" {
   221  			var r io.ReaderAt
   222  			if r, err = decompress(tt.file); err == nil {
   223  				f, err = NewFile(r)
   224  			}
   225  		} else {
   226  			f, err = Open(tt.file)
   227  		}
   228  		if err != nil {
   229  			t.Errorf("cannot open file %s: %v", tt.file, err)
   230  			continue
   231  		}
   232  		defer f.Close()
   233  		if !reflect.DeepEqual(f.FileHeader, tt.hdr) {
   234  			t.Errorf("open %s:\n\thave %#v\n\twant %#v\n", tt.file, f.FileHeader, tt.hdr)
   235  			continue
   236  		}
   237  		for i, s := range f.Sections {
   238  			if i >= len(tt.sections) {
   239  				break
   240  			}
   241  			sh := &tt.sections[i]
   242  			if !reflect.DeepEqual(&s.SectionHeader, sh) {
   243  				t.Errorf("open %s, section %d:\n\thave %#v\n\twant %#v\n", tt.file, i, &s.SectionHeader, sh)
   244  			}
   245  		}
   246  		for i, p := range f.Progs {
   247  			if i >= len(tt.progs) {
   248  				break
   249  			}
   250  			ph := &tt.progs[i]
   251  			if !reflect.DeepEqual(&p.ProgHeader, ph) {
   252  				t.Errorf("open %s, program %d:\n\thave %#v\n\twant %#v\n", tt.file, i, &p.ProgHeader, ph)
   253  			}
   254  		}
   255  		tn := len(tt.sections)
   256  		fn := len(f.Sections)
   257  		if tn != fn {
   258  			t.Errorf("open %s: len(Sections) = %d, want %d", tt.file, fn, tn)
   259  		}
   260  		tn = len(tt.progs)
   261  		fn = len(f.Progs)
   262  		if tn != fn {
   263  			t.Errorf("open %s: len(Progs) = %d, want %d", tt.file, fn, tn)
   264  		}
   265  		tl := tt.needed
   266  		fl, err := f.ImportedLibraries()
   267  		if err != nil {
   268  			t.Error(err)
   269  		}
   270  		if !reflect.DeepEqual(tl, fl) {
   271  			t.Errorf("open %s: DT_NEEDED = %v, want %v", tt.file, tl, fl)
   272  		}
   273  	}
   274  }
   275  
   276  // elf.NewFile requires io.ReaderAt, which compress/gzip cannot
   277  // provide. Decompress the file to a bytes.Reader.
   278  func decompress(gz string) (io.ReaderAt, error) {
   279  	in, err := os.Open(gz)
   280  	if err != nil {
   281  		return nil, err
   282  	}
   283  	defer in.Close()
   284  	r, err := gzip.NewReader(in)
   285  	if err != nil {
   286  		return nil, err
   287  	}
   288  	var out bytes.Buffer
   289  	_, err = io.Copy(&out, r)
   290  	return bytes.NewReader(out.Bytes()), err
   291  }
   292  
   293  type relocationTestEntry struct {
   294  	entryNumber int
   295  	entry       *dwarf.Entry
   296  }
   297  
   298  type relocationTest struct {
   299  	file    string
   300  	entries []relocationTestEntry
   301  }
   302  
   303  var relocationTests = []relocationTest{
   304  	{
   305  		"testdata/go-relocation-test-gcc441-x86-64.obj",
   306  		[]relocationTestEntry{
   307  			{0, &dwarf.Entry{
   308  				Offset:   0xb,
   309  				Tag:      dwarf.TagCompileUnit,
   310  				Children: true,
   311  				Field: []dwarf.Field{
   312  					{Attr: dwarf.AttrProducer, Val: "GNU C 4.4.1", Class: dwarf.ClassString},
   313  					{Attr: dwarf.AttrLanguage, Val: int64(1), Class: dwarf.ClassConstant},
   314  					{Attr: dwarf.AttrName, Val: "go-relocation-test.c", Class: dwarf.ClassString},
   315  					{Attr: dwarf.AttrCompDir, Val: "/tmp", Class: dwarf.ClassString},
   316  					{Attr: dwarf.AttrLowpc, Val: uint64(0x0), Class: dwarf.ClassAddress},
   317  					{Attr: dwarf.AttrHighpc, Val: uint64(0x6), Class: dwarf.ClassAddress},
   318  					{Attr: dwarf.AttrStmtList, Val: int64(0), Class: dwarf.ClassLinePtr},
   319  				},
   320  			}},
   321  		},
   322  	},
   323  	{
   324  		"testdata/go-relocation-test-gcc441-x86.obj",
   325  		[]relocationTestEntry{
   326  			{0, &dwarf.Entry{
   327  				Offset:   0xb,
   328  				Tag:      dwarf.TagCompileUnit,
   329  				Children: true,
   330  				Field: []dwarf.Field{
   331  					{Attr: dwarf.AttrProducer, Val: "GNU C 4.4.1", Class: dwarf.ClassString},
   332  					{Attr: dwarf.AttrLanguage, Val: int64(1), Class: dwarf.ClassConstant},
   333  					{Attr: dwarf.AttrName, Val: "t.c", Class: dwarf.ClassString},
   334  					{Attr: dwarf.AttrCompDir, Val: "/tmp", Class: dwarf.ClassString},
   335  					{Attr: dwarf.AttrLowpc, Val: uint64(0x0), Class: dwarf.ClassAddress},
   336  					{Attr: dwarf.AttrHighpc, Val: uint64(0x5), Class: dwarf.ClassAddress},
   337  					{Attr: dwarf.AttrStmtList, Val: int64(0), Class: dwarf.ClassLinePtr},
   338  				},
   339  			}},
   340  		},
   341  	},
   342  	{
   343  		"testdata/go-relocation-test-gcc424-x86-64.obj",
   344  		[]relocationTestEntry{
   345  			{0, &dwarf.Entry{
   346  				Offset:   0xb,
   347  				Tag:      dwarf.TagCompileUnit,
   348  				Children: true,
   349  				Field: []dwarf.Field{
   350  					{Attr: dwarf.AttrProducer, Val: "GNU C 4.2.4 (Ubuntu 4.2.4-1ubuntu4)", Class: dwarf.ClassString},
   351  					{Attr: dwarf.AttrLanguage, Val: int64(1), Class: dwarf.ClassConstant},
   352  					{Attr: dwarf.AttrName, Val: "go-relocation-test-gcc424.c", Class: dwarf.ClassString},
   353  					{Attr: dwarf.AttrCompDir, Val: "/tmp", Class: dwarf.ClassString},
   354  					{Attr: dwarf.AttrLowpc, Val: uint64(0x0), Class: dwarf.ClassAddress},
   355  					{Attr: dwarf.AttrHighpc, Val: uint64(0x6), Class: dwarf.ClassAddress},
   356  					{Attr: dwarf.AttrStmtList, Val: int64(0), Class: dwarf.ClassLinePtr},
   357  				},
   358  			}},
   359  		},
   360  	},
   361  	{
   362  		"testdata/go-relocation-test-gcc482-aarch64.obj",
   363  		[]relocationTestEntry{
   364  			{0, &dwarf.Entry{
   365  				Offset:   0xb,
   366  				Tag:      dwarf.TagCompileUnit,
   367  				Children: true,
   368  				Field: []dwarf.Field{
   369  					{Attr: dwarf.AttrProducer, Val: "GNU C 4.8.2 -g -fstack-protector", Class: dwarf.ClassString},
   370  					{Attr: dwarf.AttrLanguage, Val: int64(1), Class: dwarf.ClassConstant},
   371  					{Attr: dwarf.AttrName, Val: "go-relocation-test-gcc482.c", Class: dwarf.ClassString},
   372  					{Attr: dwarf.AttrCompDir, Val: "/tmp", Class: dwarf.ClassString},
   373  					{Attr: dwarf.AttrLowpc, Val: uint64(0x0), Class: dwarf.ClassAddress},
   374  					{Attr: dwarf.AttrHighpc, Val: int64(0x24), Class: dwarf.ClassConstant},
   375  					{Attr: dwarf.AttrStmtList, Val: int64(0), Class: dwarf.ClassLinePtr},
   376  				},
   377  			}},
   378  		},
   379  	},
   380  	{
   381  		"testdata/go-relocation-test-gcc492-arm.obj",
   382  		[]relocationTestEntry{
   383  			{0, &dwarf.Entry{
   384  				Offset:   0xb,
   385  				Tag:      dwarf.TagCompileUnit,
   386  				Children: true,
   387  				Field: []dwarf.Field{
   388  					{Attr: dwarf.AttrProducer, Val: "GNU C 4.9.2 20141224 (prerelease) -march=armv7-a -mfloat-abi=hard -mfpu=vfpv3-d16 -mtls-dialect=gnu -g", Class: dwarf.ClassString},
   389  					{Attr: dwarf.AttrLanguage, Val: int64(1), Class: dwarf.ClassConstant},
   390  					{Attr: dwarf.AttrName, Val: "go-relocation-test-gcc492.c", Class: dwarf.ClassString},
   391  					{Attr: dwarf.AttrCompDir, Val: "/root/go/src/debug/elf/testdata", Class: dwarf.ClassString},
   392  					{Attr: dwarf.AttrLowpc, Val: uint64(0x0), Class: dwarf.ClassAddress},
   393  					{Attr: dwarf.AttrHighpc, Val: int64(0x28), Class: dwarf.ClassConstant},
   394  					{Attr: dwarf.AttrStmtList, Val: int64(0), Class: dwarf.ClassLinePtr},
   395  				},
   396  			}},
   397  		},
   398  	},
   399  	{
   400  		"testdata/go-relocation-test-clang-arm.obj",
   401  		[]relocationTestEntry{
   402  			{0, &dwarf.Entry{
   403  				Offset:   0xb,
   404  				Tag:      dwarf.TagCompileUnit,
   405  				Children: true,
   406  				Field: []dwarf.Field{
   407  					{Attr: dwarf.AttrProducer, Val: "Debian clang version 3.5.0-10 (tags/RELEASE_350/final) (based on LLVM 3.5.0)", Class: dwarf.ClassString},
   408  					{Attr: dwarf.AttrLanguage, Val: int64(12), Class: dwarf.ClassConstant},
   409  					{Attr: dwarf.AttrName, Val: "hello.c", Class: dwarf.ClassString},
   410  					{Attr: dwarf.AttrStmtList, Val: int64(0x0), Class: dwarf.ClassLinePtr},
   411  					{Attr: dwarf.AttrCompDir, Val: "/tmp", Class: dwarf.ClassString},
   412  					{Attr: dwarf.AttrLowpc, Val: uint64(0x0), Class: dwarf.ClassAddress},
   413  					{Attr: dwarf.AttrHighpc, Val: int64(48), Class: dwarf.ClassConstant},
   414  				},
   415  			}},
   416  		},
   417  	},
   418  	{
   419  		"testdata/go-relocation-test-gcc5-ppc.obj",
   420  		[]relocationTestEntry{
   421  			{0, &dwarf.Entry{
   422  				Offset:   0xb,
   423  				Tag:      dwarf.TagCompileUnit,
   424  				Children: true,
   425  				Field: []dwarf.Field{
   426  					{Attr: dwarf.AttrProducer, Val: "GNU C11 5.0.0 20150116 (experimental) -Asystem=linux -Asystem=unix -Asystem=posix -g", Class: dwarf.ClassString},
   427  					{Attr: dwarf.AttrLanguage, Val: int64(12), Class: dwarf.ClassConstant},
   428  					{Attr: dwarf.AttrName, Val: "go-relocation-test-gcc5-ppc.c", Class: dwarf.ClassString},
   429  					{Attr: dwarf.AttrCompDir, Val: "/tmp", Class: dwarf.ClassString},
   430  					{Attr: dwarf.AttrLowpc, Val: uint64(0x0), Class: dwarf.ClassAddress},
   431  					{Attr: dwarf.AttrHighpc, Val: int64(0x44), Class: dwarf.ClassConstant},
   432  					{Attr: dwarf.AttrStmtList, Val: int64(0), Class: dwarf.ClassLinePtr},
   433  				},
   434  			}},
   435  		},
   436  	},
   437  	{
   438  		"testdata/go-relocation-test-gcc482-ppc64le.obj",
   439  		[]relocationTestEntry{
   440  			{0, &dwarf.Entry{
   441  				Offset:   0xb,
   442  				Tag:      dwarf.TagCompileUnit,
   443  				Children: true,
   444  				Field: []dwarf.Field{
   445  					{Attr: dwarf.AttrProducer, Val: "GNU C 4.8.2 -Asystem=linux -Asystem=unix -Asystem=posix -msecure-plt -mtune=power8 -mcpu=power7 -gdwarf-2 -fstack-protector", Class: dwarf.ClassString},
   446  					{Attr: dwarf.AttrLanguage, Val: int64(1), Class: dwarf.ClassConstant},
   447  					{Attr: dwarf.AttrName, Val: "go-relocation-test-gcc482-ppc64le.c", Class: dwarf.ClassString},
   448  					{Attr: dwarf.AttrCompDir, Val: "/tmp", Class: dwarf.ClassString},
   449  					{Attr: dwarf.AttrLowpc, Val: uint64(0x0), Class: dwarf.ClassAddress},
   450  					{Attr: dwarf.AttrHighpc, Val: uint64(0x24), Class: dwarf.ClassAddress},
   451  					{Attr: dwarf.AttrStmtList, Val: int64(0), Class: dwarf.ClassLinePtr},
   452  				},
   453  			}},
   454  		},
   455  	},
   456  	{
   457  		"testdata/go-relocation-test-gcc492-mips64.obj",
   458  		[]relocationTestEntry{
   459  			{0, &dwarf.Entry{
   460  				Offset:   0xb,
   461  				Tag:      dwarf.TagCompileUnit,
   462  				Children: true,
   463  				Field: []dwarf.Field{
   464  					{Attr: dwarf.AttrProducer, Val: "GNU C 4.9.2 -meb -mabi=64 -march=mips3 -mtune=mips64 -mllsc -mno-shared -g", Class: dwarf.ClassString},
   465  					{Attr: dwarf.AttrLanguage, Val: int64(1), Class: dwarf.ClassConstant},
   466  					{Attr: dwarf.AttrName, Val: "hello.c", Class: dwarf.ClassString},
   467  					{Attr: dwarf.AttrCompDir, Val: "/tmp", Class: dwarf.ClassString},
   468  					{Attr: dwarf.AttrLowpc, Val: uint64(0x0), Class: dwarf.ClassAddress},
   469  					{Attr: dwarf.AttrHighpc, Val: int64(100), Class: dwarf.ClassConstant},
   470  					{Attr: dwarf.AttrStmtList, Val: int64(0), Class: dwarf.ClassLinePtr},
   471  				},
   472  			}},
   473  		},
   474  	},
   475  	{
   476  		"testdata/go-relocation-test-gcc531-s390x.obj",
   477  		[]relocationTestEntry{
   478  			{0, &dwarf.Entry{
   479  				Offset:   0xb,
   480  				Tag:      dwarf.TagCompileUnit,
   481  				Children: true,
   482  				Field: []dwarf.Field{
   483  					{Attr: dwarf.AttrProducer, Val: "GNU C11 5.3.1 20160316 -march=zEC12 -m64 -mzarch -g -fstack-protector-strong", Class: dwarf.ClassString},
   484  					{Attr: dwarf.AttrLanguage, Val: int64(12), Class: dwarf.ClassConstant},
   485  					{Attr: dwarf.AttrName, Val: "hello.c", Class: dwarf.ClassString},
   486  					{Attr: dwarf.AttrCompDir, Val: "/tmp", Class: dwarf.ClassString},
   487  					{Attr: dwarf.AttrLowpc, Val: uint64(0x0), Class: dwarf.ClassAddress},
   488  					{Attr: dwarf.AttrHighpc, Val: int64(58), Class: dwarf.ClassConstant},
   489  					{Attr: dwarf.AttrStmtList, Val: int64(0), Class: dwarf.ClassLinePtr},
   490  				},
   491  			}},
   492  		},
   493  	},
   494  	{
   495  		"testdata/go-relocation-test-gcc620-sparc64.obj",
   496  		[]relocationTestEntry{
   497  			{0, &dwarf.Entry{
   498  				Offset:   0xb,
   499  				Tag:      dwarf.TagCompileUnit,
   500  				Children: true,
   501  				Field: []dwarf.Field{
   502  					{Attr: dwarf.AttrProducer, Val: "GNU C11 6.2.0 20160914 -mcpu=v9 -g -fstack-protector-strong", Class: dwarf.ClassString},
   503  					{Attr: dwarf.AttrLanguage, Val: int64(12), Class: dwarf.ClassConstant},
   504  					{Attr: dwarf.AttrName, Val: "hello.c", Class: dwarf.ClassString},
   505  					{Attr: dwarf.AttrCompDir, Val: "/tmp", Class: dwarf.ClassString},
   506  					{Attr: dwarf.AttrLowpc, Val: uint64(0x0), Class: dwarf.ClassAddress},
   507  					{Attr: dwarf.AttrHighpc, Val: int64(0x2c), Class: dwarf.ClassConstant},
   508  					{Attr: dwarf.AttrStmtList, Val: int64(0), Class: dwarf.ClassLinePtr},
   509  				},
   510  			}},
   511  		},
   512  	},
   513  	{
   514  		"testdata/go-relocation-test-gcc493-mips64le.obj",
   515  		[]relocationTestEntry{
   516  			{0, &dwarf.Entry{
   517  				Offset:   0xb,
   518  				Tag:      dwarf.TagCompileUnit,
   519  				Children: true,
   520  				Field: []dwarf.Field{
   521  					{Attr: dwarf.AttrProducer, Val: "GNU C 4.9.3 -mel -mabi=64 -mllsc -mno-shared -g -fstack-protector-strong", Class: dwarf.ClassString},
   522  					{Attr: dwarf.AttrLanguage, Val: int64(1), Class: dwarf.ClassConstant},
   523  					{Attr: dwarf.AttrName, Val: "hello.c", Class: dwarf.ClassString},
   524  					{Attr: dwarf.AttrCompDir, Val: "/tmp", Class: dwarf.ClassString},
   525  					{Attr: dwarf.AttrLowpc, Val: uint64(0x0), Class: dwarf.ClassAddress},
   526  					{Attr: dwarf.AttrHighpc, Val: int64(100), Class: dwarf.ClassConstant},
   527  					{Attr: dwarf.AttrStmtList, Val: int64(0), Class: dwarf.ClassLinePtr},
   528  				},
   529  			}},
   530  		},
   531  	},
   532  	{
   533  		"testdata/go-relocation-test-clang-x86.obj",
   534  		[]relocationTestEntry{
   535  			{0, &dwarf.Entry{
   536  				Offset:   0xb,
   537  				Tag:      dwarf.TagCompileUnit,
   538  				Children: true,
   539  				Field: []dwarf.Field{
   540  					{Attr: dwarf.AttrProducer, Val: "clang version google3-trunk (trunk r209387)", Class: dwarf.ClassString},
   541  					{Attr: dwarf.AttrLanguage, Val: int64(12), Class: dwarf.ClassConstant},
   542  					{Attr: dwarf.AttrName, Val: "go-relocation-test-clang.c", Class: dwarf.ClassString},
   543  					{Attr: dwarf.AttrStmtList, Val: int64(0), Class: dwarf.ClassLinePtr},
   544  					{Attr: dwarf.AttrCompDir, Val: "/tmp", Class: dwarf.ClassString},
   545  				},
   546  			}},
   547  		},
   548  	},
   549  	{
   550  		"testdata/gcc-amd64-openbsd-debug-with-rela.obj",
   551  		[]relocationTestEntry{
   552  			{203, &dwarf.Entry{
   553  				Offset:   0xc62,
   554  				Tag:      dwarf.TagMember,
   555  				Children: false,
   556  				Field: []dwarf.Field{
   557  					{Attr: dwarf.AttrName, Val: "it_interval", Class: dwarf.ClassString},
   558  					{Attr: dwarf.AttrDeclFile, Val: int64(7), Class: dwarf.ClassConstant},
   559  					{Attr: dwarf.AttrDeclLine, Val: int64(236), Class: dwarf.ClassConstant},
   560  					{Attr: dwarf.AttrType, Val: dwarf.Offset(0xb7f), Class: dwarf.ClassReference},
   561  					{Attr: dwarf.AttrDataMemberLoc, Val: []byte{0x23, 0x0}, Class: dwarf.ClassExprLoc},
   562  				},
   563  			}},
   564  			{204, &dwarf.Entry{
   565  				Offset:   0xc70,
   566  				Tag:      dwarf.TagMember,
   567  				Children: false,
   568  				Field: []dwarf.Field{
   569  					{Attr: dwarf.AttrName, Val: "it_value", Class: dwarf.ClassString},
   570  					{Attr: dwarf.AttrDeclFile, Val: int64(7), Class: dwarf.ClassConstant},
   571  					{Attr: dwarf.AttrDeclLine, Val: int64(237), Class: dwarf.ClassConstant},
   572  					{Attr: dwarf.AttrType, Val: dwarf.Offset(0xb7f), Class: dwarf.ClassReference},
   573  					{Attr: dwarf.AttrDataMemberLoc, Val: []byte{0x23, 0x10}, Class: dwarf.ClassExprLoc},
   574  				},
   575  			}},
   576  		},
   577  	},
   578  }
   579  
   580  func TestDWARFRelocations(t *testing.T) {
   581  	for i, test := range relocationTests {
   582  		f, err := Open(test.file)
   583  		if err != nil {
   584  			t.Error(err)
   585  			continue
   586  		}
   587  		dwarf, err := f.DWARF()
   588  		if err != nil {
   589  			t.Error(err)
   590  			continue
   591  		}
   592  		for _, testEntry := range test.entries {
   593  			reader := dwarf.Reader()
   594  			for j := 0; j < testEntry.entryNumber; j++ {
   595  				entry, err := reader.Next()
   596  				if entry == nil || err != nil {
   597  					t.Errorf("Failed to skip to entry %d: %v", testEntry.entryNumber, err)
   598  					continue
   599  				}
   600  			}
   601  			entry, err := reader.Next()
   602  			if err != nil {
   603  				t.Error(err)
   604  				continue
   605  			}
   606  			if !reflect.DeepEqual(testEntry.entry, entry) {
   607  				t.Errorf("#%d/%d: mismatch: got:%#v want:%#v", i, testEntry.entryNumber, entry, testEntry.entry)
   608  				continue
   609  			}
   610  		}
   611  	}
   612  }
   613  
   614  func TestCompressedDWARF(t *testing.T) {
   615  	// Test file built with GCC 4.8.4 and as 2.24 using:
   616  	// gcc -Wa,--compress-debug-sections -g -c -o zdebug-test-gcc484-x86-64.obj hello.c
   617  	f, err := Open("testdata/zdebug-test-gcc484-x86-64.obj")
   618  	if err != nil {
   619  		t.Fatal(err)
   620  	}
   621  	dwarf, err := f.DWARF()
   622  	if err != nil {
   623  		t.Fatal(err)
   624  	}
   625  	reader := dwarf.Reader()
   626  	n := 0
   627  	for {
   628  		entry, err := reader.Next()
   629  		if err != nil {
   630  			t.Fatal(err)
   631  		}
   632  		if entry == nil {
   633  			break
   634  		}
   635  		n++
   636  	}
   637  	if n != 18 {
   638  		t.Fatalf("want %d DWARF entries, got %d", 18, n)
   639  	}
   640  }
   641  
   642  func TestCompressedSection(t *testing.T) {
   643  	// Test files built with gcc -g -S hello.c and assembled with
   644  	// --compress-debug-sections=zlib-gabi.
   645  	f, err := Open("testdata/compressed-64.obj")
   646  	if err != nil {
   647  		t.Fatal(err)
   648  	}
   649  	sec := f.Section(".debug_info")
   650  	wantData := []byte{
   651  		182, 0, 0, 0, 4, 0, 0, 0, 0, 0, 8, 1, 0, 0, 0, 0,
   652  		1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
   653  		0, 27, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 8, 7,
   654  		0, 0, 0, 0, 2, 1, 8, 0, 0, 0, 0, 2, 2, 7, 0, 0,
   655  		0, 0, 2, 4, 7, 0, 0, 0, 0, 2, 1, 6, 0, 0, 0, 0,
   656  		2, 2, 5, 0, 0, 0, 0, 3, 4, 5, 105, 110, 116, 0, 2, 8,
   657  		5, 0, 0, 0, 0, 2, 8, 7, 0, 0, 0, 0, 4, 8, 114, 0,
   658  		0, 0, 2, 1, 6, 0, 0, 0, 0, 5, 0, 0, 0, 0, 1, 4,
   659  		0, 0, 0, 0, 0, 0, 0, 0, 27, 0, 0, 0, 0, 0, 0, 0,
   660  		1, 156, 179, 0, 0, 0, 6, 0, 0, 0, 0, 1, 4, 87, 0, 0,
   661  		0, 2, 145, 108, 6, 0, 0, 0, 0, 1, 4, 179, 0, 0, 0, 2,
   662  		145, 96, 0, 4, 8, 108, 0, 0, 0, 0,
   663  	}
   664  
   665  	// Test Data method.
   666  	b, err := sec.Data()
   667  	if err != nil {
   668  		t.Fatal(err)
   669  	}
   670  	if !bytes.Equal(wantData, b) {
   671  		t.Fatalf("want data %x, got %x", wantData, b)
   672  	}
   673  
   674  	// Test Open method and seeking.
   675  	buf, have, count := make([]byte, len(b)), make([]bool, len(b)), 0
   676  	sf := sec.Open()
   677  	if got, err := sf.Seek(0, io.SeekEnd); got != int64(len(b)) || err != nil {
   678  		t.Fatalf("want seek end %d, got %d error %v", len(b), got, err)
   679  	}
   680  	if n, err := sf.Read(buf); n != 0 || err != io.EOF {
   681  		t.Fatalf("want EOF with 0 bytes, got %v with %d bytes", err, n)
   682  	}
   683  	pos := int64(len(buf))
   684  	for count < len(buf) {
   685  		// Construct random seek arguments.
   686  		whence := rand.Intn(3)
   687  		target := rand.Int63n(int64(len(buf)))
   688  		var offset int64
   689  		switch whence {
   690  		case io.SeekStart:
   691  			offset = target
   692  		case io.SeekCurrent:
   693  			offset = target - pos
   694  		case io.SeekEnd:
   695  			offset = target - int64(len(buf))
   696  		}
   697  		pos, err = sf.Seek(offset, whence)
   698  		if err != nil {
   699  			t.Fatal(err)
   700  		}
   701  		if pos != target {
   702  			t.Fatalf("want position %d, got %d", target, pos)
   703  		}
   704  
   705  		// Read data from the new position.
   706  		end := pos + 16
   707  		if end > int64(len(buf)) {
   708  			end = int64(len(buf))
   709  		}
   710  		n, err := io.ReadFull(sf, buf[pos:end])
   711  		if err != nil {
   712  			t.Fatal(err)
   713  		}
   714  		for i := 0; i < n; i++ {
   715  			if !have[pos] {
   716  				have[pos] = true
   717  				count++
   718  			}
   719  			pos++
   720  		}
   721  	}
   722  	if !bytes.Equal(wantData, buf) {
   723  		t.Fatalf("want data %x, got %x", wantData, buf)
   724  	}
   725  }
   726  
   727  func TestNoSectionOverlaps(t *testing.T) {
   728  	// Ensure 6l outputs sections without overlaps.
   729  	if runtime.GOOS != "linux" && runtime.GOOS != "freebsd" {
   730  		return // not ELF
   731  	}
   732  	_ = net.ResolveIPAddr // force dynamic linkage
   733  	f, err := Open(os.Args[0])
   734  	if err != nil {
   735  		t.Error(err)
   736  		return
   737  	}
   738  	for i, si := range f.Sections {
   739  		sih := si.SectionHeader
   740  		if sih.Type == SHT_NOBITS {
   741  			continue
   742  		}
   743  		for j, sj := range f.Sections {
   744  			sjh := sj.SectionHeader
   745  			if i == j || sjh.Type == SHT_NOBITS || sih.Offset == sjh.Offset && sih.Size == 0 {
   746  				continue
   747  			}
   748  			if sih.Offset >= sjh.Offset && sih.Offset < sjh.Offset+sjh.Size {
   749  				t.Errorf("ld produced ELF with section %s within %s: 0x%x <= 0x%x..0x%x < 0x%x",
   750  					sih.Name, sjh.Name, sjh.Offset, sih.Offset, sih.Offset+sih.Size, sjh.Offset+sjh.Size)
   751  			}
   752  		}
   753  	}
   754  }