Argus.Schema (Panoptes v0.13.0)

Copy Markdown View Source

Fact relation definitions for Argus analysis.

Each relation describes a table of facts that Argus extracts from BEAM bytecode or domain extractors. Relations map directly to Souffle .decl declarations and .facts files.

Layers

  • Layer 1 — generic bytecode facts extracted from any BEAM module.
  • Layer 2 — domain-specific facts from pluggable extractors.

Summary

Types

The semantic kind of a relation field.

Functions

Returns all relation definitions.

Looks up a relation by name.

Relations that only the in-process passes read; no Souffle program does.

Returns layer 1 (generic bytecode) relation definitions.

Returns layer 2 (domain extractor) relation definitions.

Returns all relation names.

Renders a complete .dl declaration file for a layer.

The fact-schema version, asserted by in-process consumers at compile time.

Types

field()

@type field() :: {atom(), field_type(), String.t()}

field_type()

@type field_type() :: :symbol | :number | :instr_id | :func_id | :label

The semantic kind of a relation field.

:symbol and :number are the raw Souffle types. The richer kinds drive Argus.Facts.decode/1 for in-process consumers while serializing to the same Souffle types (:instr_id/:func_idsymbol, :labelnumber):

  • :instr_id — an instruction ID ("Mod:func/arity#idx"), decoded to Argus.InstrId.t().
  • :func_id — a function ID ("Mod:func/arity"), kept as a string.
  • :label — a BEAM label number (0 conventionally means "no label").

relation()

@type relation() :: %{name: atom(), layer: 1 | 2, fields: [field()], doc: String.t()}

Functions

all()

@spec all() :: [relation()]

Returns all relation definitions.

fetch(name)

@spec fetch(atom()) :: {:ok, relation()} | :error

Looks up a relation by name.

in_process_only()

@spec in_process_only() :: [atom()]

Relations that only the in-process passes read; no Souffle program does.

layer_1()

@spec layer_1() :: [relation()]

Returns layer 1 (generic bytecode) relation definitions.

layer_2()

@spec layer_2() :: [relation()]

Returns layer 2 (domain extractor) relation definitions.

names()

@spec names() :: [atom()]

Returns all relation names.

souffle_decls(layer)

@spec souffle_decls(:layer_1 | :layer_2 | :all) :: String.t()

Renders a complete .dl declaration file for a layer.

Every relation in the layer gets a .decl and a matching .input, so a rules file that includes this never has to declare a fact relation itself. Declaring more than a given analysis reads is free: Souffle prunes unused input relations during compilation, which is why each analysis's true input set (Argus.Analysis.input_relations/1, read out of the transformed RAM) stays narrow regardless of what was declared. Unused derived relations are not pruned, which is why rule fragments still have to be included deliberately.

Written to disk by mix argus.gen.dl and checked byte-for-byte by the test suite. Hand-editing the generated files is the failure mode this exists to remove: the declarations are positional, and Souffle will not notice a field reordered against what the emitter actually writes.

layer is :layer_1, :layer_2, or :all.

version()

@spec version() :: pos_integer()

The fact-schema version, asserted by in-process consumers at compile time.

Bumped whenever a relation is added/removed, any field changes name, position, or kind, or a field's meaning changes. Independent of the package version.