1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49
#![feature(asm)] #[macro_export] macro_rules! releasetag { // The argument of releasetag!() must be a byte-string (array) of 8bit elements, // instead of unicode string. The release-tag may be a byte-string of any size. In case the // the release-tag has byte-length of 126, the occupied stack-size would be 128 bytes, // adding leading and trailing null-characters. // // The feature is restricted to byte-strings as unicode strings might contain // non-printable characters causing 'strings' command line tool to print fragments of // tag only (causing loss of information) ($tag:expr) => {{ // CAPACITY incl leading and trailing \0 (+2) const CAPACITY : usize = byte_size_of!($tag) + 2; // Analog to C, declare a type of fixed size, providing a byte-wise copy operator #[derive(Copy, Clone)] struct FixedSize { data: [u8; CAPACITY], } // const data will not be on stack. As command line tool 'strings' will search for // null-terminated printable chars, add leading and trailing null-char \0 (aka 0u8) const CONST_DATA : & 'static [u8; CAPACITY] = concat_bytes!([0u8],$tag,[0u8]); // Create instance of FixedSize and copy chunk byte-wise onto stack, // the bounds are verified during compile time. let stacktag = FixedSize{data : *CONST_DATA}; // nop to force linker to preserve the variable on stack unsafe { asm!("" : : "r"(&stacktag)) } }}; } #[cfg(test)] mod tests { // just testing syntax from within, please use test/run_test.sh which is // starting a small application. The script will cause the appl. to core-dump with // signal 6 and parse the core file for releasetag strings. If the tags can not be found // in the core file the feature did fail. #[test] fn valid_macro() { releasetag!(b"TAG1=123"); releasetag!(b"TAG2=ABC"); } }