disassembly

package
v0.14.1 Latest Latest
Warning

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

Go to latest
Published: Sep 30, 2021 License: GPL-3.0, GPL-3.0 Imports: 21 Imported by: 0

Documentation

Overview

Package disassembly coordinates the disassembly of Atari2600 (6507) cartridges.

For quick disassemblies the FromCartridge() function can be used. Debuggers will probably find it more useful however, to disassemble from the memory of an already instantiated VCS.

disasm, _ := disassembly.FromMemory(cartMem, symbols.NewTable())

The FromMemory() function takes an instance of a symbols.Table or nil. In the example above, the result of NewTable() has been used, which is fine but limits the potential of the disassembly package. For best results, the symbols.ReadSymbolsFile() function should be used (see symbols package for details). Note that the FromCartridge() function handles symbols files for you.

The Write() group of functions "print" disassambly entries of type EntryTypeBlessed only. Useful for printing static disassemblies of a cartridge but probably not much else.

The iteration types provides a convenient way of iterating of the disassembly entries. It takes care of empty entries and entries not of the correct entry type. IterateAll() in particular is useful and flexible enough for many applications.

The Grep() function provides a quick way of searching the disassembly with a scope directive. More complex search schemes can be written with the iteration types.

A Disassembly instance also keeps a reference to the symbols tables (see symbols package). The GetSymbols() function can be used to get a reference to the Symbol tables. This reference will be valid throughout the lifetime of the Disassembly instance and will "survive" calls to the FromMemory() and FromCartridge() functions.

Segmented Cartridges

The disassembly package treats small bank sized (those less than 4k) by performing the disassembly with the cartridge rooted at each origin point - in each possible segment allowed by the mapper.

Origin information is held in the mappers.BankContent type returned by the cartridge.CopyBanks() function.

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

This section is empty.

Types

type ColumnAttr added in v0.10.1

type ColumnAttr struct {
	ByteCode bool
	Cycles   bool
	Label    bool
}

ColumnAttr controls what is included in the string returned by Entry.StringColumnated().

type Disassembly

type Disassembly struct {
	Prefs *Preferences

	// symbols used to format disassembly output
	Sym symbols.Symbols

	// any cartridge coprocessor that we find
	Coprocessor *coprocessor.Coprocessor
	// contains filtered or unexported fields
}

Disassembly represents the annotated disassembly of a 6507 binary.

func FromCartridge

func FromCartridge(cartload cartridgeloader.Loader) (*Disassembly, error)

FromCartridge initialises a new partial emulation and returns a disassembly from the supplied cartridge filename. Useful for one-shot disassemblies, like the gopher2600 "disasm" mode.

func NewDisassembly added in v0.3.1

func NewDisassembly(vcs *hardware.VCS) (*Disassembly, *symbols.Symbols, error)

NewDisassembly is the preferred method of initialisation for the Disassembly type.

Also returns a reference to the disassembly's symbol table. This reference will never change over the course of the lifetime of the Disassembly type itself. ie. the returned reference is safe to use after calls to FromMemory() or FromCartrige().

func (*Disassembly) ExecutedEntry added in v0.7.1

func (dsm *Disassembly) ExecutedEntry(bank mapper.BankInfo, result execution.Result, nextAddr uint16) (*Entry, error)

ExecutedEntry creates an Entry from a cpu result that has actually been executed. When appropriate, the newly created Entry replaces the previous equivalent entry in the disassembly.

If the execution.Result was from an instruction in RAM (cartridge RAM or VCS RAM) then the newly created entry is returned but not stored anywhere in the Disassembly.

func (*Disassembly) FormatResult

func (dsm *Disassembly) FormatResult(bank mapper.BankInfo, result execution.Result, level EntryLevel) (*Entry, error)

FormatResult It is the preferred method of initialising for the Entry type. It creates a disassembly.Entry based on the bank and result information.

func (*Disassembly) FromMemory added in v0.2.1

func (dsm *Disassembly) FromMemory() error

FromMemory disassembles an existing instance of cartridge memory using a cpu with no flow control. Unlike the FromCartridge() function this function requires an existing instance of Disassembly.

Disassembly will start/assume the cartridge is in the correct starting bank.

func (*Disassembly) GetEntryByAddress

func (dsm *Disassembly) GetEntryByAddress(address uint16) (*Entry, bool)

GetEntryByAddress returns the disassembly entry at the specified bank/address. a returned value of nil indicates the entry is not in the cartridge; this will usually mean the address is in main VCS RAM.

also returns whether cartridge is currently working from another source meaning that the disassembly entry might not be reliable.

func (*Disassembly) Grep

func (dsm *Disassembly) Grep(output io.Writer, scope GrepScope, search string, caseSensitive bool) error

Grep searches the disassembly for the specified search string.

