add sentry-native files missed in earlier commit

This commit is contained in:
Marek Roszko 2023-12-18 22:10:23 -05:00
parent 5341af1a55
commit d6d25c030e
40 changed files with 2891 additions and 0 deletions

View File

@ -0,0 +1,16 @@
/*
* Copyright (c) 2000-2007 Apple Inc. All rights reserved.
*/
#ifndef _BSD_ARM__TYPES_H_
#define _BSD_ARM__TYPES_H_
#if defined (__arm__) || defined (__arm64__) || defined (__aarch64__)
typedef long __darwin_intptr_t;
typedef unsigned int __darwin_natural_t;
#endif /* defined (__arm__) || defined (__arm64__) || defined (__aarch64__) */
#endif /* _BSD_ARM__TYPES_H_ */

View File

@ -0,0 +1,74 @@
/*
* Copyright (c) 2000-2007 Apple Inc. All rights reserved.
*
* @APPLE_OSREFERENCE_LICENSE_HEADER_START@
*
* This file contains Original Code and/or Modifications of Original Code
* as defined in and that are subject to the Apple Public Source License
* Version 2.0 (the 'License'). You may not use this file except in
* compliance with the License. The rights granted to you under the License
* may not be used to create, or enable the creation or redistribution of,
* unlawful or unlicensed copies of an Apple operating system, or to
* circumvent, violate, or enable the circumvention or violation of, any
* terms of an Apple operating system software license agreement.
*
* Please obtain a copy of the License at
* http://www.opensource.apple.com/apsl/ and read it before using this file.
*
* The Original Code and all software distributed under the License are
* distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
* EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
* INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
* Please see the License for the specific language governing rights and
* limitations under the License.
*
* @APPLE_OSREFERENCE_LICENSE_HEADER_END@
*/
/*
* @OSF_COPYRIGHT@
*/
/*
* Mach Operating System
* Copyright (c) 1991,1990,1989 Carnegie Mellon University
* All Rights Reserved.
*
* Permission to use, copy, modify and distribute this software and its
* documentation is hereby granted, provided that both the copyright
* notice and this permission notice appear in all copies of the
* software, derivative works or modified versions, and any portions
* thereof, and that both notices appear in supporting documentation.
*
* CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
* CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
* ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
*
* Carnegie Mellon requests users of this software to return to
*
* Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU
* School of Computer Science
* Carnegie Mellon University
* Pittsburgh PA 15213-3890
*
* any improvements or extensions that they make and grant Carnegie Mellon
* the rights to redistribute these changes.
*/
/*
*/
/*
* File: boolean.h
*
* Boolean type, for ARM.
*/
#ifndef _MACH_ARM_BOOLEAN_H_
#define _MACH_ARM_BOOLEAN_H_
#if defined (__arm__) || defined (__arm64__) || defined (__aarch64__)
typedef int boolean_t;
#endif /* defined (__arm__) || defined (__arm64__) */
#endif /* _MACH_ARM_BOOLEAN_H_ */

View File

@ -0,0 +1,159 @@
/*
* Copyright (c) 2000-2007 Apple Inc. All rights reserved.
*
* @APPLE_OSREFERENCE_LICENSE_HEADER_START@
*
* This file contains Original Code and/or Modifications of Original Code
* as defined in and that are subject to the Apple Public Source License
* Version 2.0 (the 'License'). You may not use this file except in
* compliance with the License. The rights granted to you under the License
* may not be used to create, or enable the creation or redistribution of,
* unlawful or unlicensed copies of an Apple operating system, or to
* circumvent, violate, or enable the circumvention or violation of, any
* terms of an Apple operating system software license agreement.
*
* Please obtain a copy of the License at
* http://www.opensource.apple.com/apsl/ and read it before using this file.
*
* The Original Code and all software distributed under the License are
* distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
* EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
* INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
* Please see the License for the specific language governing rights and
* limitations under the License.
*
* @APPLE_OSREFERENCE_LICENSE_HEADER_END@
*/
/*
* @OSF_COPYRIGHT@
*/
/*
* Mach Operating System
* Copyright (c) 1991,1990,1989,1988 Carnegie Mellon University
* All Rights Reserved.
*
* Permission to use, copy, modify and distribute this software and its
* documentation is hereby granted, provided that both the copyright
* notice and this permission notice appear in all copies of the
* software, derivative works or modified versions, and any portions
* thereof, and that both notices appear in supporting documentation.
*
* CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
* CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
* ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
*
* Carnegie Mellon requests users of this software to return to
*
* Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU
* School of Computer Science
* Carnegie Mellon University
* Pittsburgh PA 15213-3890
*
* any improvements or extensions that they make and grant Carnegie Mellon
* the rights to redistribute these changes.
*/
/*
*/
/*
* File: vm_types.h
* Author: Avadis Tevanian, Jr.
* Date: 1985
*
* Header file for VM data types. ARM version.
*/
#ifndef _MACH_ARM_VM_TYPES_H_
#define _MACH_ARM_VM_TYPES_H_
#if defined (__arm__) || defined (__arm64__) || defined (__aarch64__)
#ifndef ASSEMBLER
#include <arm/_types.h>
#include <stdint.h>
#include <sys/cdefs.h>
/*
* natural_t and integer_t are Mach's legacy types for machine-
* independent integer types (unsigned, and signed, respectively).
* Their original purpose was to define other types in a machine/
* compiler independent way.
*
* They also had an implicit "same size as pointer" characteristic
* to them (i.e. Mach's traditional types are very ILP32 or ILP64
* centric). We will likely support x86 ABIs that do not follow
* either ofthese models (specifically LP64). Therefore, we had to
* make a choice between making these types scale with pointers or stay
* tied to integers. Because their use is predominantly tied to
* to the size of an integer, we are keeping that association and
* breaking free from pointer size guarantees.
*
* New use of these types is discouraged.
*/
typedef __darwin_natural_t natural_t;
typedef int integer_t;
/*
* A vm_offset_t is a type-neutral pointer,
* e.g. an offset into a virtual memory space.
*/
#ifdef __LP64__
typedef uintptr_t vm_offset_t ;
typedef uintptr_t vm_size_t;
typedef uint64_t mach_vm_address_t ;
typedef uint64_t mach_vm_offset_t ;
typedef uint64_t mach_vm_size_t;
typedef uint64_t vm_map_offset_t ;
typedef uint64_t vm_map_address_t ;
typedef uint64_t vm_map_size_t;
#else
typedef natural_t vm_offset_t ;
/*
* A vm_size_t is the proper type for e.g.
* expressing the difference between two
* vm_offset_t entities.
*/
typedef natural_t vm_size_t;
/*
* This new type is independent of a particular vm map's
* implementation size - and represents appropriate types
* for all possible maps. This is used for interfaces
* where the size of the map is not known - or we don't
* want to have to distinguish.
*/
typedef uint64_t mach_vm_address_t ;
typedef uint64_t mach_vm_offset_t ;
typedef uint64_t mach_vm_size_t;
typedef uint32_t vm_map_offset_t ;
typedef uint32_t vm_map_address_t ;
typedef uint32_t vm_map_size_t;
#endif /* __LP64__ */
typedef uint32_t vm32_offset_t;
typedef uint32_t vm32_address_t;
typedef uint32_t vm32_size_t;
typedef vm_offset_t mach_port_context_t;
#ifdef MACH_KERNEL_PRIVATE
typedef vm32_offset_t mach_port_context32_t;
typedef mach_vm_offset_t mach_port_context64_t;
#endif
#endif /* ASSEMBLER */
/*
* If composing messages by hand (please do not)
*/
#define MACH_MSG_TYPE_INTEGER_T MACH_MSG_TYPE_INTEGER_32
#endif /* defined (__arm__) || defined (__arm64__) || defined (__aarch64__) */
#endif /* _MACH_ARM_VM_TYPES_H_ */

View File

@ -0,0 +1 @@
* @getsentry/owners-native

View File

