Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Use our own implementation of iig, take two #111

Open
wants to merge 19 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions .github/workflows/build-pr.yml
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,9 @@ jobs:
- name: Install Packages
run: |
export HOMEBREW_NO_INSTALLED_DEPENDENTS_CHECK=1
brew install openssl ninja
brew install openssl ninja llvm
- name: Build
run: |
mkdir build && cd build
cmake -G Ninja -DKERNEL_BUILD_XNU=1 -DOPENSSL_ROOT_DIR=/usr/local/opt/openssl ..
cmake -G Ninja -DKERNEL_BUILD_XNU=1 -DOPENSSL_ROOT_DIR=/usr/local/opt/openssl -DLLVM_ROOT_DIR=/usr/local/opt/llvm ..
ninja
6 changes: 6 additions & 0 deletions .vscode/settings.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
{
"cmake.configureEnvironment": {
"OPENSSL_ROOT_DIR": "/usr/local/opt/openssl"
},
"cmake.clearOutputBeforeBuild": false
}
2 changes: 2 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,8 @@ include(cmake/install_helpers.cmake)
include(cmake/kext.cmake)
include(cmake/mig.cmake)

list(APPEND CMAKE_MODULE_PATH ${PUREDARWIN_SOURCE_DIR}/cmake/modules)

add_subdirectory(projects)
add_subdirectory(src)
add_subdirectory(tools)
14 changes: 14 additions & 0 deletions cmake-variants.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
kernelType:
default: xnu
description: Kernel type to build
choices:
xnu:
short: XNU
long: XNU
settings:
KERNEL_BUILD_XNU: 1
fbsd:
short: FreeBSD
long: FreeBSD
settings:
KERNEL_BUILD_FREEBSD: 1
55 changes: 55 additions & 0 deletions cmake/modules/FindLLVM.cmake
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
# This file only searches for the parts of LLVM required by PureDarwin.

if(LLVM_ROOT_DIR)
if(DEFINED LLVM_VERSION)
find_program(LLVM_CONFIG llvm-config-${LLVM_VERSION} HINTS ${LLVM_ROOT_DIR}/bin NO_CMAKE_PATH)
endif()
if(NOT LLVM_CONFIG)
find_program(LLVM_CONFIG llvm-config HINTS ${LLVM_ROOT_DIR}/bin NO_CMAKE_PATH)
endif()
else()
if(DEFINED LLVM_VERSION)
message(STATUS "Using LLVM ${LLVM_VERSION}")
find_program(LLVM_CONFIG llvm-config-${LLVM_VERSION})
endif()
if(NOT LLVM_CONFIG)
find_program(LLVM_CONFIG llvm-config)
endif()
endif()

set(LLVM_CONFIG ${LLVM_CONFIG} CACHE PATH "Path to llvm-config executable")
mark_as_advanced(LLVM_CONFIG)

if(LLVM_CONFIG)
execute_process(COMMAND ${LLVM_CONFIG} --includedir OUTPUT_VARIABLE LLVM_INCLUDE_DIR OUTPUT_STRIP_TRAILING_WHITESPACE)
set(LLVM_INCLUDE_DIR ${LLVM_INCLUDE_DIR} CACHE PATH "Path to the LLVM headers")
mark_as_advanced(LLVM_INCLUDE_DIRS)

execute_process(COMMAND ${LLVM_CONFIG} --libdir OUTPUT_VARIABLE LLVM_LIBRARY_DIR OUTPUT_STRIP_TRAILING_WHITESPACE)
set(LLVM_LIBRARY_DIR ${LLVM_LIBRARY_DIR} CACHE PATH "Path to the LLVM lib directory")
mark_as_advanced(LLVM_LIBRARY_DIRS)

execute_process(COMMAND ${LLVM_CONFIG} --bindir OUTPUT_VARIABLE LLVM_BINARY_DIR OUTPUT_STRIP_TRAILING_WHITESPACE)
set(LLVM_BINARY_DIR ${LLVM_BINARY_DIR} CACHE PATH "Path to the LLVM bin directory")
else()
message(SEND_ERROR "Could not find llvm-config program in PATH (try setting LLVM_ROOT_DIR)")
endif()

if(LLVM_BINARY_DIR)
find_program(LLVM_DSYMUTIL NAMES dsymutil llvm-dsymutil PATHS ${LLVM_BINARY_DIR})
message(STATUS "Found dsymutil: ${LLVM_DSYMUTIL}")
endif()
if(LLVM_LIBRARY_DIR)
find_library(LLVM_LIBCLANG NAMES libclang.dylib libclang.so PATHS ${LLVM_LIBRARY_DIR})
message(STATUS "Found libclang: ${LLVM_LIBCLANG}")
endif()

include(FindPackageHandleStandardArgs)
find_package_handle_standard_args(LLVM DEFAULT_MSG LLVM_LIBCLANG LLVM_DSYMUTIL
LLVM_INCLUDE_DIR LLVM_INCLUDE_DIR LLVM_LIBRARY_DIR)

