diff options
Diffstat (limited to 'crates')
-rw-r--r-- | crates/proc_macro_api/Cargo.toml | 1 | ||||
-rw-r--r-- | crates/proc_macro_api/src/lib.rs | 44 |
2 files changed, 30 insertions, 15 deletions
diff --git a/crates/proc_macro_api/Cargo.toml b/crates/proc_macro_api/Cargo.toml index 5b0a05dff..16fd56c7e 100644 --- a/crates/proc_macro_api/Cargo.toml +++ b/crates/proc_macro_api/Cargo.toml | |||
@@ -21,3 +21,4 @@ base_db = { path = "../base_db", version = "0.0.0" } | |||
21 | stdx = { path = "../stdx", version = "0.0.0" } | 21 | stdx = { path = "../stdx", version = "0.0.0" } |
22 | snap = "1" | 22 | snap = "1" |
23 | object = { version = "0.23.0", default-features = false, features = ["std", "read_core", "elf", "macho", "pe", "unaligned"] } | 23 | object = { version = "0.23.0", default-features = false, features = ["std", "read_core", "elf", "macho", "pe", "unaligned"] } |
24 | memmap = "0.7.0" | ||
diff --git a/crates/proc_macro_api/src/lib.rs b/crates/proc_macro_api/src/lib.rs index cec854746..a58e39de0 100644 --- a/crates/proc_macro_api/src/lib.rs +++ b/crates/proc_macro_api/src/lib.rs | |||
@@ -9,15 +9,22 @@ pub mod msg; | |||
9 | mod process; | 9 | mod process; |
10 | mod rpc; | 10 | mod rpc; |
11 | 11 | ||
12 | use std::{ffi::OsStr, fs::read as fsread, io::{self, Read}, path::{Path, PathBuf}, sync::Arc}; | ||
13 | |||
14 | use base_db::{Env, ProcMacro}; | 12 | use base_db::{Env, ProcMacro}; |
13 | use std::{ | ||
14 | ffi::OsStr, | ||
15 | fs::File, | ||
16 | io::{self, Read}, | ||
17 | path::{Path, PathBuf}, | ||
18 | sync::Arc, | ||
19 | }; | ||
20 | |||
15 | use tt::{SmolStr, Subtree}; | 21 | use tt::{SmolStr, Subtree}; |
16 | 22 | ||
17 | use crate::process::{ProcMacroProcessSrv, ProcMacroProcessThread}; | 23 | use crate::process::{ProcMacroProcessSrv, ProcMacroProcessThread}; |
18 | 24 | ||
19 | pub use rpc::{ExpansionResult, ExpansionTask, ListMacrosResult, ListMacrosTask, ProcMacroKind}; | 25 | pub use rpc::{ExpansionResult, ExpansionTask, ListMacrosResult, ListMacrosTask, ProcMacroKind}; |
20 | 26 | ||
27 | use memmap::Mmap; | ||
21 | use object::read::{File as BinaryFile, Object, ObjectSection}; | 28 | use object::read::{File as BinaryFile, Object, ObjectSection}; |
22 | use snap::read::FrameDecoder as SnapDecoder; | 29 | use snap::read::FrameDecoder as SnapDecoder; |
23 | 30 | ||
@@ -110,13 +117,13 @@ impl ProcMacroClient { | |||
110 | 117 | ||
111 | // This is used inside self.read_version() to locate the ".rustc" section | 118 | // This is used inside self.read_version() to locate the ".rustc" section |
112 | // from a proc macro crate's binary file. | 119 | // from a proc macro crate's binary file. |
113 | fn read_section<'a>(&self, dylib_binary: &'a [u8], section_name: &str) -> &'a [u8] { | 120 | fn read_section<'a>(&self, dylib_binary: &'a [u8], section_name: &str) -> io::Result<&'a [u8]> { |
114 | BinaryFile::parse(dylib_binary) | 121 | BinaryFile::parse(dylib_binary) |
115 | .unwrap() | 122 | .map_err(|e| io::Error::new(io::ErrorKind::InvalidData, e))? |
116 | .section_by_name(section_name) | 123 | .section_by_name(section_name) |
117 | .unwrap() | 124 | .ok_or_else(|| io::Error::new(io::ErrorKind::InvalidData, "section read error"))? |
118 | .data() | 125 | .data() |
119 | .unwrap() | 126 | .map_err(|e| io::Error::new(io::ErrorKind::InvalidData, e)) |
120 | } | 127 | } |
121 | 128 | ||
122 | // Check the version of rustc that was used to compile a proc macro crate's | 129 | // Check the version of rustc that was used to compile a proc macro crate's |
@@ -138,10 +145,19 @@ impl ProcMacroClient { | |||
138 | // * [some more bytes that we don really care but still there] :-) | 145 | // * [some more bytes that we don really care but still there] :-) |
139 | // Check this issue for more about the bytes layout: | 146 | // Check this issue for more about the bytes layout: |
140 | // https://github.com/rust-analyzer/rust-analyzer/issues/6174 | 147 | // https://github.com/rust-analyzer/rust-analyzer/issues/6174 |
141 | fn read_version(&self, dylib_path: &Path) -> String { | 148 | #[allow(unused)] |
142 | let dylib_binary = fsread(dylib_path).unwrap(); | 149 | fn read_version(&self, dylib_path: &Path) -> io::Result<String> { |
150 | let dylib_file = File::open(dylib_path)?; | ||
151 | let dylib_mmaped = unsafe { Mmap::map(&dylib_file) }?; | ||
152 | |||
153 | let dot_rustc = self.read_section(&dylib_mmaped, ".rustc")?; | ||
143 | 154 | ||
144 | let dot_rustc = self.read_section(&dylib_binary, ".rustc"); | 155 | let header = &dot_rustc[..8]; |
156 | const EXPECTED_HEADER: [u8; 8] = [b'r', b'u', b's', b't', 0, 0, 0, 5]; | ||
157 | // check if header is valid | ||
158 | if !(header == EXPECTED_HEADER) { | ||
159 | return Err(io::Error::new(io::ErrorKind::InvalidData, format!(".rustc section should start with header {:?}; header {:?} is actually presented.",EXPECTED_HEADER ,header))); | ||
160 | } | ||
145 | 161 | ||
146 | let snappy_portion = &dot_rustc[8..]; | 162 | let snappy_portion = &dot_rustc[8..]; |
147 | 163 | ||
@@ -154,14 +170,12 @@ impl ProcMacroClient { | |||
154 | // so 13 bytes in total, and we should check the 13th byte | 170 | // so 13 bytes in total, and we should check the 13th byte |
155 | // to know the length | 171 | // to know the length |
156 | let mut bytes_before_version = [0u8; 13]; | 172 | let mut bytes_before_version = [0u8; 13]; |
157 | snappy_decoder | 173 | snappy_decoder.read_exact(&mut bytes_before_version)?; |
158 | .read_exact(&mut bytes_before_version) | ||
159 | .unwrap(); | ||
160 | let length = bytes_before_version[12]; // what? can't use -1 indexing? | 174 | let length = bytes_before_version[12]; // what? can't use -1 indexing? |
161 | 175 | ||
162 | let mut version_string_utf8 = vec![0u8; length as usize]; | 176 | let mut version_string_utf8 = vec![0u8; length as usize]; |
163 | snappy_decoder.read_exact(&mut version_string_utf8).unwrap(); | 177 | snappy_decoder.read_exact(&mut version_string_utf8)?; |
164 | let version_string = String::from_utf8(version_string_utf8).unwrap(); | 178 | let version_string = String::from_utf8(version_string_utf8); |
165 | version_string | 179 | version_string.map_err(|e| io::Error::new(io::ErrorKind::InvalidData, e)) |
166 | } | 180 | } |
167 | } | 181 | } |