aboutsummaryrefslogtreecommitdiff
path: root/lib/std/dynamic_library.zig
diff options
context:
space:
mode:
authorAndrew Kelley <andrewrk@noreply.codeberg.org>2025-12-27 14:10:46 +0100
committerAndrew Kelley <andrewrk@noreply.codeberg.org>2025-12-27 14:10:46 +0100
commite55e6b5528bb2f01de242fcf32b172e244e98e74 (patch)
tree3a5eb3193d3d192c54ab0c2b7295a7f21861c27e /lib/std/dynamic_library.zig
parentc3f2de5e519926eb0029062fe8e782a6f9df9c05 (diff)
parent60a1ba0a8f3517356fa2941462f002a7f580545b (diff)
downloadzig-e55e6b5528bb2f01de242fcf32b172e244e98e74.tar.gz
zig-e55e6b5528bb2f01de242fcf32b172e244e98e74.zip
Merge pull request 'std: migrate all `fs` APIs to `Io`' (#30232) from std.Io-fs into master
Reviewed-on: https://codeberg.org/ziglang/zig/pulls/30232
Diffstat (limited to 'lib/std/dynamic_library.zig')
-rw-r--r--lib/std/dynamic_library.zig76
1 files changed, 39 insertions, 37 deletions
diff --git a/lib/std/dynamic_library.zig b/lib/std/dynamic_library.zig
index a3490ed7db..ccd60ecd97 100644
--- a/lib/std/dynamic_library.zig
+++ b/lib/std/dynamic_library.zig
@@ -1,10 +1,12 @@
-const std = @import("std.zig");
const builtin = @import("builtin");
+const native_os = builtin.os.tag;
+
+const std = @import("std.zig");
+const Io = std.Io;
const mem = std.mem;
const testing = std.testing;
const elf = std.elf;
const windows = std.os.windows;
-const native_os = builtin.os.tag;
const posix = std.posix;
/// Cross-platform dynamic library loading and symbol lookup.
@@ -53,11 +55,11 @@ pub const DynLib = struct {
// An iterator is provided in order to traverse the linked list in a idiomatic
// fashion.
const LinkMap = extern struct {
- l_addr: usize,
- l_name: [*:0]const u8,
- l_ld: ?*elf.Dyn,
- l_next: ?*LinkMap,
- l_prev: ?*LinkMap,
+ addr: usize,
+ name: [*:0]const u8,
+ ld: ?*elf.Dyn,
+ next: ?*LinkMap,
+ prev: ?*LinkMap,
pub const Iterator = struct {
current: ?*LinkMap,
@@ -68,7 +70,7 @@ const LinkMap = extern struct {
pub fn next(self: *Iterator) ?*LinkMap {
if (self.current) |it| {
- self.current = it.l_next;
+ self.current = it.next;
return it;
}
return null;
@@ -77,10 +79,10 @@ const LinkMap = extern struct {
};
const RDebug = extern struct {
- r_version: i32,
- r_map: ?*LinkMap,
- r_brk: usize,
- r_ldbase: usize,
+ version: i32,
+ map: ?*LinkMap,
+ brk: usize,
+ ldbase: usize,
};
/// TODO fix comparisons of extern symbol pointers so we don't need this helper function.
@@ -105,8 +107,8 @@ pub fn linkmap_iterator() error{InvalidExe}!LinkMap.Iterator {
elf.DT_DEBUG => {
const ptr = @as(?*RDebug, @ptrFromInt(_DYNAMIC[i].d_val));
if (ptr) |r_debug| {
- if (r_debug.r_version != 1) return error.InvalidExe;
- break :init r_debug.r_map;
+ if (r_debug.version != 1) return error.InvalidExe;
+ break :init r_debug.map;
}
},
elf.DT_PLTGOT => {
@@ -155,24 +157,24 @@ pub const ElfDynLib = struct {
dt_gnu_hash: *elf.gnu_hash.Header,
};
- fn openPath(path: []const u8) !std.fs.Dir {
+ fn openPath(io: Io, path: []const u8) !Io.Dir {
if (path.len == 0) return error.NotDir;
var parts = std.mem.tokenizeScalar(u8, path, '/');
- var parent = if (path[0] == '/') try std.fs.cwd().openDir("/", .{}) else std.fs.cwd();
+ var parent = if (path[0] == '/') try Io.Dir.cwd().openDir(io, "/", .{}) else Io.Dir.cwd();
while (parts.next()) |part| {
- const child = try parent.openDir(part, .{});
- parent.close();
+ const child = try parent.openDir(io, part, .{});
+ parent.close(io);
parent = child;
}
return parent;
}
- fn resolveFromSearchPath(search_path: []const u8, file_name: []const u8, delim: u8) ?posix.fd_t {
+ fn resolveFromSearchPath(io: Io, search_path: []const u8, file_name: []const u8, delim: u8) ?posix.fd_t {
var paths = std.mem.tokenizeScalar(u8, search_path, delim);
while (paths.next()) |p| {
- var dir = openPath(p) catch continue;
- defer dir.close();
- const fd = posix.openat(dir.fd, file_name, .{
+ var dir = openPath(io, p) catch continue;
+ defer dir.close(io);
+ const fd = posix.openat(dir.handle, file_name, .{
.ACCMODE = .RDONLY,
.CLOEXEC = true,
}, 0) catch continue;
@@ -181,10 +183,10 @@ pub const ElfDynLib = struct {
return null;
}
- fn resolveFromParent(dir_path: []const u8, file_name: []const u8) ?posix.fd_t {
- var dir = std.fs.cwd().openDir(dir_path, .{}) catch return null;
- defer dir.close();
- return posix.openat(dir.fd, file_name, .{
+ fn resolveFromParent(io: Io, dir_path: []const u8, file_name: []const u8) ?posix.fd_t {
+ var dir = Io.Dir.cwd().openDir(io, dir_path, .{}) catch return null;
+ defer dir.close(io);
+ return posix.openat(dir.handle, file_name, .{
.ACCMODE = .RDONLY,
.CLOEXEC = true,
}, 0) catch null;
@@ -195,7 +197,7 @@ pub const ElfDynLib = struct {
// - DT_RPATH of the calling binary is not used as a search path
// - DT_RUNPATH of the calling binary is not used as a search path
// - /etc/ld.so.cache is not read
- fn resolveFromName(path_or_name: []const u8) !posix.fd_t {
+ fn resolveFromName(io: Io, path_or_name: []const u8) !posix.fd_t {
// If filename contains a slash ("/"), then it is interpreted as a (relative or absolute) pathname
if (std.mem.findScalarPos(u8, path_or_name, 0, '/')) |_| {
return posix.open(path_or_name, .{ .ACCMODE = .RDONLY, .CLOEXEC = true }, 0);
@@ -206,25 +208,27 @@ pub const ElfDynLib = struct {
std.os.linux.getegid() == std.os.linux.getgid())
{
if (posix.getenvZ("LD_LIBRARY_PATH")) |ld_library_path| {
- if (resolveFromSearchPath(ld_library_path, path_or_name, ':')) |fd| {
+ if (resolveFromSearchPath(io, ld_library_path, path_or_name, ':')) |fd| {
return fd;
}
}
}
// Lastly the directories /lib and /usr/lib are searched (in this exact order)
- if (resolveFromParent("/lib", path_or_name)) |fd| return fd;
- if (resolveFromParent("/usr/lib", path_or_name)) |fd| return fd;
+ if (resolveFromParent(io, "/lib", path_or_name)) |fd| return fd;
+ if (resolveFromParent(io, "/usr/lib", path_or_name)) |fd| return fd;
return error.FileNotFound;
}
/// Trusts the file. Malicious file will be able to execute arbitrary code.
pub fn open(path: []const u8) Error!ElfDynLib {
- const fd = try resolveFromName(path);
+ const io = std.Options.debug_io;
+
+ const fd = try resolveFromName(io, path);
defer posix.close(fd);
- const file: std.fs.File = .{ .handle = fd };
- const stat = try file.stat();
+ const file: Io.File = .{ .handle = fd };
+ const stat = try file.stat(io);
const size = std.math.cast(usize, stat.size) orelse return error.FileTooBig;
const page_size = std.heap.pageSize();
@@ -549,11 +553,9 @@ fn checkver(def_arg: *elf.Verdef, vsym_arg: elf.Versym, vername: []const u8, str
}
test "ElfDynLib" {
- if (native_os != .linux) {
- return error.SkipZigTest;
- }
-
+ if (native_os != .linux) return error.SkipZigTest;
try testing.expectError(error.FileNotFound, ElfDynLib.open("invalid_so.so"));
+ try testing.expectError(error.FileNotFound, ElfDynLib.openZ("invalid_so.so"));
}
/// Separated to avoid referencing `WindowsDynLib`, because its field types may not