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