in MachODump.cpp [3064:3261]
static void DumpBitcodeSection(MachOObjectFile *O, const char *sect,
uint32_t size, bool verbose, bool PrintXarHeader,
bool PrintXarFileHeaders,
std::string XarMemberName) {
if (size < sizeof(struct xar_header)) {
outs() << "size of (__LLVM,__bundle) section too small (smaller than size "
"of struct xar_header)\n";
return;
}
struct xar_header XarHeader;
memcpy(&XarHeader, sect, sizeof(struct xar_header));
if (sys::IsLittleEndianHost)
swapStruct(XarHeader);
if (PrintXarHeader) {
if (!XarMemberName.empty())
outs() << "In xar member " << XarMemberName << ": ";
else
outs() << "For (__LLVM,__bundle) section: ";
outs() << "xar header\n";
if (XarHeader.magic == XAR_HEADER_MAGIC)
outs() << " magic XAR_HEADER_MAGIC\n";
else
outs() << " magic "
<< format_hex(XarHeader.magic, 10, true)
<< " (not XAR_HEADER_MAGIC)\n";
outs() << " size " << XarHeader.size << "\n";
outs() << " version " << XarHeader.version << "\n";
outs() << " toc_length_compressed " << XarHeader.toc_length_compressed
<< "\n";
outs() << "toc_length_uncompressed " << XarHeader.toc_length_uncompressed
<< "\n";
outs() << " cksum_alg ";
switch (XarHeader.cksum_alg) {
case XAR_CKSUM_NONE:
outs() << "XAR_CKSUM_NONE\n";
break;
case XAR_CKSUM_SHA1:
outs() << "XAR_CKSUM_SHA1\n";
break;
case XAR_CKSUM_MD5:
outs() << "XAR_CKSUM_MD5\n";
break;
#ifdef XAR_CKSUM_SHA256
case XAR_CKSUM_SHA256:
outs() << "XAR_CKSUM_SHA256\n";
break;
#endif
#ifdef XAR_CKSUM_SHA512
case XAR_CKSUM_SHA512:
outs() << "XAR_CKSUM_SHA512\n";
break;
#endif
default:
outs() << XarHeader.cksum_alg << "\n";
}
}
SmallString<128> XarFilename;
int FD;
std::error_code XarEC =
sys::fs::createTemporaryFile("llvm-mctoll", "xar", FD, XarFilename);
if (XarEC) {
errs() << XarEC.message() << "\n";
return;
}
ToolOutputFile XarFile(XarFilename, FD);
raw_fd_ostream &XarOut = XarFile.os();
StringRef XarContents(sect, size);
XarOut << XarContents;
XarOut.close();
if (XarOut.has_error())
return;
xar_t xar = xar_open(XarFilename.c_str(), READ);
if (!xar) {
errs() << "Can't create temporary xar archive " << XarFilename << "\n";
return;
}
SmallString<128> TocFilename;
std::error_code TocEC =
sys::fs::createTemporaryFile("llvm-mctoll", "toc", TocFilename);
if (TocEC) {
errs() << TocEC.message() << "\n";
return;
}
xar_serialize(xar, TocFilename.c_str());
if (PrintXarFileHeaders) {
if (!XarMemberName.empty())
outs() << "In xar member " << XarMemberName << ": ";
else
outs() << "For (__LLVM,__bundle) section: ";
outs() << "xar archive files:\n";
PrintXarFilesSummary(XarFilename.c_str(), xar);
}
ErrorOr<std::unique_ptr<MemoryBuffer>> FileOrErr =
MemoryBuffer::getFileOrSTDIN(TocFilename.c_str());
if (std::error_code EC = FileOrErr.getError()) {
errs() << EC.message() << "\n";
return;
}
std::unique_ptr<MemoryBuffer> &Buffer = FileOrErr.get();
if (!XarMemberName.empty())
outs() << "In xar member " << XarMemberName << ": ";
else
outs() << "For (__LLVM,__bundle) section: ";
outs() << "xar table of contents:\n";
outs() << Buffer->getBuffer() << "\n";
// TODO: Go through the xar's files.
xar_iter_t xi = xar_iter_new();
if (!xi) {
errs() << "Can't obtain an xar iterator for xar archive "
<< XarFilename.c_str() << "\n";
xar_close(xar);
return;
}
for (xar_file_t xf = xar_file_first(xar, xi); xf; xf = xar_file_next(xi)) {
const char *key;
xar_iter_t xp;
const char *member_name, *member_type, *member_size_string;
size_t member_size;
xp = xar_iter_new();
if (!xp) {
errs() << "Can't obtain an xar iterator for xar archive "
<< XarFilename.c_str() << "\n";
xar_close(xar);
return;
}
member_name = NULL;
member_type = NULL;
member_size_string = NULL;
for (key = xar_prop_first(xf, xp); key; key = xar_prop_next(xp)) {
const char *val = nullptr;
xar_prop_get(xf, key, &val);
#if 0 // Useful for debugging.
outs() << "key: " << key << " value: " << val << "\n";
#endif
if (strcmp(key, "name") == 0)
member_name = val;
if (strcmp(key, "type") == 0)
member_type = val;
if (strcmp(key, "data/size") == 0)
member_size_string = val;
}
/*
* If we find a file with a name, date/size and type properties
* and with the type being "file" see if that is a xar file.
*/
if (member_name != NULL && member_type != NULL &&
strcmp(member_type, "file") == 0 && member_size_string != NULL) {
// Extract the file into a buffer.
char *endptr;
member_size = strtoul(member_size_string, &endptr, 10);
if (*endptr == '\0' && member_size != 0) {
char *buffer = (char *)::operator new(member_size);
if (xar_extract_tobuffersz(xar, xf, &buffer, &member_size) == 0) {
#if 0 // Useful for debugging.
outs() << "xar member: " << member_name << " extracted\n";
#endif
// Set the XarMemberName we want to see printed in the header.
std::string OldXarMemberName;
// If XarMemberName is already set this is nested. So
// save the old name and create the nested name.
if (!XarMemberName.empty()) {
OldXarMemberName = XarMemberName;
XarMemberName =
(Twine("[") + XarMemberName + "]" + member_name).str();
} else {
OldXarMemberName = "";
XarMemberName = member_name;
}
// See if this is could be a xar file (nested).
if (member_size >= sizeof(struct xar_header)) {
#if 0 // Useful for debugging.
outs() << "could be a xar file: " << member_name << "\n";
#endif
memcpy((char *)&XarHeader, buffer, sizeof(struct xar_header));
if (sys::IsLittleEndianHost)
swapStruct(XarHeader);
if (XarHeader.magic == XAR_HEADER_MAGIC)
DumpBitcodeSection(O, buffer, member_size, verbose,
PrintXarHeader, PrintXarFileHeaders,
XarMemberName);
}
XarMemberName = OldXarMemberName;
}
delete buffer;
}
}
xar_iter_free(xp);
}
xar_close(xar);
}