github.com/mdempsky/go@v0.0.0-20151201204031-5dd372bd1e70/src/debug/elf/file_test.go (about) 1 // Copyright 2009 The Go Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style 3 // license that can be found in the LICENSE file. 4 5 package elf 6 7 import ( 8 "bytes" 9 "compress/gzip" 10 "debug/dwarf" 11 "encoding/binary" 12 "io" 13 "net" 14 "os" 15 "path" 16 "reflect" 17 "runtime" 18 "testing" 19 ) 20 21 type fileTest struct { 22 file string 23 hdr FileHeader 24 sections []SectionHeader 25 progs []ProgHeader 26 needed []string 27 } 28 29 var fileTests = []fileTest{ 30 { 31 "testdata/gcc-386-freebsd-exec", 32 FileHeader{ELFCLASS32, ELFDATA2LSB, EV_CURRENT, ELFOSABI_FREEBSD, 0, binary.LittleEndian, ET_EXEC, EM_386, 0x80483cc}, 33 []SectionHeader{ 34 {"", SHT_NULL, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}, 35 {".interp", SHT_PROGBITS, SHF_ALLOC, 0x80480d4, 0xd4, 0x15, 0x0, 0x0, 0x1, 0x0}, 36 {".hash", SHT_HASH, SHF_ALLOC, 0x80480ec, 0xec, 0x90, 0x3, 0x0, 0x4, 0x4}, 37 {".dynsym", SHT_DYNSYM, SHF_ALLOC, 0x804817c, 0x17c, 0x110, 0x4, 0x1, 0x4, 0x10}, 38 {".dynstr", SHT_STRTAB, SHF_ALLOC, 0x804828c, 0x28c, 0xbb, 0x0, 0x0, 0x1, 0x0}, 39 {".rel.plt", SHT_REL, SHF_ALLOC, 0x8048348, 0x348, 0x20, 0x3, 0x7, 0x4, 0x8}, 40 {".init", SHT_PROGBITS, SHF_ALLOC + SHF_EXECINSTR, 0x8048368, 0x368, 0x11, 0x0, 0x0, 0x4, 0x0}, 41 {".plt", SHT_PROGBITS, SHF_ALLOC + SHF_EXECINSTR, 0x804837c, 0x37c, 0x50, 0x0, 0x0, 0x4, 0x4}, 42 {".text", SHT_PROGBITS, SHF_ALLOC + SHF_EXECINSTR, 0x80483cc, 0x3cc, 0x180, 0x0, 0x0, 0x4, 0x0}, 43 {".fini", SHT_PROGBITS, SHF_ALLOC + SHF_EXECINSTR, 0x804854c, 0x54c, 0xc, 0x0, 0x0, 0x4, 0x0}, 44 {".rodata", SHT_PROGBITS, SHF_ALLOC, 0x8048558, 0x558, 0xa3, 0x0, 0x0, 0x1, 0x0}, 45 {".data", SHT_PROGBITS, SHF_WRITE + SHF_ALLOC, 0x80495fc, 0x5fc, 0xc, 0x0, 0x0, 0x4, 0x0}, 46 {".eh_frame", SHT_PROGBITS, SHF_ALLOC, 0x8049608, 0x608, 0x4, 0x0, 0x0, 0x4, 0x0}, 47 {".dynamic", SHT_DYNAMIC, SHF_WRITE + SHF_ALLOC, 0x804960c, 0x60c, 0x98, 0x4, 0x0, 0x4, 0x8}, 48 {".ctors", SHT_PROGBITS, SHF_WRITE + SHF_ALLOC, 0x80496a4, 0x6a4, 0x8, 0x0, 0x0, 0x4, 0x0}, 49 {".dtors", SHT_PROGBITS, SHF_WRITE + SHF_ALLOC, 0x80496ac, 0x6ac, 0x8, 0x0, 0x0, 0x4, 0x0}, 50 {".jcr", SHT_PROGBITS, SHF_WRITE + SHF_ALLOC, 0x80496b4, 0x6b4, 0x4, 0x0, 0x0, 0x4, 0x0}, 51 {".got", SHT_PROGBITS, SHF_WRITE + SHF_ALLOC, 0x80496b8, 0x6b8, 0x1c, 0x0, 0x0, 0x4, 0x4}, 52 {".bss", SHT_NOBITS, SHF_WRITE + SHF_ALLOC, 0x80496d4, 0x6d4, 0x20, 0x0, 0x0, 0x4, 0x0}, 53 {".comment", SHT_PROGBITS, 0x0, 0x0, 0x6d4, 0x12d, 0x0, 0x0, 0x1, 0x0}, 54 {".debug_aranges", SHT_PROGBITS, 0x0, 0x0, 0x801, 0x20, 0x0, 0x0, 0x1, 0x0}, 55 {".debug_pubnames", SHT_PROGBITS, 0x0, 0x0, 0x821, 0x1b, 0x0, 0x0, 0x1, 0x0}, 56 {".debug_info", SHT_PROGBITS, 0x0, 0x0, 0x83c, 0x11d, 0x0, 0x0, 0x1, 0x0}, 57 {".debug_abbrev", SHT_PROGBITS, 0x0, 0x0, 0x959, 0x41, 0x0, 0x0, 0x1, 0x0}, 58 {".debug_line", SHT_PROGBITS, 0x0, 0x0, 0x99a, 0x35, 0x0, 0x0, 0x1, 0x0}, 59 {".debug_frame", SHT_PROGBITS, 0x0, 0x0, 0x9d0, 0x30, 0x0, 0x0, 0x4, 0x0}, 60 {".debug_str", SHT_PROGBITS, 0x0, 0x0, 0xa00, 0xd, 0x0, 0x0, 0x1, 0x0}, 61 {".shstrtab", SHT_STRTAB, 0x0, 0x0, 0xa0d, 0xf8, 0x0, 0x0, 0x1, 0x0}, 62 {".symtab", SHT_SYMTAB, 0x0, 0x0, 0xfb8, 0x4b0, 0x1d, 0x38, 0x4, 0x10}, 63 {".strtab", SHT_STRTAB, 0x0, 0x0, 0x1468, 0x206, 0x0, 0x0, 0x1, 0x0}, 64 }, 65 []ProgHeader{ 66 {PT_PHDR, PF_R + PF_X, 0x34, 0x8048034, 0x8048034, 0xa0, 0xa0, 0x4}, 67 {PT_INTERP, PF_R, 0xd4, 0x80480d4, 0x80480d4, 0x15, 0x15, 0x1}, 68 {PT_LOAD, PF_R + PF_X, 0x0, 0x8048000, 0x8048000, 0x5fb, 0x5fb, 0x1000}, 69 {PT_LOAD, PF_R + PF_W, 0x5fc, 0x80495fc, 0x80495fc, 0xd8, 0xf8, 0x1000}, 70 {PT_DYNAMIC, PF_R + PF_W, 0x60c, 0x804960c, 0x804960c, 0x98, 0x98, 0x4}, 71 }, 72 []string{"libc.so.6"}, 73 }, 74 { 75 "testdata/gcc-amd64-linux-exec", 76 FileHeader{ELFCLASS64, ELFDATA2LSB, EV_CURRENT, ELFOSABI_NONE, 0, binary.LittleEndian, ET_EXEC, EM_X86_64, 0x4003e0}, 77 []SectionHeader{ 78 {"", SHT_NULL, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}, 79 {".interp", SHT_PROGBITS, SHF_ALLOC, 0x400200, 0x200, 0x1c, 0x0, 0x0, 0x1, 0x0}, 80 {".note.ABI-tag", SHT_NOTE, SHF_ALLOC, 0x40021c, 0x21c, 0x20, 0x0, 0x0, 0x4, 0x0}, 81 {".hash", SHT_HASH, SHF_ALLOC, 0x400240, 0x240, 0x24, 0x5, 0x0, 0x8, 0x4}, 82 {".gnu.hash", SHT_LOOS + 268435446, SHF_ALLOC, 0x400268, 0x268, 0x1c, 0x5, 0x0, 0x8, 0x0}, 83 {".dynsym", SHT_DYNSYM, SHF_ALLOC, 0x400288, 0x288, 0x60, 0x6, 0x1, 0x8, 0x18}, 84 {".dynstr", SHT_STRTAB, SHF_ALLOC, 0x4002e8, 0x2e8, 0x3d, 0x0, 0x0, 0x1, 0x0}, 85 {".gnu.version", SHT_HIOS, SHF_ALLOC, 0x400326, 0x326, 0x8, 0x5, 0x0, 0x2, 0x2}, 86 {".gnu.version_r", SHT_LOOS + 268435454, SHF_ALLOC, 0x400330, 0x330, 0x20, 0x6, 0x1, 0x8, 0x0}, 87 {".rela.dyn", SHT_RELA, SHF_ALLOC, 0x400350, 0x350, 0x18, 0x5, 0x0, 0x8, 0x18}, 88 {".rela.plt", SHT_RELA, SHF_ALLOC, 0x400368, 0x368, 0x30, 0x5, 0xc, 0x8, 0x18}, 89 {".init", SHT_PROGBITS, SHF_ALLOC + SHF_EXECINSTR, 0x400398, 0x398, 0x18, 0x0, 0x0, 0x4, 0x0}, 90 {".plt", SHT_PROGBITS, SHF_ALLOC + SHF_EXECINSTR, 0x4003b0, 0x3b0, 0x30, 0x0, 0x0, 0x4, 0x10}, 91 {".text", SHT_PROGBITS, SHF_ALLOC + SHF_EXECINSTR, 0x4003e0, 0x3e0, 0x1b4, 0x0, 0x0, 0x10, 0x0}, 92 {".fini", SHT_PROGBITS, SHF_ALLOC + SHF_EXECINSTR, 0x400594, 0x594, 0xe, 0x0, 0x0, 0x4, 0x0}, 93 {".rodata", SHT_PROGBITS, SHF_ALLOC, 0x4005a4, 0x5a4, 0x11, 0x0, 0x0, 0x4, 0x0}, 94 {".eh_frame_hdr", SHT_PROGBITS, SHF_ALLOC, 0x4005b8, 0x5b8, 0x24, 0x0, 0x0, 0x4, 0x0}, 95 {".eh_frame", SHT_PROGBITS, SHF_ALLOC, 0x4005e0, 0x5e0, 0xa4, 0x0, 0x0, 0x8, 0x0}, 96 {".ctors", SHT_PROGBITS, SHF_WRITE + SHF_ALLOC, 0x600688, 0x688, 0x10, 0x0, 0x0, 0x8, 0x0}, 97 {".dtors", SHT_PROGBITS, SHF_WRITE + SHF_ALLOC, 0x600698, 0x698, 0x10, 0x0, 0x0, 0x8, 0x0}, 98 {".jcr", SHT_PROGBITS, SHF_WRITE + SHF_ALLOC, 0x6006a8, 0x6a8, 0x8, 0x0, 0x0, 0x8, 0x0}, 99 {".dynamic", SHT_DYNAMIC, SHF_WRITE + SHF_ALLOC, 0x6006b0, 0x6b0, 0x1a0, 0x6, 0x0, 0x8, 0x10}, 100 {".got", SHT_PROGBITS, SHF_WRITE + SHF_ALLOC, 0x600850, 0x850, 0x8, 0x0, 0x0, 0x8, 0x8}, 101 {".got.plt", SHT_PROGBITS, SHF_WRITE + SHF_ALLOC, 0x600858, 0x858, 0x28, 0x0, 0x0, 0x8, 0x8}, 102 {".data", SHT_PROGBITS, SHF_WRITE + SHF_ALLOC, 0x600880, 0x880, 0x18, 0x0, 0x0, 0x8, 0x0}, 103 {".bss", SHT_NOBITS, SHF_WRITE + SHF_ALLOC, 0x600898, 0x898, 0x8, 0x0, 0x0, 0x4, 0x0}, 104 {".comment", SHT_PROGBITS, 0x0, 0x0, 0x898, 0x126, 0x0, 0x0, 0x1, 0x0}, 105 {".debug_aranges", SHT_PROGBITS, 0x0, 0x0, 0x9c0, 0x90, 0x0, 0x0, 0x10, 0x0}, 106 {".debug_pubnames", SHT_PROGBITS, 0x0, 0x0, 0xa50, 0x25, 0x0, 0x0, 0x1, 0x0}, 107 {".debug_info", SHT_PROGBITS, 0x0, 0x0, 0xa75, 0x1a7, 0x0, 0x0, 0x1, 0x0}, 108 {".debug_abbrev", SHT_PROGBITS, 0x0, 0x0, 0xc1c, 0x6f, 0x0, 0x0, 0x1, 0x0}, 109 {".debug_line", SHT_PROGBITS, 0x0, 0x0, 0xc8b, 0x13f, 0x0, 0x0, 0x1, 0x0}, 110 {".debug_str", SHT_PROGBITS, SHF_MERGE + SHF_STRINGS, 0x0, 0xdca, 0xb1, 0x0, 0x0, 0x1, 0x1}, 111 {".debug_ranges", SHT_PROGBITS, 0x0, 0x0, 0xe80, 0x90, 0x0, 0x0, 0x10, 0x0}, 112 {".shstrtab", SHT_STRTAB, 0x0, 0x0, 0xf10, 0x149, 0x0, 0x0, 0x1, 0x0}, 113 {".symtab", SHT_SYMTAB, 0x0, 0x0, 0x19a0, 0x6f0, 0x24, 0x39, 0x8, 0x18}, 114 {".strtab", SHT_STRTAB, 0x0, 0x0, 0x2090, 0x1fc, 0x0, 0x0, 0x1, 0x0}, 115 }, 116 []ProgHeader{ 117 {PT_PHDR, PF_R + PF_X, 0x40, 0x400040, 0x400040, 0x1c0, 0x1c0, 0x8}, 118 {PT_INTERP, PF_R, 0x200, 0x400200, 0x400200, 0x1c, 0x1c, 1}, 119 {PT_LOAD, PF_R + PF_X, 0x0, 0x400000, 0x400000, 0x684, 0x684, 0x200000}, 120 {PT_LOAD, PF_R + PF_W, 0x688, 0x600688, 0x600688, 0x210, 0x218, 0x200000}, 121 {PT_DYNAMIC, PF_R + PF_W, 0x6b0, 0x6006b0, 0x6006b0, 0x1a0, 0x1a0, 0x8}, 122 {PT_NOTE, PF_R, 0x21c, 0x40021c, 0x40021c, 0x20, 0x20, 0x4}, 123 {PT_LOOS + 0x474E550, PF_R, 0x5b8, 0x4005b8, 0x4005b8, 0x24, 0x24, 0x4}, 124 {PT_LOOS + 0x474E551, PF_R + PF_W, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8}, 125 }, 126 []string{"libc.so.6"}, 127 }, 128 { 129 "testdata/hello-world-core.gz", 130 FileHeader{ELFCLASS64, ELFDATA2LSB, EV_CURRENT, ELFOSABI_NONE, 0x0, binary.LittleEndian, ET_CORE, EM_X86_64, 0x0}, 131 []SectionHeader{}, 132 []ProgHeader{ 133 {Type: PT_NOTE, Flags: 0x0, Off: 0x3f8, Vaddr: 0x0, Paddr: 0x0, Filesz: 0x8ac, Memsz: 0x0, Align: 0x0}, 134 {Type: PT_LOAD, Flags: PF_X + PF_R, Off: 0x1000, Vaddr: 0x400000, Paddr: 0x0, Filesz: 0x0, Memsz: 0x1000, Align: 0x1000}, 135 {Type: PT_LOAD, Flags: PF_R, Off: 0x1000, Vaddr: 0x401000, Paddr: 0x0, Filesz: 0x1000, Memsz: 0x1000, Align: 0x1000}, 136 {Type: PT_LOAD, Flags: PF_W + PF_R, Off: 0x2000, Vaddr: 0x402000, Paddr: 0x0, Filesz: 0x1000, Memsz: 0x1000, Align: 0x1000}, 137 {Type: PT_LOAD, Flags: PF_X + PF_R, Off: 0x3000, Vaddr: 0x7f54078b8000, Paddr: 0x0, Filesz: 0x0, Memsz: 0x1b5000, Align: 0x1000}, 138 {Type: PT_LOAD, Flags: 0x0, Off: 0x3000, Vaddr: 0x7f5407a6d000, Paddr: 0x0, Filesz: 0x0, Memsz: 0x1ff000, Align: 0x1000}, 139 {Type: PT_LOAD, Flags: PF_R, Off: 0x3000, Vaddr: 0x7f5407c6c000, Paddr: 0x0, Filesz: 0x4000, Memsz: 0x4000, Align: 0x1000}, 140 {Type: PT_LOAD, Flags: PF_W + PF_R, Off: 0x7000, Vaddr: 0x7f5407c70000, Paddr: 0x0, Filesz: 0x2000, Memsz: 0x2000, Align: 0x1000}, 141 {Type: PT_LOAD, Flags: PF_W + PF_R, Off: 0x9000, Vaddr: 0x7f5407c72000, Paddr: 0x0, Filesz: 0x5000, Memsz: 0x5000, Align: 0x1000}, 142 {Type: PT_LOAD, Flags: PF_X + PF_R, Off: 0xe000, Vaddr: 0x7f5407c77000, Paddr: 0x0, Filesz: 0x0, Memsz: 0x22000, Align: 0x1000}, 143 {Type: PT_LOAD, Flags: PF_W + PF_R, Off: 0xe000, Vaddr: 0x7f5407e81000, Paddr: 0x0, Filesz: 0x3000, Memsz: 0x3000, Align: 0x1000}, 144 {Type: PT_LOAD, Flags: PF_W + PF_R, Off: 0x11000, Vaddr: 0x7f5407e96000, Paddr: 0x0, Filesz: 0x3000, Memsz: 0x3000, Align: 0x1000}, 145 {Type: PT_LOAD, Flags: PF_R, Off: 0x14000, Vaddr: 0x7f5407e99000, Paddr: 0x0, Filesz: 0x1000, Memsz: 0x1000, Align: 0x1000}, 146 {Type: PT_LOAD, Flags: PF_W + PF_R, Off: 0x15000, Vaddr: 0x7f5407e9a000, Paddr: 0x0, Filesz: 0x2000, Memsz: 0x2000, Align: 0x1000}, 147 {Type: PT_LOAD, Flags: PF_W + PF_R, Off: 0x17000, Vaddr: 0x7fff79972000, Paddr: 0x0, Filesz: 0x23000, Memsz: 0x23000, Align: 0x1000}, 148 {Type: PT_LOAD, Flags: PF_X + PF_R, Off: 0x3a000, Vaddr: 0x7fff799f8000, Paddr: 0x0, Filesz: 0x1000, Memsz: 0x1000, Align: 0x1000}, 149 {Type: PT_LOAD, Flags: PF_X + PF_R, Off: 0x3b000, Vaddr: 0xffffffffff600000, Paddr: 0x0, Filesz: 0x1000, Memsz: 0x1000, Align: 0x1000}, 150 }, 151 nil, 152 }, 153 } 154 155 func TestOpen(t *testing.T) { 156 for i := range fileTests { 157 tt := &fileTests[i] 158 159 var f *File 160 var err error 161 if path.Ext(tt.file) == ".gz" { 162 var r io.ReaderAt 163 if r, err = decompress(tt.file); err == nil { 164 f, err = NewFile(r) 165 } 166 } else { 167 f, err = Open(tt.file) 168 } 169 if err != nil { 170 t.Errorf("cannot open file %s: %v", tt.file, err) 171 continue 172 } 173 defer f.Close() 174 if !reflect.DeepEqual(f.FileHeader, tt.hdr) { 175 t.Errorf("open %s:\n\thave %#v\n\twant %#v\n", tt.file, f.FileHeader, tt.hdr) 176 continue 177 } 178 for i, s := range f.Sections { 179 if i >= len(tt.sections) { 180 break 181 } 182 sh := &tt.sections[i] 183 if !reflect.DeepEqual(&s.SectionHeader, sh) { 184 t.Errorf("open %s, section %d:\n\thave %#v\n\twant %#v\n", tt.file, i, &s.SectionHeader, sh) 185 } 186 } 187 for i, p := range f.Progs { 188 if i >= len(tt.progs) { 189 break 190 } 191 ph := &tt.progs[i] 192 if !reflect.DeepEqual(&p.ProgHeader, ph) { 193 t.Errorf("open %s, program %d:\n\thave %#v\n\twant %#v\n", tt.file, i, &p.ProgHeader, ph) 194 } 195 } 196 tn := len(tt.sections) 197 fn := len(f.Sections) 198 if tn != fn { 199 t.Errorf("open %s: len(Sections) = %d, want %d", tt.file, fn, tn) 200 } 201 tn = len(tt.progs) 202 fn = len(f.Progs) 203 if tn != fn { 204 t.Errorf("open %s: len(Progs) = %d, want %d", tt.file, fn, tn) 205 } 206 tl := tt.needed 207 fl, err := f.ImportedLibraries() 208 if err != nil { 209 t.Error(err) 210 } 211 if !reflect.DeepEqual(tl, fl) { 212 t.Errorf("open %s: DT_NEEDED = %v, want %v", tt.file, tl, fl) 213 } 214 } 215 } 216 217 // elf.NewFile requires io.ReaderAt, which compress/gzip cannot 218 // provide. Decompress the file to a bytes.Reader. 219 func decompress(gz string) (io.ReaderAt, error) { 220 in, err := os.Open(gz) 221 if err != nil { 222 return nil, err 223 } 224 defer in.Close() 225 r, err := gzip.NewReader(in) 226 if err != nil { 227 return nil, err 228 } 229 var out bytes.Buffer 230 _, err = io.Copy(&out, r) 231 return bytes.NewReader(out.Bytes()), err 232 } 233 234 type relocationTestEntry struct { 235 entryNumber int 236 entry *dwarf.Entry 237 } 238 239 type relocationTest struct { 240 file string 241 entries []relocationTestEntry 242 } 243 244 var relocationTests = []relocationTest{ 245 { 246 "testdata/go-relocation-test-gcc441-x86-64.obj", 247 []relocationTestEntry{ 248 {0, &dwarf.Entry{ 249 Offset: 0xb, 250 Tag: dwarf.TagCompileUnit, 251 Children: true, 252 Field: []dwarf.Field{ 253 {Attr: dwarf.AttrProducer, Val: "GNU C 4.4.1", Class: dwarf.ClassString}, 254 {Attr: dwarf.AttrLanguage, Val: int64(1), Class: dwarf.ClassConstant}, 255 {Attr: dwarf.AttrName, Val: "go-relocation-test.c", Class: dwarf.ClassString}, 256 {Attr: dwarf.AttrCompDir, Val: "/tmp", Class: dwarf.ClassString}, 257 {Attr: dwarf.AttrLowpc, Val: uint64(0x0), Class: dwarf.ClassAddress}, 258 {Attr: dwarf.AttrHighpc, Val: uint64(0x6), Class: dwarf.ClassAddress}, 259 {Attr: dwarf.AttrStmtList, Val: int64(0), Class: dwarf.ClassLinePtr}, 260 }, 261 }}, 262 }, 263 }, 264 { 265 "testdata/go-relocation-test-gcc441-x86.obj", 266 []relocationTestEntry{ 267 {0, &dwarf.Entry{ 268 Offset: 0xb, 269 Tag: dwarf.TagCompileUnit, 270 Children: true, 271 Field: []dwarf.Field{ 272 {Attr: dwarf.AttrProducer, Val: "GNU C 4.4.1", Class: dwarf.ClassString}, 273 {Attr: dwarf.AttrLanguage, Val: int64(1), Class: dwarf.ClassConstant}, 274 {Attr: dwarf.AttrName, Val: "t.c", Class: dwarf.ClassString}, 275 {Attr: dwarf.AttrCompDir, Val: "/tmp", Class: dwarf.ClassString}, 276 {Attr: dwarf.AttrLowpc, Val: uint64(0x0), Class: dwarf.ClassAddress}, 277 {Attr: dwarf.AttrHighpc, Val: uint64(0x5), Class: dwarf.ClassAddress}, 278 {Attr: dwarf.AttrStmtList, Val: int64(0), Class: dwarf.ClassLinePtr}, 279 }, 280 }}, 281 }, 282 }, 283 { 284 "testdata/go-relocation-test-gcc424-x86-64.obj", 285 []relocationTestEntry{ 286 {0, &dwarf.Entry{ 287 Offset: 0xb, 288 Tag: dwarf.TagCompileUnit, 289 Children: true, 290 Field: []dwarf.Field{ 291 {Attr: dwarf.AttrProducer, Val: "GNU C 4.2.4 (Ubuntu 4.2.4-1ubuntu4)", Class: dwarf.ClassString}, 292 {Attr: dwarf.AttrLanguage, Val: int64(1), Class: dwarf.ClassConstant}, 293 {Attr: dwarf.AttrName, Val: "go-relocation-test-gcc424.c", Class: dwarf.ClassString}, 294 {Attr: dwarf.AttrCompDir, Val: "/tmp", Class: dwarf.ClassString}, 295 {Attr: dwarf.AttrLowpc, Val: uint64(0x0), Class: dwarf.ClassAddress}, 296 {Attr: dwarf.AttrHighpc, Val: uint64(0x6), Class: dwarf.ClassAddress}, 297 {Attr: dwarf.AttrStmtList, Val: int64(0), Class: dwarf.ClassLinePtr}, 298 }, 299 }}, 300 }, 301 }, 302 { 303 "testdata/go-relocation-test-gcc482-aarch64.obj", 304 []relocationTestEntry{ 305 {0, &dwarf.Entry{ 306 Offset: 0xb, 307 Tag: dwarf.TagCompileUnit, 308 Children: true, 309 Field: []dwarf.Field{ 310 {Attr: dwarf.AttrProducer, Val: "GNU C 4.8.2 -g -fstack-protector", Class: dwarf.ClassString}, 311 {Attr: dwarf.AttrLanguage, Val: int64(1), Class: dwarf.ClassConstant}, 312 {Attr: dwarf.AttrName, Val: "go-relocation-test-gcc482.c", Class: dwarf.ClassString}, 313 {Attr: dwarf.AttrCompDir, Val: "/tmp", Class: dwarf.ClassString}, 314 {Attr: dwarf.AttrLowpc, Val: uint64(0x0), Class: dwarf.ClassAddress}, 315 {Attr: dwarf.AttrHighpc, Val: int64(0x24), Class: dwarf.ClassConstant}, 316 {Attr: dwarf.AttrStmtList, Val: int64(0), Class: dwarf.ClassLinePtr}, 317 }, 318 }}, 319 }, 320 }, 321 { 322 "testdata/go-relocation-test-gcc492-arm.obj", 323 []relocationTestEntry{ 324 {0, &dwarf.Entry{ 325 Offset: 0xb, 326 Tag: dwarf.TagCompileUnit, 327 Children: true, 328 Field: []dwarf.Field{ 329 {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}, 330 {Attr: dwarf.AttrLanguage, Val: int64(1), Class: dwarf.ClassConstant}, 331 {Attr: dwarf.AttrName, Val: "go-relocation-test-gcc492.c", Class: dwarf.ClassString}, 332 {Attr: dwarf.AttrCompDir, Val: "/root/go/src/debug/elf/testdata", Class: dwarf.ClassString}, 333 {Attr: dwarf.AttrLowpc, Val: uint64(0x0), Class: dwarf.ClassAddress}, 334 {Attr: dwarf.AttrHighpc, Val: int64(0x28), Class: dwarf.ClassConstant}, 335 {Attr: dwarf.AttrStmtList, Val: int64(0), Class: dwarf.ClassLinePtr}, 336 }, 337 }}, 338 }, 339 }, 340 { 341 "testdata/go-relocation-test-clang-arm.obj", 342 []relocationTestEntry{ 343 {0, &dwarf.Entry{ 344 Offset: 0xb, 345 Tag: dwarf.TagCompileUnit, 346 Children: true, 347 Field: []dwarf.Field{ 348 {Attr: dwarf.AttrProducer, Val: "Debian clang version 3.5.0-10 (tags/RELEASE_350/final) (based on LLVM 3.5.0)", Class: dwarf.ClassString}, 349 {Attr: dwarf.AttrLanguage, Val: int64(12), Class: dwarf.ClassConstant}, 350 {Attr: dwarf.AttrName, Val: "hello.c", Class: dwarf.ClassString}, 351 {Attr: dwarf.AttrStmtList, Val: int64(0x0), Class: dwarf.ClassLinePtr}, 352 {Attr: dwarf.AttrCompDir, Val: "/tmp", Class: dwarf.ClassString}, 353 {Attr: dwarf.AttrLowpc, Val: uint64(0x0), Class: dwarf.ClassAddress}, 354 {Attr: dwarf.AttrHighpc, Val: int64(48), Class: dwarf.ClassConstant}, 355 }, 356 }}, 357 }, 358 }, 359 { 360 "testdata/go-relocation-test-gcc5-ppc.obj", 361 []relocationTestEntry{ 362 {0, &dwarf.Entry{ 363 Offset: 0xb, 364 Tag: dwarf.TagCompileUnit, 365 Children: true, 366 Field: []dwarf.Field{ 367 {Attr: dwarf.AttrProducer, Val: "GNU C11 5.0.0 20150116 (experimental) -Asystem=linux -Asystem=unix -Asystem=posix -g", Class: dwarf.ClassString}, 368 {Attr: dwarf.AttrLanguage, Val: int64(12), Class: dwarf.ClassConstant}, 369 {Attr: dwarf.AttrName, Val: "go-relocation-test-gcc5-ppc.c", Class: dwarf.ClassString}, 370 {Attr: dwarf.AttrCompDir, Val: "/tmp", Class: dwarf.ClassString}, 371 {Attr: dwarf.AttrLowpc, Val: uint64(0x0), Class: dwarf.ClassAddress}, 372 {Attr: dwarf.AttrHighpc, Val: int64(0x44), Class: dwarf.ClassConstant}, 373 {Attr: dwarf.AttrStmtList, Val: int64(0), Class: dwarf.ClassLinePtr}, 374 }, 375 }}, 376 }, 377 }, 378 { 379 "testdata/go-relocation-test-gcc482-ppc64le.obj", 380 []relocationTestEntry{ 381 {0, &dwarf.Entry{ 382 Offset: 0xb, 383 Tag: dwarf.TagCompileUnit, 384 Children: true, 385 Field: []dwarf.Field{ 386 {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}, 387 {Attr: dwarf.AttrLanguage, Val: int64(1), Class: dwarf.ClassConstant}, 388 {Attr: dwarf.AttrName, Val: "go-relocation-test-gcc482-ppc64le.c", Class: dwarf.ClassString}, 389 {Attr: dwarf.AttrCompDir, Val: "/tmp", Class: dwarf.ClassString}, 390 {Attr: dwarf.AttrLowpc, Val: uint64(0x0), Class: dwarf.ClassAddress}, 391 {Attr: dwarf.AttrHighpc, Val: uint64(0x24), Class: dwarf.ClassAddress}, 392 {Attr: dwarf.AttrStmtList, Val: int64(0), Class: dwarf.ClassLinePtr}, 393 }, 394 }}, 395 }, 396 }, 397 { 398 "testdata/go-relocation-test-gcc492-mips64.obj", 399 []relocationTestEntry{ 400 {0, &dwarf.Entry{ 401 Offset: 0xb, 402 Tag: dwarf.TagCompileUnit, 403 Children: true, 404 Field: []dwarf.Field{ 405 {Attr: dwarf.AttrProducer, Val: "GNU C 4.9.2 -meb -mabi=64 -march=mips3 -mtune=mips64 -mllsc -mno-shared -g", Class: dwarf.ClassString}, 406 {Attr: dwarf.AttrLanguage, Val: int64(1), Class: dwarf.ClassConstant}, 407 {Attr: dwarf.AttrName, Val: "hello.c", Class: dwarf.ClassString}, 408 {Attr: dwarf.AttrCompDir, Val: "/tmp", Class: dwarf.ClassString}, 409 {Attr: dwarf.AttrLowpc, Val: uint64(0x0), Class: dwarf.ClassAddress}, 410 {Attr: dwarf.AttrHighpc, Val: int64(100), Class: dwarf.ClassConstant}, 411 {Attr: dwarf.AttrStmtList, Val: int64(0), Class: dwarf.ClassLinePtr}, 412 }, 413 }}, 414 }, 415 }, 416 { 417 "testdata/go-relocation-test-gcc493-mips64le.obj", 418 []relocationTestEntry{ 419 {0, &dwarf.Entry{ 420 Offset: 0xb, 421 Tag: dwarf.TagCompileUnit, 422 Children: true, 423 Field: []dwarf.Field{ 424 {Attr: dwarf.AttrProducer, Val: "GNU C 4.9.3 -mel -mabi=64 -mllsc -mno-shared -g -fstack-protector-strong", Class: dwarf.ClassString}, 425 {Attr: dwarf.AttrLanguage, Val: int64(1), Class: dwarf.ClassConstant}, 426 {Attr: dwarf.AttrName, Val: "hello.c", Class: dwarf.ClassString}, 427 {Attr: dwarf.AttrCompDir, Val: "/tmp", Class: dwarf.ClassString}, 428 {Attr: dwarf.AttrLowpc, Val: uint64(0x0), Class: dwarf.ClassAddress}, 429 {Attr: dwarf.AttrHighpc, Val: int64(100), Class: dwarf.ClassConstant}, 430 {Attr: dwarf.AttrStmtList, Val: int64(0), Class: dwarf.ClassLinePtr}, 431 }, 432 }}, 433 }, 434 }, 435 { 436 "testdata/go-relocation-test-clang-x86.obj", 437 []relocationTestEntry{ 438 {0, &dwarf.Entry{ 439 Offset: 0xb, 440 Tag: dwarf.TagCompileUnit, 441 Children: true, 442 Field: []dwarf.Field{ 443 {Attr: dwarf.AttrProducer, Val: "clang version google3-trunk (trunk r209387)", Class: dwarf.ClassString}, 444 {Attr: dwarf.AttrLanguage, Val: int64(12), Class: dwarf.ClassConstant}, 445 {Attr: dwarf.AttrName, Val: "go-relocation-test-clang.c", Class: dwarf.ClassString}, 446 {Attr: dwarf.AttrStmtList, Val: int64(0), Class: dwarf.ClassLinePtr}, 447 {Attr: dwarf.AttrCompDir, Val: "/tmp", Class: dwarf.ClassString}, 448 }, 449 }}, 450 }, 451 }, 452 { 453 "testdata/gcc-amd64-openbsd-debug-with-rela.obj", 454 []relocationTestEntry{ 455 {203, &dwarf.Entry{ 456 Offset: 0xc62, 457 Tag: dwarf.TagMember, 458 Children: false, 459 Field: []dwarf.Field{ 460 {Attr: dwarf.AttrName, Val: "it_interval", Class: dwarf.ClassString}, 461 {Attr: dwarf.AttrDeclFile, Val: int64(7), Class: dwarf.ClassConstant}, 462 {Attr: dwarf.AttrDeclLine, Val: int64(236), Class: dwarf.ClassConstant}, 463 {Attr: dwarf.AttrType, Val: dwarf.Offset(0xb7f), Class: dwarf.ClassReference}, 464 {Attr: dwarf.AttrDataMemberLoc, Val: []byte{0x23, 0x0}, Class: dwarf.ClassExprLoc}, 465 }, 466 }}, 467 {204, &dwarf.Entry{ 468 Offset: 0xc70, 469 Tag: dwarf.TagMember, 470 Children: false, 471 Field: []dwarf.Field{ 472 {Attr: dwarf.AttrName, Val: "it_value", Class: dwarf.ClassString}, 473 {Attr: dwarf.AttrDeclFile, Val: int64(7), Class: dwarf.ClassConstant}, 474 {Attr: dwarf.AttrDeclLine, Val: int64(237), Class: dwarf.ClassConstant}, 475 {Attr: dwarf.AttrType, Val: dwarf.Offset(0xb7f), Class: dwarf.ClassReference}, 476 {Attr: dwarf.AttrDataMemberLoc, Val: []byte{0x23, 0x10}, Class: dwarf.ClassExprLoc}, 477 }, 478 }}, 479 }, 480 }, 481 } 482 483 func TestDWARFRelocations(t *testing.T) { 484 for i, test := range relocationTests { 485 f, err := Open(test.file) 486 if err != nil { 487 t.Error(err) 488 continue 489 } 490 dwarf, err := f.DWARF() 491 if err != nil { 492 t.Error(err) 493 continue 494 } 495 for _, testEntry := range test.entries { 496 reader := dwarf.Reader() 497 for j := 0; j < testEntry.entryNumber; j++ { 498 entry, err := reader.Next() 499 if entry == nil || err != nil { 500 t.Errorf("Failed to skip to entry %d: %v", testEntry.entryNumber, err) 501 continue 502 } 503 } 504 entry, err := reader.Next() 505 if err != nil { 506 t.Error(err) 507 continue 508 } 509 if !reflect.DeepEqual(testEntry.entry, entry) { 510 t.Errorf("#%d/%d: mismatch: got:%#v want:%#v", i, testEntry.entryNumber, entry, testEntry.entry) 511 continue 512 } 513 } 514 } 515 } 516 517 func TestNoSectionOverlaps(t *testing.T) { 518 // Ensure 6l outputs sections without overlaps. 519 if runtime.GOOS != "linux" && runtime.GOOS != "freebsd" { 520 return // not ELF 521 } 522 _ = net.ResolveIPAddr // force dynamic linkage 523 f, err := Open(os.Args[0]) 524 if err != nil { 525 t.Error(err) 526 return 527 } 528 for i, si := range f.Sections { 529 sih := si.SectionHeader 530 if sih.Type == SHT_NOBITS { 531 continue 532 } 533 for j, sj := range f.Sections { 534 sjh := sj.SectionHeader 535 if i == j || sjh.Type == SHT_NOBITS || sih.Offset == sjh.Offset && sih.Size == 0 { 536 continue 537 } 538 if sih.Offset >= sjh.Offset && sih.Offset < sjh.Offset+sjh.Size { 539 t.Errorf("ld produced ELF with section %s within %s: 0x%x <= 0x%x..0x%x < 0x%x", 540 sih.Name, sjh.Name, sjh.Offset, sih.Offset, sih.Offset+sih.Size, sjh.Offset+sjh.Size) 541 } 542 } 543 } 544 }