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

                     Bastard  Database  Schematics




================================================================================
 BDB Files

The bastard 'native' file format is .bdb, standing of course for Bastard 
Database; a .bdb is simply a tarball of the ./.target.bdb working directory
created by the bastard when a target is loaded. When unpacked, a .bdb file
looks somewhat like this:

   ./.$TARGET.bdb/
   ./.$TARGET.bdb/sequence.dat
   ./.$TARGET.bdb/address.db
   ./.$TARGET.bdb/address.ix1
      /* more .db and .ix files here ... */
   ./.$TARGET.bdb/$TARGET
   ./.$TARGET.bdb/.info
   ./.$TARGET.bdb/header.txt
   
The .dat, .db, and .ix# files represent the Typhoon database files; the .db 
files contain the actual data, and the .ix# files contains the table indexes.

Typhoon databases are defined in .ddl (Database Description Language) files,
which use a C-like syntax to specify the contents of tables in the manner of
C structures. These .ddl files are processed by the Typhoon utility ddlp 
(located in $BASTARD_HOME/utils), which creates a .dbd (Database Description)
file, and a .h file containing structure definitions and symbolic constants
used for accessing the database via the typhoon interface.

================================================================================
 Target Database


The target database is defined in bdb.ddl, and processed into bdb.h and 
bdb.dbd. This database is the mainstay of the disassembler; for any serious
work with the disassembled file, an understanding of the database is
essential.


Address Table
The fundamental block of the target is the ADDRESS; in the database, a program
is viewed as a sequential series of addresses, which serve as links --usually
via the 'rva' field-- to additional constructs such as code, subroutines, and
strings. 

ADDRESS entries are created with DefineAddress(); each address must have a
virtual address (rva), a physical address (pa), and a size. When loading the
file, a single large address is created at pa 0 rva 0, spanning the entire
size of the file. Sections of the file are then either allocated from this
address, if their rva's are contained within it, or allocated their own
address block starting at the section's rva and spanning the size of the
section. Note that this makes the rva a unique key, while pa is not; in the
case of data belonging to more than one section (e.g., the teensy ELF file),
more than one rva can reference the same pa.

This can cause some confusion when viewing the ADDRESS table in and of itself;
as a result, rather than iterating through a program address by address, it is
recommended instead to iterate through the sections, and only examine addresses
contained within structures. An alternative to the default loading scheme, and
one which can be implemented in a file format parser (by deleting the existing
huge address block and doing its own DefineAddress calls), would be to create 
address blocks for existing sections, and perform all subsequent allocations
from those.

