Files
Interpreter/vm/src/Image.cpp
T
Admin dbedc17032 阶段4-2a:vm/Image V2(头 128B/6 段校验/槽表访问器)
- 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)
2026-08-26 09:59:18 +08:00

406 lines
14 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
/**
* @file Image.cpp
* @brief vm 自带的 .stb 只读视图实现(执行器侧;compiler 各有实现,V2
* @author
* @date 2026-08-21
*/
#include "vm/Image.h"
#include <cstring>
#include <string>
namespace vm {
namespace {
/// 映像魔数:"STSC" 小端。
const uint32_t kMagic = 0x43545353u;
/// 映像格式版本(V2)。
const uint32_t kVersion = 2;
/// 映像头字节数(V2:128)。
const size_t kHeaderSize = 128;
/// 常量表一行字节数(value:8,无 tag)。
const size_t kConstEntrySize = 8;
/// 函数表一行字节数(nregs/code_offset/code_len 各 4)。
const size_t kFuncRowSize = 12;
/// 槽表一行字节数(addr:4 + 预留:4)。
const size_t kSlotRowSize = 8;
/// SHA-256 摘要长度(文件尾)。
const size_t kSha256Size = 32;
/// 型号标识长度(头内 @72,不足补 '\0')。
const size_t kModelIdSize = 32;
// ---- 头字段偏移(与 Doc/isa/指令与映像.md §8.1 一致;compiler 侧另有同值一份)----
constexpr size_t kOffMagic = 0; ///< 魔数 "STSC"
constexpr size_t kOffVersion = 4; ///< 格式版本(V2 = 2
constexpr size_t kOffCycleLimit = 8; ///< 每周期指令数上限
constexpr size_t kOffDtMs = 12; ///< 周期时长(毫秒)
constexpr size_t kOffProjectHash = 16; ///< 工程哈希(8 字节)
constexpr size_t kOffEntryFnId = 24; ///< 入口函数 fn_id
constexpr size_t kOffNGlobals = 28; ///< 全局槽数
constexpr size_t kOffNI = 32; ///< 输入(I)槽数(保留恒 0)
constexpr size_t kOffNQ = 36; ///< 输出(Q)槽数(保留恒 0)
constexpr size_t kOffNM = 40; ///< 中间(M)槽数(保留恒 0)
constexpr size_t kOffNConsts = 44; ///< 常量表条目数
constexpr size_t kOffNFuncs = 48; ///< 函数表行数
constexpr size_t kOffConst = 52; ///< 常量表段偏移
constexpr size_t kOffFuncs = 56; ///< 函数表段偏移
constexpr size_t kOffCode = 60; ///< 字节码段偏移
constexpr size_t kOffSlots = 64; ///< 槽表段偏移
constexpr size_t kOffValues = 68; ///< 值段偏移
constexpr size_t kOffModelId = 72; ///< 型号标识[32]
constexpr size_t kOffNSlots = 104; ///< 槽表条目数
constexpr size_t kOffValuesSize = 108; ///< 值段字节数
constexpr size_t kOffMeta = 112; ///< 元数据段偏移(0 = 空段)
constexpr size_t kOffMaxStack = 116; ///< 栈区字节数
// ---- 段内行偏移 ----
constexpr size_t kConstValueOff = 0; ///< 常量表行内:value8 字节)
constexpr size_t kFuncNregsOff = 0; ///< 函数表行内:nregs
constexpr size_t kFuncCodeOff = 4; ///< 函数表行内:code_offset(字节)
constexpr size_t kFuncLenOff = 8; ///< 函数表行内:code_len(字节)
constexpr size_t kSlotAddrOff = 0; ///< 槽表行内:addr
uint32_t get_le32(const uint8_t* p) {
return static_cast<uint32_t>(p[0])
| (static_cast<uint32_t>(p[1]) << 8)
| (static_cast<uint32_t>(p[2]) << 16)
| (static_cast<uint32_t>(p[3]) << 24);
}
uint64_t get_le64(const uint8_t* p) {
uint64_t v = 0;
for (int i = 0; i < 8; ++i) {
v |= static_cast<uint64_t>(p[i]) << (8 * i);
}
return v;
}
// ---- SHA-256(执行器侧实现,与 compiler 各一份)----
const uint32_t kShaK[64] = {
0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, 0x3956c25b, 0x59f111f1,
0x923f82a4, 0xab1c5ed5, 0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3,
0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174, 0xe49b69c1, 0xefbe4786,
0x0fc19dc6, 0x240ca1cc, 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da,
0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7, 0xc6e00bf3, 0xd5a79147,
0x06ca6351, 0x14292967, 0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13,
0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85, 0xa2bfe8a1, 0xa81a664b,
0xc24b8b70, 0xc76c51a3, 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070,
0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5, 0x391c0cb3, 0x4ed8aa4a,
0x5b9cca4f, 0x682e6ff3, 0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208,
0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2,
};
inline uint32_t rotr(uint32_t x, uint32_t n) { return (x >> n) | (x << (32 - n)); }
struct Sha256 {
uint32_t h[8] = {0x6a09e667, 0xbb67ae85, 0x3c6ef372, 0xa54ff53a,
0x510e527f, 0x9b05688c, 0x1f83d9ab, 0x5be0cd19}; ///< 初始哈希值
uint64_t total = 0; ///< 已吸收字节数(final 时编码进长度域)
uint8_t block[64]; ///< 当前块缓冲
size_t block_len = 0; ///< 块缓冲已用字节数
void update(const uint8_t* data, size_t len) {
total += len;
while (len > 0) {
const size_t n = (block_len < 64) ? (64 - block_len) : 0;
const size_t take = len < n ? len : n;
if (take == 0) {
break;
}
for (size_t i = 0; i < take; ++i) {
block[block_len + i] = data[i];
}
block_len += take;
data += take;
len -= take;
if (block_len == 64) {
process();
block_len = 0;
}
}
}
void process() {
uint32_t w[64];
for (int i = 0; i < 16; ++i) {
w[i] = get_be32(block + i * 4);
}
for (int i = 16; i < 64; ++i) {
const uint32_t s0 = rotr(w[i - 15], 7) ^ rotr(w[i - 15], 18) ^ (w[i - 15] >> 3);
const uint32_t s1 = rotr(w[i - 2], 17) ^ rotr(w[i - 2], 19) ^ (w[i - 2] >> 10);
w[i] = w[i - 16] + s0 + w[i - 7] + s1;
}
uint32_t a = h[0], b = h[1], c = h[2], d = h[3];
uint32_t e = h[4], f = h[5], g = h[6], hh = h[7];
for (int i = 0; i < 64; ++i) {
const uint32_t s1 = rotr(e, 6) ^ rotr(e, 11) ^ rotr(e, 25);
const uint32_t ch = (e & f) ^ (~e & g);
const uint32_t t1 = hh + s1 + ch + kShaK[i] + w[i];
const uint32_t s0 = rotr(a, 2) ^ rotr(a, 13) ^ rotr(a, 22);
const uint32_t maj = (a & b) ^ (a & c) ^ (b & c);
const uint32_t t2 = s0 + maj;
hh = g;
g = f;
f = e;
e = d + t1;
d = c;
c = b;
b = a;
a = t1 + t2;
}
h[0] += a; h[1] += b; h[2] += c; h[3] += d;
h[4] += e; h[5] += f; h[6] += g; h[7] += hh;
}
void final(uint8_t out[32]) {
const uint64_t bitlen = total * 8;
const uint8_t pad = 0x80;
update(&pad, 1);
const uint8_t zeros[64] = {0};
while (block_len != 56) {
const size_t n = (block_len < 56) ? (56 - block_len) : (64 - block_len);
update(zeros, n);
}
for (int i = 0; i < 8; ++i) {
const uint8_t b2[1] = {static_cast<uint8_t>((bitlen >> (56 - 8 * i)) & 0xFF)};
update(b2, 1);
}
for (int i = 0; i < 8; ++i) {
out[i * 4 + 0] = static_cast<uint8_t>((h[i] >> 24) & 0xFF);
out[i * 4 + 1] = static_cast<uint8_t>((h[i] >> 16) & 0xFF);
out[i * 4 + 2] = static_cast<uint8_t>((h[i] >> 8) & 0xFF);
out[i * 4 + 3] = static_cast<uint8_t>(h[i] & 0xFF);
}
}
static uint32_t get_be32(const uint8_t* p) {
return (static_cast<uint32_t>(p[0]) << 24) | (static_cast<uint32_t>(p[1]) << 16) |
(static_cast<uint32_t>(p[2]) << 8) | static_cast<uint32_t>(p[3]);
}
};
void sha256(const uint8_t* data, size_t len, uint8_t out[32]) {
Sha256 s;
s.update(data, len);
s.final(out);
}
void fill_model_id(const std::string& name, uint32_t version, char out[32]) {
const std::string id = name + std::to_string(version);
for (size_t i = 0; i < 32; ++i) {
out[i] = i < id.size() ? id[i] : '\0';
}
}
} // namespace
/**
* @brief 从原始字节构造只读视图(不拷贝,调用方保证生命周期)。
*/
Image Image::from(const uint8_t* buf, size_t len) {
Image v;
v.buf_ = buf;
v.len_ = len;
if (buf == nullptr) {
v.err_ = "null buffer";
return v;
}
if (len < kHeaderSize) {
v.err_ = "image too short";
return v;
}
if (get_le32(buf + kOffMagic) != kMagic) {
v.err_ = "bad magic";
return v;
}
if (get_le32(buf + kOffVersion) != kVersion) {
v.err_ = "bad version";
return v;
}
ImageHeader& h = v.hdr_;
h.cycle_limit = get_le32(buf + kOffCycleLimit);
h.dt_ms = get_le32(buf + kOffDtMs);
h.project_hash = get_le64(buf + kOffProjectHash);
h.entry_fn_id = get_le32(buf + kOffEntryFnId);
h.n_globals = get_le32(buf + kOffNGlobals);
h.n_i = get_le32(buf + kOffNI);
h.n_q = get_le32(buf + kOffNQ);
h.n_m = get_le32(buf + kOffNM);
h.n_consts = get_le32(buf + kOffNConsts);
h.n_funcs = get_le32(buf + kOffNFuncs);
h.offset_const = get_le32(buf + kOffConst);
h.offset_funcs = get_le32(buf + kOffFuncs);
h.offset_code = get_le32(buf + kOffCode);
h.offset_slots = get_le32(buf + kOffSlots);
h.offset_values = get_le32(buf + kOffValues);
h.n_slots = get_le32(buf + kOffNSlots);
h.values_size = get_le32(buf + kOffValuesSize);
h.offset_meta = get_le32(buf + kOffMeta);
h.max_stack = get_le32(buf + kOffMaxStack);
// 段校验(V2:值段之后是 SHA-256 文件尾;元数据段 0 = 空段)
if (len < static_cast<size_t>(h.offset_values) + kSha256Size) {
v.err_ = "missing sha256 tail";
return v;
}
const uint64_t offs[5] = {h.offset_const, h.offset_funcs, h.offset_code, h.offset_slots,
h.offset_values};
for (int i = 0; i < 5; ++i) {
if (offs[i] < kHeaderSize || offs[i] > len - kSha256Size) {
v.err_ = "segment offset out of range";
return v;
}
if (i > 0 && offs[i] < offs[i - 1]) {
v.err_ = "segment offsets not monotonic";
return v;
}
}
if (offs[1] - offs[0] != static_cast<uint64_t>(h.n_consts) * kConstEntrySize) {
v.err_ = "const table size mismatch";
return v;
}
if (offs[2] - offs[1] != static_cast<uint64_t>(h.n_funcs) * kFuncRowSize) {
v.err_ = "function table size mismatch";
return v;
}
if (offs[4] - offs[3] != static_cast<uint64_t>(h.n_slots) * kSlotRowSize) {
v.err_ = "slot table size mismatch";
return v;
}
// 值段大小:meta 段为 0(空段)时值段到 SHA 尾;否则到 meta 起点
if (h.offset_meta != 0) {
if (static_cast<uint64_t>(h.offset_meta) - offs[4] != h.values_size) {
v.err_ = "values segment size mismatch";
return v;
}
} else if (static_cast<uint64_t>(len - kSha256Size) - offs[4] != h.values_size) {
v.err_ = "values segment size mismatch";
return v;
}
if ((h.offset_slots - h.offset_code) % 4 != 0) {
v.err_ = "code segment not aligned";
return v;
}
if (h.entry_fn_id >= h.n_funcs && h.n_funcs != 0) {
v.err_ = "entry fn_id out of range";
return v;
}
v.ok_ = true;
v.err_.clear();
return v;
}
/**
* @brief 从 vector 构造只读视图。
*/
Image Image::from(const std::vector<uint8_t>& buf) {
return from(buf.data(), buf.size());
}
/**
* @brief 读函数表一行。
*/
FuncRow Image::func_row(size_t i) const {
FuncRow r;
if (ok_ && i < hdr_.n_funcs) {
const uint8_t* p = buf_ + hdr_.offset_funcs + i * kFuncRowSize;
r.nregs = get_le32(p + kFuncNregsOff);
r.code_offset = get_le32(p + kFuncCodeOff);
r.code_len = get_le32(p + kFuncLenOff);
}
return r;
}
/**
* @brief 读常量表一项(8B 原始值)。
*/
ConstEntry Image::const_entry(size_t i) const {
ConstEntry e;
if (ok_ && i < hdr_.n_consts) {
const uint8_t* p = buf_ + hdr_.offset_const + i * kConstEntrySize;
e.value = get_le64(p + kConstValueOff);
}
return e;
}
/**
* @brief 读槽表一项的地址(值段内偏移)。
*/
uint32_t Image::slot_addr(size_t i) const {
if (ok_ && i < hdr_.n_slots) {
const uint8_t* p = buf_ + hdr_.offset_slots + i * kSlotRowSize;
return get_le32(p + kSlotAddrOff);
}
return 0;
}
/**
* @brief 槽表段起点。
*/
const uint8_t* Image::slots_bytes() const {
return ok_ ? buf_ + hdr_.offset_slots : nullptr;
}
/**
* @brief 字节码段起点。
*/
const uint8_t* Image::code_bytes() const {
return ok_ ? buf_ + hdr_.offset_code : nullptr;
}
/**
* @brief 值段起点。
*/
const uint8_t* Image::data_bytes() const {
return ok_ ? buf_ + hdr_.offset_values : nullptr;
}
/**
* @brief 值段字节数。
*/
size_t Image::data_len() const {
return ok_ ? (len_ - kSha256Size) - hdr_.offset_values : 0;
}
/**
* @brief 型号标识字符串。
*/
std::string Image::model_id() const {
if (!ok_) {
return "";
}
std::string s(reinterpret_cast<const char*>(buf_ + kOffModelId), kModelIdSize);
const size_t z = s.find('\0');
if (z != std::string::npos) {
s.resize(z);
}
return s;
}
/**
* @brief 型号标识是否匹配。
*/
bool Image::model_matches(const std::string& name, uint32_t version) const {
char want[kModelIdSize];
fill_model_id(name, version, want);
return std::memcmp(buf_ + kOffModelId, want, kModelIdSize) == 0;
}
/**
* @brief 文件尾 SHA-256 完整性校验。
*/
bool Image::sha_ok() const {
if (!ok_) {
return false;
}
const size_t content_len = len_ - kSha256Size;
uint8_t digest[32];
sha256(buf_, content_len, digest);
return std::memcmp(buf_ + content_len, digest, 32) == 0;
}
} // namespace vm