| 160 | use object::{Object, ObjectSection}; |
| 161 | |
| 162 | fn roundtrip(maps: &[(u64, u32, &[u32])]) { |
| 163 | let mut section = StackMapSection::default(); |
| 164 | for (pc, frame, offsets) in maps { |
| 165 | println!("append {pc}"); |
| 166 | section.push(*pc, *frame, offsets.iter().copied()); |
| 167 | } |
| 168 | let mut object = object::write::Object::new( |
| 169 | object::BinaryFormat::Elf, |
| 170 | object::Architecture::X86_64, |
| 171 | object::Endianness::Little, |
| 172 | ); |
| 173 | section.append_to(&mut object); |
| 174 | let elf = object.write().unwrap(); |
| 175 | |
| 176 | let image = object::File::parse(&elf[..]).unwrap(); |
| 177 | let data = image |
| 178 | .sections() |
| 179 | .find(|s| s.name().ok() == Some(ELF_WASMTIME_STACK_MAP)) |
| 180 | .unwrap() |
| 181 | .data() |
| 182 | .unwrap(); |
| 183 | |
| 184 | for (pc, frame, offsets) in maps { |
| 185 | println!("lookup {pc}"); |
| 186 | let map = match StackMap::lookup(*pc as u32, data) { |
| 187 | Some(map) => map, |
| 188 | None => { |
| 189 | assert!(offsets.is_empty()); |
| 190 | continue; |
| 191 | } |
| 192 | }; |
| 193 | assert_eq!(map.frame_size(), *frame); |
| 194 | |
| 195 | let map_offsets = map.offsets().collect::<Vec<_>>(); |
| 196 | assert_eq!(map_offsets, *offsets); |
| 197 | } |
| 198 | |
| 199 | let mut expected = maps.iter(); |
| 200 | 'outer: for (pc, map) in StackMap::iter(data).unwrap() { |
| 201 | while let Some((expected_pc, expected_frame, expected_offsets)) = expected.next() { |
| 202 | if expected_offsets.is_empty() { |
| 203 | continue; |
| 204 | } |
| 205 | assert_eq!(*expected_pc, u64::from(pc)); |
| 206 | assert_eq!(*expected_frame, map.frame_size()); |
| 207 | let offsets = map.offsets().collect::<Vec<_>>(); |
| 208 | assert_eq!(offsets, *expected_offsets); |
| 209 | continue 'outer; |
| 210 | } |
| 211 | panic!("didn't find {pc:#x} in expected list"); |
| 212 | } |
| 213 | assert!(expected.next().is_none()); |
| 214 | } |
| 215 | |
| 216 | #[test] |
| 217 | fn roundtrip_many() { |