lib/tldr/src/formats/elf/object/test.zig
daab053ee43316e1809a84551d573ddd1e5bf3d2
1 const std = @import("std");
2
3 const tldr = @import("../../../root.zig");
4 const elf = @import("../root.zig");
5 const object = @import("root.zig");
6
7 const Section = object.Section;
8 const Symbol = object.Symbol;
9 const Relocation = object.Relocation;
10
11 test {
12 std.testing.refAllDecls(object);
13 }
14
15 const text_bytes = "\x31\xc0\xc3\x90";
16 const data_bytes = "\x01\x02\x03\x04\x05\x06\x07\x08";
17
18 test "ELF object round trips through the parser and the linker" {
19 const allocator = std.testing.allocator;
20 const bytes = try object.build(allocator, .{
21 .sections = &.{
22 Section.progbits(".text", text_bytes, std.elf.SHF_EXECINSTR, 16),
23 Section.progbits(".data", data_bytes, std.elf.SHF_WRITE, 8),
24 Section.nobits(".bss", 32, std.elf.SHF_WRITE, 8),
25 },
26 .symbols = &.{
27 Symbol.section(1),
28 Symbol.section(2),
29 Symbol.function("_start", 1, 0, 4),
30 Symbol.object("counter", 2, 0, 8),
31 },
32 .relocations = &.{Relocation.x86_64(2, 0, 3, .@"64", 0)},
33 });
34 defer allocator.free(bytes);
35
36 var parsed = try tldr.parseObject(allocator, .{ .name = "object.o", .bytes = bytes });
37 defer parsed.deinit(allocator);
38 try std.testing.expectEqual(tldr.model.Architecture.x86_64, parsed.target.architecture);
39 try std.testing.expect(findSection(parsed, ".text") != null);
40 try std.testing.expect(findSection(parsed, ".bss") != null);
41 try std.testing.expect(findSymbol(parsed, "_start") != null);
42 try std.testing.expect(findSymbol(parsed, "counter") != null);
43
44 const inputs = [_]tldr.Input{.{ .name = "object.o", .bytes = bytes }};
45 var linked = try elf.linkExecutable(allocator, &inputs, .{});
46 defer linked.deinit(allocator);
47
48 const image = try elf.view.View.parse(linked.bytes);
49 try std.testing.expectEqual(std.elf.ET.EXEC, image.header.type);
50 try std.testing.expect(image.header.phnum != 0);
51 try std.testing.expect((try image.find(".text")) != null);
52 }
53
54 fn findSection(parsed: tldr.Object, name: []const u8) ?tldr.ObjectSection {
55 for (parsed.sections) |section| {
56 if (std.mem.eql(u8, section.name, name)) return section;
57 }
58 return null;
59 }
60
61 fn findSymbol(parsed: tldr.Object, name: []const u8) ?tldr.ObjectSymbol {
62 for (parsed.symbols) |symbol| {
63 if (std.mem.eql(u8, symbol.name, name)) return symbol;
64 }
65 return null;
66 }