Skip to content

Use a u64 for the rmeta root position #118344

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
Dec 11, 2023
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 8 additions & 8 deletions compiler/rustc_codegen_ssa/src/back/metadata.rs
Original file line number Diff line number Diff line change
Expand Up @@ -158,12 +158,12 @@ pub(super) fn get_metadata_xcoff<'a>(path: &Path, data: &'a [u8]) -> Result<&'a
file.symbols().find(|sym| sym.name() == Ok(AIX_METADATA_SYMBOL_NAME))
{
let offset = metadata_symbol.address() as usize;
if offset < 4 {
if offset < 8 {
return Err(format!("Invalid metadata symbol offset: {offset}"));
}
// The offset specifies the location of rustc metadata in the comment section.
// The metadata is preceded by a 4-byte length field.
let len = u32::from_be_bytes(info_data[(offset - 4)..offset].try_into().unwrap()) as usize;
let len = u64::from_le_bytes(info_data[(offset - 8)..offset].try_into().unwrap()) as usize;
if offset + len > (info_data.len() as usize) {
return Err(format!(
"Metadata at offset {offset} with size {len} is beyond .info section"
Expand Down Expand Up @@ -479,8 +479,8 @@ pub fn create_wrapper_file(
file.section_mut(section).flags =
SectionFlags::Xcoff { s_flags: xcoff::STYP_INFO as u32 };

let len = data.len() as u32;
let offset = file.append_section_data(section, &len.to_be_bytes(), 1);
let len = data.len() as u64;
let offset = file.append_section_data(section, &len.to_le_bytes(), 1);
// Add a symbol referring to the data in .info section.
file.add_symbol(Symbol {
name: AIX_METADATA_SYMBOL_NAME.into(),
Expand Down Expand Up @@ -524,7 +524,7 @@ pub fn create_compressed_metadata_file(
symbol_name: &str,
) -> Vec<u8> {
let mut packed_metadata = rustc_metadata::METADATA_HEADER.to_vec();
packed_metadata.write_all(&(metadata.raw_data().len() as u32).to_be_bytes()).unwrap();
packed_metadata.write_all(&(metadata.raw_data().len() as u64).to_le_bytes()).unwrap();
packed_metadata.extend(metadata.raw_data());

let Some(mut file) = create_object_file(sess) else {
Expand Down Expand Up @@ -599,12 +599,12 @@ pub fn create_compressed_metadata_file_for_xcoff(
section: SymbolSection::Section(data_section),
flags: SymbolFlags::None,
});
let len = data.len() as u32;
let offset = file.append_section_data(section, &len.to_be_bytes(), 1);
let len = data.len() as u64;
let offset = file.append_section_data(section, &len.to_le_bytes(), 1);
// Add a symbol referring to the rustc metadata.
file.add_symbol(Symbol {
name: AIX_METADATA_SYMBOL_NAME.into(),
value: offset + 4, // The metadata is preceded by a 4-byte length field.
value: offset + 8, // The metadata is preceded by a 8-byte length field.
size: 0,
kind: SymbolKind::Unknown,
scope: SymbolScope::Dynamic,
Expand Down
8 changes: 4 additions & 4 deletions compiler/rustc_metadata/src/locator.rs
Original file line number Diff line number Diff line change
Expand Up @@ -783,8 +783,8 @@ fn get_metadata_section<'p>(
loader.get_dylib_metadata(target, filename).map_err(MetadataError::LoadFailure)?;
// The header is uncompressed
let header_len = METADATA_HEADER.len();
// header + u32 length of data
let data_start = header_len + 4;
// header + u64 length of data
let data_start = header_len + 8;

debug!("checking {} bytes of metadata-version stamp", header_len);
let header = &buf[..cmp::min(header_len, buf.len())];
Expand All @@ -797,13 +797,13 @@ fn get_metadata_section<'p>(

// Length of the compressed stream - this allows linkers to pad the section if they want
let Ok(len_bytes) =
<[u8; 4]>::try_from(&buf[header_len..cmp::min(data_start, buf.len())])
<[u8; 8]>::try_from(&buf[header_len..cmp::min(data_start, buf.len())])
else {
return Err(MetadataError::LoadFailure(
"invalid metadata length found".to_string(),
));
};
let compressed_len = u32::from_be_bytes(len_bytes) as usize;
let compressed_len = u64::from_le_bytes(len_bytes) as usize;

// Header is okay -> inflate the actual metadata
let compressed_bytes = buf.slice(|buf| &buf[data_start..(data_start + compressed_len)]);
Expand Down
24 changes: 11 additions & 13 deletions compiler/rustc_metadata/src/rmeta/decoder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -700,28 +700,26 @@ impl MetadataBlob {
}

pub(crate) fn get_rustc_version(&self) -> String {
LazyValue::<String>::from_position(NonZeroUsize::new(METADATA_HEADER.len() + 4).unwrap())
LazyValue::<String>::from_position(NonZeroUsize::new(METADATA_HEADER.len() + 8).unwrap())
.decode(self)
}

pub(crate) fn get_header(&self) -> CrateHeader {
fn root_pos(&self) -> NonZeroUsize {
let slice = &self.blob()[..];
let offset = METADATA_HEADER.len();
let pos_bytes = slice[offset..][..8].try_into().unwrap();
let pos = u64::from_le_bytes(pos_bytes);
NonZeroUsize::new(pos as usize).unwrap()
}

let pos_bytes = slice[offset..][..4].try_into().unwrap();
let pos = u32::from_be_bytes(pos_bytes) as usize;

LazyValue::<CrateHeader>::from_position(NonZeroUsize::new(pos).unwrap()).decode(self)
pub(crate) fn get_header(&self) -> CrateHeader {
let pos = self.root_pos();
LazyValue::<CrateHeader>::from_position(pos).decode(self)
}

pub(crate) fn get_root(&self) -> CrateRoot {
let slice = &self.blob()[..];
let offset = METADATA_HEADER.len();

let pos_bytes = slice[offset..][..4].try_into().unwrap();
let pos = u32::from_be_bytes(pos_bytes) as usize;

LazyValue::<CrateRoot>::from_position(NonZeroUsize::new(pos).unwrap()).decode(self)
let pos = self.root_pos();
LazyValue::<CrateRoot>::from_position(pos).decode(self)
}

pub(crate) fn list_crate_metadata(
Expand Down
4 changes: 2 additions & 2 deletions compiler/rustc_metadata/src/rmeta/encoder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2213,7 +2213,7 @@ fn encode_metadata_impl(tcx: TyCtxt<'_>, path: &Path) {
encoder.emit_raw_bytes(METADATA_HEADER);

// Will be filled with the root position after encoding everything.
encoder.emit_raw_bytes(&[0, 0, 0, 0]);
encoder.emit_raw_bytes(&0u64.to_le_bytes());

let source_map_files = tcx.sess.source_map().files();
let source_file_cache = (source_map_files[0].clone(), 0);
Expand Down Expand Up @@ -2269,7 +2269,7 @@ fn encode_root_position(mut file: &File, pos: usize) -> Result<(), std::io::Erro
// Encode the root position.
let header = METADATA_HEADER.len();
file.seek(std::io::SeekFrom::Start(header as u64))?;
file.write_all(&[(pos >> 24) as u8, (pos >> 16) as u8, (pos >> 8) as u8, (pos >> 0) as u8])?;
file.write_all(&pos.to_le_bytes())?;

// Return to the position where we are before writing the root position.
file.seek(std::io::SeekFrom::Start(pos_before_seek))?;
Expand Down
4 changes: 2 additions & 2 deletions compiler/rustc_metadata/src/rmeta/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -57,12 +57,12 @@ pub(crate) fn rustc_version(cfg_version: &'static str) -> String {
/// Metadata encoding version.
/// N.B., increment this if you change the format of metadata such that
/// the rustc version can't be found to compare with `rustc_version()`.
const METADATA_VERSION: u8 = 8;
const METADATA_VERSION: u8 = 9;

/// Metadata header which includes `METADATA_VERSION`.
///
/// This header is followed by the length of the compressed data, then
/// the position of the `CrateRoot`, which is encoded as a 32-bit big-endian
/// the position of the `CrateRoot`, which is encoded as a 64-bit little-endian
/// unsigned integer, and further followed by the rustc version string.
pub const METADATA_HEADER: &[u8] = &[b'r', b'u', b's', b't', 0, 0, 0, METADATA_VERSION];

Expand Down
21 changes: 13 additions & 8 deletions src/tools/rust-analyzer/crates/proc-macro-api/src/version.rs
Original file line number Diff line number Diff line change
Expand Up @@ -120,13 +120,18 @@ pub fn read_version(dylib_path: &AbsPath) -> io::Result<String> {
let version = u32::from_be_bytes([dot_rustc[4], dot_rustc[5], dot_rustc[6], dot_rustc[7]]);
// Last supported version is:
// https://github.com/rust-lang/rust/commit/0696e79f2740ad89309269b460579e548a5cd632
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this should point to your commit updating the format (yes it looks like we forgot to update it 2 times already).

Copy link
Member Author

@saethlin saethlin Dec 11, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's so outdated that when I saw this I wasn't sure if it's supposed to point at the oldest or the newest version that's supported. I can point this at the first commit in this PR.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it's supposed to point at the newest, because

  1. Last

  2. This points to 6, but the oldest supported version is 5, so I don't think it could have been added as an oldest one

let snappy_portion = match version {
5 | 6 => &dot_rustc[8..],
let (snappy_portion, bytes_before_version) = match version {
5 | 6 => (&dot_rustc[8..], 13),
7 | 8 => {
let len_bytes = &dot_rustc[8..12];
let data_len = u32::from_be_bytes(len_bytes.try_into().unwrap()) as usize;
&dot_rustc[12..data_len + 12]
(&dot_rustc[12..data_len + 12], 13)
}
9 => {
let len_bytes = &dot_rustc[8..16];
let data_len = u64::from_le_bytes(len_bytes.try_into().unwrap()) as usize;
(&dot_rustc[16..data_len + 12], 17)
}
_ => {
return Err(io::Error::new(
io::ErrorKind::InvalidData,
Expand All @@ -142,15 +147,15 @@ pub fn read_version(dylib_path: &AbsPath) -> io::Result<String> {
Box::new(SnapDecoder::new(snappy_portion))
};

// the bytes before version string bytes, so this basically is:
// We're going to skip over the bytes before the version string, so basically:
// 8 bytes for [b'r',b'u',b's',b't',0,0,0,5]
// 4 bytes for [crate root bytes]
// 4 or 8 bytes for [crate root bytes]
// 1 byte for length of version string
// so 13 bytes in total, and we should check the 13th byte
// so 13 or 17 bytes in total, and we should check the last of those bytes
// to know the length
let mut bytes_before_version = [0u8; 13];
let mut bytes_before_version = vec![0u8; bytes_before_version];
uncompressed.read_exact(&mut bytes_before_version)?;
let length = bytes_before_version[12];
let length = *bytes_before_version.last().unwrap();

let mut version_string_utf8 = vec![0u8; length as usize];
uncompressed.read_exact(&mut version_string_utf8)?;
Expand Down