Modular IDE:Loading and Symbol Resolution


Initial Core Loading

  1. Core IDE is loaded at a fixed address by the Prom.
  2. Core Ide begins executing its script.
  3. If Core IDE encounters a load command (either via its script or from the user), it executes the module loading mechanism described below.

Module Loading & Execution Mechanism

  1. If no other modules have been previously loaded by Core IDE, Core reads its own symbol table (this is done only once before the first module is loaded). This symbol table will later be used by Core IDE to resolve core symbols in IDE modules.
  2. The load command will only load a module if is a dynamic elf binary (i.e. the module has been compiled -shared). If this criteria is not met, the load will fail.
  3. Now Core IDE begins loading the dynamic elf module binary. To be able to do proper symbol resolution later, Core IDE needs to make sure that the following elf program segments exist in the module:
    1. .MIPS.options segment: contains the value of the GP (global pointer) of the module
    2. .got segment: contains the Global Offset Table (GOT). The GOT is used to resolve symbols in the module that refer to Core symbols. Note that a module may not have a GOT if it has no unresolved symbols.
    3. .dynsym segment: the dynamic symbol table. This symbol table is used by Core IDE to find the module's undefined symbols (the dynamic symbol table uses offsets into the dynamic string table for symbol string names).
    4. .dynstr segment: the dynamic string table. The string table contains the string names of the module's symbols. This is used by Core IDE to do symbol look-up in conjunction with the dynamic symbol table.
  4. Now Core IDE uses the following symbol resolution mechanism:
    1. Core IDE scans through the dynamic symbol table (.dynsym) of the module looking for undefined symbols.
    2. For each undefined symbol:
      1. Core IDE uses the module's dynamic string table (.dynstr) to get the symbol's string name.
      2. Core IDE tries to look up the unknown symbol's string in its own symbol table.
      3. If the symbol is found, Core places the symbol's core address into the symbol's GOT (.got) entry of the module. Else an error is reported and the load fails due to an unresolved symbol.
  5. All symbols are now defined in the module.
  6. Core IDE uses the .reginfo segment to read the module's GP value. This value is needed by the initial module code so that it can inialize the $gp register. This register is needed because all symbol references in the module use the GOT table which in turn depend on $gp as a base register.
  7. Core IDE uses the standard argv & environment passing mechanism of the Prom as follows:
    1. argv[0] contains the path name of the module
    2. argv[1] contains the module's GP value in ascii (no leading 0x or 0X).
    3. the remaining argv strings which were passed to Core IDE from Prom are passed to the module in argv[2], argv[3], ....
    4. the environment strings which were passed to Core IDE from Prom, are copied and passed to the module
  8. Core IDE jumps to the module's start_module() assembly routine and begins execution.
  9. Before any references can be made by the module, its $gp register must be set so that references can go through the GOT. The very first thing that start_module() does is convert the GP value string in argv[1] to a hex number and store it in $gp. Once $gp is set, the module's stack can be initialized, the original $gp is saved, the original stack is saved, and the C module_main() function is called.
  10. module_main() can now set variables in the Core to point to the module's script and its list of module commands.
  11. Finally, module_main() calls the Core main() function which starts the parser on the module's script.

stojanof@engr.sgi.com