powerpc

package module
v0.0.1 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Apr 11, 2022 License: MIT Imports: 5 Imported by: 1

README

powerpc

A simple library to handle PowerPC instruction encoding, and to enable patching ranges of a binary. This allows simple reproduction of patches to a channel - perhaps ones downloaded via NUS.

Consider this example of a patch:

example := PatchSet{
	// A name describing this patch.
	Name: "Nullify access check",
	// The offset of the function in the binary - i.e. the DOL.
	AtOffset: 57236,

	// Instructions present previously.
	// In this example, we have a generic function prolog.
	Before: Instructions{
		STWU(R1, R1, 0xFC10),
	}.Bytes(),
	// Instructions present afterwards.
	// They must match the same length as what they are replacing.
	// In this example, we immediately return.
	After: Instructions{
		BLR(),
	}.Bytes(),
}
patched, err := ApplyPatch(example, binary)

You additionally have the option to use PatchSets, collections of patches that may be related to each other. Consider the following scenario:

example := PatchSet{
	Name: "Change domains",

	Patches: []Patch{
		Patch{
			Name: "Remove domain whitelist",
				// [...]
			},
			Patch{
				Name: "Use custom domain",
				// [...]
			},
		},
}
patched, err := ApplyPatchSet(example, binary)

It is recommended to import this package without a prefix in order to permit easier usage of instruction types. An example doing this is as follows:

import (
	. "github.com/wii-tools/powerpc"
)

Wishlist

  • Implement more instructions forms.
  • Use type constraints within structs to allow both byte and Instruction slices.

Resources

Documentation

Index

Constants

View Source
const (
	R0 = iota
	R1
	R2
	R3
	R4
	R5
	R6
	R7
	R8
	R9
	R10
	R11
	R12
	R13
	R14
	R15
	R16
	R17
	R18
	R19
	R20
	R21
	R22
	R23
	R24
	R25
	R26
	R27
	R28
	R29
	R30
	R31
)

Variables

View Source
var (
	ErrInconsistentPatch = errors.New("before and after data present within file are not the same size")
	ErrPatchOutOfRange   = errors.New("patch cannot be applied past binary size")
	ErrInvalidPatch      = errors.New("before data present within patch did not exist in file")
)

Functions

func ApplyPatch

func ApplyPatch(patch Patch, binary []byte) ([]byte, error)

ApplyPatch applies the given patch to the given binary.

func ApplyPatchSet

func ApplyPatchSet(set PatchSet, binary []byte) ([]byte, error)

ApplyPatchSet applies a set of patches to a binary, noting their name.

func EmptyBytes

func EmptyBytes(length int) []byte

EmptyBytes returns an empty byte array of the given length. It is useful when creating a patch with an original value of none.

Types

type Bits

type Bits [8]bool

Bits represents bits for a byte. If set, considered as 1. If not, 0.

type Instruction

type Instruction [4]byte

Instruction represents a 4-byte PowerPC instruction.

var Padding Instruction = [4]byte{0x00, 0x00, 0x00, 0x00}

Padding is not an actual instruction - it represents 4 zeros.

func ADDI

func ADDI(rT Register, rA Register, value uint16) Instruction

ADDI represents the addi PowerPC instruction.

func ADDIS

func ADDIS(rT Register, rA Register, value uint16) Instruction

ADDIS represents the addis PowerPC instruction.

func B

func B(current uint, target uint) Instruction

B represents the b PowerPC instruction. It calculates the offset from the given current address and the given target address, and then branches.

func BL

func BL(current uint, target uint) Instruction

BL represents the bl PowerPC instruction. It calculates the offset from the given current address and the given target address, saving the current address in the link register. It then branches.

func BLR

func BLR() Instruction

BLR represents the blr mnemonic on PowerPC.

func BNE

func BNE(current uint, target uint) Instruction

BNE represents the bne PowerPC instruction. It calculates the offset from the given current address and the given target address, and then branches.

func CMPWI

func CMPWI(rA Register, value uint16) Instruction

CMPWI represents the cmpwi mnemonic for PowerPC. It does not support any other CR fields asides from 0.

func CRXOR

func CRXOR() Instruction

CRXOR represents a common use of CRXOR on PowerPC. TODO: actually implement

func EIEIO

func EIEIO() Instruction

EIEIO represents the eieio PowerPC instruction.

func EncodeInstrBForm

