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, false, 0, 1, 134512852, 0, "", ""},
    82  			{"", 3, 0, false, 0, 2, 134512876, 0, "", ""},
    83  			{"", 3, 0, false, 0, 3, 134513020, 0, "", ""},
    84  			{"", 3, 0, false, 0, 4, 134513292, 0, "", ""},
    85  			{"", 3, 0, false, 0, 5, 134513480, 0, "", ""},
    86  			{"", 3, 0, false, 0, 6, 134513512, 0, "", ""},
    87  			{"", 3, 0, false, 0, 7, 134513532, 0, "", ""},
    88  			{"", 3, 0, false, 0, 8, 134513612, 0, "", ""},
    89  			{"", 3, 0, false, 0, 9, 134513996, 0, "", ""},
    90  			{"", 3, 0, false, 0, 10, 134514008, 0, "", ""},
    91  			{"", 3, 0, false, 0, 11, 134518268, 0, "", ""},
    92  			{"", 3, 0, false, 0, 12, 134518280, 0, "", ""},
    93  			{"", 3, 0, false, 0, 13, 134518284, 0, "", ""},
    94  			{"", 3, 0, false, 0, 14, 134518436, 0, "", ""},
    95  			{"", 3, 0, false, 0, 15, 134518444, 0, "", ""},
    96  			{"", 3, 0, false, 0, 16, 134518452, 0, "", ""},
    97  			{"", 3, 0, false, 0, 17, 134518456, 0, "", ""},
    98  			{"", 3, 0, false, 0, 18, 134518484, 0, "", ""},
    99  			{"", 3, 0, false, 0, 19, 0, 0, "", ""},
   100  			{"", 3, 0, false, 0, 20, 0, 0, "", ""},
   101  			{"", 3, 0, false, 0, 21, 0, 0, "", ""},
   102  			{"", 3, 0, false, 0, 22, 0, 0, "", ""},
   103  			{"", 3, 0, false, 0, 23, 0, 0, "", ""},
   104  			{"", 3, 0, false, 0, 24, 0, 0, "", ""},
   105  			{"", 3, 0, false, 0, 25, 0, 0, "", ""},
   106  			{"", 3, 0, false, 0, 26, 0, 0, "", ""},
   107  			{"", 3, 0, false, 0, 27, 0, 0, "", ""},
   108  			{"", 3, 0, false, 0, 28, 0, 0, "", ""},
   109  			{"", 3, 0, false, 0, 29, 0, 0, "", ""},
   110  			{"crt1.c", 4, 0, false, 0, 65521, 0, 0, "", ""},
   111  			{"/usr/src/lib/csu/i386-elf/crti.S", 4, 0, false, 0, 65521, 0, 0, "", ""},
   112  			{"<command line>", 4, 0, false, 0, 65521, 0, 0, "", ""},
   113  			{"<built-in>", 4, 0, false, 0, 65521, 0, 0, "", ""},
   114  			{"/usr/src/lib/csu/i386-elf/crti.S", 4, 0, false, 0, 65521, 0, 0, "", ""},
   115  			{"crtstuff.c", 4, 0, false, 0, 65521, 0, 0, "", ""},
   116  			{"__CTOR_LIST__", 1, 0, false, 0, 14, 134518436, 0, "", ""},
   117  			{"__DTOR_LIST__", 1, 0, false, 0, 15, 134518444, 0, "", ""},
   118  			{"__EH_FRAME_BEGIN__", 1, 0, false, 0, 12, 134518280, 0, "", ""},
   119  			{"__JCR_LIST__", 1, 0, false, 0, 16, 134518452, 0, "", ""},
   120  			{"p.0", 1, 0, false, 0, 11, 134518276, 0, "", ""},
   121  			{"completed.1", 1, 0, false, 0, 18, 134518484, 1, "", ""},
   122  			{"__do_global_dtors_aux", 2, 0, false, 0, 8, 134513760, 0, "", ""},
   123  			{"object.2", 1, 0, false, 0, 18, 134518488, 24, "", ""},
   124  			{"frame_dummy", 2, 0, false, 0, 8, 134513836, 0, "", ""},
   125  			{"crtstuff.c", 4, 0, false, 0, 65521, 0, 0, "", ""},
   126  			{"__CTOR_END__", 1, 0, false, 0, 14, 134518440, 0, "", ""},
   127  			{"__DTOR_END__", 1, 0, false, 0, 15, 134518448, 0, "", ""},
   128  			{"__FRAME_END__", 1, 0, false, 0, 12, 134518280, 0, "", ""},
   129  			{"__JCR_END__", 1, 0, false, 0, 16, 134518452, 0, "", ""},
   130  			{"__do_global_ctors_aux", 2, 0, false, 0, 8, 134513960, 0, "", ""},
   131  			{"/usr/src/lib/csu/i386-elf/crtn.S", 4, 0, false, 0, 65521, 0, 0, "", ""},
   132  			{"<command line>", 4, 0, false, 0, 65521, 0, 0, "", ""},
   133  			{"<built-in>", 4, 0, false, 0, 65521, 0, 0, "", ""},
   134  			{"/usr/src/lib/csu/i386-elf/crtn.S", 4, 0, false, 0, 65521, 0, 0, "", ""},
   135  			{"hello.c", 4, 0, false, 0, 65521, 0, 0, "", ""},
   136  			{"printf", 18, 0, false, 0, 0, 0, 44, "", ""},
   137  			{"_DYNAMIC", 17, 0, false, 0, 65521, 134518284, 0, "", ""},
   138  			{"__dso_handle", 17, 2, false, 0, 11, 134518272, 0, "", ""},
   139  			{"_init", 18, 0, false, 0, 6, 134513512, 0, "", ""},
   140  			{"environ", 17, 0, false, 0, 18, 134518512, 4, "", ""},
   141  			{"__deregister_frame_info", 32, 0, false, 0, 0, 0, 0, "", ""},
   142  			{"__progname", 17, 0, false, 0, 11, 134518268, 4, "", ""},
   143  			{"_start", 18, 0, false, 0, 8, 134513612, 145, "", ""},
   144  			{"__bss_start", 16, 0, false, 0, 65521, 134518484, 0, "", ""},
   145  			{"main", 18, 0, false, 0, 8, 134513912, 46, "", ""},
   146  			{"_init_tls", 18, 0, false, 0, 0, 0, 5, "", ""},
   147  			{"_fini", 18, 0, false, 0, 9, 134513996, 0, "", ""},
   148  			{"atexit", 18, 0, false, 0, 0, 0, 43, "", ""},
   149  			{"_edata", 16, 0, false, 0, 65521, 134518484, 0, "", ""},
   150  			{"_GLOBAL_OFFSET_TABLE_", 17, 0, false, 0, 65521, 134518456, 0, "", ""},
   151  			{"_end", 16, 0, false, 0, 65521, 134518516, 0, "", ""},
   152  			{"exit", 18, 0, false, 0, 0, 0, 68, "", ""},
   153  			{"_Jv_RegisterClasses", 32, 0, false, 0, 0, 0, 0, "", ""},
   154  			{"__register_frame_info", 32, 0, false, 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, false, 0, 1, 4194816, 0, "", ""},
   212  			{"", 3, 0, false, 0, 2, 4194844, 0, "", ""},
   213  			{"", 3, 0, false, 0, 3, 4194880, 0, "", ""},
   214  			{"", 3, 0, false, 0, 4, 4194920, 0, "", ""},
   215  			{"", 3, 0, false, 0, 5, 4194952, 0, "", ""},
   216  			{"", 3, 0, false, 0, 6, 4195048, 0, "", ""},
   217  			{"", 3, 0, false, 0, 7, 4195110, 0, "", ""},
   218  			{"", 3, 0, false, 0, 8, 4195120, 0, "", ""},
   219  			{"", 3, 0, false, 0, 9, 4195152, 0, "", ""},
   220  			{"", 3, 0, false, 0, 10, 4195176, 0, "", ""},
   221  			{"", 3, 0, false, 0, 11, 4195224, 0, "", ""},
   222  			{"", 3, 0, false, 0, 12, 4195248, 0, "", ""},
   223  			{"", 3, 0, false, 0, 13, 4195296, 0, "", ""},
   224  			{"", 3, 0, false, 0, 14, 4195732, 0, "", ""},
   225  			{"", 3, 0, false, 0, 15, 4195748, 0, "", ""},
   226  			{"", 3, 0, false, 0, 16, 4195768, 0, "", ""},
   227  			{"", 3, 0, false, 0, 17, 4195808, 0, "", ""},
   228  			{"", 3, 0, false, 0, 18, 6293128, 0, "", ""},
   229  			{"", 3, 0, false, 0, 19, 6293144, 0, "", ""},
   230  			{"", 3, 0, false, 0, 20, 6293160, 0, "", ""},
   231  			{"", 3, 0, false, 0, 21, 6293168, 0, "", ""},
   232  			{"", 3, 0, false, 0, 22, 6293584, 0, "", ""},
   233  			{"", 3, 0, false, 0, 23, 6293592, 0, "", ""},
   234  			{"", 3, 0, false, 0, 24, 6293632, 0, "", ""},
   235  			{"", 3, 0, false, 0, 25, 6293656, 0, "", ""},
   236  			{"", 3, 0, false, 0, 26, 0, 0, "", ""},
   237  			{"", 3, 0, false, 0, 27, 0, 0, "", ""},
   238  			{"", 3, 0, false, 0, 28, 0, 0, "", ""},
   239  			{"", 3, 0, false, 0, 29, 0, 0, "", ""},
   240  			{"", 3, 0, false, 0, 30, 0, 0, "", ""},
   241  			{"", 3, 0, false, 0, 31, 0, 0, "", ""},
   242  			{"", 3, 0, false, 0, 32, 0, 0, "", ""},
   243  			{"", 3, 0, false, 0, 33, 0, 0, "", ""},
   244  			{"init.c", 4, 0, false, 0, 65521, 0, 0, "", ""},
   245  			{"initfini.c", 4, 0, false, 0, 65521, 0, 0, "", ""},
   246  			{"call_gmon_start", 2, 0, false, 0, 13, 4195340, 0, "", ""},
   247  			{"crtstuff.c", 4, 0, false, 0, 65521, 0, 0, "", ""},
   248  			{"__CTOR_LIST__", 1, 0, false, 0, 18, 6293128, 0, "", ""},
   249  			{"__DTOR_LIST__", 1, 0, false, 0, 19, 6293144, 0, "", ""},
   250  			{"__JCR_LIST__", 1, 0, false, 0, 20, 6293160, 0, "", ""},
   251  			{"__do_global_dtors_aux", 2, 0, false, 0, 13, 4195376, 0, "", ""},
   252  			{"completed.6183", 1, 0, false, 0, 25, 6293656, 1, "", ""},
   253  			{"p.6181", 1, 0, false, 0, 24, 6293648, 0, "", ""},
   254  			{"frame_dummy", 2, 0, false, 0, 13, 4195440, 0, "", ""},
   255  			{"crtstuff.c", 4, 0, false, 0, 65521, 0, 0, "", ""},
   256  			{"__CTOR_END__", 1, 0, false, 0, 18, 6293136, 0, "", ""},
   257  			{"__DTOR_END__", 1, 0, false, 0, 19, 6293152, 0, "", ""},
   258  			{"__FRAME_END__", 1, 0, false, 0, 17, 4195968, 0, "", ""},
   259  			{"__JCR_END__", 1, 0, false, 0, 20, 6293160, 0, "", ""},
   260  			{"__do_global_ctors_aux", 2, 0, false, 0, 13, 4195680, 0, "", ""},
   261  			{"initfini.c", 4, 0, false, 0, 65521, 0, 0, "", ""},
   262  			{"hello.c", 4, 0, false, 0, 65521, 0, 0, "", ""},
   263  			{"_GLOBAL_OFFSET_TABLE_", 1, 2, false, 0, 23, 6293592, 0, "", ""},
   264  			{"__init_array_end", 0, 2, false, 0, 18, 6293124, 0, "", ""},
   265  			{"__init_array_start", 0, 2, false, 0, 18, 6293124, 0, "", ""},
   266  			{"_DYNAMIC", 1, 2, false, 0, 21, 6293168, 0, "", ""},
   267  			{"data_start", 32, 0, false, 0, 24, 6293632, 0, "", ""},
   268  			{"__libc_csu_fini", 18, 0, false, 0, 13, 4195520, 2, "", ""},
   269  			{"_start", 18, 0, false, 0, 13, 4195296, 0, "", ""},
   270  			{"__gmon_start__", 32, 0, false, 0, 0, 0, 0, "", ""},
   271  			{"_Jv_RegisterClasses", 32, 0, false, 0, 0, 0, 0, "", ""},
   272  			{"puts@@GLIBC_2.2.5", 18, 0, false, 0, 0, 0, 396, "", ""},
   273  			{"_fini", 18, 0, false, 0, 14, 4195732, 0, "", ""},
   274  			{"__libc_start_main@@GLIBC_2.2.5", 18, 0, false, 0, 0, 0, 450, "", ""},
   275  			{"_IO_stdin_used", 17, 0, false, 0, 15, 4195748, 4, "", ""},
   276  			{"__data_start", 16, 0, false, 0, 24, 6293632, 0, "", ""},
   277  			{"__dso_handle", 17, 2, false, 0, 24, 6293640, 0, "", ""},
   278  			{"__libc_csu_init", 18, 0, false, 0, 13, 4195536, 137, "", ""},
   279  			{"__bss_start", 16, 0, false, 0, 65521, 6293656, 0, "", ""},
   280  			{"_end", 16, 0, false, 0, 65521, 6293664, 0, "", ""},
   281  			{"_edata", 16, 0, false, 0, 65521, 6293656, 0, "", ""},
   282  			{"main", 18, 0, false, 0, 13, 4195480, 27, "", ""},
   283  			{"_init", 18, 0, false, 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, false, 0, 65521, 0, 0, "", ""},
   342  			{"", 3, 0, false, 0, 1, 0, 0, "", ""},
   343  			{"", 3, 0, false, 0, 3, 0, 0, "", ""},
   344  			{"", 3, 0, false, 0, 4, 0, 0, "", ""},
   345  			{"", 3, 0, false, 0, 5, 0, 0, "", ""},
   346  			{"", 3, 0, false, 0, 6, 0, 0, "", ""},
   347  			{"", 3, 0, false, 0, 8, 0, 0, "", ""},
   348  			{"", 3, 0, false, 0, 9, 0, 0, "", ""},
   349  			{"", 3, 0, false, 0, 11, 0, 0, "", ""},
   350  			{"", 3, 0, false, 0, 13, 0, 0, "", ""},
   351  			{"", 3, 0, false, 0, 15, 0, 0, "", ""},
   352  			{"", 3, 0, false, 0, 16, 0, 0, "", ""},
   353  			{"", 3, 0, false, 0, 14, 0, 0, "", ""},
   354  			{"main", 18, 0, false, 0, 1, 0, 23, "", ""},
   355  			{"puts", 16, 0, false, 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, false, 0, 65521, 0, 0, "", ""},
   388  			{"", 3, 0, false, 0, 1, 0, 0, "", ""},
   389  			{"", 3, 0, false, 0, 3, 0, 0, "", ""},
   390  			{"", 3, 0, false, 0, 4, 0, 0, "", ""},
   391  			{"", 3, 0, false, 0, 5, 0, 0, "", ""},
   392  			{"", 3, 0, false, 0, 6, 0, 0, "", ""},
   393  			{"", 3, 0, false, 0, 8, 0, 0, "", ""},
   394  			{"", 3, 0, false, 0, 9, 0, 0, "", ""},
   395  			{"", 3, 0, false, 0, 11, 0, 0, "", ""},
   396  			{"", 3, 0, false, 0, 13, 0, 0, "", ""},
   397  			{"", 3, 0, false, 0, 15, 0, 0, "", ""},
   398  			{"", 3, 0, false, 0, 16, 0, 0, "", ""},
   399  			{"", 3, 0, false, 0, 14, 0, 0, "", ""},
   400  			{"main", 18, 0, false, 0, 1, 0, 27, "", ""},
   401  			{"puts", 16, 0, false, 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, false, 0, 65521, 0, 0, "", ""},
   434  			{"", 3, 0, false, 0, 1, 0, 0, "", ""},
   435  			{"", 3, 0, false, 0, 3, 0, 0, "", ""},
   436  			{"", 3, 0, false, 0, 4, 0, 0, "", ""},
   437  			{"", 3, 0, false, 0, 5, 0, 0, "", ""},
   438  			{"", 3, 0, false, 0, 6, 0, 0, "", ""},
   439  			{"", 3, 0, false, 0, 8, 0, 0, "", ""},
   440  			{"", 3, 0, false, 0, 9, 0, 0, "", ""},
   441  			{"", 3, 0, false, 0, 11, 0, 0, "", ""},
   442  			{"", 3, 0, false, 0, 13, 0, 0, "", ""},
   443  			{"", 3, 0, false, 0, 15, 0, 0, "", ""},
   444  			{"", 3, 0, false, 0, 16, 0, 0, "", ""},
   445  			{"", 3, 0, false, 0, 14, 0, 0, "", ""},
   446  			{"main", 18, 0, false, 0, 1, 0, 44, "", ""},
   447  			{"puts", 16, 0, false, 0, 0, 0, 0, "", ""},
   448  		},
   449  	},
   450  	{
   451  		"testdata/gcc-riscv64-linux-exec",
   452  		FileHeader{ELFCLASS64, ELFDATA2LSB, EV_CURRENT, ELFOSABI_NONE, 0, binary.LittleEndian, ET_EXEC, EM_RISCV, 0x10460},
   453  		[]SectionHeader{
   454  			{"", SHT_NULL, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0},
   455  			{".interp", SHT_PROGBITS, SHF_ALLOC, 0x10270, 0x270, 0x21, 0x0, 0x0, 0x1, 0x0, 0x21},
   456  			{".note.gnu.build-id", SHT_NOTE, SHF_ALLOC, 0x10294, 0x294, 0x24, 0x0, 0x0, 0x4, 0x0, 0x24},
   457  			{".note.ABI-tag", SHT_NOTE, SHF_ALLOC, 0x102b8, 0x2b8, 0x20, 0x0, 0x0, 0x4, 0x0, 0x20},
   458  			{".gnu.hash", SHT_GNU_HASH, SHF_ALLOC, 0x102d8, 0x2d8, 0x30, 0x5, 0x0, 0x8, 0x0, 0x30},
   459  			{".dynsym", SHT_DYNSYM, SHF_ALLOC, 0x10308, 0x308, 0x60, 0x6, 0x1, 0x8, 0x18, 0x60},
   460  			{".dynstr", SHT_STRTAB, SHF_ALLOC, 0x10368, 0x368, 0x4a, 0x0, 0x0, 0x1, 0x0, 0x4a},
   461  			{".gnu.version", SHT_GNU_VERSYM, SHF_ALLOC, 0x103b2, 0x3b2, 0x8, 0x5, 0x0, 0x2, 0x2, 0x8},
   462  			{".gnu.version_r", SHT_GNU_VERNEED, SHF_ALLOC, 0x103c0, 0x3c0, 0x30, 0x6, 0x1, 0x8, 0x0, 0x30},
   463  			{".rela.plt", SHT_RELA, SHF_ALLOC + SHF_INFO_LINK, 0x103f0, 0x3f0, 0x30, 0x5, 0x14, 0x8, 0x18, 0x30},
   464  			{".plt", SHT_PROGBITS, SHF_ALLOC + SHF_EXECINSTR, 0x10420, 0x420, 0x40, 0x0, 0x0, 0x10, 0x10, 0x40},
   465  			{".text", SHT_PROGBITS, SHF_ALLOC + SHF_EXECINSTR, 0x10460, 0x460, 0xd8, 0x0, 0x0, 0x4, 0x0, 0xd8},
   466  			{".rodata", SHT_PROGBITS, SHF_ALLOC, 0x10538, 0x538, 0x15, 0x0, 0x0, 0x8, 0x0, 0x15},
   467  			{".eh_frame_hdr", SHT_PROGBITS, SHF_ALLOC, 0x10550, 0x550, 0x24, 0x0, 0x0, 0x4, 0x0, 0x24},
   468  			{".eh_frame", SHT_PROGBITS, SHF_ALLOC, 0x10578, 0x578, 0x6c, 0x0, 0x0, 0x8, 0x0, 0x6c},
   469  			{".preinit_array", SHT_PREINIT_ARRAY, SHF_WRITE + SHF_ALLOC, 0x11e00, 0xe00, 0x8, 0x0, 0x0, 0x1, 0x8, 0x8},
   470  			{".init_array", SHT_INIT_ARRAY, SHF_WRITE + SHF_ALLOC, 0x11e08, 0xe08, 0x8, 0x0, 0x0, 0x8, 0x8, 0x8},
   471  			{".fini_array", SHT_FINI_ARRAY, SHF_WRITE + SHF_ALLOC, 0x11e10, 0xe10, 0x8, 0x0, 0x0, 0x8, 0x8, 0x8},
   472  			{".dynamic", SHT_DYNAMIC, SHF_WRITE + SHF_ALLOC, 0x11e18, 0xe18, 0x1d0, 0x6, 0x0, 0x8, 0x10, 0x1d0},
   473  			{".got", SHT_PROGBITS, SHF_WRITE + SHF_ALLOC, 0x11fe8, 0xfe8, 0x8, 0x0, 0x0, 0x8, 0x8, 0x8},
   474  			{".got.plt", SHT_PROGBITS, SHF_WRITE + SHF_ALLOC, 0x11ff0, 0xff0, 0x20, 0x0, 0x0, 0x8, 0x8, 0x20},
   475  			{".sdata", SHT_PROGBITS, SHF_WRITE + SHF_ALLOC, 0x12010, 0x1010, 0x8, 0x0, 0x0, 0x8, 0x0, 0x8},
   476  			{".bss", SHT_NOBITS, SHF_WRITE + SHF_ALLOC, 0x12018, 0x1018, 0x8, 0x0, 0x0, 0x1, 0x0, 0x8},
   477  			{".comment", SHT_PROGBITS, SHF_MERGE + SHF_STRINGS, 0x0, 0x1018, 0x26, 0x0, 0x0, 0x1, 0x1, 0x26},
   478  			{".riscv.attributes", SHT_RISCV_ATTRIBUTES, 0x0, 0x0, 0x103e, 0x66, 0x0, 0x0, 0x1, 0x0, 0x66},
   479  			{".shstrtab", SHT_STRTAB, 0x0, 0x0, 0x10a4, 0xff, 0x0, 0x0, 0x1, 0x0, 0xff},
   480  		},
   481  		[]ProgHeader{
   482  			{PT_PHDR, PF_R, 0x40, 0x10040, 0x10040, 0x230, 0x230, 0x8},
   483  			{PT_INTERP, PF_R, 0x270, 0x10270, 0x10270, 0x21, 0x21, 0x1},
   484  			{PT_RISCV_ATTRIBUTES, PF_R, 0x103e, 0x0, 0x0, 0x66, 0x0, 0x1},
   485  			{PT_LOAD, PF_X + PF_R, 0x0, 0x10000, 0x10000, 0x5e4, 0x5e4, 0x1000},
   486  			{PT_LOAD, PF_W + PF_R, 0xe00, 0x11e00, 0x11e00, 0x218, 0x220, 0x1000},
   487  			{PT_DYNAMIC, PF_W + PF_R, 0xe18, 0x11e18, 0x11e18, 0x1d0, 0x1d0, 0x8},
   488  			{PT_NOTE, PF_R, 0x294, 0x10294, 0x10294, 0x44, 0x44, 0x4},
   489  			{PT_GNU_EH_FRAME, PF_R, 0x550, 0x10550, 0x10550, 0x24, 0x24, 0x4},
   490  			{PT_GNU_STACK, PF_W + PF_R, 0x0, 0x0, 0x0, 0x0, 0x0, 0x10},
   491  			{PT_GNU_RELRO, PF_R, 0xe00, 0x11e00, 0x11e00, 0x200, 0x200, 0x1},
   492  		},
   493  		[]string{"libc.so.6"},
   494  		nil,
   495  	},
   496  }
   497  
   498  func TestOpen(t *testing.T) {
   499  	for i := range fileTests {
   500  		tt := &fileTests[i]
   501  
   502  		var f *File
   503  		var err error
   504  		if path.Ext(tt.file) == ".gz" {
   505  			var r io.ReaderAt
   506  			if r, err = decompress(tt.file); err == nil {
   507  				f, err = NewFile(r)
   508  			}
   509  		} else {
   510  			f, err = Open(tt.file)
   511  		}
   512  		if err != nil {
   513  			t.Errorf("cannot open file %s: %v", tt.file, err)
   514  			continue
   515  		}
   516  		defer f.Close()
   517  		if f.FileHeader != tt.hdr {
   518  			t.Errorf("open %s:\n\thave %#v\n\twant %#v\n", tt.file, f.FileHeader, tt.hdr)
   519  			continue
   520  		}
   521  		for i, s := range f.Sections {
   522  			if i >= len(tt.sections) {
   523  				break
   524  			}
   525  			sh := tt.sections[i]
   526  			if s.SectionHeader != sh {
   527  				t.Errorf("open %s, section %d:\n\thave %#v\n\twant %#v\n", tt.file, i, s.SectionHeader, sh)
   528  			}
   529  		}
   530  		for i, p := range f.Progs {
   531  			if i >= len(tt.progs) {
   532  				break
   533  			}
   534  			ph := tt.progs[i]
   535  			if p.ProgHeader != ph {
   536  				t.Errorf("open %s, program %d:\n\thave %#v\n\twant %#v\n", tt.file, i, p.ProgHeader, ph)
   537  			}
   538  		}
   539  		tn := len(tt.sections)
   540  		fn := len(f.Sections)
   541  		if tn != fn {
   542  			t.Errorf("open %s: len(Sections) = %d, want %d", tt.file, fn, tn)
   543  		}
   544  		tn = len(tt.progs)
   545  		fn = len(f.Progs)
   546  		if tn != fn {
   547  			t.Errorf("open %s: len(Progs) = %d, want %d", tt.file, fn, tn)
   548  		}
   549  		tl := tt.needed
   550  		fl, err := f.ImportedLibraries()
   551  		if err != nil {
   552  			t.Error(err)
   553  		}
   554  		if !reflect.DeepEqual(tl, fl) {
   555  			t.Errorf("open %s: DT_NEEDED = %v, want %v", tt.file, tl, fl)
   556  		}
   557  		symbols, err := f.Symbols()
   558  		if tt.symbols == nil {
   559  			if !errors.Is(err, ErrNoSymbols) {
   560  				t.Errorf("open %s: Symbols() expected ErrNoSymbols, have nil", tt.file)
   561  			}
   562  			if symbols != nil {
   563  				t.Errorf("open %s: Symbols() expected no symbols, have %v", tt.file, symbols)
   564  			}
   565  		} else {
   566  			if err != nil {
   567  				t.Errorf("open %s: Symbols() unexpected error %v", tt.file, err)
   568  			}
   569  			if !slices.Equal(symbols, tt.symbols) {
   570  				t.Errorf("open %s: Symbols() = %v, want %v", tt.file, symbols, tt.symbols)
   571  			}
   572  		}
   573  	}
   574  }
   575  
   576  // elf.NewFile requires io.ReaderAt, which compress/gzip cannot
   577  // provide. Decompress the file to a bytes.Reader.
   578  func decompress(gz string) (io.ReaderAt, error) {
   579  	in, err := os.Open(gz)
   580  	if err != nil {
   581  		return nil, err
   582  	}
   583  	defer in.Close()
   584  	r, err := gzip.NewReader(in)
   585  	if err != nil {
   586  		return nil, err
   587  	}
   588  	var out bytes.Buffer
   589  	_, err = io.Copy(&out, r)
   590  	return bytes.NewReader(out.Bytes()), err
   591  }
   592  
   593  type relocationTestEntry struct {
   594  	entryNumber int
   595  	entry       *dwarf.Entry
   596  	pcRanges    [][2]uint64
   597  }
   598  
   599  type relocationTest struct {
   600  	file    string
   601  	entries []relocationTestEntry
   602  }
   603  
   604  var relocationTests = []relocationTest{
   605  	{
   606  		"testdata/go-relocation-test-gcc441-x86-64.obj",
   607  		[]relocationTestEntry{
   608  			{
   609  				entry: &dwarf.Entry{
   610  					Offset:   0xb,
   611  					Tag:      dwarf.TagCompileUnit,
   612  					Children: true,
   613  					Field: []dwarf.Field{
   614  						{Attr: dwarf.AttrProducer, Val: "GNU C 4.4.1", Class: dwarf.ClassString},
   615  						{Attr: dwarf.AttrLanguage, Val: int64(1), Class: dwarf.ClassConstant},
   616  						{Attr: dwarf.AttrName, Val: "go-relocation-test.c", Class: dwarf.ClassString},
   617  						{Attr: dwarf.AttrCompDir, Val: "/tmp", Class: dwarf.ClassString},
   618  						{Attr: dwarf.AttrLowpc, Val: uint64(0x0), Class: dwarf.ClassAddress},
   619  						{Attr: dwarf.AttrHighpc, Val: uint64(0x6), Class: dwarf.ClassAddress},
   620  						{Attr: dwarf.AttrStmtList, Val: int64(0), Class: dwarf.ClassLinePtr},
   621  					},
   622  				},
   623  				pcRanges: [][2]uint64{{0x0, 0x6}},
   624  			},
   625  		},
   626  	},
   627  	{
   628  		"testdata/go-relocation-test-gcc441-x86.obj",
   629  		[]relocationTestEntry{
   630  			{
   631  				entry: &dwarf.Entry{
   632  					Offset:   0xb,
   633  					Tag:      dwarf.TagCompileUnit,
   634  					Children: true,
   635  					Field: []dwarf.Field{
   636  						{Attr: dwarf.AttrProducer, Val: "GNU C 4.4.1", Class: dwarf.ClassString},
   637  						{Attr: dwarf.AttrLanguage, Val: int64(1), Class: dwarf.ClassConstant},
   638  						{Attr: dwarf.AttrName, Val: "t.c", Class: dwarf.ClassString},
   639  						{Attr: dwarf.AttrCompDir, Val: "/tmp", Class: dwarf.ClassString},
   640  						{Attr: dwarf.AttrLowpc, Val: uint64(0x0), Class: dwarf.ClassAddress},
   641  						{Attr: dwarf.AttrHighpc, Val: uint64(0x5), Class: dwarf.ClassAddress},
   642  						{Attr: dwarf.AttrStmtList, Val: int64(0), Class: dwarf.ClassLinePtr},
   643  					},
   644  				},
   645  				pcRanges: [][2]uint64{{0x0, 0x5}},
   646  			},
   647  		},
   648  	},
   649  	{
   650  		"testdata/go-relocation-test-gcc424-x86-64.obj",
   651  		[]relocationTestEntry{
   652  			{
   653  				entry: &dwarf.Entry{
   654  					Offset:   0xb,
   655  					Tag:      dwarf.TagCompileUnit,
   656  					Children: true,
   657  					Field: []dwarf.Field{
   658  						{Attr: dwarf.AttrProducer, Val: "GNU C 4.2.4 (Ubuntu 4.2.4-1ubuntu4)", Class: dwarf.ClassString},
   659  						{Attr: dwarf.AttrLanguage, Val: int64(1), Class: dwarf.ClassConstant},
   660  						{Attr: dwarf.AttrName, Val: "go-relocation-test-gcc424.c", Class: dwarf.ClassString},
   661  						{Attr: dwarf.AttrCompDir, Val: "/tmp", Class: dwarf.ClassString},
   662  						{Attr: dwarf.AttrLowpc, Val: uint64(0x0), Class: dwarf.ClassAddress},
   663  						{Attr: dwarf.AttrHighpc, Val: uint64(0x6), Class: dwarf.ClassAddress},
   664  						{Attr: dwarf.AttrStmtList, Val: int64(0), Class: dwarf.ClassLinePtr},
   665  					},
   666  				},
   667  				pcRanges: [][2]uint64{{0x0, 0x6}},
   668  			},
   669  		},
   670  	},
   671  	{
   672  		"testdata/go-relocation-test-gcc482-aarch64.obj",
   673  		[]relocationTestEntry{
   674  			{
   675  				entry: &dwarf.Entry{
   676  					Offset:   0xb,
   677  					Tag:      dwarf.TagCompileUnit,
   678  					Children: true,
   679  					Field: []dwarf.Field{
   680  						{Attr: dwarf.AttrProducer, Val: "GNU C 4.8.2 -g -fstack-protector", Class: dwarf.ClassString},
   681  						{Attr: dwarf.AttrLanguage, Val: int64(1), Class: dwarf.ClassConstant},
   682  						{Attr: dwarf.AttrName, Val: "go-relocation-test-gcc482.c", Class: dwarf.ClassString},
   683  						{Attr: dwarf.AttrCompDir, Val: "/tmp", Class: dwarf.ClassString},
   684  						{Attr: dwarf.AttrLowpc, Val: uint64(0x0), Class: dwarf.ClassAddress},
   685  						{Attr: dwarf.AttrHighpc, Val: int64(0x24), Class: dwarf.ClassConstant},
   686  						{Attr: dwarf.AttrStmtList, Val: int64(0), Class: dwarf.ClassLinePtr},
   687  					},
   688  				},
   689  				pcRanges: [][2]uint64{{0x0, 0x24}},
   690  			},
   691  		},
   692  	},
   693  	{
   694  		"testdata/go-relocation-test-gcc492-arm.obj",
   695  		[]relocationTestEntry{
   696  			{
   697  				entry: &dwarf.Entry{
   698  					Offset:   0xb,
   699  					Tag:      dwarf.TagCompileUnit,
   700  					Children: true,
   701  					Field: []dwarf.Field{
   702  						{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},
   703  						{Attr: dwarf.AttrLanguage, Val: int64(1), Class: dwarf.ClassConstant},
   704  						{Attr: dwarf.AttrName, Val: "go-relocation-test-gcc492.c", Class: dwarf.ClassString},
   705  						{Attr: dwarf.AttrCompDir, Val: "/root/go/src/debug/elf/testdata", Class: dwarf.ClassString},
   706  						{Attr: dwarf.AttrLowpc, Val: uint64(0x0), Class: dwarf.ClassAddress},
   707  						{Attr: dwarf.AttrHighpc, Val: int64(0x28), Class: dwarf.ClassConstant},
   708  						{Attr: dwarf.AttrStmtList, Val: int64(0), Class: dwarf.ClassLinePtr},
   709  					},
   710  				},
   711  				pcRanges: [][2]uint64{{0x0, 0x28}},
   712  			},
   713  		},
   714  	},
   715  	{
   716  		"testdata/go-relocation-test-clang-arm.obj",
   717  		[]relocationTestEntry{
   718  			{
   719  				entry: &dwarf.Entry{
   720  					Offset:   0xb,
   721  					Tag:      dwarf.TagCompileUnit,
   722  					Children: true,
   723  					Field: []dwarf.Field{
   724  						{Attr: dwarf.AttrProducer, Val: "Debian clang version 3.5.0-10 (tags/RELEASE_350/final) (based on LLVM 3.5.0)", Class: dwarf.ClassString},
   725  						{Attr: dwarf.AttrLanguage, Val: int64(12), Class: dwarf.ClassConstant},
   726  						{Attr: dwarf.AttrName, Val: "hello.c", Class: dwarf.ClassString},
   727  						{Attr: dwarf.AttrStmtList, Val: int64(0x0), Class: dwarf.ClassLinePtr},
   728  						{Attr: dwarf.AttrCompDir, Val: "/tmp", Class: dwarf.ClassString},
   729  						{Attr: dwarf.AttrLowpc, Val: uint64(0x0), Class: dwarf.ClassAddress},
   730  						{Attr: dwarf.AttrHighpc, Val: int64(0x30), Class: dwarf.ClassConstant},
   731  					},
   732  				},
   733  				pcRanges: [][2]uint64{{0x0, 0x30}},
   734  			},
   735  		},
   736  	},
   737  	{
   738  		"testdata/go-relocation-test-gcc5-ppc.obj",
   739  		[]relocationTestEntry{
   740  			{
   741  				entry: &dwarf.Entry{
   742  					Offset:   0xb,
   743  					Tag:      dwarf.TagCompileUnit,
   744  					Children: true,
   745  					Field: []dwarf.Field{
   746  						{Attr: dwarf.AttrProducer, Val: "GNU C11 5.0.0 20150116 (experimental) -Asystem=linux -Asystem=unix -Asystem=posix -g", Class: dwarf.ClassString},
   747  						{Attr: dwarf.AttrLanguage, Val: int64(12), Class: dwarf.ClassConstant},
   748  						{Attr: dwarf.AttrName, Val: "go-relocation-test-gcc5-ppc.c", Class: dwarf.ClassString},
   749  						{Attr: dwarf.AttrCompDir, Val: "/tmp", Class: dwarf.ClassString},
   750  						{Attr: dwarf.AttrLowpc, Val: uint64(0x0), Class: dwarf.ClassAddress},
   751  						{Attr: dwarf.AttrHighpc, Val: int64(0x44), Class: dwarf.ClassConstant},
   752  						{Attr: dwarf.AttrStmtList, Val: int64(0), Class: dwarf.ClassLinePtr},
   753  					},
   754  				},
   755  				pcRanges: [][2]uint64{{0x0, 0x44}},
   756  			},
   757  		},
   758  	},
   759  	{
   760  		"testdata/go-relocation-test-gcc482-ppc64le.obj",
   761  		[]relocationTestEntry{
   762  			{
   763  				entry: &dwarf.Entry{
   764  					Offset:   0xb,
   765  					Tag:      dwarf.TagCompileUnit,
   766  					Children: true,
   767  					Field: []dwarf.Field{
   768  						{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},
   769  						{Attr: dwarf.AttrLanguage, Val: int64(1), Class: dwarf.ClassConstant},
   770  						{Attr: dwarf.AttrName, Val: "go-relocation-test-gcc482-ppc64le.c", Class: dwarf.ClassString},
   771  						{Attr: dwarf.AttrCompDir, Val: "/tmp", Class: dwarf.ClassString},
   772  						{Attr: dwarf.AttrLowpc, Val: uint64(0x0), Class: dwarf.ClassAddress},
   773  						{Attr: dwarf.AttrHighpc, Val: uint64(0x24), Class: dwarf.ClassAddress},
   774  						{Attr: dwarf.AttrStmtList, Val: int64(0), Class: dwarf.ClassLinePtr},
   775  					},
   776  				},
   777  				pcRanges: [][2]uint64{{0x0, 0x24}},
   778  			},
   779  		},
   780  	},
   781  	{
   782  		"testdata/go-relocation-test-gcc492-mips64.obj",
   783  		[]relocationTestEntry{
   784  			{
   785  				entry: &dwarf.Entry{
   786  					Offset:   0xb,
   787  					Tag:      dwarf.TagCompileUnit,
   788  					Children: true,
   789  					Field: []dwarf.Field{
   790  						{Attr: dwarf.AttrProducer, Val: "GNU C 4.9.2 -meb -mabi=64 -march=mips3 -mtune=mips64 -mllsc -mno-shared -g", Class: dwarf.ClassString},
   791  						{Attr: dwarf.AttrLanguage, Val: int64(1), Class: dwarf.ClassConstant},
   792  						{Attr: dwarf.AttrName, Val: "hello.c", Class: dwarf.ClassString},
   793  						{Attr: dwarf.AttrCompDir, Val: "/tmp", Class: dwarf.ClassString},
   794  						{Attr: dwarf.AttrLowpc, Val: uint64(0x0), Class: dwarf.ClassAddress},
   795  						{Attr: dwarf.AttrHighpc, Val: int64(0x64), Class: dwarf.ClassConstant},
   796  						{Attr: dwarf.AttrStmtList, Val: int64(0), Class: dwarf.ClassLinePtr},
   797  					},
   798  				},
   799  				pcRanges: [][2]uint64{{0x0, 0x64}},
   800  			},
   801  		},
   802  	},
   803  	{
   804  		"testdata/go-relocation-test-gcc531-s390x.obj",
   805  		[]relocationTestEntry{
   806  			{
   807  				entry: &dwarf.Entry{
   808  					Offset:   0xb,
   809  					Tag:      dwarf.TagCompileUnit,
   810  					Children: true,
   811  					Field: []dwarf.Field{
   812  						{Attr: dwarf.AttrProducer, Val: "GNU C11 5.3.1 20160316 -march=zEC12 -m64 -mzarch -g -fstack-protector-strong", Class: dwarf.ClassString},
   813  						{Attr: dwarf.AttrLanguage, Val: int64(12), Class: dwarf.ClassConstant},
   814  						{Attr: dwarf.AttrName, Val: "hello.c", Class: dwarf.ClassString},
   815  						{Attr: dwarf.AttrCompDir, Val: "/tmp", Class: dwarf.ClassString},
   816  						{Attr: dwarf.AttrLowpc, Val: uint64(0x0), Class: dwarf.ClassAddress},
   817  						{Attr: dwarf.AttrHighpc, Val: int64(0x3a), Class: dwarf.ClassConstant},
   818  						{Attr: dwarf.AttrStmtList, Val: int64(0), Class: dwarf.ClassLinePtr},
   819  					},
   820  				},
   821  				pcRanges: [][2]uint64{{0x0, 0x3a}},
   822  			},
   823  		},
   824  	},
   825  	{
   826  		"testdata/go-relocation-test-gcc620-sparc64.obj",
   827  		[]relocationTestEntry{
   828  			{
   829  				entry: &dwarf.Entry{
   830  					Offset:   0xb,
   831  					Tag:      dwarf.TagCompileUnit,
   832  					Children: true,
   833  					Field: []dwarf.Field{
   834  						{Attr: dwarf.AttrProducer, Val: "GNU C11 6.2.0 20160914 -mcpu=v9 -g -fstack-protector-strong", Class: dwarf.ClassString},
   835  						{Attr: dwarf.AttrLanguage, Val: int64(12), Class: dwarf.ClassConstant},
   836  						{Attr: dwarf.AttrName, Val: "hello.c", Class: dwarf.ClassString},
   837  						{Attr: dwarf.AttrCompDir, Val: "/tmp", Class: dwarf.ClassString},
   838  						{Attr: dwarf.AttrLowpc, Val: uint64(0x0), Class: dwarf.ClassAddress},
   839  						{Attr: dwarf.AttrHighpc, Val: int64(0x2c), Class: dwarf.ClassConstant},
   840  						{Attr: dwarf.AttrStmtList, Val: int64(0), Class: dwarf.ClassLinePtr},
   841  					},
   842  				},
   843  				pcRanges: [][2]uint64{{0x0, 0x2c}},
   844  			},
   845  		},
   846  	},
   847  	{
   848  		"testdata/go-relocation-test-gcc492-mipsle.obj",
   849  		[]relocationTestEntry{
   850  			{
   851  				entry: &dwarf.Entry{
   852  					Offset:   0xb,
   853  					Tag:      dwarf.TagCompileUnit,
   854  					Children: true,
   855  					Field: []dwarf.Field{
   856  						{Attr: dwarf.AttrProducer, Val: "GNU C 4.9.2 -mel -march=mips2 -mtune=mips32 -mllsc -mno-shared -mabi=32 -g", Class: dwarf.ClassString},
   857  						{Attr: dwarf.AttrLanguage, Val: int64(1), Class: dwarf.ClassConstant},
   858  						{Attr: dwarf.AttrName, Val: "hello.c", Class: dwarf.ClassString},
   859  						{Attr: dwarf.AttrCompDir, Val: "/tmp", Class: dwarf.ClassString},
   860  						{Attr: dwarf.AttrLowpc, Val: uint64(0x0), Class: dwarf.ClassAddress},
   861  						{Attr: dwarf.AttrHighpc, Val: int64(0x58), Class: dwarf.ClassConstant},
   862  						{Attr: dwarf.AttrStmtList, Val: int64(0), Class: dwarf.ClassLinePtr},
   863  					},
   864  				},
   865  				pcRanges: [][2]uint64{{0x0, 0x58}},
   866  			},
   867  		},
   868  	},
   869  	{
   870  		"testdata/go-relocation-test-gcc540-mips.obj",
   871  		[]relocationTestEntry{
   872  			{
   873  				entry: &dwarf.Entry{
   874  					Offset:   0xb,
   875  					Tag:      dwarf.TagCompileUnit,
   876  					Children: true,
   877  					Field: []dwarf.Field{
   878  						{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},
   879  						{Attr: dwarf.AttrLanguage, Val: int64(12), Class: dwarf.ClassConstant},
   880  						{Attr: dwarf.AttrName, Val: "hello.c", Class: dwarf.ClassString},
   881  						{Attr: dwarf.AttrCompDir, Val: "/tmp", Class: dwarf.ClassString},
   882  						{Attr: dwarf.AttrLowpc, Val: uint64(0x0), Class: dwarf.ClassAddress},
   883  						{Attr: dwarf.AttrHighpc, Val: uint64(0x5c), Class: dwarf.ClassAddress},
   884  						{Attr: dwarf.AttrStmtList, Val: int64(0), Class: dwarf.ClassLinePtr},
   885  					},
   886  				},
   887  				pcRanges: [][2]uint64{{0x0, 0x5c}},
   888  			},
   889  		},
   890  	},
   891  	{
   892  		"testdata/go-relocation-test-gcc493-mips64le.obj",
   893  		[]relocationTestEntry{
   894  			{
   895  				entry: &dwarf.Entry{
   896  					Offset:   0xb,
   897  					Tag:      dwarf.TagCompileUnit,
   898  					Children: true,
   899  					Field: []dwarf.Field{
   900  						{Attr: dwarf.AttrProducer, Val: "GNU C 4.9.3 -mel -mabi=64 -mllsc -mno-shared -g -fstack-protector-strong", Class: dwarf.ClassString},
   901  						{Attr: dwarf.AttrLanguage, Val: int64(1), Class: dwarf.ClassConstant},
   902  						{Attr: dwarf.AttrName, Val: "hello.c", Class: dwarf.ClassString},
   903  						{Attr: dwarf.AttrCompDir, Val: "/tmp", Class: dwarf.ClassString},
   904  						{Attr: dwarf.AttrLowpc, Val: uint64(0x0), Class: dwarf.ClassAddress},
   905  						{Attr: dwarf.AttrHighpc, Val: int64(0x64), Class: dwarf.ClassConstant},
   906  						{Attr: dwarf.AttrStmtList, Val: int64(0), Class: dwarf.ClassLinePtr},
   907  					},
   908  				},
   909  				pcRanges: [][2]uint64{{0x0, 0x64}},
   910  			},
   911  		},
   912  	},
   913  	{
   914  		"testdata/go-relocation-test-gcc720-riscv64.obj",
   915  		[]relocationTestEntry{
   916  			{
   917  				entry: &dwarf.Entry{
   918  					Offset:   0xb,
   919  					Tag:      dwarf.TagCompileUnit,
   920  					Children: true,
   921  					Field: []dwarf.Field{
   922  						{Attr: dwarf.AttrProducer, Val: "GNU C11 7.2.0 -march=rv64imafdc -mabi=lp64d -g -gdwarf-2", Class: dwarf.ClassString},
   923  						{Attr: dwarf.AttrLanguage, Val: int64(12), Class: dwarf.ClassConstant},
   924  						{Attr: dwarf.AttrName, Val: "hello.c", Class: dwarf.ClassString},
   925  						{Attr: dwarf.AttrCompDir, Val: "/tmp", Class: dwarf.ClassString},
   926  						{Attr: dwarf.AttrLowpc, Val: uint64(0x0), Class: dwarf.ClassAddress},
   927  						{Attr: dwarf.AttrHighpc, Val: uint64(0x2c), Class: dwarf.ClassAddress},
   928  						{Attr: dwarf.AttrStmtList, Val: int64(0), Class: dwarf.ClassLinePtr},
   929  					},
   930  				},
   931  				pcRanges: [][2]uint64{{0x0, 0x2c}},
   932  			},
   933  		},
   934  	},
   935  	{
   936  		"testdata/go-relocation-test-clang-x86.obj",
   937  		[]relocationTestEntry{
   938  			{
   939  				entry: &dwarf.Entry{
   940  					Offset:   0xb,
   941  					Tag:      dwarf.TagCompileUnit,
   942  					Children: true,
   943  					Field: []dwarf.Field{
   944  						{Attr: dwarf.AttrProducer, Val: "clang version google3-trunk (trunk r209387)", Class: dwarf.ClassString},
   945  						{Attr: dwarf.AttrLanguage, Val: int64(12), Class: dwarf.ClassConstant},
   946  						{Attr: dwarf.AttrName, Val: "go-relocation-test-clang.c", Class: dwarf.ClassString},
   947  						{Attr: dwarf.AttrStmtList, Val: int64(0), Class: dwarf.ClassLinePtr},
   948  						{Attr: dwarf.AttrCompDir, Val: "/tmp", Class: dwarf.ClassString},
   949  					},
   950  				},
   951  			},
   952  		},
   953  	},
   954  	{
   955  		"testdata/gcc-amd64-openbsd-debug-with-rela.obj",
   956  		[]relocationTestEntry{
   957  			{
   958  				entryNumber: 203,
   959  				entry: &dwarf.Entry{
   960  					Offset:   0xc62,
   961  					Tag:      dwarf.TagMember,
   962  					Children: false,
   963  					Field: []dwarf.Field{
   964  						{Attr: dwarf.AttrName, Val: "it_interval", Class: dwarf.ClassString},
   965  						{Attr: dwarf.AttrDeclFile, Val: int64(7), Class: dwarf.ClassConstant},
   966  						{Attr: dwarf.AttrDeclLine, Val: int64(236), Class: dwarf.ClassConstant},
   967  						{Attr: dwarf.AttrType, Val: dwarf.Offset(0xb7f), Class: dwarf.ClassReference},
   968  						{Attr: dwarf.AttrDataMemberLoc, Val: []byte{0x23, 0x0}, Class: dwarf.ClassExprLoc},
   969  					},
   970  				},
   971  			},
   972  			{
   973  				entryNumber: 204,
   974  				entry: &dwarf.Entry{
   975  					Offset:   0xc70,
   976  					Tag:      dwarf.TagMember,
   977  					Children: false,
   978  					Field: []dwarf.Field{
   979  						{Attr: dwarf.AttrName, Val: "it_value", Class: dwarf.ClassString},
   980  						{Attr: dwarf.AttrDeclFile, Val: int64(7), Class: dwarf.ClassConstant},
   981  						{Attr: dwarf.AttrDeclLine, Val: int64(237), Class: dwarf.ClassConstant},
   982  						{Attr: dwarf.AttrType, Val: dwarf.Offset(0xb7f), Class: dwarf.ClassReference},
   983  						{Attr: dwarf.AttrDataMemberLoc, Val: []byte{0x23, 0x10}, Class: dwarf.ClassExprLoc},
   984  					},
   985  				},
   986  			},
   987  		},
   988  	},
   989  	{
   990  		"testdata/go-relocation-test-gcc930-ranges-no-rela-x86-64",
   991  		[]relocationTestEntry{
   992  			{
   993  				entry: &dwarf.Entry{
   994  					Offset:   0xb,
   995  					Tag:      dwarf.TagCompileUnit,
   996  					Children: true,
   997  					Field: []dwarf.Field{
   998  						{Attr: dwarf.AttrProducer, Val: "GNU C17 9.3.0 -mtune=generic -march=x86-64 -g -fno-asynchronous-unwind-tables", Class: dwarf.ClassString},
   999  						{Attr: dwarf.AttrLanguage, Val: int64(12), Class: dwarf.ClassConstant},
  1000  						{Attr: dwarf.AttrName, Val: "multiple-code-sections.c", Class: dwarf.ClassString},
  1001  						{Attr: dwarf.AttrCompDir, Val: "/tmp", Class: dwarf.ClassString},
  1002  						{Attr: dwarf.AttrRanges, Val: int64(0), Class: dwarf.ClassRangeListPtr},
  1003  						{Attr: dwarf.AttrLowpc, Val: uint64(0), Class: dwarf.ClassAddress},
  1004  						{Attr: dwarf.AttrStmtList, Val: int64(0), Class: dwarf.ClassLinePtr},
  1005  					},
  1006  				},
  1007  				pcRanges: [][2]uint64{
  1008  					{0x765, 0x777},
  1009  					{0x7e1, 0x7ec},
  1010  				},
  1011  			},
  1012  		},
  1013  	},
  1014  	{
  1015  		"testdata/go-relocation-test-gcc930-ranges-with-rela-x86-64",
  1016  		[]relocationTestEntry{
  1017  			{
  1018  				entry: &dwarf.Entry{
  1019  					Offset:   0xb,
  1020  					Tag:      dwarf.TagCompileUnit,
  1021  					Children: true,
  1022  					Field: []dwarf.Field{
  1023  						{Attr: dwarf.AttrProducer, Val: "GNU C17 9.3.0 -mtune=generic -march=x86-64 -g -fno-asynchronous-unwind-tables", Class: dwarf.ClassString},
  1024  						{Attr: dwarf.AttrLanguage, Val: int64(12), Class: dwarf.ClassConstant},
  1025  						{Attr: dwarf.AttrName, Val: "multiple-code-sections.c", Class: dwarf.ClassString},
  1026  						{Attr: dwarf.AttrCompDir, Val: "/tmp", Class: dwarf.ClassString},
  1027  						{Attr: dwarf.AttrRanges, Val: int64(0), Class: dwarf.ClassRangeListPtr},
  1028  						{Attr: dwarf.AttrLowpc, Val: uint64(0), Class: dwarf.ClassAddress},
  1029  						{Attr: dwarf.AttrStmtList, Val: int64(0), Class: dwarf.ClassLinePtr},
  1030  					},
  1031  				},
  1032  				pcRanges: [][2]uint64{
  1033  					{0x765, 0x777},
  1034  					{0x7e1, 0x7ec},
  1035  				},
  1036  			},
  1037  		},
  1038  	},
  1039  }
  1040  
  1041  func TestDWARFRelocations(t *testing.T) {
  1042  	for _, test := range relocationTests {
  1043  		t.Run(test.file, func(t *testing.T) {
  1044  			t.Parallel()
  1045  			f, err := Open(test.file)
  1046  			if err != nil {
  1047  				t.Fatal(err)
  1048  			}
  1049  			dwarf, err := f.DWARF()
  1050  			if err != nil {
  1051  				t.Fatal(err)
  1052  			}
  1053  			reader := dwarf.Reader()
  1054  			idx := 0
  1055  			for _, testEntry := range test.entries {
  1056  				if testEntry.entryNumber < idx {
  1057  					t.Fatalf("internal test error: %d < %d", testEntry.entryNumber, idx)
  1058  				}
  1059  				for ; idx < testEntry.entryNumber; idx++ {
  1060  					entry, err := reader.Next()
  1061  					if entry == nil || err != nil {
  1062  						t.Fatalf("Failed to skip to entry %d: %v", testEntry.entryNumber, err)
  1063  					}
  1064  				}
  1065  				entry, err := reader.Next()
  1066  				idx++
  1067  				if err != nil {
  1068  					t.Fatal(err)
  1069  				}
  1070  				if !reflect.DeepEqual(testEntry.entry, entry) {
  1071  					t.Errorf("entry %d mismatch: got:%#v want:%#v", testEntry.entryNumber, entry, testEntry.entry)
  1072  				}
  1073  				pcRanges, err := dwarf.Ranges(entry)
  1074  				if err != nil {
  1075  					t.Fatal(err)
  1076  				}
  1077  				if !reflect.DeepEqual(testEntry.pcRanges, pcRanges) {
  1078  					t.Errorf("entry %d: PC range mismatch: got:%#v want:%#v", testEntry.entryNumber, pcRanges, testEntry.pcRanges)
  1079  				}
  1080  			}
  1081  		})
  1082  	}
  1083  }
  1084  
  1085  func TestCompressedDWARF(t *testing.T) {
  1086  	// Test file built with GCC 4.8.4 and as 2.24 using:
  1087  	// gcc -Wa,--compress-debug-sections -g -c -o zdebug-test-gcc484-x86-64.obj hello.c
  1088  	f, err := Open("testdata/zdebug-test-gcc484-x86-64.obj")
  1089  	if err != nil {
  1090  		t.Fatal(err)
  1091  	}
  1092  	dwarf, err := f.DWARF()
  1093  	if err != nil {
  1094  		t.Fatal(err)
  1095  	}
  1096  	reader := dwarf.Reader()
  1097  	n := 0
  1098  	for {
  1099  		entry, err := reader.Next()
  1100  		if err != nil {
  1101  			t.Fatal(err)
  1102  		}
  1103  		if entry == nil {
  1104  			break
  1105  		}
  1106  		n++
  1107  	}
  1108  	if n != 18 {
  1109  		t.Fatalf("want %d DWARF entries, got %d", 18, n)
  1110  	}
  1111  }
  1112  
  1113  func TestCompressedSection(t *testing.T) {
  1114  	// Test files built with gcc -g -S hello.c and assembled with
  1115  	// --compress-debug-sections=zlib-gabi.
  1116  	f, err := Open("testdata/compressed-64.obj")
  1117  	if err != nil {
  1118  		t.Fatal(err)
  1119  	}
  1120  	sec := f.Section(".debug_info")
  1121  	wantData := []byte{
  1122  		182, 0, 0, 0, 4, 0, 0, 0, 0, 0, 8, 1, 0, 0, 0, 0,
  1123  		1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  1124  		0, 27, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 8, 7,
  1125  		0, 0, 0, 0, 2, 1, 8, 0, 0, 0, 0, 2, 2, 7, 0, 0,
  1126  		0, 0, 2, 4, 7, 0, 0, 0, 0, 2, 1, 6, 0, 0, 0, 0,
  1127  		2, 2, 5, 0, 0, 0, 0, 3, 4, 5, 105, 110, 116, 0, 2, 8,
  1128  		5, 0, 0, 0, 0, 2, 8, 7, 0, 0, 0, 0, 4, 8, 114, 0,
  1129  		0, 0, 2, 1, 6, 0, 0, 0, 0, 5, 0, 0, 0, 0, 1, 4,
  1130  		0, 0, 0, 0, 0, 0, 0, 0, 27, 0, 0, 0, 0, 0, 0, 0,
  1131  		1, 156, 179, 0, 0, 0, 6, 0, 0, 0, 0, 1, 4, 87, 0, 0,
  1132  		0, 2, 145, 108, 6, 0, 0, 0, 0, 1, 4, 179, 0, 0, 0, 2,
  1133  		145, 96, 0, 4, 8, 108, 0, 0, 0, 0,
  1134  	}
  1135  
  1136  	// Test Data method.
  1137  	b, err := sec.Data()
  1138  	if err != nil {
  1139  		t.Fatal(err)
  1140  	}
  1141  	if !bytes.Equal(wantData, b) {
  1142  		t.Fatalf("want data %x, got %x", wantData, b)
  1143  	}
  1144  
  1145  	// Test Open method and seeking.
  1146  	buf, have, count := make([]byte, len(b)), make([]bool, len(b)), 0
  1147  	sf := sec.Open()
  1148  	if got, err := sf.Seek(0, io.SeekEnd); got != int64(len(b)) || err != nil {
  1149  		t.Fatalf("want seek end %d, got %d error %v", len(b), got, err)
  1150  	}
  1151  	if n, err := sf.Read(buf); n != 0 || err != io.EOF {
  1152  		t.Fatalf("want EOF with 0 bytes, got %v with %d bytes", err, n)
  1153  	}
  1154  	pos := int64(len(buf))
  1155  	for count < len(buf) {
  1156  		// Construct random seek arguments.
  1157  		whence := rand.Intn(3)
  1158  		target := rand.Int63n(int64(len(buf)))
  1159  		var offset int64
  1160  		switch whence {
  1161  		case io.SeekStart:
  1162  			offset = target
  1163  		case io.SeekCurrent:
  1164  			offset = target - pos
  1165  		case io.SeekEnd:
  1166  			offset = target - int64(len(buf))
  1167  		}
  1168  		pos, err = sf.Seek(offset, whence)
  1169  		if err != nil {
  1170  			t.Fatal(err)
  1171  		}
  1172  		if pos != target {
  1173  			t.Fatalf("want position %d, got %d", target, pos)
  1174  		}
  1175  
  1176  		// Read data from the new position.
  1177  		end := pos + 16
  1178  		if end > int64(len(buf)) {
  1179  			end = int64(len(buf))
  1180  		}
  1181  		n, err := io.ReadFull(sf, buf[pos:end])
  1182  		if err != nil {
  1183  			t.Fatal(err)
  1184  		}
  1185  		for i := 0; i < n; i++ {
  1186  			if !have[pos] {
  1187  				have[pos] = true
  1188  				count++
  1189  			}
  1190  			pos++
  1191  		}
  1192  	}
  1193  	if !bytes.Equal(wantData, buf) {
  1194  		t.Fatalf("want data %x, got %x", wantData, buf)
  1195  	}
  1196  }
  1197  
  1198  func TestNoSectionOverlaps(t *testing.T) {
  1199  	// Ensure cmd/link outputs sections without overlaps.
  1200  	switch runtime.GOOS {
  1201  	case "aix", "android", "darwin", "ios", "js", "plan9", "windows", "wasip1":
  1202  		t.Skipf("cmd/link doesn't produce ELF binaries on %s", runtime.GOOS)
  1203  	}
  1204  	_ = net.ResolveIPAddr // force dynamic linkage
  1205  	f, err := Open(os.Args[0])
  1206  	if err != nil {
  1207  		t.Error(err)
  1208  		return
  1209  	}
  1210  	for i, si := range f.Sections {
  1211  		sih := si.SectionHeader
  1212  		if sih.Type == SHT_NOBITS {
  1213  			continue
  1214  		}
  1215  		// checking for overlap in file
  1216  		for j, sj := range f.Sections {
  1217  			sjh := sj.SectionHeader
  1218  			if i == j || sjh.Type == SHT_NOBITS || sih.Offset == sjh.Offset && sih.FileSize == 0 {
  1219  				continue
  1220  			}
  1221  			if sih.Offset >= sjh.Offset && sih.Offset < sjh.Offset+sjh.FileSize {
  1222  				t.Errorf("ld produced ELF with section offset %s within %s: 0x%x <= 0x%x..0x%x < 0x%x",
  1223  					sih.Name, sjh.Name, sjh.Offset, sih.Offset, sih.Offset+sih.FileSize, sjh.Offset+sjh.FileSize)
  1224  			}
  1225  		}
  1226  
  1227  		if sih.Flags&SHF_ALLOC == 0 {
  1228  			continue
  1229  		}
  1230  
  1231  		// checking for overlap in address space
  1232  		for j, sj := range f.Sections {
  1233  			sjh := sj.SectionHeader
  1234  			if i == j || sjh.Flags&SHF_ALLOC == 0 || sjh.Type == SHT_NOBITS ||
  1235  				sih.Addr == sjh.Addr && sih.Size == 0 {
  1236  				continue
  1237  			}
  1238  			if sih.Addr >= sjh.Addr && sih.Addr < sjh.Addr+sjh.Size {
  1239  				t.Errorf("ld produced ELF with section address %s within %s: 0x%x <= 0x%x..0x%x < 0x%x",
  1240  					sih.Name, sjh.Name, sjh.Addr, sih.Addr, sih.Addr+sih.Size, sjh.Addr+sjh.Size)
  1241  			}
  1242  		}
  1243  	}
  1244  }
  1245  
  1246  func TestNobitsSection(t *testing.T) {
  1247  	const testdata = "testdata/gcc-amd64-linux-exec"
  1248  	f, err := Open(testdata)
  1249  	if err != nil {
  1250  		t.Fatalf("could not read %s: %v", testdata, err)
  1251  	}
  1252  	defer f.Close()
  1253  
  1254  	wantError := "unexpected read from SHT_NOBITS section"
  1255  	bss := f.Section(".bss")
  1256  
  1257  	_, err = bss.Data()
  1258  	if err == nil || err.Error() != wantError {
  1259  		t.Fatalf("bss.Data() got error %q, want error %q", err, wantError)
  1260  	}
  1261  
  1262  	r := bss.Open()
  1263  	p := make([]byte, 1)
  1264  	_, err = r.Read(p)
  1265  	if err == nil || err.Error() != wantError {
  1266  		t.Fatalf("r.Read(p) got error %q, want error %q", err, wantError)
  1267  	}
  1268  }
  1269  
  1270  // TestLargeNumberOfSections tests the case that a file has greater than or
  1271  // equal to 65280 (0xff00) sections.
  1272  func TestLargeNumberOfSections(t *testing.T) {
  1273  	// A file with >= 0xff00 sections is too big, so we will construct it on the
  1274  	// fly. The original file "y.o" is generated by these commands:
  1275  	// 1. generate "y.c":
  1276  	//   for i in `seq 1 65288`; do
  1277  	//     printf -v x "%04x" i;
  1278  	//     echo "int var_$x __attribute__((section(\"section_$x\"))) = $i;"
  1279  	//   done > y.c
  1280  	// 2. compile: gcc -c y.c -m32
  1281  	//
  1282  	// $readelf -h y.o
  1283  	// ELF Header:
  1284  	//   Magic:   7f 45 4c 46 01 01 01 00 00 00 00 00 00 00 00 00
  1285  	//   Class:                             ELF32
  1286  	//   Data:                              2's complement, little endian
  1287  	//   Version:                           1 (current)
  1288  	//   OS/ABI:                            UNIX - System V
  1289  	//   ABI Version:                       0
  1290  	//   Type:                              REL (Relocatable file)
  1291  	//   Machine:                           Intel 80386
  1292  	//   Version:                           0x1
  1293  	//   Entry point address:               0x0
  1294  	//   Start of program headers:          0 (bytes into file)
  1295  	//   Start of section headers:          3003468 (bytes into file)
  1296  	//   Flags:                             0x0
  1297  	//   Size of this header:               52 (bytes)
  1298  	//   Size of program headers:           0 (bytes)
  1299  	//   Number of program headers:         0
  1300  	//   Size of section headers:           40 (bytes)
  1301  	//   Number of section headers:         0 (65298)
  1302  	//   Section header string table index: 65535 (65297)
  1303  	//
  1304  	// $readelf -S y.o
  1305  	// There are 65298 section headers, starting at offset 0x2dd44c:
  1306  	// Section Headers:
  1307  	//   [Nr]    Name              Type            Addr     Off    Size   ES Flg Lk Inf Al
  1308  	//   [    0]                   NULL            00000000 000000 00ff12 00     65297   0  0
  1309  	//   [    1] .text             PROGBITS        00000000 000034 000000 00  AX  0   0  1
  1310  	//   [    2] .data             PROGBITS        00000000 000034 000000 00  WA  0   0  1
  1311  	//   [    3] .bss              NOBITS          00000000 000034 000000 00  WA  0   0  1
  1312  	//   [    4] section_0001      PROGBITS        00000000 000034 000004 00  WA  0   0  4
  1313  	//   [    5] section_0002      PROGBITS        00000000 000038 000004 00  WA  0   0  4
  1314  	//   [ section_0003 ~ section_ff06 truncated ]
  1315  	//   [65290] section_ff07      PROGBITS        00000000 03fc4c 000004 00  WA  0   0  4
  1316  	//   [65291] section_ff08      PROGBITS        00000000 03fc50 000004 00  WA  0   0  4
  1317  	//   [65292] .comment          PROGBITS        00000000 03fc54 000027 01  MS  0   0  1
  1318  	//   [65293] .note.GNU-stack   PROGBITS        00000000 03fc7b 000000 00      0   0  1
  1319  	//   [65294] .symtab           SYMTAB          00000000 03fc7c 0ff0a0 10     65296   2  4
  1320  	//   [65295] .symtab_shndx     SYMTAB SECTION  00000000 13ed1c 03fc28 04     65294   0  4
  1321  	//   [65296] .strtab           STRTAB          00000000 17e944 08f74d 00      0   0  1
  1322  	//   [65297] .shstrtab         STRTAB          00000000 20e091 0cf3bb 00      0   0  1
  1323  
  1324  	var buf bytes.Buffer
  1325  
  1326  	{
  1327  		buf.Grow(0x55AF1C) // 3003468 + 40 * 65298
  1328  
  1329  		h := Header32{
  1330  			Ident:     [16]byte{0x7F, 'E', 'L', 'F', 0x01, 0x01, 0x01},
  1331  			Type:      1,
  1332  			Machine:   3,
  1333  			Version:   1,
  1334  			Shoff:     0x2DD44C,
  1335  			Ehsize:    0x34,
  1336  			Shentsize: 0x28,
  1337  			Shnum:     0,
  1338  			Shstrndx:  0xFFFF,
  1339  		}
  1340  		binary.Write(&buf, binary.LittleEndian, h)
  1341  
  1342  		// Zero out sections [1]~[65294].
  1343  		buf.Write(bytes.Repeat([]byte{0}, 0x13ED1C-binary.Size(h)))
  1344  
  1345  		// Write section [65295]. Section [65295] are all zeros except for the
  1346  		// last 48 bytes.
  1347  		buf.Write(bytes.Repeat([]byte{0}, 0x03FC28-12*4))
  1348  		for i := 0; i < 12; i++ {
  1349  			binary.Write(&buf, binary.LittleEndian, uint32(0xFF00|i))
  1350  		}
  1351  
  1352  		// Write section [65296].
  1353  		buf.Write([]byte{0})
  1354  		buf.Write([]byte("y.c\x00"))
  1355  		for i := 1; i <= 65288; i++ {
  1356  			// var_0001 ~ var_ff08
  1357  			name := fmt.Sprintf("var_%04x", i)
  1358  			buf.Write([]byte(name))
  1359  			buf.Write([]byte{0})
  1360  		}
  1361  
  1362  		// Write section [65297].
  1363  		buf.Write([]byte{0})
  1364  		buf.Write([]byte(".symtab\x00"))
  1365  		buf.Write([]byte(".strtab\x00"))
  1366  		buf.Write([]byte(".shstrtab\x00"))
  1367  		buf.Write([]byte(".text\x00"))
  1368  		buf.Write([]byte(".data\x00"))
  1369  		buf.Write([]byte(".bss\x00"))
  1370  		for i := 1; i <= 65288; i++ {
  1371  			// s_0001 ~ s_ff08
  1372  			name := fmt.Sprintf("section_%04x", i)
  1373  			buf.Write([]byte(name))
  1374  			buf.Write([]byte{0})
  1375  		}
  1376  		buf.Write([]byte(".comment\x00"))
  1377  		buf.Write([]byte(".note.GNU-stack\x00"))
  1378  		buf.Write([]byte(".symtab_shndx\x00"))
  1379  
  1380  		// Write section header table.
  1381  		// NULL
  1382  		binary.Write(&buf, binary.LittleEndian, Section32{Name: 0, Size: 0xFF12, Link: 0xFF11})
  1383  		// .text
  1384  		binary.Write(&buf, binary.LittleEndian, Section32{
  1385  			Name:      0x1B,
  1386  			Type:      uint32(SHT_PROGBITS),
  1387  			Flags:     uint32(SHF_ALLOC | SHF_EXECINSTR),
  1388  			Off:       0x34,
  1389  			Addralign: 0x01,
  1390  		})
  1391  		// .data
  1392  		binary.Write(&buf, binary.LittleEndian, Section32{
  1393  			Name:      0x21,
  1394  			Type:      uint32(SHT_PROGBITS),
  1395  			Flags:     uint32(SHF_WRITE | SHF_ALLOC),
  1396  			Off:       0x34,
  1397  			Addralign: 0x01,
  1398  		})
  1399  		// .bss
  1400  		binary.Write(&buf, binary.LittleEndian, Section32{
  1401  			Name:      0x27,
  1402  			Type:      uint32(SHT_NOBITS),
  1403  			Flags:     uint32(SHF_WRITE | SHF_ALLOC),
  1404  			Off:       0x34,
  1405  			Addralign: 0x01,
  1406  		})
  1407  		// s_1 ~ s_65537
  1408  		for i := 0; i < 65288; i++ {
  1409  			s := Section32{
  1410  				Name:      uint32(0x2C + i*13),
  1411  				Type:      uint32(SHT_PROGBITS),
  1412  				Flags:     uint32(SHF_WRITE | SHF_ALLOC),
  1413  				Off:       uint32(0x34 + i*4),
  1414  				Size:      0x04,
  1415  				Addralign: 0x04,
  1416  			}
  1417  			binary.Write(&buf, binary.LittleEndian, s)
  1418  		}
  1419  		// .comment
  1420  		binary.Write(&buf, binary.LittleEndian, Section32{
  1421  			Name:      0x0CF394,
  1422  			Type:      uint32(SHT_PROGBITS),
  1423  			Flags:     uint32(SHF_MERGE | SHF_STRINGS),
  1424  			Off:       0x03FC54,
  1425  			Size:      0x27,
  1426  			Addralign: 0x01,
  1427  			Entsize:   0x01,
  1428  		})
  1429  		// .note.GNU-stack
  1430  		binary.Write(&buf, binary.LittleEndian, Section32{
  1431  			Name:      0x0CF39D,
  1432  			Type:      uint32(SHT_PROGBITS),
  1433  			Off:       0x03FC7B,
  1434  			Addralign: 0x01,
  1435  		})
  1436  		// .symtab
  1437  		binary.Write(&buf, binary.LittleEndian, Section32{
  1438  			Name:      0x01,
  1439  			Type:      uint32(SHT_SYMTAB),
  1440  			Off:       0x03FC7C,
  1441  			Size:      0x0FF0A0,
  1442  			Link:      0xFF10,
  1443  			Info:      0x02,
  1444  			Addralign: 0x04,
  1445  			Entsize:   0x10,
  1446  		})
  1447  		// .symtab_shndx
  1448  		binary.Write(&buf, binary.LittleEndian, Section32{
  1449  			Name:      0x0CF3AD,
  1450  			Type:      uint32(SHT_SYMTAB_SHNDX),
  1451  			Off:       0x13ED1C,
  1452  			Size:      0x03FC28,
  1453  			Link:      0xFF0E,
  1454  			Addralign: 0x04,
  1455  			Entsize:   0x04,
  1456  		})
  1457  		// .strtab
  1458  		binary.Write(&buf, binary.LittleEndian, Section32{
  1459  			Name:      0x09,
  1460  			Type:      uint32(SHT_STRTAB),
  1461  			Off:       0x17E944,
  1462  			Size:      0x08F74D,
  1463  			Addralign: 0x01,
  1464  		})
  1465  		// .shstrtab
  1466  		binary.Write(&buf, binary.LittleEndian, Section32{
  1467  			Name:      0x11,
  1468  			Type:      uint32(SHT_STRTAB),
  1469  			Off:       0x20E091,
  1470  			Size:      0x0CF3BB,
  1471  			Addralign: 0x01,
  1472  		})
  1473  	}
  1474  
  1475  	data := buf.Bytes()
  1476  
  1477  	f, err := NewFile(bytes.NewReader(data))
  1478  	if err != nil {
  1479  		t.Errorf("cannot create file from data: %v", err)
  1480  	}
  1481  	defer f.Close()
  1482  
  1483  	wantFileHeader := FileHeader{
  1484  		Class:     ELFCLASS32,
  1485  		Data:      ELFDATA2LSB,
  1486  		Version:   EV_CURRENT,
  1487  		OSABI:     ELFOSABI_NONE,
  1488  		ByteOrder: binary.LittleEndian,
  1489  		Type:      ET_REL,
  1490  		Machine:   EM_386,
  1491  	}
  1492  	if f.FileHeader != wantFileHeader {
  1493  		t.Errorf("\nhave %#v\nwant %#v\n", f.FileHeader, wantFileHeader)
  1494  	}
  1495  
  1496  	wantSectionNum := 65298
  1497  	if len(f.Sections) != wantSectionNum {
  1498  		t.Errorf("len(Sections) = %d, want %d", len(f.Sections), wantSectionNum)
  1499  	}
  1500  
  1501  	wantSectionHeader := SectionHeader{
  1502  		Name:      "section_0007",
  1503  		Type:      SHT_PROGBITS,
  1504  		Flags:     SHF_WRITE + SHF_ALLOC,
  1505  		Offset:    0x4c,
  1506  		Size:      0x4,
  1507  		Addralign: 0x4,
  1508  		FileSize:  0x4,
  1509  	}
  1510  	if f.Sections[10].SectionHeader != wantSectionHeader {
  1511  		t.Errorf("\nhave %#v\nwant %#v\n", f.Sections[10].SectionHeader, wantSectionHeader)
  1512  	}
  1513  }
  1514  
  1515  func TestIssue10996(t *testing.T) {
  1516  	data := []byte("\u007fELF\x02\x01\x010000000000000" +
  1517  		"\x010000000000000000000" +
  1518  		"\x00\x00\x00\x00\x00\x00\x00\x0000000000\x00\x00\x00\x00" +
  1519  		"0000")
  1520  	_, err := NewFile(bytes.NewReader(data))
  1521  	if err == nil {
  1522  		t.Fatalf("opening invalid ELF file unexpectedly succeeded")
  1523  	}
  1524  }
  1525  
  1526  func TestDynValue(t *testing.T) {
  1527  	const testdata = "testdata/gcc-amd64-linux-exec"
  1528  	f, err := Open(testdata)
  1529  	if err != nil {
  1530  		t.Fatalf("could not read %s: %v", testdata, err)
  1531  	}
  1532  	defer f.Close()
  1533  
  1534  	vals, err := f.DynValue(DT_VERNEEDNUM)
  1535  	if err != nil {
  1536  		t.Fatalf("DynValue(DT_VERNEEDNUM): got unexpected error %v", err)
  1537  	}
  1538  
  1539  	if len(vals) != 1 || vals[0] != 1 {
  1540  		t.Errorf("DynValue(DT_VERNEEDNUM): got %v, want [1]", vals)
  1541  	}
  1542  }
  1543  
  1544  func TestIssue59208(t *testing.T) {
  1545  	// corrupted dwarf data should raise invalid dwarf data instead of invalid zlib
  1546  	const orig = "testdata/compressed-64.obj"
  1547  	f, err := Open(orig)
  1548  	if err != nil {
  1549  		t.Fatal(err)
  1550  	}
  1551  	sec := f.Section(".debug_info")
  1552  
  1553  	data, err := os.ReadFile(orig)
  1554  	if err != nil {
  1555  		t.Fatal(err)
  1556  	}
  1557  
  1558  	dn := make([]byte, len(data))
  1559  	zoffset := sec.Offset + uint64(sec.compressionOffset)
  1560  	copy(dn, data[:zoffset])
  1561  
  1562  	ozd, err := sec.Data()
  1563  	if err != nil {
  1564  		t.Fatal(err)
  1565  	}
  1566  	buf := bytes.NewBuffer(nil)
  1567  	wr := zlib.NewWriter(buf)
  1568  	// corrupt origin data same as COMPRESS_ZLIB
  1569  	copy(ozd, []byte{1, 0, 0, 0})
  1570  	wr.Write(ozd)
  1571  	wr.Close()
  1572  
  1573  	copy(dn[zoffset:], buf.Bytes())
  1574  	copy(dn[sec.Offset+sec.FileSize:], data[sec.Offset+sec.FileSize:])
  1575  
  1576  	nf, err := NewFile(bytes.NewReader(dn))
  1577  	if err != nil {
  1578  		t.Error(err)
  1579  	}
  1580  
  1581  	const want = "decoding dwarf section info"
  1582  	_, err = nf.DWARF()
  1583  	if err == nil || !strings.Contains(err.Error(), want) {
  1584  		t.Errorf("DWARF = %v; want %q", err, want)
  1585  	}
  1586  }
  1587  
  1588  func BenchmarkSymbols64(b *testing.B) {
  1589  	const testdata = "testdata/gcc-amd64-linux-exec"
  1590  	f, err := Open(testdata)
  1591  	if err != nil {
  1592  		b.Fatalf("could not read %s: %v", testdata, err)
  1593  	}
  1594  	defer f.Close()
  1595  	b.ResetTimer()
  1596  	for i := 0; i < b.N; i++ {
  1597  		symbols, err := f.Symbols()
  1598  		if err != nil {
  1599  			b.Fatalf("Symbols(): got unexpected error %v", err)
  1600  		}
  1601  		if len(symbols) != 73 {
  1602  			b.Errorf("\nhave %d symbols\nwant %d symbols\n", len(symbols), 73)
  1603  		}
  1604  	}
  1605  }
  1606  
  1607  func BenchmarkSymbols32(b *testing.B) {
  1608  	const testdata = "testdata/gcc-386-freebsd-exec"
  1609  	f, err := Open(testdata)
  1610  	if err != nil {
  1611  		b.Fatalf("could not read %s: %v", testdata, err)
  1612  	}
  1613  	defer f.Close()
  1614  	b.ResetTimer()
  1615  	for i := 0; i < b.N; i++ {
  1616  		symbols, err := f.Symbols()
  1617  		if err != nil {
  1618  			b.Fatalf("Symbols(): got unexpected error %v", err)
  1619  		}
  1620  		if len(symbols) != 74 {
  1621  			b.Errorf("\nhave %d symbols\nwant %d symbols\n", len(symbols), 74)
  1622  		}
  1623  	}
  1624  }
  1625  

View as plain text