diff --git a/cmake/StandardProjectSettings.cmake b/cmake/StandardProjectSettings.cmake index 77519bb..8298898 100644 --- a/cmake/StandardProjectSettings.cmake +++ b/cmake/StandardProjectSettings.cmake @@ -16,6 +16,8 @@ endif() # Generate compile_commands.json to make it easier to work with clang based tools set(CMAKE_EXPORT_COMPILE_COMMANDS ON) +# Include implicit directories in the compile commands file +set(CMAKE_CXX_STANDARD_INCLUDE_DIRECTORIES ${CMAKE_CXX_IMPLICIT_INCLUDE_DIRECTORIES}) option(ENABLE_IPO "Enable Interprocedural Optimization, aka Link Time Optimization (LTO)" OFF) diff --git a/oi/CMakeLists.txt b/oi/CMakeLists.txt index 7d805e5..7080245 100644 --- a/oi/CMakeLists.txt +++ b/oi/CMakeLists.txt @@ -12,6 +12,8 @@ target_link_libraries(drgn_utils add_library(symbol_service Descs.cpp SymbolService.cpp + arch/aarch64.cpp + arch/x86_64.cpp ) target_link_libraries(symbol_service drgn_utils diff --git a/oi/Descs.cpp b/oi/Descs.cpp index c750eae..d384057 100644 --- a/oi/Descs.cpp +++ b/oi/Descs.cpp @@ -38,18 +38,16 @@ std::ostream& operator<<(std::ostream& os, const FuncDesc::Range& r) { * location?). */ std::optional FuncDesc::Arg::findAddress( - struct user_regs_struct* regs, uintptr_t pc) const { - auto prevRip = std::exchange(regs->rip, pc); - BOOST_SCOPE_EXIT_ALL(&) { - regs->rip = prevRip; - }; + const user_regs_struct* regs, uintptr_t pc) const { + user_regs_struct modifiedRegs = *regs; + oi::detail::arch::setProgramCounter(modifiedRegs, pc); struct drgn_object object {}; BOOST_SCOPE_EXIT_ALL(&) { drgn_object_deinit(&object); }; - if (auto* err = drgn_object_locate(&locator, regs, &object)) { + if (auto* err = drgn_object_locate(&locator, &modifiedRegs, &object)) { LOG(ERROR) << "Error while finding address of argument: " << err->message; drgn_error_destroy(err); return std::nullopt; diff --git a/oi/Descs.h b/oi/Descs.h index b41c94c..32f2eab 100644 --- a/oi/Descs.h +++ b/oi/Descs.h @@ -20,6 +20,8 @@ #include #include +#include "oi/arch/Arch.h" + extern "C" { #include } @@ -103,7 +105,7 @@ struct FuncDesc { * can be found at the given pc (what about if we don't have this * location?). */ - virtual std::optional findAddress(struct user_regs_struct* regs, + virtual std::optional findAddress(const user_regs_struct* regs, uintptr_t pc) const = 0; }; @@ -114,16 +116,16 @@ struct FuncDesc { drgn_object_locator_deinit(&locator); } - std::optional findAddress(struct user_regs_struct* regs, + std::optional findAddress(const user_regs_struct* regs, uintptr_t pc) const final; }; struct Retval final : virtual TargetObject { ~Retval() final = default; - std::optional findAddress(struct user_regs_struct* regs, + std::optional findAddress(const user_regs_struct* regs, uintptr_t /* pc */) const final { - return regs->rax; + return oi::detail::arch::getReturnValueAddress(*regs); } }; }; diff --git a/oi/OICompiler.cpp b/oi/OICompiler.cpp index d824e6c..a36941c 100644 --- a/oi/OICompiler.cpp +++ b/oi/OICompiler.cpp @@ -88,8 +88,9 @@ static struct LLVMInitializer { llvm::InitializeNativeTargetAsmPrinter(); llvm::InitializeNativeTargetDisassembler(); + std::string triple = llvm::sys::getProcessTriple(); disassemblerContext = LLVMCreateDisasm( - "x86_64-pc-linux", nullptr, 0, nullptr, symbolLookupCallback); + triple.c_str(), nullptr, 0, nullptr, symbolLookupCallback); if (!disassemblerContext) { throw std::runtime_error("Failed to initialize disassemblerContext"); } diff --git a/oi/arch/Arch.h b/oi/arch/Arch.h new file mode 100644 index 0000000..40648bb --- /dev/null +++ b/oi/arch/Arch.h @@ -0,0 +1,29 @@ +/* + * Copyright (c) Meta Platforms, Inc. and affiliates. + * + * 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 +#include + +struct user_regs_struct; + +namespace oi::detail::arch { + +void setProgramCounter(user_regs_struct& regs, uintptr_t pc); + +std::optional getReturnValueAddress(const user_regs_struct&); + +} // namespace oi::detail::arch diff --git a/oi/arch/aarch64.cpp b/oi/arch/aarch64.cpp new file mode 100644 index 0000000..6c0e276 --- /dev/null +++ b/oi/arch/aarch64.cpp @@ -0,0 +1,36 @@ +/* + * Copyright (c) Meta Platforms, Inc. and affiliates. + * + * 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. + */ +#ifdef __aarch64__ + +extern "C" { +#include +} + +#include "Arch.h" + +namespace oi::detail::arch { + +std::optional getReturnValueAddress(const user_regs_struct& regs) { + return regs.regs[0]; +} + +void setProgramCounter(user_regs_struct& regs, uintptr_t pc) { + regs.pc = pc; +} + +} // namespace oi::detail::arch + +#endif diff --git a/oi/arch/x86_64.cpp b/oi/arch/x86_64.cpp new file mode 100644 index 0000000..dce8453 --- /dev/null +++ b/oi/arch/x86_64.cpp @@ -0,0 +1,36 @@ +/* + * Copyright (c) Meta Platforms, Inc. and affiliates. + * + * 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. + */ +#ifdef __x86_64__ + +extern "C" { +#include +} + +#include "Arch.h" + +namespace oi::detail::arch { + +std::optional getReturnValueAddress(const user_regs_struct& regs) { + return regs.rax; +} + +void setProgramCounter(user_regs_struct& regs, uintptr_t pc) { + regs.rip = pc; +} + +} // namespace oi::detail::arch + +#endif