@ -0,0 +1,350 @@
#!/usr/bin/env vpython3
# Copyright 2023 The Chromium Authors
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
#
# Generates a single BUILD.gn file with build targets generated using the
# manifest files in the SDK.
import json
import logging
import os
import shutil
import sys
DIR_SRC_ROOT = os.path.abspath(
os.path.join(os.path.dirname(__file__), os.pardir, os.pardir))
def GetHostOS():
"""Get host operating system."""
host_platform = sys.platform
if host_platform.startswith('linux'):
return 'linux'
if host_platform.startswith('darwin'):
return 'mac'
raise Exception('Unsupported host platform: %s' % host_platform)
# Inserted at the top of the generated BUILD.gn file.
_GENERATED_PREAMBLE = """# DO NOT EDIT! This file was generated by
# //build/fuchsia/gen_build_def.py.
# Any changes made to this file will be discarded.
import("//third_party/fuchsia/sdk/{host_os}-amd64/build/fidl_library.gni")
import("//third_party/fuchsia/sdk/{host_os}-amd64/build/fuchsia_sdk_pkg.gni")
""".format(host_os=GetHostOS())
SDK_ROOT = os.path.join(DIR_SRC_ROOT, 'third_party', 'fuchsia', 'sdk',
f'{GetHostOS()}-amd64')
def ReformatTargetName(dep_name):
""""Substitutes characters in |dep_name| which are not valid in GN target
names (e.g. dots become hyphens)."""
return dep_name
def FormatGNTarget(fields):
"""Returns a GN target definition as a string.
|fields|: The GN fields to include in the target body.
'target_name' and 'type' are mandatory."""
output = '%s("%s") {\n' % (fields['type'], fields['target_name'])
del fields['target_name']
del fields['type']
# Ensure that fields with no ordering requirement are sorted.
for field in ['sources', 'public_deps']:
if field in fields:
fields[field].sort()
for key, val in fields.items():
if isinstance(val, str):
val_serialized = '\"%s\"' % val
elif isinstance(val, list):
# Serialize a list of strings in the prettiest possible manner.
if len(val) == 0:
val_serialized = '[]'
elif len(val) == 1:
val_serialized = '[ \"%s\" ]' % val[0]
else:
val_serialized = '[\n ' + ',\n '.join(['\"%s\"' % x
for x in val]) + '\n ]'
else:
raise Exception('Could not serialize %r' % val)
output += ' %s = %s\n' % (key, val_serialized)
output += '}'
return output
def MetaRootRelativePaths(sdk_relative_paths, meta_root):
return [os.path.relpath(path, meta_root) for path in sdk_relative_paths]
def ConvertCommonFields(json):
"""Extracts fields from JSON manifest data which are used across all
target types. Note that FIDL packages do their own processing."""
meta_root = json['root']
converted = {'target_name': ReformatTargetName(json['name'])}
if 'deps' in json:
converted['public_deps'] = MetaRootRelativePaths(json['deps'],
os.path.dirname(meta_root))
# FIDL bindings dependencies are relative to the "fidl" sub-directory.
if 'fidl_binding_deps' in json:
for entry in json['fidl_binding_deps']:
converted['public_deps'] += MetaRootRelativePaths([
'fidl/' + dep + ':' + os.path.basename(dep) + '_' +
entry['binding_type'] for dep in entry['deps']
], meta_root)
return converted
def ConvertFidlLibrary(json):
"""Converts a fidl_library manifest entry to a GN target.
Arguments:
json: The parsed manifest JSON.
Returns:
The GN target definition, represented as a string."""
meta_root = json['root']
converted = ConvertCommonFields(json)
converted['type'] = 'fidl_library'
converted['sources'] = MetaRootRelativePaths(json['sources'], meta_root)
converted['library_name'] = json['name']
return converted
def ConvertCcPrebuiltLibrary(json):
"""Converts a cc_prebuilt_library manifest entry to a GN target.
Arguments:
json: The parsed manifest JSON.
Returns:
The GN target definition, represented as a string."""
meta_root = json['root']
converted = ConvertCommonFields(json)
converted['type'] = 'fuchsia_sdk_pkg'
converted['sources'] = MetaRootRelativePaths(json['headers'], meta_root)
converted['include_dirs'] = MetaRootRelativePaths([json['include_dir']],
meta_root)
if json['format'] == 'shared':
converted['shared_libs'] = [json['name']]
else:
converted['static_libs'] = [json['name']]
return converted
def ConvertCcSourceLibrary(json):
"""Converts a cc_source_library manifest entry to a GN target.
Arguments:
json: The parsed manifest JSON.
Returns:
The GN target definition, represented as a string."""
meta_root = json['root']
converted = ConvertCommonFields(json)
converted['type'] = 'fuchsia_sdk_pkg'
# Headers and source file paths can be scattered across "sources", "headers",
# and "files". Merge them together into one source list.
converted['sources'] = MetaRootRelativePaths(json['sources'], meta_root)
if 'headers' in json:
converted['sources'] += MetaRootRelativePaths(json['headers'], meta_root)
if 'files' in json:
converted['sources'] += MetaRootRelativePaths(json['files'], meta_root)
converted['sources'] = list(set(converted['sources']))
converted['include_dirs'] = MetaRootRelativePaths([json['include_dir']],
meta_root)
return converted
def ConvertLoadableModule(json):
"""Converts a loadable module manifest entry to GN targets.
Arguments:
json: The parsed manifest JSON.
Returns:
A list of GN target definitions."""
name = json['name']
if name != 'vulkan_layers':
raise RuntimeError('Unsupported loadable_module: %s' % name)
# Copy resources and binaries
resources = json['resources']
binaries = json['binaries']
def _filename_no_ext(name):
return os.path.splitext(os.path.basename(name))[0]
# Pair each json resource with its corresponding binary. Each such pair
# is a "layer". We only need to check one arch because each arch has the
# same list of binaries.
arch = next(iter(binaries))
binary_names = binaries[arch]
local_pkg = json['root']
vulkan_targets = []
for res in resources:
layer_name = _filename_no_ext(res)
# Filter binaries for a matching name.
filtered = [n for n in binary_names if _filename_no_ext(n) == layer_name]
if not filtered:
# If the binary could not be found then do not generate a
# target for this layer. The missing targets will cause a
# mismatch with the "golden" outputs.
continue
# Replace hardcoded arch in the found binary filename.
binary = filtered[0].replace('/' + arch + '/', "/${target_cpu}/")
target = {}
target['name'] = layer_name
target['config'] = os.path.relpath(res, start=local_pkg)
target['binary'] = os.path.relpath(binary, start=local_pkg)
vulkan_targets.append(target)
converted = []
all_target = {}
all_target['target_name'] = 'all'
all_target['type'] = 'group'
all_target['data_deps'] = []
for target in vulkan_targets:
config_target = {}
config_target['target_name'] = target['name'] + '_config'
config_target['type'] = 'copy'
config_target['sources'] = [target['config']]
config_target['outputs'] = ['${root_gen_dir}/' + target['config']]
converted.append(config_target)
lib_target = {}
lib_target['target_name'] = target['name'] + '_lib'
lib_target['type'] = 'copy'
lib_target['sources'] = [target['binary']]
lib_target['outputs'] = ['${root_out_dir}/lib/{{source_file_part}}']
converted.append(lib_target)
group_target = {}
group_target['target_name'] = target['name']
group_target['type'] = 'group'
group_target['data_deps'] = [
':' + target['name'] + '_config', ':' + target['name'] + '_lib'
]
converted.append(group_target)
all_target['data_deps'].append(':' + target['name'])
converted.append(all_target)
return converted
def ConvertNoOp(json):
"""Null implementation of a conversion function. No output is generated."""
return None
"""Maps manifest types to conversion functions."""
_CONVERSION_FUNCTION_MAP = {
'fidl_library': ConvertFidlLibrary,
'cc_source_library': ConvertCcSourceLibrary,
'cc_prebuilt_library': ConvertCcPrebuiltLibrary,
'loadable_module': ConvertLoadableModule,
# No need to build targets for these types yet.
'companion_host_tool': ConvertNoOp,
'component_manifest': ConvertNoOp,
'config': ConvertNoOp,
'dart_library': ConvertNoOp,
'data': ConvertNoOp,
'device_profile': ConvertNoOp,
'documentation': ConvertNoOp,
'ffx_tool': ConvertNoOp,
'host_tool': ConvertNoOp,
'image': ConvertNoOp,
'sysroot': ConvertNoOp,
}
def ConvertMeta(meta_path):
parsed = json.load(open(meta_path))
if 'type' not in parsed:
return
convert_function = _CONVERSION_FUNCTION_MAP.get(parsed['type'])
if convert_function is None:
logging.warning('Unexpected SDK artifact type %s in %s.' %
(parsed['type'], meta_path))
return
converted = convert_function(parsed)
if not converted:
return
output_path = os.path.join(os.path.dirname(meta_path), 'BUILD.gn')
if os.path.exists(output_path):
os.unlink(output_path)
with open(output_path, 'w') as buildfile:
buildfile.write(_GENERATED_PREAMBLE)
# Loadable modules have multiple targets
if convert_function != ConvertLoadableModule:
buildfile.write(FormatGNTarget(converted) + '\n\n')
else:
for target in converted:
buildfile.write(FormatGNTarget(target) + '\n\n')
def ProcessSdkManifest():
toplevel_meta = json.load(
open(os.path.join(SDK_ROOT, 'meta', 'manifest.json')))
for part in toplevel_meta['parts']:
meta_path = os.path.join(SDK_ROOT, part['meta'])
ConvertMeta(meta_path)
def main():
# Exit if there's no Fuchsia support for this platform.
try:
GetHostOS()
except:
logging.warning('Fuchsia SDK is not supported on this platform.')
return 0
# TODO(crbug/1432399): Remove this when links to these files inside the sdk
# directory have been redirected.
shutil.copytree(os.path.join(DIR_SRC_ROOT, 'third_party', 'fuchsia-gn-sdk',
'src'),
os.path.join(SDK_ROOT, 'build'),
dirs_exist_ok=True)
ProcessSdkManifest()
if __name__ == '__main__':
sys.exit(main())

View File

@ -0,0 +1,95 @@
// Copyright 2023 The Crashpad Authors
//
// 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 <string.h>
#include "base/files/file_path.h"
#include "base/logging.h"
#include "client/crashpad_client.h"
#include "util/misc/paths.h"
#include <Windows.h>
// We set up a program that crashes with a heap corruption exception.
// STATUS_HEAP_CORRUPTION (0xC0000374 3221226356).
namespace crashpad {
namespace {
void HeapCorruptionCrash() {
__try {
HANDLE heap = ::HeapCreate(0, 0, 0);
CHECK(heap);
CHECK(HeapSetInformation(
heap, HeapEnableTerminationOnCorruption, nullptr, 0));
void* addr = ::HeapAlloc(heap, 0, 0x1000);
CHECK(addr);
// Corrupt heap header.
char* addr_mutable = reinterpret_cast<char*>(addr);
memset(addr_mutable - sizeof(addr), 0xCC, sizeof(addr));
HeapFree(heap, 0, addr);
HeapDestroy(heap);
} __except (EXCEPTION_EXECUTE_HANDLER) {
// Heap corruption exception should never be caught.
CHECK(false);
}
// Should never reach here.
abort();
}
int CrashyMain(int argc, wchar_t* argv[]) {
static CrashpadClient* client = new crashpad::CrashpadClient();
if (argc == 2) {
// We call this from end_to_end_test.py.
if (!client->SetHandlerIPCPipe(argv[1])) {
LOG(ERROR) << "SetHandler";
return EXIT_FAILURE;
}
} else if (argc == 3) {
// This is helpful for debugging.
if (!client->StartHandler(base::FilePath(argv[1]),
base::FilePath(argv[2]),
base::FilePath(),
std::string(),
std::map<std::string, std::string>(),
std::vector<std::string>(),
false,
true)) {
LOG(ERROR) << "StartHandler";
return EXIT_FAILURE;
}
// Got to have a handler & registration.
if (!client->WaitForHandlerStart(10000)) {
LOG(ERROR) << "Handler failed to start";
return EXIT_FAILURE;
}
} else {
fprintf(stderr, "Usage: %ls <server_pipe_name>\n", argv[0]);
fprintf(stderr, " %ls <handler_path> <database_path>\n", argv[0]);
return EXIT_FAILURE;
}
HeapCorruptionCrash();
LOG(ERROR) << "Invalid type or exception failed.";
return EXIT_FAILURE;
}
} // namespace
} // namespace crashpad
int wmain(int argc, wchar_t* argv[]) {
return crashpad::CrashyMain(argc, argv);
}

View File

