| ... | @@ -2,6 +2,7 @@ const std = @import("../std.zig"); | ... | @@ -2,6 +2,7 @@ const std = @import("../std.zig"); |
| 2 | const assert = std.debug.assert; | 2 | const assert = std.debug.assert; |
| 3 | const builtin = @import("builtin"); | 3 | const builtin = @import("builtin"); |
| 4 | const maxInt = std.math.maxInt; | 4 | const maxInt = std.math.maxInt; |
| | 5 | const elf = std.elf; |
| 5 | const vdso = @import("linux/vdso.zig"); | 6 | const vdso = @import("linux/vdso.zig"); |
| 6 | pub use switch (builtin.arch) { | 7 | pub use switch (builtin.arch) { |
| 7 | builtin.Arch.x86_64 => @import("linux/x86_64.zig"), | 8 | builtin.Arch.x86_64 => @import("linux/x86_64.zig"), |
| ... | @@ -1534,6 +1535,68 @@ pub const dirent64 = extern struct { | ... | @@ -1534,6 +1535,68 @@ pub const dirent64 = extern struct { |
| 1534 | d_name: u8, // field address is the address of first byte of name https://github.com/ziglang/zig/issues/173 | 1535 | d_name: u8, // field address is the address of first byte of name https://github.com/ziglang/zig/issues/173 |
| 1535 | }; | 1536 | }; |
| 1536 | | 1537 | |
| | 1538 | pub const dl_phdr_info = extern struct { |
| | 1539 | dlpi_addr: usize, |
| | 1540 | dlpi_name: [*c]const u8, |
| | 1541 | dlpi_phdr: [*c]*c_void, |
| | 1542 | dlpi_phnum: u16, |
| | 1543 | }; |
| | 1544 | |
| | 1545 | const DynLib = @import("../dynamic_library.zig"); |
| | 1546 | |
| | 1547 | // XXX: This should be weak |
| | 1548 | extern const __ehdr_start: elf.Ehdr = undefined; |
| | 1549 | |
| | 1550 | pub fn dl_iterate_phdr(callback: extern fn (info: *dl_phdr_info, size: usize, data: ?*c_void) i32, data: ?*c_void) isize { |
| | 1551 | if (builtin.link_libc) { |
| | 1552 | return std.c.dl_iterate_phdr(@ptrCast(*const c_void, callback), data); |
| | 1553 | } |
| | 1554 | |
| | 1555 | const elf_base = @ptrToInt(&__ehdr_start); |
| | 1556 | const n_phdr = __ehdr_start.e_phnum; |
| | 1557 | const phdrs = (@intToPtr([*]elf.Phdr, elf_base + __ehdr_start.e_phoff))[0..n_phdr]; |
| | 1558 | |
| | 1559 | var it = DynLib.linkmap_iterator(phdrs) catch return 0; |
| | 1560 | if (it.end()) { |
| | 1561 | // The executable has no dynamic link infos, create a single info |
| | 1562 | // struct for the whole ELF image |
| | 1563 | var info = dl_phdr_info{ |
| | 1564 | .dlpi_addr = elf_base, |
| | 1565 | .dlpi_name = c"/proc/self/exe", |
| | 1566 | .dlpi_phdr = @intToPtr([*c]*c_void, elf_base + __ehdr_start.e_phoff), |
| | 1567 | .dlpi_phnum = __ehdr_start.e_phnum, |
| | 1568 | }; |
| | 1569 | |
| | 1570 | return callback(&info, @sizeOf(dl_phdr_info), data); |
| | 1571 | } |
| | 1572 | |
| | 1573 | // Last return value from the callback function |
| | 1574 | var last_r: isize = 0; |
| | 1575 | while (it.next()) |entry| { |
| | 1576 | var info = dl_phdr_info{ |
| | 1577 | .dlpi_addr = entry.l_addr, |
| | 1578 | .dlpi_name = entry.l_name, |
| | 1579 | .dlpi_phdr = 0, |
| | 1580 | .dlpi_phnum = 0, |
| | 1581 | }; |
| | 1582 | |
| | 1583 | if (entry.l_addr != 0) { |
| | 1584 | const elf_header = @intToPtr(*elf.Ehdr, entry.l_addr); |
| | 1585 | info.dlpi_phdr = @intToPtr([*c]*c_void, entry.l_addr + elf_header.e_phoff); |
| | 1586 | info.dlpi_phnum = elf_header.e_phnum; |
| | 1587 | } else { |
| | 1588 | // This is the running ELF image |
| | 1589 | info.dlpi_phdr = @intToPtr([*c]*c_void, elf_base + __ehdr_start.e_phoff); |
| | 1590 | info.dlpi_phnum = __ehdr_start.e_phnum; |
| | 1591 | } |
| | 1592 | |
| | 1593 | last_r = callback(&info, @sizeOf(dl_phdr_info), data); |
| | 1594 | if (last_r != 0) break; |
| | 1595 | } |
| | 1596 | |
| | 1597 | return last_r; |
| | 1598 | } |
| | 1599 | |
| 1537 | test "import" { | 1600 | test "import" { |
| 1538 | if (builtin.os == builtin.Os.linux) { | 1601 | if (builtin.os == builtin.Os.linux) { |
| 1539 | _ = @import("linux/test.zig"); | 1602 | _ = @import("linux/test.zig"); |