authorgravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2022-06-22 22:40:05+02:00
committergravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2022-06-22 22:40:05+02:00
loge6c012c7432a6de409bf08eb7964b3d99fe4362e
tree84e92264c5cdcfae042b873fa4eed073b8f889bb
parent51f2442fc4160415796cf6271d1951969ab71c83

link-tests: add better docs


1 files changed, 28 insertions(+), 0 deletions(-)

lib/std/build/CheckObjectStep.zig+28
...@@ -41,9 +41,22 @@ const Action = union(enum) {...@@ -41,9 +41,22 @@ const Action = union(enum) {
41 compute_eq: ComputeEqAction,41 compute_eq: ComputeEqAction,
42};42};
4343
44/// MatchAction is the main building block of standard matchers with optional eat-all token `{*}`
45/// and extractors by name such as `{n_value}`. Please note this action is very simplistic in nature
46/// i.e., it won't really handle edge cases/nontrivial examples. But given that we do want to use
47/// it mainly to test the output of our object format parser-dumpers when testing the linkers, etc.
48/// it should be plenty useful in its current form.
44const MatchAction = struct {49const MatchAction = struct {
45 needle: []const u8,50 needle: []const u8,
4651
52 /// Will return true if the `needle` was found in the `haystack`.
53 /// Some examples include:
54 ///
55 /// LC 0 => will match in its entirety
56 /// vmaddr {vmaddr} => will match `vmaddr` and then extract the following value as u64
57 /// and save under `vmaddr` global name (see `global_vars` param)
58 /// name {*}libobjc{*}.dylib => will match `name` followed by a token which contains `libobjc` and `.dylib`
59 /// in that order with other letters in between
47 fn match(act: MatchAction, haystack: []const u8, global_vars: anytype) !bool {60 fn match(act: MatchAction, haystack: []const u8, global_vars: anytype) !bool {
48 var hay_it = mem.tokenize(u8, mem.trim(u8, haystack, " "), " ");61 var hay_it = mem.tokenize(u8, mem.trim(u8, haystack, " "), " ");
49 var needle_it = mem.tokenize(u8, mem.trim(u8, act.needle, " "), " ");62 var needle_it = mem.tokenize(u8, mem.trim(u8, act.needle, " "), " ");
...@@ -81,6 +94,12 @@ const MatchAction = struct {...@@ -81,6 +94,12 @@ const MatchAction = struct {
81 }94 }
82};95};
8396
97/// ComputeEqAction can be used to perform an operation on the extracted global variables
98/// using the MatchAction. It currently only supports an addition. The operation is required
99/// to be specified in Reverse Polish Notation to ease in operator-precedence parsing (well,
100/// to avoid any parsing really).
101/// For example, if the two extracted values were saved as `vmaddr` and `entryoff` respectively
102/// they could then be added with this simple program `vmaddr entryoff +`.
84const ComputeEqAction = struct {103const ComputeEqAction = struct {
85 expected: []const u8,104 expected: []const u8,
86 var_stack: std.ArrayList([]const u8),105 var_stack: std.ArrayList([]const u8),
...@@ -115,23 +134,32 @@ const Check = struct {...@@ -115,23 +134,32 @@ const Check = struct {
115 }134 }
116};135};
117136
137/// Creates a new sequence of actions with `phrase` as the first anchor searched phrase.
118pub fn check(self: *CheckObjectStep, phrase: []const u8) void {138pub fn check(self: *CheckObjectStep, phrase: []const u8) void {
119 var new_check = Check.create(self.builder);139 var new_check = Check.create(self.builder);
120 new_check.match(phrase);140 new_check.match(phrase);
121 self.checks.append(new_check) catch unreachable;141 self.checks.append(new_check) catch unreachable;
122}142}
123143
144/// Adds another searched phrase to the latest created Check with `CheckObjectStep.check(...)`.
145/// Asserts at least one check already exists.
124pub fn checkNext(self: *CheckObjectStep, phrase: []const u8) void {146pub fn checkNext(self: *CheckObjectStep, phrase: []const u8) void {
125 assert(self.checks.items.len > 0);147 assert(self.checks.items.len > 0);
126 const last = &self.checks.items[self.checks.items.len - 1];148 const last = &self.checks.items[self.checks.items.len - 1];
127 last.match(phrase);149 last.match(phrase);
128}150}
129151
152/// Creates a new check checking specifically symbol table parsed and dumped from the object
153/// file.
154/// Issuing this check will force parsing and dumping of the symbol table.
130pub fn checkInSymtab(self: *CheckObjectStep) void {155pub fn checkInSymtab(self: *CheckObjectStep) void {
131 self.dump_symtab = true;156 self.dump_symtab = true;
132 self.check("symtab");157 self.check("symtab");
133}158}
134159
160/// Creates a new standalone, singular check which allows running simple binary operations
161/// on the extracted variables. It will then compare the reduced program with the value of
162/// the expected variable.
135pub fn checkComputeEq(self: *CheckObjectStep, program: []const u8, expected: []const u8) void {163pub fn checkComputeEq(self: *CheckObjectStep, program: []const u8, expected: []const u8) void {
136 const gpa = self.builder.allocator;164 const gpa = self.builder.allocator;
137 var ca = ComputeEqAction{165 var ca = ComputeEqAction{