Zig 0.17.0-dev (Split by item)

This is an example of documentation generated by ZigDoc, an alternative to Zig's built-in Auto Doc feature. See also examples in other modes/formats. The project being documented here (as the example) is the Zig library itself.

getModule

Pdb.getModule
pub fn getModule(self: *Pdb, index: usize) !?*Module

File

lib/std/debug/Pdb.zig:844

Code

pub fn getModule(self: *Pdb, index: usize) !?*Module {
    if (index >= self.modules.len)
        return null;

    const mod = &self.modules[index];
    if (mod.populated)
        return mod;

    // At most one can be non-zero.
    if (mod.mod_info.c11_byte_size != 0 and mod.mod_info.c13_byte_size != 0)
        return error.InvalidDebugInfo;
    if (mod.mod_info.c13_byte_size == 0)
        return error.InvalidDebugInfo;

    const stream = self.getStreamById(mod.mod_info.module_sym_stream) orelse
        return error.MissingDebugInfo;
    const reader = &stream.interface;

    const signature = try reader.takeInt(u32, .little);
    if (signature != 4)
        return error.InvalidDebugInfo;

    const gpa = self.allocator;

    mod.symbols = try reader.readAlloc(gpa, mod.mod_info.sym_byte_size - 4);
    errdefer gpa.free(mod.symbols);
    mod.subsect_info = try reader.readAlloc(gpa, mod.mod_info.c13_byte_size);
    errdefer gpa.free(mod.subsect_info);
    mod.inlinee_source_lines = b: {
        var inlinee_source_lines: std.ArrayList(*align(1) const pdb.InlineeSourceLine) = .empty;
        defer inlinee_source_lines.deinit(gpa);
        var subsects: Io.Reader = .fixed(mod.subsect_info);
        while (subsects.takeStructPointer(pdb.DebugSubsectionHeader) catch null) |subsect_hdr| {
            var subsect: Io.Reader = .fixed(subsects.take(subsect_hdr.length) catch return null);
            if (subsect_hdr.kind == .inlinee_lines) {
                const inlinee_source_line_signature = subsect.takeEnum(pdb.InlineeSourceLineSignature, .little) catch return error.InvalidDebugInfo;
                const has_extra_files = switch (inlinee_source_line_signature) {
                    .normal => false,
                    .ex => true,
                    else => continue,
                };
                while (subsect.takeStructPointer(pdb.InlineeSourceLine) catch null) |info| {
                    if (has_extra_files) {
                        const file_count = subsect.takeInt(u32, .little) catch
                            return error.InvalidDebugInfo;
                        const file_bytes = std.math.mul(usize, file_count, @sizeOf(u32)) catch return error.InvalidDebugInfo;
                        subsect.discardAll(file_bytes) catch
                            return error.InvalidDebugInfo;
                    }

                    try inlinee_source_lines.append(gpa, info);
                }
            }
        }

        std.mem.sortUnstable(
            *align(1) const pdb.InlineeSourceLine,
            inlinee_source_lines.items,
            {},
            inlineeSourceLineLessThan,
        );
        break :b try inlinee_source_lines.toOwnedSlice(gpa);
    };
    errdefer gpa.free(mod.inlinee_source_lines);

    var sect_offset: usize = 0;
    var skip_len: usize = undefined;
    while (sect_offset != mod.subsect_info.len) : (sect_offset += skip_len) {
        const subsect_hdr: *align(1) pdb.DebugSubsectionHeader = @ptrCast(&mod.subsect_info[sect_offset]);
        skip_len = subsect_hdr.length;
        sect_offset += @sizeOf(pdb.DebugSubsectionHeader);

        switch (subsect_hdr.kind) {
            .file_checksums => {
                mod.checksum_offset = sect_offset;
                break;
            },
            else => {},
        }

        if (sect_offset > mod.subsect_info.len)
            return error.InvalidDebugInfo;
    }

    mod.populated = true;
    return mod;
}