func (*Disassembly) IterateBlessed added in v0.10.1

func (dsm *Disassembly) IterateBlessed(output io.Writer, f func(*Entry) string) error

IterateBlessed visits every entry in the disassembly optionally writing to output. This will very often be more convenient that looping over IterateBanks and IterateEntries.

Entries can be filtered with function f(). Strings returned from the filter function will be trimmed of trailing newline characters. Strings of length greater than zero thereafter, will be written to output.

The string returned by the filter function can be multiline if required.

If no output is required and all the necessary work is done in the filter function then an io.Writer value of nil is acceptable.

If the io.Writer value is not nil then a sequential list of entries returned by the filter function. The sequnce of entries will be in bank and address order.

Banks will be labelled (with a header) if output has been written for that bank. For example:

--- Bank 2 ---

entry
entry

--- Bank 5 ---

entry

In this example there are no filtered entries for banks 0, 1, 3 or 4. There are entries for banks 2 and 5 so those entries have a header indicating the bank.

func (*Disassembly) NewBanksIteration added in v0.10.1

func (dsm *Disassembly) NewBanksIteration() *IterateBanks

NewBanksIteration is the preferred method of initialisation for the IterateCart type.

func (*Disassembly) NewEntriesIteration added in v0.10.1

func (dsm *Disassembly) NewEntriesIteration(minLevel EntryLevel, bank int, focusAddr ...uint16) (*IterateEntries, error)

NewEntriesIteration initialises a new iteration of a dissasembly bank. The minLevel argument specifies the minimum entry level which should be returned in the iteration. So, using the following as a guide:

dead < decoded < blessed

Specifying a minLevel of EntryLevelDecode will iterate *only* entries of EntryLevelDecode. A minLevel of EntryLevelNaive on the other hand, will iterate through entries of EntryLevelNaive *and* EntryLevelDecode. A minLevel of EntryLevelDead will iterate through *all* Entries.

The final argument, focusAddr, specifies the addresses that must be included in the iteration regardless of EntryLevel. Can be left empty.

func (*Disassembly) Write

func (dsm *Disassembly) Write(output io.Writer, attr ColumnAttr) error

Write the entire disassembly to io.Writer.

func (*Disassembly) WriteAddr added in v0.10.1

func (dsm *Disassembly) WriteAddr(output io.Writer, attr ColumnAttr, addr uint16) error

WriteAddr writes the disassembly of the specified address to the io.Writer.

func (*Disassembly) WriteBank

func (dsm *Disassembly) WriteBank(output io.Writer, attr ColumnAttr, bank int) error

WriteBank writes the disassembly of the selected bank to io.Writer.

type Entry

type Entry struct {

	// the level of reliability of the information in the Entry
	Level EntryLevel

	// execution.Result does not specify which bank the instruction is from
	// because that information isn't available to the CPU. we note it here if
	// possible.
	Bank mapper.BankInfo

	// copy of the CPU execution. must not be updated except through
	// updateExecutionEntry() function
	Result execution.Result

	// string representations of information in execution.Result. GetField()
	// will apply white-space padding and should be preferred in most
	// instances.
	Label    Label
	Bytecode string
	Address  string
	Operator string
	Operand  Operand

	// formatted cycles information from instructions.Defintion
	DefnCycles string

	// actual number of cycles. consider using Cycles() for presentation
	// purposes
	ActualCycles string

	// information about the most recent execution of the entry
	//
	// should be empty if EntryLevel != EntryLevelExecuted
	ExecutionNotes string
	// contains filtered or unexported fields
}

Entry is a disassambled instruction. The constituent parts of the disassembly. It is a representation of execution.Instruction.

func (*Entry) Cycles added in v0.7.1

func (e *Entry) Cycles() string

Cycles returns the number of cycles annotated if actual cycles differs from the number of cycles in the definition. for executed branch instructions this will always be the case.

func (*Entry) GetField added in v0.7.1

func (e *Entry) GetField(field Field) string

GetField returns the formatted field from the speficied Entry.

func (*Entry) String added in v0.2.1

func (e *Entry) String() string

String returns a very basic representation of an Entry. Provided for convenience. Probably not of any use except for the simplest of tools.

See StringColumnated() for a fancier option.

func (*Entry) StringColumnated added in v0.10.1

func (e *Entry) StringColumnated(attr ColumnAttr) string

StringColumnated returns a columnated string representation of the Entry.

Trailing newline is not included. However, if attr.Label is true then a newline will be added after any label.

type EntryLevel

type EntryLevel int

EntryLevel describes the level of the Entry.

const (
	EntryLevelUnmappable EntryLevel = iota
	EntryLevelDecoded
	EntryLevelBlessed
	EntryLevelExecuted
)

