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

// Parsing of XCOFF executable (AIX)

package objfile

import (
	"debug/dwarf"
	"fmt"
	"internal/xcoff"
	"io"
	"unicode"
)

type xcoffFile struct {
	xcoff *xcoff.File
}

func openXcoff(r io.ReaderAt) (rawFile, error) {
	f, err := xcoff.NewFile(r)
	if err != nil {
		return nil, err
	}
	return &xcoffFile{f}, nil
}

func (f *xcoffFile) symbols() ([]Sym, error) {
	var syms []Sym
	for _, s := range f.xcoff.Symbols {
		const (
			N_UNDEF = 0  // An undefined (extern) symbol
			N_ABS   = -1 // An absolute symbol (e_value is a constant, not an address)
			N_DEBUG = -2 // A debugging symbol
		)
		sym := Sym{Name: s.Name, Addr: s.Value, Code: '?'}

		switch s.SectionNumber {
		case N_UNDEF:
			sym.Code = 'U'
		case N_ABS:
			sym.Code = 'C'
		case N_DEBUG:
			sym.Code = '?'
		default:
			if s.SectionNumber < 0 || len(f.xcoff.Sections) < int(s.SectionNumber) {
				return nil, fmt.Errorf("invalid section number in symbol table")
			}
			sect := f.xcoff.Sections[s.SectionNumber-1]

			// debug/xcoff returns an offset in the section not the actual address
			sym.Addr += sect.VirtualAddress

			if s.AuxCSect.SymbolType&0x3 == xcoff.XTY_LD {
				// The size of a function is contained in the
				// AUX_FCN entry
				sym.Size = s.AuxFcn.Size
			} else {
				sym.Size = s.AuxCSect.Length
			}

			sym.Size = s.AuxCSect.Length

			switch sect.Type {
			case xcoff.STYP_TEXT:
				if s.AuxCSect.StorageMappingClass == xcoff.XMC_RO {
					sym.Code = 'R'
				} else {
					sym.Code = 'T'
				}
			case xcoff.STYP_DATA:
				sym.Code = 'D'
			case xcoff.STYP_BSS:
				sym.Code = 'B'
			}

			if s.StorageClass == xcoff.C_HIDEXT {
				// Local symbol
				sym.Code = unicode.ToLower(sym.Code)
			}

		}
		syms = append(syms, sym)
	}

	return syms, nil
}

func (f *xcoffFile) pcln() (textStart uint64, symtab, pclntab []byte, err error) {
	if sect := f.xcoff.Section(".text"); sect != nil {
		textStart = sect.VirtualAddress
	}
	if pclntab, err = loadXCOFFTable(f.xcoff, "runtime.pclntab", "runtime.epclntab"); err != nil {
		return 0, nil, nil, err
	}
	if symtab, err = loadXCOFFTable(f.xcoff, "runtime.symtab", "runtime.esymtab"); err != nil {
		return 0, nil, nil, err
	}
	return textStart, symtab, pclntab, nil
}

func (f *xcoffFile) text() (textStart uint64, text []byte, err error) {
	sect := f.xcoff.Section(".text")
	if sect == nil {
		return 0, nil, fmt.Errorf("text section not found")
	}
	textStart = sect.VirtualAddress
	text, err = sect.Data()
	return
}

func findXCOFFSymbol(f *xcoff.File, name string) (*xcoff.Symbol, error) {
	for _, s := range f.Symbols {
		if s.Name != name {
			continue
		}
		if s.SectionNumber <= 0 {
			return nil, fmt.Errorf("symbol %s: invalid section number %d", name, s.SectionNumber)
		}
		if len(f.Sections) < int(s.SectionNumber) {
			return nil, fmt.Errorf("symbol %s: section number %d is larger than max %d", name, s.SectionNumber, len(f.Sections))
		}
		return s, nil
	}
	return nil, fmt.Errorf("no %s symbol found", name)
}

func loadXCOFFTable(f *xcoff.File, sname, ename string) ([]byte, error) {
	ssym, err := findXCOFFSymbol(f, sname)
	if err != nil {
		return nil, err
	}
	esym, err := findXCOFFSymbol(f, ename)
	if err != nil {
		return nil, err
	}
	if ssym.SectionNumber != esym.SectionNumber {
		return nil, fmt.Errorf("%s and %s symbols must be in the same section", sname, ename)
	}
	sect := f.Sections[ssym.SectionNumber-1]
	data, err := sect.Data()
	if err != nil {
		return nil, err
	}
	return data[ssym.Value:esym.Value], nil
}

func (f *xcoffFile) goarch() string {
	switch f.xcoff.TargetMachine {
	case xcoff.U802TOCMAGIC:
		return "ppc"
	case xcoff.U64_TOCMAGIC:
		return "ppc64"
	}
	return ""
}

func (f *xcoffFile) loadAddress() (uint64, error) {
	return 0, fmt.Errorf("unknown load address")
}

func (f *xcoffFile) dwarf() (*dwarf.Data, error) {
	return f.xcoff.DWARF()
}
