crashpad/test/mac/dyld.cc
Mark Mentovai bdf9471324 mac: Switch from <AvailabilityMacros.h> to <Availability.h>
The macOS 11.0 SDK, as of Xcode 12b6 12A8189n, has not updated
<AvailabilityMacros.h> with a MAC_OS_X_VERSION_11_0 or
MAC_OS_X_VERSION_10_16 constant. However, the <Availability.h> interface
has been updated to provide both __MAC_11_0 and __MAC_10_16.
<AvailabilityMacros.h>’s MAC_OS_X_VERSION_MAX_ALLOWED, which is supposed
to identify the SDK version, is broken in the 11.0 SDK in that whenever
the deployment target is set to 10.15 or earlier, the SDK will be
mis-identified through this interface as 10.15. When using the
<Availability.h> equivalent, __MAC_OS_X_VERSION_MAX_ALLOWED, the 11.0
SDK is identified as 10.16 (arguably it should be internally versioned
as 11.0, but at least this interface allows it to be detected
unambiguously.) It’s clear that the <AvailabilityMacros.h> interface
provides no meaningful support for the macOS 11.0 SDK at all, but
<Availability.h> does.

<Availability.h> was introduced in the Mac OS X 10.5 SDK, so there is no
relevant SDK version compatibility problem with this interface.

Key differences between these interfaces for the purposes used by
Crashpad:
 - <AvailabilityMacros.h> → <Availability.h>
 - MAC_OS_X_VERSION_MIN_REQUIRED (DT) → __MAC_OS_X_VERSION_MIN_REQUIRED
 - MAC_OS_X_VERSION_MAX_ALLOWED (SDK) → __MAC_OS_X_VERSION_MAX_ALLOWED
 - MAC_OS_X_VERSION_x_y → __MAC_x_y
 - <Availability.h> __MAC_OS_X_VERSION_* SDK/DT macros are only
   available when targeting macOS, while <AvailabilityMacros.h>
   MAC_OS_X_VERSION_* SDK/DT macros are available on all Apple platforms,
   which may be a source of confusion. (<Availability.h> __MAC_* macros
   do remain available on all Apple platforms.)

This change was made mostly mechanically by:

sed -i '' -Ee 's/<AvailabilityMacros.h>/<Availability.h>/g' \
    $(git grep -E -l '<AvailabilityMacros.h>' |
          grep -v AvailabilityMacros.h)

sed -i '' -Ee 's/(MAC_OS_X_VERSION_(MIN_REQUIRED|MAX_ALLOWED))/__\1/g' \
    $(git grep -E -l 'MAC_OS_X_VERSION_(MIN_REQUIRED|MAX_ALLOWED)' |
          grep -v AvailabilityMacros.h)

sed -i '' -Ee 's/(MAC_OS_X_VERSION_(10_[0-9]+))/__MAC_\2/g' \
    $(git grep -E -l 'MAC_OS_X_VERSION_(10_[0-9]+)' |
          grep -v AvailabilityMacros.h)

Bug: crashpad:347
Change-Id: Ibdcd7a6215a82f7060b7b67d98691f88454085fc
Reviewed-on: https://chromium-review.googlesource.com/c/crashpad/crashpad/+/2382421
Reviewed-by: Robert Sesek <rsesek@chromium.org>
Commit-Queue: Mark Mentovai <mark@chromium.org>
2020-08-31 21:11:29 +00:00

100 lines
3.3 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

// Copyright 2017 The Crashpad Authors. All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#include "test/mac/dyld.h"
#include <Availability.h>
#include <dlfcn.h>
#include <mach-o/dyld.h>
#include <mach/mach.h>
#include <stdint.h>
#include "base/logging.h"
#include "snapshot/mac/process_reader_mac.h"
#include "test/scoped_module_handle.h"
#include "util/numeric/safe_assignment.h"
#if __MAC_OS_X_VERSION_MAX_ALLOWED < __MAC_10_13
extern "C" {
// A non-public dyld API, declared in 10.12.4
// dyld-433.5/include/mach-o/dyld_priv.h. The code still exists in 10.13, but
// its symbol is no longer public, so it cant be used there.
const dyld_all_image_infos* _dyld_get_all_image_infos()
__attribute__((weak_import));
} // extern "C"
#endif
namespace crashpad {
namespace test {
const dyld_all_image_infos* DyldGetAllImageInfos() {
#if __MAC_OS_X_VERSION_MAX_ALLOWED < __MAC_10_13
// When building with the pre-10.13 SDK, the weak_import declaration above is
// available and a symbol will be present in the SDK to link against. If the
// old interface is also available at run time (running on pre-10.13), use it.
if (_dyld_get_all_image_infos) {
return _dyld_get_all_image_infos();
}
#elif __MAC_OS_X_VERSION_MIN_REQUIRED < __MAC_10_13
// When building with the 10.13 SDK or later, but able to run on pre-10.13,
// look for _dyld_get_all_image_infos in the same module that provides
// _dyld_image_count. Theres no symbol in the SDK to link against, so this is
// a little more involved than the pre-10.13 SDK case above.
Dl_info dli;
if (!dladdr(reinterpret_cast<void*>(_dyld_image_count), &dli)) {
LOG(WARNING) << "dladdr: failed";
} else {
ScopedModuleHandle module(
dlopen(dli.dli_fname, RTLD_LAZY | RTLD_LOCAL | RTLD_NOLOAD));
if (!module.valid()) {
LOG(WARNING) << "dlopen: " << dlerror();
} else {
using DyldGetAllImageInfosType = const dyld_all_image_infos*(*)();
const auto _dyld_get_all_image_infos =
module.LookUpSymbol<DyldGetAllImageInfosType>(
"_dyld_get_all_image_infos");
if (_dyld_get_all_image_infos) {
return _dyld_get_all_image_infos();
}
}
}
#endif
// On 10.13 and later, do it the hard way.
ProcessReaderMac process_reader;
if (!process_reader.Initialize(mach_task_self())) {
return nullptr;
}
mach_vm_address_t all_image_info_addr_m =
process_reader.DyldAllImageInfo(nullptr);
if (!all_image_info_addr_m) {
return nullptr;
}
uintptr_t all_image_info_addr_u;
if (!AssignIfInRange(&all_image_info_addr_u, all_image_info_addr_m)) {
LOG(ERROR) << "all_image_info_addr_m " << all_image_info_addr_m
<< " out of range";
return nullptr;
}
return reinterpret_cast<const dyld_all_image_infos*>(all_image_info_addr_u);
}
} // namespace test
} // namespace crashpad