asoma.dev · the C reference for libose
libose
the C library every o.se host is built on
Loading...
Searching...
No Matches
ose_abi.h File Reference

What two builds must agree about to share a bundle. More...

#include <stdint.h>
#include "ose.h"
#include "ose_context.h"
Include dependency graph for ose_abi.h:

Go to the source code of this file.

Data Structures

struct  ose_abi
 What a build was compiled to expect. More...

Macros

#define OSE_ABI_FIELDS(F)
 The compatibility fields, listed once.
#define OSE_ABI_WRAP_BUNDLE_PTR   1
#define OSE_ABI_DEBUG   0
#define OSE_ABI_TYPE(name, bit)
#define OSE_ABI_TYPEMASK
#define OSE_ABI_TYPE_SYMBOL(b)
#define OSE_ABI_TYPE_DOUBLE(b)
#define OSE_ABI_TYPE_INT8(b)
#define OSE_ABI_TYPE_UINT8(b)
#define OSE_ABI_TYPE_INT16(b)
#define OSE_ABI_TYPE_UINT16(b)
#define OSE_ABI_TYPE_UINT32(b)
#define OSE_ABI_TYPE_INT64(b)
#define OSE_ABI_TYPE_UINT64(b)
#define OSE_ABI_TYPE_TIMETAG(b)
#define OSE_ABI_TYPE_TRUE(b)
#define OSE_ABI_TYPE_FALSE(b)
#define OSE_ABI_TYPE_NIL(b)
#define OSE_ABI_TYPE_INFINITUM(b)
#define OSE_ABI_FIELD_DECL(name, value)
#define OSE_ABI_FIELD_VALUE(name, value)
 The values this translation unit was compiled with.
#define OSE_ABI_INIT   { OSE_ABI_FIELDS(OSE_ABI_FIELD_VALUE) }
#define OSE_ABI_SYMBOL_NAME   "ose_abi_expected"
 The symbol a module exports so a loader can find its expectations.
#define OSE_ABI_DECLARE    const struct ose_abi ose_abi_expected = OSE_ABI_INIT
 Declare the exported record. A module writes this once, at file scope.

Functions

void ose_abi_thisBuild (struct ose_abi *a)
 Fill a with the values this build was compiled with.
int32_t ose_abi_compatible (const struct ose_abi *host, const struct ose_abi *mod, char *buf, int32_t buflen)
 Compare two records.

Detailed Description

What two builds must agree about to share a bundle.

A module does not call libose across a stable interface. It is handed an ose_bundle and reads structure out of it using offsets that were compiled into the module itself. So a module built against one libose and loaded into a VM built from another does not fail to find a function – it reads the wrong bytes, and behaves as though the data were something else.

This header is the list of everything that determines whether two builds can share a bundle. Each build stamps the values it was compiled with into a struct; a host compares its own against a module's before handing over a bundle, and refuses on any difference.

A struct rather than a hash, deliberately: a hash can only say that something differs, where this can say which field and what the two values were. That is most of what makes the check worth having.

When adding something to libose that changes bundle layout, add it here. That is the one obligation this scheme carries. The OSE_ABI_FIELDS list below is the single place to edit; everything else is generated from it.

Macro Definition Documentation

◆ OSE_ABI_FIELD_DECL

#define OSE_ABI_FIELD_DECL ( name,
value )
Value:
int32_t name;

◆ OSE_ABI_FIELD_VALUE

#define OSE_ABI_FIELD_VALUE ( name,
value )
Value:
(value),

The values this translation unit was compiled with.

A module defines an object with this initialiser under the name in OSE_ABI_SYMBOL_NAME, so a loader can read its expectations back out.

◆ OSE_ABI_FIELDS

#define OSE_ABI_FIELDS ( F)
Value:
F(cache_size, OSE_CONTEXT_CACHE_SIZE) \
F(cache_items, OSE_CONTEXT_NUM_CACHE_ITEMS) \
F(cache_ttstrlen, OSE_CONTEXT_CACHE_TYPETAG_STRLEN) \
F(cache_offset, OSE_CONTEXT_CACHE_OFFSET) \
F(bundle_offset, OSE_CONTEXT_BUNDLE_OFFSET) \
F(alignment, OSE_CONTEXT_ALIGNMENT) \
F(ptr_size, (int32_t)sizeof(intptr_t)) \
F(types, OSE_ABI_TYPEMASK) \
F(wrapped_bundle, OSE_ABI_WRAP_BUNDLE_PTR) \
F(debug, OSE_ABI_DEBUG)
#define OSE_CONTEXT_ALIGNMENT
Bytes passed to ose_newBundleFromCBytes will be aligned to a boundary that is a multiple of this numb...
Definition ose_context.h:45

