
Caveat Reader
-------------
I think most of this stuff is out of date. However, the docs in the doc/
directory are very current.


Intended Use
------------
The bastard is a disassembler which is intended to be controlled by a more
sophisticated front end [e.g. a Gtk or ncurses UI]; as such it consists
primarily of a disassembly engine for opcode decoding/analysis, and a database
of disassembled code, symbols, and comments. In the future, higher-level
decompilation features such as library/compiler signatures will be added.

When a controlling front-end launches the bastard [usually through a call to
popen(), though scripting languages can simply fork and exec], commands are
sent to the bastard via STDIN, and data is read from the bastard via STDOUT;
alternatively, a the name of a file or FIFO can be used in place of either
STDIN or STDOUT by using the -i and -o command-line switches. 

The bastard is controlled by calling its api commands; a full list of these
commands is provided in include/api.h, though a typical disassembly will look
like
   LoadTarget("/home/work/target");   //path of target is passed
	SetFileType("ELF");					  //"ELF" is a script in formats/
	SetCPUType( "i386" );				  //"i386" is a lib in arch/
	DisassembleFull();					  //DisassembleForward from entry point
Once these commands are run, the file has gone through its initial disassemble,
and may be modified or printed using a number of API commands, such as
PrintAddress(rva), GetName(rva), AddComment(rva, text), and so on. 

In order to fit in with the unix style of tools, the bastard has been designed
to work as an interpreter --in the manner of perl, gnuplot, awk, and so on-- 
and thus when launched without redirected input its built-in CLI can be used
to do disassembly. The CLI supports API calls and macros [via the SeerC
interpreter]; in addition, it has command aliases [such as "L", which provides
the four steps listed above] and incorporates the GNU readline library for
tab-completion, command line history, and line editting. Thus the bastard can
be used without any front-end at all, if desired.


Typical Operation
-----------------
The typical use of the bastard consists of four stages:
    1. Load the target
    2. Disassemble it
    3. Muck with it
    4. Print or save the results
Steps 1, 2, and 4 are of the most concern starting out; when functional, the
bastard should provide a reasonable disassembly which can be produced with
minimal effort [hence the "LOAD" or "L" command]. 

"Loading the target" consists of specifying the path of the target, choosing a
file format, and setting the CPU type; alternatively, an existing bastard
database [.bdb] can be loaded. The file type must be a script under formats/
[these are SeerC scripts which have full access to the bastard API and internal
structures]; the CPU will be loaded from a .so under the processors/ directory
when libopcodes is finally replaced with a real disassembler. Note that file
type defaults to ELF and cpu to x86 if neither are specified.

When the target is loaded, the bastard creates a ./.bdb directory and proceeds
to copy the target into this directory; the copy of the target is then memory
mapped, and a typhoon database is created in .bdb. When the target is saved,
this .bdb directory is tar/gz'ed into target.bdb; as such it contains a full
binary image of the target as well as a complete disassembly database. Note
that the typhoon files can be viewed "offline" with the dbdview utility
included in utils/.

"Disassembling the target" refers to choosing a range of the target to
disassemble -- the functions for this are DisassembleFull(),
DisassembleSection(char *name), DisassembleForward(long rva), and
DisassembleRange(long from, int size). DisassembleForward performs flow-of-
execution disassembly on the target, starting with address 'rva'; it is called
by DisassembleFull() with the target's entry point as an argument.

The disassembly performs the creation of xrefs, data items, and basic naming
of addresses based on the symbol table of the target. Further naming of
addresses, commenting, creation of structures and functions, and so forth will
be handled by the user while "mucking with the target", though primitive
attempts at these will eventually be incorporated into the actual disassembly.

"Printing or saving the target" syncs the mmap'ed file and makes a tarball of 
the .bdb directory; the .bdb dir is removed when the target is unloaded. When
saving or printing the file, the asmsprintf() function in api.c used; this 
function allows the user or front-end to specify the format of the line using
printf-like formatting codes, specifically
     %a - rva                %p - pa
     %m - mnemonic           %n - name
     %d - dest operand       %c - comment
     %s - source operand     %x - xrefs
     %b - raw bytes          %S - section
Thus asmsprintf("%a\t%m\t%s, %d\t;%c\n", rva) would produce a line such as
 080401089	mov	eax, ebx	; typical reg move
