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