================================================================================
B A S T A R D                                            disassembly environment



Intro...
Well, this is going to double as a manual as well.

================================================================================
 QuickStart

/* note: wrap this in .sc or in shell */
./bastard < test.in > asm.out


================================================================================
 Theory of Operation

The action all begins when LoadTarget() is used to open a file to disassemble. 
In the future, support may be provided for binary input via STDIN; this will
be made available through a command line option, and may provide the ability
to disassemble arbitrary sequences of bytes.

A .bdb directory is created in the current directory; this will contain the
database and temporary files needed during disassembly. When the database is
saved, the contents of .bdb will be tar-gz'ed into a file with a '.bdb'
extension. The target is copied to a binary image inside .bdb [1], a Target
database is created, and a record is added to the ADDRESS object table with
ADDRESS->PA = 0 and ADDRESS->size = sizeof(target). A TARGET struct is created
as well:
	struct TARGET{
		char* name,
		char* path,
		long  size,
		ADDR  entry;
	} Target;

The next step is to apply a file format structure to the file -- since an
executable is in essence a predictable structure composed of blocks of code and
data, different file formats will be considered different structures rather
than different disassembly operations. Hopefully this will the support for
future file formats more straightforward.

The structure definition will be a Seer C script containing the structure
definition, and a brief main routine for creating sections:
 /* File Format Sample ------------------------------------------------ */
	import int  FD;
	import int  read(int fd, void *buf, int count);
	import void malloc(int size);
	import void free(void* ptr);
	import void CreateSection(char* name, long start, long end, int flags);
	export main;
	struct FILEFMT{
		....
	} FileHeader;
	struct FILESEC{
		....
	} FileSection;

	void main() {
		int flags;
		char ptr = malloc( sizeof(FILEFMT) );
		read( FD, ptr, sizeof(FILEFMT));
		for (/* each section */) {
			CreateSection( Section.Name, Section.start, Section.End, flags);
		}
 /* EOF ----------------------------------------------------------------*/

As you can see, the code for parsing the header is actually part of this
script -- this allows arbitrarily complex programs or files to be ported
without recompiling the disassembler. This could be used, in theory, for
writing unpackers.

When the File Format is selected using SetFileType(), the Seer script for the
specified type is executed using a file descriptor to the binary image as a
global variable. A record is added to the SECTION table of the database for
each section created with CreateSection; likewise, an ADDRESS record is added 
and sized for the start of each section. [2]

At this point, the target can be considered 'loaded' and ready for disassembly.
There are many disassembly options available, but in general one will begin
with a disassembly of whichever section contains the program entry point, 
starting of course at that entry point:
	ADDR* EndAddr = GetSectionEnd( Target.entry );
	MakeAddress( Target.entry );
The disassembly will consist of a function which calls libopcodes to
disassemble, and a callback with which to handle the libopcodes result:
	Disassemble( ADDR addr ){
		addr = MakeAddr( long offset );
		while ( IsCode( addr )) addr = NextAddr(addr);
		if ( addr.rva < EndAddr ) {
			libOpcodes(addr.rva);
		}
	}
	CallBack( addr, char* InstrString ){
		CODE c = MakeCode( addr );
		(c.mnem, c.op1, c.op2)  split( InstrString);
		c.InsType = GetInsType( c.mnem );
		c.Op1Type = GetOpType( c.op1);
		c.Op2Type = GetOpType( c.op2);
		/* Get/Create XRefs */
		/* Make XRefs, Comment, Name, Function, Inline */
		if ( c.InsType & INST_RELOC) Disassemble( NextAddr(addr));
		else Disassemble( xref.addr );

It is up to the user/driver program to display the disassembled lines. One will
want to use PrintLine, PrintRange, PrintSection, PrintHeader, and PrintFile.
The most common method for a front-end will be to use PrintLine to get each 
line in its current display area, so that scrolls up and down need only to get
a single line at a time. An idea of how PrintFile might work:
	PrintFile(){
		for (/*each ADDRESS */){
			if (addr == GetSectionStart(addr)) PrintSectionPrefix;
			if (addr == GetFunctionStart(addr)) PrintFunctionPrefix;
			if (addr == GetInlineStart(addr)) PrintInline;
			if (IsCode(addr)){
				printf("%s %08X %s", addr.rva, addr.data, c.mnem);
				if (Op1 == OP_REG) { /*Print Reg*/}
				else if (Op1 == OP_MEM) { /*Print Mem*/}
				else if (Op1 == OP_IMM) {/*Print Immediate*/}
				/* ditto for Op2 */
				if (HasComment(addr)) { /*PrintComment*/}
			} else /* Is DATA */ {
				if ( byte ) {}
			 	else if (word) {}
				else if (dword) {}
				else {/* array */}
			}
		}		
	}

		

Notes:
	1. All of the bytes in the file must be retained in order to produce a 
	   patched version of the program, or to do a manual disassembly. As such,
	   a perfect duplicate of the original executable is stored as an image in
	   the .bdb; all address objects will consist of an offset into this image
	   and a size attribute to be used for reading data.
	2. Since a section is the only distinct block of code available at this
	   point, the start of each section is used to break the original single 
	   ADDRESS record up into smaller, component ADDRESS objects. Subsequent 
	   disassembly will use functions, structures, code, and data objects to
	   create further ADDRESS objects.

================================================================================
 Command Line Parameters
 
 bastard [-q] [-i FD] [-o FD] [-p str] [filename]
	-i [file]	-- use [file] instead of STDIN
	-o [file]	-- use [file] instead of STDOUT
	-p [prompt] -- use [prompt] for interpreter prompt, e.g. "" for no prompt.
	-q			-- quite [suppress unnecessary output]
	filename	-- file or database to open

================================================================================
 Interfacing With The Bastard


================================================================================
 Scripting The Bastard

 [basically a discussion of seer and such]


================================================================================
 The Bastard API

 This is intended too be used by a controlling process, or Seer scripts.




 Loading
 =======
 LoadTarget( filename );
 LoadDB( filename );
 	Thankfully this can be sent right to typhoon!
 SetCPUType( char? type);
 	Used to pass info to libopcodes/BFD
 SetFileType( char* type );
 	Check to make sure file type is not already set!
	This function will either 
		1) call a macro file specific to the file type, which parses the
		   header and creates a Section for each, ah, section
		2) open a file format definition in $BASTARD/formats and apply it,
		   creating sections and such as necessary
	Option1 is more flexible, but requires macro support

 Saving
 ======
 SaveDB( filename );
 SaveAsASM( filename );
 SaveAsDiff( filename );
 	Compares with original target and produces a binary diff. If original
	moves, this will not work -- no sense saving changed bytes.
 SaveAsBinary( filename );
  	Moves the binary image used to store the actual program bytes into
	the named location. Does not *really* do anything :)
 	
 Sections
 ========
 PrintHeader();
 	Based on Target info
 CreateSection( name, start, end, perms );
 	e.g. for ELF->num_sections CreateSection(...)
    This routine must check that start/end are less than other
	sections
	NB: we need a global error string/code for shit like this
 DeleteSection( name );
 	This will increase the end addr of the previous section through curr->end
 GetSectionStart ( addr );	
 GetSectionEnd (addr );
 GetSectionName( addr );
 GetSectionPerms( addr );
 SetSectionStart( addr );
 SetSectionEnd( addr );
 SetSectionName( addr );
 SetsectionPerms( addr );

 Disassembly
 ===========
 DisassembleFull();
 	This will disassemble all code sections, label data sections, create
	names and xrefs, and so forth. Just like IDA.
 DisassembleSection( name );
 	Must have 'if code/data/other' info
 DisassembleRange( start, end);
 	Calls libopcodes and only records opcodes within the specified range.
	This is a linear [not flow of execution] disassembly.
 DisassembleForward( addr );
 	Does flow-of execution disassembly using addr as the 'entry point'

