GoPLS Viewer

Home|gopls/cmd/splitdwarf/internal/macho/file_test.go
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
5package macho
6
7import (
8    "reflect"
9    "strings"
10    "testing"
11)
12
13type fileTest struct {
14    file        string
15    hdr         FileHeader
16    loads       []interface{}
17    sections    []*SectionHeader
18    relocations map[string][]Reloc
19}
20
21var fileTests = []fileTest{
22    {
23        "testdata/gcc-386-darwin-exec",
24        FileHeader{0xfeedfaceCpu3860x30x20xc0x3c00x85},
25        []interface{}{
26            &SegmentHeader{LcSegment0x38"__PAGEZERO"0x00x10000x00x00x00x00x00x00},
27            &SegmentHeader{LcSegment0xc0"__TEXT"0x10000x10000x00x10000x70x50x20x00},
28            &SegmentHeader{LcSegment0xc0"__DATA"0x20000x10000x10000x10000x70x30x20x02},
29            &SegmentHeader{LcSegment0x7c"__IMPORT"0x30000x10000x20000x10000x70x70x10x04},
30            &SegmentHeader{LcSegment0x38"__LINKEDIT"0x40000x10000x30000x12c0x70x10x00x05},
31            nil// LC_SYMTAB
32            nil// LC_DYSYMTAB
33            nil// LC_LOAD_DYLINKER
34            nil// LC_UUID
35            nil// LC_UNIXTHREAD
36            &Dylib{DylibCmd{}, "/usr/lib/libgcc_s.1.dylib"0x20x100000x10000},
37            &Dylib{DylibCmd{}, "/usr/lib/libSystem.B.dylib"0x20x6f01040x10000},
38        },
39        []*SectionHeader{
40            {"__text""__TEXT"0x1f680x880xf680x20x00x00x80000400000},
41            {"__cstring""__TEXT"0x1ff00xd0xff00x00x00x00x2000},
42            {"__data""__DATA"0x20000x140x10000x20x00x00x0000},
43            {"__dyld""__DATA"0x20140x1c0x10140x20x00x00x0000},
44            {"__jump_table""__IMPORT"0x30000xa0x20000x60x00x00x4000008050},
45        },
46        nil,
47    },
48    {
49        "testdata/gcc-amd64-darwin-exec",
50        FileHeader{0xfeedfacfCpuAmd640x800000030x20xb0x5680x85},
51        []interface{}{
52            &SegmentHeader{LcSegment640x48"__PAGEZERO"0x00x1000000000x00x00x00x00x00x00},
53            &SegmentHeader{LcSegment640x1d8"__TEXT"0x1000000000x10000x00x10000x70x50x50x00},
54            &SegmentHeader{LcSegment640x138"__DATA"0x1000010000x10000x10000x10000x70x30x30x05},
55            &SegmentHeader{LcSegment640x48"__LINKEDIT"0x1000020000x10000x20000x1400x70x10x00x08},
56            nil// LC_SYMTAB
57            nil// LC_DYSYMTAB
58            nil// LC_LOAD_DYLINKER
59            nil// LC_UUID
60            nil// LC_UNIXTHREAD
61            &Dylib{DylibCmd{}, "/usr/lib/libgcc_s.1.dylib"0x20x100000x10000},
62            &Dylib{DylibCmd{}, "/usr/lib/libSystem.B.dylib"0x20x6f01040x10000},
63        },
64        []*SectionHeader{
65            {"__text""__TEXT"0x100000f140x6d0xf140x20x00x00x80000400000},
66            {"__symbol_stub1""__TEXT"0x100000f810xc0xf810x00x00x00x80000408060},
67            {"__stub_helper""__TEXT"0x100000f900x180xf900x20x00x00x0000},
68            {"__cstring""__TEXT"0x100000fa80xd0xfa80x00x00x00x2000},
69            {"__eh_frame""__TEXT"0x100000fb80x480xfb80x30x00x00x6000000b000},
70            {"__data""__DATA"0x1000010000x1c0x10000x30x00x00x0000},
71            {"__dyld""__DATA"0x1000010200x380x10200x30x00x00x0000},
72            {"__la_symbol_ptr""__DATA"0x1000010580x100x10580x20x00x00x7200},
73        },
74        nil,
75    },
76    {
77        "testdata/gcc-amd64-darwin-exec-debug",
78        FileHeader{0xfeedfacfCpuAmd640x800000030xa0x40x5a00},
79        []interface{}{
80            nil// LC_UUID
81            &SegmentHeader{LcSegment640x1d8"__TEXT"0x1000000000x10000x00x00x70x50x50x00},
82            &SegmentHeader{LcSegment640x138"__DATA"0x1000010000x10000x00x00x70x30x30x05},
83            &SegmentHeader{LcSegment640x278"__DWARF"0x1000020000x10000x10000x1bc0x70x30x70x08},
84        },
85        []*SectionHeader{
86            {"__text""__TEXT"0x100000f140x00x00x20x00x00x80000400000},
87            {"__symbol_stub1""__TEXT"0x100000f810x00x00x00x00x00x80000408060},
88            {"__stub_helper""__TEXT"0x100000f900x00x00x20x00x00x0000},
89            {"__cstring""__TEXT"0x100000fa80x00x00x00x00x00x2000},
90            {"__eh_frame""__TEXT"0x100000fb80x00x00x30x00x00x6000000b000},
91            {"__data""__DATA"0x1000010000x00x00x30x00x00x0000},
92            {"__dyld""__DATA"0x1000010200x00x00x30x00x00x0000},
93            {"__la_symbol_ptr""__DATA"0x1000010580x00x00x20x00x00x7200},
94            {"__debug_abbrev""__DWARF"0x1000020000x360x10000x00x00x00x0000},
95            {"__debug_aranges""__DWARF"0x1000020360x300x10360x00x00x00x0000},
96            {"__debug_frame""__DWARF"0x1000020660x400x10660x00x00x00x0000},
97            {"__debug_info""__DWARF"0x1000020a60x540x10a60x00x00x00x0000},
98            {"__debug_line""__DWARF"0x1000020fa0x470x10fa0x00x00x00x0000},
99            {"__debug_pubnames""__DWARF"0x1000021410x1b0x11410x00x00x00x0000},
100            {"__debug_str""__DWARF"0x10000215c0x600x115c0x00x00x00x0000},
101        },
102        nil,
103    },
104    {
105        "testdata/clang-386-darwin-exec-with-rpath",
106        FileHeader{0xfeedfaceCpu3860x30x20x100x42c0x1200085},
107        []interface{}{
108            nil// LC_SEGMENT
109            nil// LC_SEGMENT
110            nil// LC_SEGMENT
111            nil// LC_SEGMENT
112            nil// LC_DYLD_INFO_ONLY
113            nil// LC_SYMTAB
114            nil// LC_DYSYMTAB
115            nil// LC_LOAD_DYLINKER
116            nil// LC_UUID
117            nil// LC_VERSION_MIN_MACOSX
118            nil// LC_SOURCE_VERSION
119            nil// LC_MAIN
120            nil// LC_LOAD_DYLIB
121            &Rpath{LcRpath"/my/rpath"},
122            nil// LC_FUNCTION_STARTS
123            nil// LC_DATA_IN_CODE
124        },
125        nil,
126        nil,
127    },
128    {
129        "testdata/clang-amd64-darwin-exec-with-rpath",
130        FileHeader{0xfeedfacfCpuAmd640x800000030x20x100x4c80x200085},
131        []interface{}{
132            nil// LC_SEGMENT
133            nil// LC_SEGMENT
134            nil// LC_SEGMENT
135            nil// LC_SEGMENT
136            nil// LC_DYLD_INFO_ONLY
137            nil// LC_SYMTAB
138            nil// LC_DYSYMTAB
139            nil// LC_LOAD_DYLINKER
140            nil// LC_UUID
141            nil// LC_VERSION_MIN_MACOSX
142            nil// LC_SOURCE_VERSION
143            nil// LC_MAIN
144            nil// LC_LOAD_DYLIB
145            &Rpath{LcRpath"/my/rpath"},
146            nil// LC_FUNCTION_STARTS
147            nil// LC_DATA_IN_CODE
148        },
149        nil,
150        nil,
151    },
152    {
153        "testdata/clang-386-darwin.obj",
154        FileHeader{0xfeedfaceCpu3860x30x10x40x1380x2000},
155        nil,
156        nil,
157        map[string][]Reloc{
158            "__text": []Reloc{
159                {
160                    Addr:      0x1d,
161                    Type:      uint8(GENERIC_RELOC_VANILLA),
162                    Len:       2,
163                    Pcrel:     true,
164                    Extern:    true,
165                    Value:     1,
166                    Scatteredfalse,
167                },
168                {
169                    Addr:      0xe,
170                    Type:      uint8(GENERIC_RELOC_LOCAL_SECTDIFF),
171                    Len:       2,
172                    Pcrel:     false,
173                    Value:     0x2d,
174                    Scatteredtrue,
175                },
176                {
177                    Addr:      0x0,
178                    Type:      uint8(GENERIC_RELOC_PAIR),
179                    Len:       2,
180                    Pcrel:     false,
181                    Value:     0xb,
182                    Scatteredtrue,
183                },
184            },
185        },
186    },
187    {
188        "testdata/clang-amd64-darwin.obj",
189        FileHeader{0xfeedfacfCpuAmd640x30x10x40x2000x2000},
190        nil,
191        nil,
192        map[string][]Reloc{
193            "__text": []Reloc{
194                {
195                    Addr:   0x19,
196                    Type:   uint8(X86_64_RELOC_BRANCH),
197                    Len:    2,
198                    Pcrel:  true,
199                    Externtrue,
200                    Value:  1,
201                },
202                {
203                    Addr:   0xb,
204                    Type:   uint8(X86_64_RELOC_SIGNED),
205                    Len:    2,
206                    Pcrel:  true,
207                    Externfalse,
208                    Value:  2,
209                },
210            },
211            "__compact_unwind": []Reloc{
212                {
213                    Addr:   0x0,
214                    Type:   uint8(X86_64_RELOC_UNSIGNED),
215                    Len:    3,
216                    Pcrel:  false,
217                    Externfalse,
218                    Value:  1,
219                },
220            },
221        },
222    },
223}
224
225func TestOpen(t *testing.T) {
226    for i := range fileTests {
227        tt := &fileTests[i]
228
229        ferr := Open(tt.file)
230        if err != nil {
231            t.Error(err)
232            continue
233        }
234        if !reflect.DeepEqual(f.FileHeadertt.hdr) {
235            t.Errorf("open %s:\n\thave %#v\n\twant %#v\n"tt.filef.FileHeadertt.hdr)
236            continue
237        }
238        // for i, l := range f.Loads {
239        //     if len(l.Raw()) < 8 {
240        //         t.Errorf("open %s, command %d:\n\tload command %T don't have enough data\n", tt.file, i, l)
241        //     }
242        // }
243        if tt.loads != nil {
244            for il := range f.Loads {
245                if i >= len(tt.loads) {
246                    break
247                }
248
249                want := tt.loads[i]
250                if want == nil {
251                    continue
252                }
253
254                switch l := l.(type) {
255                case *Segment:
256                    have := &l.SegmentHeader
257                    if !reflect.DeepEqual(havewant) {
258                        t.Errorf("open %s, command %d:\n\thave %s\n\twant %s\n"tt.fileihave.String(), want.(*SegmentHeader).String())
259                    }
260                case *Dylib:
261                    // have := l
262                    // have.LoadBytes = nil
263                    // if !reflect.DeepEqual(have, want) {
264                    //     t.Errorf("open %s, command %d:\n\thave %#v\n\twant %#v\n", tt.file, i, have, want)
265                    // }
266                case *Rpath:
267                    // have := l
268                    // have.LoadBytes = nil
269                    // if !reflect.DeepEqual(have, want) {
270                    //     t.Errorf("open %s, command %d:\n\thave %#v\n\twant %#v\n", tt.file, i, have, want)
271                    // }
272                default:
273                    t.Errorf("open %s, command %d: unknown load command\n\thave %#v\n\twant %#v\n"tt.fileilwant)
274                }
275            }
276            tn := len(tt.loads)
277            fn := len(f.Loads)
278            if tn != fn {
279                t.Errorf("open %s: len(Loads) = %d, want %d"tt.filefntn)
280            }
281        }
282
283        if tt.sections != nil {
284            for ish := range f.Sections {
285                if i >= len(tt.sections) {
286                    break
287                }
288                have := &sh.SectionHeader
289                want := tt.sections[i]
290                if !reflect.DeepEqual(havewant) {
291                    t.Errorf("open %s, section %d:\n\thave %#v\n\twant %#v\n"tt.fileihavewant)
292                }
293            }
294            tn := len(tt.sections)
295            fn := len(f.Sections)
296            if tn != fn {
297                t.Errorf("open %s: len(Sections) = %d, want %d"tt.filefntn)
298            }
299        }
300
301        if tt.relocations != nil {
302            for ish := range f.Sections {
303                have := sh.Relocs
304                want := tt.relocations[sh.Name]
305                if !reflect.DeepEqual(havewant) {
306                    t.Errorf("open %s, relocations in section %d (%s):\n\thave %#v\n\twant %#v\n"tt.fileish.Namehavewant)
307                }
308            }
309        }
310    }
311}
312
313func TestOpenFailure(t *testing.T) {
314    filename := "file.go"    // not a Mach-O file
315    _err := Open(filename// don't crash
316    if err == nil {
317        t.Errorf("open %s: succeeded unexpectedly"filename)
318    }
319}
320
321func TestOpenFat(t *testing.T) {
322    fferr := OpenFat("testdata/fat-gcc-386-amd64-darwin-exec")
323    if err != nil {
324        t.Fatal(err)
325    }
326
327    if ff.Magic != MagicFat {
328        t.Errorf("OpenFat: got magic number %#x, want %#x"ff.MagicMagicFat)
329    }
330    if len(ff.Arches) != 2 {
331        t.Errorf("OpenFat: got %d architectures, want 2"len(ff.Arches))
332    }
333
334    for i := range ff.Arches {
335        arch := &ff.Arches[i]
336        ftArch := &fileTests[i]
337
338        if arch.Cpu != ftArch.hdr.Cpu || arch.SubCpu != ftArch.hdr.SubCpu {
339            t.Errorf("OpenFat: architecture #%d got cpu=%#x subtype=%#x, expected cpu=%#x, subtype=%#x"iarch.Cpuarch.SubCpuftArch.hdr.CpuftArch.hdr.SubCpu)
340        }
341
342        if !reflect.DeepEqual(arch.FileHeaderftArch.hdr) {
343            t.Errorf("OpenFat header:\n\tgot %#v\n\twant %#v\n"arch.FileHeaderftArch.hdr)
344        }
345    }
346}
347
348func TestOpenFatFailure(t *testing.T) {
349    filename := "file.go" // not a Mach-O file
350    if _err := OpenFat(filename); err == nil {
351        t.Errorf("OpenFat %s: succeeded unexpectedly"filename)
352    }
353
354    filename = "testdata/gcc-386-darwin-exec" // not a fat Mach-O
355    fferr := OpenFat(filename)
356    if err == nil {
357        t.Errorf("OpenFat %s: expected error, got nil"filename)
358    }
359    if _ok := err.(*FormatError); !ok {
360        t.Errorf("OpenFat %s: expected FormatError, got %v"filenameerr)
361    }
362
363    ferr := err.(*FormatError)
364    if !strings.Contains(ferr.String(), "not a fat") {
365        t.Errorf("OpenFat %s: expected error containing 'not a fat', got %s"filenameferr.String())
366    }
367
368    if ff != nil {
369        t.Errorf("OpenFat %s: got %v, want nil"filenameff)
370    }
371}
372
373func TestRelocTypeString(t *testing.T) {
374    if X86_64_RELOC_BRANCH.String() != "X86_64_RELOC_BRANCH" {
375        t.Errorf("got %v, want %v"X86_64_RELOC_BRANCH.String(), "X86_64_RELOC_BRANCH")
376    }
377    if X86_64_RELOC_BRANCH.GoString() != "macho.X86_64_RELOC_BRANCH" {
378        t.Errorf("got %v, want %v"X86_64_RELOC_BRANCH.GoString(), "macho.X86_64_RELOC_BRANCH")
379    }
380}
381
382func TestTypeString(t *testing.T) {
383    if MhExecute.String() != "Exec" {
384        t.Errorf("got %v, want %v"MhExecute.String(), "Exec")
385    }
386    if MhExecute.GoString() != "macho.Exec" {
387        t.Errorf("got %v, want %v"MhExecute.GoString(), "macho.Exec")
388    }
389}
390
MembersX
TestTypeString.t
fileTest
fileTest.loads
TestOpenFailure.t
TestOpenFat.t
TestOpenFailure.err
TestOpenFat.RangeStmt_10442.i
TestOpenFatFailure._
TestOpenFatFailure.ff
fileTest.hdr
TestOpen.RangeStmt_7604.BlockStmt.BlockStmt.RangeStmt_9180.i
TestOpen.RangeStmt_7604.BlockStmt.BlockStmt.RangeStmt_9636.BlockStmt.have
TestOpenFailure.filename
TestOpen.t
TestOpen.RangeStmt_7604.i
fileTest.relocations
TestOpenFatFailure
TestOpenFatFailure.filename
TestRelocTypeString
TestOpen.RangeStmt_7604.BlockStmt.BlockStmt.RangeStmt_9180.sh
TestOpenFat.err
testing
TestOpen.RangeStmt_7604.BlockStmt.err
TestOpen.RangeStmt_7604.BlockStmt.BlockStmt.RangeStmt_8076.l
TestOpen.RangeStmt_7604.BlockStmt.BlockStmt.tn
TestOpenFatFailure.t
reflect
fileTest.file
fileTest.sections
TestOpenFailure._
TestOpenFat.ff
TestRelocTypeString.t
TestOpen.RangeStmt_7604.BlockStmt.f
TestOpen.RangeStmt_7604.BlockStmt.BlockStmt.RangeStmt_8076.i
TestOpen.RangeStmt_7604.BlockStmt.BlockStmt.RangeStmt_9636.sh
TestOpenFat
TestOpenFatFailure.err
TestTypeString
TestOpen
TestOpen.RangeStmt_7604.BlockStmt.BlockStmt.fn
TestOpen.RangeStmt_7604.BlockStmt.BlockStmt.RangeStmt_9636.i
TestOpenFailure
Members
X