Defining an address causes some rather aggressive resizing; it is assumed that
current definitions have precedence over previous ones (the we-assume-you-know-
what-you're-doing school of program design), so defining an address causes the
following effects:
   * A larger address containing that address is split or resized
   * An existing address at the same rva is resized
   * A smaller address in the midst of the new address is deleted
The effects are best demonstrated with a visual; what follows depicts a 
1024-byte address block in which the rva is equal to the pa, and shows the 
effects of various DefineAddress(rva, size, pa, flags) calls.

   1. DefineAddress( 0, 1024, 0, 0);
  ______________________________________________________________________
  0                                                                 1023
  ----------------------------------------------------------------------
   2. DefineAddress( 0, 512, 0, 0);
  ______________________________________________________________________
  0                             512|513                             1023
  ----------------------------------------------------------------------
   3. DefineAddress( 900, 100, 900, 0);
  ______________________________________________________________________
  0                             512|513                899|900  999|1023
  ----------------------------------------------------------------------
   4. DefineAddress( 300, 500, 300, 0);
  ______________________________________________________________________
  0                299|300                       799|800  |900 1000|1023
  ----------------------------------------------------------------------
   5. DefineAddress( 10, 100, 10, 0);
  ______________________________________________________________________
  0|10  109|110    299|300                       799|800  |900 1000|1023
  ----------------------------------------------------------------------
   6. DefineAddress( 50, 200, 50, 0);
  ______________________________________________________________________
  0|10 49|50   |250   |300                       799|800  |900 1000|1023
  ----------------------------------------------------------------------
   7. DefineAddress( 750, 200, 200, 0);
  ______________________________________________________________________
  0|10 49|  249|   299|300                  749|750     949|950    |1023
  ----------------------------------------------------------------------
  
As shown, an initial address is created from 0 - 1023. Next, a 512-byte block
is created at rva 0; this effectively resizes the existing block to cover from
0-512, and the new address is created from 513-1023 to represent the "old"
address block. In step 3, a 100 byte block is created at rva 0; this splits the
address from 513-1023 into three addresses: 513-899, 900-999, 1000-1023. Then
a 500-byte address is created at rva 300; the 0-512 block is resized to 0-299,
the 513-899 block is deleted, and two new blocks are created: 300-799 and 800-
899. At step 5 an address block is created at rva 10 for 100 bytes; the block
from 0-299 is resized to 0-9, and two new blocks are created at 10-109 and 110-
299. And so on and so on, until in the final stage the block from 800-899 is
removed in order to create the larger 750-949 block that encompasses it.

   TABLE ADDRESS
      FIELD rva         (unsigned long)
      FIELD pa          (unsigned long)
      FIELD size        (unsigned short)
      FIELD flags       (int)
      FIELD dataConst   (unsigned long)
      FIELD structure   (unsigned long)
      FIELD comment     (unsigned long)

      INDEX ADDRESS_RVA (rva, ascending, unique): PRIMARY
      INDEX ADDRESS_PA  (pa, ascending)

      Notes: 
      flags is a combination of one of the two base types
         ADDR_CODE
         ADDR_DATA
      along with any number of the following additional types:
         ADDR_IMPORT
         ADDR_EXPORT
         ADDR_SECTION
         ADDR_STRUCT
         ADDR_STRING
         ADDR_FUNCTION
         ADDR_INLINE
         ADDR_NAME
         ADDR_COMMENT
         ADDR_SYMBOL
         
      dataConst is the id of a CONSTANT record if ADDR_DATA is set and
      the data has a symbolic constant associated with it.

      structure is the id of a STRUCTURE record if ADDR_DATA is set and
      the data has a structure definition associated with it.

      comment is the id of a COMMENT record if ADDR_COMMENT flags is set.
      

Section Table 

   TABLE SECTION
      FIELD name     (char[32])
      FIELD rva      (unsigned long)
      FIELD size     (unsigned long)
      FIELD flags    (int)

      INDEX  SECTION_NAME (name, ascending, unique): PRIMARY
      INDEX  SECTION_RVA  (rva, ascending, unique)


Xref Table

   TABLE XREF
      FIELD id       (unsigned long)
      FIELD from_rva (usigned long)
      FIELD to_rva   usigned long)
      FIELD type     (int)

      INDEX  XREF_ID            (id, ascending, unique): PRIMARY
      INDEX  XREF_FROM_RVA      (from_rva, ascending)
      INDEX  XREF_TO_RVA        (to_rva, ascending)
      INDEX  XREF_XREF_FROM_RVA (from_rva, to_rva, ascending, unique)
      INDEX  XREF_XREF_TO_RVA   (to_rva, from_rva, ascending, unique)


Code Table
   
   TABLE CODE
      FIELD rva         (unsigned long)
      FIELD mnemonic    (char[16])
      FIELD dest        (long)
      FIELD src         (long)
      FIELD aux         (long)
      FIELD mnemType    (int)
      FIELD destType    (int)
      FIELD srcType     (int)
      FIELD auxType     (int)
      FIELD destConst   (unsigned long)
      FIELD srcConst    (unsigned long)
      FIELD auxConst    (unsigned long)

      INDEX  CODE_RVA           (rva, ascending, unique): PRIMARY
      INDEX  CODE_CODE_DEST     (dest, rva, ascending)
      INDEX  CODE_CODE_SRC      (src, rva, ascending)
      INDEX  CODE_CODE_MNEMONIC (mnemonic, rva, ascending)


Address Expression Table

   TABLE ADDR_EXP
      FIELD id    (int)
      FIELD scale (int)
      FIELD index (int)
      FIELD base  (int)
      FIELD disp  (long)
      FIELD flags (int)
      FIELD name  (unsigned long)

      INDEX  ADDRPEXP_ID (id, ascending, unique): PRIMARY


