1/*******************************************************************\
7\*******************************************************************/
17// we define file-type magic values for all platforms to detect when we find a
18// file that we might not be able to process
19 #define CPROVER_FAT_MAGIC 0xcafebabe
20 #define CPROVER_FAT_CIGAM 0xbebafeca
21 #define CPROVER_MH_MAGIC 0xfeedface
22 #define CPROVER_MH_CIGAM 0xcefaedfe
23 #define CPROVER_MH_MAGIC_64 0xfeedfacf
24 #define CPROVER_MH_CIGAM_64 0xcffaedfe
27# include <architecture/byte_order.h>
28# include <mach-o/fat.h>
29# include <mach-o/loader.h>
30# include <mach-o/swap.h>
32# if(CPROVER_FAT_MAGIC != FAT_MAGIC) || (CPROVER_FAT_CIGAM != FAT_CIGAM) || \
33 (CPROVER_MH_MAGIC != MH_MAGIC) || (CPROVER_MH_CIGAM != MH_CIGAM) || \
34 (CPROVER_MH_MAGIC_64 != MH_MAGIC_64) || \
35 (CPROVER_MH_CIGAM_64 != MH_CIGAM_64)
36# error "Mach-O magic has inconsistent value"
62 // Unfortunately for us, both Java class files and Mach fat binaries use the
63 // magic number 0xCAFEBABE. Therefore we must also check the second field,
64 // number of architectures, is in a sensible range (I use at 1 <= archs < 20,
65 // the same criterion used by `GNU file`).
66 // Luckily the class file format stores the file version here, which cannot
67 // fall in this range.
77 :
log(message_handler), has_gb_arch(
false)
80 // NOLINTNEXTLINE(readability/identifiers)
82 // NOLINTNEXTLINE(readability/identifiers)
83 in.read(
reinterpret_cast<char*
>(&
fh),
sizeof(
struct fat_header));
88 static_assert(
sizeof(
fh) >= 8,
"fat_header is at least 8 bytes");
93 sizeof(
fh.nfat_arch) == 4,
"fat_header::nfat_arch is of type uint32_t");
98 // NOLINTNEXTLINE(readability/identifiers)
100 // NOLINTNEXTLINE(readability/identifiers)
101 in.read(
reinterpret_cast<char*
>(&
fa),
sizeof(
struct fat_arch));
104 sizeof(
fa.cputype) == 4 &&
sizeof(
fa.cpusubtype) == 4 &&
105 sizeof(
fa.size) == 4,
106 "This requires a specific fat architecture");
116 (
void)in;
// unused parameter
118 log.
warning() <<
"Cannot read OSX fat archive on this platform"
124 const std::string &source,
125 const std::string &dest)
const
130 "lipo", {
"lipo",
"-thin",
"hppa7100LC",
"-output", dest, source}) !=
134// guided by https://lowlevelbits.org/parsing-mach-o-files/
156 // NOLINTNEXTLINE(readability/identifiers)
158 in.read(
reinterpret_cast<char *
>(&s),
sizeof(s));
180 // NOLINTNEXTLINE(readability/identifiers)
182 in.read(
reinterpret_cast<char *
>(&s),
sizeof(s));
209 // NOLINTNEXTLINE(readability/identifiers)
211 in.read(
reinterpret_cast<char *
>(&
lc),
sizeof(
lc));
219 // we may need to re-read the command once we have figured out its type; in
220 // particular, segment commands contain additional information that we have
221 // now just read a prefix of
228 // NOLINTNEXTLINE(readability/identifiers)
230 in.read(
reinterpret_cast<char *
>(&
seg),
sizeof(
seg));
243 // NOLINTNEXTLINE(readability/identifiers)
245 in.read(
reinterpret_cast<char *
>(&
seg),
sizeof(
seg));
260 offset +=
lc.cmdsize;
277 in.read(
reinterpret_cast<char *
>(&magic),
sizeof(magic));
303 std::size_t offset = 0;
305 // re-read from the beginning, now reading the full header
310 // NOLINTNEXTLINE(readability/identifiers)
312 in.read(
reinterpret_cast<char *
>(&
mh),
sizeof(
mh));
325 // NOLINTNEXTLINE(readability/identifiers)
327 in.read(
reinterpret_cast<char *
>(&
mh),
sizeof(
mh));
message_handlert & message_handler
ait supplies three of the four components needed: an abstract interpreter (in this case handling func...
Thrown when failing to deserialize a value from some low level format, like JSON or raw bytes.
mstreamt & warning() const
osx_fat_readert(std::ifstream &, message_handlert &)
bool extract_gb(const std::string &source, const std::string &dest) const
void process_commands(uint32_t ncmds, std::size_t offset, bool need_swap)
osx_mach_o_readert(std::istream &, message_handlert &)
void process_sections_32(uint32_t nsects, bool need_swap)
void process_sections_64(uint32_t nsects, bool need_swap)
Thrown when some external system fails unexpectedly.
bool is_osx_fat_header(char header_bytes[8])
#define CPROVER_FAT_MAGIC
static uint32_t u32_to_native_endian(uint32_t input)
#define CPROVER_MH_MAGIC_64
bool is_osx_mach_object(char hdr[4])
#define CPROVER_MH_CIGAM_64
bool is_osx_fat_header(char hdr[8])
int run(const std::string &what, const std::vector< std::string > &argv)
#define PRECONDITION(CONDITION)