
This allows us to update this dependency on our schedule which is important because the module relies on manually updating the known list of Go versions to function correctly. Forking allows us to keep this up to date ourselves and possibly create a new system to prevent having to perform this manual step in the future.
96 lines
3.0 KiB
Go
96 lines
3.0 KiB
Go
// This file is part of GoRE.
|
|
//
|
|
// Copyright (C) 2019-2021 GoRE Authors
|
|
//
|
|
// This program is free software: you can redistribute it and/or modify
|
|
// it under the terms of the GNU Affero General Public License as published by
|
|
// the Free Software Foundation, either version 3 of the License, or
|
|
// (at your option) any later version.
|
|
//
|
|
// This program is distributed in the hope that it will be useful,
|
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
// GNU General Public License for more details.
|
|
//
|
|
// You should have received a copy of the GNU Affero General Public License
|
|
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
|
|
package gore
|
|
|
|
import (
|
|
"bytes"
|
|
"debug/pe"
|
|
)
|
|
|
|
// pclntab12magic is the magic bytes used for binaries compiled with Go
|
|
// prior to 1.16
|
|
var pclntab12magic = []byte{0xfb, 0xff, 0xff, 0xff, 0x0, 0x0}
|
|
|
|
// pclntab116magic is the magic bytes used for binaries compiled with
|
|
// Go 1.16 and Go 1.17.
|
|
var pclntab116magic = []byte{0xfa, 0xff, 0xff, 0xff, 0x0, 0x0}
|
|
|
|
// pclntab118magic is the magic bytes used for binaries compiled with
|
|
// Go 1.18 and Go 1.19.
|
|
var pclntab118magic = []byte{0xf0, 0xff, 0xff, 0xff, 0x0, 0x0}
|
|
|
|
// pclntab120magic is the magic bytes used for binaries compiled with
|
|
// Go 1.20 and onwards.
|
|
var pclntab120magic = []byte{0xf1, 0xff, 0xff, 0xff, 0x0, 0x0}
|
|
|
|
// searchFileForPCLNTab will search the .rdata and .text section for the
|
|
// PCLN table. Note!! The address returned by this function needs to be
|
|
// adjusted by adding the image base address!!!
|
|
func searchFileForPCLNTab(f *pe.File) (uint32, []byte, error) {
|
|
for _, v := range []string{".rdata", ".text"} {
|
|
sec := f.Section(v)
|
|
if sec == nil {
|
|
continue
|
|
}
|
|
secData, err := sec.Data()
|
|
if err != nil {
|
|
continue
|
|
}
|
|
tab, err := searchSectionForTab(secData)
|
|
if err == ErrNoPCLNTab {
|
|
continue
|
|
}
|
|
// TODO: Switch to returning a uint64 instead.
|
|
addr := sec.VirtualAddress + uint32(len(secData)-len(tab))
|
|
return addr, tab, err
|
|
}
|
|
return 0, []byte{}, ErrNoPCLNTab
|
|
}
|
|
|
|
// searchSectionForTab looks for the PCLN table within the section.
|
|
func searchSectionForTab(secData []byte) ([]byte, error) {
|
|
// First check for the current magic used. If this fails, it could be
|
|
// an older version. So check for the old header.
|
|
MAGIC_LOOP:
|
|
for _, magic := range [][]byte{pclntab120magic, pclntab118magic, pclntab116magic, pclntab12magic} {
|
|
off := bytes.LastIndex(secData, magic)
|
|
if off == -1 {
|
|
continue // Try other magic.
|
|
}
|
|
for off != -1 {
|
|
if off != 0 {
|
|
buf := secData[off:]
|
|
if len(buf) < 16 || buf[4] != 0 || buf[5] != 0 ||
|
|
(buf[6] != 1 && buf[6] != 2 && buf[6] != 4) || // pc quantum
|
|
(buf[7] != 4 && buf[7] != 8) { // pointer size
|
|
// Header doesn't match.
|
|
if off-1 <= 0 {
|
|
continue MAGIC_LOOP
|
|
}
|
|
off = bytes.LastIndex(secData[:off-1], magic)
|
|
continue
|
|
}
|
|
// Header match
|
|
return secData[off:], nil
|
|
}
|
|
break
|
|
}
|
|
}
|
|
return nil, ErrNoPCLNTab
|
|
}
|