List of valid EntryL in increasing reliability.

Decoded entries have been decoded as though every byte point is a valid instruction. Blessed entries meanwhile take into consideration the preceding instruction and the number of bytes it would have consumed.

Decoded entries are useful in the event of the CPU landing on an address that didn't look like an instruction at disassembly time.

Blessed instructions are deemed to be more accurate because they have been reached according to the flow of the instructions from the start address.

For normal debugging operations there is no need to use EntryLevelUnused outside of the disassembly package. It used for the unusual case where a bank is not able to be referenced from the Entry address. See M-Network for an example of this, where Bank 7 cannot be mapped to the lower segment.

type Field

type Field int

Field identifies which part of the disassmbly entry is of interest.

const (
	FldLabel Field = iota
	FldBytecode
	FldAddress
	FldOperator
	FldOperand
	FldCycles
	FldNotes
)

List of valid fields.

type GrepScope

type GrepScope int

GrepScope limits the scope of the search.

const (
	GrepAll GrepScope = iota
	GrepOperator
	GrepOperand
)

List of available scopes.

type IterateBanks added in v0.10.1

type IterateBanks struct {

	// number of banks in cart iteration
	BankCount int
	// contains filtered or unexported fields
}

IterateBanks faciliates traversal over all the banks in a cartridge.

func (*IterateBanks) Next added in v0.10.1

func (citr *IterateBanks) Next() (int, bool)

The next bank in the cartidge. Returns (-1, false) if there are no more banks.

func (*IterateBanks) Start added in v0.10.1

func (citr *IterateBanks) Start() (int, bool)

Start new iteration from the first bank.

type IterateEntries added in v0.10.1

type IterateEntries struct {

	// address the iteration is focused on. this entry will be included event
	// if the EntryLevel does not meet the minimum level
	FocusAddr []uint16

	// the iteration count at which the first entry in FocusAddr will be found
	FocusAddrCt int

	// total number of entries in iteration with the specified minimum level
	EntryCount int

	// the number of those entries with a label
	LabelCount int
	// contains filtered or unexported fields
}

IterateEntries iterates over all entries in a cartridge bank.

Instances of Entry returned by Start(), Next() and SkipNext() are copies of the disassembly entry, so the Iterate mechanism is suitable for use in a goroutine different to that which is handling (eg. updating) the disassembly itslef.

func (*IterateEntries) Next added in v0.10.1

func (eitr *IterateEntries) Next() (int, *Entry)

Next entry in the disassembly of the previously specified type.

Returns (-1, nil) if end of disassembly has been reached.

func (*IterateEntries) SkipNext added in v0.10.1

func (eitr *IterateEntries) SkipNext(n int, skipLabels bool) (int, *Entry)

SkipNext n entries and return that Entry. An n value of < 0 returns the most recent value in the iteration

The skipLabels argument indicates that an entry with a label should count as two entries. This is useful for the sdlimgui disassembly window's list clipper (and maybe nothing else).

Returns (-1, nil) if end of disassembly has been reached.

func (*IterateEntries) Start added in v0.10.1

func (eitr *IterateEntries) Start() (int, *Entry)

Start new iteration from the first instance of the EntryLevel specified in NewEntriesIteration.

type Label added in v0.7.1

type Label struct {
	// contains filtered or unexported fields
}

Label implements the Stringer interface. The String() implementation returns any address label for the entry. Use GetField() function for a white-space padded label.

func (Label) String added in v0.7.1

func (l Label) String() string

type Operand added in v0.7.1

type Operand struct {
	// contains filtered or unexported fields
}

Operand implements the Stringer interface. The String() implementation returns the operand (with symbols if appropriate). Use GetField function for white-space padded operand string.

func (Operand) String added in v0.7.1

func (l Operand) String() string

type Preferences added in v0.3.1

type Preferences struct {

	// whether to apply the high mirror bits to the displayed address
	FxxxMirror prefs.Bool
	Symbols    prefs.Bool
	// contains filtered or unexported fields
}

func (*Preferences) Load added in v0.3.1

func (p *Preferences) Load() error

Load disassembly preferences and apply to the current disassembly.

func (*Preferences) Save added in v0.3.1

func (p *Preferences) Save() error

Save current disassembly preferences to disk.

func (*Preferences) String added in v0.3.1

func (p *Preferences) String() string

Directories

Path Synopsis
Package coprocessor is used to capture execution/disassembly information from any program running on a coprocessor that may be present in an attached VCS cartridge.
Package coprocessor is used to capture execution/disassembly information from any program running on a coprocessor that may be present in an attached VCS cartridge.
Package symbols helps keep track of address symbols for the currently loaded cartridge.
Package symbols helps keep track of address symbols for the currently loaded cartridge.

Jump to

Keyboard shortcuts

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