Intermediate Code Table

   TABLE INT_CODE
      FIELD id       (unsigned long)
      FIELD rva      (unsigned long)
      FIELD size     (int)
      FIELD lvalue   (char[32])
      FIELD rvalue   (char[64])

      INDEX  INT_CODE_ID  (id, ascending, unique): PRIMARY
      INDEX  INT_CODE_RVA (rva, ascending, unique)
		alternate key rva;


Final Code Table

   TABLE FIN_CODE
      FIELD id    (unsigned long)
      FIELD rva   (unsigned long)
      FIELD size  (int)
		FIELD line  (char[256])

      INDEX  FIN_CODE_ID  (id, ascending, unique): PRIMARY
      INDEX  FIN_CODE_RVA (rva, ascending, unique)


Export Table

   TABLE EXPORT_ADDR
      FIELD rva   (unsigned long)

      INDEX  EXPORT_ADDR_RVA (rva, ascending, unique): PRIMARY


Import Table

   TABLE IMPORT_ADDR
      FIELD library  (int)
      FIELD type     (int)
      FIELD rva      (unsigned long)

      INDEX  IMPORT_ADDR_RVA (rva, ascending, unique): PRIMARY
      INDEX  IMPORT_ADDR_IMPORT_LIBRARY (library, rva, ascending, unique)


Library Table

   TABLE LIBRARY
      FIELD id       (int)
      FIELD name     (char[64])
      FIELD ver_hi   (int)
      FIELD ver_lo   (int)

		primary key id;
      INDEX  LIBRARY_ID    (id, ascending, unique): PRIMARY
      INDEX  LIBRARY_ NAME (name, ascending, unique)
		

String Table

   TABLE STRING
      FIELD rva      (unsigned long)
      FIELD length   (int)
      FIELD text     (char[256])

      INDEX  STRING_RVA (rva, ascending, unique): PRIMARY


Name Table

   TABLE NAME
      FIELD rva   (unsigned long)
      FIELD type  (int)
      FIELD name  (char[64])

      INDEX  NAME_RVA  (rva, ascending, unique): PRIMARY
      INDEX  NAME_NAME (name, ascending, unique)


Comment Table

   TABLE COMMENT
      FIELD id    (unsigned long)
      FIELD type  (int)
      FIELD text  (char[256])

      INDEX  COMMENT_ID (id, ascending, unique): PRIMARY


Function Table

   TABLE FUNCTION
      FIELD id        (unsigned long)
      FIELD rva       (unsigned long)
      FIELD size      (unsigned short)
      FIELD comment   (unsigned long)

      INDEX  FUNCTION_ID  (id, ascending, unique): PRIMARY
      INDEX  FUNCTION_RVA (rva, ascending, unique)


Function Parameter Table

   TABLE FUNC_PARAM
      FIELD id      (unsigned long)
      FIELD func    (unsigned long)
      FIELD type    (unsigned long)
      FIELD offset  (int)
      FIELD name    (char[32])

      INDEX  FUNC_PARAM_ID   (id, ascending, unique): PRIMARY
      INDEX  FUNC_PARAM_FUNC (func, ascending)


Function Local Variable Table

   TABLE FUNC_LOCAL
      FIELD id      (unsigned long)
      FIELD func    (unsigned long)
      FIELD type    (unsigned long)
      FIELD offset  (int)
      FIELD name    (char[32])

      INDEX  FUNC_LOCAL_ID (id, ascending, unique): PRIMARY
      INDEX  FUNC_LOCAL_FUNC (func, ascending)


Inline Function Table

   TABLE F_INLINE
      FIELD id    (unsigned long)
      FIELD type  (unsigned long)

      INDEX  F_INLINE_ID (id, ascending, unique): PRIMARY
		

Inline Function Type Table      

   TABLE INLINE_TYPE
      FIELD id      (unsigned long)
      FIELD name    (char[64])
      FIELD rva     (unsigned long)
      FIELD size    (unsigned short)

      INDEX  INLINE_TYPE_ID  (id, ascending, unique): PRIMARY
      INDEX  INLINE_TYPE_RVA (id, ascending, unique)