in the output. Note that 'printing' a range of lines or an entire file sends
the data to STDOUT; thus a controlling process with a 60-line disassembly
window would have the bastard print 60 addresses, copy the output from STDOUT
to its internal buffer, perform any syntax highlighting and formatting, and
display those 60 lines in its disassembly window. The asmsprintf function was
designed with this in mind; it allows the fields to be separated with arbitrary
delimiters. It should be pointed out that asmsprintf() will not actually be
called by the user or the controlling process; the line format will be stored
in an environment variable, and the PrintAddress, PrintRange, and
PrintNumAddress [print a specified number of lines] will be used instead.


Layout of the Source
--------------------
The source code is in the files in $BASTARD_HOME/src:
    bastard.c  -- startup & error handling
    api_*.c    -- bastard API functions [most of the code]
	 parser.c   -- command-line parser; calls fn's in macro.c & db.c
    macro.c    -- Seer initialization/interface; CLI command fn's
    db.c       -- Typhoon initialization, management, & interface routines
The distinction between one file and the next can get pretty fuzzy; in general,
the 'useful' code is in api.c, while the other files contain support code which
is used primarily to interface with the user, the controlling process, or the
embedded database/interpreter/readline libraries. This structure has caused 
api.c to become large and unwieldly; in the future it may be broken up into
files based on subsystem [loading, imports, names, etc].

When loaded, the program runs as follows:
   main()-->initialize data structures;
         |->call ReadPrefs();
         |->handle command-line options;
         |->call doSeer() to initalize seer;
         |->call doTyphoon() to initialize typhoon;
         |->install sighandler userkill();
         |->loop until exit;
         |  |->call readline() to get command;
         |  |->call ProcessCommand() to parse command line;
         |  -->pass CLI commands to handlers; API calls to Seer
         -->cleanup;
...everything else is dependent on user decisions. Note that CLI aliases such
as "L" are handled via direct calls, while all API calls are compiled into a 
temporary seer script and executed; this means that CLI commands will be
marginally faster than standard API calls, and that potential problems exist in
API calls due to the intermediate Seer layer. This is to be considered a
'design tradeoff' in order to make the API calls work the same from the CLI,
from a controlling process, and from user-written Seer scripts. 


Disassembly
-----------
The disassembly functions in the bastard are:
  InitDisassembler(char *dis);
  DisassembleFull();
  DisassembleDumb();
  DisassembleSection(char *sec);
  DisassembleRange(long rva, int size);
  DisassembleForward(long rva);
  DisAddr(DWORD pa, struct code *c, DWORD rva);
  GetOpType(char *op);
  AnalyzeCurrInst();
Of these, the first six are API functions; they are used to choose the
disassembler [based on processor type; called by SetCPUType()] and to determine
the method of disassembly ["dumb section", "dumb range", "smart"] used. The 
remaining functions are utility functions used to create a code object [along
with associated data objects, xrefs, and so forth] for each disassembled
address. The disassembly process is generally as follows:
  InitDisassembler() --> register callback disasmCB();
  Disassemble*()     --> DisAddr->(*disasm_fn)();
                     |-> DefineAddr( curr_addr );
                     --> AnalyzeCurrInst() --> GetOpType();
Note that DisAddr calls the "disassemble address" function in the disassembler
module loaded by InitDisassembler(). Each Disassemble* function loops through
a range of addresses [e.g. an entire section] and calls the disassembler
function, the DefineAddr() API function, and the AnalyzeCurrInst() function on
an address. By the time AnalyzeCurrInst() is called, a CODE object called
curr_inst has been created and filled with the rva, mnemonic, and operands of
the current instruction; AnalyzeCurrInst() then determined the mnemonic and 
operand types, creates data objects and xrefs if needed, and inserts the CODE
object into the database.
  

Database
--------
The bastard uses an embedded Typhoon database to manage information about the
target; this is used instead of linked lists due to the typhoon support for
offline DB browsing, and its flexibility -- however there is a noticeable
performance decrease when using the Typhoon DB instead of a series of internal
linked lists. Once again, this is considered to be a design tradeoff; revision
of the Typhoon source code may be necessary in the future, to increase response
time.

