authorgravatar for marc@tiehu.isMarc Tiehuis <marc@tiehu.is> 2019-05-14 16:43:21+12:00
committergravatar for noreply@github.comGitHub <noreply@github.com> 2019-05-14 16:43:21+12:00
logb64cee2ec2cdfd4c49208b3b32bb925233a73e08
tree4a4387479ba8084d7e0f3009a2b54a363f1ba814
parent08d41da916787ab0c19130dc4dc4e7b0e75c9fa8
parentc4d1597f503f812fdf514cdeca50a3f61781b76d
signaturebadge-question-mark Signed by PGP key 4AEE18F83AFDEB23

Merge pull request #2482 from ziglang/linux-elf-read

Mmap debug info on linux

3 files changed, 106 insertions(+), 28 deletions(-)

std/debug.zig+26-16
...@@ -1004,21 +1004,33 @@ pub fn openElfDebugInfo(...@@ -1004,21 +1004,33 @@ pub fn openElfDebugInfo(
1004fn openSelfDebugInfoLinux(allocator: *mem.Allocator) !DwarfInfo {1004fn openSelfDebugInfoLinux(allocator: *mem.Allocator) !DwarfInfo {
1005 const S = struct {1005 const S = struct {
1006 var self_exe_file: os.File = undefined;1006 var self_exe_file: os.File = undefined;
1007 var self_exe_seekable_stream: os.File.SeekableStream = undefined;1007 var self_exe_mmap_seekable: io.SliceSeekableInStream = undefined;
1008 var self_exe_in_stream: os.File.InStream = undefined;
1009 };1008 };
1009
1010 S.self_exe_file = try os.openSelfExe();1010 S.self_exe_file = try os.openSelfExe();
1011 errdefer S.self_exe_file.close();1011 errdefer S.self_exe_file.close();
10121012
1013 S.self_exe_seekable_stream = S.self_exe_file.seekableStream();1013 const self_exe_mmap_len = try S.self_exe_file.getEndPos();
1014 S.self_exe_in_stream = S.self_exe_file.inStream();1014 const self_exe_mmap = os.posix.mmap(
1015 null,
1016 self_exe_mmap_len,
1017 os.posix.PROT_READ,
1018 os.posix.MAP_SHARED,
1019 S.self_exe_file.handle,
1020 0,
1021 );
1022 if (self_exe_mmap == os.posix.MAP_FAILED) return error.OutOfMemory;
1023 errdefer assert(os.posix.munmap(self_exe_mmap, self_exe_mmap_len) == 0);
1024
1025 const file_mmap_slice = @intToPtr([*]const u8, self_exe_mmap)[0..self_exe_mmap_len];
1026 S.self_exe_mmap_seekable = io.SliceSeekableInStream.init(file_mmap_slice);
10151027
1016 return openElfDebugInfo(1028 return openElfDebugInfo(
1017 allocator,1029 allocator,
1018 // TODO https://github.com/ziglang/zig/issues/7641030 // TODO https://github.com/ziglang/zig/issues/764
1019 @ptrCast(*DwarfSeekableStream, &S.self_exe_seekable_stream.stream),1031 @ptrCast(*DwarfSeekableStream, &S.self_exe_mmap_seekable.seekable_stream),
1020 // TODO https://github.com/ziglang/zig/issues/7641032 // TODO https://github.com/ziglang/zig/issues/764
1021 @ptrCast(*DwarfInStream, &S.self_exe_in_stream.stream),1033 @ptrCast(*DwarfInStream, &S.self_exe_mmap_seekable.stream),
1022 );1034 );
1023}1035}
10241036
...@@ -1478,16 +1490,14 @@ fn parseFormValueTargetAddrSize(in_stream: var) !u64 {...@@ -1478,16 +1490,14 @@ fn parseFormValueTargetAddrSize(in_stream: var) !u64 {
1478}1490}
14791491
1480fn parseFormValueRef(allocator: *mem.Allocator, in_stream: var, size: i32) !FormValue {1492fn parseFormValueRef(allocator: *mem.Allocator, in_stream: var, size: i32) !FormValue {
1481 return FormValue{1493 return FormValue{ .Ref = switch (size) {
1482 .Ref = switch (size) {1494 1 => try in_stream.readIntLittle(u8),
1483 1 => try in_stream.readIntLittle(u8),1495 2 => try in_stream.readIntLittle(u16),
1484 2 => try in_stream.readIntLittle(u16),1496 4 => try in_stream.readIntLittle(u32),
1485 4 => try in_stream.readIntLittle(u32),1497 8 => try in_stream.readIntLittle(u64),
1486 8 => try in_stream.readIntLittle(u64),1498 -1 => try leb.readULEB128(u64, in_stream),
1487 -1 => try leb.readULEB128(u64, in_stream),1499 else => unreachable,
1488 else => unreachable,1500 } };
1489 },
1490 };
1491}1501}
14921502
1493fn parseFormValue(allocator: *mem.Allocator, in_stream: var, form_id: u64, is_64: bool) anyerror!FormValue {1503fn parseFormValue(allocator: *mem.Allocator, in_stream: var, form_id: u64, is_64: bool) anyerror!FormValue {
std/io.zig+9-12
...@@ -36,6 +36,7 @@ pub fn getStdIn() GetStdIoErrs!File {...@@ -36,6 +36,7 @@ pub fn getStdIn() GetStdIoErrs!File {
36}36}
3737
38pub const SeekableStream = @import("io/seekable_stream.zig").SeekableStream;38pub const SeekableStream = @import("io/seekable_stream.zig").SeekableStream;
39pub const SliceSeekableInStream = @import("io/seekable_stream.zig").SliceSeekableInStream;
39pub const COutStream = @import("io/c_out_stream.zig").COutStream;40pub const COutStream = @import("io/c_out_stream.zig").COutStream;
4041
41pub fn InStream(comptime ReadError: type) type {42pub fn InStream(comptime ReadError: type) type {
...@@ -1115,12 +1116,10 @@ pub fn Deserializer(comptime endian: builtin.Endian, comptime packing: Packing,...@@ -1115,12 +1116,10 @@ pub fn Deserializer(comptime endian: builtin.Endian, comptime packing: Packing,
1115 pub const Stream = InStream(Error);1116 pub const Stream = InStream(Error);
11161117
1117 pub fn init(in_stream: *Stream) Self {1118 pub fn init(in_stream: *Stream) Self {
1118 return Self{1119 return Self{ .in_stream = switch (packing) {
1119 .in_stream = switch (packing) {1120 .Bit => BitInStream(endian, Stream.Error).init(in_stream),
1120 .Bit => BitInStream(endian, Stream.Error).init(in_stream),1121 .Byte => in_stream,
1121 .Byte => in_stream,1122 } };
1122 },
1123 };
1124 }1123 }
11251124
1126 pub fn alignToByte(self: *Self) void {1125 pub fn alignToByte(self: *Self) void {
...@@ -1326,12 +1325,10 @@ pub fn Serializer(comptime endian: builtin.Endian, comptime packing: Packing, co...@@ -1326,12 +1325,10 @@ pub fn Serializer(comptime endian: builtin.Endian, comptime packing: Packing, co
1326 pub const Stream = OutStream(Error);1325 pub const Stream = OutStream(Error);
13271326
1328 pub fn init(out_stream: *Stream) Self {1327 pub fn init(out_stream: *Stream) Self {
1329 return Self{1328 return Self{ .out_stream = switch (packing) {
1330 .out_stream = switch (packing) {1329 .Bit => BitOutStream(endian, Stream.Error).init(out_stream),
1331 .Bit => BitOutStream(endian, Stream.Error).init(out_stream),1330 .Byte => out_stream,
1332 .Byte => out_stream,1331 } };
1333 },
1334 };
1335 }1332 }
13361333
1337 /// Flushes any unwritten bits to the stream1334 /// Flushes any unwritten bits to the stream
std/io/seekable_stream.zig+71
...@@ -30,3 +30,74 @@ pub fn SeekableStream(comptime SeekErrorType: type, comptime GetSeekPosErrorType...@@ -30,3 +30,74 @@ pub fn SeekableStream(comptime SeekErrorType: type, comptime GetSeekPosErrorType
30 }30 }
31 };31 };
32}32}
33
34pub const SliceSeekableInStream = struct {
35 const Self = @This();
36 pub const Error = error{};
37 pub const SeekError = error{EndOfStream};
38 pub const GetSeekPosError = error{};
39 pub const Stream = InStream(Error);
40 pub const SeekableInStream = SeekableStream(SeekError, GetSeekPosError);
41
42 pub stream: Stream,
43 pub seekable_stream: SeekableInStream,
44
45 pos: usize,
46 slice: []const u8,
47
48 pub fn init(slice: []const u8) Self {
49 return Self{
50 .slice = slice,
51 .pos = 0,
52 .stream = Stream{ .readFn = readFn },
53 .seekable_stream = SeekableInStream{
54 .seekToFn = seekToFn,
55 .seekForwardFn = seekForwardFn,
56 .getEndPosFn = getEndPosFn,
57 .getPosFn = getPosFn,
58 },
59 };
60 }
61
62 fn readFn(in_stream: *Stream, dest: []u8) Error!usize {
63 const self = @fieldParentPtr(Self, "stream", in_stream);
64 const size = std.math.min(dest.len, self.slice.len - self.pos);
65 const end = self.pos + size;
66
67 std.mem.copy(u8, dest[0..size], self.slice[self.pos..end]);
68 self.pos = end;
69
70 return size;
71 }
72
73 fn seekToFn(in_stream: *SeekableInStream, pos: u64) SeekError!void {
74 const self = @fieldParentPtr(Self, "seekable_stream", in_stream);
75 const usize_pos = @intCast(usize, pos);
76 if (usize_pos >= self.slice.len) return error.EndOfStream;
77 self.pos = usize_pos;
78 }
79
80 fn seekForwardFn(in_stream: *SeekableInStream, amt: i64) SeekError!void {
81 const self = @fieldParentPtr(Self, "seekable_stream", in_stream);
82
83 if (amt < 0) {
84 const abs_amt = @intCast(usize, -amt);
85 if (abs_amt > self.pos) return error.EndOfStream;
86 self.pos -= abs_amt;
87 } else {
88 const usize_amt = @intCast(usize, amt);
89 if (self.pos + usize_amt >= self.slice.len) return error.EndOfStream;
90 self.pos += usize_amt;
91 }
92 }
93
94 fn getEndPosFn(in_stream: *SeekableInStream) GetSeekPosError!u64 {
95 const self = @fieldParentPtr(Self, "seekable_stream", in_stream);
96 return @intCast(u64, self.slice.len);
97 }
98
99 fn getPosFn(in_stream: *SeekableInStream) GetSeekPosError!u64 {
100 const self = @fieldParentPtr(Self, "seekable_stream", in_stream);
101 return @intCast(u64, self.pos);
102 }
103};