// Copyright 2022 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.

//go:build go1.18
// +build go1.18

package buildinfo

// This file adds to buildinfo the functionality for extracting the PCLN table.

import (
	"debug/elf"
	"debug/macho"
	"debug/pe"
	"encoding/binary"
	"errors"
	"fmt"
	"io"
)

// ErrNoSymbols represents non-existence of symbol
// table in binaries supported by buildinfo.
var ErrNoSymbols = errors.New("no symbol section")

// SymbolInfo is derived from cmd/internal/objfile/elf.go:symbols, symbolData.
func (x *elfExe) SymbolInfo(name string) (uint64, uint64, io.ReaderAt, error) {
	sym, err := x.lookupSymbol(name)
	if err != nil || sym == nil {
		if errors.Is(err, elf.ErrNoSymbols) {
			return 0, 0, nil, ErrNoSymbols
		}
		return 0, 0, nil, fmt.Errorf("no symbol %q", name)
	}
	prog := x.progContaining(sym.Value)
	if prog == nil {
		return 0, 0, nil, fmt.Errorf("no Prog containing value %d for %q", sym.Value, name)
	}
	return sym.Value, prog.Vaddr, prog.ReaderAt, nil
}

func (x *elfExe) lookupSymbol(name string) (*elf.Symbol, error) {
	x.symbolsOnce.Do(func() {
		syms, err := x.f.Symbols()
		if err != nil {
			x.symbolsErr = err
			return
		}
		x.symbols = make(map[string]*elf.Symbol, len(syms))
		for _, s := range syms {
			s := s // make a copy to prevent aliasing
			x.symbols[s.Name] = &s
		}
	})
	if x.symbolsErr != nil {
		return nil, x.symbolsErr
	}
	return x.symbols[name], nil
}

func (x *elfExe) progContaining(addr uint64) *elf.Prog {
	for _, p := range x.f.Progs {
		if addr >= p.Vaddr && addr < p.Vaddr+p.Filesz {
			return p
		}
	}
	return nil
}

const go12magic = 0xfffffffb
const go116magic = 0xfffffffa

// PCLNTab is derived from cmd/internal/objfile/elf.go:pcln.
func (x *elfExe) PCLNTab() ([]byte, uint64) {
	var offset uint64
	text := x.f.Section(".text")
	if text != nil {
		offset = text.Offset
	}
	pclntab := x.f.Section(".gopclntab")
	if pclntab == nil {
		// Addition: this code is added to support some form of stripping.
		pclntab = x.f.Section(".data.rel.ro.gopclntab")
		if pclntab == nil {
			pclntab = x.f.Section(".data.rel.ro")
			if pclntab == nil {
				return nil, 0
			}
			// Possibly the PCLN table has been stuck in the .data.rel.ro section, but without
			// its own section header. We can search for for the start by looking for the four
			// byte magic and the go magic.
			b, err := pclntab.Data()
			if err != nil {
				return nil, 0
			}
			// TODO(rolandshoemaker): I'm not sure if the 16 byte increment during the search is
			// actually correct. During testing it worked, but that may be because I got lucky
			// with the binary I was using, and we need to do four byte jumps to exhaustively
			// search the section?
			for i := 0; i < len(b); i += 16 {
				if len(b)-i > 16 && b[i+4] == 0 && b[i+5] == 0 &&
					(b[i+6] == 1 || b[i+6] == 2 || b[i+6] == 4) &&
					(b[i+7] == 4 || b[i+7] == 8) {
					// Also check for the go magic
					leMagic := binary.LittleEndian.Uint32(b[i:])
					beMagic := binary.BigEndian.Uint32(b[i:])
					switch {
					case leMagic == go12magic:
						fallthrough
					case beMagic == go12magic:
						fallthrough
					case leMagic == go116magic:
						fallthrough
					case beMagic == go116magic:
						return b[i:], offset
					}
				}
			}
		}
	}
	b, err := pclntab.Data()
	if err != nil {
		return nil, 0
	}
	return b, offset
}

