let exe_path = std::env::current_exe().expect("unable to retrieve test executable path");
cmd.arg(exe_path);
let output = cmd.output().expect("failed to spawn otool");
assert!(output.status.success());
String::from_utf8(output.stdout).expect("stdout was invalid utf-8")
}
/// Validates we can iterate the load commands for all of the images in the task #[test] fn iterates_load_commands() { let lc_str = call_otool(&["-l"]);
// otool prints the load command index for each command, but we only // handle the small subset of the available load commands we care about // so just ignore that let block = &block[block.find('\n').unwrap() + 1..];
// otool also prints all the sections for LC_SEGMENT_* commands, but // we don't care about those, so ignore them let block = match block.find("Section") {
Some(ind) => &block[..ind],
None => block,
};
lc_index += 13;
let cmd = block
.find("cmd ")
.expect("load commnd didn't specify cmd kind"); let cmd_end = block[cmd..]
.find('\n')
.expect("load cmd didn't end with newline"); if matches!(
&block[cmd + 4..cmd + cmd_end], "LC_SEGMENT_64" | "LC_UUID" | "LC_ID_DYLIB" | "LC_LOAD_DYLINKER"
) {
expected.push_str(block);
}
}
// Unfortunately, Apple decided to move dynamic libs into a shared cache, // removing them from the file system completely, and unless I'm missing it // there is no way to get the load commands for the dylibs since otool // only understands file paths? So we just get the load commands for the main // executable instead, this means that we miss the `LC_ID_DYLIB` commands // since they only apply to dylibs, but this test is more that we can // correctly iterate through the load commands themselves, so this _should_ // be fine... let exe_img = task_dumper
.read_executable_image()
.expect("failed to read executable image");
{ let lcmds = task_dumper
.read_load_commands(&exe_img)
.expect("failed to read load commands");
for lc in lcmds.iter() { match lc {
LoadCommand::Segment(seg) => { let segname = std::str::from_utf8(&seg.segment_name).unwrap(); let segname = &segname[..segname.find('\0').unwrap()];
write!(
&mut actual, "
cmd LC_SEGMENT_64
cmdsize {}
segname {}
vmaddr 0x{:016x}
vmsize 0x{:016x}
fileoff {}
filesize {}
maxprot 0x{:08x}
initprot 0x{:08x}
nsects {}
flags 0x{:x}",
seg.cmd_size,
segname,
seg.vm_addr,
seg.vm_size,
seg.file_off,
seg.file_size,
seg.max_prot,
seg.init_prot,
seg.num_sections,
seg.flags,
)
.unwrap();
}
LoadCommand::Dylib(_dylib) => {
unreachable!();
}
LoadCommand::Uuid(uuid) => { let id = uuid::Uuid::from_bytes(uuid.uuid); letmut uuid_buf = [0u8; uuid::fmt::Hyphenated::LENGTH]; let uuid_str = id.hyphenated().encode_upper(&mut uuid_buf);
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.