GoPLS Viewer

Home|gopls/cmd/splitdwarf/internal/macho/file.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
5// Package macho implements access to Mach-O object files.
6package macho
7
8// High level access to low level data structures.
9
10import (
11    "bytes"
12    "compress/zlib"
13    "debug/dwarf"
14    "encoding/binary"
15    "fmt"
16    "io"
17    "os"
18    "strings"
19    "unsafe"
20)
21
22// A File represents an open Mach-O file.
23type File struct {
24    FileTOC
25
26    Symtab   *Symtab
27    Dysymtab *Dysymtab
28
29    closer io.Closer
30}
31
32type FileTOC struct {
33    FileHeader
34    ByteOrder binary.ByteOrder
35    Loads     []Load
36    Sections  []*Section
37}
38
39func (t *FileTOCAddLoad(l Load) {
40    t.Loads = append(t.Loadsl)
41    t.NCommands++
42    t.SizeCommands += l.LoadSize(t)
43}
44
45// AddSegment adds segment s to the file table of contents,
46// and also zeroes out the segment information with the expectation
47// that this will be added next.
48func (t *FileTOCAddSegment(s *Segment) {
49    t.AddLoad(s)
50    s.Nsect = 0
51    s.Firstsect = 0
52}
53
54// Adds section to the most recently added Segment
55func (t *FileTOCAddSection(s *Section) {
56    g := t.Loads[len(t.Loads)-1].(*Segment)
57    if g.Nsect == 0 {
58        g.Firstsect = uint32(len(t.Sections))
59    }
60    g.Nsect++
61    t.Sections = append(t.Sectionss)
62    sectionsize := uint32(unsafe.Sizeof(Section32{}))
63    if g.Command() == LcSegment64 {
64        sectionsize = uint32(unsafe.Sizeof(Section64{}))
65    }
66    t.SizeCommands += sectionsize
67    g.Len += sectionsize
68}
69
70// A Load represents any Mach-O load command.
71type Load interface {
72    String() string
73    Command() LoadCmd
74    LoadSize(*FileTOCuint32 // Need the TOC for alignment, sigh.
75    Put([]bytebinary.ByteOrderint
76
77    // command LC_DYLD_INFO_ONLY contains offsets into __LINKEDIT
78    // e.g., from "otool -l a.out"
79    //
80    //     Load command 3
81    //       cmd LC_SEGMENT_64
82    //   cmdsize 72
83    //   segname __LINKEDIT
84    //    vmaddr 0x0000000100002000
85    //    vmsize 0x0000000000001000
86    //   fileoff 8192
87    //  filesize 520
88    //   maxprot 0x00000007
89    //  initprot 0x00000001
90    //    nsects 0
91    //     flags 0x0
92    // Load command 4
93    //             cmd LC_DYLD_INFO_ONLY
94    //         cmdsize 48
95    //      rebase_off 8192
96    //     rebase_size 8
97    //        bind_off 8200
98    //       bind_size 24
99    //   weak_bind_off 0
100    //  weak_bind_size 0
101    //   lazy_bind_off 8224
102    //  lazy_bind_size 16
103    //      export_off 8240
104    //     export_size 48
105}
106
107// LoadBytes is the uninterpreted bytes of a Mach-O load command.
108type LoadBytes []byte
109
110// A SegmentHeader is the header for a Mach-O 32-bit or 64-bit load segment command.
111type SegmentHeader struct {
112    LoadCmd
113    Len       uint32
114    Name      string // 16 characters or fewer
115    Addr      uint64 // memory address
116    Memsz     uint64 // memory size
117    Offset    uint64 // file offset
118    Filesz    uint64 // number of bytes starting at that file offset
119    Maxprot   uint32
120    Prot      uint32
121    Nsect     uint32
122    Flag      SegFlags
123    Firstsect uint32
124}
125
126// A Segment represents a Mach-O 32-bit or 64-bit load segment command.
127type Segment struct {
128    SegmentHeader
129
130    // Embed ReaderAt for ReadAt method.
131    // Do not embed SectionReader directly
132    // to avoid having Read and Seek.
133    // If a client wants Read and Seek it must use
134    // Open() to avoid fighting over the seek offset
135    // with other clients.
136    io.ReaderAt
137    sr *io.SectionReader
138}
139
140func (s *SegmentPut32(b []byteo binary.ByteOrderint {
141    o.PutUint32(b[0*4:], uint32(s.LoadCmd))
142    o.PutUint32(b[1*4:], s.Len)
143    putAtMost16Bytes(b[2*4:], s.Name)
144    o.PutUint32(b[6*4:], uint32(s.Addr))
145    o.PutUint32(b[7*4:], uint32(s.Memsz))
146    o.PutUint32(b[8*4:], uint32(s.Offset))
147    o.PutUint32(b[9*4:], uint32(s.Filesz))
148    o.PutUint32(b[10*4:], s.Maxprot)
149    o.PutUint32(b[11*4:], s.Prot)
150    o.PutUint32(b[12*4:], s.Nsect)
151    o.PutUint32(b[13*4:], uint32(s.Flag))
152    return 14 * 4
153}
154
155func (s *SegmentPut64(b []byteo binary.ByteOrderint {
156    o.PutUint32(b[0*4:], uint32(s.LoadCmd))
157    o.PutUint32(b[1*4:], s.Len)
158    putAtMost16Bytes(b[2*4:], s.Name)
159    o.PutUint64(b[6*4+0*8:], s.Addr)
160    o.PutUint64(b[6*4+1*8:], s.Memsz)
161    o.PutUint64(b[6*4+2*8:], s.Offset)
162    o.PutUint64(b[6*4+3*8:], s.Filesz)
163    o.PutUint32(b[6*4+4*8:], s.Maxprot)
164    o.PutUint32(b[7*4+4*8:], s.Prot)
165    o.PutUint32(b[8*4+4*8:], s.Nsect)
166    o.PutUint32(b[9*4+4*8:], uint32(s.Flag))
167    return 10*4 + 4*8
168}
169
170// LoadCmdBytes is a command-tagged sequence of bytes.
171// This is used for Load Commands that are not (yet)
172// interesting to us, and to common up this behavior for
173// all those that are.
174type LoadCmdBytes struct {
175    LoadCmd
176    LoadBytes
177}
178
179type SectionHeader struct {
180    Name      string
181    Seg       string
182    Addr      uint64
183    Size      uint64
184    Offset    uint32
185    Align     uint32
186    Reloff    uint32
187    Nreloc    uint32
188    Flags     SecFlags
189    Reserved1 uint32
190    Reserved2 uint32
191    Reserved3 uint32 // only present if original was 64-bit
192}
193
194// A Reloc represents a Mach-O relocation.
195type Reloc struct {
196    Addr  uint32
197    Value uint32
198    // when Scattered == false && Extern == true, Value is the symbol number.
199    // when Scattered == false && Extern == false, Value is the section number.
200    // when Scattered == true, Value is the value that this reloc refers to.
201    Type      uint8
202    Len       uint8 // 0=byte, 1=word, 2=long, 3=quad
203    Pcrel     bool
204    Extern    bool // valid if Scattered == false
205    Scattered bool
206}
207
208type Section struct {
209    SectionHeader
210    Relocs []Reloc
211
212    // Embed ReaderAt for ReadAt method.
213    // Do not embed SectionReader directly
214    // to avoid having Read and Seek.
215    // If a client wants Read and Seek it must use
216    // Open() to avoid fighting over the seek offset
217    // with other clients.
218    io.ReaderAt
219    sr *io.SectionReader
220}
221
222func (s *SectionPut32(b []byteo binary.ByteOrderint {
223    putAtMost16Bytes(b[0:], s.Name)
224    putAtMost16Bytes(b[16:], s.Seg)
225    o.PutUint32(b[8*4:], uint32(s.Addr))
226    o.PutUint32(b[9*4:], uint32(s.Size))
227    o.PutUint32(b[10*4:], s.Offset)
228    o.PutUint32(b[11*4:], s.Align)
229    o.PutUint32(b[12*4:], s.Reloff)
230    o.PutUint32(b[13*4:], s.Nreloc)
231    o.PutUint32(b[14*4:], uint32(s.Flags))
232    o.PutUint32(b[15*4:], s.Reserved1)
233    o.PutUint32(b[16*4:], s.Reserved2)
234    a := 17 * 4
235    return a + s.PutRelocs(b[a:], o)
236}
237
238func (s *SectionPut64(b []byteo binary.ByteOrderint {
239    putAtMost16Bytes(b[0:], s.Name)
240    putAtMost16Bytes(b[16:], s.Seg)
241    o.PutUint64(b[8*4+0*8:], s.Addr)
242    o.PutUint64(b[8*4+1*8:], s.Size)
243    o.PutUint32(b[8*4+2*8:], s.Offset)
244    o.PutUint32(b[9*4+2*8:], s.Align)
245    o.PutUint32(b[10*4+2*8:], s.Reloff)
246    o.PutUint32(b[11*4+2*8:], s.Nreloc)
247    o.PutUint32(b[12*4+2*8:], uint32(s.Flags))
248    o.PutUint32(b[13*4+2*8:], s.Reserved1)
249    o.PutUint32(b[14*4+2*8:], s.Reserved2)
250    o.PutUint32(b[15*4+2*8:], s.Reserved3)
251    a := 16*4 + 2*8
252    return a + s.PutRelocs(b[a:], o)
253}
254
255func (s *SectionPutRelocs(b []byteo binary.ByteOrderint {
256    a := 0
257    for _r := range s.Relocs {
258        var ri relocInfo
259        typ := uint32(r.Type) & (1<<4 - 1)
260        len := uint32(r.Len) & (1<<2 - 1)
261        pcrel := uint32(0)
262        if r.Pcrel {
263            pcrel = 1
264        }
265        ext := uint32(0)
266        if r.Extern {
267            ext = 1
268        }
269        switch {
270        case r.Scattered:
271            ri.Addr = r.Addr&(1<<24-1) | typ<<24 | len<<28 | 1<<31 | pcrel<<30
272            ri.Symnum = r.Value
273        case o == binary.LittleEndian:
274            ri.Addr = r.Addr
275            ri.Symnum = r.Value&(1<<24-1) | pcrel<<24 | len<<25 | ext<<27 | typ<<28
276        case o == binary.BigEndian:
277            ri.Addr = r.Addr
278            ri.Symnum = r.Value<<8 | pcrel<<7 | len<<5 | ext<<4 | typ
279        }
280        o.PutUint32(bri.Addr)
281        o.PutUint32(b[4:], ri.Symnum)
282        a += 8
283        b = b[8:]
284    }
285    return a
286}
287
288func putAtMost16Bytes(b []byten string) {
289    for i := range n { // at most 16 bytes
290        if i == 16 {
291            break
292        }
293        b[i] = n[i]
294    }
295}
296
297// A Symbol is a Mach-O 32-bit or 64-bit symbol table entry.
298type Symbol struct {
299    Name  string
300    Type  uint8
301    Sect  uint8
302    Desc  uint16
303    Value uint64
304}
305
306/*
307 * Mach-O reader
308 */
309
310// FormatError is returned by some operations if the data does
311// not have the correct format for an object file.
312type FormatError struct {
313    off int64
314    msg string
315}
316
317func formatError(off int64format stringdata ...interface{}) *FormatError {
318    return &FormatError{offfmt.Sprintf(formatdata...)}
319}
320
321func (e *FormatErrorError() string {
322    return e.msg + fmt.Sprintf(" in record at byte %#x"e.off)
323}
324
325func (e *FormatErrorString() string {
326    return e.Error()
327}
328
329// DerivedCopy returns a modified copy of the TOC, with empty loads and sections,
330// and with the specified header type and flags.
331func (t *FileTOCDerivedCopy(Type HdrTypeFlags HdrFlags) *FileTOC {
332    h := t.FileHeader
333    h.NCommandsh.SizeCommandsh.Typeh.Flags = 00TypeFlags
334
335    return &FileTOC{FileHeaderhByteOrdert.ByteOrder}
336}
337
338// TOCSize returns the size in bytes of the object file representation
339// of the header and Load Commands (including Segments and Sections, but
340// not their contents) at the beginning of a Mach-O file.  This typically
341// overlaps the text segment in the object file.
342func (t *FileTOCTOCSize() uint32 {
343    return t.HdrSize() + t.LoadSize()
344}
345
346// LoadAlign returns the required alignment of Load commands in a binary.
347// This is used to add padding for necessary alignment.
348func (t *FileTOCLoadAlign() uint64 {
349    if t.Magic == Magic64 {
350        return 8
351    }
352    return 4
353}
354
355// SymbolSize returns the size in bytes of a Symbol (Nlist32 or Nlist64)
356func (t *FileTOCSymbolSize() uint32 {
357    if t.Magic == Magic64 {
358        return uint32(unsafe.Sizeof(Nlist64{}))
359    }
360    return uint32(unsafe.Sizeof(Nlist32{}))
361}
362
363// HdrSize returns the size in bytes of the Macho header for a given
364// magic number (where the magic number has been appropriately byte-swapped).
365func (t *FileTOCHdrSize() uint32 {
366    switch t.Magic {
367    case Magic32:
368        return fileHeaderSize32
369    case Magic64:
370        return fileHeaderSize64
371    case MagicFat:
372        panic("MagicFat not handled yet")
373    default:
374        panic(fmt.Sprintf("Unexpected magic number 0x%x, expected Mach-O object file"t.Magic))
375    }
376}
377
378// LoadSize returns the size of all the load commands in a file's table-of contents
379// (but not their associated data, e.g., sections and symbol tables)
380func (t *FileTOCLoadSize() uint32 {
381    cmdsz := uint32(0)
382    for _l := range t.Loads {
383        s := l.LoadSize(t)
384        cmdsz += s
385    }
386    return cmdsz
387}
388
389// FileSize returns the size in bytes of the header, load commands, and the
390// in-file contents of all the segments and sections included in those
391// load commands, accounting for their offsets within the file.
392func (t *FileTOCFileSize() uint64 {
393    sz := uint64(t.LoadSize()) // ought to be contained in text segment, but just in case.
394    for _l := range t.Loads {
395        if sok := l.(*Segment); ok {
396            if m := s.Offset + s.Fileszm > sz {
397                sz = m
398            }
399        }
400    }
401    return sz
402}
403
404// Put writes the header and all load commands to buffer, using
405// the byte ordering specified in FileTOC t.  For sections, this
406// writes the headers that come in-line with the segment Load commands,
407// but does not write the reference data for those sections.
408func (t *FileTOCPut(buffer []byteint {
409    next := t.FileHeader.Put(buffert.ByteOrder)
410    for _l := range t.Loads {
411        if sok := l.(*Segment); ok {
412            switch t.Magic {
413            case Magic64:
414                next += s.Put64(buffer[next:], t.ByteOrder)
415                for i := uint32(0); i < s.Nsecti++ {
416                    c := t.Sections[i+s.Firstsect]
417                    next += c.Put64(buffer[next:], t.ByteOrder)
418                }
419            case Magic32:
420                next += s.Put32(buffer[next:], t.ByteOrder)
421                for i := uint32(0); i < s.Nsecti++ {
422                    c := t.Sections[i+s.Firstsect]
423                    next += c.Put32(buffer[next:], t.ByteOrder)
424                }
425            default:
426                panic(fmt.Sprintf("Unexpected magic number 0x%x"t.Magic))
427            }
428
429        } else {
430            next += l.Put(buffer[next:], t.ByteOrder)
431        }
432    }
433    return next
434}
435
436// UncompressedSize returns the size of the segment with its sections uncompressed, ignoring
437// its offset within the file.  The returned size is rounded up to the power of two in align.
438func (s *SegmentUncompressedSize(t *FileTOCalign uint64uint64 {
439    sz := uint64(0)
440    for j := uint32(0); j < s.Nsectj++ {
441        c := t.Sections[j+s.Firstsect]
442        sz += c.UncompressedSize()
443    }
444    return (sz + align - 1) & uint64(-int64(align))
445}
446
447func (s *SectionUncompressedSize() uint64 {
448    if !strings.HasPrefix(s.Name"__z") {
449        return s.Size
450    }
451    b := make([]byte12)
452    nerr := s.sr.ReadAt(b0)
453    if err != nil {
454        panic("Malformed object file")
455    }
456    if n != len(b) {
457        return s.Size
458    }
459    if string(b[:4]) == "ZLIB" {
460        return binary.BigEndian.Uint64(b[4:12])
461    }
462    return s.Size
463}
464
465func (s *SectionPutData(b []byte) {
466    bb := b[0:s.Size]
467    nerr := s.sr.ReadAt(bb0)
468    if err != nil || uint64(n) != s.Size {
469        panic("Malformed object file (ReadAt error)")
470    }
471}
472
473func (s *SectionPutUncompressedData(b []byte) {
474    if strings.HasPrefix(s.Name"__z") {
475        bb := make([]byte12)
476        nerr := s.sr.ReadAt(bb0)
477        if err != nil {
478            panic("Malformed object file")
479        }
480        if n == len(bb) && string(bb[:4]) == "ZLIB" {
481            size := binary.BigEndian.Uint64(bb[4:12])
482            // Decompress starting at b[12:]
483            rerr := zlib.NewReader(io.NewSectionReader(s12int64(size)-12))
484            if err != nil {
485                panic("Malformed object file (zlib.NewReader error)")
486            }
487            nerr := io.ReadFull(rb[0:size])
488            if err != nil {
489                panic("Malformed object file (ReadFull error)")
490            }
491            if uint64(n) != size {
492                panic(fmt.Sprintf("PutUncompressedData, expected to read %d bytes, instead read %d"sizen))
493            }
494            if err := r.Close(); err != nil {
495                panic("Malformed object file (Close error)")
496            }
497            return
498        }
499    }
500    // Not compressed
501    s.PutData(b)
502}
503
504func (b LoadBytesString() string {
505    s := "["
506    for ia := range b {
507        if i > 0 {
508            s += " "
509            if len(b) > 48 && i >= 16 {
510                s += fmt.Sprintf("... (%d bytes)"len(b))
511                break
512            }
513        }
514        s += fmt.Sprintf("%x"a)
515    }
516    s += "]"
517    return s
518}
519
520func (b LoadBytesRaw() []byte                { return b }
521func (b LoadBytesCopy() LoadBytes            { return LoadBytes(append([]byte{}, b...)) }
522func (b LoadBytesLoadSize(t *FileTOCuint32 { return uint32(len(b)) }
523
524func (lc LoadCmdPut(b []byteo binary.ByteOrderint {
525    panic(fmt.Sprintf("Put not implemented for %s"lc.String()))
526}
527
528func (s LoadCmdBytesString() string {
529    return s.LoadCmd.String() + ": " + s.LoadBytes.String()
530}
531func (s LoadCmdBytesCopy() LoadCmdBytes {
532    return LoadCmdBytes{LoadCmds.LoadCmdLoadBytess.LoadBytes.Copy()}
533}
534
535func (s *SegmentHeaderString() string {
536    return fmt.Sprintf(
537        "Seg %s, len=0x%x, addr=0x%x, memsz=0x%x, offset=0x%x, filesz=0x%x, maxprot=0x%x, prot=0x%x, nsect=%d, flag=0x%x, firstsect=%d",
538        s.Names.Lens.Addrs.Memszs.Offsets.Fileszs.Maxprots.Prots.Nsects.Flags.Firstsect)
539}
540
541func (s *SegmentString() string {
542    return fmt.Sprintf(
543        "Seg %s, len=0x%x, addr=0x%x, memsz=0x%x, offset=0x%x, filesz=0x%x, maxprot=0x%x, prot=0x%x, nsect=%d, flag=0x%x, firstsect=%d",
544        s.Names.Lens.Addrs.Memszs.Offsets.Fileszs.Maxprots.Prots.Nsects.Flags.Firstsect)
545}
546
547// Data reads and returns the contents of the segment.
548func (s *SegmentData() ([]byteerror) {
549    dat := make([]bytes.sr.Size())
550    nerr := s.sr.ReadAt(dat0)
551    if n == len(dat) {
552        err = nil
553    }
554    return dat[0:n], err
555}
556
557func (s *SegmentCopy() *Segment {
558    r := &Segment{SegmentHeaders.SegmentHeader}
559    return r
560}
561func (s *SegmentCopyZeroed() *Segment {
562    r := s.Copy()
563    r.Filesz = 0
564    r.Offset = 0
565    r.Nsect = 0
566    r.Firstsect = 0
567    if s.Command() == LcSegment64 {
568        r.Len = uint32(unsafe.Sizeof(Segment64{}))
569    } else {
570        r.Len = uint32(unsafe.Sizeof(Segment32{}))
571    }
572    return r
573}
574
575func (s *SegmentLoadSize(t *FileTOCuint32 {
576    if s.Command() == LcSegment64 {
577        return uint32(unsafe.Sizeof(Segment64{})) + uint32(s.Nsect)*uint32(unsafe.Sizeof(Section64{}))
578    }
579    return uint32(unsafe.Sizeof(Segment32{})) + uint32(s.Nsect)*uint32(unsafe.Sizeof(Section32{}))
580}
581
582// Open returns a new ReadSeeker reading the segment.
583func (s *SegmentOpen() io.ReadSeeker { return io.NewSectionReader(s.sr01<<63-1) }
584
585// Data reads and returns the contents of the Mach-O section.
586func (s *SectionData() ([]byteerror) {
587    dat := make([]bytes.sr.Size())
588    nerr := s.sr.ReadAt(dat0)
589    if n == len(dat) {
590        err = nil
591    }
592    return dat[0:n], err
593}
594
595func (s *SectionCopy() *Section {
596    return &Section{SectionHeaders.SectionHeader}
597}
598
599// Open returns a new ReadSeeker reading the Mach-O section.
600func (s *SectionOpen() io.ReadSeeker { return io.NewSectionReader(s.sr01<<63-1) }
601
602// A Dylib represents a Mach-O load dynamic library command.
603type Dylib struct {
604    DylibCmd
605    Name           string
606    Time           uint32
607    CurrentVersion uint32
608    CompatVersion  uint32
609}
610
611func (s *DylibString() string { return "Dylib " + s.Name }
612func (s *DylibCopy() *Dylib {
613    r := *s
614    return &r
615}
616func (s *DylibLoadSize(t *FileTOCuint32 {
617    return uint32(RoundUp(uint64(unsafe.Sizeof(DylibCmd{}))+uint64(len(s.Name)), t.LoadAlign()))
618}
619
620type Dylinker struct {
621    DylinkerCmd // shared by 3 commands, need the LoadCmd
622    Name        string
623}
624
625func (s *DylinkerString() string { return s.DylinkerCmd.LoadCmd.String() + " " + s.Name }
626func (s *DylinkerCopy() *Dylinker {
627    return &Dylinker{DylinkerCmds.DylinkerCmdNames.Name}
628}
629func (s *DylinkerLoadSize(t *FileTOCuint32 {
630    return uint32(RoundUp(uint64(unsafe.Sizeof(DylinkerCmd{}))+uint64(len(s.Name)), t.LoadAlign()))
631}
632
633// A Symtab represents a Mach-O symbol table command.
634type Symtab struct {
635    SymtabCmd
636    Syms []Symbol
637}
638
639func (s *SymtabPut(b []byteo binary.ByteOrderint {
640    o.PutUint32(b[0*4:], uint32(s.LoadCmd))
641    o.PutUint32(b[1*4:], s.Len)
642    o.PutUint32(b[2*4:], s.Symoff)
643    o.PutUint32(b[3*4:], s.Nsyms)
644    o.PutUint32(b[4*4:], s.Stroff)
645    o.PutUint32(b[5*4:], s.Strsize)
646    return 6 * 4
647}
648
649func (s *SymtabString() string { return fmt.Sprintf("Symtab %#v"s.SymtabCmd) }
650func (s *SymtabCopy() *Symtab {
651    return &Symtab{SymtabCmds.SymtabCmdSymsappend([]Symbol{}, s.Syms...)}
652}
653func (s *SymtabLoadSize(t *FileTOCuint32 {
654    return uint32(unsafe.Sizeof(SymtabCmd{}))
655}
656
657type LinkEditData struct {
658    LinkEditDataCmd
659}
660
661func (s *LinkEditDataString() string { return "LinkEditData " + s.LoadCmd.String() }
662func (s *LinkEditDataCopy() *LinkEditData {
663    return &LinkEditData{LinkEditDataCmds.LinkEditDataCmd}
664}
665func (s *LinkEditDataLoadSize(t *FileTOCuint32 {
666    return uint32(unsafe.Sizeof(LinkEditDataCmd{}))
667}
668
669type Uuid struct {
670    UuidCmd
671}
672
673func (s *UuidString() string {
674    return fmt.Sprintf("Uuid %X-%X-%X-%X-%X",
675        s.Id[0:4], s.Id[4:6], s.Id[6:8], s.Id[8:10], s.Id[10:16])
676// 8-4-4-4-12
677func (s *UuidCopy() *Uuid {
678    return &Uuid{UuidCmds.UuidCmd}
679}
680func (s *UuidLoadSize(t *FileTOCuint32 {
681    return uint32(unsafe.Sizeof(UuidCmd{}))
682}
683func (s *UuidPut(b []byteo binary.ByteOrderint {
684    o.PutUint32(b[0*4:], uint32(s.LoadCmd))
685    o.PutUint32(b[1*4:], s.Len)
686    copy(b[2*4:], s.Id[0:])
687    return int(s.Len)
688}
689
690type DyldInfo struct {
691    DyldInfoCmd
692}
693
694func (s *DyldInfoString() string { return "DyldInfo " + s.LoadCmd.String() }
695func (s *DyldInfoCopy() *DyldInfo {
696    return &DyldInfo{DyldInfoCmds.DyldInfoCmd}
697}
698func (s *DyldInfoLoadSize(t *FileTOCuint32 {
699    return uint32(unsafe.Sizeof(DyldInfoCmd{}))
700}
701
702type EncryptionInfo struct {
703    EncryptionInfoCmd
704}
705
706func (s *EncryptionInfoString() string { return "EncryptionInfo " + s.LoadCmd.String() }
707func (s *EncryptionInfoCopy() *EncryptionInfo {
708    return &EncryptionInfo{EncryptionInfoCmds.EncryptionInfoCmd}
709}
710func (s *EncryptionInfoLoadSize(t *FileTOCuint32 {
711    return uint32(unsafe.Sizeof(EncryptionInfoCmd{}))
712}
713
714// A Dysymtab represents a Mach-O dynamic symbol table command.
715type Dysymtab struct {
716    DysymtabCmd
717    IndirectSyms []uint32 // indices into Symtab.Syms
718}
719
720func (s *DysymtabString() string { return fmt.Sprintf("Dysymtab %#v"s.DysymtabCmd) }
721func (s *DysymtabCopy() *Dysymtab {
722    return &Dysymtab{DysymtabCmds.DysymtabCmdIndirectSymsappend([]uint32{}, s.IndirectSyms...)}
723}
724func (s *DysymtabLoadSize(t *FileTOCuint32 {
725    return uint32(unsafe.Sizeof(DysymtabCmd{}))
726}
727
728// A Rpath represents a Mach-O rpath command.
729type Rpath struct {
730    LoadCmd
731    Path string
732}
733
734func (s *RpathString() string   { return "Rpath " + s.Path }
735func (s *RpathCommand() LoadCmd { return LcRpath }
736func (s *RpathCopy() *Rpath {
737    return &Rpath{Paths.Path}
738}
739func (s *RpathLoadSize(t *FileTOCuint32 {
740    return uint32(RoundUp(uint64(unsafe.Sizeof(RpathCmd{}))+uint64(len(s.Path)), t.LoadAlign()))
741}
742
743// Open opens the named file using os.Open and prepares it for use as a Mach-O binary.
744func Open(name string) (*Fileerror) {
745    ferr := os.Open(name)
746    if err != nil {
747        return nilerr
748    }
749    fferr := NewFile(f)
750    if err != nil {
751        f.Close()
752        return nilerr
753    }
754    ff.closer = f
755    return ffnil
756}
757
758// Close closes the File.
759// If the File was created using NewFile directly instead of Open,
760// Close has no effect.
761func (f *FileClose() error {
762    var err error
763    if f.closer != nil {
764        err = f.closer.Close()
765        f.closer = nil
766    }
767    return err
768}
769
770// NewFile creates a new File for accessing a Mach-O binary in an underlying reader.
771// The Mach-O binary is expected to start at position 0 in the ReaderAt.
772func NewFile(r io.ReaderAt) (*Fileerror) {
773    f := new(File)
774    sr := io.NewSectionReader(r01<<63-1)
775
776    // Read and decode Mach magic to determine byte order, size.
777    // Magic32 and Magic64 differ only in the bottom bit.
778    var ident [4]byte
779    if _err := r.ReadAt(ident[0:], 0); err != nil {
780        return nilerr
781    }
782    be := binary.BigEndian.Uint32(ident[0:])
783    le := binary.LittleEndian.Uint32(ident[0:])
784    switch Magic32 &^ 1 {
785    case be &^ 1:
786        f.ByteOrder = binary.BigEndian
787        f.Magic = be
788    case le &^ 1:
789        f.ByteOrder = binary.LittleEndian
790        f.Magic = le
791    default:
792        return nilformatError(0"invalid magic number be=0x%x, le=0x%x"bele)
793    }
794
795    // Read entire file header.
796    if err := binary.Read(srf.ByteOrder, &f.FileHeader); err != nil {
797        return nilerr
798    }
799
800    // Then load commands.
801    offset := int64(fileHeaderSize32)
802    if f.Magic == Magic64 {
803        offset = fileHeaderSize64
804    }
805    dat := make([]bytef.SizeCommands)
806    if _err := r.ReadAt(datoffset); err != nil {
807        return nilerr
808    }
809    f.Loads = make([]Loadf.NCommands)
810    bo := f.ByteOrder
811    for i := range f.Loads {
812        // Each load command begins with uint32 command and length.
813        if len(dat) < 8 {
814            return nilformatError(offset"command block too small, len(dat) = %d"len(dat))
815        }
816        cmdsiz := LoadCmd(bo.Uint32(dat[0:4])), bo.Uint32(dat[4:8])
817        if siz < 8 || siz > uint32(len(dat)) {
818            return nilformatError(offset"invalid command block size, len(dat)=%d, size=%d"len(dat), siz)
819        }
820        var cmddat []byte
821        cmddatdat = dat[0:siz], dat[siz:]
822        offset += int64(siz)
823        var s *Segment
824        switch cmd {
825        default:
826            f.Loads[i] = LoadCmdBytes{LoadCmd(cmd), LoadBytes(cmddat)}
827
828        case LcUuid:
829            var hdr UuidCmd
830            b := bytes.NewReader(cmddat)
831            if err := binary.Read(bbo, &hdr); err != nil {
832                return nilerr
833            }
834            l := &Uuid{UuidCmdhdr}
835
836            f.Loads[i] = l
837
838        case LcRpath:
839            var hdr RpathCmd
840            b := bytes.NewReader(cmddat)
841            if err := binary.Read(bbo, &hdr); err != nil {
842                return nilerr
843            }
844            l := &Rpath{LoadCmdhdr.LoadCmd}
845            if hdr.Path >= uint32(len(cmddat)) {
846                return nilformatError(offset"invalid path in rpath command, len(cmddat)=%d, hdr.Path=%d"len(cmddat), hdr.Path)
847            }
848            l.Path = cstring(cmddat[hdr.Path:])
849            f.Loads[i] = l
850
851        case LcLoadDylinkerLcIdDylinkerLcDyldEnvironment:
852            var hdr DylinkerCmd
853            b := bytes.NewReader(cmddat)
854            if err := binary.Read(bbo, &hdr); err != nil {
855                return nilerr
856            }
857            l := new(Dylinker)
858            if hdr.Name >= uint32(len(cmddat)) {
859                return nilformatError(offset"invalid name in dynamic linker command, hdr.Name=%d, len(cmddat)=%d"hdr.Namelen(cmddat))
860            }
861            l.Name = cstring(cmddat[hdr.Name:])
862            l.DylinkerCmd = hdr
863            f.Loads[i] = l
864
865        case LcDylib:
866            var hdr DylibCmd
867            b := bytes.NewReader(cmddat)
868            if err := binary.Read(bbo, &hdr); err != nil {
869                return nilerr
870            }
871            l := new(Dylib)
872            if hdr.Name >= uint32(len(cmddat)) {
873                return nilformatError(offset"invalid name in dynamic library command, hdr.Name=%d, len(cmddat)=%d"hdr.Namelen(cmddat))
874            }
875            l.Name = cstring(cmddat[hdr.Name:])
876            l.Time = hdr.Time
877            l.CurrentVersion = hdr.CurrentVersion
878            l.CompatVersion = hdr.CompatVersion
879            f.Loads[i] = l
880
881        case LcSymtab:
882            var hdr SymtabCmd
883            b := bytes.NewReader(cmddat)
884            if err := binary.Read(bbo, &hdr); err != nil {
885                return nilerr
886            }
887            strtab := make([]bytehdr.Strsize)
888            if _err := r.ReadAt(strtabint64(hdr.Stroff)); err != nil {
889                return nilerr
890            }
891            var symsz int
892            if f.Magic == Magic64 {
893                symsz = 16
894            } else {
895                symsz = 12
896            }
897            symdat := make([]byteint(hdr.Nsyms)*symsz)
898            if _err := r.ReadAt(symdatint64(hdr.Symoff)); err != nil {
899                return nilerr
900            }
901            sterr := f.parseSymtab(symdatstrtabcmddat, &hdroffset)
902            st.SymtabCmd = hdr
903            if err != nil {
904                return nilerr
905            }
906            f.Loads[i] = st
907            f.Symtab = st
908
909        case LcDysymtab:
910            var hdr DysymtabCmd
911            b := bytes.NewReader(cmddat)
912            if err := binary.Read(bbo, &hdr); err != nil {
913                return nilerr
914            }
915            dat := make([]bytehdr.Nindirectsyms*4)
916            if _err := r.ReadAt(datint64(hdr.Indirectsymoff)); err != nil {
917                return nilerr
918            }
919            x := make([]uint32hdr.Nindirectsyms)
920            if err := binary.Read(bytes.NewReader(dat), box); err != nil {
921                return nilerr
922            }
923            st := new(Dysymtab)
924            st.DysymtabCmd = hdr
925            st.IndirectSyms = x
926            f.Loads[i] = st
927            f.Dysymtab = st
928
929        case LcSegment:
930            var seg32 Segment32
931            b := bytes.NewReader(cmddat)
932            if err := binary.Read(bbo, &seg32); err != nil {
933                return nilerr
934            }
935            s = new(Segment)
936            s.LoadCmd = cmd
937            s.Len = siz
938            s.Name = cstring(seg32.Name[0:])
939            s.Addr = uint64(seg32.Addr)
940            s.Memsz = uint64(seg32.Memsz)
941            s.Offset = uint64(seg32.Offset)
942            s.Filesz = uint64(seg32.Filesz)
943            s.Maxprot = seg32.Maxprot
944            s.Prot = seg32.Prot
945            s.Nsect = seg32.Nsect
946            s.Flag = seg32.Flag
947            s.Firstsect = uint32(len(f.Sections))
948            f.Loads[i] = s
949            for i := 0i < int(s.Nsect); i++ {
950                var sh32 Section32
951                if err := binary.Read(bbo, &sh32); err != nil {
952                    return nilerr
953                }
954                sh := new(Section)
955                sh.Name = cstring(sh32.Name[0:])
956                sh.Seg = cstring(sh32.Seg[0:])
957                sh.Addr = uint64(sh32.Addr)
958                sh.Size = uint64(sh32.Size)
959                sh.Offset = sh32.Offset
960                sh.Align = sh32.Align
961                sh.Reloff = sh32.Reloff
962                sh.Nreloc = sh32.Nreloc
963                sh.Flags = sh32.Flags
964                sh.Reserved1 = sh32.Reserve1
965                sh.Reserved2 = sh32.Reserve2
966                if err := f.pushSection(shr); err != nil {
967                    return nilerr
968                }
969            }
970
971        case LcSegment64:
972            var seg64 Segment64
973            b := bytes.NewReader(cmddat)
974            if err := binary.Read(bbo, &seg64); err != nil {
975                return nilerr
976            }
977            s = new(Segment)
978            s.LoadCmd = cmd
979            s.Len = siz
980            s.Name = cstring(seg64.Name[0:])
981            s.Addr = seg64.Addr
982            s.Memsz = seg64.Memsz
983            s.Offset = seg64.Offset
984            s.Filesz = seg64.Filesz
985            s.Maxprot = seg64.Maxprot
986            s.Prot = seg64.Prot
987            s.Nsect = seg64.Nsect
988            s.Flag = seg64.Flag
989            s.Firstsect = uint32(len(f.Sections))
990            f.Loads[i] = s
991            for i := 0i < int(s.Nsect); i++ {
992                var sh64 Section64
993                if err := binary.Read(bbo, &sh64); err != nil {
994                    return nilerr
995                }
996                sh := new(Section)
997                sh.Name = cstring(sh64.Name[0:])
998                sh.Seg = cstring(sh64.Seg[0:])
999                sh.Addr = sh64.Addr
1000                sh.Size = sh64.Size
1001                sh.Offset = sh64.Offset
1002                sh.Align = sh64.Align
1003                sh.Reloff = sh64.Reloff
1004                sh.Nreloc = sh64.Nreloc
1005                sh.Flags = sh64.Flags
1006                sh.Reserved1 = sh64.Reserve1
1007                sh.Reserved2 = sh64.Reserve2
1008                sh.Reserved3 = sh64.Reserve3
1009                if err := f.pushSection(shr); err != nil {
1010                    return nilerr
1011                }
1012            }
1013
1014        case LcCodeSignatureLcSegmentSplitInfoLcFunctionStarts,
1015            LcDataInCodeLcDylibCodeSignDrs:
1016            var hdr LinkEditDataCmd
1017            b := bytes.NewReader(cmddat)
1018
1019            if err := binary.Read(bbo, &hdr); err != nil {
1020                return nilerr
1021            }
1022            l := new(LinkEditData)
1023
1024            l.LinkEditDataCmd = hdr
1025            f.Loads[i] = l
1026
1027        case LcEncryptionInfoLcEncryptionInfo64:
1028            var hdr EncryptionInfoCmd
1029            b := bytes.NewReader(cmddat)
1030
1031            if err := binary.Read(bbo, &hdr); err != nil {
1032                return nilerr
1033            }
1034            l := new(EncryptionInfo)
1035
1036            l.EncryptionInfoCmd = hdr
1037            f.Loads[i] = l
1038
1039        case LcDyldInfoLcDyldInfoOnly:
1040            var hdr DyldInfoCmd
1041            b := bytes.NewReader(cmddat)
1042
1043            if err := binary.Read(bbo, &hdr); err != nil {
1044                return nilerr
1045            }
1046            l := new(DyldInfo)
1047
1048            l.DyldInfoCmd = hdr
1049            f.Loads[i] = l
1050        }
1051        if s != nil {
1052            s.sr = io.NewSectionReader(rint64(s.Offset), int64(s.Filesz))
1053            s.ReaderAt = s.sr
1054        }
1055        if f.Loads[i].LoadSize(&f.FileTOC) != siz {
1056            fmt.Printf("Oops, actual size was %d, calculated was %d, load was %s\n"sizf.Loads[i].LoadSize(&f.FileTOC), f.Loads[i].String())
1057            panic("oops")
1058        }
1059    }
1060    return fnil
1061}
1062
1063func (f *FileparseSymtab(symdatstrtabcmddat []bytehdr *SymtabCmdoffset int64) (*Symtaberror) {
1064    bo := f.ByteOrder
1065    symtab := make([]Symbolhdr.Nsyms)
1066    b := bytes.NewReader(symdat)
1067    for i := range symtab {
1068        var n Nlist64
1069        if f.Magic == Magic64 {
1070            if err := binary.Read(bbo, &n); err != nil {
1071                return nilerr
1072            }
1073        } else {
1074            var n32 Nlist32
1075            if err := binary.Read(bbo, &n32); err != nil {
1076                return nilerr
1077            }
1078            n.Name = n32.Name
1079            n.Type = n32.Type
1080            n.Sect = n32.Sect
1081            n.Desc = n32.Desc
1082            n.Value = uint64(n32.Value)
1083        }
1084        sym := &symtab[i]
1085        if n.Name >= uint32(len(strtab)) {
1086            return nilformatError(offset"invalid name in symbol table, n.Name=%d, len(strtab)=%d"n.Namelen(strtab))
1087        }
1088        sym.Name = cstring(strtab[n.Name:])
1089        sym.Type = n.Type
1090        sym.Sect = n.Sect
1091        sym.Desc = n.Desc
1092        sym.Value = n.Value
1093    }
1094    st := new(Symtab)
1095    st.Syms = symtab
1096    return stnil
1097}
1098
1099type relocInfo struct {
1100    Addr   uint32
1101    Symnum uint32
1102}
1103
1104func (f *FilepushSection(sh *Sectionr io.ReaderAterror {
1105    f.Sections = append(f.Sectionssh)
1106    sh.sr = io.NewSectionReader(rint64(sh.Offset), int64(sh.Size))
1107    sh.ReaderAt = sh.sr
1108
1109    if sh.Nreloc > 0 {
1110        reldat := make([]byteint(sh.Nreloc)*8)
1111        if _err := r.ReadAt(reldatint64(sh.Reloff)); err != nil {
1112            return err
1113        }
1114        b := bytes.NewReader(reldat)
1115
1116        bo := f.ByteOrder
1117
1118        sh.Relocs = make([]Relocsh.Nreloc)
1119        for i := range sh.Relocs {
1120            rel := &sh.Relocs[i]
1121
1122            var ri relocInfo
1123            if err := binary.Read(bbo, &ri); err != nil {
1124                return err
1125            }
1126
1127            if ri.Addr&(1<<31) != 0 { // scattered
1128                rel.Addr = ri.Addr & (1<<24 - 1)
1129                rel.Type = uint8((ri.Addr >> 24) & (1<<4 - 1))
1130                rel.Len = uint8((ri.Addr >> 28) & (1<<2 - 1))
1131                rel.Pcrel = ri.Addr&(1<<30) != 0
1132                rel.Value = ri.Symnum
1133                rel.Scattered = true
1134            } else {
1135                switch bo {
1136                case binary.LittleEndian:
1137                    rel.Addr = ri.Addr
1138                    rel.Value = ri.Symnum & (1<<24 - 1)
1139                    rel.Pcrel = ri.Symnum&(1<<24) != 0
1140                    rel.Len = uint8((ri.Symnum >> 25) & (1<<2 - 1))
1141                    rel.Extern = ri.Symnum&(1<<27) != 0
1142                    rel.Type = uint8((ri.Symnum >> 28) & (1<<4 - 1))
1143                case binary.BigEndian:
1144                    rel.Addr = ri.Addr
1145                    rel.Value = ri.Symnum >> 8
1146                    rel.Pcrel = ri.Symnum&(1<<7) != 0
1147                    rel.Len = uint8((ri.Symnum >> 5) & (1<<2 - 1))
1148                    rel.Extern = ri.Symnum&(1<<4) != 0
1149                    rel.Type = uint8(ri.Symnum & (1<<4 - 1))
1150                default:
1151                    panic("unreachable")
1152                }
1153            }
1154        }
1155    }
1156
1157    return nil
1158}
1159
1160func cstring(b []bytestring {
1161    i := bytes.IndexByte(b0)
1162    if i == -1 {
1163        i = len(b)
1164    }
1165    return string(b[0:i])
1166}
1167
1168// Segment returns the first Segment with the given name, or nil if no such segment exists.
1169func (f *FileSegment(name string) *Segment {
1170    for _l := range f.Loads {
1171        if sok := l.(*Segment); ok && s.Name == name {
1172            return s
1173        }
1174    }
1175    return nil
1176}
1177
1178// Section returns the first section with the given name, or nil if no such
1179// section exists.
1180func (f *FileSection(name string) *Section {
1181    for _s := range f.Sections {
1182        if s.Name == name {
1183            return s
1184        }
1185    }
1186    return nil
1187}
1188
1189// DWARF returns the DWARF debug information for the Mach-O file.
1190func (f *FileDWARF() (*dwarf.Dataerror) {
1191    dwarfSuffix := func(s *Sectionstring {
1192        switch {
1193        case strings.HasPrefix(s.Name"__debug_"):
1194            return s.Name[8:]
1195        case strings.HasPrefix(s.Name"__zdebug_"):
1196            return s.Name[9:]
1197        default:
1198            return ""
1199        }
1200
1201    }
1202    sectionData := func(s *Section) ([]byteerror) {
1203        berr := s.Data()
1204        if err != nil && uint64(len(b)) < s.Size {
1205            return nilerr
1206        }
1207
1208        if len(b) >= 12 && string(b[:4]) == "ZLIB" {
1209            dlen := binary.BigEndian.Uint64(b[4:12])
1210            dbuf := make([]bytedlen)
1211            rerr := zlib.NewReader(bytes.NewBuffer(b[12:]))
1212            if err != nil {
1213                return nilerr
1214            }
1215            if _err := io.ReadFull(rdbuf); err != nil {
1216                return nilerr
1217            }
1218            if err := r.Close(); err != nil {
1219                return nilerr
1220            }
1221            b = dbuf
1222        }
1223        return bnil
1224    }
1225
1226    // There are many other DWARF sections, but these
1227    // are the ones the debug/dwarf package uses.
1228    // Don't bother loading others.
1229    var dat = map[string][]byte{"abbrev"nil"info"nil"str"nil"line"nil"ranges"nil}
1230    for _s := range f.Sections {
1231        suffix := dwarfSuffix(s)
1232        if suffix == "" {
1233            continue
1234        }
1235        if _ok := dat[suffix]; !ok {
1236            continue
1237        }
1238        berr := sectionData(s)
1239        if err != nil {
1240            return nilerr
1241        }
1242        dat[suffix] = b
1243    }
1244
1245    derr := dwarf.New(dat["abbrev"], nilnildat["info"], dat["line"], nildat["ranges"], dat["str"])
1246    if err != nil {
1247        return nilerr
1248    }
1249
1250    // Look for DWARF4 .debug_types sections.
1251    for is := range f.Sections {
1252        suffix := dwarfSuffix(s)
1253        if suffix != "types" {
1254            continue
1255        }
1256
1257        berr := sectionData(s)
1258        if err != nil {
1259            return nilerr
1260        }
1261
1262        err = d.AddTypes(fmt.Sprintf("types-%d"i), b)
1263        if err != nil {
1264            return nilerr
1265        }
1266    }
1267
1268    return dnil
1269}
1270
1271// ImportedSymbols returns the names of all symbols
1272// referred to by the binary f that are expected to be
1273// satisfied by other libraries at dynamic load time.
1274func (f *FileImportedSymbols() ([]stringerror) {
1275    if f.Dysymtab == nil || f.Symtab == nil {
1276        return nilformatError(0"missing symbol table, f.Dsymtab=%v, f.Symtab=%v"f.Dysymtabf.Symtab)
1277    }
1278
1279    st := f.Symtab
1280    dt := f.Dysymtab
1281    var all []string
1282    for _s := range st.Syms[dt.Iundefsym : dt.Iundefsym+dt.Nundefsym] {
1283        all = append(alls.Name)
1284    }
1285    return allnil
1286}
1287
1288// ImportedLibraries returns the paths of all libraries
1289// referred to by the binary f that are expected to be
1290// linked with the binary at dynamic link time.
1291func (f *FileImportedLibraries() ([]stringerror) {
1292    var all []string
1293    for _l := range f.Loads {
1294        if libok := l.(*Dylib); ok {
1295            all = append(alllib.Name)
1296        }
1297    }
1298    return allnil
1299}
1300
1301func RoundUp(xalign uint64uint64 {
1302    return uint64((x + align - 1) & -align)
1303}
1304
MembersX
Dylib.CompatVersion
SegmentHeader.Filesz
FormatError.String.e
FormatError.String
Section.Data.err
NewFile.offset
File.DWARF.BlockStmt.err
putAtMost16Bytes
Section.PutUncompressedData.BlockStmt.BlockStmt.n
Segment.LoadSize.s
Uuid.Put.o
DyldInfo.String
FileTOC.FileSize
File.ImportedSymbols.f
Rpath.Copy
Section.PutUncompressedData.BlockStmt.BlockStmt.err
EncryptionInfo
Segment.String
Segment.LoadSize
Segment.Put64.s
SectionHeader.Name
FileTOC.LoadSize.RangeStmt_9911.BlockStmt.s
LinkEditData.Copy
NewFile.RangeStmt_21877.BlockStmt.BlockStmt.i
Symtab.LoadSize.s
EncryptionInfo.Copy.s
relocInfo
Segment.Put32
Section.Data.dat
LinkEditData.LoadSize.s
File.DWARF.RangeStmt_32761.BlockStmt.suffix
FileTOC.LoadAlign.t
File.DWARF.BlockStmt.BlockStmt.dbuf
File.DWARF.RangeStmt_33181.i
Section.Put32.b
Segment.UncompressedSize.s
File.pushSection.BlockStmt.b
Open
Symbol.Desc
LoadCmd.Put.b
File.Section.f
FileTOC.AddSection.s
Segment.Data
LoadBytes
FileTOC.DerivedCopy.Type
Dysymtab
File.ImportedLibraries.RangeStmt_34233.l
FileTOC
NewFile.RangeStmt_21877.BlockStmt.BlockStmt.b
Section.UncompressedSize
File.DWARF.BlockStmt.BlockStmt.r
File.DWARF.err
Section.PutRelocs.RangeStmt_6655.BlockStmt.ri
File.parseSymtab.strtab
FileTOC.DerivedCopy.Flags
NewFile._
NewFile.f
Section.Put64.b
LoadBytes.Raw
Uuid.LoadSize.t
File.parseSymtab.hdr
SectionHeader.Reserved3
FileTOC.Put.RangeStmt_10823.l
Section.Data.n
LinkEditData.LoadSize.t
File.DWARF.RangeStmt_33181.BlockStmt.err
File.DWARF.RangeStmt_33181.BlockStmt.suffix
Dylinker.LoadSize.s
File.pushSection.BlockStmt.err
NewFile.RangeStmt_21877.BlockStmt.BlockStmt.symsz
NewFile.RangeStmt_21877.BlockStmt.BlockStmt.BlockStmt.sh32
FormatError
Section.PutUncompressedData.BlockStmt.BlockStmt.r
Segment.Data.s
FileTOC.SymbolSize
DyldInfo.String.s
File.parseSymtab.st
Segment
Segment.Put32.s
Section.UncompressedSize.b
Dylinker.LoadSize
NewFile.RangeStmt_21877.BlockStmt.BlockStmt.BlockStmt.sh
FileTOC.TOCSize
Section.Data
Dysymtab.LoadSize.s
File.DWARF.RangeStmt_33181.BlockStmt.b
SectionHeader.Offset
SegmentHeader.Addr
Section.UncompressedSize.err
NewFile.RangeStmt_21877.BlockStmt.BlockStmt.x
Dylib.LoadSize.t
Dylinker.Name
Symbol.Sect
NewFile.bo
File.pushSection.BlockStmt._
Segment.Put32.b
Section
Section.Put64
LoadBytes.String.b
File.ImportedSymbols.all
Section.PutRelocs.s
FileTOC.FileSize.sz
NewFile.RangeStmt_21877.BlockStmt.BlockStmt.seg32
File.Section.name
Segment.UncompressedSize.j
EncryptionInfo.Copy
NewFile.RangeStmt_21877.BlockStmt.cmddat
NewFile.RangeStmt_21877.BlockStmt.s
Reloc.Value
formatError
Segment.Data.n
Symtab.Put.s
Section.PutRelocs
Symbol.Value
FileTOC.Put.t
Section.Put32.s
Symbol.Type
LoadCmdBytes.String
Symtab.LoadSize.t
SegmentHeader.Memsz
FileTOC.DerivedCopy.t
Section.PutData
LoadCmd.Put
File.parseSymtab.symtab
File.Segment.name
RoundUp.x
SectionHeader.Align
Section.PutRelocs.o
Open.ff
NewFile.RangeStmt_21877.BlockStmt.BlockStmt.st
File.parseSymtab.RangeStmt_28806.i
DyldInfo.LoadSize
File.parseSymtab.RangeStmt_28806.BlockStmt.BlockStmt.n32
formatError.off
LoadCmd.Put.lc
Dylib.Copy
cstring.i
Open.name
NewFile.RangeStmt_21877.BlockStmt.BlockStmt.hdr
NewFile.RangeStmt_21877.BlockStmt.BlockStmt.BlockStmt.err
dwarf
Section.PutData.err
Segment.Copy.r
Dylib
Dysymtab.Copy.s
Section.Put32
LoadBytes.LoadSize.b
Symtab.Syms
Section.PutUncompressedData.b
LoadBytes.LoadSize.t
File.parseSymtab.offset
Section.Put32.o
Segment.Copy.s
Section.PutRelocs.a
Segment.Data.dat
File.Close
Section.UncompressedSize.n
Segment.Copy
NewFile.r
NewFile.RangeStmt_21877.BlockStmt.BlockStmt.strtab
Symtab.String.s
Symtab.String
Uuid.Put
FileTOC.AddSegment.s
Dylib.Copy.r
Rpath.String.s
FileTOC.HdrSize
Dylinker.Copy.s
SegmentHeader.Nsect
RoundUp
FileTOC.Loads
Section.PutRelocs.RangeStmt_6655.r
Segment.UncompressedSize
EncryptionInfo.LoadSize.t
Segment.Put64
File.parseSymtab.symdat
Symtab.Copy
NewFile.RangeStmt_21877.BlockStmt.cmd
File.parseSymtab.b
FileTOC.AddLoad.l
Uuid.Copy.s
NewFile.RangeStmt_21877.BlockStmt.BlockStmt.dat
NewFile.RangeStmt_21877.i
Section.PutData.b
Section.Copy.s
NewFile.le
FileTOC.LoadSize.cmdsz
File.pushSection.BlockStmt.RangeStmt_30012.i
Segment.Put64.o
putAtMost16Bytes.b
FileTOC.LoadAlign
Dylib.String
SegmentHeader.Name
LoadBytes.Copy
Segment.CopyZeroed.s
Segment.Put32.o
Section.PutRelocs.RangeStmt_6655.BlockStmt.ext
File.DWARF.BlockStmt.BlockStmt.err
File.DWARF.RangeStmt_32761.s
File.Close.f
File.ImportedSymbols.dt
FileTOC.DerivedCopy.h
File.ImportedLibraries.f
Segment.Data.err
NewFile.RangeStmt_21877.BlockStmt.BlockStmt.err
Load
Reloc.Scattered
Section.Copy
Section.PutUncompressedData.BlockStmt.bb
Segment.String.s
Rpath.LoadSize
SegmentHeader.Offset
Section.Put64.s
FormatError.msg
FileTOC.Put.RangeStmt_10823.BlockStmt.BlockStmt.BlockStmt.i
Section.Data.s
Reloc.Extern
File.pushSection
FileTOC.LoadSize.t
Section.PutData.n
Open.f
Uuid
NewFile.RangeStmt_21877.BlockStmt.siz
File.parseSymtab.RangeStmt_28806.BlockStmt.BlockStmt.err
SectionHeader.Size
putAtMost16Bytes.RangeStmt_7386.i
LoadCmdBytes.Copy
Dylinker.Copy
Segment.sr
SectionHeader.Nreloc
Rpath.LoadSize.s
NewFile.RangeStmt_21877.BlockStmt.BlockStmt._
SegmentHeader.Firstsect
Section.PutUncompressedData.BlockStmt.n
LinkEditData.String.s
Section.UncompressedSize.s
FileTOC.TOCSize.t
FileTOC.LoadSize
LinkEditData.Copy.s
Uuid.LoadSize
File.parseSymtab.RangeStmt_28806.BlockStmt.n
FileTOC.DerivedCopy
LoadBytes.Raw.b
Dylib.Time
Symtab.Put
LoadCmdBytes
SectionHeader.Addr
DyldInfo.Copy.s
LoadCmd.Put.o
Dylinker.LoadSize.t
Rpath.Command.s
FormatError.off
LoadBytes.String
LoadBytes.Copy.b
LoadCmdBytes.String.s
File.DWARF.RangeStmt_32761.BlockStmt.b
SectionHeader.Reloff
NewFile.sr
Uuid.Put.b
NewFile.RangeStmt_21877.BlockStmt.BlockStmt.symdat
FileTOC.AddSegment
SegmentHeader.Flag
Dylinker.String.s
File.pushSection.BlockStmt.RangeStmt_30012.BlockStmt.err
Reloc.Addr
SegmentHeader.String
Rpath.String
FileTOC.AddLoad.t
FileTOC.Put.next
FileTOC.Put
Dylib.CurrentVersion
Dylib.String.s
File
Symtab.Put.o
Dysymtab.Copy
formatError.data
FileTOC.Put.buffer
NewFile
File.parseSymtab
File.DWARF.RangeStmt_33181.s
formatError.format
Dylib.Copy.s
File.DWARF.BlockStmt.b
File.DWARF.d
DyldInfo
File.closer
Section.PutRelocs.RangeStmt_6655.BlockStmt.pcrel
bytes
Uuid.Copy
EncryptionInfo.LoadSize.s
Dylib.Name
Dylib.LoadSize.s
NewFile.be
Reloc.Pcrel
Symbol
LoadBytes.String.RangeStmt_13336.a
File.pushSection.r
File.ImportedLibraries
FileTOC.AddSection.sectionsize
Section.Put64.o
FileTOC.SymbolSize.t
Uuid.String
EncryptionInfo.String.s
File.ImportedSymbols.RangeStmt_33879.s
DyldInfo.LoadSize.t
File.pushSection.BlockStmt.RangeStmt_30012.BlockStmt.ri
FileTOC.AddSection
FileTOC.FileSize.t
Dylib.LoadSize
File.Segment
SectionHeader.Seg
cstring
RoundUp.align
Symtab.Put.b
File.Symtab
Reloc.Len
Section.PutRelocs.b
Section.PutUncompressedData
File.ImportedSymbols.st
Section.Open.s
File.Dysymtab
SectionHeader
NewFile.RangeStmt_21877.BlockStmt.BlockStmt.BlockStmt.sh64
FileTOC.AddSection.t
Section.Relocs
putAtMost16Bytes.n
NewFile.RangeStmt_21877.BlockStmt.BlockStmt.l
LinkEditData.LoadSize
NewFile.ident
File.DWARF.BlockStmt.BlockStmt._
FileTOC.LoadSize.RangeStmt_9911.l
FileTOC.AddSegment.t
Segment.UncompressedSize.align
Dysymtab.String
Symtab
DyldInfo.LoadSize.s
Section.PutData.s
File.Segment.f
File.Section
unsafe
FileTOC.AddLoad
Symbol.Name
LoadBytes.String.s
Rpath.Copy.s
Dysymtab.LoadSize
Segment.Put64.b
FormatError.Error
File.DWARF
LoadBytes.LoadSize
Rpath.Command
File.parseSymtab.f
DyldInfo.Copy
Open.err
SegmentHeader
EncryptionInfo.LoadSize
Dysymtab.IndirectSyms
SegmentHeader.Prot
Symtab.LoadSize
File.pushSection.BlockStmt.reldat
File.pushSection.BlockStmt.bo
File.pushSection.sh
cstring.b
Reloc.Type
Segment.LoadSize.t
LinkEditData.String
Rpath.LoadSize.t
Section.Open
Rpath.Path
fmt
FileTOC.ByteOrder
FileTOC.Sections
Section.sr
strings
Section.PutUncompressedData.BlockStmt.err
Segment.CopyZeroed.r
File.DWARF.f
SegmentHeader.Len
File.DWARF.BlockStmt.BlockStmt.dlen
FileTOC.FileSize.RangeStmt_10331.l
LoadCmdBytes.Copy.s
Segment.Open
LinkEditData
File.DWARF.RangeStmt_32761.BlockStmt.err
Rpath
Section.PutUncompressedData.s
zlib
FileTOC.HdrSize.t
Segment.UncompressedSize.sz
Segment.CopyZeroed
SegmentHeader.Maxprot
FormatError.Error.e
relocInfo.Symnum
SectionHeader.Reserved2
Dysymtab.LoadSize.t
File.ImportedLibraries.all
NewFile.RangeStmt_21877.BlockStmt.BlockStmt.seg64
File.parseSymtab.cmddat
relocInfo.Addr
File.Segment.RangeStmt_31324.l
File.ImportedSymbols
EncryptionInfo.String
NewFile.err
File.parseSymtab.bo
Section.PutUncompressedData.BlockStmt.BlockStmt.size
NewFile.dat
File.pushSection.f
LoadBytes.String.RangeStmt_13336.i
Uuid.Put.s
Segment.Open.s
SectionHeader.Reserved1
Reloc
SegmentHeader.String.s
Uuid.LoadSize.s
SectionHeader.Flags
Segment.UncompressedSize.t
Dysymtab.String.s
File.Section.RangeStmt_31580.s
Uuid.String.s
File.Close.err
Dylinker.String
Dylinker
Symtab.Copy.s
Members
X