func EncodeInstrBForm(opcode byte, BO Register, BI Register, BD [3]byte, AA bool, LK bool) Instruction

EncodeInstrBForm handles encoding a given opcode, BO, BI, BD, AA and LK. I-form assumes:

  • 6 bits for the opcode
  • 5 bits for BO
  • 5 bits for BI
  • 24 bits for BD
  • 1 bit for absolute (AA)
  • 1 bit for should store in link register (LK)

func EncodeInstrDForm

func EncodeInstrDForm(opcode byte, rT Register, rA Register, value uint16) Instruction

EncodeInstrDForm handles encoding a given opcode, RT, RA and SI. D-form assumes:

  • 6 bits for the opcode
  • 5 for rT
  • 5 for rA
  • 16 for SI

func EncodeInstrIForm

func EncodeInstrIForm(opcode byte, LI [3]byte, AA bool, LK bool) Instruction

EncodeInstrIForm handles encoding a given opcode, LI, AA and LK. I-form assumes:

  • 6 bits for the opcode
  • 24 bits for LI
  • 1 bit for absolute (AA)
  • 1 bit for should store in link register (LK)

func EncodeInstrXForm

func EncodeInstrXForm(opcode byte, rS Register, rA Register, rB Register, XO uint16, rC bool) Instruction

EncodeInstrXForm handles encoding a given opcode, rS, rA, rB, an extended opcode and rC. X-form assumes:

  • 6 bits for the opcode
  • 5 bits for rS
  • 5 bits for rA
  • 5 bits for rB
  • 10 bits for XO (extended opcode)
  • 1 bit for rC (dependent on the condition register)

func LI

func LI(rT Register, value uint16) Instruction

LI represents the li mnemonic on PowerPC.

func LIS

func LIS(rT Register, value uint16) Instruction

LIS represents the lis mnemonic on PowerPC.

func LWZ

func LWZ(rT Register, offset uint16, rA Register) Instruction

LWZ represents the lwz PowerPC instruction.

func MFSPR

func MFSPR() Instruction

MFSPR is a hack, hardcoding r0, LR. TODO(spotlightishere): actually encode this

func MTSPR

func MTSPR() Instruction

MTSPR is a hack, hardcoding LR, r0. TODO(spotlightishere): actually encode this

func NOP

func NOP() Instruction

NOP represents the nop mnemonic for PowerPC.

func OR

func OR(rS Register, rA Register, rB Register, rC bool) Instruction

OR represents the or PowerPC instruction.

func ORI

func ORI(rS Register, rA Register, value uint16) Instruction

ORI represents the ori PowerPC instruction.

func STH

func STH(rS Register, offset uint16, rA Register) Instruction

STH represents the sth PowerPC instruction.

func STW

func STW(rS Register, offset uint16, rA Register) Instruction

STW represents the stw PowerPC instruction.

func STWU

func STWU(rS Register, rA Register, offset uint16) Instruction

STWU represents the stwu PowerPC instruction.

func SUBI

func SUBI(rT Register, rA Register, value uint16) Instruction

SUBI represents the subi mnemonic on PowerPC. TODO: handle negative values properly?

func SYNC

func SYNC() Instruction

SYNC is a hack, hardcoding sync 0. TODO(spotlightishere): actually encode this

type Instructions

type Instructions []Instruction

Instructions represents a group of PowerPC instructions.

func (Instructions) Bytes

func (i Instructions) Bytes() []byte

Bytes returns the represented bytes of these instructions.

As PowerPC has a fixed-width instruction set, the returned size will always be in a multiple of four.

type Patch

type Patch struct {
	// Name is an optional name for this patch.
	// If present, its name will be logged upon application.
	Name string

	// AtOffset is the offset within the file this patch should be applied at.
	// If not present, the patch will be recursively applied across the entire file.
	// Relying on this behavior is highly discouraged, as it may damage other parts of the binary
	// if gone unchecked.
	AtOffset int

	// Before is an array of the bytes to find for, i.e. present within the original file.
	Before []byte

	// After is an array of the bytes to replace with.
	After []byte
}

Patch represents a patch applied to the main binary.

type PatchSet

type PatchSet struct {
	// Name is an optional name for this patch.
	// If present, its name will be logged upon application.
	Name string

	// Patches is a slice of patches to apply to the given binary.
	Patches []Patch
}

PatchSet represents multiple patches available to be applied. This is most useful when you have a collection of related patches.

type Register

type Register byte

Register represents a value for a PowerPC register.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL