make
Function parameters
Parameters
- step:*Step
- make_options:Step.MakeOptions
Functions in this namespace
Functions
- checkExact
- Adds an exact match phrase to the latest created Check.
- checkExactPath
- Like `checkExact()` but takes an additional argument `LazyPath` which will be
- checkContains
- Adds a fuzzy match phrase to the latest created Check.
- checkContainsPath
- Like `checkContains()` but takes an additional argument `lazy_path` which will be
- checkExtract
- Adds an exact match phrase with variable extractor to the latest created Check.
- checkExtractLazyPath
- Like `checkExtract()` but takes an additional argument `LazyPath` which will be
- checkNotPresent
- Adds another searched phrase to the latest created Check
- checkNotPresentLazyPath
- Like `checkExtract()` but takes an additional argument `LazyPath` which will be
- checkInHeaders
- Creates a new check checking in the file headers (section, program headers, etc.).
- checkInSymtab
- Creates a new check checking specifically symbol table parsed and dumped from the object
- checkInDyldRebase
- Creates a new check checking specifically dyld rebase opcodes contents parsed and dumped
- checkInDyldBind
- Creates a new check checking specifically dyld bind opcodes contents parsed and dumped
- checkInDyldWeakBind
- Creates a new check checking specifically dyld weak bind opcodes contents parsed and dumped
- checkInDyldLazyBind
- Creates a new check checking specifically dyld lazy bind opcodes contents parsed and dumped
- checkInExports
- Creates a new check checking specifically exports info contents parsed and dumped
- checkInIndirectSymtab
- Creates a new check checking specifically indirect symbol table parsed and dumped
- checkInDynamicSymtab
- Creates a new check checking specifically dynamic symbol table parsed and dumped from the object
- checkInDynamicSection
- Creates a new check checking specifically dynamic section parsed and dumped from the object
- checkInArchiveSymtab
- Creates a new check checking specifically symbol table parsed and dumped from the archive
- checkComputeCompare
- Creates a new standalone, singular check which allows running simple binary operations
= .check_object
Values
- base_id
- = .check_object
Source
Implementation
fn make(step: *Step, make_options: Step.MakeOptions) !void {
_ = make_options;
const b = step.owner;
const gpa = b.allocator;
const check_object: *CheckObject = @fieldParentPtr("step", step);
try step.singleUnchangingWatchInput(check_object.source);
const src_path = check_object.source.getPath3(b, step);
const contents = src_path.root_dir.handle.readFileAllocOptions(
gpa,
src_path.sub_path,
check_object.max_bytes,
null,
.of(u64),
null,
) catch |err| return step.fail("unable to read '{f}': {s}", .{
std.fmt.alt(src_path, .formatEscapeChar), @errorName(err),
});
var vars: std.StringHashMap(u64) = .init(gpa);
for (check_object.checks.items) |chk| {
if (chk.kind == .compute_compare) {
assert(chk.actions.items.len == 1);
const act = chk.actions.items[0];
assert(act.tag == .compute_cmp);
const res = act.computeCmp(b, step, vars) catch |err| switch (err) {
error.UnknownVariable => return step.fail("Unknown variable", .{}),
else => |e| return e,
};
if (!res) {
return step.fail(
\\
\\========= comparison failed for action: ===========
\\{s} {f}
\\===================================================
, .{ act.phrase.resolve(b, step), act.expected.? });
}
continue;
}
const output = switch (check_object.obj_format) {
.macho => try MachODumper.parseAndDump(step, chk, contents),
.elf => try ElfDumper.parseAndDump(step, chk, contents),
.coff => return step.fail("TODO coff parser", .{}),
.wasm => try WasmDumper.parseAndDump(step, chk, contents),
else => unreachable,
};
// Depending on whether we requested dumping section verbatim or not,
// we either format message string with escaped codes, or not to aid debugging
// the failed test.
const fmtMessageString = struct {
fn fmtMessageString(kind: Check.Kind, msg: []const u8) std.fmt.Formatter(Ctx, formatMessageString) {
return .{ .data = .{
.kind = kind,
.msg = msg,
} };
}
const Ctx = struct {
kind: Check.Kind,
msg: []const u8,
};
fn formatMessageString(ctx: Ctx, w: *Writer) !void {
switch (ctx.kind) {
.dump_section => try w.print("{f}", .{std.ascii.hexEscape(ctx.msg, .lower)}),
else => try w.writeAll(ctx.msg),
}
}
}.fmtMessageString;
var it = mem.tokenizeAny(u8, output, "\r\n");
for (chk.actions.items) |act| {
switch (act.tag) {
.exact => {
while (it.next()) |line| {
if (act.exact(b, step, line)) break;
} else {
return step.fail(
\\
\\========= expected to find: ==========================
\\{f}
\\========= but parsed file does not contain it: =======
\\{f}
\\========= file path: =================================
\\{f}
, .{
fmtMessageString(chk.kind, act.phrase.resolve(b, step)),
fmtMessageString(chk.kind, output),
src_path,
});
}
},
.contains => {
while (it.next()) |line| {
if (act.contains(b, step, line)) break;
} else {
return step.fail(
\\
\\========= expected to find: ==========================
\\*{f}*
\\========= but parsed file does not contain it: =======
\\{f}
\\========= file path: =================================
\\{f}
, .{
fmtMessageString(chk.kind, act.phrase.resolve(b, step)),
fmtMessageString(chk.kind, output),
src_path,
});
}
},
.not_present => {
while (it.next()) |line| {
if (act.notPresent(b, step, line)) continue;
return step.fail(
\\
\\========= expected not to find: ===================
\\{f}
\\========= but parsed file does contain it: ========
\\{f}
\\========= file path: ==============================
\\{f}
, .{
fmtMessageString(chk.kind, act.phrase.resolve(b, step)),
fmtMessageString(chk.kind, output),
src_path,
});
}
},
.extract => {
while (it.next()) |line| {
if (try act.extract(b, step, line, &vars)) break;
} else {
return step.fail(
\\
\\========= expected to find and extract: ==============
\\{f}
\\========= but parsed file does not contain it: =======
\\{f}
\\========= file path: ==============================
\\{f}
, .{
fmtMessageString(chk.kind, act.phrase.resolve(b, step)),
fmtMessageString(chk.kind, output),
src_path,
});
}
},
.compute_cmp => unreachable,
}
}
}
}