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