@ -0,0 +1,84 @@
/* Copyright 2022 Google LLC
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following disclaimer
* in the documentation and/or other materials provided with the
* distribution.
* * Neither the name of Google LLC nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "test_skel.h"
int main(int argc, char *argv[]) {
// We need an invalid timer value. The assert()'s below should
// be static asserts but it is not available in older C versions.
#define kInvalidTimer 9999
assert(kInvalidTimer != ITIMER_REAL);
assert(kInvalidTimer != ITIMER_VIRTUAL);
assert(kInvalidTimer != ITIMER_PROF);
// This should fail with EINVAL.
struct kernel_itimerval curr_itimer;
assert(sys_getitimer(kInvalidTimer, &curr_itimer) == -1);
assert(errno == EINVAL);
// Create a read-only page.
size_t page_size = getpagesize();
void* read_only_page = sys_mmap(NULL, page_size, PROT_READ,
MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
assert(read_only_page != MAP_FAILED);
// This should fail with EFAULT.
assert(sys_getitimer(ITIMER_REAL,
(struct kernel_itimerval*) read_only_page) == -1);
assert(errno == EFAULT);
// This should complete without an error.
assert(sys_getitimer(ITIMER_REAL, &curr_itimer) == 0);
// Set up a real time timer with very long interval and value so that
// we do not need to handle SIGALARM in test.
struct kernel_itimerval new_itimer;
const time_t kIntervalSec = 60 * 60 * 24 * 365; // One year.
const long kIntervalUSec = 123;
new_itimer.it_interval.tv_sec = kIntervalSec;
new_itimer.it_interval.tv_usec = kIntervalUSec;
new_itimer.it_value = new_itimer.it_interval;
assert(sys_setitimer(ITIMER_REAL, &new_itimer, NULL) == 0);
assert(sys_getitimer(ITIMER_REAL, &curr_itimer) == 0);
assert(kernel_timeval_eq(&curr_itimer.it_interval, &new_itimer.it_interval));
// Disable timer.
struct kernel_itimerval empty_itimer;
empty_itimer.it_interval.tv_sec = 0;
empty_itimer.it_interval.tv_usec = 0;
empty_itimer.it_value = empty_itimer.it_interval;
assert(sys_setitimer(ITIMER_REAL, &empty_itimer, NULL) == 0);
// We should read back an empty itimer.
assert(sys_getitimer(ITIMER_REAL, &curr_itimer) == 0);
assert(kernel_itimerval_eq(&curr_itimer, &empty_itimer));
return 0;
}

View File

@ -0,0 +1,90 @@
/* Copyright 2022 Google LLC
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following disclaimer
* in the documentation and/or other materials provided with the
* distribution.
* * Neither the name of Google LLC nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "test_skel.h"
int main(int argc, char *argv[]) {
// We need an invalid timer value. The assert()'s below should
// be static asserts but it is not avalible in older C versions.
#define kInvalidTimer 9999
assert(kInvalidTimer != ITIMER_REAL);
assert(kInvalidTimer != ITIMER_VIRTUAL);
assert(kInvalidTimer != ITIMER_PROF);
// Invalid timer returns EINVAL.
assert(sys_setitimer(kInvalidTimer, NULL, NULL) == -1);
assert(errno == EINVAL);
const int kSignal = SIGALRM;
const size_t kSigsetSize = sizeof(struct kernel_sigset_t);
// Block SIGALRM.
struct kernel_sigset_t sigalarm_only;
struct kernel_sigset_t old_sigset;
assert(sys_sigemptyset(&sigalarm_only) == 0);
assert(sys_sigaddset(&sigalarm_only, kSignal) == 0);
assert(sys_rt_sigprocmask(SIG_BLOCK, &sigalarm_only, &old_sigset,
kSigsetSize) == 0);
// Set up a real time timer.
struct kernel_itimerval new_itimer = {};
const long kIntervalUSec = 123;
new_itimer.it_interval.tv_sec = 0;
new_itimer.it_interval.tv_usec = kIntervalUSec;
new_itimer.it_value = new_itimer.it_interval;
assert(sys_setitimer(ITIMER_REAL, &new_itimer, NULL) == 0);
// Wait for alarm.
struct timespec timeout;
const unsigned long kNanoSecsPerSec = 1000000000;
const unsigned long kNanoSecsPerMicroSec = 1000;
// Use a timeout 3 times of the timer interval.
unsigned long duration_ns = kIntervalUSec * kNanoSecsPerMicroSec * 3;
timeout.tv_sec = duration_ns / kNanoSecsPerSec ;
timeout.tv_nsec = duration_ns % kNanoSecsPerSec;
int sig;
do {
sig = sys_sigtimedwait(&sigalarm_only, NULL, &timeout);
} while (sig == -1 && errno == EINTR);
assert(sig == kSignal);
// Disable timer, check saving of old timer value.
struct kernel_itimerval empty_itimer = {};
struct kernel_itimerval old_itimer;
empty_itimer.it_interval.tv_sec = 0;
empty_itimer.it_interval.tv_usec = 0;
empty_itimer.it_value = empty_itimer.it_interval;
assert(sys_setitimer(ITIMER_REAL, &empty_itimer, &old_itimer) == 0);
assert(kernel_timeval_eq(&old_itimer.it_interval, &new_itimer.it_interval));
return 0;
}

View File

@ -0,0 +1,140 @@
// Copyright 2021 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef BASE_APPLE_BRIDGING_H_
#define BASE_APPLE_BRIDGING_H_
#include <CoreText/CoreText.h>
#import <Foundation/Foundation.h>
#include "base/apple/scoped_cftyperef.h"
#include "base/check.h"
#include "build/build_config.h"
#if BUILDFLAG(IS_IOS)
#import <UIKit/UIKit.h>
#endif
#if BUILDFLAG(IS_MAC)
#import <AppKit/AppKit.h>
#endif
// These functions convert pointers of bridged CFTypes to NSTypes and
// vice-versa. They come in two flavors: those that transfer ownership
// (`OwnershipCast`) and those that just convert the pointer (`PtrCast`).
//
// Examples:
//
// Ownership transference (as in `CFBridgingRetain`/`Release`):
// CFStringRef cf_string = CFStringCreateWithCString(...);
// NSString* ns_string = CFToNSOwnershipCast(cf_string);
// // At this point, `cf_string` does not need releasing.
//
// NSString* ns_string = [[NSString alloc] initWithString:...];
// CFStringRef cf_string = NSToCFOwnershipCast(ns_string);
// // At this point, `cf_string` must be released.
//
// Pointer conversion (as in `__bridge`):
// // `cf_data` is some `CFDataRef` from somewhere.
// NSImage* ns_image = [[NSImage alloc] initWithData:CFToNSPtrCast(cf_data)];
//
// // `ns_data` is some `NSData *` from somewhere.
// SecKeyRef sec_key = SecKeyCreateFromData(..., NSToCFPtrCast(ns_data), ...);
//
// The reason to use these functions (rather than using `__bridge` and
// `CFBridgingRetain`/`Release`) is because they are type-safe. The OS-provided
// bridging calls do not type check, while these calls do the appropriate type
// checking via the magic of macros.
//
// Implementation note: Why not templates? Type checking in Core Foundation
// involves functions named in a specific pattern, and only macro token pasting
// works for this purpose.
#define CF_TO_NS_CAST_IMPL(TypeCF, TypeNS) \
namespace base::apple { \
inline TypeNS* _Nullable CFToNSOwnershipCast( \
TypeCF##Ref CF_CONSUMED _Nullable cf_val) { \
DCHECK(!cf_val || TypeCF##GetTypeID() == CFGetTypeID(cf_val)); \
return (__bridge_transfer TypeNS*)cf_val; \
} \
inline CF_RETURNS_RETAINED TypeCF##Ref _Nullable NSToCFOwnershipCast( \
TypeNS* _Nullable ns_val) { \
TypeCF##Ref cf_val = (__bridge_retained TypeCF##Ref)ns_val; \
DCHECK(!cf_val || TypeCF##GetTypeID() == CFGetTypeID(cf_val)); \
return cf_val; \
} \
inline TypeNS* _Nullable CFToNSPtrCast(TypeCF##Ref _Nullable cf_val) { \
DCHECK(!cf_val || TypeCF##GetTypeID() == CFGetTypeID(cf_val)); \
return (__bridge TypeNS*)cf_val; \
} \
inline TypeCF##Ref _Nullable NSToCFPtrCast(TypeNS* _Nullable ns_val) { \
TypeCF##Ref cf_val = (__bridge TypeCF##Ref)ns_val; \
DCHECK(!cf_val || TypeCF##GetTypeID() == CFGetTypeID(cf_val)); \
return cf_val; \
} \
}
#define CF_TO_NS_MUTABLE_CAST_IMPL(name) \
CF_TO_NS_CAST_IMPL(CF##name, NS##name) \
namespace base::apple { \
inline NSMutable##name* _Nullable CFToNSOwnershipCast( \
CFMutable##name##Ref CF_CONSUMED _Nullable cf_val) { \
DCHECK(!cf_val || CF##name##GetTypeID() == CFGetTypeID(cf_val)); \
return (__bridge_transfer NSMutable##name*)cf_val; \
} \
inline CF_RETURNS_RETAINED \
CFMutable##name##Ref _Nullable NSToCFOwnershipCast( \
NSMutable##name* _Nullable ns_val) { \
CFMutable##name##Ref cf_val = \
(__bridge_retained CFMutable##name##Ref)ns_val; \
DCHECK(!cf_val || CF##name##GetTypeID() == CFGetTypeID(cf_val)); \
return cf_val; \
} \
inline NSMutable##name* _Nullable CFToNSPtrCast( \
CFMutable##name##Ref _Nullable cf_val) { \
DCHECK(!cf_val || CF##name##GetTypeID() == CFGetTypeID(cf_val)); \
return (__bridge NSMutable##name*)cf_val; \
} \
inline CFMutable##name##Ref _Nullable NSToCFPtrCast( \
NSMutable##name* _Nullable ns_val) { \
CFMutable##name##Ref cf_val = (__bridge CFMutable##name##Ref)ns_val; \
DCHECK(!cf_val || CF##name##GetTypeID() == CFGetTypeID(cf_val)); \
return cf_val; \
} \
}
// List of toll-free bridged types taken from:
// https://web.archive.org/web/20111124025525/http://www.cocoadev.com/index.pl?TollFreeBridged
// https://developer.apple.com/library/archive/documentation/CoreFoundation/Conceptual/CFDesignConcepts/Articles/tollFreeBridgedTypes.html#//apple_ref/doc/uid/TP40010677-SW4
// Foundation
CF_TO_NS_MUTABLE_CAST_IMPL(Array)
CF_TO_NS_MUTABLE_CAST_IMPL(AttributedString)
CF_TO_NS_CAST_IMPL(CFCalendar, NSCalendar)
CF_TO_NS_MUTABLE_CAST_IMPL(CharacterSet)
CF_TO_NS_MUTABLE_CAST_IMPL(Data)
CF_TO_NS_CAST_IMPL(CFDate, NSDate)
CF_TO_NS_MUTABLE_CAST_IMPL(Dictionary)
CF_TO_NS_CAST_IMPL(CFError, NSError)
CF_TO_NS_CAST_IMPL(CFLocale, NSLocale)
CF_TO_NS_CAST_IMPL(CFNumber, NSNumber)
CF_TO_NS_CAST_IMPL(CFRunLoopTimer, NSTimer)
CF_TO_NS_CAST_IMPL(CFTimeZone, NSTimeZone)
CF_TO_NS_MUTABLE_CAST_IMPL(Set)
CF_TO_NS_CAST_IMPL(CFReadStream, NSInputStream)
CF_TO_NS_CAST_IMPL(CFWriteStream, NSOutputStream)
CF_TO_NS_MUTABLE_CAST_IMPL(String)
CF_TO_NS_CAST_IMPL(CFURL, NSURL)
// AppKit / UIKit
#if BUILDFLAG(IS_IOS)
CF_TO_NS_CAST_IMPL(CTFont, UIFont)
#else
CF_TO_NS_CAST_IMPL(CTFont, NSFont)
#endif // BUILDFLAG(IS_IOS)
#undef CF_TO_NS_CAST_IMPL
#undef CF_TO_NS_MUTABLE_CAST_IMPL
#endif // BASE_APPLE_BRIDGING_H_

View File

@ -0,0 +1,124 @@
// Copyright 2008 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef MINI_CHROMIUM_BASE_APPLE_FOUNDATION_UTIL_H_
#define MINI_CHROMIUM_BASE_APPLE_FOUNDATION_UTIL_H_
#include "base/logging.h"
#include "build/build_config.h"
#if BUILDFLAG(IS_IOS)
#include <CoreText/CoreText.h>
#else
#include <ApplicationServices/ApplicationServices.h>
#endif
#if defined(__OBJC__)
#import <Foundation/Foundation.h>
#else // defined(__OBJC__)
#include <CoreFoundation/CoreFoundation.h>
#endif // defined(__OBJC__)
namespace base {
namespace apple {
// CFCast<>() and CFCastStrict<>() cast a basic CFTypeRef to a more
// specific CoreFoundation type. The compatibility of the passed
// object is found by comparing its opaque type against the
// requested type identifier. If the supplied object is not
// compatible with the requested return type, CFCast<>() returns
// NULL and CFCastStrict<>() will DCHECK. Providing a NULL pointer
// to either variant results in NULL being returned without
// triggering any DCHECK.
//
// Example usage:
// CFNumberRef some_number = base::apple::CFCast<CFNumberRef>(
// CFArrayGetValueAtIndex(array, index));
//
// CFTypeRef hello = CFSTR("hello world");
// CFStringRef some_string = base::apple::CFCastStrict<CFStringRef>(hello);
template <typename T>
T CFCast(const CFTypeRef& cf_val);
template <typename T>
T CFCastStrict(const CFTypeRef& cf_val);
#define CF_CAST_DECL(TypeCF) \
template <> \
TypeCF##Ref CFCast<TypeCF##Ref>(const CFTypeRef& cf_val); \
\
template <> \
TypeCF##Ref CFCastStrict<TypeCF##Ref>(const CFTypeRef& cf_val)
CF_CAST_DECL(CFArray);
CF_CAST_DECL(CFBag);
CF_CAST_DECL(CFBoolean);
CF_CAST_DECL(CFData);
CF_CAST_DECL(CFDate);
CF_CAST_DECL(CFDictionary);
CF_CAST_DECL(CFNull);
CF_CAST_DECL(CFNumber);
CF_CAST_DECL(CFSet);
CF_CAST_DECL(CFString);
CF_CAST_DECL(CFURL);
CF_CAST_DECL(CFUUID);
CF_CAST_DECL(CGColor);
CF_CAST_DECL(CTFont);
CF_CAST_DECL(CTRun);
#if !BUILDFLAG(IS_IOS)
CF_CAST_DECL(SecACL);
CF_CAST_DECL(SecTrustedApplication);
#endif
#undef CF_CAST_DECL
#if defined(__OBJC__)
// ObjCCast<>() and ObjCCastStrict<>() cast a basic id to a more
// specific (NSObject-derived) type. The compatibility of the passed
// object is found by checking if it's a kind of the requested type
// identifier. If the supplied object is not compatible with the
// requested return type, ObjCCast<>() returns nil and
// ObjCCastStrict<>() will DCHECK. Providing a nil pointer to either
// variant results in nil being returned without triggering any DCHECK.
//
// The strict variant is useful when retrieving a value from a
// collection which only has values of a specific type, e.g. an
// NSArray of NSStrings. The non-strict variant is useful when
// retrieving values from data that you can't fully control. For
// example, a plist read from disk may be beyond your exclusive
// control, so you'd only want to check that the values you retrieve
// from it are of the expected types, but not crash if they're not.
//
// Example usage:
// NSString* version = base::apple::ObjCCast<NSString>(
// [bundle objectForInfoDictionaryKey:@"CFBundleShortVersionString"]);
//
// NSString* str = base::apple::ObjCCastStrict<NSString>(
// [ns_arr_of_ns_strs objectAtIndex:0]);
template <typename T>
T* ObjCCast(id objc_val) {
if ([objc_val isKindOfClass:[T class]]) {
return reinterpret_cast<T*>(objc_val);
}
return nil;
}
template <typename T>
T* ObjCCastStrict(id objc_val) {
T* rv = ObjCCast<T>(objc_val);
DCHECK(objc_val == nil || rv);
return rv;
}
#endif // defined(__OBJC__)
} // namespace apple
} // namespace base
#endif // MINI_CHROMIUM_BASE_APPLE_FOUNDATION_UTIL_H_

View File

@ -0,0 +1,62 @@
// Copyright 2008 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "base/apple/foundation_util.h"
#if !BUILDFLAG(IS_IOS)
extern "C" {
CFTypeID SecACLGetTypeID();
CFTypeID SecTrustedApplicationGetTypeID();
} // extern "C"
#endif
namespace base {
namespace apple {
#define CF_CAST_DEFN(TypeCF) \
template <> \
TypeCF##Ref CFCast<TypeCF##Ref>(const CFTypeRef& cf_val) { \
if (cf_val == NULL) { \
return NULL; \
} \
if (CFGetTypeID(cf_val) == TypeCF##GetTypeID()) { \
return (TypeCF##Ref)(cf_val); \
} \
return NULL; \
} \
\
template <> \
TypeCF##Ref CFCastStrict<TypeCF##Ref>(const CFTypeRef& cf_val) { \
TypeCF##Ref rv = CFCast<TypeCF##Ref>(cf_val); \
DCHECK(cf_val == NULL || rv); \
return rv; \
}
CF_CAST_DEFN(CFArray)
CF_CAST_DEFN(CFBag)
CF_CAST_DEFN(CFBoolean)
CF_CAST_DEFN(CFData)
CF_CAST_DEFN(CFDate)
CF_CAST_DEFN(CFDictionary)
CF_CAST_DEFN(CFNull)
CF_CAST_DEFN(CFNumber)
CF_CAST_DEFN(CFSet)
CF_CAST_DEFN(CFString)
CF_CAST_DEFN(CFURL)
CF_CAST_DEFN(CFUUID)
CF_CAST_DEFN(CGColor)
CF_CAST_DEFN(CTFont)
CF_CAST_DEFN(CTRun)
#if !BUILDFLAG(IS_IOS)
CF_CAST_DEFN(SecACL)
CF_CAST_DEFN(SecTrustedApplication)
#endif
#undef CF_CAST_DEFN
} // namespace apple
} // namespace base

View File

@ -0,0 +1,84 @@
// Copyright 2014 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "base/apple/mach_logging.h"
#include <iomanip>
#include <string>
#include "base/strings/stringprintf.h"
#if !BUILDFLAG(IS_IOS)
#include <servers/bootstrap.h>
#endif // !BUILDFLAG(IS_IOS)
namespace {
std::string FormatMachErrorNumber(mach_error_t mach_err) {
// For the os/kern subsystem, give the error number in decimal as in
// <mach/kern_return.h>. Otherwise, give it in hexadecimal to make it easier
// to visualize the various bits. See <mach/error.h>.
if (mach_err >= 0 && mach_err < KERN_RETURN_MAX) {
return base::StringPrintf(" (%d)", mach_err);
}
return base::StringPrintf(" (0x%08x)", mach_err);
}
} // namespace
namespace logging {
MachLogMessage::MachLogMessage(const char* function,
const char* file_path,
int line,
LogSeverity severity,
mach_error_t mach_err)
: LogMessage(function, file_path, line, severity), mach_err_(mach_err) {}
MachLogMessage::~MachLogMessage() {
stream() << ": " << mach_error_string(mach_err_)
<< FormatMachErrorNumber(mach_err_);
}
#if !BUILDFLAG(IS_IOS)
BootstrapLogMessage::BootstrapLogMessage(const char* function,
const char* file_path,
int line,
LogSeverity severity,
kern_return_t bootstrap_err)
: LogMessage(function, file_path, line, severity),
bootstrap_err_(bootstrap_err) {}
BootstrapLogMessage::~BootstrapLogMessage() {
stream() << ": " << bootstrap_strerror(bootstrap_err_);
switch (bootstrap_err_) {
case BOOTSTRAP_SUCCESS:
case BOOTSTRAP_NOT_PRIVILEGED:
case BOOTSTRAP_NAME_IN_USE:
case BOOTSTRAP_UNKNOWN_SERVICE:
case BOOTSTRAP_SERVICE_ACTIVE:
case BOOTSTRAP_BAD_COUNT:
case BOOTSTRAP_NO_MEMORY:
case BOOTSTRAP_NO_CHILDREN: {
// Show known bootstrap errors in decimal because that's how they're
// defined in <servers/bootstrap.h>.
stream() << " (" << bootstrap_err_ << ")";
break;
}
default: {
// bootstrap_strerror passes unknown errors to mach_error_string, so
// format them as they would be if they were handled by
// MachErrorMessage.
stream() << FormatMachErrorNumber(bootstrap_err_);
break;
}
}
}
#endif // !BUILDFLAG(IS_IOS)
} // namespace logging

View File

@ -0,0 +1,163 @@
// Copyright 2014 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef MINI_CHROMIUM_BASE_APPLE_MACH_LOGGING_H_
#define MINI_CHROMIUM_BASE_APPLE_MACH_LOGGING_H_
#include <mach/mach.h>
#include "base/logging.h"
#include "build/build_config.h"
// Use the MACH_LOG family of macros along with a mach_error_t (kern_return_t)
// containing a Mach error. The error value will be decoded so that logged
// messages explain the error.
//
// Use the BOOTSTRAP_LOG family of macros specifically for errors that occur
// while interoperating with the bootstrap subsystem. These errors will first
// be looked up as bootstrap error messages. If no match is found, they will
// be treated as generic Mach errors, as in MACH_LOG.
//
// Examples:
//
// kern_return_t kr = mach_timebase_info(&info);
// if (kr != KERN_SUCCESS) {
// MACH_LOG(ERROR, kr) << "mach_timebase_info";
// }
//
// kr = vm_deallocate(task, address, size);
// MACH_DCHECK(kr == KERN_SUCCESS, kr) << "vm_deallocate";
namespace logging {
class MachLogMessage : public logging::LogMessage {
public:
MachLogMessage(const char* function,
const char* file_path,
int line,
LogSeverity severity,
mach_error_t mach_err);
MachLogMessage(const MachLogMessage&) = delete;
MachLogMessage& operator=(const MachLogMessage&) = delete;
~MachLogMessage();
private:
mach_error_t mach_err_;
};
} // namespace logging
#define MACH_LOG_STREAM(severity, mach_err) \
COMPACT_GOOGLE_LOG_EX_##severity(MachLogMessage, mach_err).stream()
#define MACH_VLOG_STREAM(verbose_level, mach_err) \
logging::MachLogMessage( \
__PRETTY_FUNCTION__, __FILE__, __LINE__, -verbose_level, mach_err) \
.stream()
#define MACH_LOG(severity, mach_err) \
LAZY_STREAM(MACH_LOG_STREAM(severity, mach_err), LOG_IS_ON(severity))
#define MACH_LOG_IF(severity, condition, mach_err) \
LAZY_STREAM(MACH_LOG_STREAM(severity, mach_err), \
LOG_IS_ON(severity) && (condition))
#define MACH_VLOG(verbose_level, mach_err) \
LAZY_STREAM(MACH_VLOG_STREAM(verbose_level, mach_err), \
VLOG_IS_ON(verbose_level))
#define MACH_VLOG_IF(verbose_level, condition, mach_err) \
LAZY_STREAM(MACH_VLOG_STREAM(verbose_level, mach_err), \
VLOG_IS_ON(verbose_level) && (condition))
#define MACH_CHECK(condition, mach_err) \
LAZY_STREAM(MACH_LOG_STREAM(FATAL, mach_err), !(condition)) \
<< "Check failed: " #condition << ". "
#define MACH_DLOG(severity, mach_err) \
LAZY_STREAM(MACH_LOG_STREAM(severity, mach_err), DLOG_IS_ON(severity))
#define MACH_DLOG_IF(severity, condition, mach_err) \
LAZY_STREAM(MACH_LOG_STREAM(severity, mach_err), \
DLOG_IS_ON(severity) && (condition))
#define MACH_DVLOG(verbose_level, mach_err) \
LAZY_STREAM(MACH_VLOG_STREAM(verbose_level, mach_err), \
DVLOG_IS_ON(verbose_level))
#define MACH_DVLOG_IF(verbose_level, condition, mach_err) \
LAZY_STREAM(MACH_VLOG_STREAM(verbose_level, mach_err), \
DVLOG_IS_ON(verbose_level) && (condition))
#define MACH_DCHECK(condition, mach_err) \
LAZY_STREAM(MACH_LOG_STREAM(FATAL, mach_err), DCHECK_IS_ON && !(condition)) \
<< "Check failed: " #condition << ". "
#if !BUILDFLAG(IS_IOS)
namespace logging {
class BootstrapLogMessage : public logging::LogMessage {
public:
BootstrapLogMessage(const char* function,
const char* file_path,
int line,
LogSeverity severity,
kern_return_t bootstrap_err);
BootstrapLogMessage(const BootstrapLogMessage&) = delete;
BootstrapLogMessage& operator=(const BootstrapLogMessage&) = delete;
~BootstrapLogMessage();
private:
kern_return_t bootstrap_err_;
};
} // namespace logging
#define BOOTSTRAP_LOG_STREAM(severity, bootstrap_err) \
COMPACT_GOOGLE_LOG_EX_##severity(BootstrapLogMessage, bootstrap_err).stream()
#define BOOTSTRAP_VLOG_STREAM(verbose_level, bootstrap_err) \
logging::BootstrapLogMessage( \
__PRETTY_FUNCTION__, __FILE__, __LINE__, -verbose_level, bootstrap_err) \
.stream()
#define BOOTSTRAP_LOG(severity, bootstrap_err) \
LAZY_STREAM(BOOTSTRAP_LOG_STREAM(severity, bootstrap_err), \
LOG_IS_ON(severity))
#define BOOTSTRAP_LOG_IF(severity, condition, bootstrap_err) \
LAZY_STREAM(BOOTSTRAP_LOG_STREAM(severity, bootstrap_err), \
LOG_IS_ON(severity) && (condition))
#define BOOTSTRAP_VLOG(verbose_level, bootstrap_err) \
LAZY_STREAM(BOOTSTRAP_VLOG_STREAM(verbose_level, bootstrap_err), \
VLOG_IS_ON(verbose_level))
#define BOOTSTRAP_VLOG_IF(verbose_level, condition, bootstrap_err) \
LAZY_STREAM(BOOTSTRAP_VLOG_STREAM(verbose_level, bootstrap_err), \
VLOG_IS_ON(verbose_level) && (condition))
#define BOOTSTRAP_CHECK(condition, bootstrap_err) \
LAZY_STREAM(BOOTSTRAP_LOG_STREAM(FATAL, bootstrap_err), !(condition)) \
<< "Check failed: " #condition << ". "
#define BOOTSTRAP_DLOG(severity, bootstrap_err) \
LAZY_STREAM(BOOTSTRAP_LOG_STREAM(severity, bootstrap_err), \
DLOG_IS_ON(severity))
#define BOOTSTRAP_DLOG_IF(severity, condition, bootstrap_err) \
LAZY_STREAM(BOOTSTRAP_LOG_STREAM(severity, bootstrap_err), \
DLOG_IS_ON(severity) && (condition))
#define BOOTSTRAP_DVLOG(verbose_level, bootstrap_err) \
LAZY_STREAM(BOOTSTRAP_VLOG_STREAM(verbose_level, bootstrap_err), \
DVLOG_IS_ON(verbose_level))
#define BOOTSTRAP_DVLOG_IF(verbose_level, condition, bootstrap_err) \
LAZY_STREAM(BOOTSTRAP_VLOG_STREAM(verbose_level, bootstrap_err), \
DVLOG_IS_ON(verbose_level) && (condition))
#define BOOTSTRAP_DCHECK(condition, bootstrap_err) \
LAZY_STREAM(BOOTSTRAP_LOG_STREAM(FATAL, bootstrap_err), \
DCHECK_IS_ON && !(condition)) \
<< "Check failed: " #condition << ". "
#endif // !BUILDFLAG(IS_IOS)
#endif // MINI_CHROMIUM_BASE_APPLE_MACH_LOGGING_H_

View File

@ -0,0 +1,36 @@
// Copyright 2006-2008 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef MINI_CHROMIUM_BASE_APPLE_SCOPED_CFTYPEREF_H_
#define MINI_CHROMIUM_BASE_APPLE_SCOPED_CFTYPEREF_H_
#include <CoreFoundation/CoreFoundation.h>
#include "base/apple/scoped_typeref.h"
namespace base {
namespace apple {
namespace internal {
template <typename CFT>
struct ScopedCFTypeRefTraits {
static CFT InvalidValue() { return nullptr; }
static CFT Retain(CFT object) {
CFRetain(object);
return object;
}
static void Release(CFT object) { CFRelease(object); }
};
} // namespace internal
template <typename CFT>
using ScopedCFTypeRef =
ScopedTypeRef<CFT, internal::ScopedCFTypeRefTraits<CFT>>;
} // namespace apple
} // namespace base
#endif // MINI_CHROMIUM_BASE_APPLE_SCOPED_CFTYPEREF_H_

View File

@ -0,0 +1,32 @@
// Copyright 2012 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "base/apple/scoped_mach_port.h"
#include "base/apple/mach_logging.h"
namespace base {
namespace apple {
namespace internal {
void SendRightTraits::Free(mach_port_t port) {
kern_return_t kr = mach_port_deallocate(mach_task_self(), port);
MACH_LOG_IF(ERROR, kr != KERN_SUCCESS, kr) << "mach_port_deallocate";
}
void ReceiveRightTraits::Free(mach_port_t port) {
kern_return_t kr =
mach_port_mod_refs(mach_task_self(), port, MACH_PORT_RIGHT_RECEIVE, -1);
MACH_LOG_IF(ERROR, kr != KERN_SUCCESS, kr) << "mach_port_mod_refs";
}
void PortSetTraits::Free(mach_port_t port) {
kern_return_t kr =
mach_port_mod_refs(mach_task_self(), port, MACH_PORT_RIGHT_PORT_SET, -1);
MACH_LOG_IF(ERROR, kr != KERN_SUCCESS, kr) << "mach_port_mod_refs";
}
} // namespace internal
} // namespace apple
} // namespace base

View File

@ -0,0 +1,43 @@
// Copyright 2012 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef MINI_CHROMIUM_BASE_APPLE_SCOPED_MACH_PORT_H_
#define MINI_CHROMIUM_BASE_APPLE_SCOPED_MACH_PORT_H_
#include <mach/mach.h>
#include "base/scoped_generic.h"
namespace base {
namespace apple {
namespace internal {
struct SendRightTraits {
static mach_port_t InvalidValue() { return MACH_PORT_NULL; }
static void Free(mach_port_t port);
};
struct ReceiveRightTraits {
static mach_port_t InvalidValue() { return MACH_PORT_NULL; }
static void Free(mach_port_t port);
};
struct PortSetTraits {
static mach_port_t InvalidValue() { return MACH_PORT_NULL; }
static void Free(mach_port_t port);
};
} // namespace internal
using ScopedMachSendRight =
ScopedGeneric<mach_port_t, internal::SendRightTraits>;
using ScopedMachReceiveRight =
ScopedGeneric<mach_port_t, internal::ReceiveRightTraits>;
using ScopedMachPortSet = ScopedGeneric<mach_port_t, internal::PortSetTraits>;
} // namespace apple
} // namespace base
#endif // MINI_CHROMIUM_BASE_APPLE_SCOPED_MACH_PORT_H_

View File

@ -0,0 +1,32 @@
// Copyright 2014 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "base/apple/scoped_mach_vm.h"
namespace base {
namespace apple {
void ScopedMachVM::reset(vm_address_t address, vm_size_t size) {
DCHECK(address % PAGE_SIZE == 0);
DCHECK(size % PAGE_SIZE == 0);
if (size_) {
if (address_ < address) {
vm_deallocate(
mach_task_self(), address_, std::min(size_, address - address_));
}
if (address_ + size_ > address + size) {
vm_address_t deallocate_start = std::max(address_, address + size);
vm_deallocate(mach_task_self(),
deallocate_start,
address_ + size_ - deallocate_start);
}
}
address_ = address;
size_ = size;
}
} // namespace apple
} // namespace base

View File

@ -0,0 +1,87 @@
// Copyright 2014 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef MINI_CHROMIUM_BASE_APPLE_SCOPED_MACH_VM_H_
#define MINI_CHROMIUM_BASE_APPLE_SCOPED_MACH_VM_H_
#include <mach/mach.h>
#include <algorithm>
#include "base/logging.h"
// Use ScopedMachVM to supervise ownership of pages in the current process
// through the Mach VM subsystem. Pages allocated with vm_allocate can be
// released when exiting a scope with ScopedMachVM.
//
// The Mach VM subsystem operates on a page-by-page basis, and a single VM
// allocation managed by a ScopedMachVM object may span multiple pages. As far
// as Mach is concerned, allocated pages may be deallocated individually. This
// is in contrast to higher-level allocators such as malloc, where the base
// address of an allocation implies the size of an allocated block.
// Consequently, it is not sufficient to just pass the base address of an
// allocation to ScopedMachVM, it also needs to know the size of the
// allocation. To avoid any confusion, both the base address and size must
// be page-aligned.
//
// When dealing with Mach VM, base addresses will naturally be page-aligned,
// but user-specified sizes may not be. If there's a concern that a size is
// not page-aligned, use the mach_vm_round_page macro to correct it.
//
// Example:
//
// vm_address_t address = 0;
// vm_size_t size = 12345; // This requested size is not page-aligned.
// kern_return_t kr =
// vm_allocate(mach_task_self(), &address, size, VM_FLAGS_ANYWHERE);
// if (kr != KERN_SUCCESS) {
// return false;
// }
// ScopedMachVM vm_owner(address, mach_vm_round_page(size));
namespace base {
namespace apple {
class ScopedMachVM {
public:
explicit ScopedMachVM(vm_address_t address = 0, vm_size_t size = 0)
: address_(address), size_(size) {
DCHECK(address % PAGE_SIZE == 0);
DCHECK(size % PAGE_SIZE == 0);
}
ScopedMachVM(const ScopedMachVM&) = delete;
ScopedMachVM& operator=(const ScopedMachVM&) = delete;
~ScopedMachVM() {
if (size_) {
vm_deallocate(mach_task_self(), address_, size_);
}
}
void reset(vm_address_t address = 0, vm_size_t size = 0);
vm_address_t address() const { return address_; }
vm_size_t size() const { return size_; }
void swap(ScopedMachVM& that) {
std::swap(address_, that.address_);
std::swap(size_, that.size_);
}
void release() {
address_ = 0;
size_ = 0;
}
private:
vm_address_t address_;
vm_size_t size_;
};
} // namespace apple
} // namespace base
#endif // MINI_CHROMIUM_BASE_APPLE_SCOPED_MACH_VM_H_

View File

@ -0,0 +1,48 @@
// Copyright 2008 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef MINI_CHROMIUM_BASE_APPLE_SCOPED_NSAUTORELEASE_POOL_H_
#define MINI_CHROMIUM_BASE_APPLE_SCOPED_NSAUTORELEASE_POOL_H_
#include "build/build_config.h"
namespace base {
namespace apple {
// On the Mac, ScopedNSAutoreleasePool creates an autorelease pool when
// instantiated and pops it when destroyed. This allows an autorelease pool to
// be maintained in ordinary C++ code without bringing in any direct Objective-C
// dependency.
//
// On other platforms, ScopedNSAutoreleasePool is an empty object with no
// effects. This allows it to be used directly in cross-platform code without
// ugly #ifdefs.
class ScopedNSAutoreleasePool {
public:
#if !BUILDFLAG(IS_APPLE)
ScopedNSAutoreleasePool() {}
void Recycle() {}
#else // BUILDFLAG(IS_APPLE)
ScopedNSAutoreleasePool();
ScopedNSAutoreleasePool(const ScopedNSAutoreleasePool&) = delete;
ScopedNSAutoreleasePool& operator=(const ScopedNSAutoreleasePool&) = delete;
~ScopedNSAutoreleasePool();
// Clear out the pool in case its position on the stack causes it to be
// alive for long periods of time (such as the entire length of the app).
// Only use then when you're certain the items currently in the pool are
// no longer needed.
void Recycle();
private:
void* autorelease_pool_;
#endif // BUILDFLAG(IS_APPLE)
};
} // namespace apple
} // namespace base
#endif // MINI_CHROMIUM_BASE_APPLE_SCOPED_NSAUTORELEASE_POOL_H_

View File

@ -0,0 +1,36 @@
// Copyright 2008 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "base/apple/scoped_nsautorelease_pool.h"
#include "base/logging.h"
// Note that this uses the direct runtime interface to the autorelease pool.
// https://clang.llvm.org/docs/AutomaticReferenceCounting.html#runtime-support
// This is so this can work when compiled for ARC.
extern "C" {
void* objc_autoreleasePoolPush(void);
void objc_autoreleasePoolPop(void* pool);
}
namespace base {
namespace apple {
ScopedNSAutoreleasePool::ScopedNSAutoreleasePool()
: autorelease_pool_(objc_autoreleasePoolPush()) {}
ScopedNSAutoreleasePool::~ScopedNSAutoreleasePool() {
objc_autoreleasePoolPop(autorelease_pool_);
}
// Cycle the internal pool, allowing everything there to get cleaned up and
// start anew.
void ScopedNSAutoreleasePool::Recycle() {
objc_autoreleasePoolPop(autorelease_pool_);
autorelease_pool_ = objc_autoreleasePoolPush();
}
} // namespace apple
} // namespace base

View File

@ -0,0 +1,87 @@
// Copyright 2014 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef MINI_CHROMIUM_BASE_APPLE_SCOPED_TYPEREF_H_
#define MINI_CHROMIUM_BASE_APPLE_SCOPED_TYPEREF_H_
#include "base/logging.h"
#include "base/memory/scoped_policy.h"
namespace base {
namespace apple {
template <typename T>
struct ScopedTypeRefTraits;
template <typename T, typename Traits = ScopedTypeRefTraits<T>>
class ScopedTypeRef {
public:
typedef T element_type;
ScopedTypeRef(
T object = Traits::InvalidValue(),
base::scoped_policy::OwnershipPolicy policy = base::scoped_policy::ASSUME)
: object_(object) {
if (object_ && policy == base::scoped_policy::RETAIN)
object_ = Traits::Retain(object_);
}
ScopedTypeRef(const ScopedTypeRef<T, Traits>& that) : object_(that.object_) {
if (object_)
object_ = Traits::Retain(object_);
}
~ScopedTypeRef() {
if (object_)
Traits::Release(object_);
}
ScopedTypeRef& operator=(const ScopedTypeRef<T, Traits>& that) {
reset(that.get(), base::scoped_policy::RETAIN);
return *this;
}
[[nodiscard]] T* InitializeInto() {
DCHECK(!object_);
return &object_;
}
void reset(T object = Traits::InvalidValue(),
base::scoped_policy::OwnershipPolicy policy =
base::scoped_policy::ASSUME) {
if (object && policy == base::scoped_policy::RETAIN)
object = Traits::Retain(object);
if (object_)
Traits::Release(object_);
object_ = object;
}
bool operator==(T that) const { return object_ == that; }
bool operator!=(T that) const { return object_ != that; }
operator T() const { return object_; }
T get() const { return object_; }
void swap(ScopedTypeRef& that) {
T temp = that.object_;
that.object_ = object_;
object_ = temp;
}
[[nodiscard]] T release() {
T temp = object_;
object_ = Traits::InvalidValue();
return temp;
}
private:
T object_;
};
} // namespace apple
} // namespace base
#endif // MINI_CHROMIUM_BASE_APPLE_SCOPED_TYPEREF_H_

View File

@ -0,0 +1,155 @@
// Copyright 2015 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "base/strings/pattern.h"
#include "base/third_party/icu/icu_utf.h"
namespace base {
namespace {
constexpr bool IsWildcard(base_icu::UChar32 character) {
return character == '*' || character == '?';
}
// Searches for the next subpattern of |pattern| in |string|, up to the given
// |maximum_distance|. The subpattern extends from the start of |pattern| up to
// the first wildcard character (or the end of the string). If the value of
// |maximum_distance| is negative, the maximum distance is considered infinite.
template <typename CHAR, typename NEXT>
constexpr bool SearchForChars(const CHAR** pattern,
const CHAR* pattern_end,
const CHAR** string,
const CHAR* string_end,
int maximum_distance,
NEXT next) {
const CHAR* pattern_start = *pattern;
const CHAR* string_start = *string;
bool escape = false;
while (true) {
if (*pattern == pattern_end) {
// If this is the end of the pattern, only accept the end of the string;
// anything else falls through to the mismatch case.
if (*string == string_end)
return true;
} else {
// If we have found a wildcard, we're done.
if (!escape && IsWildcard(**pattern))
return true;
// Check if the escape character is found. If so, skip it and move to the
// next character.
if (!escape && **pattern == '\\') {
escape = true;
next(pattern, pattern_end);
continue;
}
escape = false;
if (*string == string_end)
return false;
// Check if the chars match, if so, increment the ptrs.
const CHAR* pattern_next = *pattern;
const CHAR* string_next = *string;
base_icu::UChar32 pattern_char = next(&pattern_next, pattern_end);
if (pattern_char == next(&string_next, string_end) &&
pattern_char != CBU_SENTINEL) {
*pattern = pattern_next;
*string = string_next;
continue;
}
}
// Mismatch. If we have reached the maximum distance, return false,
// otherwise restart at the beginning of the pattern with the next character
// in the string.
// TODO(bauerb): This is a naive implementation of substring search, which
// could be implemented with a more efficient algorithm, e.g.
// Knuth-Morris-Pratt (at the expense of requiring preprocessing).
if (maximum_distance == 0)
return false;
// Because unlimited distance is represented as -1, this will never reach 0
// and therefore fail the match above.
maximum_distance--;
*pattern = pattern_start;
next(&string_start, string_end);
*string = string_start;
}
}
// Consumes consecutive wildcard characters (? or *). Returns the maximum number
// of characters matched by the sequence of wildcards, or -1 if the wildcards
// match an arbitrary number of characters (which is the case if it contains at
// least one *).
template <typename CHAR, typename NEXT>
constexpr int EatWildcards(const CHAR** pattern, const CHAR* end, NEXT next) {
int num_question_marks = 0;
bool has_asterisk = false;
while (*pattern != end) {
if (**pattern == '?') {
num_question_marks++;
} else if (**pattern == '*') {
has_asterisk = true;
} else {
break;
}
next(pattern, end);
}
return has_asterisk ? -1 : num_question_marks;
}
template <typename CHAR, typename NEXT>
constexpr bool MatchPatternT(const CHAR* eval,
const CHAR* eval_end,
const CHAR* pattern,
const CHAR* pattern_end,
NEXT next) {
do {
int maximum_wildcard_length = EatWildcards(&pattern, pattern_end, next);
if (!SearchForChars(&pattern, pattern_end, &eval, eval_end,
maximum_wildcard_length, next)) {
return false;
}
} while (pattern != pattern_end);
return true;
}
struct NextCharUTF8 {
base_icu::UChar32 operator()(const char** p, const char* end) {
base_icu::UChar32 c;
int offset = 0;
CBU8_NEXT(reinterpret_cast<const uint8_t*>(*p), offset, end - *p, c);
*p += offset;
return c;
}
};
struct NextCharUTF16 {
base_icu::UChar32 operator()(const char16_t** p, const char16_t* end) {
base_icu::UChar32 c;
int offset = 0;
CBU16_NEXT(*p, offset, end - *p, c);
*p += offset;
return c;
}
};
} // namespace
bool MatchPattern(StringPiece eval, StringPiece pattern) {
return MatchPatternT(eval.data(), eval.data() + eval.size(), pattern.data(),
pattern.data() + pattern.size(), NextCharUTF8());
}
bool MatchPattern(StringPiece16 eval, StringPiece16 pattern) {
return MatchPatternT(eval.data(), eval.data() + eval.size(), pattern.data(),
pattern.data() + pattern.size(), NextCharUTF16());
}
} // namespace base

View File

@ -0,0 +1,22 @@
// Copyright 2015 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef BASE_STRINGS_PATTERN_H_
#define BASE_STRINGS_PATTERN_H_
#include "base/strings/string_piece.h"
namespace base {
// Returns true if the |string| passed in matches the |pattern|. The pattern
// string can contain wildcards like * and ?.
//
// The backslash character (\) is an escape character for * and ?.
// ? matches 0 or 1 character, while * matches 0 or more characters.
bool MatchPattern(StringPiece string, StringPiece pattern);
bool MatchPattern(StringPiece16 string, StringPiece16 pattern);
} // namespace base
#endif // BASE_STRINGS_PATTERN_H_

View File

@ -0,0 +1,25 @@
// Copyright 2023 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef MINI_CHROMIUM_BASE_TYPES_CXX23_TO_UNDERLYING_H_
#define MINI_CHROMIUM_BASE_TYPES_CXX23_TO_UNDERLYING_H_
#include <type_traits>
namespace base {
// Implementation of C++23's std::to_underlying.
//
// Note: This has an additional `std::is_enum<EnumT>` requirement to be SFINAE
// friendly prior to C++20.
//
// Reference: https://en.cppreference.com/w/cpp/utility/to_underlying
template <typename EnumT, typename = std::enable_if_t<std::is_enum<EnumT>{}>>
constexpr std::underlying_type_t<EnumT> to_underlying(EnumT e) noexcept {
return static_cast<std::underlying_type_t<EnumT>>(e);
}
} // namespace base
#endif // MINI_CHROMIUM_BASE_TYPES_CXX23_TO_UNDERLYING_H_

View File

@ -0,0 +1,147 @@
// Copyright 2023 The Crashpad Authors
//
// 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 <getopt.h>
#include "base/files/file_path.h"
#include "client/annotation.h"
#include "util/file/file_reader.h"
#include "snapshot/minidump/process_snapshot_minidump.h"
#include "tools/tool_support.h"
namespace crashpad {
namespace {
void Usage(const base::FilePath& me) {
// clang-format off
fprintf(stderr,
"Usage: %" PRFilePath " [OPTION]... PATH\n"
"Dump annotations from minidumps.\n"
"\n"
" --help display this help and exit\n"
" --version output version information and exit\n",
me.value().c_str());
// clang-format on
ToolSupport::UsageTail(me);
}
struct Options {
const char* minidump;
};
int DumpMinidumpAnnotationsMain(int argc, char* argv[]) {
const base::FilePath argv0(
ToolSupport::CommandLineArgumentToFilePathStringType(argv[0]));
const base::FilePath me(argv0.BaseName());
enum OptionFlags {
// Long options without short equivalents.
kOptionLastChar = 255,
kOptionMinidump,
// Standard options.
kOptionHelp = -2,
kOptionVersion = -3,
};
static constexpr option long_options[] = {
{"minidump", required_argument, nullptr, kOptionMinidump},
{"help", no_argument, nullptr, kOptionHelp},
{"version", no_argument, nullptr, kOptionVersion},
{nullptr, 0, nullptr, 0},
};
Options options = {};
int opt;
while ((opt = getopt_long(argc, argv, "", long_options, nullptr)) != -1) {
switch (opt) {
case kOptionMinidump: {
options.minidump = optarg;
break;
}
case kOptionHelp: {
Usage(me);
return EXIT_SUCCESS;
}
case kOptionVersion: {
ToolSupport::Version(me);
return EXIT_SUCCESS;
}
default: {
ToolSupport::UsageHint(me, nullptr);
return EXIT_FAILURE;
}
}
}
argc -= optind;
argv += optind;
if (!options.minidump) {
ToolSupport::UsageHint(me, "--minidump is required");
return EXIT_FAILURE;
}
FileReader reader;
if (!reader.Open(base::FilePath(
ToolSupport::CommandLineArgumentToFilePathStringType(
options.minidump)))) {
return EXIT_FAILURE;
}
ProcessSnapshotMinidump snapshot;
if (!snapshot.Initialize(&reader)) {
return EXIT_FAILURE;
}
for (const ModuleSnapshot* module : snapshot.Modules()) {
printf("Module: %s\n", module->Name().c_str());
printf(" Simple Annotations\n");
for (const auto& kv : module->AnnotationsSimpleMap()) {
printf(" simple_annotations[\"%s\"] = %s\n",
kv.first.c_str(), kv.second.c_str());
}
printf(" Vectored Annotations\n");
int index = 0;
for (const std::string& annotation : module->AnnotationsVector()) {
printf(" vectored_annotations[%d] = %s\n", index, annotation.c_str());
index++;
}
printf(" Annotation Objects\n");
for (const AnnotationSnapshot& annotation : module->AnnotationObjects()) {
printf(" annotation_objects[\"%s\"] = ", annotation.name.c_str());
if (annotation.type != static_cast<uint16_t>(Annotation::Type::kString)) {
printf("<non-string value, not printing>\n");
continue;
}
std::string value(reinterpret_cast<const char*>(annotation.value.data()),
annotation.value.size());
printf("%s\n", value.c_str());
}
}
return EXIT_SUCCESS;
}
} // namespace
} // namespace crashpad
int main(int argc, char* argv[]) {
return crashpad::DumpMinidumpAnnotationsMain(argc, argv);
}

View File

@ -0,0 +1,44 @@
// Copyright 2023 The Crashpad Authors
//
// 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 "util/linux/pac_helper.h"
#if defined(__has_feature)
#define CRASHPAD_HAS_FEATURE(x) __has_feature(x)
#else
#define CRASHPAD_HAS_FEATURE(x) 0
#endif
#if CRASHPAD_HAS_FEATURE(ptrauth_intrinsics)
#include <ptrauth.h>
#endif
#include "util/misc/address_types.h"
namespace crashpad {
VMAddress StripPACBits(VMAddress address) {
#if CRASHPAD_HAS_FEATURE(ptrauth_intrinsics)
address = ptrauth_strip(address, ptrauth_key_function_pointer);
#elif defined(ARCH_CPU_ARM64)
// Strip any pointer authentication bits that are assigned to the address.
register uintptr_t x30 __asm("x30") = address;
asm("xpaclri" : "+r"(x30));
address = x30;
#endif
return address;
}
} // namespace crashpad

View File

@ -0,0 +1,29 @@
// Copyright 2023 The Crashpad Authors
//
// 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.
#ifndef CRASHPAD_UTIL_LINUX_PAC_HELPER_H_
#define CRASHPAD_UTIL_LINUX_PAC_HELPER_H_
#include "util/misc/address_types.h"
namespace crashpad {
//! \brief Strips PAC bits from an address
VMAddress StripPACBits(VMAddress address);
} // namespace crashpad
#endif // CRASHPAD_UTIL_LINUX_PAC_HELPER_H_

View File

@ -0,0 +1,55 @@
/*
* Copyright (C) 2023 The Android Open Source Project
*
* 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 <cxxabi.h>
#include <stdlib.h>
#include <string>
#ifdef SENTRY_REMOVED
#include <rustc_demangle.h>
#endif //SENTRY_REMOVED
#include <unwindstack/Demangle.h>
namespace unwindstack {
std::string DemangleNameIfNeeded(const std::string& name) {
if (name.length() < 2 || name[0] != '_') {
return name;
}
char* demangled_str = nullptr;
if (name[1] == 'Z') {
// Try to demangle C++ name.
demangled_str = abi::__cxa_demangle(name.c_str(), nullptr, nullptr, nullptr);
#ifdef SENTRY_REMOVED
} else if (name[1] == 'R') {
// Try to demangle rust name.
demangled_str = rustc_demangle(name.c_str(), nullptr, nullptr, nullptr);
#endif //SENTRY_REMOVED
}
if (demangled_str == nullptr) {
return name;
}
std::string demangled_name(demangled_str);
free(demangled_str);
return demangled_name;
}
} // namespace unwindstack

View File

@ -0,0 +1,25 @@
/*
* Copyright (C) 2023 The Android Open Source Project
*
* 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.
*/
#pragma once
#include <string>
namespace unwindstack {
std::string DemangleNameIfNeeded(const std::string& name);
} // namespace unwindstack

