add minimal support for aarch64 (#507)

Summary:
Pull Request resolved: https://github.com/facebookexperimental/object-introspection/pull/507

OI is currently completely incompatible with anything except `x86_64`. Changing that generally is a big effort, but `oilgen` should work on other architectures. Begin adding some support for `aarch64` architecture.

This change sets up a file structure for architecture support. It pulls the 2 functions needed to make `Descs.{h,cpp}` architecture agnostic into architecture specific files for `x86_64` and `aarch64`. This enables `oilgen` (the binary) to build. At this stage `oilgen` is unable to generate working code for `aarch64`, but at least this is a step in the right direction.

Differential Revision: D61661524
This commit is contained in:
Jake Hillion 2024-08-23 02:39:18 -07:00 committed by Facebook Community Bot
parent 8831269523
commit b7b9ac1536
8 changed files with 117 additions and 11 deletions

View File

@ -16,6 +16,8 @@ endif()
# Generate compile_commands.json to make it easier to work with clang based tools # Generate compile_commands.json to make it easier to work with clang based tools
set(CMAKE_EXPORT_COMPILE_COMMANDS ON) 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) option(ENABLE_IPO "Enable Interprocedural Optimization, aka Link Time Optimization (LTO)" OFF)

View File

@ -12,6 +12,8 @@ target_link_libraries(drgn_utils
add_library(symbol_service add_library(symbol_service
Descs.cpp Descs.cpp
SymbolService.cpp SymbolService.cpp
arch/aarch64.cpp
arch/x86_64.cpp
) )
target_link_libraries(symbol_service target_link_libraries(symbol_service
drgn_utils drgn_utils

View File

@ -38,18 +38,16 @@ std::ostream& operator<<(std::ostream& os, const FuncDesc::Range& r) {
* location?). * location?).
*/ */
std::optional<uintptr_t> FuncDesc::Arg::findAddress( std::optional<uintptr_t> FuncDesc::Arg::findAddress(
struct user_regs_struct* regs, uintptr_t pc) const { const user_regs_struct* regs, uintptr_t pc) const {
auto prevRip = std::exchange(regs->rip, pc); user_regs_struct modifiedRegs = *regs;
BOOST_SCOPE_EXIT_ALL(&) { oi::detail::arch::setProgramCounter(modifiedRegs, pc);
regs->rip = prevRip;
};
struct drgn_object object {}; struct drgn_object object {};
BOOST_SCOPE_EXIT_ALL(&) { BOOST_SCOPE_EXIT_ALL(&) {
drgn_object_deinit(&object); 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; LOG(ERROR) << "Error while finding address of argument: " << err->message;
drgn_error_destroy(err); drgn_error_destroy(err);
return std::nullopt; return std::nullopt;

View File

@ -20,6 +20,8 @@
#include <string> #include <string>
#include <vector> #include <vector>
#include "oi/arch/Arch.h"
extern "C" { extern "C" {
#include <drgn.h> #include <drgn.h>
} }
@ -103,7 +105,7 @@ struct FuncDesc {
* can be found at the given pc (what about if we don't have this * can be found at the given pc (what about if we don't have this
* location?). * location?).
*/ */
virtual std::optional<uintptr_t> findAddress(struct user_regs_struct* regs, virtual std::optional<uintptr_t> findAddress(const user_regs_struct* regs,
uintptr_t pc) const = 0; uintptr_t pc) const = 0;
}; };
@ -114,16 +116,16 @@ struct FuncDesc {
drgn_object_locator_deinit(&locator); drgn_object_locator_deinit(&locator);
} }
std::optional<uintptr_t> findAddress(struct user_regs_struct* regs, std::optional<uintptr_t> findAddress(const user_regs_struct* regs,
uintptr_t pc) const final; uintptr_t pc) const final;
}; };
struct Retval final : virtual TargetObject { struct Retval final : virtual TargetObject {
~Retval() final = default; ~Retval() final = default;
std::optional<uintptr_t> findAddress(struct user_regs_struct* regs, std::optional<uintptr_t> findAddress(const user_regs_struct* regs,
uintptr_t /* pc */) const final { uintptr_t /* pc */) const final {
return regs->rax; return oi::detail::arch::getReturnValueAddress(*regs);
} }
}; };
}; };

View File

@ -88,8 +88,9 @@ static struct LLVMInitializer {
llvm::InitializeNativeTargetAsmPrinter(); llvm::InitializeNativeTargetAsmPrinter();
llvm::InitializeNativeTargetDisassembler(); llvm::InitializeNativeTargetDisassembler();
std::string triple = llvm::sys::getProcessTriple();
disassemblerContext = LLVMCreateDisasm( disassemblerContext = LLVMCreateDisasm(
"x86_64-pc-linux", nullptr, 0, nullptr, symbolLookupCallback); triple.c_str(), nullptr, 0, nullptr, symbolLookupCallback);
if (!disassemblerContext) { if (!disassemblerContext) {
throw std::runtime_error("Failed to initialize disassemblerContext"); throw std::runtime_error("Failed to initialize disassemblerContext");
} }

29
oi/arch/Arch.h Normal file
View File

@ -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 <cstdint>
#include <optional>
struct user_regs_struct;
namespace oi::detail::arch {
void setProgramCounter(user_regs_struct& regs, uintptr_t pc);
std::optional<uintptr_t> getReturnValueAddress(const user_regs_struct&);
} // namespace oi::detail::arch

36
oi/arch/aarch64.cpp Normal file
View File

@ -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 <sys/user.h>
}
#include "Arch.h"
namespace oi::detail::arch {
std::optional<uintptr_t> 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

36
oi/arch/x86_64.cpp Normal file
View File

@ -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 <sys/user.h>
}
#include "Arch.h"
namespace oi::detail::arch {
std::optional<uintptr_t> 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