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.

findModule

Elf.findModule
fn findModule(si: *SelfInfo, gpa: Allocator, io: Io, address: usize, lock: enum

File

Code

fn findModule(si: *SelfInfo, gpa: Allocator, io: Io, address: usize, lock: enum { shared, exclusive }) Error!*Module {
    // With the requested lock, scan the module ranges looking for `address`.
    switch (lock) {
        .shared => si.rwlock.lockSharedUncancelable(io),
        .exclusive => si.rwlock.lockUncancelable(io),
    }
    for (si.ranges.items) |*range| {
        if (address >= range.start and address < range.start + range.len) {
            return &si.modules.items[range.module_index];
        }
    }
    // The address wasn't in a known range. We will rebuild the module/range lists, since it's possible
    // a new module was loaded. Upgrade to an exclusive lock if necessary.
    switch (lock) {
        .shared => {
            si.rwlock.unlockShared(io);
            si.rwlock.lockUncancelable(io);
        },
        .exclusive => {},
    }
    // Rebuild module list with the exclusive lock.
    {
        errdefer si.rwlock.unlock(io);
        if (si.unwind_cache) |cache| {
            @memset(cache, .empty);
        }
        for (si.modules.items) |*mod| {
            unwind: {
                const u = &(mod.unwind orelse break :unwind catch break :unwind);
                for (u.buf[0..u.len]) |*unwind| unwind.deinit(gpa);
            }
            loaded: {
                const l = &(mod.loaded_elf orelse break :loaded catch break :loaded);
                l.file.deinit(gpa);
            }
        }
        si.modules.clearRetainingCapacity();
        si.ranges.clearRetainingCapacity();
        var ctx: DlIterContext = .{ .si = si, .gpa = gpa };
        try std.posix.dl_iterate_phdr(&ctx, error{OutOfMemory}, DlIterContext.callback);
    }
    // Downgrade the lock back to shared if necessary.
    switch (lock) {
        .shared => {
            si.rwlock.unlock(io);
            si.rwlock.lockSharedUncancelable(io);
        },
        .exclusive => {},
    }
    // Scan the newly rebuilt module ranges.
    for (si.ranges.items) |*range| {
        if (address >= range.start and address < range.start + range.len) {
            return &si.modules.items[range.module_index];
        }
    }
    // Still nothing; unlock and error.
    switch (lock) {
        .shared => si.rwlock.unlockShared(io),
        .exclusive => si.rwlock.unlock(io),
    }
    return error.MissingDebugInfo;
}