Structure Table

   TABLE STRUCTURE
      FIELD id    (unsigned long)
      FIELD name  (char[32])
      FIELD size  (unsigned short)

      INDEX  DATA_TYPE_ID (id, ascending, unique): PRIMARY
		primary key id;


Structure Member Table

   TABLE STRUCT_MEMBER
      FIELD id         (unsigned long)
      FIELD type       (unsigned long)
      FIELD structure  (unsigned long)
      FIELD order      (int)
      FIELD name    (char[32])

      INDEX  STRUCT_MEMBER_ID (id, ascending, unique): PRIMARY
      INDEX  STRUCT_MEMBER_STRUCTURE (structure, ascending, unique)
		

 Data Type Table     

   TABLE DATA_TYPE
      FIELD id    (unsigned long)
      FIELD size  (int)
      FIELD name  (char[32])

      INDEX  DATA_TYPE_ID (id, ascending, unique): PRIMARY
		

Symbolic Constant Table

   TABLE CONSTANT
      FIELD id    (unsigned long)
      FIELD name  (char[32])
      FIELD value (long)

      INDEX  CONSTANT_ID (id, ascending, unique): PRIMARY
      INDEX  CONSTANT_NAME (name, ascending)
      INDEX  CONSTANT_VALUE (value, ascending)


================================================================================
 Configuration Database


Environment Profile Table

   TABLE PROVILE_ENV
      FIELD    user     (char[32])
      FIELD    home     (char[256])
      FIELD    p1       (char[16])
      FIELD    p2       (char[16])
      FIELD    p3       (char[16])
      FIELD    p4       (char[16])
      FIELD    dbpath   (char[256])
      FIELD    output   (int)

      INDEX  PROFILE_ENV_USER (user, ascending, unique): PRIMARY


Preferences Profile Table

   TABLE PROFILE_PREF
      FIELD    user     (char[32])
      FIELD    arch     (char[32])
      FIELD    asmblr   (char[32])
      FIELD    format   (char[32])
      FIELD    lang     (char[32])
      FIELD    pager    (char[256])
      FIELD    editor   (char[256])
      FIELD    debugger (char[256])
      FIELD    options  (int)

      INDEX  PROFILE_PREF_USER (user, ascending, unique): PRIMARY


Assembler Extension Profile Table

   TABLE PROFILE_ASM
      FIELD    name           (char[32])
      FIELD    asm_ttyColor   (char[128])
      FIELD    data_ttyColor  (char[128])
      FIELD    asm_ttyMono    (char[128])
      FIELD    data_ttyMono   (char[128])
      FIELD    asm_file       (char[128])
      FIELD    data_file      (char[128])
      FIELD    asm_lpr        (char[128])
      FIELD    data_lpr       (char[128])

      INDEX  PROFILE_ASM_NAME  (name, ascending, unique): PRIMARY


Architecture Extension Profile Table

   TABLE PROFILE_ARCH
      FIELD    name     (char[32])
      FIELD    options  (int)

      INDEX  PROFILE_ARCH_NAME  (name, ascending, unique): PRIMARY


Macro History Table

   TABLE HIST_MACRO
      FIELD    type        (int)
      FIELD    name        (char[32])
      FIELD    macro_text  (char[2048])
      
      INDEX  HIST_MACRO_NAME  (name, ascending, unique): PRIMARY


Command History Table

   TABLE HIST_CMD
      FIELD    id   (int)
      FIELD    cmd  (char[256])
      

      INDEX  HIST_CMD_ID  (id, ascending, unique): PRIMARY


Target Profile Table

   TABLE PROFILE_TARGET
      FIELD    name    (char[64])
      FIELD    path    (char[256])
      FIELD    dbname  (char[256])
      FIELD    size    (int)
      FIELD    entry   (long)
      FIELD    arch    (char[32])
      FIELD    asmblr  (char[32])
      FIELD    format  (char[32])
      FIELD    lang    (char[32])

      INDEX  PROFILE_TARGET_NAME    (name, ascending, unique): PRIMARY
      INDEX  PROFILE_TARGET_DBNAME  (dbname, ascending, unique)