View File

@ -0,0 +1,12 @@
# Metadata information for this directory.
#
# For more information on DIR_METADATA files, see:
# https://source.chromium.org/chromium/infra/infra/+/HEAD:go/src/infra/tools/dirmd/README.md
#
# For the schema of this file, see Metadata message:
# https://source.chromium.org/chromium/infra/infra/+/HEAD:go/src/infra/tools/dirmd/proto/dir_metadata.proto
os: LINUX
monorail {
project: "linux-syscall-support"
}

View File

@ -0,0 +1,27 @@
Copyright 2005-2011 Google LLC
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are
met:
Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
Redistributions in binary form must reproduce the above
copyright notice, this list of conditions and the following disclaimer
in the documentation and/or other materials provided with the
distribution.
Neither the name of Google LLC nor the names of its
contributors may be used to endorse or promote products derived from
this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

View File

@ -0,0 +1,2 @@
mseaborn@chromium.org
vapier@chromium.org

View File

@ -0,0 +1,84 @@
/* Copyright 2022 Google LLC
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following disclaimer
* in the documentation and/or other materials provided with the
* distribution.
* * Neither the name of Google LLC nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "test_skel.h"
int main(int argc, char *argv[]) {
// We need an invalid timer value. The assert()'s below should
// be static asserts but it is not available in older C versions.
#define kInvalidTimer 9999
assert(kInvalidTimer != ITIMER_REAL);
assert(kInvalidTimer != ITIMER_VIRTUAL);
assert(kInvalidTimer != ITIMER_PROF);
// This should fail with EINVAL.
struct kernel_itimerval curr_itimer;
assert(sys_getitimer(kInvalidTimer, &curr_itimer) == -1);
assert(errno == EINVAL);
// Create a read-only page.
size_t page_size = getpagesize();
void* read_only_page = sys_mmap(NULL, page_size, PROT_READ,
MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
assert(read_only_page != MAP_FAILED);
// This should fail with EFAULT.
assert(sys_getitimer(ITIMER_REAL,
(struct kernel_itimerval*) read_only_page) == -1);
assert(errno == EFAULT);
// This should complete without an error.
assert(sys_getitimer(ITIMER_REAL, &curr_itimer) == 0);
// Set up a real time timer with very long interval and value so that
// we do not need to handle SIGALARM in test.
struct kernel_itimerval new_itimer;
const time_t kIntervalSec = 60 * 60 * 24 * 365; // One year.
const long kIntervalUSec = 123;
new_itimer.it_interval.tv_sec = kIntervalSec;
new_itimer.it_interval.tv_usec = kIntervalUSec;
new_itimer.it_value = new_itimer.it_interval;
assert(sys_setitimer(ITIMER_REAL, &new_itimer, NULL) == 0);
assert(sys_getitimer(ITIMER_REAL, &curr_itimer) == 0);
assert(kernel_timeval_eq(&curr_itimer.it_interval, &new_itimer.it_interval));
// Disable timer.
struct kernel_itimerval empty_itimer;
empty_itimer.it_interval.tv_sec = 0;
empty_itimer.it_interval.tv_usec = 0;
empty_itimer.it_value = empty_itimer.it_interval;
assert(sys_setitimer(ITIMER_REAL, &empty_itimer, NULL) == 0);
// We should read back an empty itimer.
assert(sys_getitimer(ITIMER_REAL, &curr_itimer) == 0);
assert(kernel_itimerval_eq(&curr_itimer, &empty_itimer));
return 0;
}

View File

@ -0,0 +1,59 @@
/* Copyright 2020 Google LLC
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following disclaimer
* in the documentation and/or other materials provided with the
* distribution.
* * Neither the name of Google LLC nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "test_skel.h"
#define BUFFER_SIZE 256
int main(int argc, char *argv[]) {
char buffer[BUFFER_SIZE];
// Zero it out so we can check later that it's at least not all 0s.
memset(buffer, 0, BUFFER_SIZE);
bool buffer_contains_all_zeros = true;
// Don't bother passing any flags. (If we're using lss, we might not have the
// right header files with the flags defined anyway, and we'd have to copy
// this in here too, and risk getting out of sync in yet another way.)
const ssize_t r = sys_getrandom(buffer, BUFFER_SIZE, 0);
// Make sure it either worked, or that it's just not supported.
assert(r == BUFFER_SIZE || errno == ENOSYS);
if (r == BUFFER_SIZE) {
// If all the bytes are 0, it didn't really work.
for (size_t i = 0; i < BUFFER_SIZE; ++i) {
if (buffer[i] != 0) {
buffer_contains_all_zeros = false;
}
}
assert(!buffer_contains_all_zeros);
}
return 0;
}

View File

@ -0,0 +1,97 @@
/* Copyright 2021 Google LLC
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following disclaimer
* in the documentation and/or other materials provided with the
* distribution.
* * Neither the name of Google LLC nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "test_skel.h"
int main(int argc, char *argv[]) {
int exit_status = 0;
// Get two unique paths to play with.
char foo[] = "tempfile.XXXXXX";
char bar[] = "tempfile.XXXXXX";
int fd_foo = mkstemp(foo);
int fd_bar = mkstemp(bar);
assert(fd_foo != -1);
assert(fd_bar != -1);
// Then delete foo.
assert(sys_unlink(foo) == 0);
// Now make foo a symlink to bar.
assert(symlink(bar, foo) == 0);
// Make sure sys_stat() and sys_lstat() implementation return different
// information.
// We need to check our stat syscalls for EOVERFLOW, as sometimes the integer
// types used in the stat structures are too small to fit the actual value.
// E.g. on some systems st_ino is 32-bit, but some filesystems have 64-bit
// inodes.
struct kernel_stat lstat_info;
int rc = sys_lstat(foo, &lstat_info);
if (rc < 0 && errno == EOVERFLOW) {
// Bail out since we had an overflow in the stat structure.
exit_status = SKIP_TEST_EXIT_STATUS;
goto cleanup;
}
assert(rc == 0);
struct kernel_stat stat_info;
rc = sys_stat(foo, &stat_info);
if (rc < 0 && errno == EOVERFLOW) {
// Bail out since we had an overflow in the stat structure.
exit_status = SKIP_TEST_EXIT_STATUS;
goto cleanup;
}
assert(rc == 0);
struct kernel_stat bar_stat_info;
rc = sys_stat(bar, &bar_stat_info);
if (rc < 0 && errno == EOVERFLOW) {
// Bail out since we had an overflow in the stat structure.
exit_status = SKIP_TEST_EXIT_STATUS;
goto cleanup;
}
assert(rc == 0);
// lstat should produce information about a symlink.
assert((lstat_info.st_mode & S_IFMT) == S_IFLNK);
// stat-ing foo and bar should produce the same inode.
assert(stat_info.st_ino == bar_stat_info.st_ino);
// lstat-ing foo should give a different inode than stat-ing foo.
assert(stat_info.st_ino != lstat_info.st_ino);
cleanup:
sys_unlink(foo);
sys_unlink(bar);
return exit_status;
}

View File

@ -0,0 +1,90 @@
/* Copyright 2022 Google LLC
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following disclaimer
* in the documentation and/or other materials provided with the
* distribution.
* * Neither the name of Google LLC nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "test_skel.h"
int main(int argc, char *argv[]) {
// We need an invalid timer value. The assert()'s below should
// be static asserts but it is not avalible in older C versions.
#define kInvalidTimer 9999
assert(kInvalidTimer != ITIMER_REAL);
assert(kInvalidTimer != ITIMER_VIRTUAL);
assert(kInvalidTimer != ITIMER_PROF);
// Invalid timer returns EINVAL.
assert(sys_setitimer(kInvalidTimer, NULL, NULL) == -1);
assert(errno == EINVAL);
const int kSignal = SIGALRM;
const size_t kSigsetSize = sizeof(struct kernel_sigset_t);
// Block SIGALRM.
struct kernel_sigset_t sigalarm_only;
struct kernel_sigset_t old_sigset;
assert(sys_sigemptyset(&sigalarm_only) == 0);
assert(sys_sigaddset(&sigalarm_only, kSignal) == 0);
assert(sys_rt_sigprocmask(SIG_BLOCK, &sigalarm_only, &old_sigset,
kSigsetSize) == 0);
// Set up a real time timer.
struct kernel_itimerval new_itimer = {};
const long kIntervalUSec = 123;
new_itimer.it_interval.tv_sec = 0;
new_itimer.it_interval.tv_usec = kIntervalUSec;
new_itimer.it_value = new_itimer.it_interval;
assert(sys_setitimer(ITIMER_REAL, &new_itimer, NULL) == 0);
// Wait for alarm.
struct timespec timeout;
const unsigned long kNanoSecsPerSec = 1000000000;
const unsigned long kNanoSecsPerMicroSec = 1000;
// Use a timeout 3 times of the timer interval.
unsigned long duration_ns = kIntervalUSec * kNanoSecsPerMicroSec * 3;
timeout.tv_sec = duration_ns / kNanoSecsPerSec ;
timeout.tv_nsec = duration_ns % kNanoSecsPerSec;
int sig;
do {
sig = sys_sigtimedwait(&sigalarm_only, NULL, &timeout);
} while (sig == -1 && errno == EINTR);
assert(sig == kSignal);
// Disable timer, check saving of old timer value.
struct kernel_itimerval empty_itimer = {};
struct kernel_itimerval old_itimer;
empty_itimer.it_interval.tv_sec = 0;
empty_itimer.it_interval.tv_usec = 0;
empty_itimer.it_value = empty_itimer.it_interval;
assert(sys_setitimer(ITIMER_REAL, &empty_itimer, &old_itimer) == 0);
assert(kernel_timeval_eq(&old_itimer.it_interval, &new_itimer.it_interval));
return 0;
}

View File

@ -0,0 +1,54 @@
/* Copyright 2020 Google LLC
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following disclaimer
* in the documentation and/or other materials provided with the
* distribution.
* * Neither the name of Google LLC nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "test_skel.h"
void test_handler(int sig) {}
int main(int argc, char *argv[]) {
const size_t kSigsetSize = sizeof(struct kernel_sigset_t);
struct kernel_sigaction action = {};
// Invalid signal returns EINVAL.
assert(sys_rt_sigaction(SIGKILL, &action, NULL, kSigsetSize) == -1);
assert(errno == EINVAL);
// Set an action.
action.sa_handler_ = test_handler;
action.sa_flags = SA_SIGINFO;
assert(sys_sigemptyset(&action.sa_mask) == 0);
assert(sys_sigaddset(&action.sa_mask, SIGPIPE) == 0);
assert(sys_rt_sigaction(SIGSEGV, &action, NULL, kSigsetSize) == 0);
// Retrieve the action.
struct kernel_sigaction old_action = {};
assert(sys_rt_sigaction(SIGSEGV, NULL, &old_action, kSigsetSize) == 0);
assert(memcmp(&action, &old_action, sizeof(action)) == 0);
return 0;
}

View File

@ -0,0 +1,67 @@
/* Copyright 2021 Google LLC
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following disclaimer
* in the documentation and/or other materials provided with the
* distribution.
* * Neither the name of Google LLC nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "test_skel.h"
int main(int argc, char *argv[]) {
int exit_status = 0;
// Get two unique paths to play with.
char foo[] = "tempfile.XXXXXX";
int fd_foo = mkstemp(foo);
assert(fd_foo != -1);
// Make sure it exists.
assert(access(foo, F_OK) == 0);
// Make sure sys_stat() and a libc stat() implementation return the same
// information.
struct stat libc_stat;
assert(stat(foo, &libc_stat) == 0);
struct kernel_stat raw_stat;
// We need to check our stat syscall for EOVERFLOW, as sometimes the integer
// types used in the stat structures are too small to fit the actual value.
// E.g. on some systems st_ino is 32-bit, but some filesystems have 64-bit
// inodes.
int rc = sys_stat(foo, &raw_stat);
if (rc < 0 && errno == EOVERFLOW) {
// Bail out since we had an overflow in the stat structure.
exit_status = SKIP_TEST_EXIT_STATUS;
goto cleanup;
}
assert(rc == 0);
assert(libc_stat.st_ino == raw_stat.st_ino);
cleanup:
sys_unlink(foo);
return exit_status;
}

View File

@ -0,0 +1,54 @@
#include "sentry_options.h"
#include "sentry_testsupport.h"
SENTRY_TEST(options_sdk_name_defaults)
{
sentry_options_t *options = sentry_options_new();
// when nothing is set
// then both sdk name and user agent should default to the build time
// directives
TEST_CHECK_STRING_EQUAL(
sentry_options_get_sdk_name(options), SENTRY_SDK_NAME);
TEST_CHECK_STRING_EQUAL(
sentry_options_get_user_agent(options), SENTRY_SDK_USER_AGENT);
sentry_options_free(options);
}
SENTRY_TEST(options_sdk_name_custom)
{
sentry_options_t *options = sentry_options_new();
// when the sdk name is set to a custom string
const int result
= sentry_options_set_sdk_name(options, "sentry.native.android.flutter");
// both the sdk_name and user_agent should reflect this change
TEST_CHECK_INT_EQUAL(result, 0);
TEST_CHECK_STRING_EQUAL(
sentry_options_get_sdk_name(options), "sentry.native.android.flutter");
TEST_CHECK_STRING_EQUAL(sentry_options_get_user_agent(options),
"sentry.native.android.flutter/" SENTRY_SDK_VERSION);
sentry_options_free(options);
}
SENTRY_TEST(options_sdk_name_invalid)
{
sentry_options_t *options = sentry_options_new();
// when the sdk name is set to an invalid value
const char *sdk_name = NULL;
const int result = sentry_options_set_sdk_name(options, sdk_name);
// then the value should be ignored
TEST_CHECK_INT_EQUAL(result, 1);
TEST_CHECK_STRING_EQUAL(
sentry_options_get_sdk_name(options), SENTRY_SDK_NAME);
TEST_CHECK_STRING_EQUAL(
sentry_options_get_user_agent(options), SENTRY_SDK_USER_AGENT);
sentry_options_free(options);
}