CodeQL / Analyze (actions) (push) Canceled after 0s
CodeQL / Analyze (python) (push) Canceled after 0s
pre-commit / pre-commit (push) Canceled after 0s
Multi-Arch CI / setup (push) Canceled after 0s
Publish build_manylinux_x86_64 images / publish_build_manylinux_x86_64 (push) Canceled after 0s
Setup (Multi-Arch) / setup (push) Canceled after 0s
Multi-Arch CI / Linux::${{ fromJSON(needs.setup.outputs.linux_build_config || '{}').build_variant_label || 'skip' }} (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Publish no_rocm_image_ubi10 image / publish_no_rocm_image_ubi10 (push) Canceled after 0s
Multi-Arch CI / Windows::${{ fromJSON(needs.setup.outputs.windows_build_config || '{}').build_variant_label || 'skip' }} (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Multi-Arch CI / Manifest Diff (push) Canceled after 0s
TheRock Manifest Diff Report / Generate Manifest Diff Report (push) Canceled after 0s
Multi-Arch CI / CI Summary (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04 (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04_ocl_rt images / publish_no_rocm_image_ubuntu24_04_ocl_rt (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04_rocgdb (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04_rocgdb images / publish_no_rocm_image_ubuntu24_04_rocgdb (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04_ocl_rt (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Unit Tests / Unit Tests :: ubuntu-24.04 (push) Canceled after 0s
Unit Tests / Unit Tests :: windows-2022 (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04_media (push) Canceled after 0s
Unit Tests / Unit Tests Summary (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04_openmpi (push) Canceled after 0s
193 lines
6.3 KiB
C++
193 lines
6.3 KiB
C++
//===- tools/dsymutil/SwiftModule.cpp -------------------------------------===//
|
|
//
|
|
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
|
// See https://llvm.org/LICENSE.txt for license information.
|
|
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
#include "llvm/Bitcode/BitcodeReader.h"
|
|
#include "llvm/Bitcode/LLVMBitCodes.h"
|
|
#include "llvm/Bitstream/BitCodes.h"
|
|
#include "llvm/Bitstream/BitstreamReader.h"
|
|
|
|
namespace {
|
|
// Copied from swift/lib/Serialization/ModuleFormat.h
|
|
constexpr unsigned char SWIFTMODULE_SIGNATURE[] = {0xE2, 0x9C, 0xA8, 0x0E};
|
|
constexpr uint16_t expectedMajorVersion = 0;
|
|
constexpr unsigned MODULE_BLOCK_ID = llvm::bitc::FIRST_APPLICATION_BLOCKID;
|
|
constexpr unsigned CONTROL_BLOCK_ID = llvm::bitc::FIRST_APPLICATION_BLOCKID + 1;
|
|
constexpr unsigned METADATA = 1;
|
|
constexpr unsigned OPTIONS_BLOCK_ID = llvm::bitc::FIRST_APPLICATION_BLOCKID + 8;
|
|
constexpr unsigned IS_BUILT_FROM_INTERFACE = 11;
|
|
|
|
llvm::Error checkModuleSignature(llvm::BitstreamCursor &cursor,
|
|
llvm::ArrayRef<unsigned char> signature) {
|
|
for (unsigned char byte : signature) {
|
|
if (cursor.AtEndOfStream())
|
|
return llvm::createStringError("malformed bitstream");
|
|
llvm::Expected<llvm::SimpleBitstreamCursor::word_t> maybeRead =
|
|
cursor.Read(8);
|
|
if (!maybeRead)
|
|
return maybeRead.takeError();
|
|
if (maybeRead.get() != byte)
|
|
return llvm::createStringError("malformed bitstream");
|
|
}
|
|
return llvm::Error::success();
|
|
}
|
|
|
|
llvm::Error enterTopLevelModuleBlock(llvm::BitstreamCursor &cursor,
|
|
unsigned ID) {
|
|
llvm::Expected<llvm::BitstreamEntry> maybeNext = cursor.advance();
|
|
if (!maybeNext)
|
|
return maybeNext.takeError();
|
|
llvm::BitstreamEntry next = maybeNext.get();
|
|
|
|
if (next.Kind != llvm::BitstreamEntry::SubBlock)
|
|
return llvm::createStringError("malformed bitstream");
|
|
|
|
if (next.ID == llvm::bitc::BLOCKINFO_BLOCK_ID) {
|
|
if (cursor.SkipBlock())
|
|
return llvm::createStringError("malformed bitstream");
|
|
return enterTopLevelModuleBlock(cursor, ID);
|
|
}
|
|
|
|
if (next.ID != ID)
|
|
return llvm::createStringError("malformed bitstream");
|
|
|
|
if (llvm::Error Err = cursor.EnterSubBlock(ID))
|
|
return Err;
|
|
|
|
return llvm::Error::success();
|
|
}
|
|
|
|
llvm::Expected<bool>
|
|
readOptionsBlock(llvm::BitstreamCursor &cursor,
|
|
llvm::SmallVectorImpl<uint64_t> &scratch) {
|
|
bool is_built_from_interface = false;
|
|
while (!cursor.AtEndOfStream()) {
|
|
llvm::Expected<llvm::BitstreamEntry> maybeEntry = cursor.advance();
|
|
if (!maybeEntry)
|
|
return maybeEntry.takeError();
|
|
|
|
llvm::BitstreamEntry entry = maybeEntry.get();
|
|
if (entry.Kind == llvm::BitstreamEntry::EndBlock)
|
|
break;
|
|
|
|
if (entry.Kind == llvm::BitstreamEntry::Error)
|
|
return llvm::createStringError("malformed bitstream");
|
|
|
|
if (entry.Kind == llvm::BitstreamEntry::SubBlock) {
|
|
if (cursor.SkipBlock())
|
|
return llvm::createStringError("malformed bitstream");
|
|
continue;
|
|
}
|
|
|
|
scratch.clear();
|
|
llvm::StringRef blobData;
|
|
llvm::Expected<unsigned> maybeKind =
|
|
cursor.readRecord(entry.ID, scratch, &blobData);
|
|
if (!maybeKind)
|
|
return maybeKind.takeError();
|
|
unsigned kind = maybeKind.get();
|
|
switch (kind) {
|
|
case IS_BUILT_FROM_INTERFACE:
|
|
is_built_from_interface = true;
|
|
continue;
|
|
default:
|
|
continue;
|
|
}
|
|
}
|
|
return is_built_from_interface;
|
|
}
|
|
|
|
llvm::Expected<bool>
|
|
parseControlBlock(llvm::BitstreamCursor &cursor,
|
|
llvm::SmallVectorImpl<uint64_t> &scratch) {
|
|
// The control block is malformed until we've at least read a major version
|
|
// number.
|
|
bool versionSeen = false;
|
|
|
|
while (!cursor.AtEndOfStream()) {
|
|
llvm::Expected<llvm::BitstreamEntry> maybeEntry = cursor.advance();
|
|
if (!maybeEntry)
|
|
return maybeEntry.takeError();
|
|
|
|
llvm::BitstreamEntry entry = maybeEntry.get();
|
|
if (entry.Kind == llvm::BitstreamEntry::EndBlock)
|
|
break;
|
|
|
|
if (entry.Kind == llvm::BitstreamEntry::Error)
|
|
return llvm::createStringError("malformed bitstream");
|
|
|
|
if (entry.Kind == llvm::BitstreamEntry::SubBlock) {
|
|
if (entry.ID == OPTIONS_BLOCK_ID) {
|
|
if (llvm::Error Err = cursor.EnterSubBlock(OPTIONS_BLOCK_ID))
|
|
return Err;
|
|
|
|
return readOptionsBlock(cursor, scratch);
|
|
} else {
|
|
// Unknown metadata sub-block, possibly for use by a future version of
|
|
// the module format.
|
|
if (cursor.SkipBlock())
|
|
return llvm::createStringError("malformed bitstream");
|
|
}
|
|
continue;
|
|
}
|
|
|
|
scratch.clear();
|
|
llvm::StringRef blobData;
|
|
llvm::Expected<unsigned> maybeKind =
|
|
cursor.readRecord(entry.ID, scratch, &blobData);
|
|
if (!maybeKind)
|
|
return maybeKind.takeError();
|
|
|
|
unsigned kind = maybeKind.get();
|
|
if (kind == METADATA) {
|
|
if (versionSeen)
|
|
return llvm::createStringError("multiple metadata blocks");
|
|
|
|
uint16_t versionMajor = scratch[0];
|
|
if (versionMajor != expectedMajorVersion)
|
|
return llvm::createStringError("unsupported module version");
|
|
|
|
versionSeen = true;
|
|
}
|
|
}
|
|
return llvm::createStringError("could not find control block");
|
|
}
|
|
|
|
} // namespace
|
|
|
|
llvm::Expected<bool> IsBuiltFromSwiftInterface(llvm::StringRef data) {
|
|
llvm::BitstreamCursor cursor(data);
|
|
if (llvm::Error Err = checkModuleSignature(cursor, SWIFTMODULE_SIGNATURE))
|
|
return llvm::joinErrors(
|
|
llvm::createStringError("could not check signature"), std::move(Err));
|
|
if (llvm::Error Err = enterTopLevelModuleBlock(cursor, MODULE_BLOCK_ID))
|
|
return llvm::joinErrors(
|
|
llvm::createStringError("could not enter top level block"),
|
|
std::move(Err));
|
|
|
|
llvm::BitstreamEntry topLevelEntry;
|
|
llvm::SmallVector<uint64_t, 32> scratch;
|
|
|
|
while (!cursor.AtEndOfStream()) {
|
|
llvm::Expected<llvm::BitstreamEntry> maybeEntry =
|
|
cursor.advance(llvm::BitstreamCursor::AF_DontPopBlockAtEnd);
|
|
if (!maybeEntry)
|
|
return maybeEntry.takeError();
|
|
|
|
topLevelEntry = maybeEntry.get();
|
|
if (topLevelEntry.Kind != llvm::BitstreamEntry::SubBlock)
|
|
break;
|
|
|
|
if (topLevelEntry.ID == CONTROL_BLOCK_ID) {
|
|
if (llvm::Error Err = cursor.EnterSubBlock(CONTROL_BLOCK_ID))
|
|
return Err;
|
|
return parseControlBlock(cursor, scratch);
|
|
}
|
|
}
|
|
return llvm::createStringError("no control block found");
|
|
}
|