The database consists of the following tables:
  SECTION       -- a program section or segment
  ADDRESS       -- an address [code or data] within the program
  CODE          -- an asm instruction associated with an ADDRESS
  INT_CODE      -- intermediate representation of a CODE record
  FIN_CODE      -- final 'decompiled' representation of INT_CODE record
  XREF          -- a reference from one ADDRESS to another
  NAME          -- a symbolic name associated with an ADDRESS
  CONSTANT      -- a named constant applied to immediate values
  EXPORT        -- a program entry point or exported function
  IMPORT        -- an external address referred to by the program
  LIBRARY       -- a library required by the program
  COMMENT       -- a user-supplied comment associated with an ADDRESS
  FUNCTION      -- a sequence of code in the target ended in a RET instruction
  FUNC_PARAM    -- a parameter to a FUNCTION
  FUNC_LOCAL    -- a local variable in a FUNCTION
  F_INLINE      -- an instance of an INLINE_TYPE block of code
  INLINE_TYPE   -- a block of oft-repeated code in the target, e.g. a C macro
  STRING        -- an ADDRESS object that consists of an ASCII string
  STRUCTURE     -- a logical, named structure applied to ADDRESS objects
  STRUCT_MEMBER -- a data member for a STRUCTURE
  DATA_TYPE     -- a predefined data type, ala typedef
  SEER_MACRO   -- a user-supplied, precompiled SeerC macro 
Note that while these tables have been sketched out in include/bdb.h, many of
them have not been finalized; these will be extended when the appropriate
functionality has been added to the disassembler. The database is intended to
be a convenient means of saving and retrieving data about a target between
sessions; as such all information regarding the target should be stored in the
database.


Coding Conventions
------------------
None ;)

Functions should return 0 on error and >0 on success; the proper way to 
return with error is to use
	return( SetLastError( int error_code ) );
which will return 0, and set the global _last_bastard_error which can be
retrieved via GetLastError() and GetLastErrorString().


Status
------
Functional. Need UIs. Many features need to be written. More CPU modules would be nice too.


Misc Notes
----------
Here's some excerpts from the ML that may prove handy. I'm too lazy to format them into coherent README text.


*using the bastard
The CLI has basic commands that can be listed by typing
'HELP' 'H' or just '?'. 

In addition, any API call can be made
from the command line -- the CLI is just like C in this
respect. 

To do multi-line commands --essentially, C scripts which
are assumed to be one long main() with no inputs or 
outputs-- type '{{' on a line of its own to start the 
script, and '}}' on a line of its own to end it. The script
will run when you submit the '}}'

API calls are all listed in $BASTARD_HOME/include/api.h .
No, they're not commented yet ;)

Some very, *very* basic examples of using the bastard are 
the shell scripts in $BASTARD_HOME/utils . Also, the .sc
scripts in $BASTARD_HOME/arch and $BASTARD_HOME/engines 
demonstrate how to use Seer as well as the API .

Keep an eye out for instructions that disassemble 
incorrectly -- I would like to hear about these.
Comparisons with IDA and objdump for specific byte
sequences would be greatly appreciated :)



*coding the bastard

Yeah, I know no-one is going to want to do this but me,
but it never hurts to cover it.

The main files to be concerned with are the 
$BASTARD_HOME/src/api_*.c files -- the other .c files
contain superfluous stuff for the CLI and interfacing 
with the db and with seer. 

In addition, the disassembler engines are in arch/ , while
the file format parsers and the post-disassembly passes are 
in engines/ -- these last 2 contain seer scripts and not 
regular C files, but the differences are minimal [and good,
like being able to modify them while the bastard is running :) ].

Seer uses the include files seer.b_def.h, seer.bastard.h, and 
seer.clib.h to interface with the bastard; the bastard uses seer.h 
and bastard_seer.h to interface with seer. 

The DB is defined in $BASTARD_HOME/src/bdb.ddl ; the include file for
coding purposes is bdb.h . I recommend looking at the DDL file to
get a feel for the DB, since it governs how the file is represented and
what can be done with the disassembly. The bastard uses typhoon.h 
and environ.h to interface with the DB.
    
	 ----------------------------------------------------------
> can it recognise a call 0x0804xxxxx as say, call printf() ?

The address to 'printf' is stored in the NAME table; I need to do 
some work on asmsprintf() so that when it prints an operand, it does 
a search for the operand [explicitly if it is type OP_ADDR, or by 
adding the current rva to the operand if it is OP_IMM or OP_REL] in 
the name.rva index, and prints name.name instead of the operand.

To make a long story short,
  call 0x0804xxxx
will become
  call printf
when I have updated asmsprintf [which I have slated for this weekend]. 
The DB and disassembler support is there; it just doesn't display 
when you do a 'd' ;)