if(LLVM_FOUND)
add_library(libclang_imported UNKNOWN IMPORTED)
set_property(TARGET libclang_imported APPEND PROPERTY IMPORTED_LOCATION ${LLVM_LIBCLANG})
set_property(TARGET libclang_imported APPEND PROPERTY INTERFACE_INCLUDE_DIRECTORIES ${LLVM_INCLUDE_DIR})
endif()
16 changes: 11 additions & 5 deletions src/Kernel/xnu/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,4 +1,8 @@
find_program(dsymutil_path NAMES dsymutil llvm-dsymutil REQUIRED)
find_package(LLVM REQUIRED)
if(NOT LLVM_DSYMUTIL)
# Otherwise CI would fail with a syntax error when calling dsymutil.
message(SEND_ERROR "Cannot locate dsymutil")
endif()

file(MAKE_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/xnu_header_install)
externalproject_add(xnu_headers.extproj
Expand All @@ -22,7 +26,8 @@ externalproject_add(xnu_headers.extproj
-D NMEDIT_PATH=$<TARGET_FILE:host_nmedit>
-D LIBTOOL_PATH=$<TARGET_FILE:host_libtool>
-D UNIFDEF_PATH=$<TARGET_FILE:unifdef>
-D DSYMUTIL_PATH=${dsymutil_path}
-D IIG_PATH=$<TARGET_FILE:host_iig>
-D DSYMUTIL_PATH=${LLVM_DSYMUTIL}
-P ${CMAKE_CURRENT_SOURCE_DIR}/preprocess_files.cmake
COMMAND
make -C <SOURCE_DIR> installhdrs ARCH_CONFIGS=X86_64 BUILD_LTO=0
Expand All @@ -35,7 +40,7 @@ externalproject_add(xnu_headers.extproj
)
add_dependencies(xnu_headers.extproj darwin_codesign_allocate
migcom host_strip host_lipo host_nm unifdef host_nmedit
ctfconvert.host ctfmerge.host availability.pl)
ctfconvert.host ctfmerge.host availability.pl host_iig)

add_library(xnu_headers INTERFACE)
add_dependencies(xnu_headers xnu_headers.extproj)
Expand Down Expand Up @@ -86,7 +91,8 @@ externalproject_add(xnu
-D NMEDIT_PATH=$<TARGET_FILE:host_nmedit>
-D LIBTOOL_PATH=$<TARGET_FILE:host_libtool>
-D UNIFDEF_PATH=$<TARGET_FILE:unifdef>
-D DSYMUTIL_PATH=${dsymutil_path}
-D IIG_PATH=$<TARGET_FILE:host_iig>
-D DSYMUTIL_PATH=${LLVM_DSYMUTIL}
-D FIREHOSE_KERNEL_LIBRARY_PATH=$<TARGET_FILE:libfirehose_kernel>
-D FIREHOSE_KERNEL_HEADER_PATH=$<TARGET_PROPERTY:libfirehose_kernel,INTERFACE_INCLUDE_DIRECTORIES>
-D PTHREAD_HEADER_PATH=$<TARGET_PROPERTY:pthread_common_headers,INTERFACE_INCLUDE_DIRECTORIES>
Expand All @@ -100,7 +106,7 @@ externalproject_add(xnu
USES_TERMINAL_CONFIGURE TRUE
USES_TERMINAL_BUILD TRUE
)
add_dependencies(xnu xnu_headers libfirehose_kernel darwin_codesign_allocate ctfconvert.host ctfmerge.host migcom host_strip host_lipo host_nm unifdef host_nmedit availability.pl darwin_ld)
add_dependencies(xnu xnu_headers libfirehose_kernel darwin_codesign_allocate ctfconvert.host ctfmerge.host migcom host_strip host_lipo host_nm unifdef host_nmedit availability.pl darwin_ld host_iig)

install(DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/xnu/System/Library/Frameworks/Kernel.framework/Versions/A/Resources DESTINATION System/Library/Frameworks/Kernel.framework/Versions/A COMPONENT BaseSystem)
install(DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/xnu/System/Library/Frameworks/Kernel.framework/Versions/A/Headers DESTINATION System/Library/Frameworks/Kernel.framework/Versions/A COMPONENT DeveloperTools)
Expand Down
2 changes: 1 addition & 1 deletion src/Kernel/xnu/cmake/MakeInc.cmd.in
Original file line number Diff line number Diff line change
Expand Up @@ -171,7 +171,7 @@ ifeq ($(MIGCC),)
export MIGCC := $(CC)
endif
ifeq ($(IIG),)
export IIG := false
export IIG := @IIG_PATH@
endif
ifeq ($(STRIP),)
export STRIP := @STRIP_PATH@
Expand Down
1 change: 1 addition & 0 deletions tools/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
add_subdirectory(cctools)
add_subdirectory(dtrace_ctf)
add_subdirectory(iig)
add_subdirectory(mig)
add_subdirectory(unifdef)
add_subdirectory(xar)
6 changes: 6 additions & 0 deletions tools/iig/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
find_package(LLVM REQUIRED)

add_executable(host_iig)
target_sources(host_iig PRIVATE iig.cpp)
target_link_libraries(host_iig PRIVATE libclang_imported)
set_property(TARGET host_iig PROPERTY CXX_STANDARD 14)
120 changes: 120 additions & 0 deletions tools/iig/iig.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,120 @@
#include "iig.h"

static void usage(const char *progname) {
std::cerr <<
"usage: " << progname <<
" --def <path/to/input.iig> --header <path/to/header.h> --impl <path/to/source.iig.cpp> -- <clang args>\n"
"note: The --edits, --log, --framework-name, and --deployment-target options from Apple iig are not "
"implemented and will be ignored" << std::endl;

exit(1);
}

int main(int argc, const char * argv[]) {
int exitCode = 0;
string inputFilePath, headerOutputPath, implOutputPath;
string clangFlags; bool seenDashDash = false;

for (int i = 1; i < argc; i++) {
if (seenDashDash) {
clangFlags += argv[i];
clangFlags += " ";
} else if (strequal(argv[i], "--def")) {
if (++i == argc) {
std::cerr << "iig: error: --def option requires an argument" << std::endl;
usage(argv[0]);
}

inputFilePath = argv[i];
} else if (strequal(argv[i], "--header")) {
if (++i == argc) {
std::cerr << "iig: error: --header option requires an argument" << std::endl;
usage(argv[0]);
}

headerOutputPath = argv[i];
} else if (strequal(argv[i], "--impl")) {
if (++i == argc) {
std::cerr << "iig: error: --impl option requires an argument" << std::endl;
usage(argv[0]);
}

implOutputPath = argv[i];
} else if (strequal(argv[i], "--edits") || strequal(argv[i], "--log") || strequal(argv[i], "--framework-name") || strequal(argv[i], "--deployment-target")) {
if (++i == argc) {
std::cerr << "iig: error: " << argv[i] << " option requires an argument" << std::endl;
usage(argv[0]);
}

// These options are unimplemented and ignored.
} else if (strequal(argv[i], "--help")) {
usage(argv[0]);
} else if (strequal(argv[i], "--")) {
seenDashDash = true;
} else {
std::cerr << "iig: error: unrecognized option: " << argv[i] << std::endl;
usage(argv[0]);
}
}

if (inputFilePath.empty()) {
std::cerr << "iig: error: input file not specified" << std::endl;
usage(argv[0]);
} else if (headerOutputPath.empty()) {
std::cerr << "iig: error: output header file not specified" << std::endl;
usage(argv[0]);
} else if (implOutputPath.empty()) {
std::cerr << "iig: error: output source file not specified" << std::endl;
usage(argv[0]);
}

CXIndex index = clang_createIndex(0, 0);
const char *clangFlagsStr = clangFlags.c_str();
CXTranslationUnit source = clang_createTranslationUnitFromSourceFile(index, inputFilePath.c_str(), 1, &clangFlagsStr, 0, nullptr);

size_t num_diags = clang_getNumDiagnostics(source);
if (num_diags > 0) {
bool found_error = false;
for (size_t diag_index = 0; diag_index < num_diags; diag_index++) {
auto diag = clang_getDiagnostic(source, diag_index);

const char *severity = nullptr;
switch (clang_getDiagnosticSeverity(diag)) {
case CXDiagnostic_Fatal:
severity = "fatal error";
break;
case CXDiagnostic_Error:
severity = "error";
found_error = true;
break;
case CXDiagnostic_Warning:
severity = "warning";
break;
case CXDiagnostic_Note:
severity = "note";
break;
default:
assertion_failure("unknown CXDiagnosticSeverity");
break;
}

auto text = clang_formatDiagnostic(diag, CXDiagnostic_DisplaySourceLocation);
std::cerr << "iig: " << severity << ": " << text << std::endl;
clang_disposeString(text);

if (clang_getDiagnosticSeverity(diag) == CXDiagnostic_Fatal) {
exit(1);
}

clang_disposeDiagnostic(diag);
}

if (found_error) exit(1);
}

std::cerr << "iig: fatal error: iig is not implemented at this time." << std::endl;
exitCode = -1;

clang_disposeIndex(index);
return exitCode;
}
25 changes: 25 additions & 0 deletions tools/iig/iig.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
#pragma once

#include <iostream>
#include <string>
#include <vector>

#include <clang-c/Index.h>

using namespace std;

inline bool strequal(const char *s1, const char *s2) {
return strcmp(s1, s2) == 0;
}

inline bool strnequal(const char *s1, const char *s2, size_t n) {
return strncmp(s1, s2, n) == 0;
}

inline ostream& operator <<(ostream& stream, CXString string) {
const char *str = clang_getCString(string);
stream << str;
return stream;
}

#define assertion_failure(msg) __assert_rtn(__func__, __FILE__, __LINE__, msg)