In initial versions, DisassembleFull() will iterate through each section, and 
will call DisassembleSection() for each section with execute permissions.
Later, DisassembleFull() will iterate through entry points, and will call
DisassembleForward() for each entry point. This second method will provide an
IDA-style disassembly, where portions of each section might not be
disassembled.

It might be advisable in the future to call DisassembleSection() first, then to
call DisassembleForward for each entry point to 'repair' disassembly done by
the unassuming DisassembleSection() calls -- or to call DisassembleRange() for
each series of addresses in an executable section that is not associated with a 
code object.

Addresses
=========
 PrintAddress( addr );
 	Prints code or data representation to output FD
 GetPhysicalAddress( addr );
 	i.e. offset from start of file
 GetRVA( addr );
 GetAddrType( addr );
 	returns addr->type
 GetAddrSize( addr);
 MakeCode( addr );
 	Link addr to a code object and disassemble 1 instruction
 MakeData( addr, size );
 	Code and data are considered toggles -- to unmake code, you make it data
 	Note that MakeData provides a size attr -- it is up to the front-end to
	display this as a byte, word, dword, or array
 GetName( addr, char* );
 	NULL == no name;
 SetName( addr, char* );
 GetComment( addr, char* );
 SetComment( addr, char* );
 GetRefsTo( addr );
 GetRefsFrom( addr );
 	...these two have variable return values: an array?
	Maybe a get first, get next xref function?
	e.g. while( GetNextXref( addr, xref);
 JumpTo( addr );
 	use this to follow xrefs
 GetNextAddr( addr );
 GetPrevAddr( addr );
 GetNextCode( addr );
 	Gets next code item in sequence
 GetPrevCode( addr );
 GetBranchCode( addr );
 	Gets next code item from a JMP/JCC
 GetNextData( addr );
 GetPrevData( addr );

Code
====
	GetCode( addr );
		Gets code object for an addr if it exists
	GetCodeRep( addr );
		Returns a basic [INTEL fmt] representation of the line of code
	GetMnemonic( code );
	GetOp1( code );
	GetOp2( code );
	GetInstType( code );
	GetOp1Type( code );
	GetOp2Type( code );
	GetFlags( code );
	
Strings
=======

Imports
=======

Exports
=======

Structures
==========
	LoadStructure( char*, name);
	ApplyStructure( name, addr );

Functions
=========
 MakeFunction();
 NameFunction();
 SetFunctionComment();
 GetFunctionComment();
 GetFunctionStart();
 GetFunctionEnd();
 GetFunctionPrototype();
 	A type of comment
 SetFunctionPrototype();
 MakeInlineFunction( addr, name );
 ApplyInlineFunction( name );
 	consider these to be 'structs' for code...
 
Constants
=========
 DefineConstant( char*, long );
 UnDefineConstants( char* );
 GetConstVal( char* );
 GetConstName( long );

Macros
======
 DefineMacro
 RecordMacro
 UndefineMacro
 RunMacro
 RunScript
 	A Script is assumed to be macros saved in a Seer-style script

System Interaction
==================
 Exec
 Quit
 Core
 Panic
 LaunchTargetInGDB
 	If we do this, it should take an addr arg to BP as a parameter

 
================================================================================
 Database Structure


   SECTION     -- Distinct regions of code or data within the program
		ulong ID,
		char *name[ ];
		int type,
		ADDRESS* start,
		long size,
		void *header,
		int permissions;
   ADDRESS     -- Distinct code or data units within the program
		ulong ID,
		long RVA,
		long PA, //physical addr
		char * name[ ],
		long type, //code, data
		long size,
		long flags, 
		void * data,
		COMMENT * comment,
   XREF       -- References to code/data 
   		ulong ID;
		ADDRESS * from,
		ADDRESS * to,
		int type;
   CODE        -- An address object interpreted as a machine instruction
		ulong ID,
		ADDRESS * address,
		int Type,
		char* mnemonic,
		char* op1,
		char*  op2,
		int op1Type,
		int op2Type,
		long flags,
   EXPORT      -- Program Entry Points
		ulong ID,
		ADDRESS * addr,
   IMPORT      -- External code references in the program
		ulong ID,
		ADDRESS * addr,
   STRING      -- Data regions considered strings
		ulong ID,
		ADDRESS * addr,
		long size,
		NAME * name;
   NAME        -- Unique text strings associated with address objects
		ulong ID,
		ADDRESS * addr,
		char * string,
   COMMENT     -- Text strings associated with address objects
		ulong ID,
		char * comment[];
   FUNCTION    -- Code regions defined as a function
		ulong ID,
		ADDRESS * start,
		ADDRESS * end,
		NAME * name,
   INLINE      -- Code regions associated with C macro/inline function
		ulong ID,
		NAME * name,
		long * size
   STRUCTURE   -- Data regions associated with a defined structure
		ulong ID,
		NAME * name,
		long size,
		char * filename,
   CONSTANT    -- User-defined enumerations [from .h files]
		ulong ID,
		NAME * name,
		long value,
   MACRO       -- User-defined EiC macros [char strings]
		ulong ID,
		char * name,
		char * code,

================================================================================
Responsible Parties
