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  		test := test
  1044  		t.Run(test.file, func(t *testing.T) {
  1045  			t.Parallel()
  1046  			f, err := Open(test.file)
  1047  			if err != nil {
  1048  				t.Fatal(err)
  1049  			}
  1050  			dwarf, err := f.DWARF()
  1051  			if err != nil {
  1052  				t.Fatal(err)
  1053  			}
  1054  			reader := dwarf.Reader()
  1055  			idx := 0
  1056  			for _, testEntry := range test.entries {
  1057  				if testEntry.entryNumber < idx {
  1058  					t.Fatalf("internal test error: %d < %d", testEntry.entryNumber, idx)
  1059  				}
  1060  				for ; idx < testEntry.entryNumber; idx++ {
  1061  					entry, err := reader.Next()
  1062  					if entry == nil || err != nil {
  1063  						t.Fatalf("Failed to skip to entry %d: %v", testEntry.entryNumber, err)
  1064  					}
  1065  				}
  1066  				entry, err := reader.Next()
  1067  				idx++
  1068  				if err != nil {
  1069  					t.Fatal(err)
  1070  				}
  1071  				if !reflect.DeepEqual(testEntry.entry, entry) {
  1072  					t.Errorf("entry %d mismatch: got:%#v want:%#v", testEntry.entryNumber, entry, testEntry.entry)
  1073  				}
  1074  				pcRanges, err := dwarf.Ranges(entry)
  1075  				if err != nil {
  1076  					t.Fatal(err)
  1077  				}
  1078  				if !reflect.DeepEqual(testEntry.pcRanges, pcRanges) {
  1079  					t.Errorf("entry %d: PC range mismatch: got:%#v want:%#v", testEntry.entryNumber, pcRanges, testEntry.pcRanges)
  1080  				}
  1081  			}
  1082  		})
  1083  	}
  1084  }
  1085  
  1086  func TestCompressedDWARF(t *testing.T) {
  1087  	// Test file built with GCC 4.8.4 and as 2.24 using:
  1088  	// gcc -Wa,--compress-debug-sections -g -c -o zdebug-test-gcc484-x86-64.obj hello.c
  1089  	f, err := Open("testdata/zdebug-test-gcc484-x86-64.obj")
  1090  	if err != nil {
  1091  		t.Fatal(err)
  1092  	}
  1093  	dwarf, err := f.DWARF()
  1094  	if err != nil {
  1095  		t.Fatal(err)
  1096  	}
  1097  	reader := dwarf.Reader()
  1098  	n := 0
  1099  	for {
  1100  		entry, err := reader.Next()
  1101  		if err != nil {
  1102  			t.Fatal(err)
  1103  		}
  1104  		if entry == nil {
  1105  			break
  1106  		}
  1107  		n++
  1108  	}
  1109  	if n != 18 {
  1110  		t.Fatalf("want %d DWARF entries, got %d", 18, n)
  1111  	}
  1112  }
  1113  
  1114  func TestCompressedSection(t *testing.T) {
  1115  	// Test files built with gcc -g -S hello.c and assembled with
  1116  	// --compress-debug-sections=zlib-gabi.
  1117  	f, err := Open("testdata/compressed-64.obj")
  1118  	if err != nil {
  1119  		t.Fatal(err)
  1120  	}
  1121  	sec := f.Section(".debug_info")
  1122  	wantData := []byte{
  1123  		182, 0, 0, 0, 4, 0, 0, 0, 0, 0, 8, 1, 0, 0, 0, 0,
  1124  		1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  1125  		0, 27, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 8, 7,
  1126  		0, 0, 0, 0, 2, 1, 8, 0, 0, 0, 0, 2, 2, 7, 0, 0,
  1127  		0, 0, 2, 4, 7, 0, 0, 0, 0, 2, 1, 6, 0, 0, 0, 0,
  1128  		2, 2, 5, 0, 0, 0, 0, 3, 4, 5, 105, 110, 116, 0, 2, 8,
  1129  		5, 0, 0, 0, 0, 2, 8, 7, 0, 0, 0, 0, 4, 8, 114, 0,
  1130  		0, 0, 2, 1, 6, 0, 0, 0, 0, 5, 0, 0, 0, 0, 1, 4,
  1131  		0, 0, 0, 0, 0, 0, 0, 0, 27, 0, 0, 0, 0, 0, 0, 0,
  1132  		1, 156, 179, 0, 0, 0, 6, 0, 0, 0, 0, 1, 4, 87, 0, 0,
  1133  		0, 2, 145, 108, 6, 0, 0, 0, 0, 1, 4, 179, 0, 0, 0, 2,
  1134  		145, 96, 0, 4, 8, 108, 0, 0, 0, 0,
  1135  	}
  1136  
  1137  	// Test Data method.
  1138  	b, err := sec.Data()
  1139  	if err != nil {
  1140  		t.Fatal(err)
  1141  	}
  1142  	if !bytes.Equal(wantData, b) {
  1143  		t.Fatalf("want data %x, got %x", wantData, b)
  1144  	}
  1145  
  1146  	// Test Open method and seeking.
  1147  	buf, have, count := make([]byte, len(b)), make([]bool, len(b)), 0
  1148  	sf := sec.Open()
  1149  	if got, err := sf.Seek(0, io.SeekEnd); got != int64(len(b)) || err != nil {
  1150  		t.Fatalf("want seek end %d, got %d error %v", len(b), got, err)
  1151  	}
  1152  	if n, err := sf.Read(buf); n != 0 || err != io.EOF {
  1153  		t.Fatalf("want EOF with 0 bytes, got %v with %d bytes", err, n)
  1154  	}
  1155  	pos := int64(len(buf))
  1156  	for count < len(buf) {
  1157  		// Construct random seek arguments.
  1158  		whence := rand.Intn(3)
  1159  		target := rand.Int63n(int64(len(buf)))
  1160  		var offset int64
  1161  		switch whence {
  1162  		case io.SeekStart:
  1163  			offset = target
  1164  		case io.SeekCurrent:
  1165  			offset = target - pos
  1166  		case io.SeekEnd:
  1167  			offset = target - int64(len(buf))
  1168  		}
  1169  		pos, err = sf.Seek(offset, whence)
  1170  		if err != nil {
  1171  			t.Fatal(err)
  1172  		}
  1173  		if pos != target {
  1174  			t.Fatalf("want position %d, got %d", target, pos)
  1175  		}
  1176  
  1177  		// Read data from the new position.
  1178  		end := pos + 16
  1179  		if end > int64(len(buf)) {
  1180  			end = int64(len(buf))
  1181  		}
  1182  		n, err := io.ReadFull(sf, buf[pos:end])
  1183  		if err != nil {
  1184  			t.Fatal(err)
  1185  		}
  1186  		for i := 0; i < n; i++ {
  1187  			if !have[pos] {
  1188  				have[pos] = true
  1189  				count++
  1190  			}
  1191  			pos++
  1192  		}
  1193  	}
  1194  	if !bytes.Equal(wantData, buf) {
  1195  		t.Fatalf("want data %x, got %x", wantData, buf)
  1196  	}
  1197  }
  1198  
  1199  func TestNoSectionOverlaps(t *testing.T) {
  1200  	// Ensure cmd/link outputs sections without overlaps.
  1201  	switch runtime.GOOS {
  1202  	case "aix", "android", "darwin", "ios", "js", "plan9", "windows", "wasip1":
  1203  		t.Skipf("cmd/link doesn't produce ELF binaries on %s", runtime.GOOS)
  1204  	}
  1205  	_ = net.ResolveIPAddr // force dynamic linkage
  1206  	f, err := Open(os.Args[0])
  1207  	if err != nil {
  1208  		t.Error(err)
  1209  		return
  1210  	}
  1211  	for i, si := range f.Sections {
  1212  		sih := si.SectionHeader
  1213  		if sih.Type == SHT_NOBITS {
  1214  			continue
  1215  		}
  1216  		// checking for overlap in file
  1217  		for j, sj := range f.Sections {
  1218  			sjh := sj.SectionHeader
  1219  			if i == j || sjh.Type == SHT_NOBITS || sih.Offset == sjh.Offset && sih.FileSize == 0 {
  1220  				continue
  1221  			}
  1222  			if sih.Offset >= sjh.Offset && sih.Offset < sjh.Offset+sjh.FileSize {
  1223  				t.Errorf("ld produced ELF with section offset %s within %s: 0x%x <= 0x%x..0x%x < 0x%x",
  1224  					sih.Name, sjh.Name, sjh.Offset, sih.Offset, sih.Offset+sih.FileSize, sjh.Offset+sjh.FileSize)
  1225  			}
  1226  		}
  1227  
  1228  		if sih.Flags&SHF_ALLOC == 0 {
  1229  			continue
  1230  		}
  1231  
  1232  		// checking for overlap in address space
  1233  		for j, sj := range f.Sections {
  1234  			sjh := sj.SectionHeader
  1235  			if i == j || sjh.Flags&SHF_ALLOC == 0 || sjh.Type == SHT_NOBITS ||
  1236  				sih.Addr == sjh.Addr && sih.Size == 0 {
  1237  				continue
  1238  			}
  1239  			if sih.Addr >= sjh.Addr && sih.Addr < sjh.Addr+sjh.Size {
  1240  				t.Errorf("ld produced ELF with section address %s within %s: 0x%x <= 0x%x..0x%x < 0x%x",
  1241  					sih.Name, sjh.Name, sjh.Addr, sih.Addr, sih.Addr+sih.Size, sjh.Addr+sjh.Size)
  1242  			}
  1243  		}
  1244  	}
  1245  }
  1246  
  1247  func TestNobitsSection(t *testing.T) {
  1248  	const testdata = "testdata/gcc-amd64-linux-exec"
  1249  	f, err := Open(testdata)
  1250  	if err != nil {
  1251  		t.Fatalf("could not read %s: %v", testdata, err)
  1252  	}
  1253  	defer f.Close()
  1254  
  1255  	wantError := "unexpected read from SHT_NOBITS section"
  1256  	bss := f.Section(".bss")
  1257  
  1258  	_, err = bss.Data()
  1259  	if err == nil || err.Error() != wantError {
  1260  		t.Fatalf("bss.Data() got error %q, want error %q", err, wantError)
  1261  	}
  1262  
  1263  	r := bss.Open()
  1264  	p := make([]byte, 1)
  1265  	_, err = r.Read(p)
  1266  	if err == nil || err.Error() != wantError {
  1267  		t.Fatalf("r.Read(p) got error %q, want error %q", err, wantError)
  1268  	}
  1269  }
  1270  
  1271  // TestLargeNumberOfSections tests the case that a file has greater than or
  1272  // equal to 65280 (0xff00) sections.
  1273  func TestLargeNumberOfSections(t *testing.T) {
  1274  	// A file with >= 0xff00 sections is too big, so we will construct it on the
  1275  	// fly. The original file "y.o" is generated by these commands:
  1276  	// 1. generate "y.c":
  1277  	//   for i in `seq 1 65288`; do
  1278  	//     printf -v x "%04x" i;
  1279  	//     echo "int var_$x __attribute__((section(\"section_$x\"))) = $i;"
  1280  	//   done > y.c
  1281  	// 2. compile: gcc -c y.c -m32
  1282  	//
  1283  	// $readelf -h y.o
  1284  	// ELF Header:
  1285  	//   Magic:   7f 45 4c 46 01 01 01 00 00 00 00 00 00 00 00 00
  1286  	//   Class:                             ELF32
  1287  	//   Data:                              2's complement, little endian
  1288  	//   Version:                           1 (current)
  1289  	//   OS/ABI:                            UNIX - System V
  1290  	//   ABI Version:                       0
  1291  	//   Type:                              REL (Relocatable file)
  1292  	//   Machine:                           Intel 80386
  1293  	//   Version:                           0x1
  1294  	//   Entry point address:               0x0
  1295  	//   Start of program headers:          0 (bytes into file)
  1296  	//   Start of section headers:          3003468 (bytes into file)
  1297  	//   Flags:                             0x0
  1298  	//   Size of this header:               52 (bytes)
  1299  	//   Size of program headers:           0 (bytes)
  1300  	//   Number of program headers:         0
  1301  	//   Size of section headers:           40 (bytes)
  1302  	//   Number of section headers:         0 (65298)
  1303  	//   Section header string table index: 65535 (65297)
  1304  	//
  1305  	// $readelf -S y.o
  1306  	// There are 65298 section headers, starting at offset 0x2dd44c:
  1307  	// Section Headers:
  1308  	//   [Nr]    Name              Type            Addr     Off    Size   ES Flg Lk Inf Al
  1309  	//   [    0]                   NULL            00000000 000000 00ff12 00     65297   0  0
  1310  	//   [    1] .text             PROGBITS        00000000 000034 000000 00  AX  0   0  1
  1311  	//   [    2] .data             PROGBITS        00000000 000034 000000 00  WA  0   0  1
  1312  	//   [    3] .bss              NOBITS          00000000 000034 000000 00  WA  0   0  1
  1313  	//   [    4] section_0001      PROGBITS        00000000 000034 000004 00  WA  0   0  4
  1314  	//   [    5] section_0002      PROGBITS        00000000 000038 000004 00  WA  0   0  4
  1315  	//   [ section_0003 ~ section_ff06 truncated ]
  1316  	//   [65290] section_ff07      PROGBITS        00000000 03fc4c 000004 00  WA  0   0  4
  1317  	//   [65291] section_ff08      PROGBITS        00000000 03fc50 000004 00  WA  0   0  4
  1318  	//   [65292] .comment          PROGBITS        00000000 03fc54 000027 01  MS  0   0  1
  1319  	//   [65293] .note.GNU-stack   PROGBITS        00000000 03fc7b 000000 00      0   0  1
  1320  	//   [65294] .symtab           SYMTAB          00000000 03fc7c 0ff0a0 10     65296   2  4
  1321  	//   [65295] .symtab_shndx     SYMTAB SECTION  00000000 13ed1c 03fc28 04     65294   0  4
  1322  	//   [65296] .strtab           STRTAB          00000000 17e944 08f74d 00      0   0  1
  1323  	//   [65297] .shstrtab         STRTAB          00000000 20e091 0cf3bb 00      0   0  1
  1324  
  1325  	var buf bytes.Buffer
  1326  
  1327  	{
  1328  		buf.Grow(0x55AF1C) // 3003468 + 40 * 65298
  1329  
  1330  		h := Header32{
  1331  			Ident:     [16]byte{0x7F, 'E', 'L', 'F', 0x01, 0x01, 0x01},
  1332  			Type:      1,
  1333  			Machine:   3,
  1334  			Version:   1,
  1335  			Shoff:     0x2DD44C,
  1336  			Ehsize:    0x34,
  1337  			Shentsize: 0x28,
  1338  			Shnum:     0,
  1339  			Shstrndx:  0xFFFF,
  1340  		}
  1341  		binary.Write(&buf, binary.LittleEndian, h)
  1342  
  1343  		// Zero out sections [1]~[65294].
  1344  		buf.Write(bytes.Repeat([]byte{0}, 0x13ED1C-binary.Size(h)))
  1345  
  1346  		// Write section [65295]. Section [65295] are all zeros except for the
  1347  		// last 48 bytes.
  1348  		buf.Write(bytes.Repeat([]byte{0}, 0x03FC28-12*4))
  1349  		for i := 0; i < 12; i++ {
  1350  			binary.Write(&buf, binary.LittleEndian, uint32(0xFF00|i))
  1351  		}
  1352  
  1353  		// Write section [65296].
  1354  		buf.Write([]byte{0})
  1355  		buf.Write([]byte("y.c\x00"))
  1356  		for i := 1; i <= 65288; i++ {
  1357  			// var_0001 ~ var_ff08
  1358  			name := fmt.Sprintf("var_%04x", i)
  1359  			buf.Write([]byte(name))
  1360  			buf.Write([]byte{0})
  1361  		}
  1362  
  1363  		// Write section [65297].
  1364  		buf.Write([]byte{0})
  1365  		buf.Write([]byte(".symtab\x00"))
  1366  		buf.Write([]byte(".strtab\x00"))
  1367  		buf.Write([]byte(".shstrtab\x00"))
  1368  		buf.Write([]byte(".text\x00"))
  1369  		buf.Write([]byte(".data\x00"))
  1370  		buf.Write([]byte(".bss\x00"))
  1371  		for i := 1; i <= 65288; i++ {
  1372  			// s_0001 ~ s_ff08
  1373  			name := fmt.Sprintf("section_%04x", i)
  1374  			buf.Write([]byte(name))
  1375  			buf.Write([]byte{0})
  1376  		}
  1377  		buf.Write([]byte(".comment\x00"))
  1378  		buf.Write([]byte(".note.GNU-stack\x00"))
  1379  		buf.Write([]byte(".symtab_shndx\x00"))
  1380  
  1381  		// Write section header table.
  1382  		// NULL
  1383  		binary.Write(&buf, binary.LittleEndian, Section32{Name: 0, Size: 0xFF12, Link: 0xFF11})
  1384  		// .text
  1385  		binary.Write(&buf, binary.LittleEndian, Section32{
  1386  			Name:      0x1B,
  1387  			Type:      uint32(SHT_PROGBITS),
  1388  			Flags:     uint32(SHF_ALLOC | SHF_EXECINSTR),
  1389  			Off:       0x34,
  1390  			Addralign: 0x01,
  1391  		})
  1392  		// .data
  1393  		binary.Write(&buf, binary.LittleEndian, Section32{
  1394  			Name:      0x21,
  1395  			Type:      uint32(SHT_PROGBITS),
  1396  			Flags:     uint32(SHF_WRITE | SHF_ALLOC),
  1397  			Off:       0x34,
  1398  			Addralign: 0x01,
  1399  		})
  1400  		// .bss
  1401  		binary.Write(&buf, binary.LittleEndian, Section32{
  1402  			Name:      0x27,
  1403  			Type:      uint32(SHT_NOBITS),
  1404  			Flags:     uint32(SHF_WRITE | SHF_ALLOC),
  1405  			Off:       0x34,
  1406  			Addralign: 0x01,
  1407  		})
  1408  		// s_1 ~ s_65537
  1409  		for i := 0; i < 65288; i++ {
  1410  			s := Section32{
  1411  				Name:      uint32(0x2C + i*13),
  1412  				Type:      uint32(SHT_PROGBITS),
  1413  				Flags:     uint32(SHF_WRITE | SHF_ALLOC),
  1414  				Off:       uint32(0x34 + i*4),
  1415  				Size:      0x04,
  1416  				Addralign: 0x04,
  1417  			}
  1418  			binary.Write(&buf, binary.LittleEndian, s)
  1419  		}
  1420  		// .comment
  1421  		binary.Write(&buf, binary.LittleEndian, Section32{
  1422  			Name:      0x0CF394,
  1423  			Type:      uint32(SHT_PROGBITS),
  1424  			Flags:     uint32(SHF_MERGE | SHF_STRINGS),
  1425  			Off:       0x03FC54,
  1426  			Size:      0x27,
  1427  			Addralign: 0x01,
  1428  			Entsize:   0x01,
  1429  		})
  1430  		// .note.GNU-stack
  1431  		binary.Write(&buf, binary.LittleEndian, Section32{
  1432  			Name:      0x0CF39D,
  1433  			Type:      uint32(SHT_PROGBITS),
  1434  			Off:       0x03FC7B,
  1435  			Addralign: 0x01,
  1436  		})
  1437  		// .symtab
  1438  		binary.Write(&buf, binary.LittleEndian, Section32{
  1439  			Name:      0x01,
  1440  			Type:      uint32(SHT_SYMTAB),
  1441  			Off:       0x03FC7C,
  1442  			Size:      0x0FF0A0,
  1443  			Link:      0xFF10,
  1444  			Info:      0x02,
  1445  			Addralign: 0x04,
  1446  			Entsize:   0x10,
  1447  		})
  1448  		// .symtab_shndx
  1449  		binary.Write(&buf, binary.LittleEndian, Section32{
  1450  			Name:      0x0CF3AD,
  1451  			Type:      uint32(SHT_SYMTAB_SHNDX),
  1452  			Off:       0x13ED1C,
  1453  			Size:      0x03FC28,
  1454  			Link:      0xFF0E,
  1455  			Addralign: 0x04,
  1456  			Entsize:   0x04,
  1457  		})
  1458  		// .strtab
  1459  		binary.Write(&buf, binary.LittleEndian, Section32{
  1460  			Name:      0x09,
  1461  			Type:      uint32(SHT_STRTAB),
  1462  			Off:       0x17E944,
  1463  			Size:      0x08F74D,
  1464  			Addralign: 0x01,
  1465  		})
  1466  		// .shstrtab
  1467  		binary.Write(&buf, binary.LittleEndian, Section32{
  1468  			Name:      0x11,
  1469  			Type:      uint32(SHT_STRTAB),
  1470  			Off:       0x20E091,
  1471  			Size:      0x0CF3BB,
  1472  			Addralign: 0x01,
  1473  		})
  1474  	}
  1475  
  1476  	data := buf.Bytes()
  1477  
  1478  	f, err := NewFile(bytes.NewReader(data))
  1479  	if err != nil {
  1480  		t.Errorf("cannot create file from data: %v", err)
  1481  	}
  1482  	defer f.Close()
  1483  
  1484  	wantFileHeader := FileHeader{
  1485  		Class:     ELFCLASS32,
  1486  		Data:      ELFDATA2LSB,
  1487  		Version:   EV_CURRENT,
  1488  		OSABI:     ELFOSABI_NONE,
  1489  		ByteOrder: binary.LittleEndian,
  1490  		Type:      ET_REL,
  1491  		Machine:   EM_386,
  1492  	}
  1493  	if f.FileHeader != wantFileHeader {
  1494  		t.Errorf("\nhave %#v\nwant %#v\n", f.FileHeader, wantFileHeader)
  1495  	}
  1496  
  1497  	wantSectionNum := 65298
  1498  	if len(f.Sections) != wantSectionNum {
  1499  		t.Errorf("len(Sections) = %d, want %d", len(f.Sections), wantSectionNum)
  1500  	}
  1501  
  1502  	wantSectionHeader := SectionHeader{
  1503  		Name:      "section_0007",
  1504  		Type:      SHT_PROGBITS,
  1505  		Flags:     SHF_WRITE + SHF_ALLOC,
  1506  		Offset:    0x4c,
  1507  		Size:      0x4,
  1508  		Addralign: 0x4,
  1509  		FileSize:  0x4,
  1510  	}
  1511  	if f.Sections[10].SectionHeader != wantSectionHeader {
  1512  		t.Errorf("\nhave %#v\nwant %#v\n", f.Sections[10].SectionHeader, wantSectionHeader)
  1513  	}
  1514  }
  1515  
  1516  func TestIssue10996(t *testing.T) {
  1517  	data := []byte("\u007fELF\x02\x01\x010000000000000" +
  1518  		"\x010000000000000000000" +
  1519  		"\x00\x00\x00\x00\x00\x00\x00\x0000000000\x00\x00\x00\x00" +
  1520  		"0000")
  1521  	_, err := NewFile(bytes.NewReader(data))
  1522  	if err == nil {
  1523  		t.Fatalf("opening invalid ELF file unexpectedly succeeded")
  1524  	}
  1525  }
  1526  
  1527  func TestDynValue(t *testing.T) {
  1528  	const testdata = "testdata/gcc-amd64-linux-exec"
  1529  	f, err := Open(testdata)
  1530  	if err != nil {
  1531  		t.Fatalf("could not read %s: %v", testdata, err)
  1532  	}
  1533  	defer f.Close()
  1534  
  1535  	vals, err := f.DynValue(DT_VERNEEDNUM)
  1536  	if err != nil {
  1537  		t.Fatalf("DynValue(DT_VERNEEDNUM): got unexpected error %v", err)
  1538  	}
  1539  
  1540  	if len(vals) != 1 || vals[0] != 1 {
  1541  		t.Errorf("DynValue(DT_VERNEEDNUM): got %v, want [1]", vals)
  1542  	}
  1543  }
  1544  
  1545  func TestIssue59208(t *testing.T) {
  1546  	// corrupted dwarf data should raise invalid dwarf data instead of invalid zlib
  1547  	const orig = "testdata/compressed-64.obj"
  1548  	f, err := Open(orig)
  1549  	if err != nil {
  1550  		t.Fatal(err)
  1551  	}
  1552  	sec := f.Section(".debug_info")
  1553  
  1554  	data, err := os.ReadFile(orig)
  1555  	if err != nil {
  1556  		t.Fatal(err)
  1557  	}
  1558  
  1559  	dn := make([]byte, len(data))
  1560  	zoffset := sec.Offset + uint64(sec.compressionOffset)
  1561  	copy(dn, data[:zoffset])
  1562  
  1563  	ozd, err := sec.Data()
  1564  	if err != nil {
  1565  		t.Fatal(err)
  1566  	}
  1567  	buf := bytes.NewBuffer(nil)
  1568  	wr := zlib.NewWriter(buf)
  1569  	// corrupt origin data same as COMPRESS_ZLIB
  1570  	copy(ozd, []byte{1, 0, 0, 0})
  1571  	wr.Write(ozd)
  1572  	wr.Close()
  1573  
  1574  	copy(dn[zoffset:], buf.Bytes())
  1575  	copy(dn[sec.Offset+sec.FileSize:], data[sec.Offset+sec.FileSize:])
  1576  
  1577  	nf, err := NewFile(bytes.NewReader(dn))
  1578  	if err != nil {
  1579  		t.Error(err)
  1580  	}
  1581  
  1582  	const want = "decoding dwarf section info"
  1583  	_, err = nf.DWARF()
  1584  	if err == nil || !strings.Contains(err.Error(), want) {
  1585  		t.Errorf("DWARF = %v; want %q", err, want)
  1586  	}
  1587  }
  1588  
  1589  func BenchmarkSymbols64(b *testing.B) {
  1590  	const testdata = "testdata/gcc-amd64-linux-exec"
  1591  	f, err := Open(testdata)
  1592  	if err != nil {
  1593  		b.Fatalf("could not read %s: %v", testdata, err)
  1594  	}
  1595  	defer f.Close()
  1596  	b.ResetTimer()
  1597  	for i := 0; i < b.N; i++ {
  1598  		symbols, err := f.Symbols()
  1599  		if err != nil {
  1600  			b.Fatalf("Symbols(): got unexpected error %v", err)
  1601  		}
  1602  		if len(symbols) != 73 {
  1603  			b.Errorf("\nhave %d symbols\nwant %d symbols\n", len(symbols), 73)
  1604  		}
  1605  	}
  1606  }
  1607  
  1608  func BenchmarkSymbols32(b *testing.B) {
  1609  	const testdata = "testdata/gcc-386-freebsd-exec"
  1610  	f, err := Open(testdata)
  1611  	if err != nil {
  1612  		b.Fatalf("could not read %s: %v", testdata, err)
  1613  	}
  1614  	defer f.Close()
  1615  	b.ResetTimer()
  1616  	for i := 0; i < b.N; i++ {
  1617  		symbols, err := f.Symbols()
  1618  		if err != nil {
  1619  			b.Fatalf("Symbols(): got unexpected error %v", err)
  1620  		}
  1621  		if len(symbols) != 74 {
  1622  			b.Errorf("\nhave %d symbols\nwant %d symbols\n", len(symbols), 74)
  1623  		}
  1624  	}
  1625  }
  1626  

View as plain text