Linking

This chapter describes how linking objects before runtime works. Linking functionality can be found in dlink.c and dlink.h.

Decision is a compiled language, and you compile individual sheets into their respective objects. Most of the time you will want to just run a sheet straight from the terminal. But sometimes, especially if the sheet is very big, it may be worth your while to compile the sheet into an object file to increase performance (since it doesn’t compile the program every time).

The fact that you can compile a sheet to an object file is the reason why we need to link. Every time you load an object from an object file in memory, it is very likely that it will not be places into the same memory address every time. So, we will need to change where the instructions in the .text section point to, and that is exactly what we do when linking.

Object Sections

Objects have 2 sections that are purely used for linking:

.lmeta

A list of LinkMeta, where each LinkMeta describes a thing like a variable, function, or string literal, and where you can find it (if it’s defined on the same sheet).

.link

A table of instruction indexes and which LinkMeta they link to.

Structures

LinkType

An enum which describes what kind of thing a link points to, whether it be a variable, function, or something else.

LinkMeta

A struct that describes a link. It includes a LinkType, and the const char* name of the item it is linking to. In the case of string literals, the name is the content of the literal. It also contains a generic void* pointer that is designed to point to a struct that contains metadata for the object being linked to, i.e. a SheetVariable or SheetFunction. It also contains a generic char* pointer which serves different purposes depending on what the LinkType is:

  • If it is a link to an item in the object’s own .data section, the pointer’s value is the starting index of the item in the .data section.

  • If it is a link to an item in the object’s own .text section, the pointer’s value is the starting index of the item in the .text section.

LinkMetaList

A struct that is a list of LinkMeta.

Functions

LinkMeta d_link_new_meta(LinkType type, const char *name, void *meta)

Create a new LinkMeta structure.

Return

A new LinkMeta with the given parameters.

Parameters
  • type: The type of object this link will point to.

  • name: The name of the object this link will point to.

  • meta: A pointer to the metadata of the object the link points to.

LinkMetaList by itself has a few helper functions to help create it, free it, and to manipulate it’s contents:

LinkMetaList d_link_new_meta_list()

Create an empty LinkMetaList.

Return

An empty LinkMetaList.

void d_link_meta_list_push(LinkMetaList *list, LinkMeta item)

Add a LinkMeta item to a list.

Parameters
  • list: The list to push the item onto.

  • item: The item to push onto.

void d_link_free_list(LinkMetaList *list)

Free a LinkMetaList object.

Parameters
  • list: The list to free.

void d_link_replace_fimmediate(char *ins, char *ptr)

Change an instruction’s full immediate to point somewhere.

NOTE: If you don’t like the fact that you can’t run 32-bit Decision code on 64-bit machines and vice versa, blame it on this function.

Parameters
  • ins: A pointer to first byte of the instruction.

  • ptr: The memory address for the instruction to load.

This function is what actually changes the instructions in .text to point to the correct items. Since we use pointers to set links, the instructions need to load either 32-bit or 64-bit addresses into a register. This is always done with a PUSHF combination.

void d_link_self(struct _sheet *sheet)

Link a sheet’s properties from itself to itself and included sheets.

Parameters
  • sheet: The sheet to link.

Takes a compiled sheet, gets the information it needs to link from the .lmeta and .link sections, and uses it to call d_link_replace_fimmediate to replace all of the instructions that need linking.