Source file src/debug/elf/file_test.go

     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  	"compress/zlib"
    11  	"debug/dwarf"
    12  	"encoding/binary"
    13  	"errors"
    14  	"fmt"
    15  	"io"
    16  	"math/rand"
    17  	"net"
    18  	"os"
    19  	"path"
    20  	"reflect"
    21  	"runtime"
    22  	"slices"
    23  	"strings"
    24  	"testing"
    25  )
    26  
    27  type fileTest struct {
    28  	file     string
    29  	hdr      FileHeader
    30  	sections []SectionHeader
    31  	progs    []ProgHeader
    32  	needed   []string
    33  	symbols  []Symbol
    34  }
    35  
    36  var fileTests = []fileTest{
    37  	{
    38  		"testdata/gcc-386-freebsd-exec",
    39  		FileHeader{ELFCLASS32, ELFDATA2LSB, EV_CURRENT, ELFOSABI_FREEBSD, 0, binary.LittleEndian, ET_EXEC, EM_386, 0x80483cc},
    40  		[]SectionHeader{
    41  			{"", SHT_NULL, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0},
    42  			{".interp", SHT_PROGBITS, SHF_ALLOC, 0x80480d4, 0xd4, 0x15, 0x0, 0x0, 0x1, 0x0, 0x15},
    43  			{".hash", SHT_HASH, SHF_ALLOC, 0x80480ec, 0xec, 0x90, 0x3, 0x0, 0x4, 0x4, 0x90},
    44  			{".dynsym", SHT_DYNSYM, SHF_ALLOC, 0x804817c, 0x17c, 0x110, 0x4, 0x1, 0x4, 0x10, 0x110},
    45  			{".dynstr", SHT_STRTAB, SHF_ALLOC, 0x804828c, 0x28c, 0xbb, 0x0, 0x0, 0x1, 0x0, 0xbb},
    46  			{".rel.plt", SHT_REL, SHF_ALLOC, 0x8048348, 0x348, 0x20, 0x3, 0x7, 0x4, 0x8, 0x20},
    47  			{".init", SHT_PROGBITS, SHF_ALLOC + SHF_EXECINSTR, 0x8048368, 0x368, 0x11, 0x0, 0x0, 0x4, 0x0, 0x11},
    48  			{".plt", SHT_PROGBITS, SHF_ALLOC + SHF_EXECINSTR, 0x804837c, 0x37c, 0x50, 0x0, 0x0, 0x4, 0x4, 0x50},
    49  			{".text", SHT_PROGBITS, SHF_ALLOC + SHF_EXECINSTR, 0x80483cc, 0x3cc, 0x180, 0x0, 0x0, 0x4, 0x0, 0x180},
    50  			{".fini", SHT_PROGBITS, SHF_ALLOC + SHF_EXECINSTR, 0x804854c, 0x54c, 0xc, 0x0, 0x0, 0x4, 0x0, 0xc},
    51  			{".rodata", SHT_PROGBITS, SHF_ALLOC, 0x8048558, 0x558, 0xa3, 0x0, 0x0, 0x1, 0x0, 0xa3},
    52  			{".data", SHT_PROGBITS, SHF_WRITE + SHF_ALLOC, 0x80495fc, 0x5fc, 0xc, 0x0, 0x0, 0x4, 0x0, 0xc},
    53  			{".eh_frame", SHT_PROGBITS, SHF_ALLOC, 0x8049608, 0x608, 0x4, 0x0, 0x0, 0x4, 0x0, 0x4},
    54  			{".dynamic", SHT_DYNAMIC, SHF_WRITE + SHF_ALLOC, 0x804960c, 0x60c, 0x98, 0x4, 0x0, 0x4, 0x8, 0x98},
    55  			{".ctors", SHT_PROGBITS, SHF_WRITE + SHF_ALLOC, 0x80496a4, 0x6a4, 0x8, 0x0, 0x0, 0x4, 0x0, 0x8},
    56  			{".dtors", SHT_PROGBITS, SHF_WRITE + SHF_ALLOC, 0x80496ac, 0x6ac, 0x8, 0x0, 0x0, 0x4, 0x0, 0x8},
    57  			{".jcr", SHT_PROGBITS, SHF_WRITE + SHF_ALLOC, 0x80496b4, 0x6b4, 0x4, 0x0, 0x0, 0x4, 0x0, 0x4},
    58  			{".got", SHT_PROGBITS, SHF_WRITE + SHF_ALLOC, 0x80496b8, 0x6b8, 0x1c, 0x0, 0x0, 0x4, 0x4, 0x1c},
    59  			{".bss", SHT_NOBITS, SHF_WRITE + SHF_ALLOC, 0x80496d4, 0x6d4, 0x20, 0x0, 0x0, 0x4, 0x0, 0x20},
    60  			{".comment", SHT_PROGBITS, 0x0, 0x0, 0x6d4, 0x12d, 0x0, 0x0, 0x1, 0x0, 0x12d},
    61  			{".debug_aranges", SHT_PROGBITS, 0x0, 0x0, 0x801, 0x20, 0x0, 0x0, 0x1, 0x0, 0x20},
    62  			{".debug_pubnames", SHT_PROGBITS, 0x0, 0x0, 0x821, 0x1b, 0x0, 0x0, 0x1, 0x0, 0x1b},
    63  			{".debug_info", SHT_PROGBITS, 0x0, 0x0, 0x83c, 0x11d, 0x0, 0x0, 0x1, 0x0, 0x11d},
    64  			{".debug_abbrev", SHT_PROGBITS, 0x0, 0x0, 0x959, 0x41, 0x0, 0x0, 0x1, 0x0, 0x41},
    65  			{".debug_line", SHT_PROGBITS, 0x0, 0x0, 0x99a, 0x35, 0x0, 0x0, 0x1, 0x0, 0x35},
    66  			{".debug_frame", SHT_PROGBITS, 0x0, 0x0, 0x9d0, 0x30, 0x0, 0x0, 0x4, 0x0, 0x30},
    67  			{".debug_str", SHT_PROGBITS, 0x0, 0x0, 0xa00, 0xd, 0x0, 0x0, 0x1, 0x0, 0xd},
    68  			{".shstrtab", SHT_STRTAB, 0x0, 0x0, 0xa0d, 0xf8, 0x0, 0x0, 0x1, 0x0, 0xf8},
    69  			{".symtab", SHT_SYMTAB, 0x0, 0x0, 0xfb8, 0x4b0, 0x1d, 0x38, 0x4, 0x10, 0x4b0},
    70  			{".strtab", SHT_STRTAB, 0x0, 0x0, 0x1468, 0x206, 0x0, 0x0, 0x1, 0x0, 0x206},
    71  		},
    72  		[]ProgHeader{
    73  			{PT_PHDR, PF_R + PF_X, 0x34, 0x8048034, 0x8048034, 0xa0, 0xa0, 0x4},
    74  			{PT_INTERP, PF_R, 0xd4, 0x80480d4, 0x80480d4, 0x15, 0x15, 0x1},
    75  			{PT_LOAD, PF_R + PF_X, 0x0, 0x8048000, 0x8048000, 0x5fb, 0x5fb, 0x1000},
    76  			{PT_LOAD, PF_R + PF_W, 0x5fc, 0x80495fc, 0x80495fc, 0xd8, 0xf8, 0x1000},
    77  			{PT_DYNAMIC, PF_R + PF_W, 0x60c, 0x804960c, 0x804960c, 0x98, 0x98, 0x4},
    78  		},
    79  		[]string{"libc.so.6"},
    80  		[]Symbol{
    81  			{"", 3, 0, 1, 134512852, 0, "", ""},
    82  			{"", 3, 0, 2, 134512876, 0, "", ""},
    83  			{"", 3, 0, 3, 134513020, 0, "", ""},
    84  			{"", 3, 0, 4, 134513292, 0, "", ""},
    85  			{"", 3, 0, 5, 134513480, 0, "", ""},
    86  			{"", 3, 0, 6, 134513512, 0, "", ""},
    87  			{"", 3, 0, 7, 134513532, 0, "", ""},
    88  			{"", 3, 0, 8, 134513612, 0, "", ""},
    89  			{"", 3, 0, 9, 134513996, 0, "", ""},
    90  			{"", 3, 0, 10, 134514008, 0, "", ""},
    91  			{"", 3, 0, 11, 134518268, 0, "", ""},
    92  			{"", 3, 0, 12, 134518280, 0, "", ""},
    93  			{"", 3, 0, 13, 134518284, 0, "", ""},
    94  			{"", 3, 0, 14, 134518436, 0, "", ""},
    95  			{"", 3, 0, 15, 134518444, 0, "", ""},
    96  			{"", 3, 0, 16, 134518452, 0, "", ""},
    97  			{"", 3, 0, 17, 134518456, 0, "", ""},
    98  			{"", 3, 0, 18, 134518484, 0, "", ""},
    99  			{"", 3, 0, 19, 0, 0, "", ""},
   100  			{"", 3, 0, 20, 0, 0, "", ""},
   101  			{"", 3, 0, 21, 0, 0, "", ""},
   102  			{"", 3, 0, 22, 0, 0, "", ""},
   103  			{"", 3, 0, 23, 0, 0, "", ""},
   104  			{"", 3, 0, 24, 0, 0, "", ""},
   105  			{"", 3, 0, 25, 0, 0, "", ""},
   106  			{"", 3, 0, 26, 0, 0, "", ""},
   107  			{"", 3, 0, 27, 0, 0, "", ""},
   108  			{"", 3, 0, 28, 0, 0, "", ""},
   109  			{"", 3, 0, 29, 0, 0, "", ""},
   110  			{"crt1.c", 4, 0, 65521, 0, 0, "", ""},
   111  			{"/usr/src/lib/csu/i386-elf/crti.S", 4, 0, 65521, 0, 0, "", ""},
   112  			{"<command line>", 4, 0, 65521, 0, 0, "", ""},
   113  			{"<built-in>", 4, 0, 65521, 0, 0, "", ""},
   114  			{"/usr/src/lib/csu/i386-elf/crti.S", 4, 0, 65521, 0, 0, "", ""},
   115  			{"crtstuff.c", 4, 0, 65521, 0, 0, "", ""},
   116  			{"__CTOR_LIST__", 1, 0, 14, 134518436, 0, "", ""},
   117  			{"__DTOR_LIST__", 1, 0, 15, 134518444, 0, "", ""},
   118  			{"__EH_FRAME_BEGIN__", 1, 0, 12, 134518280, 0, "", ""},
   119  			{"__JCR_LIST__", 1, 0, 16, 134518452, 0, "", ""},
   120  			{"p.0", 1, 0, 11, 134518276, 0, "", ""},
   121  			{"completed.1", 1, 0, 18, 134518484, 1, "", ""},
   122  			{"__do_global_dtors_aux", 2, 0, 8, 134513760, 0, "", ""},
   123  			{"object.2", 1, 0, 18, 134518488, 24, "", ""},
   124  			{"frame_dummy", 2, 0, 8, 134513836, 0, "", ""},
   125  			{"crtstuff.c", 4, 0, 65521, 0, 0, "", ""},
   126  			{"__CTOR_END__", 1, 0, 14, 134518440, 0, "", ""},
   127  			{"__DTOR_END__", 1, 0, 15, 134518448, 0, "", ""},
   128  			{"__FRAME_END__", 1, 0, 12, 134518280, 0, "", ""},
   129  			{"__JCR_END__", 1, 0, 16, 134518452, 0, "", ""},
   130  			{"__do_global_ctors_aux", 2, 0, 8, 134513960, 0, "", ""},
   131  			{"/usr/src/lib/csu/i386-elf/crtn.S", 4, 0, 65521, 0, 0, "", ""},
   132  			{"<command line>", 4, 0, 65521, 0, 0, "", ""},
   133  			{"<built-in>", 4, 0, 65521, 0, 0, "", ""},
   134  			{"/usr/src/lib/csu/i386-elf/crtn.S", 4, 0, 65521, 0, 0, "", ""},
   135  			{"hello.c", 4, 0, 65521, 0, 0, "", ""},
   136  			{"printf", 18, 0, 0, 0, 44, "", ""},
   137  			{"_DYNAMIC", 17, 0, 65521, 134518284, 0, "", ""},
   138  			{"__dso_handle", 17, 2, 11, 134518272, 0, "", ""},
   139  			{"_init", 18, 0, 6, 134513512, 0, "", ""},
   140  			{"environ", 17, 0, 18, 134518512, 4, "", ""},
   141  			{"__deregister_frame_info", 32, 0, 0, 0, 0, "", ""},
   142  			{"__progname", 17, 0, 11, 134518268, 4, "", ""},
   143  			{"_start", 18, 0, 8, 134513612, 145, "", ""},
   144  			{"__bss_start", 16, 0, 65521, 134518484, 0, "", ""},
   145  			{"main", 18, 0, 8, 134513912, 46, "", ""},
   146  			{"_init_tls", 18, 0, 0, 0, 5, "", ""},
   147  			{"_fini", 18, 0, 9, 134513996, 0, "", ""},
   148  			{"atexit", 18, 0, 0, 0, 43, "", ""},
   149  			{"_edata", 16, 0, 65521, 134518484, 0, "", ""},
   150  			{"_GLOBAL_OFFSET_TABLE_", 17, 0, 65521, 134518456, 0, "", ""},
   151  			{"_end", 16, 0, 65521, 134518516, 0, "", ""},
   152  			{"exit", 18, 0, 0, 0, 68, "", ""},
   153  			{"_Jv_RegisterClasses", 32, 0, 0, 0, 0, "", ""},
   154  			{"__register_frame_info", 32, 0, 0, 0, 0, "", ""},
   155  		},
   156  	},
   157  	{
   158  		"testdata/gcc-amd64-linux-exec",
   159  		FileHeader{ELFCLASS64, ELFDATA2LSB, EV_CURRENT, ELFOSABI_NONE, 0, binary.LittleEndian, ET_EXEC, EM_X86_64, 0x4003e0},
   160  		[]SectionHeader{
   161  			{"", SHT_NULL, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0},
   162  			{".interp", SHT_PROGBITS, SHF_ALLOC, 0x400200, 0x200, 0x1c, 0x0, 0x0, 0x1, 0x0, 0x1c},
   163  			{".note.ABI-tag", SHT_NOTE, SHF_ALLOC, 0x40021c, 0x21c, 0x20, 0x0, 0x0, 0x4, 0x0, 0x20},
   164  			{".hash", SHT_HASH, SHF_ALLOC, 0x400240, 0x240, 0x24, 0x5, 0x0, 0x8, 0x4, 0x24},
   165  			{".gnu.hash", SHT_LOOS + 268435446, SHF_ALLOC, 0x400268, 0x268, 0x1c, 0x5, 0x0, 0x8, 0x0, 0x1c},
   166  			{".dynsym", SHT_DYNSYM, SHF_ALLOC, 0x400288, 0x288, 0x60, 0x6, 0x1, 0x8, 0x18, 0x60},
   167  			{".dynstr", SHT_STRTAB, SHF_ALLOC, 0x4002e8, 0x2e8, 0x3d, 0x0, 0x0, 0x1, 0x0, 0x3d},
   168  			{".gnu.version", SHT_HIOS, SHF_ALLOC, 0x400326, 0x326, 0x8, 0x5, 0x0, 0x2, 0x2, 0x8},
   169  			{".gnu.version_r", SHT_LOOS + 268435454, SHF_ALLOC, 0x400330, 0x330, 0x20, 0x6, 0x1, 0x8, 0x0, 0x20},
   170  			{".rela.dyn", SHT_RELA, SHF_ALLOC, 0x400350, 0x350, 0x18, 0x5, 0x0, 0x8, 0x18, 0x18},
   171  			{".rela.plt", SHT_RELA, SHF_ALLOC, 0x400368, 0x368, 0x30, 0x5, 0xc, 0x8, 0x18, 0x30},
   172  			{".init", SHT_PROGBITS, SHF_ALLOC + SHF_EXECINSTR, 0x400398, 0x398, 0x18, 0x0, 0x0, 0x4, 0x0, 0x18},
   173  			{".plt", SHT_PROGBITS, SHF_ALLOC + SHF_EXECINSTR, 0x4003b0, 0x3b0, 0x30, 0x0, 0x0, 0x4, 0x10, 0x30},
   174  			{".text", SHT_PROGBITS, SHF_ALLOC + SHF_EXECINSTR, 0x4003e0, 0x3e0, 0x1b4, 0x0, 0x0, 0x10, 0x0, 0x1b4},
   175  			{".fini", SHT_PROGBITS, SHF_ALLOC + SHF_EXECINSTR, 0x400594, 0x594, 0xe, 0x0, 0x0, 0x4, 0x0, 0xe},
   176  			{".rodata", SHT_PROGBITS, SHF_ALLOC, 0x4005a4, 0x5a4, 0x11, 0x0, 0x0, 0x4, 0x0, 0x11},
   177  			{".eh_frame_hdr", SHT_PROGBITS, SHF_ALLOC, 0x4005b8, 0x5b8, 0x24, 0x0, 0x0, 0x4, 0x0, 0x24},
   178  			{".eh_frame", SHT_PROGBITS, SHF_ALLOC, 0x4005e0, 0x5e0, 0xa4, 0x0, 0x0, 0x8, 0x0, 0xa4},
   179  			{".ctors", SHT_PROGBITS, SHF_WRITE + SHF_ALLOC, 0x600688, 0x688, 0x10, 0x0, 0x0, 0x8, 0x0, 0x10},
   180  			{".dtors", SHT_PROGBITS, SHF_WRITE + SHF_ALLOC, 0x600698, 0x698, 0x10, 0x0, 0x0, 0x8, 0x0, 0x10},
   181  			{".jcr", SHT_PROGBITS, SHF_WRITE + SHF_ALLOC, 0x6006a8, 0x6a8, 0x8, 0x0, 0x0, 0x8, 0x0, 0x8},
   182  			{".dynamic", SHT_DYNAMIC, SHF_WRITE + SHF_ALLOC, 0x6006b0, 0x6b0, 0x1a0, 0x6, 0x0, 0x8, 0x10, 0x1a0},
   183  			{".got", SHT_PROGBITS, SHF_WRITE + SHF_ALLOC, 0x600850, 0x850, 0x8, 0x0, 0x0, 0x8, 0x8, 0x8},
   184  			{".got.plt", SHT_PROGBITS, SHF_WRITE + SHF_ALLOC, 0x600858, 0x858, 0x28, 0x0, 0x0, 0x8, 0x8, 0x28},
   185  			{".data", SHT_PROGBITS, SHF_WRITE + SHF_ALLOC, 0x600880, 0x880, 0x18, 0x0, 0x0, 0x8, 0x0, 0x18},
   186  			{".bss", SHT_NOBITS, SHF_WRITE + SHF_ALLOC, 0x600898, 0x898, 0x8, 0x0, 0x0, 0x4, 0x0, 0x8},
   187  			{".comment", SHT_PROGBITS, 0x0, 0x0, 0x898, 0x126, 0x0, 0x0, 0x1, 0x0, 0x126},
   188  			{".debug_aranges", SHT_PROGBITS, 0x0, 0x0, 0x9c0, 0x90, 0x0, 0x0, 0x10, 0x0, 0x90},
   189  			{".debug_pubnames", SHT_PROGBITS, 0x0, 0x0, 0xa50, 0x25, 0x0, 0x0, 0x1, 0x0, 0x25},
   190  			{".debug_info", SHT_PROGBITS, 0x0, 0x0, 0xa75, 0x1a7, 0x0, 0x0, 0x1, 0x0, 0x1a7},
   191  			{".debug_abbrev", SHT_PROGBITS, 0x0, 0x0, 0xc1c, 0x6f, 0x0, 0x0, 0x1, 0x0, 0x6f},
   192  			{".debug_line", SHT_PROGBITS, 0x0, 0x0, 0xc8b, 0x13f, 0x0, 0x0, 0x1, 0x0, 0x13f},
   193  			{".debug_str", SHT_PROGBITS, SHF_MERGE + SHF_STRINGS, 0x0, 0xdca, 0xb1, 0x0, 0x0, 0x1, 0x1, 0xb1},
   194  			{".debug_ranges", SHT_PROGBITS, 0x0, 0x0, 0xe80, 0x90, 0x0, 0x0, 0x10, 0x0, 0x90},
   195  			{".shstrtab", SHT_STRTAB, 0x0, 0x0, 0xf10, 0x149, 0x0, 0x0, 0x1, 0x0, 0x149},
   196  			{".symtab", SHT_SYMTAB, 0x0, 0x0, 0x19a0, 0x6f0, 0x24, 0x39, 0x8, 0x18, 0x6f0},
   197  			{".strtab", SHT_STRTAB, 0x0, 0x0, 0x2090, 0x1fc, 0x0, 0x0, 0x1, 0x0, 0x1fc},
   198  		},
   199  		[]ProgHeader{
   200  			{PT_PHDR, PF_R + PF_X, 0x40, 0x400040, 0x400040, 0x1c0, 0x1c0, 0x8},
   201  			{PT_INTERP, PF_R, 0x200, 0x400200, 0x400200, 0x1c, 0x1c, 1},
   202  			{PT_LOAD, PF_R + PF_X, 0x0, 0x400000, 0x400000, 0x684, 0x684, 0x200000},
   203  			{PT_LOAD, PF_R + PF_W, 0x688, 0x600688, 0x600688, 0x210, 0x218, 0x200000},
   204  			{PT_DYNAMIC, PF_R + PF_W, 0x6b0, 0x6006b0, 0x6006b0, 0x1a0, 0x1a0, 0x8},
   205  			{PT_NOTE, PF_R, 0x21c, 0x40021c, 0x40021c, 0x20, 0x20, 0x4},
   206  			{PT_LOOS + 0x474E550, PF_R, 0x5b8, 0x4005b8, 0x4005b8, 0x24, 0x24, 0x4},
   207  			{PT_LOOS + 0x474E551, PF_R + PF_W, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8},
   208  		},
   209  		[]string{"libc.so.6"},
   210  		[]Symbol{
   211  			{"", 3, 0, 1, 4194816, 0, "", ""},
   212  			{"", 3, 0, 2, 4194844, 0, "", ""},
   213  			{"", 3, 0, 3, 4194880, 0, "", ""},
   214  			{"", 3, 0, 4, 4194920, 0, "", ""},
   215  			{"", 3, 0, 5, 4194952, 0, "", ""},
   216  			{"", 3, 0, 6, 4195048, 0, "", ""},
   217  			{"", 3, 0, 7, 4195110, 0, "", ""},
   218  			{"", 3, 0, 8, 4195120, 0, "", ""},
   219  			{"", 3, 0, 9, 4195152, 0, "", ""},
   220  			{"", 3, 0, 10, 4195176, 0, "", ""},
   221  			{"", 3, 0, 11, 4195224, 0, "", ""},
   222  			{"", 3, 0, 12, 4195248, 0, "", ""},
   223  			{"", 3, 0, 13, 4195296, 0, "", ""},
   224  			{"", 3, 0, 14, 4195732, 0, "", ""},
   225  			{"", 3, 0, 15, 4195748, 0, "", ""},
   226  			{"", 3, 0, 16, 4195768, 0, "", ""},
   227  			{"", 3, 0, 17, 4195808, 0, "", ""},
   228  			{"", 3, 0, 18, 6293128, 0, "", ""},
   229  			{"", 3, 0, 19, 6293144, 0, "", ""},
   230  			{"", 3, 0, 20, 6293160, 0, "", ""},
   231  			{"", 3, 0, 21, 6293168, 0, "", ""},
   232  			{"", 3, 0, 22, 6293584, 0, "", ""},
   233  			{"", 3, 0, 23, 6293592, 0, "", ""},
   234  			{"", 3, 0, 24, 6293632, 0, "", ""},
   235  			{"", 3, 0, 25, 6293656, 0, "", ""},
   236  			{"", 3, 0, 26, 0, 0, "", ""},
   237  			{"", 3, 0, 27, 0, 0, "", ""},
   238  			{"", 3, 0, 28, 0, 0, "", ""},
   239  			{"", 3, 0, 29, 0, 0, "", ""},
   240  			{"", 3, 0, 30, 0, 0, "", ""},
   241  			{"", 3, 0, 31, 0, 0, "", ""},
   242  			{"", 3, 0, 32, 0, 0, "", ""},
   243  			{"", 3, 0, 33, 0, 0, "", ""},
   244  			{"init.c", 4, 0, 65521, 0, 0, "", ""},
   245  			{"initfini.c", 4, 0, 65521, 0, 0, "", ""},
   246  			{"call_gmon_start", 2, 0, 13, 4195340, 0, "", ""},
   247  			{"crtstuff.c", 4, 0, 65521, 0, 0, "", ""},
   248  			{"__CTOR_LIST__", 1, 0, 18, 6293128, 0, "", ""},
   249  			{"__DTOR_LIST__", 1, 0, 19, 6293144, 0, "", ""},
   250  			{"__JCR_LIST__", 1, 0, 20, 6293160, 0, "", ""},
   251  			{"__do_global_dtors_aux", 2, 0, 13, 4195376, 0, "", ""},
   252  			{"completed.6183", 1, 0, 25, 6293656, 1, "", ""},
   253  			{"p.6181", 1, 0, 24, 6293648, 0, "", ""},
   254  			{"frame_dummy", 2, 0, 13, 4195440, 0, "", ""},
   255  			{"crtstuff.c", 4, 0, 65521, 0, 0, "", ""},
   256  			{"__CTOR_END__", 1, 0, 18, 6293136, 0, "", ""},
   257  			{"__DTOR_END__", 1, 0, 19, 6293152, 0, "", ""},
   258  			{"__FRAME_END__", 1, 0, 17, 4195968, 0, "", ""},
   259  			{"__JCR_END__", 1, 0, 20, 6293160, 0, "", ""},
   260  			{"__do_global_ctors_aux", 2, 0, 13, 4195680, 0, "", ""},
   261  			{"initfini.c", 4, 0, 65521, 0, 0, "", ""},
   262  			{"hello.c", 4, 0, 65521, 0, 0, "", ""},
   263  			{"_GLOBAL_OFFSET_TABLE_", 1, 2, 23, 6293592, 0, "", ""},
   264  			{"__init_array_end", 0, 2, 18, 6293124, 0, "", ""},
   265  			{"__init_array_start", 0, 2, 18, 6293124, 0, "", ""},
   266  			{"_DYNAMIC", 1, 2, 21, 6293168, 0, "", ""},
   267  			{"data_start", 32, 0, 24, 6293632, 0, "", ""},
   268  			{"__libc_csu_fini", 18, 0, 13, 4195520, 2, "", ""},
   269  			{"_start", 18, 0, 13, 4195296, 0, "", ""},
   270  			{"__gmon_start__", 32, 0, 0, 0, 0, "", ""},
   271  			{"_Jv_RegisterClasses", 32, 0, 0, 0, 0, "", ""},
   272  			{"puts@@GLIBC_2.2.5", 18, 0, 0, 0, 396, "", ""},
   273  			{"_fini", 18, 0, 14, 4195732, 0, "", ""},
   274  			{"__libc_start_main@@GLIBC_2.2.5", 18, 0, 0, 0, 450, "", ""},
   275  			{"_IO_stdin_used", 17, 0, 15, 4195748, 4, "", ""},
   276  			{"__data_start", 16, 0, 24, 6293632, 0, "", ""},
   277  			{"__dso_handle", 17, 2, 24, 6293640, 0, "", ""},
   278  			{"__libc_csu_init", 18, 0, 13, 4195536, 137, "", ""},
   279  			{"__bss_start", 16, 0, 65521, 6293656, 0, "", ""},
   280  			{"_end", 16, 0, 65521, 6293664, 0, "", ""},
   281  			{"_edata", 16, 0, 65521, 6293656, 0, "", ""},
   282  			{"main", 18, 0, 13, 4195480, 27, "", ""},
   283  			{"_init", 18, 0, 11, 4195224, 0, "", ""},
   284  		},
   285  	},
   286  	{
   287  		"testdata/hello-world-core.gz",
   288  		FileHeader{ELFCLASS64, ELFDATA2LSB, EV_CURRENT, ELFOSABI_NONE, 0x0, binary.LittleEndian, ET_CORE, EM_X86_64, 0x0},
   289  		[]SectionHeader{},
   290  		[]ProgHeader{
   291  			{Type: PT_NOTE, Flags: 0x0, Off: 0x3f8, Vaddr: 0x0, Paddr: 0x0, Filesz: 0x8ac, Memsz: 0x0, Align: 0x0},
   292  			{Type: PT_LOAD, Flags: PF_X + PF_R, Off: 0x1000, Vaddr: 0x400000, Paddr: 0x0, Filesz: 0x0, Memsz: 0x1000, Align: 0x1000},
   293  			{Type: PT_LOAD, Flags: PF_R, Off: 0x1000, Vaddr: 0x401000, Paddr: 0x0, Filesz: 0x1000, Memsz: 0x1000, Align: 0x1000},
   294  			{Type: PT_LOAD, Flags: PF_W + PF_R, Off: 0x2000, Vaddr: 0x402000, Paddr: 0x0, Filesz: 0x1000, Memsz: 0x1000, Align: 0x1000},
   295  			{Type: PT_LOAD, Flags: PF_X + PF_R, Off: 0x3000, Vaddr: 0x7f54078b8000, Paddr: 0x0, Filesz: 0x0, Memsz: 0x1b5000, Align: 0x1000},
   296  			{Type: PT_LOAD, Flags: 0x0, Off: 0x3000, Vaddr: 0x7f5407a6d000, Paddr: 0x0, Filesz: 0x0, Memsz: 0x1ff000, Align: 0x1000},
   297  			{Type: PT_LOAD, Flags: PF_R, Off: 0x3000, Vaddr: 0x7f5407c6c000, Paddr: 0x0, Filesz: 0x4000, Memsz: 0x4000, Align: 0x1000},
   298  			{Type: PT_LOAD, Flags: PF_W + PF_R, Off: 0x7000, Vaddr: 0x7f5407c70000, Paddr: 0x0, Filesz: 0x2000, Memsz: 0x2000, Align: 0x1000},
   299  			{Type: PT_LOAD, Flags: PF_W + PF_R, Off: 0x9000, Vaddr: 0x7f5407c72000, Paddr: 0x0, Filesz: 0x5000, Memsz: 0x5000, Align: 0x1000},
   300  			{Type: PT_LOAD, Flags: PF_X + PF_R, Off: 0xe000, Vaddr: 0x7f5407c77000, Paddr: 0x0, Filesz: 0x0, Memsz: 0x22000, Align: 0x1000},
   301  			{Type: PT_LOAD, Flags: PF_W + PF_R, Off: 0xe000, Vaddr: 0x7f5407e81000, Paddr: 0x0, Filesz: 0x3000, Memsz: 0x3000, Align: 0x1000},
   302  			{Type: PT_LOAD, Flags: PF_W + PF_R, Off: 0x11000, Vaddr: 0x7f5407e96000, Paddr: 0x0, Filesz: 0x3000, Memsz: 0x3000, Align: 0x1000},
   303  			{Type: PT_LOAD, Flags: PF_R, Off: 0x14000, Vaddr: 0x7f5407e99000, Paddr: 0x0, Filesz: 0x1000, Memsz: 0x1000, Align: 0x1000},
   304  			{Type: PT_LOAD, Flags: PF_W + PF_R, Off: 0x15000, Vaddr: 0x7f5407e9a000, Paddr: 0x0, Filesz: 0x2000, Memsz: 0x2000, Align: 0x1000},
   305  			{Type: PT_LOAD, Flags: PF_W + PF_R, Off: 0x17000, Vaddr: 0x7fff79972000, Paddr: 0x0, Filesz: 0x23000, Memsz: 0x23000, Align: 0x1000},
   306  			{Type: PT_LOAD, Flags: PF_X + PF_R, Off: 0x3a000, Vaddr: 0x7fff799f8000, Paddr: 0x0, Filesz: 0x1000, Memsz: 0x1000, Align: 0x1000},
   307  			{Type: PT_LOAD, Flags: PF_X + PF_R, Off: 0x3b000, Vaddr: 0xffffffffff600000, Paddr: 0x0, Filesz: 0x1000, Memsz: 0x1000, Align: 0x1000},
   308  		},
   309  		nil,
   310  		nil,
   311  	},
   312  	{
   313  		"testdata/compressed-32.obj",
   314  		FileHeader{ELFCLASS32, ELFDATA2LSB, EV_CURRENT, ELFOSABI_NONE, 0x0, binary.LittleEndian, ET_REL, EM_386, 0x0},
   315  		[]SectionHeader{
   316  			{"", SHT_NULL, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0},
   317  			{".text", SHT_PROGBITS, SHF_ALLOC | SHF_EXECINSTR, 0x0, 0x34, 0x17, 0x0, 0x0, 0x1, 0x0, 0x17},
   318  			{".rel.text", SHT_REL, SHF_INFO_LINK, 0x0, 0x3dc, 0x10, 0x13, 0x1, 0x4, 0x8, 0x10},
   319  			{".data", SHT_PROGBITS, SHF_WRITE | SHF_ALLOC, 0x0, 0x4b, 0x0, 0x0, 0x0, 0x1, 0x0, 0x0},
   320  			{".bss", SHT_NOBITS, SHF_WRITE | SHF_ALLOC, 0x0, 0x4b, 0x0, 0x0, 0x0, 0x1, 0x0, 0x0},
   321  			{".rodata", SHT_PROGBITS, SHF_ALLOC, 0x0, 0x4b, 0xd, 0x0, 0x0, 0x1, 0x0, 0xd},
   322  			{".debug_info", SHT_PROGBITS, SHF_COMPRESSED, 0x0, 0x58, 0xb4, 0x0, 0x0, 0x1, 0x0, 0x84},
   323  			{".rel.debug_info", SHT_REL, SHF_INFO_LINK, 0x0, 0x3ec, 0xa0, 0x13, 0x6, 0x4, 0x8, 0xa0},
   324  			{".debug_abbrev", SHT_PROGBITS, 0x0, 0x0, 0xdc, 0x5a, 0x0, 0x0, 0x1, 0x0, 0x5a},
   325  			{".debug_aranges", SHT_PROGBITS, 0x0, 0x0, 0x136, 0x20, 0x0, 0x0, 0x1, 0x0, 0x20},
   326  			{".rel.debug_aranges", SHT_REL, SHF_INFO_LINK, 0x0, 0x48c, 0x10, 0x13, 0x9, 0x4, 0x8, 0x10},
   327  			{".debug_line", SHT_PROGBITS, 0x0, 0x0, 0x156, 0x5c, 0x0, 0x0, 0x1, 0x0, 0x5c},
   328  			{".rel.debug_line", SHT_REL, SHF_INFO_LINK, 0x0, 0x49c, 0x8, 0x13, 0xb, 0x4, 0x8, 0x8},
   329  			{".debug_str", SHT_PROGBITS, SHF_MERGE | SHF_STRINGS | SHF_COMPRESSED, 0x0, 0x1b2, 0x10f, 0x0, 0x0, 0x1, 0x1, 0xb3},
   330  			{".comment", SHT_PROGBITS, SHF_MERGE | SHF_STRINGS, 0x0, 0x265, 0x2a, 0x0, 0x0, 0x1, 0x1, 0x2a},
   331  			{".note.GNU-stack", SHT_PROGBITS, 0x0, 0x0, 0x28f, 0x0, 0x0, 0x0, 0x1, 0x0, 0x0},
   332  			{".eh_frame", SHT_PROGBITS, SHF_ALLOC, 0x0, 0x290, 0x38, 0x0, 0x0, 0x4, 0x0, 0x38},
   333  			{".rel.eh_frame", SHT_REL, SHF_INFO_LINK, 0x0, 0x4a4, 0x8, 0x13, 0x10, 0x4, 0x8, 0x8},
   334  			{".shstrtab", SHT_STRTAB, 0x0, 0x0, 0x4ac, 0xab, 0x0, 0x0, 0x1, 0x0, 0xab},
   335  			{".symtab", SHT_SYMTAB, 0x0, 0x0, 0x2c8, 0x100, 0x14, 0xe, 0x4, 0x10, 0x100},
   336  			{".strtab", SHT_STRTAB, 0x0, 0x0, 0x3c8, 0x13, 0x0, 0x0, 0x1, 0x0, 0x13},
   337  		},
   338  		[]ProgHeader{},
   339  		nil,
   340  		[]Symbol{
   341  			{"hello.c", 4, 0, 65521, 0, 0, "", ""},
   342  			{"", 3, 0, 1, 0, 0, "", ""},
   343  			{"", 3, 0, 3, 0, 0, "", ""},
   344  			{"", 3, 0, 4, 0, 0, "", ""},
   345  			{"", 3, 0, 5, 0, 0, "", ""},
   346  			{"", 3, 0, 6, 0, 0, "", ""},
   347  			{"", 3, 0, 8, 0, 0, "", ""},
   348  			{"", 3, 0, 9, 0, 0, "", ""},
   349  			{"", 3, 0, 11, 0, 0, "", ""},
   350  			{"", 3, 0, 13, 0, 0, "", ""},
   351  			{"", 3, 0, 15, 0, 0, "", ""},
   352  			{"", 3, 0, 16, 0, 0, "", ""},
   353  			{"", 3, 0, 14, 0, 0, "", ""},
   354  			{"main", 18, 0, 1, 0, 23, "", ""},
   355  			{"puts", 16, 0, 0, 0, 0, "", ""},
   356  		},
   357  	},
   358  	{
   359  		"testdata/compressed-64.obj",
   360  		FileHeader{ELFCLASS64, ELFDATA2LSB, EV_CURRENT, ELFOSABI_NONE, 0x0, binary.LittleEndian, ET_REL, EM_X86_64, 0x0},
   361  		[]SectionHeader{
   362  			{"", SHT_NULL, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0},
   363  			{".text", SHT_PROGBITS, SHF_ALLOC | SHF_EXECINSTR, 0x0, 0x40, 0x1b, 0x0, 0x0, 0x1, 0x0, 0x1b},
   364  			{".rela.text", SHT_RELA, SHF_INFO_LINK, 0x0, 0x488, 0x30, 0x13, 0x1, 0x8, 0x18, 0x30},
   365  			{".data", SHT_PROGBITS, SHF_WRITE | SHF_ALLOC, 0x0, 0x5b, 0x0, 0x0, 0x0, 0x1, 0x0, 0x0},
   366  			{".bss", SHT_NOBITS, SHF_WRITE | SHF_ALLOC, 0x0, 0x5b, 0x0, 0x0, 0x0, 0x1, 0x0, 0x0},
   367  			{".rodata", SHT_PROGBITS, SHF_ALLOC, 0x0, 0x5b, 0xd, 0x0, 0x0, 0x1, 0x0, 0xd},
   368  			{".debug_info", SHT_PROGBITS, SHF_COMPRESSED, 0x0, 0x68, 0xba, 0x0, 0x0, 0x1, 0x0, 0x72},
   369  			{".rela.debug_info", SHT_RELA, SHF_INFO_LINK, 0x0, 0x4b8, 0x1c8, 0x13, 0x6, 0x8, 0x18, 0x1c8},
   370  			{".debug_abbrev", SHT_PROGBITS, 0x0, 0x0, 0xda, 0x5c, 0x0, 0x0, 0x1, 0x0, 0x5c},
   371  			{".debug_aranges", SHT_PROGBITS, SHF_COMPRESSED, 0x0, 0x136, 0x30, 0x0, 0x0, 0x1, 0x0, 0x2f},
   372  			{".rela.debug_aranges", SHT_RELA, SHF_INFO_LINK, 0x0, 0x680, 0x30, 0x13, 0x9, 0x8, 0x18, 0x30},
   373  			{".debug_line", SHT_PROGBITS, 0x0, 0x0, 0x165, 0x60, 0x0, 0x0, 0x1, 0x0, 0x60},
   374  			{".rela.debug_line", SHT_RELA, SHF_INFO_LINK, 0x0, 0x6b0, 0x18, 0x13, 0xb, 0x8, 0x18, 0x18},
   375  			{".debug_str", SHT_PROGBITS, SHF_MERGE | SHF_STRINGS | SHF_COMPRESSED, 0x0, 0x1c5, 0x104, 0x0, 0x0, 0x1, 0x1, 0xc3},
   376  			{".comment", SHT_PROGBITS, SHF_MERGE | SHF_STRINGS, 0x0, 0x288, 0x2a, 0x0, 0x0, 0x1, 0x1, 0x2a},
   377  			{".note.GNU-stack", SHT_PROGBITS, 0x0, 0x0, 0x2b2, 0x0, 0x0, 0x0, 0x1, 0x0, 0x0},
   378  			{".eh_frame", SHT_PROGBITS, SHF_ALLOC, 0x0, 0x2b8, 0x38, 0x0, 0x0, 0x8, 0x0, 0x38},
   379  			{".rela.eh_frame", SHT_RELA, SHF_INFO_LINK, 0x0, 0x6c8, 0x18, 0x13, 0x10, 0x8, 0x18, 0x18},
   380  			{".shstrtab", SHT_STRTAB, 0x0, 0x0, 0x6e0, 0xb0, 0x0, 0x0, 0x1, 0x0, 0xb0},
   381  			{".symtab", SHT_SYMTAB, 0x0, 0x0, 0x2f0, 0x180, 0x14, 0xe, 0x8, 0x18, 0x180},
   382  			{".strtab", SHT_STRTAB, 0x0, 0x0, 0x470, 0x13, 0x0, 0x0, 0x1, 0x0, 0x13},
   383  		},
   384  		[]ProgHeader{},
   385  		nil,
   386  		[]Symbol{
   387  			{"hello.c", 4, 0, 65521, 0, 0, "", ""},
   388  			{"", 3, 0, 1, 0, 0, "", ""},
   389  			{"", 3, 0, 3, 0, 0, "", ""},
   390  			{"", 3, 0, 4, 0, 0, "", ""},
   391  			{"", 3, 0, 5, 0, 0, "", ""},
   392  			{"", 3, 0, 6, 0, 0, "", ""},
   393  			{"", 3, 0, 8, 0, 0, "", ""},
   394  			{"", 3, 0, 9, 0, 0, "", ""},
   395  			{"", 3, 0, 11, 0, 0, "", ""},
   396  			{"", 3, 0, 13, 0, 0, "", ""},
   397  			{"", 3, 0, 15, 0, 0, "", ""},
   398  			{"", 3, 0, 16, 0, 0, "", ""},
   399  			{"", 3, 0, 14, 0, 0, "", ""},
   400  			{"main", 18, 0, 1, 0, 27, "", ""},
   401  			{"puts", 16, 0, 0, 0, 0, "", ""},
   402  		},
   403  	},
   404  	{
   405  		"testdata/go-relocation-test-gcc620-sparc64.obj",
   406  		FileHeader{Class: ELFCLASS64, Data: ELFDATA2MSB, Version: EV_CURRENT, OSABI: ELFOSABI_NONE, ABIVersion: 0x0, ByteOrder: binary.BigEndian, Type: ET_REL, Machine: EM_SPARCV9, Entry: 0x0},
   407  		[]SectionHeader{
   408  			{"", SHT_NULL, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0},
   409  			{".text", SHT_PROGBITS, SHF_ALLOC + SHF_EXECINSTR, 0x0, 0x40, 0x2c, 0x0, 0x0, 0x4, 0x0, 0x2c},
   410  			{".rela.text", SHT_RELA, SHF_INFO_LINK, 0x0, 0xa58, 0x48, 0x13, 0x1, 0x8, 0x18, 0x48},
   411  			{".data", SHT_PROGBITS, SHF_WRITE + SHF_ALLOC, 0x0, 0x6c, 0x0, 0x0, 0x0, 0x1, 0x0, 0x0},
   412  			{".bss", SHT_NOBITS, SHF_WRITE + SHF_ALLOC, 0x0, 0x6c, 0x0, 0x0, 0x0, 0x1, 0x0, 0x0},
   413  			{".rodata", SHT_PROGBITS, SHF_ALLOC, 0x0, 0x70, 0xd, 0x0, 0x0, 0x8, 0x0, 0xd},
   414  			{".debug_info", SHT_PROGBITS, 0x0, 0x0, 0x7d, 0x346, 0x0, 0x0, 0x1, 0x0, 0x346},
   415  			{".rela.debug_info", SHT_RELA, SHF_INFO_LINK, 0x0, 0xaa0, 0x630, 0x13, 0x6, 0x8, 0x18, 0x630},
   416  			{".debug_abbrev", SHT_PROGBITS, 0x0, 0x0, 0x3c3, 0xf1, 0x0, 0x0, 0x1, 0x0, 0xf1},
   417  			{".debug_aranges", SHT_PROGBITS, 0x0, 0x0, 0x4b4, 0x30, 0x0, 0x0, 0x1, 0x0, 0x30},
   418  			{".rela.debug_aranges", SHT_RELA, SHF_INFO_LINK, 0x0, 0x10d0, 0x30, 0x13, 0x9, 0x8, 0x18, 0x30},
   419  			{".debug_line", SHT_PROGBITS, 0x0, 0x0, 0x4e4, 0xd3, 0x0, 0x0, 0x1, 0x0, 0xd3},
   420  			{".rela.debug_line", SHT_RELA, SHF_INFO_LINK, 0x0, 0x1100, 0x18, 0x13, 0xb, 0x8, 0x18, 0x18},
   421  			{".debug_str", SHT_PROGBITS, SHF_MERGE + SHF_STRINGS, 0x0, 0x5b7, 0x2a3, 0x0, 0x0, 0x1, 0x1, 0x2a3},
   422  			{".comment", SHT_PROGBITS, SHF_MERGE + SHF_STRINGS, 0x0, 0x85a, 0x2e, 0x0, 0x0, 0x1, 0x1, 0x2e},
   423  			{".note.GNU-stack", SHT_PROGBITS, 0x0, 0x0, 0x888, 0x0, 0x0, 0x0, 0x1, 0x0, 0x0},
   424  			{".debug_frame", SHT_PROGBITS, 0x0, 0x0, 0x888, 0x38, 0x0, 0x0, 0x8, 0x0, 0x38},
   425  			{".rela.debug_frame", SHT_RELA, SHF_INFO_LINK, 0x0, 0x1118, 0x30, 0x13, 0x10, 0x8, 0x18, 0x30},
   426  			{".shstrtab", SHT_STRTAB, 0x0, 0x0, 0x1148, 0xb3, 0x0, 0x0, 0x1, 0x0, 0xb3},
   427  			{".symtab", SHT_SYMTAB, 0x0, 0x0, 0x8c0, 0x180, 0x14, 0xe, 0x8, 0x18, 0x180},
   428  			{".strtab", SHT_STRTAB, 0x0, 0x0, 0xa40, 0x13, 0x0, 0x0, 0x1, 0x0, 0x13},
   429  		},
   430  		[]ProgHeader{},
   431  		nil,
   432  		[]Symbol{
   433  			{"hello.c", 4, 0, 65521, 0, 0, "", ""},
   434  			{"", 3, 0, 1, 0, 0, "", ""},
   435  			{"", 3, 0, 3, 0, 0, "", ""},
   436  			{"", 3, 0, 4, 0, 0, "", ""},
   437  			{"", 3, 0, 5, 0, 0, "", ""},
   438  			{"", 3, 0, 6, 0, 0, "", ""},
   439  			{"", 3, 0, 8, 0, 0, "", ""},
   440  			{"", 3, 0, 9, 0, 0, "", ""},
   441  			{"", 3, 0, 11, 0, 0, "", ""},
   442  			{"", 3, 0, 13, 0, 0, "", ""},
   443  			{"", 3, 0, 15, 0, 0, "", ""},
   444  			{"", 3, 0, 16, 0, 0, "", ""},
   445  			{"", 3, 0, 14, 0, 0, "", ""},
   446  			{"main", 18, 0, 1, 0, 44, "", ""},
   447  			{"puts", 16, 0, 0, 0, 0, "", ""},
   448  		},
   449  	},
   450  }
   451  
   452  func TestOpen(t *testing.T) {
   453  	for i := range fileTests {
   454  		tt := &fileTests[i]
   455  
   456  		var f *File
   457  		var err error
   458  		if path.Ext(tt.file) == ".gz" {
   459  			var r io.ReaderAt
   460  			if r, err = decompress(tt.file); err == nil {
   461  				f, err = NewFile(r)
   462  			}
   463  		} else {
   464  			f, err = Open(tt.file)
   465  		}
   466  		if err != nil {
   467  			t.Errorf("cannot open file %s: %v", tt.file, err)
   468  			continue
   469  		}
   470  		defer f.Close()
   471  		if f.FileHeader != tt.hdr {
   472  			t.Errorf("open %s:\n\thave %#v\n\twant %#v\n", tt.file, f.FileHeader, tt.hdr)
   473  			continue
   474  		}
   475  		for i, s := range f.Sections {
   476  			if i >= len(tt.sections) {
   477  				break
   478  			}
   479  			sh := tt.sections[i]
   480  			if s.SectionHeader != sh {
   481  				t.Errorf("open %s, section %d:\n\thave %#v\n\twant %#v\n", tt.file, i, s.SectionHeader, sh)
   482  			}
   483  		}
   484  		for i, p := range f.Progs {
   485  			if i >= len(tt.progs) {
   486  				break
   487  			}
   488  			ph := tt.progs[i]
   489  			if p.ProgHeader != ph {
   490  				t.Errorf("open %s, program %d:\n\thave %#v\n\twant %#v\n", tt.file, i, p.ProgHeader, ph)
   491  			}
   492  		}
   493  		tn := len(tt.sections)
   494  		fn := len(f.Sections)
   495  		if tn != fn {
   496  			t.Errorf("open %s: len(Sections) = %d, want %d", tt.file, fn, tn)
   497  		}
   498  		tn = len(tt.progs)
   499  		fn = len(f.Progs)
   500  		if tn != fn {
   501  			t.Errorf("open %s: len(Progs) = %d, want %d", tt.file, fn, tn)
   502  		}
   503  		tl := tt.needed
   504  		fl, err := f.ImportedLibraries()
   505  		if err != nil {
   506  			t.Error(err)
   507  		}
   508  		if !reflect.DeepEqual(tl, fl) {
   509  			t.Errorf("open %s: DT_NEEDED = %v, want %v", tt.file, tl, fl)
   510  		}
   511  		symbols, err := f.Symbols()
   512  		if tt.symbols == nil {
   513  			if !errors.Is(err, ErrNoSymbols) {
   514  				t.Errorf("open %s: Symbols() expected ErrNoSymbols, have nil", tt.file)
   515  			}
   516  			if symbols != nil {
   517  				t.Errorf("open %s: Symbols() expected no symbols, have %v", tt.file, symbols)
   518  			}
   519  		} else {
   520  			if err != nil {
   521  				t.Errorf("open %s: Symbols() unexpected error %v", tt.file, err)
   522  			}
   523  			if !slices.Equal(symbols, tt.symbols) {
   524  				t.Errorf("open %s: Symbols() = %v, want %v", tt.file, symbols, tt.symbols)
   525  			}
   526  		}
   527  	}
   528  }
   529  
   530  // elf.NewFile requires io.ReaderAt, which compress/gzip cannot
   531  // provide. Decompress the file to a bytes.Reader.
   532  func decompress(gz string) (io.ReaderAt, error) {
   533  	in, err := os.Open(gz)
   534  	if err != nil {
   535  		return nil, err
   536  	}
   537  	defer in.Close()
   538  	r, err := gzip.NewReader(in)
   539  	if err != nil {
   540  		return nil, err
   541  	}
   542  	var out bytes.Buffer
   543  	_, err = io.Copy(&out, r)
   544  	return bytes.NewReader(out.Bytes()), err
   545  }
   546  
   547  type relocationTestEntry struct {
   548  	entryNumber int
   549  	entry       *dwarf.Entry
   550  	pcRanges    [][2]uint64
   551  }
   552  
   553  type relocationTest struct {
   554  	file    string
   555  	entries []relocationTestEntry
   556  }
   557  
   558  var relocationTests = []relocationTest{
   559  	{
   560  		"testdata/go-relocation-test-gcc441-x86-64.obj",
   561  		[]relocationTestEntry{
   562  			{
   563  				entry: &dwarf.Entry{
   564  					Offset:   0xb,
   565  					Tag:      dwarf.TagCompileUnit,
   566  					Children: true,
   567  					Field: []dwarf.Field{
   568  						{Attr: dwarf.AttrProducer, Val: "GNU C 4.4.1", Class: dwarf.ClassString},
   569  						{Attr: dwarf.AttrLanguage, Val: int64(1), Class: dwarf.ClassConstant},
   570  						{Attr: dwarf.AttrName, Val: "go-relocation-test.c", Class: dwarf.ClassString},
   571  						{Attr: dwarf.AttrCompDir, Val: "/tmp", Class: dwarf.ClassString},
   572  						{Attr: dwarf.AttrLowpc, Val: uint64(0x0), Class: dwarf.ClassAddress},
   573  						{Attr: dwarf.AttrHighpc, Val: uint64(0x6), Class: dwarf.ClassAddress},
   574  						{Attr: dwarf.AttrStmtList, Val: int64(0), Class: dwarf.ClassLinePtr},
   575  					},
   576  				},
   577  				pcRanges: [][2]uint64{{0x0, 0x6}},
   578  			},
   579  		},
   580  	},
   581  	{
   582  		"testdata/go-relocation-test-gcc441-x86.obj",
   583  		[]relocationTestEntry{
   584  			{
   585  				entry: &dwarf.Entry{
   586  					Offset:   0xb,
   587  					Tag:      dwarf.TagCompileUnit,
   588  					Children: true,
   589  					Field: []dwarf.Field{
   590  						{Attr: dwarf.AttrProducer, Val: "GNU C 4.4.1", Class: dwarf.ClassString},
   591  						{Attr: dwarf.AttrLanguage, Val: int64(1), Class: dwarf.ClassConstant},
   592  						{Attr: dwarf.AttrName, Val: "t.c", Class: dwarf.ClassString},
   593  						{Attr: dwarf.AttrCompDir, Val: "/tmp", Class: dwarf.ClassString},
   594  						{Attr: dwarf.AttrLowpc, Val: uint64(0x0), Class: dwarf.ClassAddress},
   595  						{Attr: dwarf.AttrHighpc, Val: uint64(0x5), Class: dwarf.ClassAddress},
   596  						{Attr: dwarf.AttrStmtList, Val: int64(0), Class: dwarf.ClassLinePtr},
   597  					},
   598  				},
   599  				pcRanges: [][2]uint64{{0x0, 0x5}},
   600  			},
   601  		},
   602  	},
   603  	{
   604  		"testdata/go-relocation-test-gcc424-x86-64.obj",
   605  		[]relocationTestEntry{
   606  			{
   607  				entry: &dwarf.Entry{
   608  					Offset:   0xb,
   609  					Tag:      dwarf.TagCompileUnit,
   610  					Children: true,
   611  					Field: []dwarf.Field{
   612  						{Attr: dwarf.AttrProducer, Val: "GNU C 4.2.4 (Ubuntu 4.2.4-1ubuntu4)", Class: dwarf.ClassString},
   613  						{Attr: dwarf.AttrLanguage, Val: int64(1), Class: dwarf.ClassConstant},
   614  						{Attr: dwarf.AttrName, Val: "go-relocation-test-gcc424.c", Class: dwarf.ClassString},
   615  						{Attr: dwarf.AttrCompDir, Val: "/tmp", Class: dwarf.ClassString},
   616  						{Attr: dwarf.AttrLowpc, Val: uint64(0x0), Class: dwarf.ClassAddress},
   617  						{Attr: dwarf.AttrHighpc, Val: uint64(0x6), Class: dwarf.ClassAddress},
   618  						{Attr: dwarf.AttrStmtList, Val: int64(0), Class: dwarf.ClassLinePtr},
   619  					},
   620  				},
   621  				pcRanges: [][2]uint64{{0x0, 0x6}},
   622  			},
   623  		},
   624  	},
   625  	{
   626  		"testdata/go-relocation-test-gcc482-aarch64.obj",
   627  		[]relocationTestEntry{
   628  			{
   629  				entry: &dwarf.Entry{
   630  					Offset:   0xb,
   631  					Tag:      dwarf.TagCompileUnit,
   632  					Children: true,
   633  					Field: []dwarf.Field{
   634  						{Attr: dwarf.AttrProducer, Val: "GNU C 4.8.2 -g -fstack-protector", Class: dwarf.ClassString},
   635  						{Attr: dwarf.AttrLanguage, Val: int64(1), Class: dwarf.ClassConstant},
   636  						{Attr: dwarf.AttrName, Val: "go-relocation-test-gcc482.c", Class: dwarf.ClassString},
   637  						{Attr: dwarf.AttrCompDir, Val: "/tmp", Class: dwarf.ClassString},
   638  						{Attr: dwarf.AttrLowpc, Val: uint64(0x0), Class: dwarf.ClassAddress},
   639  						{Attr: dwarf.AttrHighpc, Val: int64(0x24), Class: dwarf.ClassConstant},
   640  						{Attr: dwarf.AttrStmtList, Val: int64(0), Class: dwarf.ClassLinePtr},
   641  					},
   642  				},
   643  				pcRanges: [][2]uint64{{0x0, 0x24}},
   644  			},
   645  		},
   646  	},
   647  	{
   648  		"testdata/go-relocation-test-gcc492-arm.obj",
   649  		[]relocationTestEntry{
   650  			{
   651  				entry: &dwarf.Entry{
   652  					Offset:   0xb,
   653  					Tag:      dwarf.TagCompileUnit,
   654  					Children: true,
   655  					Field: []dwarf.Field{
   656  						{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},
   657  						{Attr: dwarf.AttrLanguage, Val: int64(1), Class: dwarf.ClassConstant},
   658  						{Attr: dwarf.AttrName, Val: "go-relocation-test-gcc492.c", Class: dwarf.ClassString},
   659  						{Attr: dwarf.AttrCompDir, Val: "/root/go/src/debug/elf/testdata", Class: dwarf.ClassString},
   660  						{Attr: dwarf.AttrLowpc, Val: uint64(0x0), Class: dwarf.ClassAddress},
   661  						{Attr: dwarf.AttrHighpc, Val: int64(0x28), Class: dwarf.ClassConstant},
   662  						{Attr: dwarf.AttrStmtList, Val: int64(0), Class: dwarf.ClassLinePtr},
   663  					},
   664  				},
   665  				pcRanges: [][2]uint64{{0x0, 0x28}},
   666  			},
   667  		},
   668  	},
   669  	{
   670  		"testdata/go-relocation-test-clang-arm.obj",
   671  		[]relocationTestEntry{
   672  			{
   673  				entry: &dwarf.Entry{
   674  					Offset:   0xb,
   675  					Tag:      dwarf.TagCompileUnit,
   676  					Children: true,
   677  					Field: []dwarf.Field{
   678  						{Attr: dwarf.AttrProducer, Val: "Debian clang version 3.5.0-10 (tags/RELEASE_350/final) (based on LLVM 3.5.0)", Class: dwarf.ClassString},
   679  						{Attr: dwarf.AttrLanguage, Val: int64(12), Class: dwarf.ClassConstant},
   680  						{Attr: dwarf.AttrName, Val: "hello.c", Class: dwarf.ClassString},
   681  						{Attr: dwarf.AttrStmtList, Val: int64(0x0), Class: dwarf.ClassLinePtr},
   682  						{Attr: dwarf.AttrCompDir, Val: "/tmp", Class: dwarf.ClassString},
   683  						{Attr: dwarf.AttrLowpc, Val: uint64(0x0), Class: dwarf.ClassAddress},
   684  						{Attr: dwarf.AttrHighpc, Val: int64(0x30), Class: dwarf.ClassConstant},
   685  					},
   686  				},
   687  				pcRanges: [][2]uint64{{0x0, 0x30}},
   688  			},
   689  		},
   690  	},
   691  	{
   692  		"testdata/go-relocation-test-gcc5-ppc.obj",
   693  		[]relocationTestEntry{
   694  			{
   695  				entry: &dwarf.Entry{
   696  					Offset:   0xb,
   697  					Tag:      dwarf.TagCompileUnit,
   698  					Children: true,
   699  					Field: []dwarf.Field{
   700  						{Attr: dwarf.AttrProducer, Val: "GNU C11 5.0.0 20150116 (experimental) -Asystem=linux -Asystem=unix -Asystem=posix -g", Class: dwarf.ClassString},
   701  						{Attr: dwarf.AttrLanguage, Val: int64(12), Class: dwarf.ClassConstant},
   702  						{Attr: dwarf.AttrName, Val: "go-relocation-test-gcc5-ppc.c", Class: dwarf.ClassString},
   703  						{Attr: dwarf.AttrCompDir, Val: "/tmp", Class: dwarf.ClassString},
   704  						{Attr: dwarf.AttrLowpc, Val: uint64(0x0), Class: dwarf.ClassAddress},
   705  						{Attr: dwarf.AttrHighpc, Val: int64(0x44), Class: dwarf.ClassConstant},
   706  						{Attr: dwarf.AttrStmtList, Val: int64(0), Class: dwarf.ClassLinePtr},
   707  					},
   708  				},
   709  				pcRanges: [][2]uint64{{0x0, 0x44}},
   710  			},
   711  		},
   712  	},
   713  	{
   714  		"testdata/go-relocation-test-gcc482-ppc64le.obj",
   715  		[]relocationTestEntry{
   716  			{
   717  				entry: &dwarf.Entry{
   718  					Offset:   0xb,
   719  					Tag:      dwarf.TagCompileUnit,
   720  					Children: true,
   721  					Field: []dwarf.Field{
   722  						{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},
   723  						{Attr: dwarf.AttrLanguage, Val: int64(1), Class: dwarf.ClassConstant},
   724  						{Attr: dwarf.AttrName, Val: "go-relocation-test-gcc482-ppc64le.c", Class: dwarf.ClassString},
   725  						{Attr: dwarf.AttrCompDir, Val: "/tmp", Class: dwarf.ClassString},
   726  						{Attr: dwarf.AttrLowpc, Val: uint64(0x0), Class: dwarf.ClassAddress},
   727  						{Attr: dwarf.AttrHighpc, Val: uint64(0x24), Class: dwarf.ClassAddress},
   728  						{Attr: dwarf.AttrStmtList, Val: int64(0), Class: dwarf.ClassLinePtr},
   729  					},
   730  				},
   731  				pcRanges: [][2]uint64{{0x0, 0x24}},
   732  			},
   733  		},
   734  	},
   735  	{
   736  		"testdata/go-relocation-test-gcc492-mips64.obj",
   737  		[]relocationTestEntry{
   738  			{
   739  				entry: &dwarf.Entry{
   740  					Offset:   0xb,
   741  					Tag:      dwarf.TagCompileUnit,
   742  					Children: true,
   743  					Field: []dwarf.Field{
   744  						{Attr: dwarf.AttrProducer, Val: "GNU C 4.9.2 -meb -mabi=64 -march=mips3 -mtune=mips64 -mllsc -mno-shared -g", Class: dwarf.ClassString},
   745  						{Attr: dwarf.AttrLanguage, Val: int64(1), Class: dwarf.ClassConstant},
   746  						{Attr: dwarf.AttrName, Val: "hello.c", Class: dwarf.ClassString},
   747  						{Attr: dwarf.AttrCompDir, Val: "/tmp", Class: dwarf.ClassString},
   748  						{Attr: dwarf.AttrLowpc, Val: uint64(0x0), Class: dwarf.ClassAddress},
   749  						{Attr: dwarf.AttrHighpc, Val: int64(0x64), Class: dwarf.ClassConstant},
   750  						{Attr: dwarf.AttrStmtList, Val: int64(0), Class: dwarf.ClassLinePtr},
   751  					},
   752  				},
   753  				pcRanges: [][2]uint64{{0x0, 0x64}},
   754  			},
   755  		},
   756  	},
   757  	{
   758  		"testdata/go-relocation-test-gcc531-s390x.obj",
   759  		[]relocationTestEntry{
   760  			{
   761  				entry: &dwarf.Entry{
   762  					Offset:   0xb,
   763  					Tag:      dwarf.TagCompileUnit,
   764  					Children: true,
   765  					Field: []dwarf.Field{
   766  						{Attr: dwarf.AttrProducer, Val: "GNU C11 5.3.1 20160316 -march=zEC12 -m64 -mzarch -g -fstack-protector-strong", Class: dwarf.ClassString},
   767  						{Attr: dwarf.AttrLanguage, Val: int64(12), Class: dwarf.ClassConstant},
   768  						{Attr: dwarf.AttrName, Val: "hello.c", Class: dwarf.ClassString},
   769  						{Attr: dwarf.AttrCompDir, Val: "/tmp", Class: dwarf.ClassString},
   770  						{Attr: dwarf.AttrLowpc, Val: uint64(0x0), Class: dwarf.ClassAddress},
   771  						{Attr: dwarf.AttrHighpc, Val: int64(0x3a), Class: dwarf.ClassConstant},
   772  						{Attr: dwarf.AttrStmtList, Val: int64(0), Class: dwarf.ClassLinePtr},
   773  					},
   774  				},
   775  				pcRanges: [][2]uint64{{0x0, 0x3a}},
   776  			},
   777  		},
   778  	},
   779  	{
   780  		"testdata/go-relocation-test-gcc620-sparc64.obj",
   781  		[]relocationTestEntry{
   782  			{
   783  				entry: &dwarf.Entry{
   784  					Offset:   0xb,
   785  					Tag:      dwarf.TagCompileUnit,
   786  					Children: true,
   787  					Field: []dwarf.Field{
   788  						{Attr: dwarf.AttrProducer, Val: "GNU C11 6.2.0 20160914 -mcpu=v9 -g -fstack-protector-strong", Class: dwarf.ClassString},
   789  						{Attr: dwarf.AttrLanguage, Val: int64(12), Class: dwarf.ClassConstant},
   790  						{Attr: dwarf.AttrName, Val: "hello.c", Class: dwarf.ClassString},
   791  						{Attr: dwarf.AttrCompDir, Val: "/tmp", Class: dwarf.ClassString},
   792  						{Attr: dwarf.AttrLowpc, Val: uint64(0x0), Class: dwarf.ClassAddress},
   793  						{Attr: dwarf.AttrHighpc, Val: int64(0x2c), Class: dwarf.ClassConstant},
   794  						{Attr: dwarf.AttrStmtList, Val: int64(0), Class: dwarf.ClassLinePtr},
   795  					},
   796  				},
   797  				pcRanges: [][2]uint64{{0x0, 0x2c}},
   798  			},
   799  		},
   800  	},
   801  	{
   802  		"testdata/go-relocation-test-gcc492-mipsle.obj",
   803  		[]relocationTestEntry{
   804  			{
   805  				entry: &dwarf.Entry{
   806  					Offset:   0xb,
   807  					Tag:      dwarf.TagCompileUnit,
   808  					Children: true,
   809  					Field: []dwarf.Field{
   810  						{Attr: dwarf.AttrProducer, Val: "GNU C 4.9.2 -mel -march=mips2 -mtune=mips32 -mllsc -mno-shared -mabi=32 -g", Class: dwarf.ClassString},
   811  						{Attr: dwarf.AttrLanguage, Val: int64(1), Class: dwarf.ClassConstant},
   812  						{Attr: dwarf.AttrName, Val: "hello.c", Class: dwarf.ClassString},
   813  						{Attr: dwarf.AttrCompDir, Val: "/tmp", Class: dwarf.ClassString},
   814  						{Attr: dwarf.AttrLowpc, Val: uint64(0x0), Class: dwarf.ClassAddress},
   815  						{Attr: dwarf.AttrHighpc, Val: int64(0x58), Class: dwarf.ClassConstant},
   816  						{Attr: dwarf.AttrStmtList, Val: int64(0), Class: dwarf.ClassLinePtr},
   817  					},
   818  				},
   819  				pcRanges: [][2]uint64{{0x0, 0x58}},
   820  			},
   821  		},
   822  	},
   823  	{
   824  		"testdata/go-relocation-test-gcc540-mips.obj",
   825  		[]relocationTestEntry{
   826  			{
   827  				entry: &dwarf.Entry{
   828  					Offset:   0xb,
   829  					Tag:      dwarf.TagCompileUnit,
   830  					Children: true,
   831  					Field: []dwarf.Field{
   832  						{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},
   833  						{Attr: dwarf.AttrLanguage, Val: int64(12), Class: dwarf.ClassConstant},
   834  						{Attr: dwarf.AttrName, Val: "hello.c", Class: dwarf.ClassString},
   835  						{Attr: dwarf.AttrCompDir, Val: "/tmp", Class: dwarf.ClassString},
   836  						{Attr: dwarf.AttrLowpc, Val: uint64(0x0), Class: dwarf.ClassAddress},
   837  						{Attr: dwarf.AttrHighpc, Val: uint64(0x5c), Class: dwarf.ClassAddress},
   838  						{Attr: dwarf.AttrStmtList, Val: int64(0), Class: dwarf.ClassLinePtr},
   839  					},
   840  				},
   841  				pcRanges: [][2]uint64{{0x0, 0x5c}},
   842  			},
   843  		},
   844  	},
   845  	{
   846  		"testdata/go-relocation-test-gcc493-mips64le.obj",
   847  		[]relocationTestEntry{
   848  			{
   849  				entry: &dwarf.Entry{
   850  					Offset:   0xb,
   851  					Tag:      dwarf.TagCompileUnit,
   852  					Children: true,
   853  					Field: []dwarf.Field{
   854  						{Attr: dwarf.AttrProducer, Val: "GNU C 4.9.3 -mel -mabi=64 -mllsc -mno-shared -g -fstack-protector-strong", Class: dwarf.ClassString},
   855  						{Attr: dwarf.AttrLanguage, Val: int64(1), Class: dwarf.ClassConstant},
   856  						{Attr: dwarf.AttrName, Val: "hello.c", Class: dwarf.ClassString},
   857  						{Attr: dwarf.AttrCompDir, Val: "/tmp", Class: dwarf.ClassString},
   858  						{Attr: dwarf.AttrLowpc, Val: uint64(0x0), Class: dwarf.ClassAddress},
   859  						{Attr: dwarf.AttrHighpc, Val: int64(0x64), Class: dwarf.ClassConstant},
   860  						{Attr: dwarf.AttrStmtList, Val: int64(0), Class: dwarf.ClassLinePtr},
   861  					},
   862  				},
   863  				pcRanges: [][2]uint64{{0x0, 0x64}},
   864  			},
   865  		},
   866  	},
   867  	{
   868  		"testdata/go-relocation-test-gcc720-riscv64.obj",
   869  		[]relocationTestEntry{
   870  			{
   871  				entry: &dwarf.Entry{
   872  					Offset:   0xb,
   873  					Tag:      dwarf.TagCompileUnit,
   874  					Children: true,
   875  					Field: []dwarf.Field{
   876  						{Attr: dwarf.AttrProducer, Val: "GNU C11 7.2.0 -march=rv64imafdc -mabi=lp64d -g -gdwarf-2", Class: dwarf.ClassString},
   877  						{Attr: dwarf.AttrLanguage, Val: int64(12), Class: dwarf.ClassConstant},
   878  						{Attr: dwarf.AttrName, Val: "hello.c", Class: dwarf.ClassString},
   879  						{Attr: dwarf.AttrCompDir, Val: "/tmp", Class: dwarf.ClassString},
   880  						{Attr: dwarf.AttrLowpc, Val: uint64(0x0), Class: dwarf.ClassAddress},
   881  						{Attr: dwarf.AttrHighpc, Val: uint64(0x2c), Class: dwarf.ClassAddress},
   882  						{Attr: dwarf.AttrStmtList, Val: int64(0), Class: dwarf.ClassLinePtr},
   883  					},
   884  				},
   885  				pcRanges: [][2]uint64{{0x0, 0x2c}},
   886  			},
   887  		},
   888  	},
   889  	{
   890  		"testdata/go-relocation-test-clang-x86.obj",
   891  		[]relocationTestEntry{
   892  			{
   893  				entry: &dwarf.Entry{
   894  					Offset:   0xb,
   895  					Tag:      dwarf.TagCompileUnit,
   896  					Children: true,
   897  					Field: []dwarf.Field{
   898  						{Attr: dwarf.AttrProducer, Val: "clang version google3-trunk (trunk r209387)", Class: dwarf.ClassString},
   899  						{Attr: dwarf.AttrLanguage, Val: int64(12), Class: dwarf.ClassConstant},
   900  						{Attr: dwarf.AttrName, Val: "go-relocation-test-clang.c", Class: dwarf.ClassString},
   901  						{Attr: dwarf.AttrStmtList, Val: int64(0), Class: dwarf.ClassLinePtr},
   902  						{Attr: dwarf.AttrCompDir, Val: "/tmp", Class: dwarf.ClassString},
   903  					},
   904  				},
   905  			},
   906  		},
   907  	},
   908  	{
   909  		"testdata/gcc-amd64-openbsd-debug-with-rela.obj",
   910  		[]relocationTestEntry{
   911  			{
   912  				entryNumber: 203,
   913  				entry: &dwarf.Entry{
   914  					Offset:   0xc62,
   915  					Tag:      dwarf.TagMember,
   916  					Children: false,
   917  					Field: []dwarf.Field{
   918  						{Attr: dwarf.AttrName, Val: "it_interval", Class: dwarf.ClassString},
   919  						{Attr: dwarf.AttrDeclFile, Val: int64(7), Class: dwarf.ClassConstant},
   920  						{Attr: dwarf.AttrDeclLine, Val: int64(236), Class: dwarf.ClassConstant},
   921  						{Attr: dwarf.AttrType, Val: dwarf.Offset(0xb7f), Class: dwarf.ClassReference},
   922  						{Attr: dwarf.AttrDataMemberLoc, Val: []byte{0x23, 0x0}, Class: dwarf.ClassExprLoc},
   923  					},
   924  				},
   925  			},
   926  			{
   927  				entryNumber: 204,
   928  				entry: &dwarf.Entry{
   929  					Offset:   0xc70,
   930  					Tag:      dwarf.TagMember,
   931  					Children: false,
   932  					Field: []dwarf.Field{
   933  						{Attr: dwarf.AttrName, Val: "it_value", Class: dwarf.ClassString},
   934  						{Attr: dwarf.AttrDeclFile, Val: int64(7), Class: dwarf.ClassConstant},
   935  						{Attr: dwarf.AttrDeclLine, Val: int64(237), Class: dwarf.ClassConstant},
   936  						{Attr: dwarf.AttrType, Val: dwarf.Offset(0xb7f), Class: dwarf.ClassReference},
   937  						{Attr: dwarf.AttrDataMemberLoc, Val: []byte{0x23, 0x10}, Class: dwarf.ClassExprLoc},
   938  					},
   939  				},
   940  			},
   941  		},
   942  	},
   943  	{
   944  		"testdata/go-relocation-test-gcc930-ranges-no-rela-x86-64",
   945  		[]relocationTestEntry{
   946  			{
   947  				entry: &dwarf.Entry{
   948  					Offset:   0xb,
   949  					Tag:      dwarf.TagCompileUnit,
   950  					Children: true,
   951  					Field: []dwarf.Field{
   952  						{Attr: dwarf.AttrProducer, Val: "GNU C17 9.3.0 -mtune=generic -march=x86-64 -g -fno-asynchronous-unwind-tables", Class: dwarf.ClassString},
   953  						{Attr: dwarf.AttrLanguage, Val: int64(12), Class: dwarf.ClassConstant},
   954  						{Attr: dwarf.AttrName, Val: "multiple-code-sections.c", Class: dwarf.ClassString},
   955  						{Attr: dwarf.AttrCompDir, Val: "/tmp", Class: dwarf.ClassString},
   956  						{Attr: dwarf.AttrRanges, Val: int64(0), Class: dwarf.ClassRangeListPtr},
   957  						{Attr: dwarf.AttrLowpc, Val: uint64(0), Class: dwarf.ClassAddress},
   958  						{Attr: dwarf.AttrStmtList, Val: int64(0), Class: dwarf.ClassLinePtr},
   959  					},
   960  				},
   961  				pcRanges: [][2]uint64{
   962  					{0x765, 0x777},
   963  					{0x7e1, 0x7ec},
   964  				},
   965  			},
   966  		},
   967  	},
   968  	{
   969  		"testdata/go-relocation-test-gcc930-ranges-with-rela-x86-64",
   970  		[]relocationTestEntry{
   971  			{
   972  				entry: &dwarf.Entry{
   973  					Offset:   0xb,
   974  					Tag:      dwarf.TagCompileUnit,
   975  					Children: true,
   976  					Field: []dwarf.Field{
   977  						{Attr: dwarf.AttrProducer, Val: "GNU C17 9.3.0 -mtune=generic -march=x86-64 -g -fno-asynchronous-unwind-tables", Class: dwarf.ClassString},
   978  						{Attr: dwarf.AttrLanguage, Val: int64(12), Class: dwarf.ClassConstant},
   979  						{Attr: dwarf.AttrName, Val: "multiple-code-sections.c", Class: dwarf.ClassString},
   980  						{Attr: dwarf.AttrCompDir, Val: "/tmp", Class: dwarf.ClassString},
   981  						{Attr: dwarf.AttrRanges, Val: int64(0), Class: dwarf.ClassRangeListPtr},
   982  						{Attr: dwarf.AttrLowpc, Val: uint64(0), Class: dwarf.ClassAddress},
   983  						{Attr: dwarf.AttrStmtList, Val: int64(0), Class: dwarf.ClassLinePtr},
   984  					},
   985  				},
   986  				pcRanges: [][2]uint64{
   987  					{0x765, 0x777},
   988  					{0x7e1, 0x7ec},
   989  				},
   990  			},
   991  		},
   992  	},
   993  }
   994  
   995  func TestDWARFRelocations(t *testing.T) {
   996  	for _, test := range relocationTests {
   997  		test := test
   998  		t.Run(test.file, func(t *testing.T) {
   999  			t.Parallel()
  1000  			f, err := Open(test.file)
  1001  			if err != nil {
  1002  				t.Fatal(err)
  1003  			}
  1004  			dwarf, err := f.DWARF()
  1005  			if err != nil {
  1006  				t.Fatal(err)
  1007  			}
  1008  			reader := dwarf.Reader()
  1009  			idx := 0
  1010  			for _, testEntry := range test.entries {
  1011  				if testEntry.entryNumber < idx {
  1012  					t.Fatalf("internal test error: %d < %d", testEntry.entryNumber, idx)
  1013  				}
  1014  				for ; idx < testEntry.entryNumber; idx++ {
  1015  					entry, err := reader.Next()
  1016  					if entry == nil || err != nil {
  1017  						t.Fatalf("Failed to skip to entry %d: %v", testEntry.entryNumber, err)
  1018  					}
  1019  				}
  1020  				entry, err := reader.Next()
  1021  				idx++
  1022  				if err != nil {
  1023  					t.Fatal(err)
  1024  				}
  1025  				if !reflect.DeepEqual(testEntry.entry, entry) {
  1026  					t.Errorf("entry %d mismatch: got:%#v want:%#v", testEntry.entryNumber, entry, testEntry.entry)
  1027  				}
  1028  				pcRanges, err := dwarf.Ranges(entry)
  1029  				if err != nil {
  1030  					t.Fatal(err)
  1031  				}
  1032  				if !reflect.DeepEqual(testEntry.pcRanges, pcRanges) {
  1033  					t.Errorf("entry %d: PC range mismatch: got:%#v want:%#v", testEntry.entryNumber, pcRanges, testEntry.pcRanges)
  1034  				}
  1035  			}
  1036  		})
  1037  	}
  1038  }
  1039  
  1040  func TestCompressedDWARF(t *testing.T) {
  1041  	// Test file built with GCC 4.8.4 and as 2.24 using:
  1042  	// gcc -Wa,--compress-debug-sections -g -c -o zdebug-test-gcc484-x86-64.obj hello.c
  1043  	f, err := Open("testdata/zdebug-test-gcc484-x86-64.obj")
  1044  	if err != nil {
  1045  		t.Fatal(err)
  1046  	}
  1047  	dwarf, err := f.DWARF()
  1048  	if err != nil {
  1049  		t.Fatal(err)
  1050  	}
  1051  	reader := dwarf.Reader()
  1052  	n := 0
  1053  	for {
  1054  		entry, err := reader.Next()
  1055  		if err != nil {
  1056  			t.Fatal(err)
  1057  		}
  1058  		if entry == nil {
  1059  			break
  1060  		}
  1061  		n++
  1062  	}
  1063  	if n != 18 {
  1064  		t.Fatalf("want %d DWARF entries, got %d", 18, n)
  1065  	}
  1066  }
  1067  
  1068  func TestCompressedSection(t *testing.T) {
  1069  	// Test files built with gcc -g -S hello.c and assembled with
  1070  	// --compress-debug-sections=zlib-gabi.
  1071  	f, err := Open("testdata/compressed-64.obj")
  1072  	if err != nil {
  1073  		t.Fatal(err)
  1074  	}
  1075  	sec := f.Section(".debug_info")
  1076  	wantData := []byte{
  1077  		182, 0, 0, 0, 4, 0, 0, 0, 0, 0, 8, 1, 0, 0, 0, 0,
  1078  		1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  1079  		0, 27, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 8, 7,
  1080  		0, 0, 0, 0, 2, 1, 8, 0, 0, 0, 0, 2, 2, 7, 0, 0,
  1081  		0, 0, 2, 4, 7, 0, 0, 0, 0, 2, 1, 6, 0, 0, 0, 0,
  1082  		2, 2, 5, 0, 0, 0, 0, 3, 4, 5, 105, 110, 116, 0, 2, 8,
  1083  		5, 0, 0, 0, 0, 2, 8, 7, 0, 0, 0, 0, 4, 8, 114, 0,
  1084  		0, 0, 2, 1, 6, 0, 0, 0, 0, 5, 0, 0, 0, 0, 1, 4,
  1085  		0, 0, 0, 0, 0, 0, 0, 0, 27, 0, 0, 0, 0, 0, 0, 0,
  1086  		1, 156, 179, 0, 0, 0, 6, 0, 0, 0, 0, 1, 4, 87, 0, 0,
  1087  		0, 2, 145, 108, 6, 0, 0, 0, 0, 1, 4, 179, 0, 0, 0, 2,
  1088  		145, 96, 0, 4, 8, 108, 0, 0, 0, 0,
  1089  	}
  1090  
  1091  	// Test Data method.
  1092  	b, err := sec.Data()
  1093  	if err != nil {
  1094  		t.Fatal(err)
  1095  	}
  1096  	if !bytes.Equal(wantData, b) {
  1097  		t.Fatalf("want data %x, got %x", wantData, b)
  1098  	}
  1099  
  1100  	// Test Open method and seeking.
  1101  	buf, have, count := make([]byte, len(b)), make([]bool, len(b)), 0
  1102  	sf := sec.Open()
  1103  	if got, err := sf.Seek(0, io.SeekEnd); got != int64(len(b)) || err != nil {
  1104  		t.Fatalf("want seek end %d, got %d error %v", len(b), got, err)
  1105  	}
  1106  	if n, err := sf.Read(buf); n != 0 || err != io.EOF {
  1107  		t.Fatalf("want EOF with 0 bytes, got %v with %d bytes", err, n)
  1108  	}
  1109  	pos := int64(len(buf))
  1110  	for count < len(buf) {
  1111  		// Construct random seek arguments.
  1112  		whence := rand.Intn(3)
  1113  		target := rand.Int63n(int64(len(buf)))
  1114  		var offset int64
  1115  		switch whence {
  1116  		case io.SeekStart:
  1117  			offset = target
  1118  		case io.SeekCurrent:
  1119  			offset = target - pos
  1120  		case io.SeekEnd:
  1121  			offset = target - int64(len(buf))
  1122  		}
  1123  		pos, err = sf.Seek(offset, whence)
  1124  		if err != nil {
  1125  			t.Fatal(err)
  1126  		}
  1127  		if pos != target {
  1128  			t.Fatalf("want position %d, got %d", target, pos)
  1129  		}
  1130  
  1131  		// Read data from the new position.
  1132  		end := pos + 16
  1133  		if end > int64(len(buf)) {
  1134  			end = int64(len(buf))
  1135  		}
  1136  		n, err := io.ReadFull(sf, buf[pos:end])
  1137  		if err != nil {
  1138  			t.Fatal(err)
  1139  		}
  1140  		for i := 0; i < n; i++ {
  1141  			if !have[pos] {
  1142  				have[pos] = true
  1143  				count++
  1144  			}
  1145  			pos++
  1146  		}
  1147  	}
  1148  	if !bytes.Equal(wantData, buf) {
  1149  		t.Fatalf("want data %x, got %x", wantData, buf)
  1150  	}
  1151  }
  1152  
  1153  func TestNoSectionOverlaps(t *testing.T) {
  1154  	// Ensure cmd/link outputs sections without overlaps.
  1155  	switch runtime.GOOS {
  1156  	case "aix", "android", "darwin", "ios", "js", "plan9", "windows", "wasip1":
  1157  		t.Skipf("cmd/link doesn't produce ELF binaries on %s", runtime.GOOS)
  1158  	}
  1159  	_ = net.ResolveIPAddr // force dynamic linkage
  1160  	f, err := Open(os.Args[0])
  1161  	if err != nil {
  1162  		t.Error(err)
  1163  		return
  1164  	}
  1165  	for i, si := range f.Sections {
  1166  		sih := si.SectionHeader
  1167  		if sih.Type == SHT_NOBITS {
  1168  			continue
  1169  		}
  1170  		// checking for overlap in file
  1171  		for j, sj := range f.Sections {
  1172  			sjh := sj.SectionHeader
  1173  			if i == j || sjh.Type == SHT_NOBITS || sih.Offset == sjh.Offset && sih.FileSize == 0 {
  1174  				continue
  1175  			}
  1176  			if sih.Offset >= sjh.Offset && sih.Offset < sjh.Offset+sjh.FileSize {
  1177  				t.Errorf("ld produced ELF with section offset %s within %s: 0x%x <= 0x%x..0x%x < 0x%x",
  1178  					sih.Name, sjh.Name, sjh.Offset, sih.Offset, sih.Offset+sih.FileSize, sjh.Offset+sjh.FileSize)
  1179  			}
  1180  		}
  1181  
  1182  		if sih.Flags&SHF_ALLOC == 0 {
  1183  			continue
  1184  		}
  1185  
  1186  		// checking for overlap in address space
  1187  		for j, sj := range f.Sections {
  1188  			sjh := sj.SectionHeader
  1189  			if i == j || sjh.Flags&SHF_ALLOC == 0 || sjh.Type == SHT_NOBITS ||
  1190  				sih.Addr == sjh.Addr && sih.Size == 0 {
  1191  				continue
  1192  			}
  1193  			if sih.Addr >= sjh.Addr && sih.Addr < sjh.Addr+sjh.Size {
  1194  				t.Errorf("ld produced ELF with section address %s within %s: 0x%x <= 0x%x..0x%x < 0x%x",
  1195  					sih.Name, sjh.Name, sjh.Addr, sih.Addr, sih.Addr+sih.Size, sjh.Addr+sjh.Size)
  1196  			}
  1197  		}
  1198  	}
  1199  }
  1200  
  1201  func TestNobitsSection(t *testing.T) {
  1202  	const testdata = "testdata/gcc-amd64-linux-exec"
  1203  	f, err := Open(testdata)
  1204  	if err != nil {
  1205  		t.Fatalf("could not read %s: %v", testdata, err)
  1206  	}
  1207  	defer f.Close()
  1208  
  1209  	wantError := "unexpected read from SHT_NOBITS section"
  1210  	bss := f.Section(".bss")
  1211  
  1212  	_, err = bss.Data()
  1213  	if err == nil || err.Error() != wantError {
  1214  		t.Fatalf("bss.Data() got error %q, want error %q", err, wantError)
  1215  	}
  1216  
  1217  	r := bss.Open()
  1218  	p := make([]byte, 1)
  1219  	_, err = r.Read(p)
  1220  	if err == nil || err.Error() != wantError {
  1221  		t.Fatalf("r.Read(p) got error %q, want error %q", err, wantError)
  1222  	}
  1223  }
  1224  
  1225  // TestLargeNumberOfSections tests the case that a file has greater than or
  1226  // equal to 65280 (0xff00) sections.
  1227  func TestLargeNumberOfSections(t *testing.T) {
  1228  	// A file with >= 0xff00 sections is too big, so we will construct it on the
  1229  	// fly. The original file "y.o" is generated by these commands:
  1230  	// 1. generate "y.c":
  1231  	//   for i in `seq 1 65288`; do
  1232  	//     printf -v x "%04x" i;
  1233  	//     echo "int var_$x __attribute__((section(\"section_$x\"))) = $i;"
  1234  	//   done > y.c
  1235  	// 2. compile: gcc -c y.c -m32
  1236  	//
  1237  	// $readelf -h y.o
  1238  	// ELF Header:
  1239  	//   Magic:   7f 45 4c 46 01 01 01 00 00 00 00 00 00 00 00 00
  1240  	//   Class:                             ELF32
  1241  	//   Data:                              2's complement, little endian
  1242  	//   Version:                           1 (current)
  1243  	//   OS/ABI:                            UNIX - System V
  1244  	//   ABI Version:                       0
  1245  	//   Type:                              REL (Relocatable file)
  1246  	//   Machine:                           Intel 80386
  1247  	//   Version:                           0x1
  1248  	//   Entry point address:               0x0
  1249  	//   Start of program headers:          0 (bytes into file)
  1250  	//   Start of section headers:          3003468 (bytes into file)
  1251  	//   Flags:                             0x0
  1252  	//   Size of this header:               52 (bytes)
  1253  	//   Size of program headers:           0 (bytes)
  1254  	//   Number of program headers:         0
  1255  	//   Size of section headers:           40 (bytes)
  1256  	//   Number of section headers:         0 (65298)
  1257  	//   Section header string table index: 65535 (65297)
  1258  	//
  1259  	// $readelf -S y.o
  1260  	// There are 65298 section headers, starting at offset 0x2dd44c:
  1261  	// Section Headers:
  1262  	//   [Nr]    Name              Type            Addr     Off    Size   ES Flg Lk Inf Al
  1263  	//   [    0]                   NULL            00000000 000000 00ff12 00     65297   0  0
  1264  	//   [    1] .text             PROGBITS        00000000 000034 000000 00  AX  0   0  1
  1265  	//   [    2] .data             PROGBITS        00000000 000034 000000 00  WA  0   0  1
  1266  	//   [    3] .bss              NOBITS          00000000 000034 000000 00  WA  0   0  1
  1267  	//   [    4] section_0001      PROGBITS        00000000 000034 000004 00  WA  0   0  4
  1268  	//   [    5] section_0002      PROGBITS        00000000 000038 000004 00  WA  0   0  4
  1269  	//   [ section_0003 ~ section_ff06 truncated ]
  1270  	//   [65290] section_ff07      PROGBITS        00000000 03fc4c 000004 00  WA  0   0  4
  1271  	//   [65291] section_ff08      PROGBITS        00000000 03fc50 000004 00  WA  0   0  4
  1272  	//   [65292] .comment          PROGBITS        00000000 03fc54 000027 01  MS  0   0  1
  1273  	//   [65293] .note.GNU-stack   PROGBITS        00000000 03fc7b 000000 00      0   0  1
  1274  	//   [65294] .symtab           SYMTAB          00000000 03fc7c 0ff0a0 10     65296   2  4
  1275  	//   [65295] .symtab_shndx     SYMTAB SECTION  00000000 13ed1c 03fc28 04     65294   0  4
  1276  	//   [65296] .strtab           STRTAB          00000000 17e944 08f74d 00      0   0  1
  1277  	//   [65297] .shstrtab         STRTAB          00000000 20e091 0cf3bb 00      0   0  1
  1278  
  1279  	var buf bytes.Buffer
  1280  
  1281  	{
  1282  		buf.Grow(0x55AF1C) // 3003468 + 40 * 65298
  1283  
  1284  		h := Header32{
  1285  			Ident:     [16]byte{0x7F, 'E', 'L', 'F', 0x01, 0x01, 0x01},
  1286  			Type:      1,
  1287  			Machine:   3,
  1288  			Version:   1,
  1289  			Shoff:     0x2DD44C,
  1290  			Ehsize:    0x34,
  1291  			Shentsize: 0x28,
  1292  			Shnum:     0,
  1293  			Shstrndx:  0xFFFF,
  1294  		}
  1295  		binary.Write(&buf, binary.LittleEndian, h)
  1296  
  1297  		// Zero out sections [1]~[65294].
  1298  		buf.Write(bytes.Repeat([]byte{0}, 0x13ED1C-binary.Size(h)))
  1299  
  1300  		// Write section [65295]. Section [65295] are all zeros except for the
  1301  		// last 48 bytes.
  1302  		buf.Write(bytes.Repeat([]byte{0}, 0x03FC28-12*4))
  1303  		for i := 0; i < 12; i++ {
  1304  			binary.Write(&buf, binary.LittleEndian, uint32(0xFF00|i))
  1305  		}
  1306  
  1307  		// Write section [65296].
  1308  		buf.Write([]byte{0})
  1309  		buf.Write([]byte("y.c\x00"))
  1310  		for i := 1; i <= 65288; i++ {
  1311  			// var_0001 ~ var_ff08
  1312  			name := fmt.Sprintf("var_%04x", i)
  1313  			buf.Write([]byte(name))
  1314  			buf.Write([]byte{0})
  1315  		}
  1316  
  1317  		// Write section [65297].
  1318  		buf.Write([]byte{0})
  1319  		buf.Write([]byte(".symtab\x00"))
  1320  		buf.Write([]byte(".strtab\x00"))
  1321  		buf.Write([]byte(".shstrtab\x00"))
  1322  		buf.Write([]byte(".text\x00"))
  1323  		buf.Write([]byte(".data\x00"))
  1324  		buf.Write([]byte(".bss\x00"))
  1325  		for i := 1; i <= 65288; i++ {
  1326  			// s_0001 ~ s_ff08
  1327  			name := fmt.Sprintf("section_%04x", i)
  1328  			buf.Write([]byte(name))
  1329  			buf.Write([]byte{0})
  1330  		}
  1331  		buf.Write([]byte(".comment\x00"))
  1332  		buf.Write([]byte(".note.GNU-stack\x00"))
  1333  		buf.Write([]byte(".symtab_shndx\x00"))
  1334  
  1335  		// Write section header table.
  1336  		// NULL
  1337  		binary.Write(&buf, binary.LittleEndian, Section32{Name: 0, Size: 0xFF12, Link: 0xFF11})
  1338  		// .text
  1339  		binary.Write(&buf, binary.LittleEndian, Section32{
  1340  			Name:      0x1B,
  1341  			Type:      uint32(SHT_PROGBITS),
  1342  			Flags:     uint32(SHF_ALLOC | SHF_EXECINSTR),
  1343  			Off:       0x34,
  1344  			Addralign: 0x01,
  1345  		})
  1346  		// .data
  1347  		binary.Write(&buf, binary.LittleEndian, Section32{
  1348  			Name:      0x21,
  1349  			Type:      uint32(SHT_PROGBITS),
  1350  			Flags:     uint32(SHF_WRITE | SHF_ALLOC),
  1351  			Off:       0x34,
  1352  			Addralign: 0x01,
  1353  		})
  1354  		// .bss
  1355  		binary.Write(&buf, binary.LittleEndian, Section32{
  1356  			Name:      0x27,
  1357  			Type:      uint32(SHT_NOBITS),
  1358  			Flags:     uint32(SHF_WRITE | SHF_ALLOC),
  1359  			Off:       0x34,
  1360  			Addralign: 0x01,
  1361  		})
  1362  		// s_1 ~ s_65537
  1363  		for i := 0; i < 65288; i++ {
  1364  			s := Section32{
  1365  				Name:      uint32(0x2C + i*13),
  1366  				Type:      uint32(SHT_PROGBITS),
  1367  				Flags:     uint32(SHF_WRITE | SHF_ALLOC),
  1368  				Off:       uint32(0x34 + i*4),
  1369  				Size:      0x04,
  1370  				Addralign: 0x04,
  1371  			}
  1372  			binary.Write(&buf, binary.LittleEndian, s)
  1373  		}
  1374  		// .comment
  1375  		binary.Write(&buf, binary.LittleEndian, Section32{
  1376  			Name:      0x0CF394,
  1377  			Type:      uint32(SHT_PROGBITS),
  1378  			Flags:     uint32(SHF_MERGE | SHF_STRINGS),
  1379  			Off:       0x03FC54,
  1380  			Size:      0x27,
  1381  			Addralign: 0x01,
  1382  			Entsize:   0x01,
  1383  		})
  1384  		// .note.GNU-stack
  1385  		binary.Write(&buf, binary.LittleEndian, Section32{
  1386  			Name:      0x0CF39D,
  1387  			Type:      uint32(SHT_PROGBITS),
  1388  			Off:       0x03FC7B,
  1389  			Addralign: 0x01,
  1390  		})
  1391  		// .symtab
  1392  		binary.Write(&buf, binary.LittleEndian, Section32{
  1393  			Name:      0x01,
  1394  			Type:      uint32(SHT_SYMTAB),
  1395  			Off:       0x03FC7C,
  1396  			Size:      0x0FF0A0,
  1397  			Link:      0xFF10,
  1398  			Info:      0x02,
  1399  			Addralign: 0x04,
  1400  			Entsize:   0x10,
  1401  		})
  1402  		// .symtab_shndx
  1403  		binary.Write(&buf, binary.LittleEndian, Section32{
  1404  			Name:      0x0CF3AD,
  1405  			Type:      uint32(SHT_SYMTAB_SHNDX),
  1406  			Off:       0x13ED1C,
  1407  			Size:      0x03FC28,
  1408  			Link:      0xFF0E,
  1409  			Addralign: 0x04,
  1410  			Entsize:   0x04,
  1411  		})
  1412  		// .strtab
  1413  		binary.Write(&buf, binary.LittleEndian, Section32{
  1414  			Name:      0x09,
  1415  			Type:      uint32(SHT_STRTAB),
  1416  			Off:       0x17E944,
  1417  			Size:      0x08F74D,
  1418  			Addralign: 0x01,
  1419  		})
  1420  		// .shstrtab
  1421  		binary.Write(&buf, binary.LittleEndian, Section32{
  1422  			Name:      0x11,
  1423  			Type:      uint32(SHT_STRTAB),
  1424  			Off:       0x20E091,
  1425  			Size:      0x0CF3BB,
  1426  			Addralign: 0x01,
  1427  		})
  1428  	}
  1429  
  1430  	data := buf.Bytes()
  1431  
  1432  	f, err := NewFile(bytes.NewReader(data))
  1433  	if err != nil {
  1434  		t.Errorf("cannot create file from data: %v", err)
  1435  	}
  1436  	defer f.Close()
  1437  
  1438  	wantFileHeader := FileHeader{
  1439  		Class:     ELFCLASS32,
  1440  		Data:      ELFDATA2LSB,
  1441  		Version:   EV_CURRENT,
  1442  		OSABI:     ELFOSABI_NONE,
  1443  		ByteOrder: binary.LittleEndian,
  1444  		Type:      ET_REL,
  1445  		Machine:   EM_386,
  1446  	}
  1447  	if f.FileHeader != wantFileHeader {
  1448  		t.Errorf("\nhave %#v\nwant %#v\n", f.FileHeader, wantFileHeader)
  1449  	}
  1450  
  1451  	wantSectionNum := 65298
  1452  	if len(f.Sections) != wantSectionNum {
  1453  		t.Errorf("len(Sections) = %d, want %d", len(f.Sections), wantSectionNum)
  1454  	}
  1455  
  1456  	wantSectionHeader := SectionHeader{
  1457  		Name:      "section_0007",
  1458  		Type:      SHT_PROGBITS,
  1459  		Flags:     SHF_WRITE + SHF_ALLOC,
  1460  		Offset:    0x4c,
  1461  		Size:      0x4,
  1462  		Addralign: 0x4,
  1463  		FileSize:  0x4,
  1464  	}
  1465  	if f.Sections[10].SectionHeader != wantSectionHeader {
  1466  		t.Errorf("\nhave %#v\nwant %#v\n", f.Sections[10].SectionHeader, wantSectionHeader)
  1467  	}
  1468  }
  1469  
  1470  func TestIssue10996(t *testing.T) {
  1471  	data := []byte("\u007fELF\x02\x01\x010000000000000" +
  1472  		"\x010000000000000000000" +
  1473  		"\x00\x00\x00\x00\x00\x00\x00\x0000000000\x00\x00\x00\x00" +
  1474  		"0000")
  1475  	_, err := NewFile(bytes.NewReader(data))
  1476  	if err == nil {
  1477  		t.Fatalf("opening invalid ELF file unexpectedly succeeded")
  1478  	}
  1479  }
  1480  
  1481  func TestDynValue(t *testing.T) {
  1482  	const testdata = "testdata/gcc-amd64-linux-exec"
  1483  	f, err := Open(testdata)
  1484  	if err != nil {
  1485  		t.Fatalf("could not read %s: %v", testdata, err)
  1486  	}
  1487  	defer f.Close()
  1488  
  1489  	vals, err := f.DynValue(DT_VERNEEDNUM)
  1490  	if err != nil {
  1491  		t.Fatalf("DynValue(DT_VERNEEDNUM): got unexpected error %v", err)
  1492  	}
  1493  
  1494  	if len(vals) != 1 || vals[0] != 1 {
  1495  		t.Errorf("DynValue(DT_VERNEEDNUM): got %v, want [1]", vals)
  1496  	}
  1497  }
  1498  
  1499  func TestIssue59208(t *testing.T) {
  1500  	// corrupted dwarf data should raise invalid dwarf data instead of invalid zlib
  1501  	const orig = "testdata/compressed-64.obj"
  1502  	f, err := Open(orig)
  1503  	if err != nil {
  1504  		t.Fatal(err)
  1505  	}
  1506  	sec := f.Section(".debug_info")
  1507  
  1508  	data, err := os.ReadFile(orig)
  1509  	if err != nil {
  1510  		t.Fatal(err)
  1511  	}
  1512  
  1513  	dn := make([]byte, len(data))
  1514  	zoffset := sec.Offset + uint64(sec.compressionOffset)
  1515  	copy(dn, data[:zoffset])
  1516  
  1517  	ozd, err := sec.Data()
  1518  	if err != nil {
  1519  		t.Fatal(err)
  1520  	}
  1521  	buf := bytes.NewBuffer(nil)
  1522  	wr := zlib.NewWriter(buf)
  1523  	// corrupt origin data same as COMPRESS_ZLIB
  1524  	copy(ozd, []byte{1, 0, 0, 0})
  1525  	wr.Write(ozd)
  1526  	wr.Close()
  1527  
  1528  	copy(dn[zoffset:], buf.Bytes())
  1529  	copy(dn[sec.Offset+sec.FileSize:], data[sec.Offset+sec.FileSize:])
  1530  
  1531  	nf, err := NewFile(bytes.NewReader(dn))
  1532  	if err != nil {
  1533  		t.Error(err)
  1534  	}
  1535  
  1536  	const want = "decoding dwarf section info"
  1537  	_, err = nf.DWARF()
  1538  	if err == nil || !strings.Contains(err.Error(), want) {
  1539  		t.Errorf("DWARF = %v; want %q", err, want)
  1540  	}
  1541  }
  1542  
  1543  func BenchmarkSymbols64(b *testing.B) {
  1544  	const testdata = "testdata/gcc-amd64-linux-exec"
  1545  	f, err := Open(testdata)
  1546  	if err != nil {
  1547  		b.Fatalf("could not read %s: %v", testdata, err)
  1548  	}
  1549  	defer f.Close()
  1550  	b.ResetTimer()
  1551  	for i := 0; i < b.N; i++ {
  1552  		symbols, err := f.Symbols()
  1553  		if err != nil {
  1554  			b.Fatalf("Symbols(): got unexpected error %v", err)
  1555  		}
  1556  		if len(symbols) != 73 {
  1557  			b.Errorf("\nhave %d symbols\nwant %d symbols\n", len(symbols), 73)
  1558  		}
  1559  	}
  1560  }
  1561  
  1562  func BenchmarkSymbols32(b *testing.B) {
  1563  	const testdata = "testdata/gcc-386-freebsd-exec"
  1564  	f, err := Open(testdata)
  1565  	if err != nil {
  1566  		b.Fatalf("could not read %s: %v", testdata, err)
  1567  	}
  1568  	defer f.Close()
  1569  	b.ResetTimer()
  1570  	for i := 0; i < b.N; i++ {
  1571  		symbols, err := f.Symbols()
  1572  		if err != nil {
  1573  			b.Fatalf("Symbols(): got unexpected error %v", err)
  1574  		}
  1575  		if len(symbols) != 74 {
  1576  			b.Errorf("\nhave %d symbols\nwant %d symbols\n", len(symbols), 74)
  1577  		}
  1578  	}
  1579  }
  1580  

View as plain text