Source file
src/debug/elf/file_test.go
1
2
3
4
5 package elf
6
7 import (
8 "bytes"
9 "compress/gzip"
10 "debug/dwarf"
11 "encoding/binary"
12 "io"
13 "math/rand"
14 "net"
15 "os"
16 "path"
17 "reflect"
18 "runtime"
19 "testing"
20 )
21
22 type fileTest struct {
23 file string
24 hdr FileHeader
25 sections []SectionHeader
26 progs []ProgHeader
27 needed []string
28 }
29
30 var fileTests = []fileTest{
31 {
32 "testdata/gcc-386-freebsd-exec",
33 FileHeader{ELFCLASS32, ELFDATA2LSB, EV_CURRENT, ELFOSABI_FREEBSD, 0, binary.LittleEndian, ET_EXEC, EM_386, 0x80483cc},
34 []SectionHeader{
35 {"", SHT_NULL, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0},
36 {".interp", SHT_PROGBITS, SHF_ALLOC, 0x80480d4, 0xd4, 0x15, 0x0, 0x0, 0x1, 0x0, 0x15},
37 {".hash", SHT_HASH, SHF_ALLOC, 0x80480ec, 0xec, 0x90, 0x3, 0x0, 0x4, 0x4, 0x90},
38 {".dynsym", SHT_DYNSYM, SHF_ALLOC, 0x804817c, 0x17c, 0x110, 0x4, 0x1, 0x4, 0x10, 0x110},
39 {".dynstr", SHT_STRTAB, SHF_ALLOC, 0x804828c, 0x28c, 0xbb, 0x0, 0x0, 0x1, 0x0, 0xbb},
40 {".rel.plt", SHT_REL, SHF_ALLOC, 0x8048348, 0x348, 0x20, 0x3, 0x7, 0x4, 0x8, 0x20},
41 {".init", SHT_PROGBITS, SHF_ALLOC + SHF_EXECINSTR, 0x8048368, 0x368, 0x11, 0x0, 0x0, 0x4, 0x0, 0x11},
42 {".plt", SHT_PROGBITS, SHF_ALLOC + SHF_EXECINSTR, 0x804837c, 0x37c, 0x50, 0x0, 0x0, 0x4, 0x4, 0x50},
43 {".text", SHT_PROGBITS, SHF_ALLOC + SHF_EXECINSTR, 0x80483cc, 0x3cc, 0x180, 0x0, 0x0, 0x4, 0x0, 0x180},
44 {".fini", SHT_PROGBITS, SHF_ALLOC + SHF_EXECINSTR, 0x804854c, 0x54c, 0xc, 0x0, 0x0, 0x4, 0x0, 0xc},
45 {".rodata", SHT_PROGBITS, SHF_ALLOC, 0x8048558, 0x558, 0xa3, 0x0, 0x0, 0x1, 0x0, 0xa3},
46 {".data", SHT_PROGBITS, SHF_WRITE + SHF_ALLOC, 0x80495fc, 0x5fc, 0xc, 0x0, 0x0, 0x4, 0x0, 0xc},
47 {".eh_frame", SHT_PROGBITS, SHF_ALLOC, 0x8049608, 0x608, 0x4, 0x0, 0x0, 0x4, 0x0, 0x4},
48 {".dynamic", SHT_DYNAMIC, SHF_WRITE + SHF_ALLOC, 0x804960c, 0x60c, 0x98, 0x4, 0x0, 0x4, 0x8, 0x98},
49 {".ctors", SHT_PROGBITS, SHF_WRITE + SHF_ALLOC, 0x80496a4, 0x6a4, 0x8, 0x0, 0x0, 0x4, 0x0, 0x8},
50 {".dtors", SHT_PROGBITS, SHF_WRITE + SHF_ALLOC, 0x80496ac, 0x6ac, 0x8, 0x0, 0x0, 0x4, 0x0, 0x8},
51 {".jcr", SHT_PROGBITS, SHF_WRITE + SHF_ALLOC, 0x80496b4, 0x6b4, 0x4, 0x0, 0x0, 0x4, 0x0, 0x4},
52 {".got", SHT_PROGBITS, SHF_WRITE + SHF_ALLOC, 0x80496b8, 0x6b8, 0x1c, 0x0, 0x0, 0x4, 0x4, 0x1c},
53 {".bss", SHT_NOBITS, SHF_WRITE + SHF_ALLOC, 0x80496d4, 0x6d4, 0x20, 0x0, 0x0, 0x4, 0x0, 0x20},
54 {".comment", SHT_PROGBITS, 0x0, 0x0, 0x6d4, 0x12d, 0x0, 0x0, 0x1, 0x0, 0x12d},
55 {".debug_aranges", SHT_PROGBITS, 0x0, 0x0, 0x801, 0x20, 0x0, 0x0, 0x1, 0x0, 0x20},
56 {".debug_pubnames", SHT_PROGBITS, 0x0, 0x0, 0x821, 0x1b, 0x0, 0x0, 0x1, 0x0, 0x1b},
57 {".debug_info", SHT_PROGBITS, 0x0, 0x0, 0x83c, 0x11d, 0x0, 0x0, 0x1, 0x0, 0x11d},
58 {".debug_abbrev", SHT_PROGBITS, 0x0, 0x0, 0x959, 0x41, 0x0, 0x0, 0x1, 0x0, 0x41},
59 {".debug_line", SHT_PROGBITS, 0x0, 0x0, 0x99a, 0x35, 0x0, 0x0, 0x1, 0x0, 0x35},
60 {".debug_frame", SHT_PROGBITS, 0x0, 0x0, 0x9d0, 0x30, 0x0, 0x0, 0x4, 0x0, 0x30},
61 {".debug_str", SHT_PROGBITS, 0x0, 0x0, 0xa00, 0xd, 0x0, 0x0, 0x1, 0x0, 0xd},
62 {".shstrtab", SHT_STRTAB, 0x0, 0x0, 0xa0d, 0xf8, 0x0, 0x0, 0x1, 0x0, 0xf8},
63 {".symtab", SHT_SYMTAB, 0x0, 0x0, 0xfb8, 0x4b0, 0x1d, 0x38, 0x4, 0x10, 0x4b0},
64 {".strtab", SHT_STRTAB, 0x0, 0x0, 0x1468, 0x206, 0x0, 0x0, 0x1, 0x0, 0x206},
65 },
66 []ProgHeader{
67 {PT_PHDR, PF_R + PF_X, 0x34, 0x8048034, 0x8048034, 0xa0, 0xa0, 0x4},
68 {PT_INTERP, PF_R, 0xd4, 0x80480d4, 0x80480d4, 0x15, 0x15, 0x1},
69 {PT_LOAD, PF_R + PF_X, 0x0, 0x8048000, 0x8048000, 0x5fb, 0x5fb, 0x1000},
70 {PT_LOAD, PF_R + PF_W, 0x5fc, 0x80495fc, 0x80495fc, 0xd8, 0xf8, 0x1000},
71 {PT_DYNAMIC, PF_R + PF_W, 0x60c, 0x804960c, 0x804960c, 0x98, 0x98, 0x4},
72 },
73 []string{"libc.so.6"},
74 },
75 {
76 "testdata/gcc-amd64-linux-exec",
77 FileHeader{ELFCLASS64, ELFDATA2LSB, EV_CURRENT, ELFOSABI_NONE, 0, binary.LittleEndian, ET_EXEC, EM_X86_64, 0x4003e0},
78 []SectionHeader{
79 {"", SHT_NULL, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0},
80 {".interp", SHT_PROGBITS, SHF_ALLOC, 0x400200, 0x200, 0x1c, 0x0, 0x0, 0x1, 0x0, 0x1c},
81 {".note.ABI-tag", SHT_NOTE, SHF_ALLOC, 0x40021c, 0x21c, 0x20, 0x0, 0x0, 0x4, 0x0, 0x20},
82 {".hash", SHT_HASH, SHF_ALLOC, 0x400240, 0x240, 0x24, 0x5, 0x0, 0x8, 0x4, 0x24},
83 {".gnu.hash", SHT_LOOS + 268435446, SHF_ALLOC, 0x400268, 0x268, 0x1c, 0x5, 0x0, 0x8, 0x0, 0x1c},
84 {".dynsym", SHT_DYNSYM, SHF_ALLOC, 0x400288, 0x288, 0x60, 0x6, 0x1, 0x8, 0x18, 0x60},
85 {".dynstr", SHT_STRTAB, SHF_ALLOC, 0x4002e8, 0x2e8, 0x3d, 0x0, 0x0, 0x1, 0x0, 0x3d},
86 {".gnu.version", SHT_HIOS, SHF_ALLOC, 0x400326, 0x326, 0x8, 0x5, 0x0, 0x2, 0x2, 0x8},
87 {".gnu.version_r", SHT_LOOS + 268435454, SHF_ALLOC, 0x400330, 0x330, 0x20, 0x6, 0x1, 0x8, 0x0, 0x20},
88 {".rela.dyn", SHT_RELA, SHF_ALLOC, 0x400350, 0x350, 0x18, 0x5, 0x0, 0x8, 0x18, 0x18},
89 {".rela.plt", SHT_RELA, SHF_ALLOC, 0x400368, 0x368, 0x30, 0x5, 0xc, 0x8, 0x18, 0x30},
90 {".init", SHT_PROGBITS, SHF_ALLOC + SHF_EXECINSTR, 0x400398, 0x398, 0x18, 0x0, 0x0, 0x4, 0x0, 0x18},
91 {".plt", SHT_PROGBITS, SHF_ALLOC + SHF_EXECINSTR, 0x4003b0, 0x3b0, 0x30, 0x0, 0x0, 0x4, 0x10, 0x30},
92 {".text", SHT_PROGBITS, SHF_ALLOC + SHF_EXECINSTR, 0x4003e0, 0x3e0, 0x1b4, 0x0, 0x0, 0x10, 0x0, 0x1b4},
93 {".fini", SHT_PROGBITS, SHF_ALLOC + SHF_EXECINSTR, 0x400594, 0x594, 0xe, 0x0, 0x0, 0x4, 0x0, 0xe},
94 {".rodata", SHT_PROGBITS, SHF_ALLOC, 0x4005a4, 0x5a4, 0x11, 0x0, 0x0, 0x4, 0x0, 0x11},
95 {".eh_frame_hdr", SHT_PROGBITS, SHF_ALLOC, 0x4005b8, 0x5b8, 0x24, 0x0, 0x0, 0x4, 0x0, 0x24},
96 {".eh_frame", SHT_PROGBITS, SHF_ALLOC, 0x4005e0, 0x5e0, 0xa4, 0x0, 0x0, 0x8, 0x0, 0xa4},
97 {".ctors", SHT_PROGBITS, SHF_WRITE + SHF_ALLOC, 0x600688, 0x688, 0x10, 0x0, 0x0, 0x8, 0x0, 0x10},
98 {".dtors", SHT_PROGBITS, SHF_WRITE + SHF_ALLOC, 0x600698, 0x698, 0x10, 0x0, 0x0, 0x8, 0x0, 0x10},
99 {".jcr", SHT_PROGBITS, SHF_WRITE + SHF_ALLOC, 0x6006a8, 0x6a8, 0x8, 0x0, 0x0, 0x8, 0x0, 0x8},
100 {".dynamic", SHT_DYNAMIC, SHF_WRITE + SHF_ALLOC, 0x6006b0, 0x6b0, 0x1a0, 0x6, 0x0, 0x8, 0x10, 0x1a0},
101 {".got", SHT_PROGBITS, SHF_WRITE + SHF_ALLOC, 0x600850, 0x850, 0x8, 0x0, 0x0, 0x8, 0x8, 0x8},
102 {".got.plt", SHT_PROGBITS, SHF_WRITE + SHF_ALLOC, 0x600858, 0x858, 0x28, 0x0, 0x0, 0x8, 0x8, 0x28},
103 {".data", SHT_PROGBITS, SHF_WRITE + SHF_ALLOC, 0x600880, 0x880, 0x18, 0x0, 0x0, 0x8, 0x0, 0x18},
104 {".bss", SHT_NOBITS, SHF_WRITE + SHF_ALLOC, 0x600898, 0x898, 0x8, 0x0, 0x0, 0x4, 0x0, 0x8},
105 {".comment", SHT_PROGBITS, 0x0, 0x0, 0x898, 0x126, 0x0, 0x0, 0x1, 0x0, 0x126},
106 {".debug_aranges", SHT_PROGBITS, 0x0, 0x0, 0x9c0, 0x90, 0x0, 0x0, 0x10, 0x0, 0x90},
107 {".debug_pubnames", SHT_PROGBITS, 0x0, 0x0, 0xa50, 0x25, 0x0, 0x0, 0x1, 0x0, 0x25},
108 {".debug_info", SHT_PROGBITS, 0x0, 0x0, 0xa75, 0x1a7, 0x0, 0x0, 0x1, 0x0, 0x1a7},
109 {".debug_abbrev", SHT_PROGBITS, 0x0, 0x0, 0xc1c, 0x6f, 0x0, 0x0, 0x1, 0x0, 0x6f},
110 {".debug_line", SHT_PROGBITS, 0x0, 0x0, 0xc8b, 0x13f, 0x0, 0x0, 0x1, 0x0, 0x13f},
111 {".debug_str", SHT_PROGBITS, SHF_MERGE + SHF_STRINGS, 0x0, 0xdca, 0xb1, 0x0, 0x0, 0x1, 0x1, 0xb1},
112 {".debug_ranges", SHT_PROGBITS, 0x0, 0x0, 0xe80, 0x90, 0x0, 0x0, 0x10, 0x0, 0x90},
113 {".shstrtab", SHT_STRTAB, 0x0, 0x0, 0xf10, 0x149, 0x0, 0x0, 0x1, 0x0, 0x149},
114 {".symtab", SHT_SYMTAB, 0x0, 0x0, 0x19a0, 0x6f0, 0x24, 0x39, 0x8, 0x18, 0x6f0},
115 {".strtab", SHT_STRTAB, 0x0, 0x0, 0x2090, 0x1fc, 0x0, 0x0, 0x1, 0x0, 0x1fc},
116 },
117 []ProgHeader{
118 {PT_PHDR, PF_R + PF_X, 0x40, 0x400040, 0x400040, 0x1c0, 0x1c0, 0x8},
119 {PT_INTERP, PF_R, 0x200, 0x400200, 0x400200, 0x1c, 0x1c, 1},
120 {PT_LOAD, PF_R + PF_X, 0x0, 0x400000, 0x400000, 0x684, 0x684, 0x200000},
121 {PT_LOAD, PF_R + PF_W, 0x688, 0x600688, 0x600688, 0x210, 0x218, 0x200000},
122 {PT_DYNAMIC, PF_R + PF_W, 0x6b0, 0x6006b0, 0x6006b0, 0x1a0, 0x1a0, 0x8},
123 {PT_NOTE, PF_R, 0x21c, 0x40021c, 0x40021c, 0x20, 0x20, 0x4},
124 {PT_LOOS + 0x474E550, PF_R, 0x5b8, 0x4005b8, 0x4005b8, 0x24, 0x24, 0x4},
125 {PT_LOOS + 0x474E551, PF_R + PF_W, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8},
126 },
127 []string{"libc.so.6"},
128 },
129 {
130 "testdata/hello-world-core.gz",
131 FileHeader{ELFCLASS64, ELFDATA2LSB, EV_CURRENT, ELFOSABI_NONE, 0x0, binary.LittleEndian, ET_CORE, EM_X86_64, 0x0},
132 []SectionHeader{},
133 []ProgHeader{
134 {Type: PT_NOTE, Flags: 0x0, Off: 0x3f8, Vaddr: 0x0, Paddr: 0x0, Filesz: 0x8ac, Memsz: 0x0, Align: 0x0},
135 {Type: PT_LOAD, Flags: PF_X + PF_R, Off: 0x1000, Vaddr: 0x400000, Paddr: 0x0, Filesz: 0x0, Memsz: 0x1000, Align: 0x1000},
136 {Type: PT_LOAD, Flags: PF_R, Off: 0x1000, Vaddr: 0x401000, Paddr: 0x0, Filesz: 0x1000, Memsz: 0x1000, Align: 0x1000},
137 {Type: PT_LOAD, Flags: PF_W + PF_R, Off: 0x2000, Vaddr: 0x402000, Paddr: 0x0, Filesz: 0x1000, Memsz: 0x1000, Align: 0x1000},
138 {Type: PT_LOAD, Flags: PF_X + PF_R, Off: 0x3000, Vaddr: 0x7f54078b8000, Paddr: 0x0, Filesz: 0x0, Memsz: 0x1b5000, Align: 0x1000},
139 {Type: PT_LOAD, Flags: 0x0, Off: 0x3000, Vaddr: 0x7f5407a6d000, Paddr: 0x0, Filesz: 0x0, Memsz: 0x1ff000, Align: 0x1000},
140 {Type: PT_LOAD, Flags: PF_R, Off: 0x3000, Vaddr: 0x7f5407c6c000, Paddr: 0x0, Filesz: 0x4000, Memsz: 0x4000, Align: 0x1000},
141 {Type: PT_LOAD, Flags: PF_W + PF_R, Off: 0x7000, Vaddr: 0x7f5407c70000, Paddr: 0x0, Filesz: 0x2000, Memsz: 0x2000, Align: 0x1000},
142 {Type: PT_LOAD, Flags: PF_W + PF_R, Off: 0x9000, Vaddr: 0x7f5407c72000, Paddr: 0x0, Filesz: 0x5000, Memsz: 0x5000, Align: 0x1000},
143 {Type: PT_LOAD, Flags: PF_X + PF_R, Off: 0xe000, Vaddr: 0x7f5407c77000, Paddr: 0x0, Filesz: 0x0, Memsz: 0x22000, Align: 0x1000},
144 {Type: PT_LOAD, Flags: PF_W + PF_R, Off: 0xe000, Vaddr: 0x7f5407e81000, Paddr: 0x0, Filesz: 0x3000, Memsz: 0x3000, Align: 0x1000},
145 {Type: PT_LOAD, Flags: PF_W + PF_R, Off: 0x11000, Vaddr: 0x7f5407e96000, Paddr: 0x0, Filesz: 0x3000, Memsz: 0x3000, Align: 0x1000},
146 {Type: PT_LOAD, Flags: PF_R, Off: 0x14000, Vaddr: 0x7f5407e99000, Paddr: 0x0, Filesz: 0x1000, Memsz: 0x1000, Align: 0x1000},
147 {Type: PT_LOAD, Flags: PF_W + PF_R, Off: 0x15000, Vaddr: 0x7f5407e9a000, Paddr: 0x0, Filesz: 0x2000, Memsz: 0x2000, Align: 0x1000},
148 {Type: PT_LOAD, Flags: PF_W + PF_R, Off: 0x17000, Vaddr: 0x7fff79972000, Paddr: 0x0, Filesz: 0x23000, Memsz: 0x23000, Align: 0x1000},
149 {Type: PT_LOAD, Flags: PF_X + PF_R, Off: 0x3a000, Vaddr: 0x7fff799f8000, Paddr: 0x0, Filesz: 0x1000, Memsz: 0x1000, Align: 0x1000},
150 {Type: PT_LOAD, Flags: PF_X + PF_R, Off: 0x3b000, Vaddr: 0xffffffffff600000, Paddr: 0x0, Filesz: 0x1000, Memsz: 0x1000, Align: 0x1000},
151 },
152 nil,
153 },
154 {
155 "testdata/compressed-32.obj",
156 FileHeader{ELFCLASS32, ELFDATA2LSB, EV_CURRENT, ELFOSABI_NONE, 0x0, binary.LittleEndian, ET_REL, EM_386, 0x0},
157 []SectionHeader{
158 {"", SHT_NULL, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0},
159 {".text", SHT_PROGBITS, SHF_ALLOC | SHF_EXECINSTR, 0x0, 0x34, 0x17, 0x0, 0x0, 0x1, 0x0, 0x17},
160 {".rel.text", SHT_REL, SHF_INFO_LINK, 0x0, 0x3dc, 0x10, 0x13, 0x1, 0x4, 0x8, 0x10},
161 {".data", SHT_PROGBITS, SHF_WRITE | SHF_ALLOC, 0x0, 0x4b, 0x0, 0x0, 0x0, 0x1, 0x0, 0x0},
162 {".bss", SHT_NOBITS, SHF_WRITE | SHF_ALLOC, 0x0, 0x4b, 0x0, 0x0, 0x0, 0x1, 0x0, 0x0},
163 {".rodata", SHT_PROGBITS, SHF_ALLOC, 0x0, 0x4b, 0xd, 0x0, 0x0, 0x1, 0x0, 0xd},
164 {".debug_info", SHT_PROGBITS, SHF_COMPRESSED, 0x0, 0x58, 0xb4, 0x0, 0x0, 0x1, 0x0, 0x84},
165 {".rel.debug_info", SHT_REL, SHF_INFO_LINK, 0x0, 0x3ec, 0xa0, 0x13, 0x6, 0x4, 0x8, 0xa0},
166 {".debug_abbrev", SHT_PROGBITS, 0x0, 0x0, 0xdc, 0x5a, 0x0, 0x0, 0x1, 0x0, 0x5a},
167 {".debug_aranges", SHT_PROGBITS, 0x0, 0x0, 0x136, 0x20, 0x0, 0x0, 0x1, 0x0, 0x20},
168 {".rel.debug_aranges", SHT_REL, SHF_INFO_LINK, 0x0, 0x48c, 0x10, 0x13, 0x9, 0x4, 0x8, 0x10},
169 {".debug_line", SHT_PROGBITS, 0x0, 0x0, 0x156, 0x5c, 0x0, 0x0, 0x1, 0x0, 0x5c},
170 {".rel.debug_line", SHT_REL, SHF_INFO_LINK, 0x0, 0x49c, 0x8, 0x13, 0xb, 0x4, 0x8, 0x8},
171 {".debug_str", SHT_PROGBITS, SHF_MERGE | SHF_STRINGS | SHF_COMPRESSED, 0x0, 0x1b2, 0x10f, 0x0, 0x0, 0x1, 0x1, 0xb3},
172 {".comment", SHT_PROGBITS, SHF_MERGE | SHF_STRINGS, 0x0, 0x265, 0x2a, 0x0, 0x0, 0x1, 0x1, 0x2a},
173 {".note.GNU-stack", SHT_PROGBITS, 0x0, 0x0, 0x28f, 0x0, 0x0, 0x0, 0x1, 0x0, 0x0},
174 {".eh_frame", SHT_PROGBITS, SHF_ALLOC, 0x0, 0x290, 0x38, 0x0, 0x0, 0x4, 0x0, 0x38},
175 {".rel.eh_frame", SHT_REL, SHF_INFO_LINK, 0x0, 0x4a4, 0x8, 0x13, 0x10, 0x4, 0x8, 0x8},
176 {".shstrtab", SHT_STRTAB, 0x0, 0x0, 0x4ac, 0xab, 0x0, 0x0, 0x1, 0x0, 0xab},
177 {".symtab", SHT_SYMTAB, 0x0, 0x0, 0x2c8, 0x100, 0x14, 0xe, 0x4, 0x10, 0x100},
178 {".strtab", SHT_STRTAB, 0x0, 0x0, 0x3c8, 0x13, 0x0, 0x0, 0x1, 0x0, 0x13},
179 },
180 []ProgHeader{},
181 nil,
182 },
183 {
184 "testdata/compressed-64.obj",
185 FileHeader{ELFCLASS64, ELFDATA2LSB, EV_CURRENT, ELFOSABI_NONE, 0x0, binary.LittleEndian, ET_REL, EM_X86_64, 0x0},
186 []SectionHeader{
187 {"", SHT_NULL, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0},
188 {".text", SHT_PROGBITS, SHF_ALLOC | SHF_EXECINSTR, 0x0, 0x40, 0x1b, 0x0, 0x0, 0x1, 0x0, 0x1b},
189 {".rela.text", SHT_RELA, SHF_INFO_LINK, 0x0, 0x488, 0x30, 0x13, 0x1, 0x8, 0x18, 0x30},
190 {".data", SHT_PROGBITS, SHF_WRITE | SHF_ALLOC, 0x0, 0x5b, 0x0, 0x0, 0x0, 0x1, 0x0, 0x0},
191 {".bss", SHT_NOBITS, SHF_WRITE | SHF_ALLOC, 0x0, 0x5b, 0x0, 0x0, 0x0, 0x1, 0x0, 0x0},
192 {".rodata", SHT_PROGBITS, SHF_ALLOC, 0x0, 0x5b, 0xd, 0x0, 0x0, 0x1, 0x0, 0xd},
193 {".debug_info", SHT_PROGBITS, SHF_COMPRESSED, 0x0, 0x68, 0xba, 0x0, 0x0, 0x1, 0x0, 0x72},
194 {".rela.debug_info", SHT_RELA, SHF_INFO_LINK, 0x0, 0x4b8, 0x1c8, 0x13, 0x6, 0x8, 0x18, 0x1c8},
195 {".debug_abbrev", SHT_PROGBITS, 0x0, 0x0, 0xda, 0x5c, 0x0, 0x0, 0x1, 0x0, 0x5c},
196 {".debug_aranges", SHT_PROGBITS, SHF_COMPRESSED, 0x0, 0x136, 0x30, 0x0, 0x0, 0x1, 0x0, 0x2f},
197 {".rela.debug_aranges", SHT_RELA, SHF_INFO_LINK, 0x0, 0x680, 0x30, 0x13, 0x9, 0x8, 0x18, 0x30},
198 {".debug_line", SHT_PROGBITS, 0x0, 0x0, 0x165, 0x60, 0x0, 0x0, 0x1, 0x0, 0x60},
199 {".rela.debug_line", SHT_RELA, SHF_INFO_LINK, 0x0, 0x6b0, 0x18, 0x13, 0xb, 0x8, 0x18, 0x18},
200 {".debug_str", SHT_PROGBITS, SHF_MERGE | SHF_STRINGS | SHF_COMPRESSED, 0x0, 0x1c5, 0x104, 0x0, 0x0, 0x1, 0x1, 0xc3},
201 {".comment", SHT_PROGBITS, SHF_MERGE | SHF_STRINGS, 0x0, 0x288, 0x2a, 0x0, 0x0, 0x1, 0x1, 0x2a},
202 {".note.GNU-stack", SHT_PROGBITS, 0x0, 0x0, 0x2b2, 0x0, 0x0, 0x0, 0x1, 0x0, 0x0},
203 {".eh_frame", SHT_PROGBITS, SHF_ALLOC, 0x0, 0x2b8, 0x38, 0x0, 0x0, 0x8, 0x0, 0x38},
204 {".rela.eh_frame", SHT_RELA, SHF_INFO_LINK, 0x0, 0x6c8, 0x18, 0x13, 0x10, 0x8, 0x18, 0x18},
205 {".shstrtab", SHT_STRTAB, 0x0, 0x0, 0x6e0, 0xb0, 0x0, 0x0, 0x1, 0x0, 0xb0},
206 {".symtab", SHT_SYMTAB, 0x0, 0x0, 0x2f0, 0x180, 0x14, 0xe, 0x8, 0x18, 0x180},
207 {".strtab", SHT_STRTAB, 0x0, 0x0, 0x470, 0x13, 0x0, 0x0, 0x1, 0x0, 0x13},
208 },
209 []ProgHeader{},
210 nil,
211 },
212 }
213
214 func TestOpen(t *testing.T) {
215 for i := range fileTests {
216 tt := &fileTests[i]
217
218 var f *File
219 var err error
220 if path.Ext(tt.file) == ".gz" {
221 var r io.ReaderAt
222 if r, err = decompress(tt.file); err == nil {
223 f, err = NewFile(r)
224 }
225 } else {
226 f, err = Open(tt.file)
227 }
228 if err != nil {
229 t.Errorf("cannot open file %s: %v", tt.file, err)
230 continue
231 }
232 defer f.Close()
233 if !reflect.DeepEqual(f.FileHeader, tt.hdr) {
234 t.Errorf("open %s:\n\thave %#v\n\twant %#v\n", tt.file, f.FileHeader, tt.hdr)
235 continue
236 }
237 for i, s := range f.Sections {
238 if i >= len(tt.sections) {
239 break
240 }
241 sh := &tt.sections[i]
242 if !reflect.DeepEqual(&s.SectionHeader, sh) {
243 t.Errorf("open %s, section %d:\n\thave %#v\n\twant %#v\n", tt.file, i, &s.SectionHeader, sh)
244 }
245 }
246 for i, p := range f.Progs {
247 if i >= len(tt.progs) {
248 break
249 }
250 ph := &tt.progs[i]
251 if !reflect.DeepEqual(&p.ProgHeader, ph) {
252 t.Errorf("open %s, program %d:\n\thave %#v\n\twant %#v\n", tt.file, i, &p.ProgHeader, ph)
253 }
254 }
255 tn := len(tt.sections)
256 fn := len(f.Sections)
257 if tn != fn {
258 t.Errorf("open %s: len(Sections) = %d, want %d", tt.file, fn, tn)
259 }
260 tn = len(tt.progs)
261 fn = len(f.Progs)
262 if tn != fn {
263 t.Errorf("open %s: len(Progs) = %d, want %d", tt.file, fn, tn)
264 }
265 tl := tt.needed
266 fl, err := f.ImportedLibraries()
267 if err != nil {
268 t.Error(err)
269 }
270 if !reflect.DeepEqual(tl, fl) {
271 t.Errorf("open %s: DT_NEEDED = %v, want %v", tt.file, tl, fl)
272 }
273 }
274 }
275
276
277
278 func decompress(gz string) (io.ReaderAt, error) {
279 in, err := os.Open(gz)
280 if err != nil {
281 return nil, err
282 }
283 defer in.Close()
284 r, err := gzip.NewReader(in)
285 if err != nil {
286 return nil, err
287 }
288 var out bytes.Buffer
289 _, err = io.Copy(&out, r)
290 return bytes.NewReader(out.Bytes()), err
291 }
292
293 type relocationTestEntry struct {
294 entryNumber int
295 entry *dwarf.Entry
296 pcRanges [][2]uint64
297 }
298
299 type relocationTest struct {
300 file string
301 entries []relocationTestEntry
302 }
303
304 var relocationTests = []relocationTest{
305 {
306 "testdata/go-relocation-test-gcc441-x86-64.obj",
307 []relocationTestEntry{
308 {
309 entry: &dwarf.Entry{
310 Offset: 0xb,
311 Tag: dwarf.TagCompileUnit,
312 Children: true,
313 Field: []dwarf.Field{
314 {Attr: dwarf.AttrProducer, Val: "GNU C 4.4.1", Class: dwarf.ClassString},
315 {Attr: dwarf.AttrLanguage, Val: int64(1), Class: dwarf.ClassConstant},
316 {Attr: dwarf.AttrName, Val: "go-relocation-test.c", Class: dwarf.ClassString},
317 {Attr: dwarf.AttrCompDir, Val: "/tmp", Class: dwarf.ClassString},
318 {Attr: dwarf.AttrLowpc, Val: uint64(0x0), Class: dwarf.ClassAddress},
319 {Attr: dwarf.AttrHighpc, Val: uint64(0x6), Class: dwarf.ClassAddress},
320 {Attr: dwarf.AttrStmtList, Val: int64(0), Class: dwarf.ClassLinePtr},
321 },
322 },
323 pcRanges: [][2]uint64{{0x0, 0x6}},
324 },
325 },
326 },
327 {
328 "testdata/go-relocation-test-gcc441-x86.obj",
329 []relocationTestEntry{
330 {
331 entry: &dwarf.Entry{
332 Offset: 0xb,
333 Tag: dwarf.TagCompileUnit,
334 Children: true,
335 Field: []dwarf.Field{
336 {Attr: dwarf.AttrProducer, Val: "GNU C 4.4.1", Class: dwarf.ClassString},
337 {Attr: dwarf.AttrLanguage, Val: int64(1), Class: dwarf.ClassConstant},
338 {Attr: dwarf.AttrName, Val: "t.c", Class: dwarf.ClassString},
339 {Attr: dwarf.AttrCompDir, Val: "/tmp", Class: dwarf.ClassString},
340 {Attr: dwarf.AttrLowpc, Val: uint64(0x0), Class: dwarf.ClassAddress},
341 {Attr: dwarf.AttrHighpc, Val: uint64(0x5), Class: dwarf.ClassAddress},
342 {Attr: dwarf.AttrStmtList, Val: int64(0), Class: dwarf.ClassLinePtr},
343 },
344 },
345 pcRanges: [][2]uint64{{0x0, 0x5}},
346 },
347 },
348 },
349 {
350 "testdata/go-relocation-test-gcc424-x86-64.obj",
351 []relocationTestEntry{
352 {
353 entry: &dwarf.Entry{
354 Offset: 0xb,
355 Tag: dwarf.TagCompileUnit,
356 Children: true,
357 Field: []dwarf.Field{
358 {Attr: dwarf.AttrProducer, Val: "GNU C 4.2.4 (Ubuntu 4.2.4-1ubuntu4)", Class: dwarf.ClassString},
359 {Attr: dwarf.AttrLanguage, Val: int64(1), Class: dwarf.ClassConstant},
360 {Attr: dwarf.AttrName, Val: "go-relocation-test-gcc424.c", Class: dwarf.ClassString},
361 {Attr: dwarf.AttrCompDir, Val: "/tmp", Class: dwarf.ClassString},
362 {Attr: dwarf.AttrLowpc, Val: uint64(0x0), Class: dwarf.ClassAddress},
363 {Attr: dwarf.AttrHighpc, Val: uint64(0x6), Class: dwarf.ClassAddress},
364 {Attr: dwarf.AttrStmtList, Val: int64(0), Class: dwarf.ClassLinePtr},
365 },
366 },
367 pcRanges: [][2]uint64{{0x0, 0x6}},
368 },
369 },
370 },
371 {
372 "testdata/go-relocation-test-gcc482-aarch64.obj",
373 []relocationTestEntry{
374 {
375 entry: &dwarf.Entry{
376 Offset: 0xb,
377 Tag: dwarf.TagCompileUnit,
378 Children: true,
379 Field: []dwarf.Field{
380 {Attr: dwarf.AttrProducer, Val: "GNU C 4.8.2 -g -fstack-protector", Class: dwarf.ClassString},
381 {Attr: dwarf.AttrLanguage, Val: int64(1), Class: dwarf.ClassConstant},
382 {Attr: dwarf.AttrName, Val: "go-relocation-test-gcc482.c", Class: dwarf.ClassString},
383 {Attr: dwarf.AttrCompDir, Val: "/tmp", Class: dwarf.ClassString},
384 {Attr: dwarf.AttrLowpc, Val: uint64(0x0), Class: dwarf.ClassAddress},
385 {Attr: dwarf.AttrHighpc, Val: int64(0x24), Class: dwarf.ClassConstant},
386 {Attr: dwarf.AttrStmtList, Val: int64(0), Class: dwarf.ClassLinePtr},
387 },
388 },
389 pcRanges: [][2]uint64{{0x0, 0x24}},
390 },
391 },
392 },
393 {
394 "testdata/go-relocation-test-gcc492-arm.obj",
395 []relocationTestEntry{
396 {
397 entry: &dwarf.Entry{
398 Offset: 0xb,
399 Tag: dwarf.TagCompileUnit,
400 Children: true,
401 Field: []dwarf.Field{
402 {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},
403 {Attr: dwarf.AttrLanguage, Val: int64(1), Class: dwarf.ClassConstant},
404 {Attr: dwarf.AttrName, Val: "go-relocation-test-gcc492.c", Class: dwarf.ClassString},
405 {Attr: dwarf.AttrCompDir, Val: "/root/go/src/debug/elf/testdata", Class: dwarf.ClassString},
406 {Attr: dwarf.AttrLowpc, Val: uint64(0x0), Class: dwarf.ClassAddress},
407 {Attr: dwarf.AttrHighpc, Val: int64(0x28), Class: dwarf.ClassConstant},
408 {Attr: dwarf.AttrStmtList, Val: int64(0), Class: dwarf.ClassLinePtr},
409 },
410 },
411 pcRanges: [][2]uint64{{0x0, 0x28}},
412 },
413 },
414 },
415 {
416 "testdata/go-relocation-test-clang-arm.obj",
417 []relocationTestEntry{
418 {
419 entry: &dwarf.Entry{
420 Offset: 0xb,
421 Tag: dwarf.TagCompileUnit,
422 Children: true,
423 Field: []dwarf.Field{
424 {Attr: dwarf.AttrProducer, Val: "Debian clang version 3.5.0-10 (tags/RELEASE_350/final) (based on LLVM 3.5.0)", Class: dwarf.ClassString},
425 {Attr: dwarf.AttrLanguage, Val: int64(12), Class: dwarf.ClassConstant},
426 {Attr: dwarf.AttrName, Val: "hello.c", Class: dwarf.ClassString},
427 {Attr: dwarf.AttrStmtList, Val: int64(0x0), Class: dwarf.ClassLinePtr},
428 {Attr: dwarf.AttrCompDir, Val: "/tmp", Class: dwarf.ClassString},
429 {Attr: dwarf.AttrLowpc, Val: uint64(0x0), Class: dwarf.ClassAddress},
430 {Attr: dwarf.AttrHighpc, Val: int64(0x30), Class: dwarf.ClassConstant},
431 },
432 },
433 pcRanges: [][2]uint64{{0x0, 0x30}},
434 },
435 },
436 },
437 {
438 "testdata/go-relocation-test-gcc5-ppc.obj",
439 []relocationTestEntry{
440 {
441 entry: &dwarf.Entry{
442 Offset: 0xb,
443 Tag: dwarf.TagCompileUnit,
444 Children: true,
445 Field: []dwarf.Field{
446 {Attr: dwarf.AttrProducer, Val: "GNU C11 5.0.0 20150116 (experimental) -Asystem=linux -Asystem=unix -Asystem=posix -g", Class: dwarf.ClassString},
447 {Attr: dwarf.AttrLanguage, Val: int64(12), Class: dwarf.ClassConstant},
448 {Attr: dwarf.AttrName, Val: "go-relocation-test-gcc5-ppc.c", Class: dwarf.ClassString},
449 {Attr: dwarf.AttrCompDir, Val: "/tmp", Class: dwarf.ClassString},
450 {Attr: dwarf.AttrLowpc, Val: uint64(0x0), Class: dwarf.ClassAddress},
451 {Attr: dwarf.AttrHighpc, Val: int64(0x44), Class: dwarf.ClassConstant},
452 {Attr: dwarf.AttrStmtList, Val: int64(0), Class: dwarf.ClassLinePtr},
453 },
454 },
455 pcRanges: [][2]uint64{{0x0, 0x44}},
456 },
457 },
458 },
459 {
460 "testdata/go-relocation-test-gcc482-ppc64le.obj",
461 []relocationTestEntry{
462 {
463 entry: &dwarf.Entry{
464 Offset: 0xb,
465 Tag: dwarf.TagCompileUnit,
466 Children: true,
467 Field: []dwarf.Field{
468 {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},
469 {Attr: dwarf.AttrLanguage, Val: int64(1), Class: dwarf.ClassConstant},
470 {Attr: dwarf.AttrName, Val: "go-relocation-test-gcc482-ppc64le.c", Class: dwarf.ClassString},
471 {Attr: dwarf.AttrCompDir, Val: "/tmp", Class: dwarf.ClassString},
472 {Attr: dwarf.AttrLowpc, Val: uint64(0x0), Class: dwarf.ClassAddress},
473 {Attr: dwarf.AttrHighpc, Val: uint64(0x24), Class: dwarf.ClassAddress},
474 {Attr: dwarf.AttrStmtList, Val: int64(0), Class: dwarf.ClassLinePtr},
475 },
476 },
477 pcRanges: [][2]uint64{{0x0, 0x24}},
478 },
479 },
480 },
481 {
482 "testdata/go-relocation-test-gcc492-mips64.obj",
483 []relocationTestEntry{
484 {
485 entry: &dwarf.Entry{
486 Offset: 0xb,
487 Tag: dwarf.TagCompileUnit,
488 Children: true,
489 Field: []dwarf.Field{
490 {Attr: dwarf.AttrProducer, Val: "GNU C 4.9.2 -meb -mabi=64 -march=mips3 -mtune=mips64 -mllsc -mno-shared -g", Class: dwarf.ClassString},
491 {Attr: dwarf.AttrLanguage, Val: int64(1), Class: dwarf.ClassConstant},
492 {Attr: dwarf.AttrName, Val: "hello.c", Class: dwarf.ClassString},
493 {Attr: dwarf.AttrCompDir, Val: "/tmp", Class: dwarf.ClassString},
494 {Attr: dwarf.AttrLowpc, Val: uint64(0x0), Class: dwarf.ClassAddress},
495 {Attr: dwarf.AttrHighpc, Val: int64(0x64), Class: dwarf.ClassConstant},
496 {Attr: dwarf.AttrStmtList, Val: int64(0), Class: dwarf.ClassLinePtr},
497 },
498 },
499 pcRanges: [][2]uint64{{0x0, 0x64}},
500 },
501 },
502 },
503 {
504 "testdata/go-relocation-test-gcc531-s390x.obj",
505 []relocationTestEntry{
506 {
507 entry: &dwarf.Entry{
508 Offset: 0xb,
509 Tag: dwarf.TagCompileUnit,
510 Children: true,
511 Field: []dwarf.Field{
512 {Attr: dwarf.AttrProducer, Val: "GNU C11 5.3.1 20160316 -march=zEC12 -m64 -mzarch -g -fstack-protector-strong", Class: dwarf.ClassString},
513 {Attr: dwarf.AttrLanguage, Val: int64(12), Class: dwarf.ClassConstant},
514 {Attr: dwarf.AttrName, Val: "hello.c", Class: dwarf.ClassString},
515 {Attr: dwarf.AttrCompDir, Val: "/tmp", Class: dwarf.ClassString},
516 {Attr: dwarf.AttrLowpc, Val: uint64(0x0), Class: dwarf.ClassAddress},
517 {Attr: dwarf.AttrHighpc, Val: int64(0x3a), Class: dwarf.ClassConstant},
518 {Attr: dwarf.AttrStmtList, Val: int64(0), Class: dwarf.ClassLinePtr},
519 },
520 },
521 pcRanges: [][2]uint64{{0x0, 0x3a}},
522 },
523 },
524 },
525 {
526 "testdata/go-relocation-test-gcc620-sparc64.obj",
527 []relocationTestEntry{
528 {
529 entry: &dwarf.Entry{
530 Offset: 0xb,
531 Tag: dwarf.TagCompileUnit,
532 Children: true,
533 Field: []dwarf.Field{
534 {Attr: dwarf.AttrProducer, Val: "GNU C11 6.2.0 20160914 -mcpu=v9 -g -fstack-protector-strong", Class: dwarf.ClassString},
535 {Attr: dwarf.AttrLanguage, Val: int64(12), Class: dwarf.ClassConstant},
536 {Attr: dwarf.AttrName, Val: "hello.c", Class: dwarf.ClassString},
537 {Attr: dwarf.AttrCompDir, Val: "/tmp", Class: dwarf.ClassString},
538 {Attr: dwarf.AttrLowpc, Val: uint64(0x0), Class: dwarf.ClassAddress},
539 {Attr: dwarf.AttrHighpc, Val: int64(0x2c), Class: dwarf.ClassConstant},
540 {Attr: dwarf.AttrStmtList, Val: int64(0), Class: dwarf.ClassLinePtr},
541 },
542 },
543 pcRanges: [][2]uint64{{0x0, 0x2c}},
544 },
545 },
546 },
547 {
548 "testdata/go-relocation-test-gcc492-mipsle.obj",
549 []relocationTestEntry{
550 {
551 entry: &dwarf.Entry{
552 Offset: 0xb,
553 Tag: dwarf.TagCompileUnit,
554 Children: true,
555 Field: []dwarf.Field{
556 {Attr: dwarf.AttrProducer, Val: "GNU C 4.9.2 -mel -march=mips2 -mtune=mips32 -mllsc -mno-shared -mabi=32 -g", Class: dwarf.ClassString},
557 {Attr: dwarf.AttrLanguage, Val: int64(1), Class: dwarf.ClassConstant},
558 {Attr: dwarf.AttrName, Val: "hello.c", Class: dwarf.ClassString},
559 {Attr: dwarf.AttrCompDir, Val: "/tmp", Class: dwarf.ClassString},
560 {Attr: dwarf.AttrLowpc, Val: uint64(0x0), Class: dwarf.ClassAddress},
561 {Attr: dwarf.AttrHighpc, Val: int64(0x58), Class: dwarf.ClassConstant},
562 {Attr: dwarf.AttrStmtList, Val: int64(0), Class: dwarf.ClassLinePtr},
563 },
564 },
565 pcRanges: [][2]uint64{{0x0, 0x58}},
566 },
567 },
568 },
569 {
570 "testdata/go-relocation-test-gcc540-mips.obj",
571 []relocationTestEntry{
572 {
573 entry: &dwarf.Entry{
574 Offset: 0xb,
575 Tag: dwarf.TagCompileUnit,
576 Children: true,
577 Field: []dwarf.Field{
578 {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},
579 {Attr: dwarf.AttrLanguage, Val: int64(12), Class: dwarf.ClassConstant},
580 {Attr: dwarf.AttrName, Val: "hello.c", Class: dwarf.ClassString},
581 {Attr: dwarf.AttrCompDir, Val: "/tmp", Class: dwarf.ClassString},
582 {Attr: dwarf.AttrLowpc, Val: uint64(0x0), Class: dwarf.ClassAddress},
583 {Attr: dwarf.AttrHighpc, Val: uint64(0x5c), Class: dwarf.ClassAddress},
584 {Attr: dwarf.AttrStmtList, Val: int64(0), Class: dwarf.ClassLinePtr},
585 },
586 },
587 pcRanges: [][2]uint64{{0x0, 0x5c}},
588 },
589 },
590 },
591 {
592 "testdata/go-relocation-test-gcc493-mips64le.obj",
593 []relocationTestEntry{
594 {
595 entry: &dwarf.Entry{
596 Offset: 0xb,
597 Tag: dwarf.TagCompileUnit,
598 Children: true,
599 Field: []dwarf.Field{
600 {Attr: dwarf.AttrProducer, Val: "GNU C 4.9.3 -mel -mabi=64 -mllsc -mno-shared -g -fstack-protector-strong", Class: dwarf.ClassString},
601 {Attr: dwarf.AttrLanguage, Val: int64(1), Class: dwarf.ClassConstant},
602 {Attr: dwarf.AttrName, Val: "hello.c", Class: dwarf.ClassString},
603 {Attr: dwarf.AttrCompDir, Val: "/tmp", Class: dwarf.ClassString},
604 {Attr: dwarf.AttrLowpc, Val: uint64(0x0), Class: dwarf.ClassAddress},
605 {Attr: dwarf.AttrHighpc, Val: int64(0x64), Class: dwarf.ClassConstant},
606 {Attr: dwarf.AttrStmtList, Val: int64(0), Class: dwarf.ClassLinePtr},
607 },
608 },
609 pcRanges: [][2]uint64{{0x0, 0x64}},
610 },
611 },
612 },
613 {
614 "testdata/go-relocation-test-gcc720-riscv64.obj",
615 []relocationTestEntry{
616 {
617 entry: &dwarf.Entry{
618 Offset: 0xb,
619 Tag: dwarf.TagCompileUnit,
620 Children: true,
621 Field: []dwarf.Field{
622 {Attr: dwarf.AttrProducer, Val: "GNU C11 7.2.0 -march=rv64imafdc -mabi=lp64d -g -gdwarf-2", Class: dwarf.ClassString},
623 {Attr: dwarf.AttrLanguage, Val: int64(12), Class: dwarf.ClassConstant},
624 {Attr: dwarf.AttrName, Val: "hello.c", Class: dwarf.ClassString},
625 {Attr: dwarf.AttrCompDir, Val: "/tmp", Class: dwarf.ClassString},
626 {Attr: dwarf.AttrLowpc, Val: uint64(0x0), Class: dwarf.ClassAddress},
627 {Attr: dwarf.AttrHighpc, Val: uint64(0x2c), Class: dwarf.ClassAddress},
628 {Attr: dwarf.AttrStmtList, Val: int64(0), Class: dwarf.ClassLinePtr},
629 },
630 },
631 pcRanges: [][2]uint64{{0x0, 0x2c}},
632 },
633 },
634 },
635 {
636 "testdata/go-relocation-test-clang-x86.obj",
637 []relocationTestEntry{
638 {
639 entry: &dwarf.Entry{
640 Offset: 0xb,
641 Tag: dwarf.TagCompileUnit,
642 Children: true,
643 Field: []dwarf.Field{
644 {Attr: dwarf.AttrProducer, Val: "clang version google3-trunk (trunk r209387)", Class: dwarf.ClassString},
645 {Attr: dwarf.AttrLanguage, Val: int64(12), Class: dwarf.ClassConstant},
646 {Attr: dwarf.AttrName, Val: "go-relocation-test-clang.c", Class: dwarf.ClassString},
647 {Attr: dwarf.AttrStmtList, Val: int64(0), Class: dwarf.ClassLinePtr},
648 {Attr: dwarf.AttrCompDir, Val: "/tmp", Class: dwarf.ClassString},
649 },
650 },
651 },
652 },
653 },
654 {
655 "testdata/gcc-amd64-openbsd-debug-with-rela.obj",
656 []relocationTestEntry{
657 {
658 entryNumber: 203,
659 entry: &dwarf.Entry{
660 Offset: 0xc62,
661 Tag: dwarf.TagMember,
662 Children: false,
663 Field: []dwarf.Field{
664 {Attr: dwarf.AttrName, Val: "it_interval", Class: dwarf.ClassString},
665 {Attr: dwarf.AttrDeclFile, Val: int64(7), Class: dwarf.ClassConstant},
666 {Attr: dwarf.AttrDeclLine, Val: int64(236), Class: dwarf.ClassConstant},
667 {Attr: dwarf.AttrType, Val: dwarf.Offset(0xb7f), Class: dwarf.ClassReference},
668 {Attr: dwarf.AttrDataMemberLoc, Val: []byte{0x23, 0x0}, Class: dwarf.ClassExprLoc},
669 },
670 },
671 },
672 {
673 entryNumber: 204,
674 entry: &dwarf.Entry{
675 Offset: 0xc70,
676 Tag: dwarf.TagMember,
677 Children: false,
678 Field: []dwarf.Field{
679 {Attr: dwarf.AttrName, Val: "it_value", Class: dwarf.ClassString},
680 {Attr: dwarf.AttrDeclFile, Val: int64(7), Class: dwarf.ClassConstant},
681 {Attr: dwarf.AttrDeclLine, Val: int64(237), Class: dwarf.ClassConstant},
682 {Attr: dwarf.AttrType, Val: dwarf.Offset(0xb7f), Class: dwarf.ClassReference},
683 {Attr: dwarf.AttrDataMemberLoc, Val: []byte{0x23, 0x10}, Class: dwarf.ClassExprLoc},
684 },
685 },
686 },
687 },
688 },
689 {
690 "testdata/go-relocation-test-gcc930-ranges-no-rela-x86-64",
691 []relocationTestEntry{
692 {
693 entry: &dwarf.Entry{
694 Offset: 0xb,
695 Tag: dwarf.TagCompileUnit,
696 Children: true,
697 Field: []dwarf.Field{
698 {Attr: dwarf.AttrProducer, Val: "GNU C17 9.3.0 -mtune=generic -march=x86-64 -g -fno-asynchronous-unwind-tables", Class: dwarf.ClassString},
699 {Attr: dwarf.AttrLanguage, Val: int64(12), Class: dwarf.ClassConstant},
700 {Attr: dwarf.AttrName, Val: "multiple-code-sections.c", Class: dwarf.ClassString},
701 {Attr: dwarf.AttrCompDir, Val: "/tmp", Class: dwarf.ClassString},
702 {Attr: dwarf.AttrRanges, Val: int64(0), Class: dwarf.ClassRangeListPtr},
703 {Attr: dwarf.AttrLowpc, Val: uint64(0), Class: dwarf.ClassAddress},
704 {Attr: dwarf.AttrStmtList, Val: int64(0), Class: dwarf.ClassLinePtr},
705 },
706 },
707 pcRanges: [][2]uint64{
708 {0x765, 0x777},
709 {0x7e1, 0x7ec},
710 },
711 },
712 },
713 },
714 {
715 "testdata/go-relocation-test-gcc930-ranges-with-rela-x86-64",
716 []relocationTestEntry{
717 {
718 entry: &dwarf.Entry{
719 Offset: 0xb,
720 Tag: dwarf.TagCompileUnit,
721 Children: true,
722 Field: []dwarf.Field{
723 {Attr: dwarf.AttrProducer, Val: "GNU C17 9.3.0 -mtune=generic -march=x86-64 -g -fno-asynchronous-unwind-tables", Class: dwarf.ClassString},
724 {Attr: dwarf.AttrLanguage, Val: int64(12), Class: dwarf.ClassConstant},
725 {Attr: dwarf.AttrName, Val: "multiple-code-sections.c", Class: dwarf.ClassString},
726 {Attr: dwarf.AttrCompDir, Val: "/tmp", Class: dwarf.ClassString},
727 {Attr: dwarf.AttrRanges, Val: int64(0), Class: dwarf.ClassRangeListPtr},
728 {Attr: dwarf.AttrLowpc, Val: uint64(0), Class: dwarf.ClassAddress},
729 {Attr: dwarf.AttrStmtList, Val: int64(0), Class: dwarf.ClassLinePtr},
730 },
731 },
732 pcRanges: [][2]uint64{
733 {0x765, 0x777},
734 {0x7e1, 0x7ec},
735 },
736 },
737 },
738 },
739 }
740
741 func TestDWARFRelocations(t *testing.T) {
742 for _, test := range relocationTests {
743 test := test
744 t.Run(test.file, func(t *testing.T) {
745 t.Parallel()
746 f, err := Open(test.file)
747 if err != nil {
748 t.Fatal(err)
749 }
750 dwarf, err := f.DWARF()
751 if err != nil {
752 t.Fatal(err)
753 }
754 reader := dwarf.Reader()
755 idx := 0
756 for _, testEntry := range test.entries {
757 if testEntry.entryNumber < idx {
758 t.Fatalf("internal test error: %d < %d", testEntry.entryNumber, idx)
759 }
760 for ; idx < testEntry.entryNumber; idx++ {
761 entry, err := reader.Next()
762 if entry == nil || err != nil {
763 t.Fatalf("Failed to skip to entry %d: %v", testEntry.entryNumber, err)
764 }
765 }
766 entry, err := reader.Next()
767 idx++
768 if err != nil {
769 t.Fatal(err)
770 }
771 if !reflect.DeepEqual(testEntry.entry, entry) {
772 t.Errorf("entry %d mismatch: got:%#v want:%#v", testEntry.entryNumber, entry, testEntry.entry)
773 }
774 pcRanges, err := dwarf.Ranges(entry)
775 if err != nil {
776 t.Fatal(err)
777 }
778 if !reflect.DeepEqual(testEntry.pcRanges, pcRanges) {
779 t.Errorf("entry %d: PC range mismatch: got:%#v want:%#v", testEntry.entryNumber, pcRanges, testEntry.pcRanges)
780 }
781 }
782 })
783 }
784 }
785
786 func TestCompressedDWARF(t *testing.T) {
787
788
789 f, err := Open("testdata/zdebug-test-gcc484-x86-64.obj")
790 if err != nil {
791 t.Fatal(err)
792 }
793 dwarf, err := f.DWARF()
794 if err != nil {
795 t.Fatal(err)
796 }
797 reader := dwarf.Reader()
798 n := 0
799 for {
800 entry, err := reader.Next()
801 if err != nil {
802 t.Fatal(err)
803 }
804 if entry == nil {
805 break
806 }
807 n++
808 }
809 if n != 18 {
810 t.Fatalf("want %d DWARF entries, got %d", 18, n)
811 }
812 }
813
814 func TestCompressedSection(t *testing.T) {
815
816
817 f, err := Open("testdata/compressed-64.obj")
818 if err != nil {
819 t.Fatal(err)
820 }
821 sec := f.Section(".debug_info")
822 wantData := []byte{
823 182, 0, 0, 0, 4, 0, 0, 0, 0, 0, 8, 1, 0, 0, 0, 0,
824 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
825 0, 27, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 8, 7,
826 0, 0, 0, 0, 2, 1, 8, 0, 0, 0, 0, 2, 2, 7, 0, 0,
827 0, 0, 2, 4, 7, 0, 0, 0, 0, 2, 1, 6, 0, 0, 0, 0,
828 2, 2, 5, 0, 0, 0, 0, 3, 4, 5, 105, 110, 116, 0, 2, 8,
829 5, 0, 0, 0, 0, 2, 8, 7, 0, 0, 0, 0, 4, 8, 114, 0,
830 0, 0, 2, 1, 6, 0, 0, 0, 0, 5, 0, 0, 0, 0, 1, 4,
831 0, 0, 0, 0, 0, 0, 0, 0, 27, 0, 0, 0, 0, 0, 0, 0,
832 1, 156, 179, 0, 0, 0, 6, 0, 0, 0, 0, 1, 4, 87, 0, 0,
833 0, 2, 145, 108, 6, 0, 0, 0, 0, 1, 4, 179, 0, 0, 0, 2,
834 145, 96, 0, 4, 8, 108, 0, 0, 0, 0,
835 }
836
837
838 b, err := sec.Data()
839 if err != nil {
840 t.Fatal(err)
841 }
842 if !bytes.Equal(wantData, b) {
843 t.Fatalf("want data %x, got %x", wantData, b)
844 }
845
846
847 buf, have, count := make([]byte, len(b)), make([]bool, len(b)), 0
848 sf := sec.Open()
849 if got, err := sf.Seek(0, io.SeekEnd); got != int64(len(b)) || err != nil {
850 t.Fatalf("want seek end %d, got %d error %v", len(b), got, err)
851 }
852 if n, err := sf.Read(buf); n != 0 || err != io.EOF {
853 t.Fatalf("want EOF with 0 bytes, got %v with %d bytes", err, n)
854 }
855 pos := int64(len(buf))
856 for count < len(buf) {
857
858 whence := rand.Intn(3)
859 target := rand.Int63n(int64(len(buf)))
860 var offset int64
861 switch whence {
862 case io.SeekStart:
863 offset = target
864 case io.SeekCurrent:
865 offset = target - pos
866 case io.SeekEnd:
867 offset = target - int64(len(buf))
868 }
869 pos, err = sf.Seek(offset, whence)
870 if err != nil {
871 t.Fatal(err)
872 }
873 if pos != target {
874 t.Fatalf("want position %d, got %d", target, pos)
875 }
876
877
878 end := pos + 16
879 if end > int64(len(buf)) {
880 end = int64(len(buf))
881 }
882 n, err := io.ReadFull(sf, buf[pos:end])
883 if err != nil {
884 t.Fatal(err)
885 }
886 for i := 0; i < n; i++ {
887 if !have[pos] {
888 have[pos] = true
889 count++
890 }
891 pos++
892 }
893 }
894 if !bytes.Equal(wantData, buf) {
895 t.Fatalf("want data %x, got %x", wantData, buf)
896 }
897 }
898
899 func TestNoSectionOverlaps(t *testing.T) {
900
901 switch runtime.GOOS {
902 case "aix", "android", "darwin", "ios", "js", "plan9", "windows":
903 t.Skipf("cmd/link doesn't produce ELF binaries on %s", runtime.GOOS)
904 }
905 _ = net.ResolveIPAddr
906 f, err := Open(os.Args[0])
907 if err != nil {
908 t.Error(err)
909 return
910 }
911 for i, si := range f.Sections {
912 sih := si.SectionHeader
913 if sih.Type == SHT_NOBITS {
914 continue
915 }
916 for j, sj := range f.Sections {
917 sjh := sj.SectionHeader
918 if i == j || sjh.Type == SHT_NOBITS || sih.Offset == sjh.Offset && sih.Size == 0 {
919 continue
920 }
921 if sih.Offset >= sjh.Offset && sih.Offset < sjh.Offset+sjh.Size {
922 t.Errorf("ld produced ELF with section %s within %s: 0x%x <= 0x%x..0x%x < 0x%x",
923 sih.Name, sjh.Name, sjh.Offset, sih.Offset, sih.Offset+sih.Size, sjh.Offset+sjh.Size)
924 }
925 }
926 }
927 }
928
929 func TestIssue10996(t *testing.T) {
930 data := []byte("\u007fELF\x02\x01\x010000000000000" +
931 "\x010000000000000000000" +
932 "\x00\x00\x00\x00\x00\x00\x00\x0000000000\x00\x00\x00\x00" +
933 "0000")
934 _, err := NewFile(bytes.NewReader(data))
935 if err == nil {
936 t.Fatalf("opening invalid ELF file unexpectedly succeeded")
937 }
938 }
939
View as plain text