zig icon indicating copy to clipboard operation
zig copied to clipboard

On UEFI, std.debug.ModuleDebugInfo errors at missing fd_t

Open T-rex08 opened this issue 1 year ago • 4 comments

Zig Version

0.12.0-dev.3381+7057bffc1

Steps to Reproduce and Observed Behavior

When compiling to UEFI, the ModuleBuildInfo struct will use std.pdb.Pdb. This PDB struct fails to compile on UEFI because it attempts to use std.os.uefi.fd_t, which doesn't exist.

Example:

const std = @import("std");

pub fn main() void {
    var bytes: [100 * 1024]u8 = undefined;
    var allocator_state = std.heap.FixedBufferAllocator.init(bytes[0..]);
    _ = std.debug.DebugInfo.init(allocator_state.allocator()) catch {};
}

This code currently returns following error (zig build-exe main.zig -target x86_64-uefi-msvc -freference-trace):

/usr/lib/zig/lib/std/os.zig:149:24: error: root struct of file 'os.uefi' has no member named 'fd_t'
pub const fd_t = system.fd_t;
                 ~~~~~~^~~~~
/usr/lib/zig/lib/std/os/uefi.zig:1:1: note: struct declared here
const std = @import("../std.zig");
^~~~~
referenced by:
    Handle: /usr/lib/zig/lib/std/fs/File.zig:4:25
    fs.File: /usr/lib/zig/lib/std/fs/File.zig:2:9
    File: /usr/lib/zig/lib/std/fs.zig:17:26
    File: /usr/lib/zig/lib/std/pdb.zig:8:20
    Pdb: /usr/lib/zig/lib/std/pdb.zig:485:14

Expected Behavior

ModuleBuildInfo should not attempt to use fd_t on UEFI and should get the PDB file some other way.

T-rex08 avatar Mar 20 '24 20:03 T-rex08

cc @truemedian

nektro avatar Mar 20 '24 21:03 nektro

If we fix this then can we support !void in root.main?

RossComputerGuy avatar Mar 20 '24 21:03 RossComputerGuy

I don't think so, as it is unclear how the error could be reported (whether SimpleTextOutput or GOP should be used, boot services could even already be exited).

T-rex08 avatar Mar 21 '24 06:03 T-rex08

firstly: UEFI does not document or even mention the use of PDB for UEFI applications.

should get the PDB file some other way.

The only way to get the PDB file is to read it from the file system, and additionally to assume that it is always adjacent to the UEFI application.

boot services could even already be exited

This can easily be asserted, and should. However, most of the standard library should assume boot services are present, because that's what the majority of the UEFI application bindings are for. When boot services are not present, the standard library functions as if freestanding, as there is no interface to accomplish the system interface.

Once an application exits boot services, it is past that point it's own operating system, and should call into freestanding code. Runtime services are the only thing available past that point.

whether SimpleTextOutput or GOP should be used

GOP should definitely not be used. It is not always present. stderr should be sent to ConErr, much like stdout should be sent to ConOut. However, this will likely cause some confusion with those unfamiliar with how these are generally bound.

For example: OVMF binds ConOut to the screen and serial console, but binds ConErr to only the serial console.

This might be slightly confusing at first, but the screen is not a reliable output source, the content may be too large and be overflowed off screen, or the screen could be in GOP mode and therefore not print anything.

On the other hand, ConErr is almost always connected to a serial console.


As for the implementation, fixing this without significantly complicating std.debug requires implementing a few things for UEFI like fd_t and the related std.os functions.

You can see some related progress in https://github.com/truemedian/zig/commit/3fb6a6ecd64d9a4e35d332b1c6f0e7518f790ecf


If we fix this then can we support !void in root.main?

Yes, this is the only thing blocking this use case.

truemedian avatar Mar 21 '24 16:03 truemedian

I'll be looking into this in my #19486 PR.

RossComputerGuy avatar Mar 30 '24 04:03 RossComputerGuy