mirror of
https://github.com/Binject/debug
synced 2026-06-08 10:28:33 +00:00
@@ -11,6 +11,10 @@ import (
|
||||
const CERTIFICATE_TABLE = 4
|
||||
|
||||
func readCertTable(f *File, r io.ReadSeeker) ([]byte, error) {
|
||||
if f.OptionalHeader == nil { // Optional header is optional, might not exist
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
var certTableOffset, certTableSize uint32
|
||||
|
||||
switch f.FileHeader.Machine {
|
||||
|
||||
+18
-71
@@ -29,15 +29,17 @@ type File struct {
|
||||
DosStub [64]byte // TODO(capnspacehook) make slice and correctly parse any DOS stub
|
||||
RichHeader []byte
|
||||
FileHeader
|
||||
OptionalHeader interface{} // of type *OptionalHeader32 or *OptionalHeader64
|
||||
Sections []*Section
|
||||
Symbols []*Symbol // COFF symbols with auxiliary symbol records removed
|
||||
COFFSymbols []COFFSymbol // all COFF symbols (including auxiliary symbol records)
|
||||
StringTable StringTable
|
||||
CertificateTable []byte
|
||||
OptionalHeader interface{} // of type *OptionalHeader32 or *OptionalHeader64
|
||||
Sections []*Section
|
||||
BaseRelocationTable *[]RelocationTableEntry
|
||||
Symbols []*Symbol // COFF symbols with auxiliary symbol records removed
|
||||
COFFSymbols []COFFSymbol // all COFF symbols (including auxiliary symbol records)
|
||||
StringTable StringTable
|
||||
CertificateTable []byte
|
||||
|
||||
InsertionAddr uint32
|
||||
InsertionBytes []byte
|
||||
OptionalHeaderOffset int64 // offset of the start of the Optional Header
|
||||
InsertionAddr uint32
|
||||
InsertionBytes []byte
|
||||
|
||||
Net Net //If a managed executable, Net provides an interface to some of the metadata
|
||||
|
||||
@@ -183,7 +185,8 @@ func newFileInternal(r io.ReaderAt, memoryMode bool) (*File, error) {
|
||||
}
|
||||
|
||||
// Read optional header.
|
||||
sr.Seek(peHeaderOffset+int64(binary.Size(f.FileHeader)), seekStart)
|
||||
f.OptionalHeaderOffset = peHeaderOffset + int64(binary.Size(f.FileHeader))
|
||||
sr.Seek(f.OptionalHeaderOffset, seekStart)
|
||||
|
||||
var oh32 OptionalHeader32
|
||||
var oh64 OptionalHeader64
|
||||
@@ -251,6 +254,12 @@ func newFileInternal(r io.ReaderAt, memoryMode bool) (*File, error) {
|
||||
}
|
||||
}
|
||||
|
||||
// Read Base Relocation Block and Items
|
||||
f.BaseRelocationTable, err = f.readBaseRelocationTable()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Read certificate table
|
||||
f.CertificateTable, err = readCertTable(f, sr)
|
||||
if err != nil {
|
||||
@@ -456,65 +465,3 @@ func (f *File) IsManaged() bool {
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
// RelocationBlock - for base relocation entries
|
||||
type RelocationBlock struct {
|
||||
VirtualAddress uint32
|
||||
SizeOfBlock uint32
|
||||
}
|
||||
|
||||
// BlockItem - relocation block item
|
||||
type BlockItem struct {
|
||||
Val uint16
|
||||
Type uint16
|
||||
Offset uint16
|
||||
}
|
||||
|
||||
// Relocate - performs base relocations on this image to the given offset
|
||||
func (f *File) Relocate(offset uint32) {
|
||||
|
||||
pe64 := f.Machine == IMAGE_FILE_MACHINE_AMD64
|
||||
var addr uint32
|
||||
var imageBase uint64
|
||||
if pe64 {
|
||||
addr = f.OptionalHeader.(*OptionalHeader64).DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress
|
||||
imageBase = f.OptionalHeader.(*OptionalHeader64).ImageBase
|
||||
} else {
|
||||
addr = f.OptionalHeader.(*OptionalHeader32).DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress
|
||||
imageBase = uint64(f.OptionalHeader.(*OptionalHeader32).ImageBase)
|
||||
}
|
||||
firstSectionRawDataPtr := uint32(0)
|
||||
for i, val := range f.Sections {
|
||||
if i == 0 {
|
||||
firstSectionRawDataPtr = val.Offset
|
||||
}
|
||||
if val.VirtualAddress == addr { // name should be .reloc?
|
||||
cur := val.Offset
|
||||
d, _ := val.Data()
|
||||
for cur-val.Offset < val.VirtualSize {
|
||||
var reloBlock RelocationBlock
|
||||
binary.Read(bytes.NewBuffer(d[cur:cur+8]), binary.LittleEndian, &reloBlock)
|
||||
cur += 8
|
||||
for i := uint32(0); i < reloBlock.SizeOfBlock-8; i += 2 {
|
||||
var bi BlockItem
|
||||
bi.Val = binary.LittleEndian.Uint16(d[cur : cur+2])
|
||||
bi.Type = uint16(bi.Val >> 12)
|
||||
bi.Offset = bi.Val & 0x0fff
|
||||
localOffset := firstSectionRawDataPtr + uint32(bi.Offset)
|
||||
relAddr := binary.LittleEndian.Uint32(d[localOffset : localOffset+4])
|
||||
relAddr += offset - uint32(imageBase)
|
||||
byts := make([]byte, 4)
|
||||
binary.LittleEndian.PutUint32(byts, relAddr)
|
||||
copy(d[localOffset:localOffset+4], byts)
|
||||
cur += 2
|
||||
}
|
||||
}
|
||||
break
|
||||
}
|
||||
}
|
||||
if pe64 {
|
||||
f.OptionalHeader.(*OptionalHeader64).ImageBase = uint64(offset)
|
||||
} else {
|
||||
f.OptionalHeader.(*OptionalHeader32).ImageBase = uint32(offset)
|
||||
}
|
||||
}
|
||||
|
||||
+62
-64
@@ -6,7 +6,6 @@ package pe
|
||||
|
||||
import (
|
||||
"debug/dwarf"
|
||||
"internal/testenv"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"os/exec"
|
||||
@@ -28,23 +27,25 @@ type fileTest struct {
|
||||
hasNoDwarfInfo bool
|
||||
}
|
||||
|
||||
var zero8 [8]uint8
|
||||
|
||||
var fileTests = []fileTest{
|
||||
{
|
||||
file: "testdata/gcc-386-mingw-obj",
|
||||
hdr: FileHeader{0x014c, 0x000c, 0x0, 0x64a, 0x1e, 0x0, 0x104},
|
||||
sections: []*SectionHeader{
|
||||
{".text", 0, 0, 36, 500, 1440, 0, 3, 0, 0x60300020},
|
||||
{".data", 0, 0, 0, 0, 0, 0, 0, 0, 3224371264},
|
||||
{".bss", 0, 0, 0, 0, 0, 0, 0, 0, 3224371328},
|
||||
{".debug_abbrev", 0, 0, 137, 536, 0, 0, 0, 0, 0x42100000},
|
||||
{".debug_info", 0, 0, 418, 673, 1470, 0, 7, 0, 1108344832},
|
||||
{".debug_line", 0, 0, 128, 1091, 1540, 0, 1, 0, 1108344832},
|
||||
{".rdata", 0, 0, 16, 1219, 0, 0, 0, 0, 1076887616},
|
||||
{".debug_frame", 0, 0, 52, 1235, 1550, 0, 2, 0, 1110441984},
|
||||
{".debug_loc", 0, 0, 56, 1287, 0, 0, 0, 0, 1108344832},
|
||||
{".debug_pubnames", 0, 0, 27, 1343, 1570, 0, 1, 0, 1108344832},
|
||||
{".debug_pubtypes", 0, 0, 38, 1370, 1580, 0, 1, 0, 1108344832},
|
||||
{".debug_aranges", 0, 0, 32, 1408, 1590, 0, 2, 0, 1108344832},
|
||||
{".text", [8]uint8{0x2e, 0x74, 0x65, 0x78, 0x74, 0x0, 0x0, 0x0}, 0, 0, 36, 500, 1440, 0, 3, 0, 0x60300020},
|
||||
{".data", [8]uint8{0x2e, 0x64, 0x61, 0x74, 0x61, 0x0, 0x0, 0x0}, 0, 0, 0, 0, 0, 0, 0, 0, 3224371264},
|
||||
{".bss", [8]uint8{0x2e, 0x62, 0x73, 0x73, 0x0, 0x0, 0x0, 0x0}, 0, 0, 0, 0, 0, 0, 0, 0, 3224371328},
|
||||
{".debug_abbrev", [8]uint8{0x2f, 0x34, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}, 0, 0, 137, 536, 0, 0, 0, 0, 0x42100000},
|
||||
{".debug_info", [8]uint8{0x2f, 0x31, 0x38, 0x0, 0x0, 0x0, 0x0, 0x0}, 0, 0, 418, 673, 1470, 0, 7, 0, 1108344832},
|
||||
{".debug_line", [8]uint8{0x2f, 0x33, 0x30, 0x0, 0x0, 0x0, 0x0, 0x0}, 0, 0, 128, 1091, 1540, 0, 1, 0, 1108344832},
|
||||
{".rdata", [8]uint8{0x2e, 0x72, 0x64, 0x61, 0x74, 0x61, 0x0, 0x0}, 0, 0, 16, 1219, 0, 0, 0, 0, 1076887616},
|
||||
{".debug_frame", [8]uint8{0x2f, 0x34, 0x32, 0x0, 0x0, 0x0, 0x0, 0x0}, 0, 0, 52, 1235, 1550, 0, 2, 0, 1110441984},
|
||||
{".debug_loc", [8]uint8{0x2f, 0x35, 0x35, 0x0, 0x0, 0x0, 0x0, 0x0}, 0, 0, 56, 1287, 0, 0, 0, 0, 1108344832},
|
||||
{".debug_pubnames", [8]uint8{0x2f, 0x36, 0x36, 0x0, 0x0, 0x0, 0x0, 0x0}, 0, 0, 27, 1343, 1570, 0, 1, 0, 1108344832},
|
||||
{".debug_pubtypes", [8]uint8{0x2f, 0x38, 0x32, 0x0, 0x0, 0x0, 0x0, 0x0}, 0, 0, 38, 1370, 1580, 0, 1, 0, 1108344832},
|
||||
{".debug_aranges", [8]uint8{0x2f, 0x39, 0x38, 0x0, 0x0, 0x0, 0x0, 0x0}, 0, 0, 32, 1408, 1590, 0, 2, 0, 1108344832},
|
||||
},
|
||||
symbols: []*Symbol{
|
||||
{".file", 0x0, -2, 0x0, 0x67},
|
||||
@@ -90,21 +91,21 @@ var fileTests = []fileTest{
|
||||
},
|
||||
},
|
||||
sections: []*SectionHeader{
|
||||
{".text", 0xcd8, 0x1000, 0xe00, 0x400, 0x0, 0x0, 0x0, 0x0, 0x60500060},
|
||||
{".data", 0x10, 0x2000, 0x200, 0x1200, 0x0, 0x0, 0x0, 0x0, 0xc0300040},
|
||||
{".rdata", 0x120, 0x3000, 0x200, 0x1400, 0x0, 0x0, 0x0, 0x0, 0x40300040},
|
||||
{".bss", 0xdc, 0x4000, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xc0400080},
|
||||
{".idata", 0x3c8, 0x5000, 0x400, 0x1600, 0x0, 0x0, 0x0, 0x0, 0xc0300040},
|
||||
{".CRT", 0x18, 0x6000, 0x200, 0x1a00, 0x0, 0x0, 0x0, 0x0, 0xc0300040},
|
||||
{".tls", 0x20, 0x7000, 0x200, 0x1c00, 0x0, 0x0, 0x0, 0x0, 0xc0300040},
|
||||
{".debug_aranges", 0x20, 0x8000, 0x200, 0x1e00, 0x0, 0x0, 0x0, 0x0, 0x42100000},
|
||||
{".debug_pubnames", 0x51, 0x9000, 0x200, 0x2000, 0x0, 0x0, 0x0, 0x0, 0x42100000},
|
||||
{".debug_pubtypes", 0x91, 0xa000, 0x200, 0x2200, 0x0, 0x0, 0x0, 0x0, 0x42100000},
|
||||
{".debug_info", 0xe22, 0xb000, 0x1000, 0x2400, 0x0, 0x0, 0x0, 0x0, 0x42100000},
|
||||
{".debug_abbrev", 0x157, 0xc000, 0x200, 0x3400, 0x0, 0x0, 0x0, 0x0, 0x42100000},
|
||||
{".debug_line", 0x144, 0xd000, 0x200, 0x3600, 0x0, 0x0, 0x0, 0x0, 0x42100000},
|
||||
{".debug_frame", 0x34, 0xe000, 0x200, 0x3800, 0x0, 0x0, 0x0, 0x0, 0x42300000},
|
||||
{".debug_loc", 0x38, 0xf000, 0x200, 0x3a00, 0x0, 0x0, 0x0, 0x0, 0x42100000},
|
||||
{".text", [8]uint8{0x2e, 0x74, 0x65, 0x78, 0x74, 0x0, 0x0, 0x0}, 0xcd8, 0x1000, 0xe00, 0x400, 0x0, 0x0, 0x0, 0x0, 0x60500060},
|
||||
{".data", [8]uint8{0x2e, 0x64, 0x61, 0x74, 0x61, 0x0, 0x0, 0x0}, 0x10, 0x2000, 0x200, 0x1200, 0x0, 0x0, 0x0, 0x0, 0xc0300040},
|
||||
{".rdata", [8]uint8{0x2e, 0x72, 0x64, 0x61, 0x74, 0x61, 0x0, 0x0}, 0x120, 0x3000, 0x200, 0x1400, 0x0, 0x0, 0x0, 0x0, 0x40300040},
|
||||
{".bss", [8]uint8{0x2e, 0x62, 0x73, 0x73, 0x0, 0x0, 0x0, 0x0}, 0xdc, 0x4000, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xc0400080},
|
||||
{".idata", [8]uint8{0x2e, 0x69, 0x64, 0x61, 0x74, 0x61, 0x0, 0x0}, 0x3c8, 0x5000, 0x400, 0x1600, 0x0, 0x0, 0x0, 0x0, 0xc0300040},
|
||||
{".CRT", [8]uint8{0x2e, 0x43, 0x52, 0x54, 0x0, 0x0, 0x0, 0x0}, 0x18, 0x6000, 0x200, 0x1a00, 0x0, 0x0, 0x0, 0x0, 0xc0300040},
|
||||
{".tls", [8]uint8{0x2e, 0x74, 0x6c, 0x73, 0x0, 0x0, 0x0, 0x0}, 0x20, 0x7000, 0x200, 0x1c00, 0x0, 0x0, 0x0, 0x0, 0xc0300040},
|
||||
{".debug_aranges", [8]uint8{0x2f, 0x34, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}, 0x20, 0x8000, 0x200, 0x1e00, 0x0, 0x0, 0x0, 0x0, 0x42100000},
|
||||
{".debug_pubnames", [8]uint8{0x2f, 0x31, 0x39, 0x0, 0x0, 0x0, 0x0, 0x0}, 0x51, 0x9000, 0x200, 0x2000, 0x0, 0x0, 0x0, 0x0, 0x42100000},
|
||||
{".debug_pubtypes", [8]uint8{0x2f, 0x33, 0x35, 0x0, 0x0, 0x0, 0x0, 0x0}, 0x91, 0xa000, 0x200, 0x2200, 0x0, 0x0, 0x0, 0x0, 0x42100000},
|
||||
{".debug_info", [8]uint8{0x2f, 0x35, 0x31, 0x0, 0x0, 0x0, 0x0, 0x0}, 0xe22, 0xb000, 0x1000, 0x2400, 0x0, 0x0, 0x0, 0x0, 0x42100000},
|
||||
{".debug_abbrev", [8]uint8{0x2f, 0x36, 0x33, 0x0, 0x0, 0x0, 0x0, 0x0}, 0x157, 0xc000, 0x200, 0x3400, 0x0, 0x0, 0x0, 0x0, 0x42100000},
|
||||
{".debug_line", [8]uint8{0x2f, 0x37, 0x37, 0x0, 0x0, 0x0, 0x0, 0x0}, 0x144, 0xd000, 0x200, 0x3600, 0x0, 0x0, 0x0, 0x0, 0x42100000},
|
||||
{".debug_frame", [8]uint8{0x2f, 0x38, 0x39, 0x0, 0x0, 0x0, 0x0, 0x0}, 0x34, 0xe000, 0x200, 0x3800, 0x0, 0x0, 0x0, 0x0, 0x42300000},
|
||||
{".debug_loc", [8]uint8{0x2f, 0x31, 0x30, 0x32, 0x0, 0x0, 0x0, 0x0}, 0x38, 0xf000, 0x200, 0x3a00, 0x0, 0x0, 0x0, 0x0, 0x42100000},
|
||||
},
|
||||
},
|
||||
{
|
||||
@@ -131,14 +132,14 @@ var fileTests = []fileTest{
|
||||
},
|
||||
},
|
||||
sections: []*SectionHeader{
|
||||
{".text", 0xc64, 0x1000, 0xe00, 0x400, 0x0, 0x0, 0x0, 0x0, 0x60500060},
|
||||
{".data", 0x10, 0x2000, 0x200, 0x1200, 0x0, 0x0, 0x0, 0x0, 0xc0300040},
|
||||
{".rdata", 0x134, 0x3000, 0x200, 0x1400, 0x0, 0x0, 0x0, 0x0, 0x40300040},
|
||||
{".eh_fram", 0x3a0, 0x4000, 0x400, 0x1600, 0x0, 0x0, 0x0, 0x0, 0x40300040},
|
||||
{".bss", 0x60, 0x5000, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xc0300080},
|
||||
{".idata", 0x378, 0x6000, 0x400, 0x1a00, 0x0, 0x0, 0x0, 0x0, 0xc0300040},
|
||||
{".CRT", 0x18, 0x7000, 0x200, 0x1e00, 0x0, 0x0, 0x0, 0x0, 0xc0300040},
|
||||
{".tls", 0x20, 0x8000, 0x200, 0x2000, 0x0, 0x0, 0x0, 0x0, 0xc0300040},
|
||||
{".text", [8]uint8{0x2e, 0x74, 0x65, 0x78, 0x74, 0x0, 0x0, 0x0}, 0xc64, 0x1000, 0xe00, 0x400, 0x0, 0x0, 0x0, 0x0, 0x60500060},
|
||||
{".data", [8]uint8{0x2e, 0x64, 0x61, 0x74, 0x61, 0x0, 0x0, 0x0}, 0x10, 0x2000, 0x200, 0x1200, 0x0, 0x0, 0x0, 0x0, 0xc0300040},
|
||||
{".rdata", [8]uint8{0x2e, 0x72, 0x64, 0x61, 0x74, 0x61, 0x0, 0x0}, 0x134, 0x3000, 0x200, 0x1400, 0x0, 0x0, 0x0, 0x0, 0x40300040},
|
||||
{".eh_fram", [8]uint8{0x2e, 0x65, 0x68, 0x5f, 0x66, 0x72, 0x61, 0x6d}, 0x3a0, 0x4000, 0x400, 0x1600, 0x0, 0x0, 0x0, 0x0, 0x40300040},
|
||||
{".bss", [8]uint8{0x2e, 0x62, 0x73, 0x73, 0x0, 0x0, 0x0, 0x0}, 0x60, 0x5000, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xc0300080},
|
||||
{".idata", [8]uint8{0x2e, 0x69, 0x64, 0x61, 0x74, 0x61, 0x0, 0x0}, 0x378, 0x6000, 0x400, 0x1a00, 0x0, 0x0, 0x0, 0x0, 0xc0300040},
|
||||
{".CRT", [8]uint8{0x2e, 0x43, 0x52, 0x54, 0x0, 0x0, 0x0, 0x0}, 0x18, 0x7000, 0x200, 0x1e00, 0x0, 0x0, 0x0, 0x0, 0xc0300040},
|
||||
{".tls", [8]uint8{0x2e, 0x74, 0x6c, 0x73, 0x0, 0x0, 0x0, 0x0}, 0x20, 0x8000, 0x200, 0x2000, 0x0, 0x0, 0x0, 0x0, 0xc0300040},
|
||||
},
|
||||
hasNoDwarfInfo: true,
|
||||
},
|
||||
@@ -146,12 +147,12 @@ var fileTests = []fileTest{
|
||||
file: "testdata/gcc-amd64-mingw-obj",
|
||||
hdr: FileHeader{0x8664, 0x6, 0x0, 0x198, 0x12, 0x0, 0x4},
|
||||
sections: []*SectionHeader{
|
||||
{".text", 0x0, 0x0, 0x30, 0x104, 0x15c, 0x0, 0x3, 0x0, 0x60500020},
|
||||
{".data", 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xc0500040},
|
||||
{".bss", 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xc0500080},
|
||||
{".rdata", 0x0, 0x0, 0x10, 0x134, 0x0, 0x0, 0x0, 0x0, 0x40500040},
|
||||
{".xdata", 0x0, 0x0, 0xc, 0x144, 0x0, 0x0, 0x0, 0x0, 0x40300040},
|
||||
{".pdata", 0x0, 0x0, 0xc, 0x150, 0x17a, 0x0, 0x3, 0x0, 0x40300040},
|
||||
{".text", [8]uint8{0x2e, 0x74, 0x65, 0x78, 0x74, 0x0, 0x0, 0x0}, 0x0, 0x0, 0x30, 0x104, 0x15c, 0x0, 0x3, 0x0, 0x60500020},
|
||||
{".data", [8]uint8{0x2e, 0x64, 0x61, 0x74, 0x61, 0x0, 0x0, 0x0}, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xc0500040},
|
||||
{".bss", [8]uint8{0x2e, 0x62, 0x73, 0x73, 0x0, 0x0, 0x0, 0x0}, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xc0500080},
|
||||
{".rdata", [8]uint8{0x2e, 0x72, 0x64, 0x61, 0x74, 0x61, 0x0, 0x0}, 0x0, 0x0, 0x10, 0x134, 0x0, 0x0, 0x0, 0x0, 0x40500040},
|
||||
{".xdata", [8]uint8{0x2e, 0x78, 0x64, 0x61, 0x74, 0x61, 0x0, 0x0}, 0x0, 0x0, 0xc, 0x144, 0x0, 0x0, 0x0, 0x0, 0x40300040},
|
||||
{".pdata", [8]uint8{0x2e, 0x70, 0x64, 0x61, 0x74, 0x61, 0x0, 0x0}, 0x0, 0x0, 0xc, 0x150, 0x17a, 0x0, 0x3, 0x0, 0x40300040},
|
||||
},
|
||||
symbols: []*Symbol{
|
||||
{".file", 0x0, -2, 0x0, 0x67},
|
||||
@@ -191,23 +192,23 @@ var fileTests = []fileTest{
|
||||
{0x0, 0x0},
|
||||
}},
|
||||
sections: []*SectionHeader{
|
||||
{".text", 0x6860, 0x1000, 0x6a00, 0x600, 0x0, 0x0, 0x0, 0x0, 0x60500020},
|
||||
{".data", 0xe0, 0x8000, 0x200, 0x7000, 0x0, 0x0, 0x0, 0x0, 0xc0500040},
|
||||
{".rdata", 0x6b0, 0x9000, 0x800, 0x7200, 0x0, 0x0, 0x0, 0x0, 0x40600040},
|
||||
{".pdata", 0x498, 0xa000, 0x600, 0x7a00, 0x0, 0x0, 0x0, 0x0, 0x40300040},
|
||||
{".xdata", 0x488, 0xb000, 0x600, 0x8000, 0x0, 0x0, 0x0, 0x0, 0x40300040},
|
||||
{".bss", 0x1410, 0xc000, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xc0600080},
|
||||
{".idata", 0x990, 0xe000, 0xa00, 0x8600, 0x0, 0x0, 0x0, 0x0, 0xc0300040},
|
||||
{".CRT", 0x68, 0xf000, 0x200, 0x9000, 0x0, 0x0, 0x0, 0x0, 0xc0400040},
|
||||
{".tls", 0x48, 0x10000, 0x200, 0x9200, 0x0, 0x0, 0x0, 0x0, 0xc0600040},
|
||||
{".debug_aranges", 0x600, 0x11000, 0x600, 0x9400, 0x0, 0x0, 0x0, 0x0, 0x42500040},
|
||||
{".debug_info", 0x1316e, 0x12000, 0x13200, 0x9a00, 0x0, 0x0, 0x0, 0x0, 0x42100040},
|
||||
{".debug_abbrev", 0x2ccb, 0x26000, 0x2e00, 0x1cc00, 0x0, 0x0, 0x0, 0x0, 0x42100040},
|
||||
{".debug_line", 0x3c4d, 0x29000, 0x3e00, 0x1fa00, 0x0, 0x0, 0x0, 0x0, 0x42100040},
|
||||
{".debug_frame", 0x18b8, 0x2d000, 0x1a00, 0x23800, 0x0, 0x0, 0x0, 0x0, 0x42400040},
|
||||
{".debug_str", 0x396, 0x2f000, 0x400, 0x25200, 0x0, 0x0, 0x0, 0x0, 0x42100040},
|
||||
{".debug_loc", 0x13240, 0x30000, 0x13400, 0x25600, 0x0, 0x0, 0x0, 0x0, 0x42100040},
|
||||
{".debug_ranges", 0xa70, 0x44000, 0xc00, 0x38a00, 0x0, 0x0, 0x0, 0x0, 0x42100040},
|
||||
{".text", [8]uint8{0x2e, 0x74, 0x65, 0x78, 0x74, 0x0, 0x0, 0x0}, 0x6860, 0x1000, 0x6a00, 0x600, 0x0, 0x0, 0x0, 0x0, 0x60500020},
|
||||
{".data", [8]uint8{0x2e, 0x64, 0x61, 0x74, 0x61, 0x0, 0x0, 0x0}, 0xe0, 0x8000, 0x200, 0x7000, 0x0, 0x0, 0x0, 0x0, 0xc0500040},
|
||||
{".rdata", [8]uint8{0x2e, 0x72, 0x64, 0x61, 0x74, 0x61, 0x0, 0x0}, 0x6b0, 0x9000, 0x800, 0x7200, 0x0, 0x0, 0x0, 0x0, 0x40600040},
|
||||
{".pdata", [8]uint8{0x2e, 0x70, 0x64, 0x61, 0x74, 0x61, 0x0, 0x0}, 0x498, 0xa000, 0x600, 0x7a00, 0x0, 0x0, 0x0, 0x0, 0x40300040},
|
||||
{".xdata", [8]uint8{0x2e, 0x78, 0x64, 0x61, 0x74, 0x61, 0x0, 0x0}, 0x488, 0xb000, 0x600, 0x8000, 0x0, 0x0, 0x0, 0x0, 0x40300040},
|
||||
{".bss", [8]uint8{0x2e, 0x62, 0x73, 0x73, 0x0, 0x0, 0x0, 0x0}, 0x1410, 0xc000, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xc0600080},
|
||||
{".idata", [8]uint8{0x2e, 0x69, 0x64, 0x61, 0x74, 0x61, 0x0, 0x0}, 0x990, 0xe000, 0xa00, 0x8600, 0x0, 0x0, 0x0, 0x0, 0xc0300040},
|
||||
{".CRT", [8]uint8{0x2e, 0x43, 0x52, 0x54, 0x0, 0x0, 0x0, 0x0}, 0x68, 0xf000, 0x200, 0x9000, 0x0, 0x0, 0x0, 0x0, 0xc0400040},
|
||||
{".tls", [8]uint8{0x2e, 0x74, 0x6c, 0x73, 0x0, 0x0, 0x0, 0x0}, 0x48, 0x10000, 0x200, 0x9200, 0x0, 0x0, 0x0, 0x0, 0xc0600040},
|
||||
{".debug_aranges", [8]uint8{0x2f, 0x34, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}, 0x600, 0x11000, 0x600, 0x9400, 0x0, 0x0, 0x0, 0x0, 0x42500040},
|
||||
{".debug_info", [8]uint8{0x2f, 0x31, 0x39, 0x0, 0x0, 0x0, 0x0, 0x0}, 0x1316e, 0x12000, 0x13200, 0x9a00, 0x0, 0x0, 0x0, 0x0, 0x42100040},
|
||||
{".debug_abbrev", [8]uint8{0x2f, 0x33, 0x31, 0x0, 0x0, 0x0, 0x0, 0x0}, 0x2ccb, 0x26000, 0x2e00, 0x1cc00, 0x0, 0x0, 0x0, 0x0, 0x42100040},
|
||||
{".debug_line", [8]uint8{0x2f, 0x34, 0x35, 0x0, 0x0, 0x0, 0x0, 0x0}, 0x3c4d, 0x29000, 0x3e00, 0x1fa00, 0x0, 0x0, 0x0, 0x0, 0x42100040},
|
||||
{".debug_frame", [8]uint8{0x2f, 0x35, 0x37, 0x0, 0x0, 0x0, 0x0, 0x0}, 0x18b8, 0x2d000, 0x1a00, 0x23800, 0x0, 0x0, 0x0, 0x0, 0x42400040},
|
||||
{".debug_str", [8]uint8{0x2f, 0x37, 0x30, 0x0, 0x0, 0x0, 0x0, 0x0}, 0x396, 0x2f000, 0x400, 0x25200, 0x0, 0x0, 0x0, 0x0, 0x42100040},
|
||||
{".debug_loc", [8]uint8{0x2f, 0x38, 0x31, 0x0, 0x0, 0x0, 0x0, 0x0}, 0x13240, 0x30000, 0x13400, 0x25600, 0x0, 0x0, 0x0, 0x0, 0x42100040},
|
||||
{".debug_ranges", [8]uint8{0x2f, 0x39, 0x32, 0x0, 0x0, 0x0, 0x0, 0x0}, 0xa70, 0x44000, 0xc00, 0x38a00, 0x0, 0x0, 0x0, 0x0, 0x42100040},
|
||||
},
|
||||
},
|
||||
}
|
||||
@@ -313,7 +314,6 @@ func testDWARF(t *testing.T, linktype int) {
|
||||
if runtime.GOOS != "windows" {
|
||||
t.Skip("skipping windows only test")
|
||||
}
|
||||
testenv.MustHaveGoRun(t)
|
||||
|
||||
tmpdir, err := ioutil.TempDir("", "TestDWARF")
|
||||
if err != nil {
|
||||
@@ -350,7 +350,7 @@ func testDWARF(t *testing.T, linktype int) {
|
||||
t.Fatalf("invalid linktype parameter of %v", linktype)
|
||||
}
|
||||
args = append(args, src)
|
||||
out, err := exec.Command(testenv.GoToolPath(t), args...).CombinedOutput()
|
||||
out, err := exec.Command("go", args...).CombinedOutput()
|
||||
if err != nil {
|
||||
t.Fatalf("building test executable for linktype %d failed: %s %s", linktype, err, out)
|
||||
}
|
||||
@@ -424,7 +424,6 @@ func testDWARF(t *testing.T, linktype int) {
|
||||
}
|
||||
|
||||
func TestBSSHasZeros(t *testing.T) {
|
||||
testenv.MustHaveExec(t)
|
||||
|
||||
if runtime.GOOS != "windows" {
|
||||
t.Skip("skipping windows only test")
|
||||
@@ -553,7 +552,6 @@ func main() {
|
||||
`
|
||||
|
||||
func TestBuildingWindowsGUI(t *testing.T) {
|
||||
testenv.MustHaveGoBuild(t)
|
||||
|
||||
if runtime.GOOS != "windows" {
|
||||
t.Skip("skipping windows only test")
|
||||
@@ -570,7 +568,7 @@ func TestBuildingWindowsGUI(t *testing.T) {
|
||||
t.Fatal(err)
|
||||
}
|
||||
exe := filepath.Join(tmpdir, "a.exe")
|
||||
cmd := exec.Command(testenv.GoToolPath(t), "build", "-ldflags", "-H=windowsgui", "-o", exe, src)
|
||||
cmd := exec.Command("go", "build", "-ldflags", "-H=windowsgui", "-o", exe, src)
|
||||
out, err := cmd.CombinedOutput()
|
||||
if err != nil {
|
||||
t.Fatalf("building test executable failed: %s %s", err, out)
|
||||
|
||||
+171
@@ -0,0 +1,171 @@
|
||||
package pe
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/binary"
|
||||
"fmt"
|
||||
"io"
|
||||
)
|
||||
|
||||
// RelocationTable - for base relocation entries
|
||||
type RelocationTableEntry struct {
|
||||
RelocationBlock
|
||||
BlockItems []BlockItem
|
||||
}
|
||||
|
||||
// RelocationBlock - for base relocation entries
|
||||
type RelocationBlock struct {
|
||||
VirtualAddress uint32
|
||||
SizeOfBlock uint32
|
||||
}
|
||||
|
||||
// BlockItem - relocation block item
|
||||
type BlockItem struct {
|
||||
Type byte // 4 bits
|
||||
Offset uint16 // 12 bits
|
||||
}
|
||||
|
||||
// Reloc represents a PE COFF relocation.
|
||||
// Each section contains its own relocation list.
|
||||
type Reloc struct {
|
||||
VirtualAddress uint32
|
||||
SymbolTableIndex uint32
|
||||
Type uint16
|
||||
}
|
||||
|
||||
const (
|
||||
//IMAGE_REL_BASED_ABSOLUTE - The base relocation is skipped. This type can be used to pad a block.
|
||||
IMAGE_REL_BASED_ABSOLUTE = 0
|
||||
|
||||
//IMAGE_REL_BASED_HIGH = 1
|
||||
//IMAGE_REL_BASED_LOW = 2
|
||||
|
||||
//IMAGE_REL_BASED_HIGHLOW - The base relocation applies all 32 bits of the difference to the 32-bit field at offset.
|
||||
IMAGE_REL_BASED_HIGHLOW = 3
|
||||
|
||||
//IMAGE_REL_BASED_HIGHADJ = 4
|
||||
//IMAGE_REL_BASED_MIPS_JMPADDR = 5
|
||||
//IMAGE_REL_BASED_ARM_MOV32 = 5
|
||||
//IMAGE_REL_BASED_RISCV_HIGH20 = 5
|
||||
//IMAGE_REL_BASED_THUMB_MOV32 = 7
|
||||
//IMAGE_REL_BASED_RISCV_LOW12I = 7
|
||||
//IMAGE_REL_BASED_RISCV_LOW12S = 8
|
||||
//IMAGE_REL_BASED_MIPS_JMPADDR16 = 9
|
||||
IMAGE_REL_BASED_DIR64 = 10
|
||||
)
|
||||
|
||||
// readBaseRelocationTable - reads the base relocation table from the file and stores it
|
||||
func (f *File) readBaseRelocationTable() (*[]RelocationTableEntry, error) {
|
||||
|
||||
if f.OptionalHeader == nil { // Optional header is optional, might not exist
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
var dd DataDirectory
|
||||
if f.Machine == IMAGE_FILE_MACHINE_AMD64 {
|
||||
dd = f.OptionalHeader.(*OptionalHeader64).DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC]
|
||||
} else {
|
||||
dd = f.OptionalHeader.(*OptionalHeader32).DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC]
|
||||
}
|
||||
var sectionData []byte
|
||||
var err error
|
||||
for _, section := range f.Sections {
|
||||
if section.VirtualAddress == dd.VirtualAddress {
|
||||
sectionData, err = section.Data()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
break
|
||||
}
|
||||
}
|
||||
r := bytes.NewReader(sectionData)
|
||||
var reloBlocks []RelocationTableEntry
|
||||
bytesRead := uint32(0)
|
||||
for bytesRead < dd.Size {
|
||||
var reloBlock RelocationBlock
|
||||
err = binary.Read(r, binary.LittleEndian, &reloBlock)
|
||||
bytesRead += 8
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("fail to read relocation block: %v", err)
|
||||
}
|
||||
numBlocks := (reloBlock.SizeOfBlock - 8) / 2
|
||||
blocks := make([]BlockItem, numBlocks)
|
||||
for i := uint32(0); i < numBlocks; i++ {
|
||||
var buf [2]byte
|
||||
err = binary.Read(r, binary.LittleEndian, &buf)
|
||||
bytesRead += 2
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("fail to read relocation block item %d: %v", i, err)
|
||||
}
|
||||
var item BlockItem
|
||||
val := binary.LittleEndian.Uint16(buf[:2])
|
||||
item.Type = byte(val >> 12)
|
||||
item.Offset = val & 0x0fff
|
||||
blocks[i] = item
|
||||
}
|
||||
reloBlocks = append(reloBlocks, RelocationTableEntry{reloBlock, blocks})
|
||||
}
|
||||
return &reloBlocks, nil
|
||||
}
|
||||
|
||||
// Relocate - performs base relocations on this image to the given offset
|
||||
func (f *File) Relocate(baseAddr uint64, image *[]byte) {
|
||||
var imageBase uint64
|
||||
pe64 := f.Machine == IMAGE_FILE_MACHINE_AMD64
|
||||
if pe64 {
|
||||
imageBase = f.OptionalHeader.(*OptionalHeader64).ImageBase
|
||||
} else {
|
||||
imageBase = uint64(f.OptionalHeader.(*OptionalHeader32).ImageBase)
|
||||
}
|
||||
for _, block := range *f.BaseRelocationTable {
|
||||
pageRVA := block.VirtualAddress
|
||||
for _, item := range block.BlockItems {
|
||||
if item.Type == IMAGE_REL_BASED_HIGHLOW { // 32 bit
|
||||
delta := uint32(baseAddr - imageBase)
|
||||
fileOffset := f.RVAToFileOffset(pageRVA)
|
||||
idx := fileOffset + uint32(item.Offset)
|
||||
originalAddress := binary.LittleEndian.Uint32((*image)[idx : idx+4])
|
||||
b := make([]byte, 4)
|
||||
binary.LittleEndian.PutUint32(b, originalAddress+delta)
|
||||
copy((*image)[idx:idx+4], b)
|
||||
} else if item.Type == IMAGE_REL_BASED_DIR64 { // 64 bit
|
||||
delta := baseAddr - imageBase
|
||||
fileOffset := f.RVAToFileOffset(pageRVA)
|
||||
idx := fileOffset + uint32(item.Offset)
|
||||
originalAddress := binary.LittleEndian.Uint64((*image)[idx : idx+8])
|
||||
b := make([]byte, 8)
|
||||
binary.LittleEndian.PutUint64(b, originalAddress+delta)
|
||||
copy((*image)[idx:idx+8], b)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// update imageBase in the optional header
|
||||
if pe64 {
|
||||
b := make([]byte, 8)
|
||||
binary.LittleEndian.PutUint64(b, baseAddr)
|
||||
idx := f.OptionalHeaderOffset + 24
|
||||
copy((*image)[idx:idx+8], b)
|
||||
} else {
|
||||
b := make([]byte, 4)
|
||||
binary.LittleEndian.PutUint32(b, uint32(baseAddr))
|
||||
idx := f.OptionalHeaderOffset + 28
|
||||
copy((*image)[idx:idx+4], b)
|
||||
}
|
||||
}
|
||||
|
||||
func readRelocs(sh *SectionHeader, r io.ReadSeeker) ([]Reloc, error) {
|
||||
if sh.NumberOfRelocations <= 0 {
|
||||
return nil, nil
|
||||
}
|
||||
_, err := r.Seek(int64(sh.PointerToRelocations), seekStart)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("fail to seek to %q section relocations: %v", sh.Name, err)
|
||||
}
|
||||
relocs := make([]Reloc, sh.NumberOfRelocations)
|
||||
err = binary.Read(r, binary.LittleEndian, relocs)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("fail to read section relocations: %v", err)
|
||||
}
|
||||
return relocs, nil
|
||||
}
|
||||
@@ -5,8 +5,6 @@
|
||||
package pe
|
||||
|
||||
import (
|
||||
"encoding/binary"
|
||||
"fmt"
|
||||
"io"
|
||||
"strconv"
|
||||
)
|
||||
@@ -39,32 +37,6 @@ func (sh *SectionHeader32) fullName(st StringTable) (string, error) {
|
||||
return st.String(uint32(i))
|
||||
}
|
||||
|
||||
// TODO(brainman): copy all IMAGE_REL_* consts from ldpe.go here
|
||||
|
||||
// Reloc represents a PE COFF relocation.
|
||||
// Each section contains its own relocation list.
|
||||
type Reloc struct {
|
||||
VirtualAddress uint32
|
||||
SymbolTableIndex uint32
|
||||
Type uint16
|
||||
}
|
||||
|
||||
func readRelocs(sh *SectionHeader, r io.ReadSeeker) ([]Reloc, error) {
|
||||
if sh.NumberOfRelocations <= 0 {
|
||||
return nil, nil
|
||||
}
|
||||
_, err := r.Seek(int64(sh.PointerToRelocations), seekStart)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("fail to seek to %q section relocations: %v", sh.Name, err)
|
||||
}
|
||||
relocs := make([]Reloc, sh.NumberOfRelocations)
|
||||
err = binary.Read(r, binary.LittleEndian, relocs)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("fail to read section relocations: %v", err)
|
||||
}
|
||||
return relocs, nil
|
||||
}
|
||||
|
||||
// SectionHeader is similar to SectionHeader32 with Name
|
||||
// field replaced by Go string. OriginalName is the
|
||||
// original name of the section on disk.
|
||||
|
||||
+6
-2
@@ -49,7 +49,11 @@ func readStringTable(fh *FileHeader, r io.ReadSeeker) (StringTable, error) {
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("fail to read string table: %v", err)
|
||||
}
|
||||
return StringTable(buf), nil
|
||||
// re-add the length to the first four bytes of the string table
|
||||
lbuf := make([]byte, 4)
|
||||
binary.LittleEndian.PutUint32(lbuf, l)
|
||||
|
||||
return StringTable(append(lbuf, buf...)), nil
|
||||
}
|
||||
|
||||
// String extracts string from COFF string table st at offset start.
|
||||
@@ -58,7 +62,7 @@ func (st StringTable) String(start uint32) (string, error) {
|
||||
if start < 4 {
|
||||
return "", fmt.Errorf("offset %d is before the start of string table", start)
|
||||
}
|
||||
start -= 4
|
||||
//start -= 4 // we are now including the uint32 length in the StringTable buffer as a prefix, this might change
|
||||
if int(start) > len(st) {
|
||||
return "", fmt.Errorf("offset %d is beyond the end of string table", start)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user