// SymbolInfo is derived from cmd/internal/objfile/pe.go:findPESymbol, loadPETable.
func (x *peExe) SymbolInfo(name string) (uint64, uint64, io.ReaderAt, error) {
	sym, err := x.lookupSymbol(name)
	if err != nil {
		return 0, 0, nil, err
	}
	if sym == nil {
		return 0, 0, nil, fmt.Errorf("no symbol %q", name)
	}
	sect := x.f.Sections[sym.SectionNumber-1]
	// In PE, the symbol's value is the offset from the section start.
	return uint64(sym.Value), 0, sect.ReaderAt, nil
}

func (x *peExe) lookupSymbol(name string) (*pe.Symbol, error) {
	x.symbolsOnce.Do(func() {
		x.symbols = make(map[string]*pe.Symbol, len(x.f.Symbols))
		if len(x.f.Symbols) == 0 {
			x.symbolsErr = ErrNoSymbols
			return
		}
		for _, s := range x.f.Symbols {
			x.symbols[s.Name] = s
		}
	})
	if x.symbolsErr != nil {
		return nil, x.symbolsErr
	}
	return x.symbols[name], nil
}

// PCLNTab is derived from cmd/internal/objfile/pe.go:pcln.
// Assumes that the underlying symbol table exists, otherwise
// it might panic.
func (x *peExe) PCLNTab() ([]byte, uint64) {
	var textOffset uint64
	for _, section := range x.f.Sections {
		if section.Name == ".text" {
			textOffset = uint64(section.Offset)
			break
		}
	}

	var start, end int64
	var section int
	if s, _ := x.lookupSymbol("runtime.pclntab"); s != nil {
		start = int64(s.Value)
		section = int(s.SectionNumber - 1)
	}
	if s, _ := x.lookupSymbol("runtime.epclntab"); s != nil {
		end = int64(s.Value)
	}
	if start == 0 || end == 0 {
		return nil, 0
	}
	offset := int64(x.f.Sections[section].Offset) + start
	size := end - start

	pclntab := make([]byte, size)
	if _, err := x.r.ReadAt(pclntab, offset); err != nil {
		return nil, 0
	}
	return pclntab, textOffset
}

// SymbolInfo is derived from cmd/internal/objfile/macho.go:symbols.
func (x *machoExe) SymbolInfo(name string) (uint64, uint64, io.ReaderAt, error) {
	sym, err := x.lookupSymbol(name)
	if err != nil {
		return 0, 0, nil, err
	}
	if sym == nil {
		return 0, 0, nil, fmt.Errorf("no symbol %q", name)
	}
	seg := x.segmentContaining(sym.Value)
	if seg == nil {
		return 0, 0, nil, fmt.Errorf("no Segment containing value %d for %q", sym.Value, name)
	}
	return sym.Value, seg.Addr, seg.ReaderAt, nil
}

func (x *machoExe) lookupSymbol(name string) (*macho.Symbol, error) {
	const mustExistSymbol = "runtime.main"
	x.symbolsOnce.Do(func() {
		x.symbols = make(map[string]*macho.Symbol, len(x.f.Symtab.Syms))
		for _, s := range x.f.Symtab.Syms {
			s := s // make a copy to prevent aliasing
			x.symbols[s.Name] = &s
		}
		// In the presence of stripping, the symbol table for darwin
		// binaries will not be empty, but the program symbols will
		// be missing.
		if _, ok := x.symbols[mustExistSymbol]; !ok {
			x.symbolsErr = ErrNoSymbols
		}
	})

	if x.symbolsErr != nil {
		return nil, x.symbolsErr
	}
	return x.symbols[name], nil
}

func (x *machoExe) segmentContaining(addr uint64) *macho.Segment {
	for _, load := range x.f.Loads {
		seg, ok := load.(*macho.Segment)
		if ok && seg.Addr <= addr && addr <= seg.Addr+seg.Filesz-1 && seg.Name != "__PAGEZERO" {
			return seg
		}
	}
	return nil
}

// SymbolInfo is derived from cmd/internal/objfile/macho.go:pcln.
func (x *machoExe) PCLNTab() ([]byte, uint64) {
	var textOffset uint64
	text := x.f.Section("__text")
	if text != nil {
		textOffset = uint64(text.Offset)
	}
	pclntab := x.f.Section("__gopclntab")
	if pclntab == nil {
		return nil, 0
	}
	b, err := pclntab.Data()
	if err != nil {
		return nil, 0
	}
	return b, textOffset
}
