Source file
src/debug/elf/file_test.go
1
2
3
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 "path/filepath"
21 "reflect"
22 "runtime"
23 "slices"
24 "strings"
25 "testing"
26 )
27
28 type fileTest struct {
29 file string
30 hdr FileHeader
31 sections []SectionHeader
32 progs []ProgHeader
33 needed []string
34 symbols []Symbol
35 }
36
37 var fileTests = []fileTest{
38 {
39 "testdata/gcc-386-freebsd-exec",
40 FileHeader{ELFCLASS32, ELFDATA2LSB, EV_CURRENT, ELFOSABI_FREEBSD, 0, binary.LittleEndian, ET_EXEC, EM_386, 0x80483cc},
41 []SectionHeader{
42 {"", SHT_NULL, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0},
43 {".interp", SHT_PROGBITS, SHF_ALLOC, 0x80480d4, 0xd4, 0x15, 0x0, 0x0, 0x1, 0x0, 0x15},
44 {".hash", SHT_HASH, SHF_ALLOC, 0x80480ec, 0xec, 0x90, 0x3, 0x0, 0x4, 0x4, 0x90},
45 {".dynsym", SHT_DYNSYM, SHF_ALLOC, 0x804817c, 0x17c, 0x110, 0x4, 0x1, 0x4, 0x10, 0x110},
46 {".dynstr", SHT_STRTAB, SHF_ALLOC, 0x804828c, 0x28c, 0xbb, 0x0, 0x0, 0x1, 0x0, 0xbb},
47 {".rel.plt", SHT_REL, SHF_ALLOC, 0x8048348, 0x348, 0x20, 0x3, 0x7, 0x4, 0x8, 0x20},
48 {".init", SHT_PROGBITS, SHF_ALLOC + SHF_EXECINSTR, 0x8048368, 0x368, 0x11, 0x0, 0x0, 0x4, 0x0, 0x11},
49 {".plt", SHT_PROGBITS, SHF_ALLOC + SHF_EXECINSTR, 0x804837c, 0x37c, 0x50, 0x0, 0x0, 0x4, 0x4, 0x50},
50 {".text", SHT_PROGBITS, SHF_ALLOC + SHF_EXECINSTR, 0x80483cc, 0x3cc, 0x180, 0x0, 0x0, 0x4, 0x0, 0x180},
51 {".fini", SHT_PROGBITS, SHF_ALLOC + SHF_EXECINSTR, 0x804854c, 0x54c, 0xc, 0x0, 0x0, 0x4, 0x0, 0xc},
52 {".rodata", SHT_PROGBITS, SHF_ALLOC, 0x8048558, 0x558, 0xa3, 0x0, 0x0, 0x1, 0x0, 0xa3},
53 {".data", SHT_PROGBITS, SHF_WRITE + SHF_ALLOC, 0x80495fc, 0x5fc, 0xc, 0x0, 0x0, 0x4, 0x0, 0xc},
54 {".eh_frame", SHT_PROGBITS, SHF_ALLOC, 0x8049608, 0x608, 0x4, 0x0, 0x0, 0x4, 0x0, 0x4},
55 {".dynamic", SHT_DYNAMIC, SHF_WRITE + SHF_ALLOC, 0x804960c, 0x60c, 0x98, 0x4, 0x0, 0x4, 0x8, 0x98},
56 {".ctors", SHT_PROGBITS, SHF_WRITE + SHF_ALLOC, 0x80496a4, 0x6a4, 0x8, 0x0, 0x0, 0x4, 0x0, 0x8},
57 {".dtors", SHT_PROGBITS, SHF_WRITE + SHF_ALLOC, 0x80496ac, 0x6ac, 0x8, 0x0, 0x0, 0x4, 0x0, 0x8},
58 {".jcr", SHT_PROGBITS, SHF_WRITE + SHF_ALLOC, 0x80496b4, 0x6b4, 0x4, 0x0, 0x0, 0x4, 0x0, 0x4},
59 {".got", SHT_PROGBITS, SHF_WRITE + SHF_ALLOC, 0x80496b8, 0x6b8, 0x1c, 0x0, 0x0, 0x4, 0x4, 0x1c},
60 {".bss", SHT_NOBITS, SHF_WRITE + SHF_ALLOC, 0x80496d4, 0x6d4, 0x20, 0x0, 0x0, 0x4, 0x0, 0x20},
61 {".comment", SHT_PROGBITS, 0x0, 0x0, 0x6d4, 0x12d, 0x0, 0x0, 0x1, 0x0, 0x12d},
62 {".debug_aranges", SHT_PROGBITS, 0x0, 0x0, 0x801, 0x20, 0x0, 0x0, 0x1, 0x0, 0x20},
63 {".debug_pubnames", SHT_PROGBITS, 0x0, 0x0, 0x821, 0x1b, 0x0, 0x0, 0x1, 0x0, 0x1b},
64 {".debug_info", SHT_PROGBITS, 0x0, 0x0, 0x83c, 0x11d, 0x0, 0x0, 0x1, 0x0, 0x11d},
65 {".debug_abbrev", SHT_PROGBITS, 0x0, 0x0, 0x959, 0x41, 0x0, 0x0, 0x1, 0x0, 0x41},
66 {".debug_line", SHT_PROGBITS, 0x0, 0x0, 0x99a, 0x35, 0x0, 0x0, 0x1, 0x0, 0x35},
67 {".debug_frame", SHT_PROGBITS, 0x0, 0x0, 0x9d0, 0x30, 0x0, 0x0, 0x4, 0x0, 0x30},
68 {".debug_str", SHT_PROGBITS, 0x0, 0x0, 0xa00, 0xd, 0x0, 0x0, 0x1, 0x0, 0xd},
69 {".shstrtab", SHT_STRTAB, 0x0, 0x0, 0xa0d, 0xf8, 0x0, 0x0, 0x1, 0x0, 0xf8},
70 {".symtab", SHT_SYMTAB, 0x0, 0x0, 0xfb8, 0x4b0, 0x1d, 0x38, 0x4, 0x10, 0x4b0},
71 {".strtab", SHT_STRTAB, 0x0, 0x0, 0x1468, 0x206, 0x0, 0x0, 0x1, 0x0, 0x206},
72 },
73 []ProgHeader{
74 {PT_PHDR, PF_R + PF_X, 0x34, 0x8048034, 0x8048034, 0xa0, 0xa0, 0x4},
75 {PT_INTERP, PF_R, 0xd4, 0x80480d4, 0x80480d4, 0x15, 0x15, 0x1},
76 {PT_LOAD, PF_R + PF_X, 0x0, 0x8048000, 0x8048000, 0x5fb, 0x5fb, 0x1000},
77 {PT_LOAD, PF_R + PF_W, 0x5fc, 0x80495fc, 0x80495fc, 0xd8, 0xf8, 0x1000},
78 {PT_DYNAMIC, PF_R + PF_W, 0x60c, 0x804960c, 0x804960c, 0x98, 0x98, 0x4},
79 },
80 []string{"libc.so.6"},
81 []Symbol{
82 {"", 3, 0, false, 0, 1, 134512852, 0, "", ""},
83 {"", 3, 0, false, 0, 2, 134512876, 0, "", ""},
84 {"", 3, 0, false, 0, 3, 134513020, 0, "", ""},
85 {"", 3, 0, false, 0, 4, 134513292, 0, "", ""},
86 {"", 3, 0, false, 0, 5, 134513480, 0, "", ""},
87 {"", 3, 0, false, 0, 6, 134513512, 0, "", ""},
88 {"", 3, 0, false, 0, 7, 134513532, 0, "", ""},
89 {"", 3, 0, false, 0, 8, 134513612, 0, "", ""},
90 {"", 3, 0, false, 0, 9, 134513996, 0, "", ""},
91 {"", 3, 0, false, 0, 10, 134514008, 0, "", ""},
92 {"", 3, 0, false, 0, 11, 134518268, 0, "", ""},
93 {"", 3, 0, false, 0, 12, 134518280, 0, "", ""},
94 {"", 3, 0, false, 0, 13, 134518284, 0, "", ""},
95 {"", 3, 0, false, 0, 14, 134518436, 0, "", ""},
96 {"", 3, 0, false, 0, 15, 134518444, 0, "", ""},
97 {"", 3, 0, false, 0, 16, 134518452, 0, "", ""},
98 {"", 3, 0, false, 0, 17, 134518456, 0, "", ""},
99 {"", 3, 0, false, 0, 18, 134518484, 0, "", ""},
100 {"", 3, 0, false, 0, 19, 0, 0, "", ""},
101 {"", 3, 0, false, 0, 20, 0, 0, "", ""},
102 {"", 3, 0, false, 0, 21, 0, 0, "", ""},
103 {"", 3, 0, false, 0, 22, 0, 0, "", ""},
104 {"", 3, 0, false, 0, 23, 0, 0, "", ""},
105 {"", 3, 0, false, 0, 24, 0, 0, "", ""},
106 {"", 3, 0, false, 0, 25, 0, 0, "", ""},
107 {"", 3, 0, false, 0, 26, 0, 0, "", ""},
108 {"", 3, 0, false, 0, 27, 0, 0, "", ""},
109 {"", 3, 0, false, 0, 28, 0, 0, "", ""},
110 {"", 3, 0, false, 0, 29, 0, 0, "", ""},
111 {"crt1.c", 4, 0, false, 0, 65521, 0, 0, "", ""},
112 {"/usr/src/lib/csu/i386-elf/crti.S", 4, 0, false, 0, 65521, 0, 0, "", ""},
113 {"<command line>", 4, 0, false, 0, 65521, 0, 0, "", ""},
114 {"<built-in>", 4, 0, false, 0, 65521, 0, 0, "", ""},
115 {"/usr/src/lib/csu/i386-elf/crti.S", 4, 0, false, 0, 65521, 0, 0, "", ""},
116 {"crtstuff.c", 4, 0, false, 0, 65521, 0, 0, "", ""},
117 {"__CTOR_LIST__", 1, 0, false, 0, 14, 134518436, 0, "", ""},
118 {"__DTOR_LIST__", 1, 0, false, 0, 15, 134518444, 0, "", ""},
119 {"__EH_FRAME_BEGIN__", 1, 0, false, 0, 12, 134518280, 0, "", ""},
120 {"__JCR_LIST__", 1, 0, false, 0, 16, 134518452, 0, "", ""},
121 {"p.0", 1, 0, false, 0, 11, 134518276, 0, "", ""},
122 {"completed.1", 1, 0, false, 0, 18, 134518484, 1, "", ""},
123 {"__do_global_dtors_aux", 2, 0, false, 0, 8, 134513760, 0, "", ""},
124 {"object.2", 1, 0, false, 0, 18, 134518488, 24, "", ""},
125 {"frame_dummy", 2, 0, false, 0, 8, 134513836, 0, "", ""},
126 {"crtstuff.c", 4, 0, false, 0, 65521, 0, 0, "", ""},
127 {"__CTOR_END__", 1, 0, false, 0, 14, 134518440, 0, "", ""},
128 {"__DTOR_END__", 1, 0, false, 0, 15, 134518448, 0, "", ""},
129 {"__FRAME_END__", 1, 0, false, 0, 12, 134518280, 0, "", ""},
130 {"__JCR_END__", 1, 0, false, 0, 16, 134518452, 0, "", ""},
131 {"__do_global_ctors_aux", 2, 0, false, 0, 8, 134513960, 0, "", ""},
132 {"/usr/src/lib/csu/i386-elf/crtn.S", 4, 0, false, 0, 65521, 0, 0, "", ""},
133 {"<command line>", 4, 0, false, 0, 65521, 0, 0, "", ""},
134 {"<built-in>", 4, 0, false, 0, 65521, 0, 0, "", ""},
135 {"/usr/src/lib/csu/i386-elf/crtn.S", 4, 0, false, 0, 65521, 0, 0, "", ""},
136 {"hello.c", 4, 0, false, 0, 65521, 0, 0, "", ""},
137 {"printf", 18, 0, false, 0, 0, 0, 44, "", ""},
138 {"_DYNAMIC", 17, 0, false, 0, 65521, 134518284, 0, "", ""},
139 {"__dso_handle", 17, 2, false, 0, 11, 134518272, 0, "", ""},
140 {"_init", 18, 0, false, 0, 6, 134513512, 0, "", ""},
141 {"environ", 17, 0, false, 0, 18, 134518512, 4, "", ""},
142 {"__deregister_frame_info", 32, 0, false, 0, 0, 0, 0, "", ""},
143 {"__progname", 17, 0, false, 0, 11, 134518268, 4, "", ""},
144 {"_start", 18, 0, false, 0, 8, 134513612, 145, "", ""},
145 {"__bss_start", 16, 0, false, 0, 65521, 134518484, 0, "", ""},
146 {"main", 18, 0, false, 0, 8, 134513912, 46, "", ""},
147 {"_init_tls", 18, 0, false, 0, 0, 0, 5, "", ""},
148 {"_fini", 18, 0, false, 0, 9, 134513996, 0, "", ""},
149 {"atexit", 18, 0, false, 0, 0, 0, 43, "", ""},
150 {"_edata", 16, 0, false, 0, 65521, 134518484, 0, "", ""},
151 {"_GLOBAL_OFFSET_TABLE_", 17, 0, false, 0, 65521, 134518456, 0, "", ""},
152 {"_end", 16, 0, false, 0, 65521, 134518516, 0, "", ""},
153 {"exit", 18, 0, false, 0, 0, 0, 68, "", ""},
154 {"_Jv_RegisterClasses", 32, 0, false, 0, 0, 0, 0, "", ""},
155 {"__register_frame_info", 32, 0, false, 0, 0, 0, 0, "", ""},
156 },
157 },
158 {
159 "testdata/gcc-amd64-linux-exec",
160 FileHeader{ELFCLASS64, ELFDATA2LSB, EV_CURRENT, ELFOSABI_NONE, 0, binary.LittleEndian, ET_EXEC, EM_X86_64, 0x4003e0},
161 []SectionHeader{
162 {"", SHT_NULL, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0},
163 {".interp", SHT_PROGBITS, SHF_ALLOC, 0x400200, 0x200, 0x1c, 0x0, 0x0, 0x1, 0x0, 0x1c},
164 {".note.ABI-tag", SHT_NOTE, SHF_ALLOC, 0x40021c, 0x21c, 0x20, 0x0, 0x0, 0x4, 0x0, 0x20},
165 {".hash", SHT_HASH, SHF_ALLOC, 0x400240, 0x240, 0x24, 0x5, 0x0, 0x8, 0x4, 0x24},
166 {".gnu.hash", SHT_LOOS + 268435446, SHF_ALLOC, 0x400268, 0x268, 0x1c, 0x5, 0x0, 0x8, 0x0, 0x1c},
167 {".dynsym", SHT_DYNSYM, SHF_ALLOC, 0x400288, 0x288, 0x60, 0x6, 0x1, 0x8, 0x18, 0x60},
168 {".dynstr", SHT_STRTAB, SHF_ALLOC, 0x4002e8, 0x2e8, 0x3d, 0x0, 0x0, 0x1, 0x0, 0x3d},
169 {".gnu.version", SHT_HIOS, SHF_ALLOC, 0x400326, 0x326, 0x8, 0x5, 0x0, 0x2, 0x2, 0x8},
170 {".gnu.version_r", SHT_LOOS + 268435454, SHF_ALLOC, 0x400330, 0x330, 0x20, 0x6, 0x1, 0x8, 0x0, 0x20},
171 {".rela.dyn", SHT_RELA, SHF_ALLOC, 0x400350, 0x350, 0x18, 0x5, 0x0, 0x8, 0x18, 0x18},
172 {".rela.plt", SHT_RELA, SHF_ALLOC, 0x400368, 0x368, 0x30, 0x5, 0xc, 0x8, 0x18, 0x30},
173 {".init", SHT_PROGBITS, SHF_ALLOC + SHF_EXECINSTR, 0x400398, 0x398, 0x18, 0x0, 0x0, 0x4, 0x0, 0x18},
174 {".plt", SHT_PROGBITS, SHF_ALLOC + SHF_EXECINSTR, 0x4003b0, 0x3b0, 0x30, 0x0, 0x0, 0x4, 0x10, 0x30},
175 {".text", SHT_PROGBITS, SHF_ALLOC + SHF_EXECINSTR, 0x4003e0, 0x3e0, 0x1b4, 0x0, 0x0, 0x10, 0x0, 0x1b4},
176 {".fini", SHT_PROGBITS, SHF_ALLOC + SHF_EXECINSTR, 0x400594, 0x594, 0xe, 0x0, 0x0, 0x4, 0x0, 0xe},
177 {".rodata", SHT_PROGBITS, SHF_ALLOC, 0x4005a4, 0x5a4, 0x11, 0x0, 0x0, 0x4, 0x0, 0x11},
178 {".eh_frame_hdr", SHT_PROGBITS, SHF_ALLOC, 0x4005b8, 0x5b8, 0x24, 0x0, 0x0, 0x4, 0x0, 0x24},
179 {".eh_frame", SHT_PROGBITS, SHF_ALLOC, 0x4005e0, 0x5e0, 0xa4, 0x0, 0x0, 0x8, 0x0, 0xa4},
180 {".ctors", SHT_PROGBITS, SHF_WRITE + SHF_ALLOC, 0x600688, 0x688, 0x10, 0x0, 0x0, 0x8, 0x0, 0x10},
181 {".dtors", SHT_PROGBITS, SHF_WRITE + SHF_ALLOC, 0x600698, 0x698, 0x10, 0x0, 0x0, 0x8, 0x0, 0x10},
182 {".jcr", SHT_PROGBITS, SHF_WRITE + SHF_ALLOC, 0x6006a8, 0x6a8, 0x8, 0x0, 0x0, 0x8, 0x0, 0x8},
183 {".dynamic", SHT_DYNAMIC, SHF_WRITE + SHF_ALLOC, 0x6006b0, 0x6b0, 0x1a0, 0x6, 0x0, 0x8, 0x10, 0x1a0},
184 {".got", SHT_PROGBITS, SHF_WRITE + SHF_ALLOC, 0x600850, 0x850, 0x8, 0x0, 0x0, 0x8, 0x8, 0x8},
185 {".got.plt", SHT_PROGBITS, SHF_WRITE + SHF_ALLOC, 0x600858, 0x858, 0x28, 0x0, 0x0, 0x8, 0x8, 0x28},
186 {".data", SHT_PROGBITS, SHF_WRITE + SHF_ALLOC, 0x600880, 0x880, 0x18, 0x0, 0x0, 0x8, 0x0, 0x18},
187 {".bss", SHT_NOBITS, SHF_WRITE + SHF_ALLOC, 0x600898, 0x898, 0x8, 0x0, 0x0, 0x4, 0x0, 0x8},
188 {".comment", SHT_PROGBITS, 0x0, 0x0, 0x898, 0x126, 0x0, 0x0, 0x1, 0x0, 0x126},
189 {".debug_aranges", SHT_PROGBITS, 0x0, 0x0, 0x9c0, 0x90, 0x0, 0x0, 0x10, 0x0, 0x90},
190 {".debug_pubnames", SHT_PROGBITS, 0x0, 0x0, 0xa50, 0x25, 0x0, 0x0, 0x1, 0x0, 0x25},
191 {".debug_info", SHT_PROGBITS, 0x0, 0x0, 0xa75, 0x1a7, 0x0, 0x0, 0x1, 0x0, 0x1a7},
192 {".debug_abbrev", SHT_PROGBITS, 0x0, 0x0, 0xc1c, 0x6f, 0x0, 0x0, 0x1, 0x0, 0x6f},
193 {".debug_line", SHT_PROGBITS, 0x0, 0x0, 0xc8b, 0x13f, 0x0, 0x0, 0x1, 0x0, 0x13f},
194 {".debug_str", SHT_PROGBITS, SHF_MERGE + SHF_STRINGS, 0x0, 0xdca, 0xb1, 0x0, 0x0, 0x1, 0x1, 0xb1},
195 {".debug_ranges", SHT_PROGBITS, 0x0, 0x0, 0xe80, 0x90, 0x0, 0x0, 0x10, 0x0, 0x90},
196 {".shstrtab", SHT_STRTAB, 0x0, 0x0, 0xf10, 0x149, 0x0, 0x0, 0x1, 0x0, 0x149},
197 {".symtab", SHT_SYMTAB, 0x0, 0x0, 0x19a0, 0x6f0, 0x24, 0x39, 0x8, 0x18, 0x6f0},
198 {".strtab", SHT_STRTAB, 0x0, 0x0, 0x2090, 0x1fc, 0x0, 0x0, 0x1, 0x0, 0x1fc},
199 },
200 []ProgHeader{
201 {PT_PHDR, PF_R + PF_X, 0x40, 0x400040, 0x400040, 0x1c0, 0x1c0, 0x8},
202 {PT_INTERP, PF_R, 0x200, 0x400200, 0x400200, 0x1c, 0x1c, 1},
203 {PT_LOAD, PF_R + PF_X, 0x0, 0x400000, 0x400000, 0x684, 0x684, 0x200000},
204 {PT_LOAD, PF_R + PF_W, 0x688, 0x600688, 0x600688, 0x210, 0x218, 0x200000},
205 {PT_DYNAMIC, PF_R + PF_W, 0x6b0, 0x6006b0, 0x6006b0, 0x1a0, 0x1a0, 0x8},
206 {PT_NOTE, PF_R, 0x21c, 0x40021c, 0x40021c, 0x20, 0x20, 0x4},
207 {PT_LOOS + 0x474E550, PF_R, 0x5b8, 0x4005b8, 0x4005b8, 0x24, 0x24, 0x4},
208 {PT_LOOS + 0x474E551, PF_R + PF_W, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8},
209 },
210 []string{"libc.so.6"},
211 []Symbol{
212 {"", 3, 0, false, 0, 1, 4194816, 0, "", ""},
213 {"", 3, 0, false, 0, 2, 4194844, 0, "", ""},
214 {"", 3, 0, false, 0, 3, 4194880, 0, "", ""},
215 {"", 3, 0, false, 0, 4, 4194920, 0, "", ""},
216 {"", 3, 0, false, 0, 5, 4194952, 0, "", ""},
217 {"", 3, 0, false, 0, 6, 4195048, 0, "", ""},
218 {"", 3, 0, false, 0, 7, 4195110, 0, "", ""},
219 {"", 3, 0, false, 0, 8, 4195120, 0, "", ""},
220 {"", 3, 0, false, 0, 9, 4195152, 0, "", ""},
221 {"", 3, 0, false, 0, 10, 4195176, 0, "", ""},
222 {"", 3, 0, false, 0, 11, 4195224, 0, "", ""},
223 {"", 3, 0, false, 0, 12, 4195248, 0, "", ""},
224 {"", 3, 0, false, 0, 13, 4195296, 0, "", ""},
225 {"", 3, 0, false, 0, 14, 4195732, 0, "", ""},
226 {"", 3, 0, false, 0, 15, 4195748, 0, "", ""},
227 {"", 3, 0, false, 0, 16, 4195768, 0, "", ""},
228 {"", 3, 0, false, 0, 17, 4195808, 0, "", ""},
229 {"", 3, 0, false, 0, 18, 6293128, 0, "", ""},
230 {"", 3, 0, false, 0, 19, 6293144, 0, "", ""},
231 {"", 3, 0, false, 0, 20, 6293160, 0, "", ""},
232 {"", 3, 0, false, 0, 21, 6293168, 0, "", ""},
233 {"", 3, 0, false, 0, 22, 6293584, 0, "", ""},
234 {"", 3, 0, false, 0, 23, 6293592, 0, "", ""},
235 {"", 3, 0, false, 0, 24, 6293632, 0, "", ""},
236 {"", 3, 0, false, 0, 25, 6293656, 0, "", ""},
237 {"", 3, 0, false, 0, 26, 0, 0, "", ""},
238 {"", 3, 0, false, 0, 27, 0, 0, "", ""},
239 {"", 3, 0, false, 0, 28, 0, 0, "", ""},
240 {"", 3, 0, false, 0, 29, 0, 0, "", ""},
241 {"", 3, 0, false, 0, 30, 0, 0, "", ""},
242 {"", 3, 0, false, 0, 31, 0, 0, "", ""},
243 {"", 3, 0, false, 0, 32, 0, 0, "", ""},
244 {"", 3, 0, false, 0, 33, 0, 0, "", ""},
245 {"init.c", 4, 0, false, 0, 65521, 0, 0, "", ""},
246 {"initfini.c", 4, 0, false, 0, 65521, 0, 0, "", ""},
247 {"call_gmon_start", 2, 0, false, 0, 13, 4195340, 0, "", ""},
248 {"crtstuff.c", 4, 0, false, 0, 65521, 0, 0, "", ""},
249 {"__CTOR_LIST__", 1, 0, false, 0, 18, 6293128, 0, "", ""},
250 {"__DTOR_LIST__", 1, 0, false, 0, 19, 6293144, 0, "", ""},
251 {"__JCR_LIST__", 1, 0, false, 0, 20, 6293160, 0, "", ""},
252 {"__do_global_dtors_aux", 2, 0, false, 0, 13, 4195376, 0, "", ""},
253 {"completed.6183", 1, 0, false, 0, 25, 6293656, 1, "", ""},
254 {"p.6181", 1, 0, false, 0, 24, 6293648, 0, "", ""},
255 {"frame_dummy", 2, 0, false, 0, 13, 4195440, 0, "", ""},
256 {"crtstuff.c", 4, 0, false, 0, 65521, 0, 0, "", ""},
257 {"__CTOR_END__", 1, 0, false, 0, 18, 6293136, 0, "", ""},
258 {"__DTOR_END__", 1, 0, false, 0, 19, 6293152, 0, "", ""},
259 {"__FRAME_END__", 1, 0, false, 0, 17, 4195968, 0, "", ""},
260 {"__JCR_END__", 1, 0, false, 0, 20, 6293160, 0, "", ""},
261 {"__do_global_ctors_aux", 2, 0, false, 0, 13, 4195680, 0, "", ""},
262 {"initfini.c", 4, 0, false, 0, 65521, 0, 0, "", ""},
263 {"hello.c", 4, 0, false, 0, 65521, 0, 0, "", ""},
264 {"_GLOBAL_OFFSET_TABLE_", 1, 2, false, 0, 23, 6293592, 0, "", ""},
265 {"__init_array_end", 0, 2, false, 0, 18, 6293124, 0, "", ""},
266 {"__init_array_start", 0, 2, false, 0, 18, 6293124, 0, "", ""},
267 {"_DYNAMIC", 1, 2, false, 0, 21, 6293168, 0, "", ""},
268 {"data_start", 32, 0, false, 0, 24, 6293632, 0, "", ""},
269 {"__libc_csu_fini", 18, 0, false, 0, 13, 4195520, 2, "", ""},
270 {"_start", 18, 0, false, 0, 13, 4195296, 0, "", ""},
271 {"__gmon_start__", 32, 0, false, 0, 0, 0, 0, "", ""},
272 {"_Jv_RegisterClasses", 32, 0, false, 0, 0, 0, 0, "", ""},
273 {"puts@@GLIBC_2.2.5", 18, 0, false, 0, 0, 0, 396, "", ""},
274 {"_fini", 18, 0, false, 0, 14, 4195732, 0, "", ""},
275 {"__libc_start_main@@GLIBC_2.2.5", 18, 0, false, 0, 0, 0, 450, "", ""},
276 {"_IO_stdin_used", 17, 0, false, 0, 15, 4195748, 4, "", ""},
277 {"__data_start", 16, 0, false, 0, 24, 6293632, 0, "", ""},
278 {"__dso_handle", 17, 2, false, 0, 24, 6293640, 0, "", ""},
279 {"__libc_csu_init", 18, 0, false, 0, 13, 4195536, 137, "", ""},
280 {"__bss_start", 16, 0, false, 0, 65521, 6293656, 0, "", ""},
281 {"_end", 16, 0, false, 0, 65521, 6293664, 0, "", ""},
282 {"_edata", 16, 0, false, 0, 65521, 6293656, 0, "", ""},
283 {"main", 18, 0, false, 0, 13, 4195480, 27, "", ""},
284 {"_init", 18, 0, false, 0, 11, 4195224, 0, "", ""},
285 },
286 },
287 {
288 "testdata/hello-world-core.gz",
289 FileHeader{ELFCLASS64, ELFDATA2LSB, EV_CURRENT, ELFOSABI_NONE, 0x0, binary.LittleEndian, ET_CORE, EM_X86_64, 0x0},
290 []SectionHeader{},
291 []ProgHeader{
292 {Type: PT_NOTE, Flags: 0x0, Off: 0x3f8, Vaddr: 0x0, Paddr: 0x0, Filesz: 0x8ac, Memsz: 0x0, Align: 0x0},
293 {Type: PT_LOAD, Flags: PF_X + PF_R, Off: 0x1000, Vaddr: 0x400000, Paddr: 0x0, Filesz: 0x0, Memsz: 0x1000, Align: 0x1000},
294 {Type: PT_LOAD, Flags: PF_R, Off: 0x1000, Vaddr: 0x401000, Paddr: 0x0, Filesz: 0x1000, Memsz: 0x1000, Align: 0x1000},
295 {Type: PT_LOAD, Flags: PF_W + PF_R, Off: 0x2000, Vaddr: 0x402000, Paddr: 0x0, Filesz: 0x1000, Memsz: 0x1000, Align: 0x1000},
296 {Type: PT_LOAD, Flags: PF_X + PF_R, Off: 0x3000, Vaddr: 0x7f54078b8000, Paddr: 0x0, Filesz: 0x0, Memsz: 0x1b5000, Align: 0x1000},
297 {Type: PT_LOAD, Flags: 0x0, Off: 0x3000, Vaddr: 0x7f5407a6d000, Paddr: 0x0, Filesz: 0x0, Memsz: 0x1ff000, Align: 0x1000},
298 {Type: PT_LOAD, Flags: PF_R, Off: 0x3000, Vaddr: 0x7f5407c6c000, Paddr: 0x0, Filesz: 0x4000, Memsz: 0x4000, Align: 0x1000},
299 {Type: PT_LOAD, Flags: PF_W + PF_R, Off: 0x7000, Vaddr: 0x7f5407c70000, Paddr: 0x0, Filesz: 0x2000, Memsz: 0x2000, Align: 0x1000},
300 {Type: PT_LOAD, Flags: PF_W + PF_R, Off: 0x9000, Vaddr: 0x7f5407c72000, Paddr: 0x0, Filesz: 0x5000, Memsz: 0x5000, Align: 0x1000},
301 {Type: PT_LOAD, Flags: PF_X + PF_R, Off: 0xe000, Vaddr: 0x7f5407c77000, Paddr: 0x0, Filesz: 0x0, Memsz: 0x22000, Align: 0x1000},
302 {Type: PT_LOAD, Flags: PF_W + PF_R, Off: 0xe000, Vaddr: 0x7f5407e81000, Paddr: 0x0, Filesz: 0x3000, Memsz: 0x3000, Align: 0x1000},
303 {Type: PT_LOAD, Flags: PF_W + PF_R, Off: 0x11000, Vaddr: 0x7f5407e96000, Paddr: 0x0, Filesz: 0x3000, Memsz: 0x3000, Align: 0x1000},
304 {Type: PT_LOAD, Flags: PF_R, Off: 0x14000, Vaddr: 0x7f5407e99000, Paddr: 0x0, Filesz: 0x1000, Memsz: 0x1000, Align: 0x1000},
305 {Type: PT_LOAD, Flags: PF_W + PF_R, Off: 0x15000, Vaddr: 0x7f5407e9a000, Paddr: 0x0, Filesz: 0x2000, Memsz: 0x2000, Align: 0x1000},
306 {Type: PT_LOAD, Flags: PF_W + PF_R, Off: 0x17000, Vaddr: 0x7fff79972000, Paddr: 0x0, Filesz: 0x23000, Memsz: 0x23000, Align: 0x1000},
307 {Type: PT_LOAD, Flags: PF_X + PF_R, Off: 0x3a000, Vaddr: 0x7fff799f8000, Paddr: 0x0, Filesz: 0x1000, Memsz: 0x1000, Align: 0x1000},
308 {Type: PT_LOAD, Flags: PF_X + PF_R, Off: 0x3b000, Vaddr: 0xffffffffff600000, Paddr: 0x0, Filesz: 0x1000, Memsz: 0x1000, Align: 0x1000},
309 },
310 nil,
311 nil,
312 },
313 {
314 "testdata/compressed-32.obj",
315 FileHeader{ELFCLASS32, ELFDATA2LSB, EV_CURRENT, ELFOSABI_NONE, 0x0, binary.LittleEndian, ET_REL, EM_386, 0x0},
316 []SectionHeader{
317 {"", SHT_NULL, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0},
318 {".text", SHT_PROGBITS, SHF_ALLOC | SHF_EXECINSTR, 0x0, 0x34, 0x17, 0x0, 0x0, 0x1, 0x0, 0x17},
319 {".rel.text", SHT_REL, SHF_INFO_LINK, 0x0, 0x3dc, 0x10, 0x13, 0x1, 0x4, 0x8, 0x10},
320 {".data", SHT_PROGBITS, SHF_WRITE | SHF_ALLOC, 0x0, 0x4b, 0x0, 0x0, 0x0, 0x1, 0x0, 0x0},
321 {".bss", SHT_NOBITS, SHF_WRITE | SHF_ALLOC, 0x0, 0x4b, 0x0, 0x0, 0x0, 0x1, 0x0, 0x0},
322 {".rodata", SHT_PROGBITS, SHF_ALLOC, 0x0, 0x4b, 0xd, 0x0, 0x0, 0x1, 0x0, 0xd},
323 {".debug_info", SHT_PROGBITS, SHF_COMPRESSED, 0x0, 0x58, 0xb4, 0x0, 0x0, 0x1, 0x0, 0x84},
324 {".rel.debug_info", SHT_REL, SHF_INFO_LINK, 0x0, 0x3ec, 0xa0, 0x13, 0x6, 0x4, 0x8, 0xa0},
325 {".debug_abbrev", SHT_PROGBITS, 0x0, 0x0, 0xdc, 0x5a, 0x0, 0x0, 0x1, 0x0, 0x5a},
326 {".debug_aranges", SHT_PROGBITS, 0x0, 0x0, 0x136, 0x20, 0x0, 0x0, 0x1, 0x0, 0x20},
327 {".rel.debug_aranges", SHT_REL, SHF_INFO_LINK, 0x0, 0x48c, 0x10, 0x13, 0x9, 0x4, 0x8, 0x10},
328 {".debug_line", SHT_PROGBITS, 0x0, 0x0, 0x156, 0x5c, 0x0, 0x0, 0x1, 0x0, 0x5c},
329 {".rel.debug_line", SHT_REL, SHF_INFO_LINK, 0x0, 0x49c, 0x8, 0x13, 0xb, 0x4, 0x8, 0x8},
330 {".debug_str", SHT_PROGBITS, SHF_MERGE | SHF_STRINGS | SHF_COMPRESSED, 0x0, 0x1b2, 0x10f, 0x0, 0x0, 0x1, 0x1, 0xb3},
331 {".comment", SHT_PROGBITS, SHF_MERGE | SHF_STRINGS, 0x0, 0x265, 0x2a, 0x0, 0x0, 0x1, 0x1, 0x2a},
332 {".note.GNU-stack", SHT_PROGBITS, 0x0, 0x0, 0x28f, 0x0, 0x0, 0x0, 0x1, 0x0, 0x0},
333 {".eh_frame", SHT_PROGBITS, SHF_ALLOC, 0x0, 0x290, 0x38, 0x0, 0x0, 0x4, 0x0, 0x38},
334 {".rel.eh_frame", SHT_REL, SHF_INFO_LINK, 0x0, 0x4a4, 0x8, 0x13, 0x10, 0x4, 0x8, 0x8},
335 {".shstrtab", SHT_STRTAB, 0x0, 0x0, 0x4ac, 0xab, 0x0, 0x0, 0x1, 0x0, 0xab},
336 {".symtab", SHT_SYMTAB, 0x0, 0x0, 0x2c8, 0x100, 0x14, 0xe, 0x4, 0x10, 0x100},
337 {".strtab", SHT_STRTAB, 0x0, 0x0, 0x3c8, 0x13, 0x0, 0x0, 0x1, 0x0, 0x13},
338 },
339 []ProgHeader{},
340 nil,
341 []Symbol{
342 {"hello.c", 4, 0, false, 0, 65521, 0, 0, "", ""},
343 {"", 3, 0, false, 0, 1, 0, 0, "", ""},
344 {"", 3, 0, false, 0, 3, 0, 0, "", ""},
345 {"", 3, 0, false, 0, 4, 0, 0, "", ""},
346 {"", 3, 0, false, 0, 5, 0, 0, "", ""},
347 {"", 3, 0, false, 0, 6, 0, 0, "", ""},
348 {"", 3, 0, false, 0, 8, 0, 0, "", ""},
349 {"", 3, 0, false, 0, 9, 0, 0, "", ""},
350 {"", 3, 0, false, 0, 11, 0, 0, "", ""},
351 {"", 3, 0, false, 0, 13, 0, 0, "", ""},
352 {"", 3, 0, false, 0, 15, 0, 0, "", ""},
353 {"", 3, 0, false, 0, 16, 0, 0, "", ""},
354 {"", 3, 0, false, 0, 14, 0, 0, "", ""},
355 {"main", 18, 0, false, 0, 1, 0, 23, "", ""},
356 {"puts", 16, 0, false, 0, 0, 0, 0, "", ""},
357 },
358 },
359 {
360 "testdata/compressed-64.obj",
361 FileHeader{ELFCLASS64, ELFDATA2LSB, EV_CURRENT, ELFOSABI_NONE, 0x0, binary.LittleEndian, ET_REL, EM_X86_64, 0x0},
362 []SectionHeader{
363 {"", SHT_NULL, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0},
364 {".text", SHT_PROGBITS, SHF_ALLOC | SHF_EXECINSTR, 0x0, 0x40, 0x1b, 0x0, 0x0, 0x1, 0x0, 0x1b},
365 {".rela.text", SHT_RELA, SHF_INFO_LINK, 0x0, 0x488, 0x30, 0x13, 0x1, 0x8, 0x18, 0x30},
366 {".data", SHT_PROGBITS, SHF_WRITE | SHF_ALLOC, 0x0, 0x5b, 0x0, 0x0, 0x0, 0x1, 0x0, 0x0},
367 {".bss", SHT_NOBITS, SHF_WRITE | SHF_ALLOC, 0x0, 0x5b, 0x0, 0x0, 0x0, 0x1, 0x0, 0x0},
368 {".rodata", SHT_PROGBITS, SHF_ALLOC, 0x0, 0x5b, 0xd, 0x0, 0x0, 0x1, 0x0, 0xd},
369 {".debug_info", SHT_PROGBITS, SHF_COMPRESSED, 0x0, 0x68, 0xba, 0x0, 0x0, 0x1, 0x0, 0x72},
370 {".rela.debug_info", SHT_RELA, SHF_INFO_LINK, 0x0, 0x4b8, 0x1c8, 0x13, 0x6, 0x8, 0x18, 0x1c8},
371 {".debug_abbrev", SHT_PROGBITS, 0x0, 0x0, 0xda, 0x5c, 0x0, 0x0, 0x1, 0x0, 0x5c},
372 {".debug_aranges", SHT_PROGBITS, SHF_COMPRESSED, 0x0, 0x136, 0x30, 0x0, 0x0, 0x1, 0x0, 0x2f},
373 {".rela.debug_aranges", SHT_RELA, SHF_INFO_LINK, 0x0, 0x680, 0x30, 0x13, 0x9, 0x8, 0x18, 0x30},
374 {".debug_line", SHT_PROGBITS, 0x0, 0x0, 0x165, 0x60, 0x0, 0x0, 0x1, 0x0, 0x60},
375 {".rela.debug_line", SHT_RELA, SHF_INFO_LINK, 0x0, 0x6b0, 0x18, 0x13, 0xb, 0x8, 0x18, 0x18},
376 {".debug_str", SHT_PROGBITS, SHF_MERGE | SHF_STRINGS | SHF_COMPRESSED, 0x0, 0x1c5, 0x104, 0x0, 0x0, 0x1, 0x1, 0xc3},
377 {".comment", SHT_PROGBITS, SHF_MERGE | SHF_STRINGS, 0x0, 0x288, 0x2a, 0x0, 0x0, 0x1, 0x1, 0x2a},
378 {".note.GNU-stack", SHT_PROGBITS, 0x0, 0x0, 0x2b2, 0x0, 0x0, 0x0, 0x1, 0x0, 0x0},
379 {".eh_frame", SHT_PROGBITS, SHF_ALLOC, 0x0, 0x2b8, 0x38, 0x0, 0x0, 0x8, 0x0, 0x38},
380 {".rela.eh_frame", SHT_RELA, SHF_INFO_LINK, 0x0, 0x6c8, 0x18, 0x13, 0x10, 0x8, 0x18, 0x18},
381 {".shstrtab", SHT_STRTAB, 0x0, 0x0, 0x6e0, 0xb0, 0x0, 0x0, 0x1, 0x0, 0xb0},
382 {".symtab", SHT_SYMTAB, 0x0, 0x0, 0x2f0, 0x180, 0x14, 0xe, 0x8, 0x18, 0x180},
383 {".strtab", SHT_STRTAB, 0x0, 0x0, 0x470, 0x13, 0x0, 0x0, 0x1, 0x0, 0x13},
384 },
385 []ProgHeader{},
386 nil,
387 []Symbol{
388 {"hello.c", 4, 0, false, 0, 65521, 0, 0, "", ""},
389 {"", 3, 0, false, 0, 1, 0, 0, "", ""},
390 {"", 3, 0, false, 0, 3, 0, 0, "", ""},
391 {"", 3, 0, false, 0, 4, 0, 0, "", ""},
392 {"", 3, 0, false, 0, 5, 0, 0, "", ""},
393 {"", 3, 0, false, 0, 6, 0, 0, "", ""},
394 {"", 3, 0, false, 0, 8, 0, 0, "", ""},
395 {"", 3, 0, false, 0, 9, 0, 0, "", ""},
396 {"", 3, 0, false, 0, 11, 0, 0, "", ""},
397 {"", 3, 0, false, 0, 13, 0, 0, "", ""},
398 {"", 3, 0, false, 0, 15, 0, 0, "", ""},
399 {"", 3, 0, false, 0, 16, 0, 0, "", ""},
400 {"", 3, 0, false, 0, 14, 0, 0, "", ""},
401 {"main", 18, 0, false, 0, 1, 0, 27, "", ""},
402 {"puts", 16, 0, false, 0, 0, 0, 0, "", ""},
403 },
404 },
405 {
406 "testdata/go-relocation-test-gcc620-sparc64.obj",
407 FileHeader{Class: ELFCLASS64, Data: ELFDATA2MSB, Version: EV_CURRENT, OSABI: ELFOSABI_NONE, ABIVersion: 0x0, ByteOrder: binary.BigEndian, Type: ET_REL, Machine: EM_SPARCV9, Entry: 0x0},
408 []SectionHeader{
409 {"", SHT_NULL, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0},
410 {".text", SHT_PROGBITS, SHF_ALLOC + SHF_EXECINSTR, 0x0, 0x40, 0x2c, 0x0, 0x0, 0x4, 0x0, 0x2c},
411 {".rela.text", SHT_RELA, SHF_INFO_LINK, 0x0, 0xa58, 0x48, 0x13, 0x1, 0x8, 0x18, 0x48},
412 {".data", SHT_PROGBITS, SHF_WRITE + SHF_ALLOC, 0x0, 0x6c, 0x0, 0x0, 0x0, 0x1, 0x0, 0x0},
413 {".bss", SHT_NOBITS, SHF_WRITE + SHF_ALLOC, 0x0, 0x6c, 0x0, 0x0, 0x0, 0x1, 0x0, 0x0},
414 {".rodata", SHT_PROGBITS, SHF_ALLOC, 0x0, 0x70, 0xd, 0x0, 0x0, 0x8, 0x0, 0xd},
415 {".debug_info", SHT_PROGBITS, 0x0, 0x0, 0x7d, 0x346, 0x0, 0x0, 0x1, 0x0, 0x346},
416 {".rela.debug_info", SHT_RELA, SHF_INFO_LINK, 0x0, 0xaa0, 0x630, 0x13, 0x6, 0x8, 0x18, 0x630},
417 {".debug_abbrev", SHT_PROGBITS, 0x0, 0x0, 0x3c3, 0xf1, 0x0, 0x0, 0x1, 0x0, 0xf1},
418 {".debug_aranges", SHT_PROGBITS, 0x0, 0x0, 0x4b4, 0x30, 0x0, 0x0, 0x1, 0x0, 0x30},
419 {".rela.debug_aranges", SHT_RELA, SHF_INFO_LINK, 0x0, 0x10d0, 0x30, 0x13, 0x9, 0x8, 0x18, 0x30},
420 {".debug_line", SHT_PROGBITS, 0x0, 0x0, 0x4e4, 0xd3, 0x0, 0x0, 0x1, 0x0, 0xd3},
421 {".rela.debug_line", SHT_RELA, SHF_INFO_LINK, 0x0, 0x1100, 0x18, 0x13, 0xb, 0x8, 0x18, 0x18},
422 {".debug_str", SHT_PROGBITS, SHF_MERGE + SHF_STRINGS, 0x0, 0x5b7, 0x2a3, 0x0, 0x0, 0x1, 0x1, 0x2a3},
423 {".comment", SHT_PROGBITS, SHF_MERGE + SHF_STRINGS, 0x0, 0x85a, 0x2e, 0x0, 0x0, 0x1, 0x1, 0x2e},
424 {".note.GNU-stack", SHT_PROGBITS, 0x0, 0x0, 0x888, 0x0, 0x0, 0x0, 0x1, 0x0, 0x0},
425 {".debug_frame", SHT_PROGBITS, 0x0, 0x0, 0x888, 0x38, 0x0, 0x0, 0x8, 0x0, 0x38},
426 {".rela.debug_frame", SHT_RELA, SHF_INFO_LINK, 0x0, 0x1118, 0x30, 0x13, 0x10, 0x8, 0x18, 0x30},
427 {".shstrtab", SHT_STRTAB, 0x0, 0x0, 0x1148, 0xb3, 0x0, 0x0, 0x1, 0x0, 0xb3},
428 {".symtab", SHT_SYMTAB, 0x0, 0x0, 0x8c0, 0x180, 0x14, 0xe, 0x8, 0x18, 0x180},
429 {".strtab", SHT_STRTAB, 0x0, 0x0, 0xa40, 0x13, 0x0, 0x0, 0x1, 0x0, 0x13},
430 },
431 []ProgHeader{},
432 nil,
433 []Symbol{
434 {"hello.c", 4, 0, false, 0, 65521, 0, 0, "", ""},
435 {"", 3, 0, false, 0, 1, 0, 0, "", ""},
436 {"", 3, 0, false, 0, 3, 0, 0, "", ""},
437 {"", 3, 0, false, 0, 4, 0, 0, "", ""},
438 {"", 3, 0, false, 0, 5, 0, 0, "", ""},
439 {"", 3, 0, false, 0, 6, 0, 0, "", ""},
440 {"", 3, 0, false, 0, 8, 0, 0, "", ""},
441 {"", 3, 0, false, 0, 9, 0, 0, "", ""},
442 {"", 3, 0, false, 0, 11, 0, 0, "", ""},
443 {"", 3, 0, false, 0, 13, 0, 0, "", ""},
444 {"", 3, 0, false, 0, 15, 0, 0, "", ""},
445 {"", 3, 0, false, 0, 16, 0, 0, "", ""},
446 {"", 3, 0, false, 0, 14, 0, 0, "", ""},
447 {"main", 18, 0, false, 0, 1, 0, 44, "", ""},
448 {"puts", 16, 0, false, 0, 0, 0, 0, "", ""},
449 },
450 },
451 {
452 "testdata/gcc-riscv64-linux-exec",
453 FileHeader{ELFCLASS64, ELFDATA2LSB, EV_CURRENT, ELFOSABI_NONE, 0, binary.LittleEndian, ET_EXEC, EM_RISCV, 0x10460},
454 []SectionHeader{
455 {"", SHT_NULL, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0},
456 {".interp", SHT_PROGBITS, SHF_ALLOC, 0x10270, 0x270, 0x21, 0x0, 0x0, 0x1, 0x0, 0x21},
457 {".note.gnu.build-id", SHT_NOTE, SHF_ALLOC, 0x10294, 0x294, 0x24, 0x0, 0x0, 0x4, 0x0, 0x24},
458 {".note.ABI-tag", SHT_NOTE, SHF_ALLOC, 0x102b8, 0x2b8, 0x20, 0x0, 0x0, 0x4, 0x0, 0x20},
459 {".gnu.hash", SHT_GNU_HASH, SHF_ALLOC, 0x102d8, 0x2d8, 0x30, 0x5, 0x0, 0x8, 0x0, 0x30},
460 {".dynsym", SHT_DYNSYM, SHF_ALLOC, 0x10308, 0x308, 0x60, 0x6, 0x1, 0x8, 0x18, 0x60},
461 {".dynstr", SHT_STRTAB, SHF_ALLOC, 0x10368, 0x368, 0x4a, 0x0, 0x0, 0x1, 0x0, 0x4a},
462 {".gnu.version", SHT_GNU_VERSYM, SHF_ALLOC, 0x103b2, 0x3b2, 0x8, 0x5, 0x0, 0x2, 0x2, 0x8},
463 {".gnu.version_r", SHT_GNU_VERNEED, SHF_ALLOC, 0x103c0, 0x3c0, 0x30, 0x6, 0x1, 0x8, 0x0, 0x30},
464 {".rela.plt", SHT_RELA, SHF_ALLOC + SHF_INFO_LINK, 0x103f0, 0x3f0, 0x30, 0x5, 0x14, 0x8, 0x18, 0x30},
465 {".plt", SHT_PROGBITS, SHF_ALLOC + SHF_EXECINSTR, 0x10420, 0x420, 0x40, 0x0, 0x0, 0x10, 0x10, 0x40},
466 {".text", SHT_PROGBITS, SHF_ALLOC + SHF_EXECINSTR, 0x10460, 0x460, 0xd8, 0x0, 0x0, 0x4, 0x0, 0xd8},
467 {".rodata", SHT_PROGBITS, SHF_ALLOC, 0x10538, 0x538, 0x15, 0x0, 0x0, 0x8, 0x0, 0x15},
468 {".eh_frame_hdr", SHT_PROGBITS, SHF_ALLOC, 0x10550, 0x550, 0x24, 0x0, 0x0, 0x4, 0x0, 0x24},
469 {".eh_frame", SHT_PROGBITS, SHF_ALLOC, 0x10578, 0x578, 0x6c, 0x0, 0x0, 0x8, 0x0, 0x6c},
470 {".preinit_array", SHT_PREINIT_ARRAY, SHF_WRITE + SHF_ALLOC, 0x11e00, 0xe00, 0x8, 0x0, 0x0, 0x1, 0x8, 0x8},
471 {".init_array", SHT_INIT_ARRAY, SHF_WRITE + SHF_ALLOC, 0x11e08, 0xe08, 0x8, 0x0, 0x0, 0x8, 0x8, 0x8},
472 {".fini_array", SHT_FINI_ARRAY, SHF_WRITE + SHF_ALLOC, 0x11e10, 0xe10, 0x8, 0x0, 0x0, 0x8, 0x8, 0x8},
473 {".dynamic", SHT_DYNAMIC, SHF_WRITE + SHF_ALLOC, 0x11e18, 0xe18, 0x1d0, 0x6, 0x0, 0x8, 0x10, 0x1d0},
474 {".got", SHT_PROGBITS, SHF_WRITE + SHF_ALLOC, 0x11fe8, 0xfe8, 0x8, 0x0, 0x0, 0x8, 0x8, 0x8},
475 {".got.plt", SHT_PROGBITS, SHF_WRITE + SHF_ALLOC, 0x11ff0, 0xff0, 0x20, 0x0, 0x0, 0x8, 0x8, 0x20},
476 {".sdata", SHT_PROGBITS, SHF_WRITE + SHF_ALLOC, 0x12010, 0x1010, 0x8, 0x0, 0x0, 0x8, 0x0, 0x8},
477 {".bss", SHT_NOBITS, SHF_WRITE + SHF_ALLOC, 0x12018, 0x1018, 0x8, 0x0, 0x0, 0x1, 0x0, 0x8},
478 {".comment", SHT_PROGBITS, SHF_MERGE + SHF_STRINGS, 0x0, 0x1018, 0x26, 0x0, 0x0, 0x1, 0x1, 0x26},
479 {".riscv.attributes", SHT_RISCV_ATTRIBUTES, 0x0, 0x0, 0x103e, 0x66, 0x0, 0x0, 0x1, 0x0, 0x66},
480 {".shstrtab", SHT_STRTAB, 0x0, 0x0, 0x10a4, 0xff, 0x0, 0x0, 0x1, 0x0, 0xff},
481 },
482 []ProgHeader{
483 {PT_PHDR, PF_R, 0x40, 0x10040, 0x10040, 0x230, 0x230, 0x8},
484 {PT_INTERP, PF_R, 0x270, 0x10270, 0x10270, 0x21, 0x21, 0x1},
485 {PT_RISCV_ATTRIBUTES, PF_R, 0x103e, 0x0, 0x0, 0x66, 0x0, 0x1},
486 {PT_LOAD, PF_X + PF_R, 0x0, 0x10000, 0x10000, 0x5e4, 0x5e4, 0x1000},
487 {PT_LOAD, PF_W + PF_R, 0xe00, 0x11e00, 0x11e00, 0x218, 0x220, 0x1000},
488 {PT_DYNAMIC, PF_W + PF_R, 0xe18, 0x11e18, 0x11e18, 0x1d0, 0x1d0, 0x8},
489 {PT_NOTE, PF_R, 0x294, 0x10294, 0x10294, 0x44, 0x44, 0x4},
490 {PT_GNU_EH_FRAME, PF_R, 0x550, 0x10550, 0x10550, 0x24, 0x24, 0x4},
491 {PT_GNU_STACK, PF_W + PF_R, 0x0, 0x0, 0x0, 0x0, 0x0, 0x10},
492 {PT_GNU_RELRO, PF_R, 0xe00, 0x11e00, 0x11e00, 0x200, 0x200, 0x1},
493 },
494 []string{"libc.so.6"},
495 nil,
496 },
497 }
498
499 func TestOpen(t *testing.T) {
500 for i := range fileTests {
501 tt := &fileTests[i]
502
503 var f *File
504 var err error
505 if path.Ext(tt.file) == ".gz" {
506 var r io.ReaderAt
507 if r, err = decompress(tt.file); err == nil {
508 f, err = NewFile(r)
509 }
510 } else {
511 f, err = Open(tt.file)
512 }
513 if err != nil {
514 t.Errorf("cannot open file %s: %v", tt.file, err)
515 continue
516 }
517 defer f.Close()
518 if f.FileHeader != tt.hdr {
519 t.Errorf("open %s:\n\thave %#v\n\twant %#v\n", tt.file, f.FileHeader, tt.hdr)
520 continue
521 }
522 for i, s := range f.Sections {
523 if i >= len(tt.sections) {
524 break
525 }
526 sh := tt.sections[i]
527 if s.SectionHeader != sh {
528 t.Errorf("open %s, section %d:\n\thave %#v\n\twant %#v\n", tt.file, i, s.SectionHeader, sh)
529 }
530 }
531 for i, p := range f.Progs {
532 if i >= len(tt.progs) {
533 break
534 }
535 ph := tt.progs[i]
536 if p.ProgHeader != ph {
537 t.Errorf("open %s, program %d:\n\thave %#v\n\twant %#v\n", tt.file, i, p.ProgHeader, ph)
538 }
539 }
540 tn := len(tt.sections)
541 fn := len(f.Sections)
542 if tn != fn {
543 t.Errorf("open %s: len(Sections) = %d, want %d", tt.file, fn, tn)
544 }
545 tn = len(tt.progs)
546 fn = len(f.Progs)
547 if tn != fn {
548 t.Errorf("open %s: len(Progs) = %d, want %d", tt.file, fn, tn)
549 }
550 tl := tt.needed
551 fl, err := f.ImportedLibraries()
552 if err != nil {
553 t.Error(err)
554 }
555 if !reflect.DeepEqual(tl, fl) {
556 t.Errorf("open %s: DT_NEEDED = %v, want %v", tt.file, tl, fl)
557 }
558 symbols, err := f.Symbols()
559 if tt.symbols == nil {
560 if !errors.Is(err, ErrNoSymbols) {
561 t.Errorf("open %s: Symbols() expected ErrNoSymbols, have nil", tt.file)
562 }
563 if symbols != nil {
564 t.Errorf("open %s: Symbols() expected no symbols, have %v", tt.file, symbols)
565 }
566 } else {
567 if err != nil {
568 t.Errorf("open %s: Symbols() unexpected error %v", tt.file, err)
569 }
570 if !slices.Equal(symbols, tt.symbols) {
571 t.Errorf("open %s: Symbols() = %v, want %v", tt.file, symbols, tt.symbols)
572 }
573 }
574 }
575 }
576
577
578
579 func decompress(gz string) (io.ReaderAt, error) {
580 in, err := os.Open(gz)
581 if err != nil {
582 return nil, err
583 }
584 defer in.Close()
585 r, err := gzip.NewReader(in)
586 if err != nil {
587 return nil, err
588 }
589 var out bytes.Buffer
590 _, err = io.Copy(&out, r)
591 return bytes.NewReader(out.Bytes()), err
592 }
593
594 type relocationTestEntry struct {
595 entryNumber int
596 entry *dwarf.Entry
597 pcRanges [][2]uint64
598 }
599
600 type relocationTest struct {
601 file string
602 entries []relocationTestEntry
603 }
604
605 var relocationTests = []relocationTest{
606 {
607 "testdata/go-relocation-test-gcc441-x86-64.obj",
608 []relocationTestEntry{
609 {
610 entry: &dwarf.Entry{
611 Offset: 0xb,
612 Tag: dwarf.TagCompileUnit,
613 Children: true,
614 Field: []dwarf.Field{
615 {Attr: dwarf.AttrProducer, Val: "GNU C 4.4.1", Class: dwarf.ClassString},
616 {Attr: dwarf.AttrLanguage, Val: int64(1), Class: dwarf.ClassConstant},
617 {Attr: dwarf.AttrName, Val: "go-relocation-test.c", Class: dwarf.ClassString},
618 {Attr: dwarf.AttrCompDir, Val: "/tmp", Class: dwarf.ClassString},
619 {Attr: dwarf.AttrLowpc, Val: uint64(0x0), Class: dwarf.ClassAddress},
620 {Attr: dwarf.AttrHighpc, Val: uint64(0x6), Class: dwarf.ClassAddress},
621 {Attr: dwarf.AttrStmtList, Val: int64(0), Class: dwarf.ClassLinePtr},
622 },
623 },
624 pcRanges: [][2]uint64{{0x0, 0x6}},
625 },
626 },
627 },
628 {
629 "testdata/go-relocation-test-gcc441-x86.obj",
630 []relocationTestEntry{
631 {
632 entry: &dwarf.Entry{
633 Offset: 0xb,
634 Tag: dwarf.TagCompileUnit,
635 Children: true,
636 Field: []dwarf.Field{
637 {Attr: dwarf.AttrProducer, Val: "GNU C 4.4.1", Class: dwarf.ClassString},
638 {Attr: dwarf.AttrLanguage, Val: int64(1), Class: dwarf.ClassConstant},
639 {Attr: dwarf.AttrName, Val: "t.c", Class: dwarf.ClassString},
640 {Attr: dwarf.AttrCompDir, Val: "/tmp", Class: dwarf.ClassString},
641 {Attr: dwarf.AttrLowpc, Val: uint64(0x0), Class: dwarf.ClassAddress},
642 {Attr: dwarf.AttrHighpc, Val: uint64(0x5), Class: dwarf.ClassAddress},
643 {Attr: dwarf.AttrStmtList, Val: int64(0), Class: dwarf.ClassLinePtr},
644 },
645 },
646 pcRanges: [][2]uint64{{0x0, 0x5}},
647 },
648 },
649 },
650 {
651 "testdata/go-relocation-test-gcc424-x86-64.obj",
652 []relocationTestEntry{
653 {
654 entry: &dwarf.Entry{
655 Offset: 0xb,
656 Tag: dwarf.TagCompileUnit,
657 Children: true,
658 Field: []dwarf.Field{
659 {Attr: dwarf.AttrProducer, Val: "GNU C 4.2.4 (Ubuntu 4.2.4-1ubuntu4)", Class: dwarf.ClassString},
660 {Attr: dwarf.AttrLanguage, Val: int64(1), Class: dwarf.ClassConstant},
661 {Attr: dwarf.AttrName, Val: "go-relocation-test-gcc424.c", Class: dwarf.ClassString},
662 {Attr: dwarf.AttrCompDir, Val: "/tmp", Class: dwarf.ClassString},
663 {Attr: dwarf.AttrLowpc, Val: uint64(0x0), Class: dwarf.ClassAddress},
664 {Attr: dwarf.AttrHighpc, Val: uint64(0x6), Class: dwarf.ClassAddress},
665 {Attr: dwarf.AttrStmtList, Val: int64(0), Class: dwarf.ClassLinePtr},
666 },
667 },
668 pcRanges: [][2]uint64{{0x0, 0x6}},
669 },
670 },
671 },
672 {
673 "testdata/go-relocation-test-gcc482-aarch64.obj",
674 []relocationTestEntry{
675 {
676 entry: &dwarf.Entry{
677 Offset: 0xb,
678 Tag: dwarf.TagCompileUnit,
679 Children: true,
680 Field: []dwarf.Field{
681 {Attr: dwarf.AttrProducer, Val: "GNU C 4.8.2 -g -fstack-protector", Class: dwarf.ClassString},
682 {Attr: dwarf.AttrLanguage, Val: int64(1), Class: dwarf.ClassConstant},
683 {Attr: dwarf.AttrName, Val: "go-relocation-test-gcc482.c", Class: dwarf.ClassString},
684 {Attr: dwarf.AttrCompDir, Val: "/tmp", Class: dwarf.ClassString},
685 {Attr: dwarf.AttrLowpc, Val: uint64(0x0), Class: dwarf.ClassAddress},
686 {Attr: dwarf.AttrHighpc, Val: int64(0x24), Class: dwarf.ClassConstant},
687 {Attr: dwarf.AttrStmtList, Val: int64(0), Class: dwarf.ClassLinePtr},
688 },
689 },
690 pcRanges: [][2]uint64{{0x0, 0x24}},
691 },
692 },
693 },
694 {
695 "testdata/go-relocation-test-gcc492-arm.obj",
696 []relocationTestEntry{
697 {
698 entry: &dwarf.Entry{
699 Offset: 0xb,
700 Tag: dwarf.TagCompileUnit,
701 Children: true,
702 Field: []dwarf.Field{
703 {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},
704 {Attr: dwarf.AttrLanguage, Val: int64(1), Class: dwarf.ClassConstant},
705 {Attr: dwarf.AttrName, Val: "go-relocation-test-gcc492.c", Class: dwarf.ClassString},
706 {Attr: dwarf.AttrCompDir, Val: "/root/go/src/debug/elf/testdata", Class: dwarf.ClassString},
707 {Attr: dwarf.AttrLowpc, Val: uint64(0x0), Class: dwarf.ClassAddress},
708 {Attr: dwarf.AttrHighpc, Val: int64(0x28), Class: dwarf.ClassConstant},
709 {Attr: dwarf.AttrStmtList, Val: int64(0), Class: dwarf.ClassLinePtr},
710 },
711 },
712 pcRanges: [][2]uint64{{0x0, 0x28}},
713 },
714 },
715 },
716 {
717 "testdata/go-relocation-test-clang-arm.obj",
718 []relocationTestEntry{
719 {
720 entry: &dwarf.Entry{
721 Offset: 0xb,
722 Tag: dwarf.TagCompileUnit,
723 Children: true,
724 Field: []dwarf.Field{
725 {Attr: dwarf.AttrProducer, Val: "Debian clang version 3.5.0-10 (tags/RELEASE_350/final) (based on LLVM 3.5.0)", Class: dwarf.ClassString},
726 {Attr: dwarf.AttrLanguage, Val: int64(12), Class: dwarf.ClassConstant},
727 {Attr: dwarf.AttrName, Val: "hello.c", Class: dwarf.ClassString},
728 {Attr: dwarf.AttrStmtList, Val: int64(0x0), Class: dwarf.ClassLinePtr},
729 {Attr: dwarf.AttrCompDir, Val: "/tmp", Class: dwarf.ClassString},
730 {Attr: dwarf.AttrLowpc, Val: uint64(0x0), Class: dwarf.ClassAddress},
731 {Attr: dwarf.AttrHighpc, Val: int64(0x30), Class: dwarf.ClassConstant},
732 },
733 },
734 pcRanges: [][2]uint64{{0x0, 0x30}},
735 },
736 },
737 },
738 {
739 "testdata/go-relocation-test-gcc5-ppc.obj",
740 []relocationTestEntry{
741 {
742 entry: &dwarf.Entry{
743 Offset: 0xb,
744 Tag: dwarf.TagCompileUnit,
745 Children: true,
746 Field: []dwarf.Field{
747 {Attr: dwarf.AttrProducer, Val: "GNU C11 5.0.0 20150116 (experimental) -Asystem=linux -Asystem=unix -Asystem=posix -g", Class: dwarf.ClassString},
748 {Attr: dwarf.AttrLanguage, Val: int64(12), Class: dwarf.ClassConstant},
749 {Attr: dwarf.AttrName, Val: "go-relocation-test-gcc5-ppc.c", Class: dwarf.ClassString},
750 {Attr: dwarf.AttrCompDir, Val: "/tmp", Class: dwarf.ClassString},
751 {Attr: dwarf.AttrLowpc, Val: uint64(0x0), Class: dwarf.ClassAddress},
752 {Attr: dwarf.AttrHighpc, Val: int64(0x44), Class: dwarf.ClassConstant},
753 {Attr: dwarf.AttrStmtList, Val: int64(0), Class: dwarf.ClassLinePtr},
754 },
755 },
756 pcRanges: [][2]uint64{{0x0, 0x44}},
757 },
758 },
759 },
760 {
761 "testdata/go-relocation-test-gcc482-ppc64le.obj",
762 []relocationTestEntry{
763 {
764 entry: &dwarf.Entry{
765 Offset: 0xb,
766 Tag: dwarf.TagCompileUnit,
767 Children: true,
768 Field: []dwarf.Field{
769 {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},
770 {Attr: dwarf.AttrLanguage, Val: int64(1), Class: dwarf.ClassConstant},
771 {Attr: dwarf.AttrName, Val: "go-relocation-test-gcc482-ppc64le.c", Class: dwarf.ClassString},
772 {Attr: dwarf.AttrCompDir, Val: "/tmp", Class: dwarf.ClassString},
773 {Attr: dwarf.AttrLowpc, Val: uint64(0x0), Class: dwarf.ClassAddress},
774 {Attr: dwarf.AttrHighpc, Val: uint64(0x24), Class: dwarf.ClassAddress},
775 {Attr: dwarf.AttrStmtList, Val: int64(0), Class: dwarf.ClassLinePtr},
776 },
777 },
778 pcRanges: [][2]uint64{{0x0, 0x24}},
779 },
780 },
781 },
782 {
783 "testdata/go-relocation-test-gcc492-mips64.obj",
784 []relocationTestEntry{
785 {
786 entry: &dwarf.Entry{
787 Offset: 0xb,
788 Tag: dwarf.TagCompileUnit,
789 Children: true,
790 Field: []dwarf.Field{
791 {Attr: dwarf.AttrProducer, Val: "GNU C 4.9.2 -meb -mabi=64 -march=mips3 -mtune=mips64 -mllsc -mno-shared -g", Class: dwarf.ClassString},
792 {Attr: dwarf.AttrLanguage, Val: int64(1), Class: dwarf.ClassConstant},
793 {Attr: dwarf.AttrName, Val: "hello.c", Class: dwarf.ClassString},
794 {Attr: dwarf.AttrCompDir, Val: "/tmp", Class: dwarf.ClassString},
795 {Attr: dwarf.AttrLowpc, Val: uint64(0x0), Class: dwarf.ClassAddress},
796 {Attr: dwarf.AttrHighpc, Val: int64(0x64), Class: dwarf.ClassConstant},
797 {Attr: dwarf.AttrStmtList, Val: int64(0), Class: dwarf.ClassLinePtr},
798 },
799 },
800 pcRanges: [][2]uint64{{0x0, 0x64}},
801 },
802 },
803 },
804 {
805 "testdata/go-relocation-test-gcc531-s390x.obj",
806 []relocationTestEntry{
807 {
808 entry: &dwarf.Entry{
809 Offset: 0xb,
810 Tag: dwarf.TagCompileUnit,
811 Children: true,
812 Field: []dwarf.Field{
813 {Attr: dwarf.AttrProducer, Val: "GNU C11 5.3.1 20160316 -march=zEC12 -m64 -mzarch -g -fstack-protector-strong", Class: dwarf.ClassString},
814 {Attr: dwarf.AttrLanguage, Val: int64(12), Class: dwarf.ClassConstant},
815 {Attr: dwarf.AttrName, Val: "hello.c", Class: dwarf.ClassString},
816 {Attr: dwarf.AttrCompDir, Val: "/tmp", Class: dwarf.ClassString},
817 {Attr: dwarf.AttrLowpc, Val: uint64(0x0), Class: dwarf.ClassAddress},
818 {Attr: dwarf.AttrHighpc, Val: int64(0x3a), Class: dwarf.ClassConstant},
819 {Attr: dwarf.AttrStmtList, Val: int64(0), Class: dwarf.ClassLinePtr},
820 },
821 },
822 pcRanges: [][2]uint64{{0x0, 0x3a}},
823 },
824 },
825 },
826 {
827 "testdata/go-relocation-test-gcc620-sparc64.obj",
828 []relocationTestEntry{
829 {
830 entry: &dwarf.Entry{
831 Offset: 0xb,
832 Tag: dwarf.TagCompileUnit,
833 Children: true,
834 Field: []dwarf.Field{
835 {Attr: dwarf.AttrProducer, Val: "GNU C11 6.2.0 20160914 -mcpu=v9 -g -fstack-protector-strong", Class: dwarf.ClassString},
836 {Attr: dwarf.AttrLanguage, Val: int64(12), Class: dwarf.ClassConstant},
837 {Attr: dwarf.AttrName, Val: "hello.c", Class: dwarf.ClassString},
838 {Attr: dwarf.AttrCompDir, Val: "/tmp", Class: dwarf.ClassString},
839 {Attr: dwarf.AttrLowpc, Val: uint64(0x0), Class: dwarf.ClassAddress},
840 {Attr: dwarf.AttrHighpc, Val: int64(0x2c), Class: dwarf.ClassConstant},
841 {Attr: dwarf.AttrStmtList, Val: int64(0), Class: dwarf.ClassLinePtr},
842 },
843 },
844 pcRanges: [][2]uint64{{0x0, 0x2c}},
845 },
846 },
847 },
848 {
849 "testdata/go-relocation-test-gcc492-mipsle.obj",
850 []relocationTestEntry{
851 {
852 entry: &dwarf.Entry{
853 Offset: 0xb,
854 Tag: dwarf.TagCompileUnit,
855 Children: true,
856 Field: []dwarf.Field{
857 {Attr: dwarf.AttrProducer, Val: "GNU C 4.9.2 -mel -march=mips2 -mtune=mips32 -mllsc -mno-shared -mabi=32 -g", Class: dwarf.ClassString},
858 {Attr: dwarf.AttrLanguage, Val: int64(1), Class: dwarf.ClassConstant},
859 {Attr: dwarf.AttrName, Val: "hello.c", Class: dwarf.ClassString},
860 {Attr: dwarf.AttrCompDir, Val: "/tmp", Class: dwarf.ClassString},
861 {Attr: dwarf.AttrLowpc, Val: uint64(0x0), Class: dwarf.ClassAddress},
862 {Attr: dwarf.AttrHighpc, Val: int64(0x58), Class: dwarf.ClassConstant},
863 {Attr: dwarf.AttrStmtList, Val: int64(0), Class: dwarf.ClassLinePtr},
864 },
865 },
866 pcRanges: [][2]uint64{{0x0, 0x58}},
867 },
868 },
869 },
870 {
871 "testdata/go-relocation-test-gcc540-mips.obj",
872 []relocationTestEntry{
873 {
874 entry: &dwarf.Entry{
875 Offset: 0xb,
876 Tag: dwarf.TagCompileUnit,
877 Children: true,
878 Field: []dwarf.Field{
879 {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},
880 {Attr: dwarf.AttrLanguage, Val: int64(12), Class: dwarf.ClassConstant},
881 {Attr: dwarf.AttrName, Val: "hello.c", Class: dwarf.ClassString},
882 {Attr: dwarf.AttrCompDir, Val: "/tmp", Class: dwarf.ClassString},
883 {Attr: dwarf.AttrLowpc, Val: uint64(0x0), Class: dwarf.ClassAddress},
884 {Attr: dwarf.AttrHighpc, Val: uint64(0x5c), Class: dwarf.ClassAddress},
885 {Attr: dwarf.AttrStmtList, Val: int64(0), Class: dwarf.ClassLinePtr},
886 },
887 },
888 pcRanges: [][2]uint64{{0x0, 0x5c}},
889 },
890 },
891 },
892 {
893 "testdata/go-relocation-test-gcc493-mips64le.obj",
894 []relocationTestEntry{
895 {
896 entry: &dwarf.Entry{
897 Offset: 0xb,
898 Tag: dwarf.TagCompileUnit,
899 Children: true,
900 Field: []dwarf.Field{
901 {Attr: dwarf.AttrProducer, Val: "GNU C 4.9.3 -mel -mabi=64 -mllsc -mno-shared -g -fstack-protector-strong", Class: dwarf.ClassString},
902 {Attr: dwarf.AttrLanguage, Val: int64(1), Class: dwarf.ClassConstant},
903 {Attr: dwarf.AttrName, Val: "hello.c", Class: dwarf.ClassString},
904 {Attr: dwarf.AttrCompDir, Val: "/tmp", Class: dwarf.ClassString},
905 {Attr: dwarf.AttrLowpc, Val: uint64(0x0), Class: dwarf.ClassAddress},
906 {Attr: dwarf.AttrHighpc, Val: int64(0x64), Class: dwarf.ClassConstant},
907 {Attr: dwarf.AttrStmtList, Val: int64(0), Class: dwarf.ClassLinePtr},
908 },
909 },
910 pcRanges: [][2]uint64{{0x0, 0x64}},
911 },
912 },
913 },
914 {
915 "testdata/go-relocation-test-gcc720-riscv64.obj",
916 []relocationTestEntry{
917 {
918 entry: &dwarf.Entry{
919 Offset: 0xb,
920 Tag: dwarf.TagCompileUnit,
921 Children: true,
922 Field: []dwarf.Field{
923 {Attr: dwarf.AttrProducer, Val: "GNU C11 7.2.0 -march=rv64imafdc -mabi=lp64d -g -gdwarf-2", Class: dwarf.ClassString},
924 {Attr: dwarf.AttrLanguage, Val: int64(12), Class: dwarf.ClassConstant},
925 {Attr: dwarf.AttrName, Val: "hello.c", Class: dwarf.ClassString},
926 {Attr: dwarf.AttrCompDir, Val: "/tmp", Class: dwarf.ClassString},
927 {Attr: dwarf.AttrLowpc, Val: uint64(0x0), Class: dwarf.ClassAddress},
928 {Attr: dwarf.AttrHighpc, Val: uint64(0x2c), Class: dwarf.ClassAddress},
929 {Attr: dwarf.AttrStmtList, Val: int64(0), Class: dwarf.ClassLinePtr},
930 },
931 },
932 pcRanges: [][2]uint64{{0x0, 0x2c}},
933 },
934 },
935 },
936 {
937 "testdata/go-relocation-test-clang-x86.obj",
938 []relocationTestEntry{
939 {
940 entry: &dwarf.Entry{
941 Offset: 0xb,
942 Tag: dwarf.TagCompileUnit,
943 Children: true,
944 Field: []dwarf.Field{
945 {Attr: dwarf.AttrProducer, Val: "clang version google3-trunk (trunk r209387)", Class: dwarf.ClassString},
946 {Attr: dwarf.AttrLanguage, Val: int64(12), Class: dwarf.ClassConstant},
947 {Attr: dwarf.AttrName, Val: "go-relocation-test-clang.c", Class: dwarf.ClassString},
948 {Attr: dwarf.AttrStmtList, Val: int64(0), Class: dwarf.ClassLinePtr},
949 {Attr: dwarf.AttrCompDir, Val: "/tmp", Class: dwarf.ClassString},
950 },
951 },
952 },
953 },
954 },
955 {
956 "testdata/gcc-amd64-openbsd-debug-with-rela.obj",
957 []relocationTestEntry{
958 {
959 entryNumber: 203,
960 entry: &dwarf.Entry{
961 Offset: 0xc62,
962 Tag: dwarf.TagMember,
963 Children: false,
964 Field: []dwarf.Field{
965 {Attr: dwarf.AttrName, Val: "it_interval", Class: dwarf.ClassString},
966 {Attr: dwarf.AttrDeclFile, Val: int64(7), Class: dwarf.ClassConstant},
967 {Attr: dwarf.AttrDeclLine, Val: int64(236), Class: dwarf.ClassConstant},
968 {Attr: dwarf.AttrType, Val: dwarf.Offset(0xb7f), Class: dwarf.ClassReference},
969 {Attr: dwarf.AttrDataMemberLoc, Val: []byte{0x23, 0x0}, Class: dwarf.ClassExprLoc},
970 },
971 },
972 },
973 {
974 entryNumber: 204,
975 entry: &dwarf.Entry{
976 Offset: 0xc70,
977 Tag: dwarf.TagMember,
978 Children: false,
979 Field: []dwarf.Field{
980 {Attr: dwarf.AttrName, Val: "it_value", Class: dwarf.ClassString},
981 {Attr: dwarf.AttrDeclFile, Val: int64(7), Class: dwarf.ClassConstant},
982 {Attr: dwarf.AttrDeclLine, Val: int64(237), Class: dwarf.ClassConstant},
983 {Attr: dwarf.AttrType, Val: dwarf.Offset(0xb7f), Class: dwarf.ClassReference},
984 {Attr: dwarf.AttrDataMemberLoc, Val: []byte{0x23, 0x10}, Class: dwarf.ClassExprLoc},
985 },
986 },
987 },
988 },
989 },
990 {
991 "testdata/go-relocation-test-gcc930-ranges-no-rela-x86-64",
992 []relocationTestEntry{
993 {
994 entry: &dwarf.Entry{
995 Offset: 0xb,
996 Tag: dwarf.TagCompileUnit,
997 Children: true,
998 Field: []dwarf.Field{
999 {Attr: dwarf.AttrProducer, Val: "GNU C17 9.3.0 -mtune=generic -march=x86-64 -g -fno-asynchronous-unwind-tables", Class: dwarf.ClassString},
1000 {Attr: dwarf.AttrLanguage, Val: int64(12), Class: dwarf.ClassConstant},
1001 {Attr: dwarf.AttrName, Val: "multiple-code-sections.c", Class: dwarf.ClassString},
1002 {Attr: dwarf.AttrCompDir, Val: "/tmp", Class: dwarf.ClassString},
1003 {Attr: dwarf.AttrRanges, Val: int64(0), Class: dwarf.ClassRangeListPtr},
1004 {Attr: dwarf.AttrLowpc, Val: uint64(0), Class: dwarf.ClassAddress},
1005 {Attr: dwarf.AttrStmtList, Val: int64(0), Class: dwarf.ClassLinePtr},
1006 },
1007 },
1008 pcRanges: [][2]uint64{
1009 {0x765, 0x777},
1010 {0x7e1, 0x7ec},
1011 },
1012 },
1013 },
1014 },
1015 {
1016 "testdata/go-relocation-test-gcc930-ranges-with-rela-x86-64",
1017 []relocationTestEntry{
1018 {
1019 entry: &dwarf.Entry{
1020 Offset: 0xb,
1021 Tag: dwarf.TagCompileUnit,
1022 Children: true,
1023 Field: []dwarf.Field{
1024 {Attr: dwarf.AttrProducer, Val: "GNU C17 9.3.0 -mtune=generic -march=x86-64 -g -fno-asynchronous-unwind-tables", Class: dwarf.ClassString},
1025 {Attr: dwarf.AttrLanguage, Val: int64(12), Class: dwarf.ClassConstant},
1026 {Attr: dwarf.AttrName, Val: "multiple-code-sections.c", Class: dwarf.ClassString},
1027 {Attr: dwarf.AttrCompDir, Val: "/tmp", Class: dwarf.ClassString},
1028 {Attr: dwarf.AttrRanges, Val: int64(0), Class: dwarf.ClassRangeListPtr},
1029 {Attr: dwarf.AttrLowpc, Val: uint64(0), Class: dwarf.ClassAddress},
1030 {Attr: dwarf.AttrStmtList, Val: int64(0), Class: dwarf.ClassLinePtr},
1031 },
1032 },
1033 pcRanges: [][2]uint64{
1034 {0x765, 0x777},
1035 {0x7e1, 0x7ec},
1036 },
1037 },
1038 },
1039 },
1040 }
1041
1042 func TestDWARFRelocations(t *testing.T) {
1043 for _, test := range relocationTests {
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
1088
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
1116
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
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
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
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
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
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
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
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
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
1272
1273 func TestLargeNumberOfSections(t *testing.T) {
1274
1275
1276
1277
1278
1279
1280
1281
1282
1283
1284
1285
1286
1287
1288
1289
1290
1291
1292
1293
1294
1295
1296
1297
1298
1299
1300
1301
1302
1303
1304
1305
1306
1307
1308
1309
1310
1311
1312
1313
1314
1315
1316
1317
1318
1319
1320
1321
1322
1323
1324
1325 var buf bytes.Buffer
1326
1327 {
1328 buf.Grow(0x55AF1C)
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
1344 buf.Write(bytes.Repeat([]byte{0}, 0x13ED1C-binary.Size(h)))
1345
1346
1347
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
1354 buf.Write([]byte{0})
1355 buf.Write([]byte("y.c\x00"))
1356 for i := 1; i <= 65288; i++ {
1357
1358 name := fmt.Sprintf("var_%04x", i)
1359 buf.Write([]byte(name))
1360 buf.Write([]byte{0})
1361 }
1362
1363
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
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
1382
1383 binary.Write(&buf, binary.LittleEndian, Section32{Name: 0, Size: 0xFF12, Link: 0xFF11})
1384
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
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
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
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
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
1431 binary.Write(&buf, binary.LittleEndian, Section32{
1432 Name: 0x0CF39D,
1433 Type: uint32(SHT_PROGBITS),
1434 Off: 0x03FC7B,
1435 Addralign: 0x01,
1436 })
1437
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
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
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
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
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
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
1627 func TestOpenEmptyFile(t *testing.T) {
1628 name := filepath.Join(t.TempDir(), "empty")
1629 if err := os.WriteFile(name, nil, 0o644); err != nil {
1630 t.Fatal(err)
1631 }
1632
1633 _, err := Open(name)
1634 if err == nil {
1635 t.Fatal("Open on empty file: got nil error, want non-nil")
1636 }
1637
1638 var formatErr *FormatError
1639 if !errors.As(err, &formatErr) {
1640 t.Errorf("Open on empty file: got %T (%v), want *FormatError", err, err)
1641 }
1642 }
1643
1644 func TestNewFileShortReader(t *testing.T) {
1645 tests := []struct {
1646 name string
1647 data []byte
1648 }{
1649 {"empty", []byte{}},
1650 {"one byte", []byte{0x7f}},
1651 {"four bytes", []byte{0x7f, 'E', 'L', 'F'}},
1652 {"fifteen bytes", make([]byte, 15)},
1653 }
1654
1655 for _, tt := range tests {
1656 t.Run(tt.name, func(t *testing.T) {
1657 _, err := NewFile(bytes.NewReader(tt.data))
1658 if err == nil {
1659 t.Fatal("NewFile with short data: got nil error, want non-nil")
1660 }
1661
1662 var formatErr *FormatError
1663 if !errors.As(err, &formatErr) {
1664 t.Errorf("NewFile with short data: got %T (%v), want *FormatError", err, err)
1665 }
1666 })
1667 }
1668 }
1669
View as plain text