Skip to content

Commit

Permalink
support mach-o overlay
Browse files Browse the repository at this point in the history
  • Loading branch information
fcharlie committed Jan 21, 2021
1 parent f544f87 commit 3690f0a
Show file tree
Hide file tree
Showing 5 changed files with 93 additions and 5 deletions.
2 changes: 1 addition & 1 deletion debug/elf/file.go
Original file line number Diff line number Diff line change
Expand Up @@ -1479,7 +1479,7 @@ func (f *File) Overlay() ([]byte, error) {
}
overlayEnd, err := sr.Seek(0, io.SeekEnd)
if err != nil {
return nil, fmt.Errorf("pe: seek %v", err)
return nil, fmt.Errorf("elf: seek %v", err)
}
overlayLen := overlayEnd - int64(f.OverlayOffset)
overlay := make([]byte, overlayLen)
Expand Down
55 changes: 53 additions & 2 deletions debug/macho/file.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,21 +12,29 @@ import (
"compress/zlib"
"debug/dwarf"
"encoding/binary"
"errors"
"fmt"
"io"
"os"
"strings"
)

// error
var (
ErrNoOverlayFound = errors.New("macho: not have overlay data")
)

// A File represents an open Mach-O file.
type File struct {
FileHeader
ByteOrder binary.ByteOrder
Loads []Load
Sections []*Section

Symtab *Symtab
Dysymtab *Dysymtab
Symtab *Symtab
Dysymtab *Dysymtab
OverlayOffset uint64
r io.ReaderAt

closer io.Closer
}
Expand Down Expand Up @@ -227,6 +235,7 @@ func (f *File) Close() error {
// The Mach-O binary is expected to start at position 0 in the ReaderAt.
func NewFile(r io.ReaderAt) (*File, error) {
f := new(File)
f.r = r
sr := io.NewSectionReader(r, 0, 1<<63-1)

// Read and decode Mach magic to determine byte order, size.
Expand Down Expand Up @@ -375,6 +384,9 @@ func NewFile(r io.ReaderAt) (*File, error) {
s.Memsz = uint64(seg32.Memsz)
s.Offset = uint64(seg32.Offset)
s.Filesz = uint64(seg32.Filesz)
if sectionEnd := uint64(s.Offset) + s.Filesz; sectionEnd > f.OverlayOffset {
f.OverlayOffset = sectionEnd
}
s.Maxprot = seg32.Maxprot
s.Prot = seg32.Prot
s.Nsect = seg32.Nsect
Expand Down Expand Up @@ -415,6 +427,9 @@ func NewFile(r io.ReaderAt) (*File, error) {
s.Memsz = seg64.Memsz
s.Offset = seg64.Offset
s.Filesz = seg64.Filesz
if sectionEnd := uint64(s.Offset) + s.Filesz; sectionEnd > f.OverlayOffset {
f.OverlayOffset = sectionEnd
}
s.Maxprot = seg64.Maxprot
s.Prot = seg64.Prot
s.Nsect = seg64.Nsect
Expand Down Expand Up @@ -445,6 +460,11 @@ func NewFile(r io.ReaderAt) (*File, error) {
s.ReaderAt = s.sr
}
}
for _, sec := range f.Sections {
if sectionEnd := uint64(sec.Offset) + sec.Size; sectionEnd > f.OverlayOffset {
f.OverlayOffset = sectionEnd
}
}
return f, nil
}

Expand Down Expand Up @@ -691,3 +711,34 @@ func (f *File) ImportedLibraries() ([]string, error) {
}
return all, nil
}

// NewOverlayReader create a new ReaderAt for read PE overlay data
func (f *File) NewOverlayReader() (io.ReaderAt, error) {
if f.r == nil {
return nil, errors.New("elf: file reader is nil")
}
if f.OverlayOffset == 0 {
return nil, ErrNoOverlayFound
}
return io.NewSectionReader(f.r, int64(f.OverlayOffset), 1<<63-1), nil
}

// Overlay returns the overlay of the ELF fil (i.e. any optional bytes directly
// succeeding the image).
func (f *File) Overlay() ([]byte, error) {
sr, ok := f.r.(io.Seeker)
if !ok {
return nil, errors.New("macho: reader not a io.Seeker")
}
overlayEnd, err := sr.Seek(0, io.SeekEnd)
if err != nil {
return nil, fmt.Errorf("macho: seek %v", err)
}
overlayLen := overlayEnd - int64(f.OverlayOffset)
overlay := make([]byte, overlayLen)
ser := io.NewSectionReader(f.r, int64(f.OverlayOffset), overlayLen)
if _, err := io.ReadFull(ser, overlay); err != nil {
return nil, err
}
return overlay, nil
}
2 changes: 1 addition & 1 deletion debug/pe/overlay.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ var (
// NewOverlayReader create a new ReaderAt for read PE overlay data
func (f *File) NewOverlayReader() (io.ReaderAt, error) {
if f.r == nil {
return nil, errors.New("PE file reader is nil")
return nil, errors.New("pe: file reader is nil")
}
return io.NewSectionReader(f.r, f.OverlayOffset, 1<<63-1), nil
}
Expand Down
2 changes: 1 addition & 1 deletion test/elfreader/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ func main() {
if st.Size() > int64(fd.OverlayOffset) {
overlay, err := fd.Overlay()
if err != nil && err != elf.ErrNoOverlayFound {
fmt.Fprintf(os.Stderr, "unable LookupExports: %s %v\n", os.Args[1], err)
fmt.Fprintf(os.Stderr, "unable lookup elf overlay data: %s %v\n", os.Args[1], err)
os.Exit(1)
}
fmt.Fprintf(os.Stderr, "Overlay: %v\n", string(overlay))
Expand Down
37 changes: 37 additions & 0 deletions test/machoreader/main.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
package main

import (
"fmt"
"os"

"github.com/fcharlie/buna/debug/macho"
)

func main() {
if len(os.Args) < 2 {
fmt.Fprintf(os.Stderr, "usage: %s pefile\n", os.Args[0])
os.Exit(1)
}
st, err := os.Stat(os.Args[1])
if err != nil {
fmt.Fprintf(os.Stderr, "unable state: %v\n", err)
os.Exit(1)
}
size := st.Size()
fmt.Fprintf(os.Stderr, "FileSize: %d\n", size)
fd, err := macho.Open(os.Args[1])
if err != nil {
fmt.Fprintf(os.Stderr, "unable open file: %s %v\n", os.Args[1], err)
os.Exit(1)
}
defer fd.Close()
if size > int64(fd.OverlayOffset) {
overlay, err := fd.Overlay()
if err != nil && err != macho.ErrNoOverlayFound {
fmt.Fprintf(os.Stderr, "unable lookuo overlay data: %s %v\n", os.Args[1], err)
os.Exit(1)
}
fmt.Fprintf(os.Stderr, "Overlay: %v\n", string(overlay))
}

}

0 comments on commit 3690f0a

Please sign in to comment.