mirror of
https://github.com/rui314/mold.git
synced 2026-11-10 04:31:31 -10:00
Use standard ranges for output file slices
This commit is contained in:
1 parent
e3a89f222d
commit
b7e53ea5e6
2 files changed
+20
-30
No files matched your search
+12
-16
@@ -1,6 +1,7 @@
|
||||
//! The linker driver: runs the passes in order.
|
||||
|
||||
use std::fmt;
|
||||
use std::ops::Range;
|
||||
use std::sync::mpsc;
|
||||
|
||||
use rayon::prelude::*;
|
||||
@@ -11,7 +12,7 @@ use crate::cmdline::{self, Args, TargetTraits};
|
||||
use crate::context::Context;
|
||||
use crate::elf::*;
|
||||
use crate::input_files::FileId;
|
||||
use crate::output_file::{split_ranges, OutputFile, Range};
|
||||
use crate::output_file::{split_ranges, OutputFile};
|
||||
use crate::{error, fatal, passes};
|
||||
|
||||
/// Runs the linker with the given command line. Returns the exit status.
|
||||
@@ -677,17 +678,15 @@ pub fn link<E: Arch>(cmdline: &[std::ffi::OsString]) -> Result<i32, String> {
|
||||
Ok(0)
|
||||
}
|
||||
|
||||
fn file_range<E: Arch>(ctx: &Context<E>, id: ChunkId) -> Range {
|
||||
fn file_range<E: Arch>(ctx: &Context<E>, id: ChunkId) -> Range<u64> {
|
||||
let hdr = ctx.chunk_header(id);
|
||||
let size = if hdr.shdr.sh_type.get() == SHT_NOBITS {
|
||||
0
|
||||
} else {
|
||||
hdr.shdr.sh_size.get()
|
||||
};
|
||||
Range {
|
||||
offset: hdr.shdr.sh_offset.get(),
|
||||
size,
|
||||
}
|
||||
let offset = hdr.shdr.sh_offset.get();
|
||||
offset..offset + size
|
||||
}
|
||||
|
||||
/// A chunk together with the other chunks whose bytes it writes.
|
||||
@@ -778,20 +777,20 @@ pub fn copy_chunks<E: Arch>(ctx: &Context<E>, buf: &mut [u8]) {
|
||||
passes::report_undef_errors(ctx);
|
||||
|
||||
// Zero-clear paddings between chunks
|
||||
let mut ranges: Vec<Range> = ctx
|
||||
let mut ranges: Vec<Range<u64>> = ctx
|
||||
.chunks
|
||||
.iter()
|
||||
.map(|&id| file_range(ctx, id))
|
||||
.filter(|r| r.size != 0)
|
||||
.filter(|r| !r.is_empty())
|
||||
.collect();
|
||||
ranges.sort_by_key(|r| r.offset);
|
||||
ranges.sort_by_key(|r| r.start);
|
||||
let mut pos = 0usize;
|
||||
for r in ranges {
|
||||
let start = r.offset as usize;
|
||||
let start = r.start as usize;
|
||||
if start > pos {
|
||||
buf[pos..start].fill(0);
|
||||
}
|
||||
pos = pos.max(start + r.size as usize);
|
||||
pos = pos.max(r.end as usize);
|
||||
}
|
||||
buf[pos..].fill(0);
|
||||
}
|
||||
@@ -802,7 +801,7 @@ fn run_tasks<E: Arch>(
|
||||
tasks: &[Task],
|
||||
timer: &crate::util::perf::Timer,
|
||||
) {
|
||||
let mut ranges: Vec<Range> = Vec::new();
|
||||
let mut ranges: Vec<Range<u64>> = Vec::new();
|
||||
let mut task_ranges: Vec<Vec<usize>> = Vec::new();
|
||||
for task in tasks {
|
||||
let mut idx = Vec::new();
|
||||
@@ -846,10 +845,7 @@ fn run_tasks<E: Arch>(
|
||||
// .eh_frame_hdr's header, whose table .eh_frame wrote.
|
||||
if tasks.iter().any(|t| t.chunk == ChunkId::EhFrame) && ctx.eh_frame_hdr.is_some() {
|
||||
let r = file_range(ctx, ChunkId::EhFrameHdr);
|
||||
chunks::eh_frame_hdr::write_header(
|
||||
ctx,
|
||||
&mut buf[r.offset as usize..(r.offset + r.size) as usize],
|
||||
);
|
||||
chunks::eh_frame_hdr::write_header(ctx, &mut buf[r.start as usize..r.end as usize]);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+8
-14
@@ -4,6 +4,7 @@
|
||||
|
||||
use std::fs::{File, OpenOptions};
|
||||
use std::io::{self, Write};
|
||||
use std::ops::Range;
|
||||
#[cfg(not(windows))]
|
||||
use std::os::unix::fs::{OpenOptionsExt, PermissionsExt};
|
||||
#[cfg(not(windows))]
|
||||
@@ -434,29 +435,22 @@ pub fn split_at_offsets<'a, T>(buf: &'a mut [T], offsets: &[u64]) -> Vec<&'a mut
|
||||
slices
|
||||
}
|
||||
|
||||
/// A byte range of the output file.
|
||||
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
|
||||
pub struct Range {
|
||||
pub offset: u64,
|
||||
pub size: u64,
|
||||
}
|
||||
|
||||
/// Borrows several disjoint ranges of a buffer mutably at once.
|
||||
pub fn split_ranges<'a>(buf: &'a mut [u8], ranges: &[Range]) -> Vec<&'a mut [u8]> {
|
||||
pub fn split_ranges<'a>(buf: &'a mut [u8], ranges: &[Range<u64>]) -> Vec<&'a mut [u8]> {
|
||||
let mut order: Vec<usize> = (0..ranges.len()).collect();
|
||||
order.sort_by_key(|&i| ranges[i].offset);
|
||||
order.sort_by_key(|&i| ranges[i].start);
|
||||
|
||||
let mut result: Vec<Option<&'a mut [u8]>> = (0..ranges.len()).map(|_| None).collect();
|
||||
let mut rest = buf;
|
||||
let mut pos = 0u64;
|
||||
for i in order {
|
||||
let r = ranges[i];
|
||||
assert!(r.offset >= pos, "overlapping output ranges");
|
||||
let (_, tail) = std::mem::take(&mut rest).split_at_mut((r.offset - pos) as usize);
|
||||
let (slice, tail) = tail.split_at_mut(r.size as usize);
|
||||
let r = &ranges[i];
|
||||
assert!(r.start >= pos, "overlapping output ranges");
|
||||
let (_, tail) = std::mem::take(&mut rest).split_at_mut((r.start - pos) as usize);
|
||||
let (slice, tail) = tail.split_at_mut((r.end - r.start) as usize);
|
||||
result[i] = Some(slice);
|
||||
rest = tail;
|
||||
pos = r.offset + r.size;
|
||||
pos = r.end;
|
||||
}
|
||||
result.into_iter().map(|s| s.unwrap()).collect()
|
||||
}
|
||||
|
||||
Reference in new issue
Block a user