mirror of
https://github.com/golang/go
synced 2024-11-26 00:38:00 -07:00
elf file parser
R=austin DELTA=448 (447 added, 0 deleted, 1 changed) OCL=34139 CL=34150
This commit is contained in:
parent
1e55e4a3e6
commit
f0492f4e27
@ -17,7 +17,7 @@ crypto/md5.install: hash.install os.install
|
||||
crypto/sha1.install: hash.install os.install
|
||||
datafmt.install: bytes.install container/vector.install fmt.install go/scanner.install go/token.install io.install os.install reflect.install runtime.install strconv.install strings.install
|
||||
debug/binary.install: io.install math.install os.install reflect.install
|
||||
debug/elf.install: fmt.install io.install os.install strconv.install
|
||||
debug/elf.install: debug/binary.install fmt.install io.install os.install strconv.install
|
||||
ebnf.install: container/vector.install fmt.install go/scanner.install go/token.install os.install strconv.install strings.install unicode.install utf8.install
|
||||
exec.install: os.install strings.install
|
||||
exvar.install: bytes.install fmt.install http.install io.install log.install strconv.install sync.install
|
||||
|
324
src/pkg/debug/elf/file.go
Normal file
324
src/pkg/debug/elf/file.go
Normal file
@ -0,0 +1,324 @@
|
||||
// Copyright 2009 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package elf
|
||||
|
||||
import (
|
||||
"debug/binary";
|
||||
"fmt";
|
||||
"io";
|
||||
"os";
|
||||
)
|
||||
|
||||
// TODO: error reporting detail
|
||||
|
||||
/*
|
||||
* Internal ELF representation
|
||||
*/
|
||||
|
||||
// A FileHeader represents an ELF file header.
|
||||
type FileHeader struct {
|
||||
Class Class;
|
||||
Data Data;
|
||||
Version Version;
|
||||
OSABI OSABI;
|
||||
ABIVersion uint8;
|
||||
ByteOrder binary.ByteOrder;
|
||||
Type Type;
|
||||
Machine Machine;
|
||||
}
|
||||
|
||||
// A File represents an open ELF file.
|
||||
type File struct {
|
||||
FileHeader;
|
||||
Sections []*Section;
|
||||
Progs []*Prog;
|
||||
|
||||
closer io.Closer;
|
||||
}
|
||||
|
||||
// A SectionHeader represents a single ELF section header.
|
||||
type SectionHeader struct {
|
||||
Name string;
|
||||
Type SectionType;
|
||||
Flags SectionFlag;
|
||||
Addr uint64;
|
||||
Offset uint64;
|
||||
Size uint64;
|
||||
Link uint32;
|
||||
Info uint32;
|
||||
Addralign uint64;
|
||||
Entsize uint64;
|
||||
}
|
||||
|
||||
// A Section represents a single section in an ELF file.
|
||||
type Section struct {
|
||||
SectionHeader;
|
||||
|
||||
// Embed ReaderAt for ReadAt method.
|
||||
// Do not embed SectionReader directly
|
||||
// to avoid having Read and Seek.
|
||||
// If a client wants Read and Seek it must use
|
||||
// Open() to avoid fighting over the seek offset
|
||||
// with other clients.
|
||||
io.ReaderAt;
|
||||
sr *io.SectionReader;
|
||||
}
|
||||
|
||||
// Open returns a new ReadSeeker reading the ELF section.
|
||||
func (s *Section) Open() io.ReadSeeker {
|
||||
return io.NewSectionReader(s.sr, 0, 1<<63 - 1);
|
||||
}
|
||||
|
||||
// A ProgHeader represents a single ELF program header.
|
||||
type ProgHeader struct {
|
||||
Type ProgType;
|
||||
Flags ProgFlag;
|
||||
Vaddr uint64;
|
||||
Paddr uint64;
|
||||
Filesz uint64;
|
||||
Memsz uint64;
|
||||
Align uint64;
|
||||
}
|
||||
|
||||
// A Prog represents a single ELF program header in an ELF binary.
|
||||
type Prog struct {
|
||||
ProgHeader;
|
||||
|
||||
// Embed ReaderAt for ReadAt method.
|
||||
// Do not embed SectionReader directly
|
||||
// to avoid having Read and Seek.
|
||||
// If a client wants Read and Seek it must use
|
||||
// Open() to avoid fighting over the seek offset
|
||||
// with other clients.
|
||||
io.ReaderAt;
|
||||
sr *io.SectionReader;
|
||||
}
|
||||
|
||||
// Open returns a new ReadSeeker reading the ELF program body.
|
||||
func (p *Prog) Open() io.ReadSeeker {
|
||||
return io.NewSectionReader(p.sr, 0, 1<<63 - 1);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* ELF reader
|
||||
*/
|
||||
|
||||
type FormatError struct {
|
||||
off int64;
|
||||
msg string;
|
||||
val interface{};
|
||||
}
|
||||
|
||||
func (e *FormatError) String() string {
|
||||
msg := e.msg;
|
||||
if e.val != nil {
|
||||
msg += fmt.Sprintf(" '%v' ", e.val);
|
||||
}
|
||||
msg += fmt.Sprintf("in record at byte %#x", e.off);
|
||||
return msg;
|
||||
}
|
||||
|
||||
// Open opens the named file using os.Open and prepares it for use as an ELF binary.
|
||||
func Open(name string) (*File, os.Error) {
|
||||
f, err := os.Open(name, os.O_RDONLY, 0);
|
||||
if err != nil {
|
||||
return nil, err;
|
||||
}
|
||||
ff, err := NewFile(f);
|
||||
if err != nil {
|
||||
f.Close();
|
||||
return nil, err;
|
||||
}
|
||||
ff.closer = f;
|
||||
return ff, nil;
|
||||
}
|
||||
|
||||
// Close closes the File.
|
||||
// If the File was created using NewFile directly instead of Open,
|
||||
// Close has no effect.
|
||||
func (f *File) Close() os.Error {
|
||||
var err os.Error;
|
||||
if f.closer != nil {
|
||||
err = f.closer.Close();
|
||||
f.closer = nil;
|
||||
}
|
||||
return err;
|
||||
}
|
||||
|
||||
// NewFile creates a new File for acecssing an ELF binary in an underlying reader.
|
||||
// The ELF binary is expected to start at position 0 in the ReaderAt.
|
||||
func NewFile(r io.ReaderAt) (*File, os.Error) {
|
||||
sr := io.NewSectionReader(r, 0, 1<<63 - 1);
|
||||
// Read and decode ELF identifier
|
||||
var ident [16]uint8;
|
||||
if _, err := r.ReadAt(&ident, 0); err != nil {
|
||||
return nil, err;
|
||||
}
|
||||
if ident[0] != '\x7f' || ident[1] != 'E' || ident[2] != 'L' || ident[3] != 'F' {
|
||||
return nil, &FormatError{0, "bad magic number", ident[0:4]};
|
||||
}
|
||||
|
||||
f := new(File);
|
||||
f.Class = Class(ident[EI_CLASS]);
|
||||
switch f.Class {
|
||||
case ELFCLASS32:
|
||||
case ELFCLASS64:
|
||||
// ok
|
||||
default:
|
||||
return nil, &FormatError{0, "unknown ELF class", f.Class};
|
||||
}
|
||||
|
||||
f.Data = Data(ident[EI_DATA]);
|
||||
switch f.Data {
|
||||
case ELFDATA2LSB:
|
||||
f.ByteOrder = binary.LittleEndian;
|
||||
case ELFDATA2MSB:
|
||||
f.ByteOrder = binary.BigEndian;
|
||||
default:
|
||||
return nil, &FormatError{0, "unknown ELF data encoding", f.Data};
|
||||
}
|
||||
|
||||
f.Version = Version(ident[EI_VERSION]);
|
||||
if f.Version != EV_CURRENT {
|
||||
return nil, &FormatError{0, "unknown ELF version", f.Version};
|
||||
}
|
||||
|
||||
f.OSABI = OSABI(ident[EI_OSABI]);
|
||||
f.ABIVersion = ident[EI_ABIVERSION];
|
||||
|
||||
// Read ELF file header
|
||||
var shoff int64;
|
||||
var shentsize, shnum, shstrndx int;
|
||||
shstrndx = -1;
|
||||
switch f.Class {
|
||||
case ELFCLASS32:
|
||||
hdr := new(Header32);
|
||||
sr.Seek(0, 0);
|
||||
if err := binary.Read(sr, f.ByteOrder, hdr); err != nil {
|
||||
return nil, err;
|
||||
}
|
||||
f.Type = Type(hdr.Type);
|
||||
f.Machine = Machine(hdr.Machine);
|
||||
if v := Version(hdr.Version); v != f.Version {
|
||||
return nil, &FormatError{0, "mismatched ELF version", v};
|
||||
}
|
||||
shoff = int64(hdr.Shoff);
|
||||
shentsize = int(hdr.Shentsize);
|
||||
shnum = int(hdr.Shnum);
|
||||
shstrndx = int(hdr.Shstrndx);
|
||||
case ELFCLASS64:
|
||||
hdr := new(Header64);
|
||||
sr.Seek(0, 0);
|
||||
if err := binary.Read(sr, f.ByteOrder, hdr); err != nil {
|
||||
return nil, err;
|
||||
}
|
||||
f.Type = Type(hdr.Type);
|
||||
f.Machine = Machine(hdr.Machine);
|
||||
if v := Version(hdr.Version); v != f.Version {
|
||||
return nil, &FormatError{0, "mismatched ELF version", v};
|
||||
}
|
||||
shoff = int64(hdr.Shoff);
|
||||
shentsize = int(hdr.Shentsize);
|
||||
shnum = int(hdr.Shnum);
|
||||
shstrndx = int(hdr.Shstrndx);
|
||||
}
|
||||
if shstrndx < 0 || shstrndx >= shnum {
|
||||
return nil, &FormatError{0, "invalid ELF shstrndx", shstrndx};
|
||||
}
|
||||
|
||||
// Read program headers
|
||||
// TODO
|
||||
|
||||
// Read section headers
|
||||
f.Sections = make([]*Section, shnum);
|
||||
names := make([]uint32, shnum);
|
||||
for i := 0; i < shnum; i++ {
|
||||
off := shoff + int64(i)*int64(shentsize);
|
||||
sr.Seek(off, 0);
|
||||
s := new(Section);
|
||||
switch f.Class {
|
||||
case ELFCLASS32:
|
||||
sh := new(Section32);
|
||||
if err := binary.Read(sr, f.ByteOrder, sh); err != nil {
|
||||
return nil, err;
|
||||
}
|
||||
names[i] = sh.Name;
|
||||
s.SectionHeader = SectionHeader{
|
||||
Type: SectionType(sh.Type),
|
||||
Flags: SectionFlag(sh.Flags),
|
||||
Addr: uint64(sh.Addr),
|
||||
Offset: uint64(sh.Off),
|
||||
Size: uint64(sh.Size),
|
||||
Link: uint32(sh.Link),
|
||||
Info: uint32(sh.Info),
|
||||
Addralign: uint64(sh.Addralign),
|
||||
Entsize: uint64(sh.Entsize),
|
||||
};
|
||||
case ELFCLASS64:
|
||||
sh := new(Section64);
|
||||
if err := binary.Read(sr, f.ByteOrder, sh); err != nil {
|
||||
return nil, err;
|
||||
}
|
||||
names[i] = sh.Name;
|
||||
s.SectionHeader = SectionHeader{
|
||||
Type: SectionType(sh.Type),
|
||||
Flags: SectionFlag(sh.Flags),
|
||||
Offset: uint64(sh.Off),
|
||||
Size: uint64(sh.Size),
|
||||
Addr: uint64(sh.Addr),
|
||||
Link: uint32(sh.Link),
|
||||
Info: uint32(sh.Info),
|
||||
Addralign: uint64(sh.Addralign),
|
||||
Entsize: uint64(sh.Entsize),
|
||||
|
||||
};
|
||||
}
|
||||
s.sr = io.NewSectionReader(r, int64(s.Offset), int64(s.Size));
|
||||
s.ReaderAt = s.sr;
|
||||
f.Sections[i] = s;
|
||||
}
|
||||
|
||||
// Load section header string table.
|
||||
s := f.Sections[shstrndx];
|
||||
shstrtab := make([]byte, s.Size);
|
||||
if _, err := r.ReadAt(shstrtab, int64(s.Offset)); err != nil {
|
||||
return nil, err;
|
||||
}
|
||||
for i, s := range f.Sections {
|
||||
var ok bool;
|
||||
s.Name, ok = getString(shstrtab, int(names[i]));
|
||||
if !ok {
|
||||
return nil, &FormatError{shoff + int64(i*shentsize), "bad section name index", names[i]};
|
||||
}
|
||||
}
|
||||
|
||||
return f, nil;
|
||||
}
|
||||
|
||||
// getString extracts a string from an ELF string table.
|
||||
func getString(section []byte, start int) (string, bool) {
|
||||
if start < 0 || start >= len(section) {
|
||||
return "", false;
|
||||
}
|
||||
|
||||
for end := start; end < len(section); end++ {
|
||||
if section[end] == 0 {
|
||||
return string(section[start:end]), true;
|
||||
}
|
||||
}
|
||||
return "", false;
|
||||
}
|
||||
|
||||
// Section returns a section with the given name, or nil if no such
|
||||
// section exists.
|
||||
func (f *File) Section(name string) *Section {
|
||||
for _, s := range f.Sections {
|
||||
if s.Name == name {
|
||||
return s;
|
||||
}
|
||||
}
|
||||
return nil;
|
||||
}
|
129
src/pkg/debug/elf/file_test.go
Normal file
129
src/pkg/debug/elf/file_test.go
Normal file
@ -0,0 +1,129 @@
|
||||
// Copyright 2009 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package elf
|
||||
|
||||
import (
|
||||
"debug/binary";
|
||||
"reflect";
|
||||
"testing";
|
||||
)
|
||||
|
||||
type fileTest struct {
|
||||
file string;
|
||||
hdr FileHeader;
|
||||
sections []SectionHeader;
|
||||
}
|
||||
|
||||
var fileTests = []fileTest {
|
||||
fileTest{
|
||||
"testdata/gcc-386-freebsd-exec",
|
||||
FileHeader{ELFCLASS32, ELFDATA2LSB, EV_CURRENT, ELFOSABI_FREEBSD, 0, binary.LittleEndian, ET_EXEC, EM_386},
|
||||
[]SectionHeader{
|
||||
SectionHeader{"", SHT_NULL, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0},
|
||||
SectionHeader{".interp", SHT_PROGBITS, SHF_ALLOC, 0x80480d4, 0xd4, 0x15, 0x0, 0x0, 0x1, 0x0},
|
||||
SectionHeader{".hash", SHT_HASH, SHF_ALLOC, 0x80480ec, 0xec, 0x90, 0x3, 0x0, 0x4, 0x4},
|
||||
SectionHeader{".dynsym", SHT_DYNSYM, SHF_ALLOC, 0x804817c, 0x17c, 0x110, 0x4, 0x1, 0x4, 0x10},
|
||||
SectionHeader{".dynstr", SHT_STRTAB, SHF_ALLOC, 0x804828c, 0x28c, 0xbb, 0x0, 0x0, 0x1, 0x0},
|
||||
SectionHeader{".rel.plt", SHT_REL, SHF_ALLOC, 0x8048348, 0x348, 0x20, 0x3, 0x7, 0x4, 0x8},
|
||||
SectionHeader{".init", SHT_PROGBITS, SHF_ALLOC+SHF_EXECINSTR, 0x8048368, 0x368, 0x11, 0x0, 0x0, 0x4, 0x0},
|
||||
SectionHeader{".plt", SHT_PROGBITS, SHF_ALLOC+SHF_EXECINSTR, 0x804837c, 0x37c, 0x50, 0x0, 0x0, 0x4, 0x4},
|
||||
SectionHeader{".text", SHT_PROGBITS, SHF_ALLOC+SHF_EXECINSTR, 0x80483cc, 0x3cc, 0x180, 0x0, 0x0, 0x4, 0x0},
|
||||
SectionHeader{".fini", SHT_PROGBITS, SHF_ALLOC+SHF_EXECINSTR, 0x804854c, 0x54c, 0xc, 0x0, 0x0, 0x4, 0x0},
|
||||
SectionHeader{".rodata", SHT_PROGBITS, SHF_ALLOC, 0x8048558, 0x558, 0xa3, 0x0, 0x0, 0x1, 0x0},
|
||||
SectionHeader{".data", SHT_PROGBITS, SHF_WRITE+SHF_ALLOC, 0x80495fc, 0x5fc, 0xc, 0x0, 0x0, 0x4, 0x0},
|
||||
SectionHeader{".eh_frame", SHT_PROGBITS, SHF_ALLOC, 0x8049608, 0x608, 0x4, 0x0, 0x0, 0x4, 0x0},
|
||||
SectionHeader{".dynamic", SHT_DYNAMIC, SHF_WRITE+SHF_ALLOC, 0x804960c, 0x60c, 0x98, 0x4, 0x0, 0x4, 0x8},
|
||||
SectionHeader{".ctors", SHT_PROGBITS, SHF_WRITE+SHF_ALLOC, 0x80496a4, 0x6a4, 0x8, 0x0, 0x0, 0x4, 0x0},
|
||||
SectionHeader{".dtors", SHT_PROGBITS, SHF_WRITE+SHF_ALLOC, 0x80496ac, 0x6ac, 0x8, 0x0, 0x0, 0x4, 0x0},
|
||||
SectionHeader{".jcr", SHT_PROGBITS, SHF_WRITE+SHF_ALLOC, 0x80496b4, 0x6b4, 0x4, 0x0, 0x0, 0x4, 0x0},
|
||||
SectionHeader{".got", SHT_PROGBITS, SHF_WRITE+SHF_ALLOC, 0x80496b8, 0x6b8, 0x1c, 0x0, 0x0, 0x4, 0x4},
|
||||
SectionHeader{".bss", SHT_NOBITS, SHF_WRITE+SHF_ALLOC, 0x80496d4, 0x6d4, 0x20, 0x0, 0x0, 0x4, 0x0},
|
||||
SectionHeader{".comment", SHT_PROGBITS, 0x0, 0x0, 0x6d4, 0x12d, 0x0, 0x0, 0x1, 0x0},
|
||||
SectionHeader{".debug_aranges", SHT_PROGBITS, 0x0, 0x0, 0x801, 0x20, 0x0, 0x0, 0x1, 0x0},
|
||||
SectionHeader{".debug_pubnames", SHT_PROGBITS, 0x0, 0x0, 0x821, 0x1b, 0x0, 0x0, 0x1, 0x0},
|
||||
SectionHeader{".debug_info", SHT_PROGBITS, 0x0, 0x0, 0x83c, 0x11d, 0x0, 0x0, 0x1, 0x0},
|
||||
SectionHeader{".debug_abbrev", SHT_PROGBITS, 0x0, 0x0, 0x959, 0x41, 0x0, 0x0, 0x1, 0x0},
|
||||
SectionHeader{".debug_line", SHT_PROGBITS, 0x0, 0x0, 0x99a, 0x35, 0x0, 0x0, 0x1, 0x0},
|
||||
SectionHeader{".debug_frame", SHT_PROGBITS, 0x0, 0x0, 0x9d0, 0x30, 0x0, 0x0, 0x4, 0x0},
|
||||
SectionHeader{".debug_str", SHT_PROGBITS, 0x0, 0x0, 0xa00, 0xd, 0x0, 0x0, 0x1, 0x0},
|
||||
SectionHeader{".shstrtab", SHT_STRTAB, 0x0, 0x0, 0xa0d, 0xf8, 0x0, 0x0, 0x1, 0x0},
|
||||
SectionHeader{".symtab", SHT_SYMTAB, 0x0, 0x0, 0xfb8, 0x4b0, 0x1d, 0x38, 0x4, 0x10},
|
||||
SectionHeader{".strtab", SHT_STRTAB, 0x0, 0x0, 0x1468, 0x206, 0x0, 0x0, 0x1, 0x0},
|
||||
}
|
||||
},
|
||||
fileTest{
|
||||
"testdata/gcc-amd64-linux-exec",
|
||||
FileHeader{ELFCLASS64, ELFDATA2LSB, EV_CURRENT, ELFOSABI_NONE, 0, binary.LittleEndian, ET_EXEC, EM_X86_64},
|
||||
[]SectionHeader{
|
||||
SectionHeader{"", SHT_NULL, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0},
|
||||
SectionHeader{".interp", SHT_PROGBITS, SHF_ALLOC, 0x400200, 0x200, 0x1c, 0x0, 0x0, 0x1, 0x0},
|
||||
SectionHeader{".note.ABI-tag", SHT_NOTE, SHF_ALLOC, 0x40021c, 0x21c, 0x20, 0x0, 0x0, 0x4, 0x0},
|
||||
SectionHeader{".hash", SHT_HASH, SHF_ALLOC, 0x400240, 0x240, 0x24, 0x5, 0x0, 0x8, 0x4},
|
||||
SectionHeader{".gnu.hash", SHT_LOOS+268435446, SHF_ALLOC, 0x400268, 0x268, 0x1c, 0x5, 0x0, 0x8, 0x0},
|
||||
SectionHeader{".dynsym", SHT_DYNSYM, SHF_ALLOC, 0x400288, 0x288, 0x60, 0x6, 0x1, 0x8, 0x18},
|
||||
SectionHeader{".dynstr", SHT_STRTAB, SHF_ALLOC, 0x4002e8, 0x2e8, 0x3d, 0x0, 0x0, 0x1, 0x0},
|
||||
SectionHeader{".gnu.version", SHT_HIOS, SHF_ALLOC, 0x400326, 0x326, 0x8, 0x5, 0x0, 0x2, 0x2},
|
||||
SectionHeader{".gnu.version_r", SHT_LOOS+268435454, SHF_ALLOC, 0x400330, 0x330, 0x20, 0x6, 0x1, 0x8, 0x0},
|
||||
SectionHeader{".rela.dyn", SHT_RELA, SHF_ALLOC, 0x400350, 0x350, 0x18, 0x5, 0x0, 0x8, 0x18},
|
||||
SectionHeader{".rela.plt", SHT_RELA, SHF_ALLOC, 0x400368, 0x368, 0x30, 0x5, 0xc, 0x8, 0x18},
|
||||
SectionHeader{".init", SHT_PROGBITS, SHF_ALLOC+SHF_EXECINSTR, 0x400398, 0x398, 0x18, 0x0, 0x0, 0x4, 0x0},
|
||||
SectionHeader{".plt", SHT_PROGBITS, SHF_ALLOC+SHF_EXECINSTR, 0x4003b0, 0x3b0, 0x30, 0x0, 0x0, 0x4, 0x10},
|
||||
SectionHeader{".text", SHT_PROGBITS, SHF_ALLOC+SHF_EXECINSTR, 0x4003e0, 0x3e0, 0x1b4, 0x0, 0x0, 0x10, 0x0},
|
||||
SectionHeader{".fini", SHT_PROGBITS, SHF_ALLOC+SHF_EXECINSTR, 0x400594, 0x594, 0xe, 0x0, 0x0, 0x4, 0x0},
|
||||
SectionHeader{".rodata", SHT_PROGBITS, SHF_ALLOC, 0x4005a4, 0x5a4, 0x11, 0x0, 0x0, 0x4, 0x0},
|
||||
SectionHeader{".eh_frame_hdr", SHT_PROGBITS, SHF_ALLOC, 0x4005b8, 0x5b8, 0x24, 0x0, 0x0, 0x4, 0x0},
|
||||
SectionHeader{".eh_frame", SHT_PROGBITS, SHF_ALLOC, 0x4005e0, 0x5e0, 0xa4, 0x0, 0x0, 0x8, 0x0},
|
||||
SectionHeader{".ctors", SHT_PROGBITS, SHF_WRITE+SHF_ALLOC, 0x600688, 0x688, 0x10, 0x0, 0x0, 0x8, 0x0},
|
||||
SectionHeader{".dtors", SHT_PROGBITS, SHF_WRITE+SHF_ALLOC, 0x600698, 0x698, 0x10, 0x0, 0x0, 0x8, 0x0},
|
||||
SectionHeader{".jcr", SHT_PROGBITS, SHF_WRITE+SHF_ALLOC, 0x6006a8, 0x6a8, 0x8, 0x0, 0x0, 0x8, 0x0},
|
||||
SectionHeader{".dynamic", SHT_DYNAMIC, SHF_WRITE+SHF_ALLOC, 0x6006b0, 0x6b0, 0x1a0, 0x6, 0x0, 0x8, 0x10},
|
||||
SectionHeader{".got", SHT_PROGBITS, SHF_WRITE+SHF_ALLOC, 0x600850, 0x850, 0x8, 0x0, 0x0, 0x8, 0x8},
|
||||
SectionHeader{".got.plt", SHT_PROGBITS, SHF_WRITE+SHF_ALLOC, 0x600858, 0x858, 0x28, 0x0, 0x0, 0x8, 0x8},
|
||||
SectionHeader{".data", SHT_PROGBITS, SHF_WRITE+SHF_ALLOC, 0x600880, 0x880, 0x18, 0x0, 0x0, 0x8, 0x0},
|
||||
SectionHeader{".bss", SHT_NOBITS, SHF_WRITE+SHF_ALLOC, 0x600898, 0x898, 0x8, 0x0, 0x0, 0x4, 0x0},
|
||||
SectionHeader{".comment", SHT_PROGBITS, 0x0, 0x0, 0x898, 0x126, 0x0, 0x0, 0x1, 0x0},
|
||||
SectionHeader{".debug_aranges", SHT_PROGBITS, 0x0, 0x0, 0x9c0, 0x90, 0x0, 0x0, 0x10, 0x0},
|
||||
SectionHeader{".debug_pubnames", SHT_PROGBITS, 0x0, 0x0, 0xa50, 0x25, 0x0, 0x0, 0x1, 0x0},
|
||||
SectionHeader{".debug_info", SHT_PROGBITS, 0x0, 0x0, 0xa75, 0x1a7, 0x0, 0x0, 0x1, 0x0},
|
||||
SectionHeader{".debug_abbrev", SHT_PROGBITS, 0x0, 0x0, 0xc1c, 0x6f, 0x0, 0x0, 0x1, 0x0},
|
||||
SectionHeader{".debug_line", SHT_PROGBITS, 0x0, 0x0, 0xc8b, 0x13f, 0x0, 0x0, 0x1, 0x0},
|
||||
SectionHeader{".debug_str", SHT_PROGBITS, SHF_MERGE+SHF_STRINGS, 0x0, 0xdca, 0xb1, 0x0, 0x0, 0x1, 0x1},
|
||||
SectionHeader{".debug_ranges", SHT_PROGBITS, 0x0, 0x0, 0xe80, 0x90, 0x0, 0x0, 0x10, 0x0},
|
||||
SectionHeader{".shstrtab", SHT_STRTAB, 0x0, 0x0, 0xf10, 0x149, 0x0, 0x0, 0x1, 0x0},
|
||||
SectionHeader{".symtab", SHT_SYMTAB, 0x0, 0x0, 0x19a0, 0x6f0, 0x24, 0x39, 0x8, 0x18},
|
||||
SectionHeader{".strtab", SHT_STRTAB, 0x0, 0x0, 0x2090, 0x1fc, 0x0, 0x0, 0x1, 0x0},
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestOpen(t *testing.T) {
|
||||
for i := range fileTests {
|
||||
tt := &fileTests[i];
|
||||
|
||||
f, err := Open(tt.file);
|
||||
if err != nil {
|
||||
t.Error(err);
|
||||
continue;
|
||||
}
|
||||
if !reflect.DeepEqual(f.FileHeader, tt.hdr) {
|
||||
t.Errorf("open %s:\n\thave %#v\n\twant %#v\n", tt.file, f.FileHeader, tt.hdr);
|
||||
continue;
|
||||
}
|
||||
for i, s := range f.Sections {
|
||||
if i >= len(tt.sections) {
|
||||
break;
|
||||
}
|
||||
sh := &tt.sections[i];
|
||||
if !reflect.DeepEqual(&s.SectionHeader, sh) {
|
||||
t.Errorf("open %s, section %d:\n\thave %#v\n\twant %#v\n", tt.file, i, &s.SectionHeader, sh);
|
||||
}
|
||||
}
|
||||
tn := len(tt.sections);
|
||||
fn := len(f.Sections);
|
||||
if tn != fn {
|
||||
t.Errorf("open %s: len(Sections) = %d, want %d", tt.file, fn, tn);
|
||||
}
|
||||
}
|
||||
}
|
BIN
src/pkg/debug/elf/testdata/gcc-386-freebsd-exec
vendored
Executable file
BIN
src/pkg/debug/elf/testdata/gcc-386-freebsd-exec
vendored
Executable file
Binary file not shown.
BIN
src/pkg/debug/elf/testdata/gcc-amd64-linux-exec
vendored
Executable file
BIN
src/pkg/debug/elf/testdata/gcc-amd64-linux-exec
vendored
Executable file
Binary file not shown.
Loading…
Reference in New Issue
Block a user