github.com/mh-cbon/go@v0.0.0-20160603070303-9e112a3fe4c0/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-gcc493-mips64le.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 C 4.9.3 -mel -mabi=64 -mllsc -mno-shared -g -fstack-protector-strong", Class: dwarf.ClassString},
   503  					{Attr: dwarf.AttrLanguage, Val: int64(1), 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(100), Class: dwarf.ClassConstant},
   508  					{Attr: dwarf.AttrStmtList, Val: int64(0), Class: dwarf.ClassLinePtr},
   509  				},
   510  			}},
   511  		},
   512  	},
   513  	{
   514  		"testdata/go-relocation-test-clang-x86.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: "clang version google3-trunk (trunk r209387)", Class: dwarf.ClassString},
   522  					{Attr: dwarf.AttrLanguage, Val: int64(12), Class: dwarf.ClassConstant},
   523  					{Attr: dwarf.AttrName, Val: "go-relocation-test-clang.c", Class: dwarf.ClassString},
   524  					{Attr: dwarf.AttrStmtList, Val: int64(0), Class: dwarf.ClassLinePtr},
   525  					{Attr: dwarf.AttrCompDir, Val: "/tmp", Class: dwarf.ClassString},
   526  				},
   527  			}},
   528  		},
   529  	},
   530  	{
   531  		"testdata/gcc-amd64-openbsd-debug-with-rela.obj",
   532  		[]relocationTestEntry{
   533  			{203, &dwarf.Entry{
   534  				Offset:   0xc62,
   535  				Tag:      dwarf.TagMember,
   536  				Children: false,
   537  				Field: []dwarf.Field{
   538  					{Attr: dwarf.AttrName, Val: "it_interval", Class: dwarf.ClassString},
   539  					{Attr: dwarf.AttrDeclFile, Val: int64(7), Class: dwarf.ClassConstant},
   540  					{Attr: dwarf.AttrDeclLine, Val: int64(236), Class: dwarf.ClassConstant},
   541  					{Attr: dwarf.AttrType, Val: dwarf.Offset(0xb7f), Class: dwarf.ClassReference},
   542  					{Attr: dwarf.AttrDataMemberLoc, Val: []byte{0x23, 0x0}, Class: dwarf.ClassExprLoc},
   543  				},
   544  			}},
   545  			{204, &dwarf.Entry{
   546  				Offset:   0xc70,
   547  				Tag:      dwarf.TagMember,
   548  				Children: false,
   549  				Field: []dwarf.Field{
   550  					{Attr: dwarf.AttrName, Val: "it_value", Class: dwarf.ClassString},
   551  					{Attr: dwarf.AttrDeclFile, Val: int64(7), Class: dwarf.ClassConstant},
   552  					{Attr: dwarf.AttrDeclLine, Val: int64(237), Class: dwarf.ClassConstant},
   553  					{Attr: dwarf.AttrType, Val: dwarf.Offset(0xb7f), Class: dwarf.ClassReference},
   554  					{Attr: dwarf.AttrDataMemberLoc, Val: []byte{0x23, 0x10}, Class: dwarf.ClassExprLoc},
   555  				},
   556  			}},
   557  		},
   558  	},
   559  }
   560  
   561  func TestDWARFRelocations(t *testing.T) {
   562  	for i, test := range relocationTests {
   563  		f, err := Open(test.file)
   564  		if err != nil {
   565  			t.Error(err)
   566  			continue
   567  		}
   568  		dwarf, err := f.DWARF()
   569  		if err != nil {
   570  			t.Error(err)
   571  			continue
   572  		}
   573  		for _, testEntry := range test.entries {
   574  			reader := dwarf.Reader()
   575  			for j := 0; j < testEntry.entryNumber; j++ {
   576  				entry, err := reader.Next()
   577  				if entry == nil || err != nil {
   578  					t.Errorf("Failed to skip to entry %d: %v", testEntry.entryNumber, err)
   579  					continue
   580  				}
   581  			}
   582  			entry, err := reader.Next()
   583  			if err != nil {
   584  				t.Error(err)
   585  				continue
   586  			}
   587  			if !reflect.DeepEqual(testEntry.entry, entry) {
   588  				t.Errorf("#%d/%d: mismatch: got:%#v want:%#v", i, testEntry.entryNumber, entry, testEntry.entry)
   589  				continue
   590  			}
   591  		}
   592  	}
   593  }
   594  
   595  func TestCompressedDWARF(t *testing.T) {
   596  	// Test file built with GCC 4.8.4 and as 2.24 using:
   597  	// gcc -Wa,--compress-debug-sections -g -c -o zdebug-test-gcc484-x86-64.obj hello.c
   598  	f, err := Open("testdata/zdebug-test-gcc484-x86-64.obj")
   599  	if err != nil {
   600  		t.Fatal(err)
   601  	}
   602  	dwarf, err := f.DWARF()
   603  	if err != nil {
   604  		t.Fatal(err)
   605  	}
   606  	reader := dwarf.Reader()
   607  	n := 0
   608  	for {
   609  		entry, err := reader.Next()
   610  		if err != nil {
   611  			t.Fatal(err)
   612  		}
   613  		if entry == nil {
   614  			break
   615  		}
   616  		n++
   617  	}
   618  	if n != 18 {
   619  		t.Fatalf("want %d DWARF entries, got %d", 18, n)
   620  	}
   621  }
   622  
   623  func TestCompressedSection(t *testing.T) {
   624  	// Test files built with gcc -g -S hello.c and assembled with
   625  	// --compress-debug-sections=zlib-gabi.
   626  	f, err := Open("testdata/compressed-64.obj")
   627  	if err != nil {
   628  		t.Fatal(err)
   629  	}
   630  	sec := f.Section(".debug_info")
   631  	wantData := []byte{
   632  		182, 0, 0, 0, 4, 0, 0, 0, 0, 0, 8, 1, 0, 0, 0, 0,
   633  		1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
   634  		0, 27, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 8, 7,
   635  		0, 0, 0, 0, 2, 1, 8, 0, 0, 0, 0, 2, 2, 7, 0, 0,
   636  		0, 0, 2, 4, 7, 0, 0, 0, 0, 2, 1, 6, 0, 0, 0, 0,
   637  		2, 2, 5, 0, 0, 0, 0, 3, 4, 5, 105, 110, 116, 0, 2, 8,
   638  		5, 0, 0, 0, 0, 2, 8, 7, 0, 0, 0, 0, 4, 8, 114, 0,
   639  		0, 0, 2, 1, 6, 0, 0, 0, 0, 5, 0, 0, 0, 0, 1, 4,
   640  		0, 0, 0, 0, 0, 0, 0, 0, 27, 0, 0, 0, 0, 0, 0, 0,
   641  		1, 156, 179, 0, 0, 0, 6, 0, 0, 0, 0, 1, 4, 87, 0, 0,
   642  		0, 2, 145, 108, 6, 0, 0, 0, 0, 1, 4, 179, 0, 0, 0, 2,
   643  		145, 96, 0, 4, 8, 108, 0, 0, 0, 0,
   644  	}
   645  
   646  	// Test Data method.
   647  	b, err := sec.Data()
   648  	if err != nil {
   649  		t.Fatal(err)
   650  	}
   651  	if !bytes.Equal(wantData, b) {
   652  		t.Fatalf("want data %x, got %x", wantData, b)
   653  	}
   654  
   655  	// Test Open method and seeking.
   656  	buf, have, count := make([]byte, len(b)), make([]bool, len(b)), 0
   657  	sf := sec.Open()
   658  	if got, err := sf.Seek(0, io.SeekEnd); got != int64(len(b)) || err != nil {
   659  		t.Fatalf("want seek end %d, got %d error %v", len(b), got, err)
   660  	}
   661  	if n, err := sf.Read(buf); n != 0 || err != io.EOF {
   662  		t.Fatalf("want EOF with 0 bytes, got %v with %d bytes", err, n)
   663  	}
   664  	pos := int64(len(buf))
   665  	for count < len(buf) {
   666  		// Construct random seek arguments.
   667  		whence := rand.Intn(3)
   668  		target := rand.Int63n(int64(len(buf)))
   669  		var offset int64
   670  		switch whence {
   671  		case io.SeekStart:
   672  			offset = target
   673  		case io.SeekCurrent:
   674  			offset = target - pos
   675  		case io.SeekEnd:
   676  			offset = target - int64(len(buf))
   677  		}
   678  		pos, err = sf.Seek(offset, whence)
   679  		if err != nil {
   680  			t.Fatal(err)
   681  		}
   682  		if pos != target {
   683  			t.Fatalf("want position %d, got %d", target, pos)
   684  		}
   685  
   686  		// Read data from the new position.
   687  		end := pos + 16
   688  		if end > int64(len(buf)) {
   689  			end = int64(len(buf))
   690  		}
   691  		n, err := io.ReadFull(sf, buf[pos:end])
   692  		if err != nil {
   693  			t.Fatal(err)
   694  		}
   695  		for i := 0; i < n; i++ {
   696  			if !have[pos] {
   697  				have[pos] = true
   698  				count++
   699  			}
   700  			pos++
   701  		}
   702  	}
   703  	if !bytes.Equal(wantData, buf) {
   704  		t.Fatalf("want data %x, got %x", wantData, buf)
   705  	}
   706  }
   707  
   708  func TestNoSectionOverlaps(t *testing.T) {
   709  	// Ensure 6l outputs sections without overlaps.
   710  	if runtime.GOOS != "linux" && runtime.GOOS != "freebsd" {
   711  		return // not ELF
   712  	}
   713  	_ = net.ResolveIPAddr // force dynamic linkage
   714  	f, err := Open(os.Args[0])
   715  	if err != nil {
   716  		t.Error(err)
   717  		return
   718  	}
   719  	for i, si := range f.Sections {
   720  		sih := si.SectionHeader
   721  		if sih.Type == SHT_NOBITS {
   722  			continue
   723  		}
   724  		for j, sj := range f.Sections {
   725  			sjh := sj.SectionHeader
   726  			if i == j || sjh.Type == SHT_NOBITS || sih.Offset == sjh.Offset && sih.Size == 0 {
   727  				continue
   728  			}
   729  			if sih.Offset >= sjh.Offset && sih.Offset < sjh.Offset+sjh.Size {
   730  				t.Errorf("ld produced ELF with section %s within %s: 0x%x <= 0x%x..0x%x < 0x%x",
   731  					sih.Name, sjh.Name, sjh.Offset, sih.Offset, sih.Offset+sih.Size, sjh.Offset+sjh.Size)
   732  			}
   733  		}
   734  	}
   735  }