Skip to content

Commit 0979236

Browse files
authored
cleanup reading kcore blocks (#102)
1 parent 7398475 commit 0979236

File tree

4 files changed

+313
-54
lines changed

4 files changed

+313
-54
lines changed

src/image.rs

+1
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,7 @@ pub struct Header {
5858
pub version: u32,
5959
}
6060

61+
#[derive(PartialEq, Eq, Debug, Clone)]
6162
pub struct Block {
6263
pub offset: u64,
6364
pub range: Range<u64>,

src/iomem.rs

+66-38
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@ fn parse_file(path: &Path) -> Result<Vec<Range<u64>>, Error> {
4848
ranges.push(start..end);
4949
}
5050

51-
Ok(ranges)
51+
Ok(merge_ranges(ranges))
5252
}
5353

5454
#[must_use]
@@ -122,43 +122,71 @@ mod tests {
122122

123123
#[test]
124124
fn test_parse_iomem() -> Result<(), Error> {
125-
let ranges = parse_file(Path::new("test/iomem.txt"))?;
126-
let expected = [
127-
4096..654_335,
128-
1_048_576..1_073_676_287,
129-
4_294_967_296..6_979_321_855,
130-
];
131-
assert_eq!(ranges, expected);
132-
133-
let ranges = parse_file(Path::new("test/iomem-2.txt"))?;
134-
let expected = [
135-
4096..655_359,
136-
1_048_576..1_055_838_207,
137-
1_056_026_624..1_073_328_127,
138-
1_073_737_728..1_073_741_823,
139-
4_294_967_296..6_979_321_855,
140-
];
141-
assert_eq!(ranges, expected);
142-
143-
let ranges = parse_file(Path::new("test/iomem-3.txt"))?;
144-
let expected = [
145-
65_536..649_215,
146-
1_048_576..2_146_303_999,
147-
2_146_435_072..2_147_483_647,
148-
];
149-
assert_eq!(ranges, expected);
150-
151-
let ranges = parse_file(Path::new("test/iomem-4.txt"))?;
152-
let expected = [
153-
4_096..655_359,
154-
1_048_576..1_423_523_839,
155-
1_423_585_280..1_511_186_431,
156-
1_780_150_272..1_818_623_999,
157-
1_818_828_800..1_843_613_695,
158-
2_071_535_616..2_071_986_175,
159-
4_294_967_296..414_464_344_063,
160-
];
161-
assert_eq!(ranges, expected);
125+
for (filename, expected) in [
126+
(
127+
Path::new("test/iomem.txt"),
128+
vec![
129+
4096..654_335,
130+
1_048_576..1_073_676_287,
131+
4_294_967_296..6_979_321_855,
132+
],
133+
),
134+
(
135+
Path::new("test/iomem-2.txt"),
136+
vec![
137+
4096..655_359,
138+
1_048_576..1_055_838_207,
139+
1_056_026_624..1_073_328_127,
140+
1_073_737_728..1_073_741_823,
141+
4_294_967_296..6_979_321_855,
142+
],
143+
),
144+
(
145+
Path::new("test/iomem-3.txt"),
146+
vec![
147+
65_536..649_215,
148+
1_048_576..2_146_303_999,
149+
2_146_435_072..2_147_483_647,
150+
],
151+
),
152+
(
153+
Path::new("test/iomem-4.txt"),
154+
vec![
155+
4_096..655_359,
156+
1_048_576..1_423_523_839,
157+
1_423_585_280..1_511_186_431,
158+
1_780_150_272..1_818_623_999,
159+
1_818_828_800..1_843_613_695,
160+
2_071_535_616..2_071_986_175,
161+
4_294_967_296..414_464_344_063,
162+
],
163+
),
164+
(
165+
Path::new("test/iomem-5.txt"),
166+
vec![
167+
4_096..655_359,
168+
1_048_576..175_058_967,
169+
175_058_968..175_067_223,
170+
175_067_224..175_071_255,
171+
175_071_256..175_077_463,
172+
175_077_464..175_079_447,
173+
175_079_448..175_087_703,
174+
175_087_704..175_091_735,
175+
175_091_736..175_124_567,
176+
175_124_568..241_524_735,
177+
241_643_520..251_310_079,
178+
251_326_464..251_383_807,
179+
251_424_768..264_671_231,
180+
264_675_328..267_280_383,
181+
267_739_136..267_866_111,
182+
267_870_208..3_221_225_471,
183+
4_294_967296..13_958_643_711,
184+
],
185+
),
186+
] {
187+
let ranges = parse_file(filename)?;
188+
assert_eq!(ranges, expected);
189+
}
162190

163191
Ok(())
164192
}

src/snapshot.rs

+107-16
Original file line numberDiff line numberDiff line change
@@ -20,9 +20,6 @@ pub enum Error {
2020
#[error("locked down /proc/kcore")]
2121
LockedDownKcore,
2222

23-
#[error("unable to find memory range: {0:?}")]
24-
UnableToFindMemoryRange(Range<u64>),
25-
2623
#[error("unable to create memory snapshot")]
2724
UnableToCreateMemorySnapshot(#[from] crate::image::Error),
2825

@@ -194,6 +191,50 @@ impl<'a, 'b> Snapshot<'a, 'b> {
194191
Ok(())
195192
}
196193

194+
// given a set of ranges from iomem and a set of Blocks derived from the
195+
// psuedo-elf phys section headers, derive a set of ranges that can be used
196+
// to create a snapshot.
197+
fn find_kcore_blocks(ranges: &[Range<u64>], headers: &[Block]) -> Vec<Block> {
198+
let mut result = vec![];
199+
200+
'outer: for range in ranges {
201+
let mut range = range.clone();
202+
203+
'inner: for header in headers {
204+
match (
205+
header.range.contains(&range.start),
206+
// TODO: ranges is currently inclusive, but not a
207+
// RangeInclusive. this should be adjusted.
208+
header.range.contains(&(range.end - 1)),
209+
) {
210+
(true, true) => {
211+
let block = Block {
212+
offset: header.offset + range.start - header.range.start,
213+
range: range.clone(),
214+
};
215+
216+
result.push(block);
217+
continue 'outer;
218+
}
219+
(true, false) => {
220+
let block = Block {
221+
offset: header.offset + range.start - header.range.start,
222+
range: range.start..header.range.end,
223+
};
224+
225+
result.push(block);
226+
range.start = header.range.end;
227+
}
228+
_ => {
229+
continue 'inner;
230+
}
231+
};
232+
}
233+
}
234+
235+
result
236+
}
237+
197238
fn kcore(&self) -> Result<()> {
198239
if !is_kcore_ok() {
199240
return Err(Error::LockedDownKcore);
@@ -206,21 +247,19 @@ impl<'a, 'b> Snapshot<'a, 'b> {
206247
file.phdrs.sort_by(|a, b| a.vaddr.cmp(&b.vaddr));
207248
let start = file.phdrs[0].vaddr - self.memory_ranges[0].start;
208249

209-
let mut blocks = vec![];
210-
'outer: for range in &self.memory_ranges {
211-
for phdr in &file.phdrs {
212-
if range.start == phdr.vaddr - start {
213-
let size = u64::min(phdr.memsz, range.end - range.start);
214-
blocks.push(Block {
215-
offset: phdr.offset,
216-
range: range.start..range.start + size,
217-
});
218-
continue 'outer;
219-
}
220-
}
221-
return Err(Error::UnableToFindMemoryRange(range.clone()));
250+
let mut physical_ranges = vec![];
251+
252+
for phdr in file.phdrs {
253+
let entry_start = phdr.vaddr - start;
254+
let entry_end = entry_start + phdr.memsz;
255+
256+
physical_ranges.push(Block {
257+
range: entry_start..entry_end,
258+
offset: phdr.offset,
259+
});
222260
}
223261

262+
let blocks = Self::find_kcore_blocks(&self.memory_ranges, &physical_ranges);
224263
image.write_blocks(&blocks)?;
225264
Ok(())
226265
}
@@ -247,3 +286,55 @@ impl<'a, 'b> Snapshot<'a, 'b> {
247286
Ok(())
248287
}
249288
}
289+
290+
#[cfg(test)]
291+
mod tests {
292+
use super::*;
293+
294+
#[test]
295+
fn translate_ranges() {
296+
let ranges = [10..20, 30..35, 45..55];
297+
298+
let core_ranges = [
299+
Block {
300+
range: 10..20,
301+
offset: 0,
302+
},
303+
Block {
304+
range: 25..35,
305+
offset: 10,
306+
},
307+
Block {
308+
range: 40..50,
309+
offset: 20,
310+
},
311+
Block {
312+
range: 50..55,
313+
offset: 35,
314+
},
315+
];
316+
317+
let expected = vec![
318+
Block {
319+
offset: 0,
320+
range: 10..20,
321+
},
322+
Block {
323+
offset: 10 + 5,
324+
range: 30..35,
325+
},
326+
Block {
327+
offset: 25,
328+
range: 45..50,
329+
},
330+
Block {
331+
offset: 35,
332+
range: 50..55,
333+
},
334+
];
335+
336+
let result = Snapshot::find_kcore_blocks(&ranges, &core_ranges);
337+
338+
assert_eq!(result, expected);
339+
}
340+
}

0 commit comments

Comments
 (0)