llvm-capstone/lld/MachO/ObjC.cpp
Jez Ng 9065fe5591 [lld-macho] Refactor archive loading
The previous logic was duplicated between symbol-initiated
archive loads versus flag-initiated loads (i.e. `-force_load` and
`-ObjC`). This resulted in code duplication as well as redundant work --
we would create Archive instances twice whenever we had one of those
flags; once in `getArchiveMembers` and again when we constructed the
ArchiveFile.

This was motivated by an upcoming diff where we load archive members
containing ObjC-related symbols before loading those containing
ObjC-related sections, as well as before performing symbol resolution.
Without this refactor, it would be difficult to do that while avoiding
loading the same archive member twice.

Differential Revision: https://reviews.llvm.org/D108780
2021-08-26 18:52:07 -04:00

67 lines
2.0 KiB
C++

//===- ObjC.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 "ObjC.h"
#include "InputFiles.h"
#include "InputSection.h"
#include "OutputSegment.h"
#include "Target.h"
#include "llvm/BinaryFormat/MachO.h"
#include "llvm/Bitcode/BitcodeReader.h"
using namespace llvm;
using namespace llvm::MachO;
using namespace lld;
using namespace lld::macho;
template <class LP> static bool objectHasObjCSection(MemoryBufferRef mb) {
using Section = typename LP::section;
auto *hdr =
reinterpret_cast<const typename LP::mach_header *>(mb.getBufferStart());
if (hdr->magic != LP::magic)
return false;
if (const auto *c =
findCommand<typename LP::segment_command>(hdr, LP::segmentLCType)) {
auto sectionHeaders =
ArrayRef<Section>{reinterpret_cast<const Section *>(c + 1), c->nsects};
for (const Section &sec : sectionHeaders) {
StringRef sectname(sec.sectname,
strnlen(sec.sectname, sizeof(sec.sectname)));
StringRef segname(sec.segname, strnlen(sec.segname, sizeof(sec.segname)));
if ((segname == segment_names::data &&
sectname == section_names::objcCatList) ||
(segname == segment_names::text &&
sectname == section_names::swift)) {
return true;
}
}
}
return false;
}
static bool objectHasObjCSection(MemoryBufferRef mb) {
if (target->wordSize == 8)
return ::objectHasObjCSection<LP64>(mb);
else
return ::objectHasObjCSection<ILP32>(mb);
}
bool macho::hasObjCSection(MemoryBufferRef mb) {
switch (identify_magic(mb.getBuffer())) {
case file_magic::macho_object:
return objectHasObjCSection(mb);
case file_magic::bitcode:
return check(isBitcodeContainingObjCCategory(mb));
default:
return false;
}
}