mirror of
https://github.com/autc04/Retro68.git
synced 2024-09-08 20:55:01 +00:00
112 lines
2.9 KiB
Go
112 lines
2.9 KiB
Go
// Copyright 2016 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 pe
|
|
|
|
import (
|
|
"encoding/binary"
|
|
"fmt"
|
|
"io"
|
|
"strconv"
|
|
)
|
|
|
|
// SectionHeader32 represents real PE COFF section header.
|
|
type SectionHeader32 struct {
|
|
Name [8]uint8
|
|
VirtualSize uint32
|
|
VirtualAddress uint32
|
|
SizeOfRawData uint32
|
|
PointerToRawData uint32
|
|
PointerToRelocations uint32
|
|
PointerToLineNumbers uint32
|
|
NumberOfRelocations uint16
|
|
NumberOfLineNumbers uint16
|
|
Characteristics uint32
|
|
}
|
|
|
|
// fullName finds real name of section sh. Normally name is stored
|
|
// in sh.Name, but if it is longer then 8 characters, it is stored
|
|
// in COFF string table st instead.
|
|
func (sh *SectionHeader32) fullName(st StringTable) (string, error) {
|
|
if sh.Name[0] != '/' {
|
|
return cstring(sh.Name[:]), nil
|
|
}
|
|
i, err := strconv.Atoi(cstring(sh.Name[1:]))
|
|
if err != nil {
|
|
return "", err
|
|
}
|
|
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.
|
|
type SectionHeader struct {
|
|
Name string
|
|
VirtualSize uint32
|
|
VirtualAddress uint32
|
|
Size uint32
|
|
Offset uint32
|
|
PointerToRelocations uint32
|
|
PointerToLineNumbers uint32
|
|
NumberOfRelocations uint16
|
|
NumberOfLineNumbers uint16
|
|
Characteristics uint32
|
|
}
|
|
|
|
// Section provides access to PE COFF section.
|
|
type Section struct {
|
|
SectionHeader
|
|
Relocs []Reloc
|
|
|
|
// 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
|
|
}
|
|
|
|
// Data reads and returns the contents of the PE section s.
|
|
func (s *Section) Data() ([]byte, error) {
|
|
dat := make([]byte, s.sr.Size())
|
|
n, err := s.sr.ReadAt(dat, 0)
|
|
if n == len(dat) {
|
|
err = nil
|
|
}
|
|
return dat[0:n], err
|
|
}
|
|
|
|
// Open returns a new ReadSeeker reading the PE section s.
|
|
func (s *Section) Open() io.ReadSeeker {
|
|
return io.NewSectionReader(s.sr, 0, 1<<63-1)
|
|
}
|