The compatibility fields, listed once.

Takes the per-field macro as a parameter, so the struct, its initialiser and the comparison are all generated from this one list and a field cannot be added to one and forgotten in another.

◆ OSE_ABI_TYPE

#define OSE_ABI_TYPE ( name,
bit )
Value:
OSE_ABI_TYPE_##name(bit)

◆ OSE_ABI_TYPE_DOUBLE

#define OSE_ABI_TYPE_DOUBLE ( b)
Value:
| (1 << (b))

◆ OSE_ABI_TYPE_FALSE

#define OSE_ABI_TYPE_FALSE ( b)
Value:
| (1 << (b))

◆ OSE_ABI_TYPE_INFINITUM

#define OSE_ABI_TYPE_INFINITUM ( b)
Value:
| (1 << (b))

◆ OSE_ABI_TYPE_INT16

#define OSE_ABI_TYPE_INT16 ( b)
Value:
| (1 << (b))

◆ OSE_ABI_TYPE_INT64

#define OSE_ABI_TYPE_INT64 ( b)
Value:
| (1 << (b))

◆ OSE_ABI_TYPE_INT8

#define OSE_ABI_TYPE_INT8 ( b)
Value:
| (1 << (b))

◆ OSE_ABI_TYPE_NIL

#define OSE_ABI_TYPE_NIL ( b)
Value:
| (1 << (b))

◆ OSE_ABI_TYPE_SYMBOL

#define OSE_ABI_TYPE_SYMBOL ( b)
Value:
| (1 << (b))

◆ OSE_ABI_TYPE_TIMETAG

#define OSE_ABI_TYPE_TIMETAG ( b)
Value:
| (1 << (b))

◆ OSE_ABI_TYPE_TRUE

#define OSE_ABI_TYPE_TRUE ( b)
Value:
| (1 << (b))

◆ OSE_ABI_TYPE_UINT16

#define OSE_ABI_TYPE_UINT16 ( b)
Value:
| (1 << (b))

◆ OSE_ABI_TYPE_UINT32

#define OSE_ABI_TYPE_UINT32 ( b)
Value:
| (1 << (b))

◆ OSE_ABI_TYPE_UINT64

#define OSE_ABI_TYPE_UINT64 ( b)
Value:
| (1 << (b))

◆ OSE_ABI_TYPE_UINT8

#define OSE_ABI_TYPE_UINT8 ( b)
Value:
| (1 << (b))

◆ OSE_ABI_TYPEMASK

#define OSE_ABI_TYPEMASK
Value:
((int32_t)(0 \
OSE_ABI_TYPE(SYMBOL, 0) \
OSE_ABI_TYPE(DOUBLE, 1) \
OSE_ABI_TYPE(INT8, 2) \
OSE_ABI_TYPE(UINT8, 3) \
OSE_ABI_TYPE(INT16, 4) \
OSE_ABI_TYPE(UINT16, 5) \
OSE_ABI_TYPE(UINT32, 6) \
OSE_ABI_TYPE(INT64, 7) \
OSE_ABI_TYPE(UINT64, 8) \
OSE_ABI_TYPE(TIMETAG, 9) \
OSE_ABI_TYPE(TRUE, 10) \
OSE_ABI_TYPE(FALSE, 11) \
OSE_ABI_TYPE(NIL, 12) \
OSE_ABI_TYPE(INFINITUM, 13)))

Function Documentation

◆ ose_abi_compatible()

int32_t ose_abi_compatible ( const struct ose_abi * host,
const struct ose_abi * mod,
char * buf,
int32_t buflen )

Compare two records.

Parameters
hostWhat the running VM was built with.
modWhat the module was built with.
bufFilled with a description of the first difference, naming the field and both values. May be NULL.
buflenSize of buf.
Return values
1They agree; a bundle may be shared.
0They do not, and buf says how.