mirror of
https://github.com/ziglang/zig.git
synced 2025-12-17 19:53:06 +00:00
Merge pull request #2581 from LemonBoy/misc-stuff
Miscellaneous stdlib changes
This commit is contained in:
commit
a608ebaa50
67
std/os.zig
67
std/os.zig
@ -19,6 +19,8 @@ const builtin = @import("builtin");
|
|||||||
const assert = std.debug.assert;
|
const assert = std.debug.assert;
|
||||||
const math = std.math;
|
const math = std.math;
|
||||||
const mem = std.mem;
|
const mem = std.mem;
|
||||||
|
const elf = std.elf;
|
||||||
|
const dl = @import("dynamic_library.zig");
|
||||||
const MAX_PATH_BYTES = std.fs.MAX_PATH_BYTES;
|
const MAX_PATH_BYTES = std.fs.MAX_PATH_BYTES;
|
||||||
|
|
||||||
comptime {
|
comptime {
|
||||||
@ -1955,7 +1957,6 @@ pub fn mmap(
|
|||||||
fd: fd_t,
|
fd: fd_t,
|
||||||
offset: isize,
|
offset: isize,
|
||||||
) MMapError![]align(mem.page_size) u8 {
|
) MMapError![]align(mem.page_size) u8 {
|
||||||
assert(mem.isAligned(length, mem.page_size));
|
|
||||||
const err = if (builtin.link_libc) blk: {
|
const err = if (builtin.link_libc) blk: {
|
||||||
const rc = std.c.mmap(ptr, length, prot, flags, fd, offset);
|
const rc = std.c.mmap(ptr, length, prot, flags, fd, offset);
|
||||||
if (rc != MAP_FAILED) return @ptrCast([*]align(mem.page_size) u8, @alignCast(mem.page_size, rc))[0..length];
|
if (rc != MAP_FAILED) return @ptrCast([*]align(mem.page_size) u8, @alignCast(mem.page_size, rc))[0..length];
|
||||||
@ -2368,6 +2369,70 @@ pub fn nanosleep(seconds: u64, nanoseconds: u64) void {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn dl_iterate_phdr(comptime T: type, callback: extern fn (info: *dl_phdr_info, size: usize, data: ?*T) i32, data: ?*T) isize {
|
||||||
|
// This is implemented only for systems using ELF executables
|
||||||
|
if (windows.is_the_target or builtin.os == .uefi or wasi.is_the_target or darwin.is_the_target)
|
||||||
|
@compileError("dl_iterate_phdr is not available for this target");
|
||||||
|
|
||||||
|
if (builtin.link_libc) {
|
||||||
|
return system.dl_iterate_phdr(
|
||||||
|
@ptrCast(std.c.dl_iterate_phdr_callback, callback),
|
||||||
|
@ptrCast(?*c_void, data),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
const elf_base = std.process.getBaseAddress();
|
||||||
|
const ehdr = @intToPtr(*elf.Ehdr, elf_base);
|
||||||
|
// Make sure the base address points to an ELF image
|
||||||
|
assert(mem.eql(u8, ehdr.e_ident[0..4], "\x7fELF"));
|
||||||
|
const n_phdr = ehdr.e_phnum;
|
||||||
|
const phdrs = (@intToPtr([*]elf.Phdr, elf_base + ehdr.e_phoff))[0..n_phdr];
|
||||||
|
|
||||||
|
var it = dl.linkmap_iterator(phdrs) catch unreachable;
|
||||||
|
|
||||||
|
// The executable has no dynamic link segment, create a single entry for
|
||||||
|
// the whole ELF image
|
||||||
|
if (it.end()) {
|
||||||
|
var info = dl_phdr_info{
|
||||||
|
.dlpi_addr = elf_base,
|
||||||
|
.dlpi_name = c"/proc/self/exe",
|
||||||
|
.dlpi_phdr = phdrs.ptr,
|
||||||
|
.dlpi_phnum = ehdr.e_phnum,
|
||||||
|
};
|
||||||
|
|
||||||
|
return callback(&info, @sizeOf(dl_phdr_info), data);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Last return value from the callback function
|
||||||
|
var last_r: isize = 0;
|
||||||
|
while (it.next()) |entry| {
|
||||||
|
var dlpi_phdr: [*]elf.Phdr = undefined;
|
||||||
|
var dlpi_phnum: u16 = undefined;
|
||||||
|
|
||||||
|
if (entry.l_addr != 0) {
|
||||||
|
const elf_header = @intToPtr(*elf.Ehdr, entry.l_addr);
|
||||||
|
dlpi_phdr = @intToPtr([*]elf.Phdr, entry.l_addr + elf_header.e_phoff);
|
||||||
|
dlpi_phnum = elf_header.e_phnum;
|
||||||
|
} else {
|
||||||
|
// This is the running ELF image
|
||||||
|
dlpi_phdr = @intToPtr([*]elf.Phdr, elf_base + ehdr.e_phoff);
|
||||||
|
dlpi_phnum = ehdr.e_phnum;
|
||||||
|
}
|
||||||
|
|
||||||
|
var info = dl_phdr_info{
|
||||||
|
.dlpi_addr = entry.l_addr,
|
||||||
|
.dlpi_name = entry.l_name,
|
||||||
|
.dlpi_phdr = dlpi_phdr,
|
||||||
|
.dlpi_phnum = dlpi_phnum,
|
||||||
|
};
|
||||||
|
|
||||||
|
last_r = callback(&info, @sizeOf(dl_phdr_info), data);
|
||||||
|
if (last_r != 0) break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return last_r;
|
||||||
|
}
|
||||||
|
|
||||||
pub const ClockGetTimeError = error{
|
pub const ClockGetTimeError = error{
|
||||||
UnsupportedClock,
|
UnsupportedClock,
|
||||||
Unexpected,
|
Unexpected,
|
||||||
|
|||||||
@ -20,6 +20,13 @@ pub const pthread_attr_t = extern struct {
|
|||||||
__align: c_long,
|
__align: c_long,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
pub const dl_phdr_info = extern struct {
|
||||||
|
dlpi_addr: usize,
|
||||||
|
dlpi_name: ?[*]const u8,
|
||||||
|
dlpi_phdr: [*]std.elf.Phdr,
|
||||||
|
dlpi_phnum: u16,
|
||||||
|
};
|
||||||
|
|
||||||
pub const msghdr = extern struct {
|
pub const msghdr = extern struct {
|
||||||
/// optional address
|
/// optional address
|
||||||
msg_name: ?*sockaddr,
|
msg_name: ?*sockaddr,
|
||||||
|
|||||||
@ -20,6 +20,13 @@ pub const pthread_attr_t = extern struct {
|
|||||||
pta_private: *c_void,
|
pta_private: *c_void,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
pub const dl_phdr_info = extern struct {
|
||||||
|
dlpi_addr: usize,
|
||||||
|
dlpi_name: ?[*]const u8,
|
||||||
|
dlpi_phdr: [*]std.elf.Phdr,
|
||||||
|
dlpi_phnum: u16,
|
||||||
|
};
|
||||||
|
|
||||||
pub const msghdr = extern struct {
|
pub const msghdr = extern struct {
|
||||||
/// optional address
|
/// optional address
|
||||||
msg_name: ?*sockaddr,
|
msg_name: ?*sockaddr,
|
||||||
|
|||||||
@ -44,42 +44,3 @@ test "timer" {
|
|||||||
// TODO implicit cast from *[N]T to [*]T
|
// TODO implicit cast from *[N]T to [*]T
|
||||||
err = linux.epoll_wait(@intCast(i32, epoll_fd), @ptrCast([*]linux.epoll_event, &events), 8, -1);
|
err = linux.epoll_wait(@intCast(i32, epoll_fd), @ptrCast([*]linux.epoll_event, &events), 8, -1);
|
||||||
}
|
}
|
||||||
|
|
||||||
export fn iter_fn(info: *linux.dl_phdr_info, size: usize, data: ?*usize) i32 {
|
|
||||||
var counter = data.?;
|
|
||||||
// Count how many libraries are loaded
|
|
||||||
counter.* += usize(1);
|
|
||||||
|
|
||||||
// The image should contain at least a PT_LOAD segment
|
|
||||||
if (info.dlpi_phnum < 1) return -1;
|
|
||||||
|
|
||||||
// Quick & dirty validation of the phdr pointers, make sure we're not
|
|
||||||
// pointing to some random gibberish
|
|
||||||
var i: usize = 0;
|
|
||||||
var found_load = false;
|
|
||||||
while (i < info.dlpi_phnum) : (i += 1) {
|
|
||||||
const phdr = info.dlpi_phdr[i];
|
|
||||||
|
|
||||||
if (phdr.p_type != elf.PT_LOAD) continue;
|
|
||||||
|
|
||||||
// Find the ELF header
|
|
||||||
const elf_header = @intToPtr(*elf.Ehdr, phdr.p_vaddr - phdr.p_offset);
|
|
||||||
// Validate the magic
|
|
||||||
if (!mem.eql(u8, elf_header.e_ident[0..], "\x7fELF")) return -1;
|
|
||||||
// Consistency check
|
|
||||||
if (elf_header.e_phnum != info.dlpi_phnum) return -1;
|
|
||||||
|
|
||||||
found_load = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!found_load) return -1;
|
|
||||||
|
|
||||||
return 42;
|
|
||||||
}
|
|
||||||
|
|
||||||
test "dl_iterate_phdr" {
|
|
||||||
var counter: usize = 0;
|
|
||||||
expect(linux.dl_iterate_phdr(usize, iter_fn, &counter) != 0);
|
|
||||||
expect(counter != 0);
|
|
||||||
}
|
|
||||||
|
|||||||
@ -5,6 +5,7 @@ const expect = std.testing.expect;
|
|||||||
const io = std.io;
|
const io = std.io;
|
||||||
const fs = std.fs;
|
const fs = std.fs;
|
||||||
const mem = std.mem;
|
const mem = std.mem;
|
||||||
|
const elf = std.elf;
|
||||||
const File = std.fs.File;
|
const File = std.fs.File;
|
||||||
const Thread = std.Thread;
|
const Thread = std.Thread;
|
||||||
|
|
||||||
@ -160,3 +161,52 @@ test "sigaltstack" {
|
|||||||
st.ss_size = 1;
|
st.ss_size = 1;
|
||||||
testing.expectError(error.SizeTooSmall, os.sigaltstack(&st, null));
|
testing.expectError(error.SizeTooSmall, os.sigaltstack(&st, null));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// If the type is not available use void to avoid erroring out when `iter_fn` is
|
||||||
|
// analyzed
|
||||||
|
const dl_phdr_info = if (@hasDecl(os, "dl_phdr_info")) os.dl_phdr_info else c_void;
|
||||||
|
|
||||||
|
export fn iter_fn(info: *dl_phdr_info, size: usize, data: ?*usize) i32 {
|
||||||
|
if (builtin.os == .windows or builtin.os == .wasi or builtin.os == .macosx)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
var counter = data.?;
|
||||||
|
// Count how many libraries are loaded
|
||||||
|
counter.* += usize(1);
|
||||||
|
|
||||||
|
// The image should contain at least a PT_LOAD segment
|
||||||
|
if (info.dlpi_phnum < 1) return -1;
|
||||||
|
|
||||||
|
// Quick & dirty validation of the phdr pointers, make sure we're not
|
||||||
|
// pointing to some random gibberish
|
||||||
|
var i: usize = 0;
|
||||||
|
var found_load = false;
|
||||||
|
while (i < info.dlpi_phnum) : (i += 1) {
|
||||||
|
const phdr = info.dlpi_phdr[i];
|
||||||
|
|
||||||
|
if (phdr.p_type != elf.PT_LOAD) continue;
|
||||||
|
|
||||||
|
// Find the ELF header
|
||||||
|
const elf_header = @intToPtr(*elf.Ehdr, phdr.p_vaddr - phdr.p_offset);
|
||||||
|
// Validate the magic
|
||||||
|
if (!mem.eql(u8, elf_header.e_ident[0..4], "\x7fELF")) return -1;
|
||||||
|
// Consistency check
|
||||||
|
if (elf_header.e_phnum != info.dlpi_phnum) return -1;
|
||||||
|
|
||||||
|
found_load = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!found_load) return -1;
|
||||||
|
|
||||||
|
return 42;
|
||||||
|
}
|
||||||
|
|
||||||
|
test "dl_iterate_phdr" {
|
||||||
|
if (builtin.os == .windows or builtin.os == .wasi or builtin.os == .macosx)
|
||||||
|
return error.SkipZigTest;
|
||||||
|
|
||||||
|
var counter: usize = 0;
|
||||||
|
expect(os.dl_iterate_phdr(usize, iter_fn, &counter) != 0);
|
||||||
|
expect(counter != 0);
|
||||||
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user