| ... | ... | @@ -2,6 +2,7 @@ const std = @import("../std.zig"); |
| 2 | 2 | const assert = std.debug.assert; |
| 3 | 3 | const builtin = @import("builtin"); |
| 4 | 4 | const maxInt = std.math.maxInt; |
| 5 | const elf = std.elf; |
| 5 | 6 | const vdso = @import("linux/vdso.zig"); |
| 6 | 7 | pub use switch (builtin.arch) { |
| 7 | 8 | builtin.Arch.x86_64 => @import("linux/x86_64.zig"), |
| ... | ... | @@ -1534,6 +1535,68 @@ pub const dirent64 = extern struct { |
| 1534 | 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 | 1600 | test "import" { |
| 1538 | 1601 | if (builtin.os == builtin.Os.linux) { |
| 1539 | 1602 | _ = @import("linux/test.zig"); |