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