- ImageHeader:V2 字段(offset_slots/offset_values + n_slots/values_size/ offset_meta/max_stack);kModelVersion=2(STATOR2) - 段校验:const/funcs/code/slots/values + meta=0 空段处理、尺寸一致性、对齐 - 常量表 8B 无 tag;FuncRow.code_len 字节;slot_addr/slots_bytes 访问器 - 验证:V2 产物解析 ok、model_matches(STATOR,2)/sha 校验通过 - 状态:Machine.cpp 仍破(4-2b)
163 lines
6.7 KiB
C++
163 lines
6.7 KiB
C++
/**
|
||
* @file Image.h
|
||
* @brief vm 自带的 .stb 只读视图(执行器侧;compiler 各有实现,V2)
|
||
* @author
|
||
* @date 2026-08-21
|
||
*
|
||
* @details 格式契约见 Doc/isa/指令与映像.md(V2:头 128B、version=2、型号 STATOR2、
|
||
* 常量表 8B 无 tag、槽表段 8B/条 {addr,预留}、值段变宽紧凑、文件尾 SHA-256[32])。
|
||
* 解析头与段、补型号匹配与 SHA-256 校验都在本模块完成。
|
||
*/
|
||
|
||
#pragma once
|
||
|
||
#include <cstddef>
|
||
#include <cstdint>
|
||
#include <string>
|
||
#include <vector>
|
||
|
||
namespace vm {
|
||
|
||
/// 执行器内建支持型号(与 machine.toml [meta] 对齐;.stb 型号不匹配直接拒绝)。
|
||
static const char* const kModelName = "STATOR";
|
||
/// 执行器内建支持型号版本(V2;型号标识 = "STATOR2")。
|
||
static const uint32_t kModelVersion = 2;
|
||
|
||
/**
|
||
* @brief 映像头字段(V2:128 字节;字段顺序与 Doc/isa/指令与映像.md §8.1 一致)。
|
||
* @details 全部为小端值;型号标识 32 字节 @72 不在此结构内(见 model_id())。
|
||
*/
|
||
struct ImageHeader {
|
||
uint32_t cycle_limit = 0; ///< 每周期指令数上限(超出 → Fault::CycleLimit)
|
||
uint32_t dt_ms = 0; ///< 周期时长(毫秒,定时器/计数器推进步长)
|
||
uint64_t project_hash = 0; ///< 工程哈希(FNV-1a 64,只读展示)
|
||
uint32_t entry_fn_id = 0; ///< 入口函数(PROGRAM MAIN)在函数表的下标
|
||
uint32_t n_globals = 0; ///< 全局变量槽数(槽表最前段)
|
||
uint32_t n_i = 0; ///< 输入槽数(保留恒 0)
|
||
uint32_t n_q = 0; ///< 输出槽数(保留恒 0)
|
||
uint32_t n_m = 0; ///< 中间槽数(保留恒 0)
|
||
uint32_t n_consts = 0; ///< 常量表条目数
|
||
uint32_t n_funcs = 0; ///< 函数表行数
|
||
uint32_t offset_const = 0; ///< 常量表段起点(相对文件头)
|
||
uint32_t offset_funcs = 0; ///< 函数表段起点
|
||
uint32_t offset_code = 0; ///< 字节码段起点
|
||
uint32_t offset_slots = 0; ///< 槽表段起点
|
||
uint32_t offset_values = 0; ///< 值段起点(16 对齐)
|
||
uint32_t n_slots = 0; ///< 槽表条目数(@104)
|
||
uint32_t values_size = 0; ///< 值段字节数(@108)
|
||
uint32_t offset_meta = 0; ///< 元数据段偏移(@112;0 = 空段)
|
||
uint32_t max_stack = 0; ///< 栈区字节数(@116,编译期算)
|
||
};
|
||
|
||
/**
|
||
* @brief 函数表一行(12 字节;code_len 为字节数,变长指令)。
|
||
*/
|
||
struct FuncRow {
|
||
uint32_t nregs = 0; ///< 本函数寄存器数(函数头 nregs)
|
||
uint32_t code_offset = 0; ///< 相对字节码段起点(字节)
|
||
uint32_t code_len = 0; ///< 字节码长度(字节)
|
||
};
|
||
|
||
/**
|
||
* @brief 常量表一项(8 字节:原始位模式,无 tag——LOADK 按 func 位段解释)。
|
||
*/
|
||
struct ConstEntry {
|
||
uint64_t value = 0; ///< 原始 64 位位模式
|
||
};
|
||
|
||
/**
|
||
* @brief 只读视图:指向外部缓冲的校验过的 .stb 映像。
|
||
* @details from() 完成魔数/版本/头/六段/尺寸一致性校验(元数据段 0 = 空段);
|
||
* 型号匹配与 SHA-256 由 model_matches() / sha_ok() 另行查询
|
||
* (Machine::create 里一起做)。所有方法在校验失败(ok() == false)
|
||
* 时返回安全默认值。
|
||
*/
|
||
class Image {
|
||
public:
|
||
/**
|
||
* @brief 从原始字节构造只读视图(不拷贝,调用方保证生命周期)。
|
||
* @param buf 映像缓冲;可为 nullptr
|
||
* @param len 缓冲字节数
|
||
* @return 校验结果;ok() 判成功,error() 取失败原因
|
||
* @details 校验项:非空、长度 ≥ 头、魔数 STSC、版本 2、六段偏移单调且在
|
||
* SHA-256 尾之前、常量表/函数表/槽表尺寸一致、值段大小一致、
|
||
* 代码段对齐、入口 fn_id 在函数表内。
|
||
*/
|
||
static Image from(const uint8_t* buf, size_t len);
|
||
|
||
/**
|
||
* @brief 从 vector 构造只读视图。
|
||
* @param buf 映像缓冲(引用 data(),调用方保证生命周期)
|
||
* @return 同 from(const uint8_t*, size_t)
|
||
*/
|
||
static Image from(const std::vector<uint8_t>& buf);
|
||
|
||
/// @return 校验是否通过。
|
||
bool ok() const { return ok_; }
|
||
|
||
/// @return 校验失败原因;成功时为空串。
|
||
const std::string& error() const { return err_; }
|
||
|
||
/// @return 映像头字段。
|
||
const ImageHeader& header() const { return hdr_; }
|
||
|
||
/**
|
||
* @brief 读函数表一行。
|
||
* @param i 函数下标
|
||
* @return 该行字段;越界(或校验失败)时全 0
|
||
*/
|
||
FuncRow func_row(size_t i) const;
|
||
|
||
/**
|
||
* @brief 读常量表一项(8B 原始值)。
|
||
* @param i 常量下标
|
||
* @return 该条目;越界(或校验失败)时全 0
|
||
*/
|
||
ConstEntry const_entry(size_t i) const;
|
||
|
||
/**
|
||
* @brief 读槽表一项的地址(值段内偏移)。
|
||
* @param i 槽号
|
||
* @return addr;越界(或校验失败)时 0
|
||
*/
|
||
uint32_t slot_addr(size_t i) const;
|
||
|
||
/// @return 槽表段起点;校验失败返回 nullptr。
|
||
const uint8_t* slots_bytes() const;
|
||
|
||
/// @return 字节码段起点;校验失败返回 nullptr。
|
||
const uint8_t* code_bytes() const;
|
||
|
||
/// @return 值段起点;校验失败返回 nullptr。
|
||
const uint8_t* data_bytes() const;
|
||
|
||
/// @return 值段字节数(不含 SHA-256 尾);校验失败返回 0。
|
||
size_t data_len() const;
|
||
|
||
/// @return 型号标识字符串(头 @72 的 32 字节,去 '\0' 截断)。
|
||
std::string model_id() const;
|
||
|
||
/**
|
||
* @brief 型号标识是否匹配。
|
||
* @param name 期望型号名(如 "STATOR")
|
||
* @param version 期望版本(如 2)
|
||
* @return 头内 32 字节与 "name + version" 补零后逐字节相等
|
||
*/
|
||
bool model_matches(const std::string& name, uint32_t version) const;
|
||
|
||
/// @return 文件尾 32 字节是否为内容(去尾后)的 SHA-256。
|
||
bool sha_ok() const;
|
||
|
||
public:
|
||
/// 默认构造为无效态(ok() == false)。
|
||
Image() : buf_(nullptr), len_(0) {}
|
||
|
||
private:
|
||
const uint8_t* buf_; ///< 外部缓冲指针(不持有)
|
||
size_t len_; ///< 缓冲长度
|
||
bool ok_ = false; ///< 校验是否通过
|
||
std::string err_; ///< 失败原因
|
||
ImageHeader hdr_; ///< 解析出的头字段
|
||
};
|
||
}
|