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