Of course the number of strncmp's should be reduced as much as possible. 
All of the strcmp-heavy code, btw, is in the 'engine' scripts and 
does not have to be executed. By default, all scripts in engines/ 
are run when you call DisassembleFull() on the target [and the CLI 
'l' command does this], but if yu check out the alternate disassembly 
routines in api_disasm.c, you'll see it's possible to things quite 
differently [by section, by byte range, by following flow of execution 
from an arbitrary starting point...].

Anyways, if the accumulation of features in DisassembleFull() troubles 
you, you'll see it's not hard to re-create:

      struct function f;

      d_keyfrst(FUNCTION_RVA);
      while (db_status == S_OKAY) {
         d_recread(&f);
         if (db_status == S_OKAY) DisassembleForward(f.rva);
         d_keynext(FUNCTION_RVA);
      }
      DisassembleForward(target.entry);
      DisassembleAllPasses();

If you recode this as

   function_t f;
   int cont;

   cont = DBIndexFirst(FUNCTION_RVA, &f);
   while(cont) {
      DisassembleForward(f.rva);
      cont = DBIndexNext(FUNCTION_RVA, &f);
   }
   DisassembleForward(target.entry);
   

it should run from the CLI or a script ['should' meaning 'untested', 
but all of these functions work from the CLI].

You can remove the engines files by removing DisassembleAllPasses() ;  you
can call specific engine scripts by calling DisassemblePass(num) where 
'num' is the pass# of the script [engine scripts are named pass#.sc ].


> structures is something which should be done via plugins/scripts. 
>  Same with strings, macros,
> I dont' understand what you mean by that, but I assume it is collapsing 
> asm statements into assembler macros, i.e.

nope, that would be meaningless.  Macros are just seerc scripts that 
are stored in the DB. The idea is that you 'start recording' what 
you do in the CLI, then when you 'stop recoding' you have a script 
that you can re-use later. Frivolous, but since this *is* CLI based 
it could be useful.


> do you currently support both syntaxes?  It would be a good idea to 
> have both of them supported 

yeah, you can change the output syntax by using 

void SetTtyFmt( char *fmt );
void SetAsmFmt( char *fmt );
void SetLprFmt( char *fmt );

to set the console (printf), .asm file, and printer output formats. 
These format strings are passed to asmsprintf() . And no, grugq, the 
formatting strings are not then blindly passed to sprintf ;)



> sounds pretty good.  It might be interesting to make this support 
> decompilation, that is
> to have it output some sort of pseudo-assembler code which isn't CPU 
> specific and can then be
> turned into an (arbitrary ?) high level language. 

That's already part of the plan : it's what the INT_CODE and FIN_CODE tables are for.



> name mangling is also related to which compiler is used.  Not totally, 

True. "target_language" could actually be 'target_compiler", and may 
end up being responsible for library signatures [which are not a big 
deal on linux, but are a huge problem on win32 since only kernel and 
GDI are shared ;P ]. I'm open to ideas on this.


> I think that most people can do that on their own.  What is more important 
> is getting strings 
> insertet and asm outputted.  I would love something like that, it 

Strings can currently be defined manually. Doing it auto means making 
assumptions about the string style; I'm not about to hardcode string 
types like IDA does [try defining FORTRAN strings in IDA -- it won't 
work].



> I mean hell; that is basicly something which builds on a parser for 
> .h files or something, a sub routine 
> figurer-outer (thats the technical name), and some other low level 


Well, intialy the user would type in the prototype for the fn. We 
can get into .h parsers later. It occurred to me, while trying to 
figure out how to represent function arguments and return values outside 
of the DB [for input to the DB, and for output to the screen/.asm 
file], that prototypes are really the best way; and if we bite the 
bullet and code a prototype parser now, adding .h file parsing later 
won't be a big deal.


> and added two more, just to make my life more... intrigueing? ;-P

Just to make you happy -- even though the latest CVS dompiles out 
of the box on the unretouched debian, mandrake, and RH boxes I have 
access to at work -- I added a NO_LIBOPCODES option to the Makefile 
which will disable bfd, libopcodes, and all the #include problems 
that I was just commenting my way past before. Enjoy.

> you could write a test sequence.  I might even do it for you, if I 
> am feeling up to it.
> create a small set of programs which you disassemble with the bastard 
> and nasm, then go 


Well, yeah, but I'd rather code than look for bugs. You guys who aren;t 
doing any coding: Look For Bugs. ;P


> I guess it wouldn't be a bad idea to have some sort of README.CODERS 

`cat ./README.CODERS`
;)
