clang-format: disable bin packing

Bin packing often makes code hard to read. Disable it entirely.

Test plan:
- CI
This commit is contained in:
Jake Hillion 2023-11-13 08:50:09 -08:00 committed by Jake Hillion
parent c207972af6
commit 393f8aab42
45 changed files with 668 additions and 358 deletions

View File

@ -9,3 +9,4 @@ AllowShortLoopsOnASingleLine: false
DerivePointerAlignment: false
PointerAlignment: Left
BinPackParameters: false
BinPackArguments: false

View File

@ -39,10 +39,17 @@ class CSV {
static constexpr std::string_view kEscapedQuote = "\\\"";
static constexpr std::string_view kListDelimiter = ";";
static constexpr std::string_view kColumns[] = {
"id", "name", "typePath", "typeNames",
"staticSize", "exclusiveSize", "pointer", "length",
"capacity", "is_set", "parent_id"};
static constexpr std::string_view kColumns[] = {"id",
"name",
"typePath",
"typeNames",
"staticSize",
"exclusiveSize",
"pointer",
"length",
"capacity",
"is_set",
"parent_id"};
size_t id_ = 0;
std::vector<size_t> parentIdStack_ = {0};

View File

@ -194,12 +194,12 @@ namespace {
size_t calculateExclusiveSize(const Type& t) {
if (const auto* c = dynamic_cast<const Class*>(&t)) {
return std::accumulate(c->members.cbegin(), c->members.cend(), 0,
[](size_t a, const auto& m) {
if (m.name.starts_with(AddPadding::MemberPrefix))
return a + m.type().size();
return a;
});
return std::accumulate(
c->members.cbegin(), c->members.cend(), 0, [](size_t a, const auto& m) {
if (m.name.starts_with(AddPadding::MemberPrefix))
return a + m.type().size();
return a;
});
}
return t.size();
}
@ -1087,8 +1087,8 @@ constexpr inst::Field make_field(std::string_view name) {
TemplateParam{typeGraph.makeType<Primitive>(Primitive::Kind::UInt64),
"0"},
};
genContainerTypeHandler(features, used, FuncGen::GetOiArrayContainerInfo(),
arrayParams, code);
genContainerTypeHandler(
features, used, FuncGen::GetOiArrayContainerInfo(), arrayParams, code);
}
} // namespace
@ -1098,12 +1098,17 @@ void CodeGen::addTypeHandlers(const TypeGraph& typeGraph, std::string& code) {
if (const auto* c = dynamic_cast<const Class*>(&t)) {
genClassTypeHandler(*c, code);
} else if (const auto* con = dynamic_cast<const Container*>(&t)) {
genContainerTypeHandler(config_.features, definedContainers_,
con->containerInfo_, con->templateParams, code);
genContainerTypeHandler(config_.features,
definedContainers_,
con->containerInfo_,
con->templateParams,
code);
} else if (const auto* cap = dynamic_cast<const CaptureKeys*>(&t)) {
genContainerTypeHandler(config_.features, definedContainers_,
genContainerTypeHandler(config_.features,
definedContainers_,
cap->containerInfo(),
cap->container().templateParams, code);
cap->container().templateParams,
code);
}
}
}
@ -1301,7 +1306,8 @@ void CodeGen::generate(
}
if (config_.features[Feature::TreeBuilderV2]) {
FuncGen::DefineTreeBuilderInstructions(code, typeName,
FuncGen::DefineTreeBuilderInstructions(code,
typeName,
calculateExclusiveSize(rootType),
enumerateTypeNames(rootType));
} else if (config_.features[Feature::TreeBuilderTypeChecking]) {

View File

@ -215,8 +215,8 @@ std::optional<FeatureSet> processConfigFile(
auto* members = (*captureKeys)["members"].as_array();
if (!members) {
generatorConfig.keysToCapture.push_back(
OICodeGen::Config::KeyToCapture{type->value_or(""), "*",
false});
OICodeGen::Config::KeyToCapture{
type->value_or(""), "*", false});
} else {
for (auto&& member : *members) {
generatorConfig.keysToCapture.push_back(
@ -226,8 +226,8 @@ std::optional<FeatureSet> processConfigFile(
}
} else if (topLevel) {
generatorConfig.keysToCapture.push_back(
OICodeGen::Config::KeyToCapture{std::nullopt, std::nullopt,
true});
OICodeGen::Config::KeyToCapture{
std::nullopt, std::nullopt, true});
}
}
}

View File

@ -323,6 +323,8 @@ ContainerInfo::ContainerInfo(std::string typeName_,
matcher(getMatcher(typeName)),
ctype(ctype_),
header(std::move(header_)),
codegen(Codegen{"// DummyDecl %1%\n", "// DummyFunc %1%\n",
"// DummyHandler %1%\n", "// DummyFunc\n"}) {
codegen(Codegen{"// DummyDecl %1%\n",
"// DummyFunc %1%\n",
"// DummyHandler %1%\n",
"// DummyFunc\n"}) {
}

View File

@ -800,7 +800,8 @@ void FuncGen::DefineBasicTypeHandlers(std::string& code, FeatureSet features) {
}
ContainerInfo FuncGen::GetOiArrayContainerInfo() {
ContainerInfo oiArray{"OIArray", UNKNOWN_TYPE,
ContainerInfo oiArray{"OIArray",
UNKNOWN_TYPE,
"cstdint"}; // TODO: remove the need for a dummy header
oiArray.codegen.handler = R"(

View File

@ -130,8 +130,11 @@ void Tracing::stop() {
std::lock_guard<std::mutex> guard{static_.mutex};
// Can't use emplace_back() because of old clang++ on CI
static_.traces.push_back({getNextIndex(), std::move(traceName),
duration.count(), rssBeforeBytes, rssAfterBytes});
static_.traces.push_back({getNextIndex(),
std::move(traceName),
duration.count(),
rssBeforeBytes,
rssAfterBytes});
}
void Tracing::saveTraces(const std::filesystem::path& output) {

View File

@ -204,8 +204,8 @@ std::string OICodeGen::preProcessUniquePtr(drgn_type* type, std::string name) {
} else if (typeSize == cFunctionDeleterSize) {
name.replace(begin, end - begin + 1, "void(*)(" + typeName + "*)");
} else if (typeSize == stdFunctionDeleterSize) {
name.replace(begin, end - begin + 1,
"std::function<void (" + typeName + "*)>");
name.replace(
begin, end - begin + 1, "std::function<void (" + typeName + "*)>");
} else {
LOG(ERROR) << "Unhandled case, unique_ptr size: " << typeSize;
}
@ -540,8 +540,8 @@ bool OICodeGen::buildNameInt(drgn_type* type,
templateParamsStrings.push_back(templateParamName);
}
replaceTemplateParameters(type, templateParams, templateParamsStrings,
nameWithoutTemplate);
replaceTemplateParameters(
type, templateParams, templateParamsStrings, nameWithoutTemplate);
outName = nameWithoutTemplate;
for (size_t i = 0; i < templateParamsStrings.size(); ++i) {
@ -765,8 +765,9 @@ bool OICodeGen::enumerateTemplateParamIdxs(drgn_type* type,
auto& templateTypes =
containerTypeMapDrgn
.emplace(type, std::pair(std::ref(containerInfo),
std::vector<drgn_qualified_type>()))
.emplace(type,
std::pair(std::ref(containerInfo),
std::vector<drgn_qualified_type>()))
.first->second.second;
for (auto i : paramIdxs) {
@ -1721,8 +1722,8 @@ void OICodeGen::enumerateDescendants(drgn_type* type, drgn_type* baseType) {
// TODO this list may end up containing duplicates
const auto& children = it->second;
descendantClasses[baseType].insert(descendantClasses[baseType].end(),
children.begin(), children.end());
descendantClasses[baseType].insert(
descendantClasses[baseType].end(), children.begin(), children.end());
for (const auto& child : children) {
enumerateDescendants(child, baseType);
@ -1878,7 +1879,8 @@ void OICodeGen::memberTransformName(
sortedTypes.push_back(e.first);
}
std::sort(sortedTypes.begin(), sortedTypes.end(),
std::sort(sortedTypes.begin(),
sortedTypes.end(),
[](const std::string& first, const std::string& second) {
return first.size() > second.size();
});
@ -2212,8 +2214,13 @@ bool OICodeGen::generateStructDef(drgn_type* e, std::string& code) {
uint64_t offsetBits = 0;
std::unordered_map<std::string, int> memberNames;
if (!generateStructMembers(e, memberNames, generatedMembers, offsetBits,
paddingInfo, violatesAlignmentRequirement, 0)) {
if (!generateStructMembers(e,
memberNames,
generatedMembers,
offsetBits,
paddingInfo,
violatesAlignmentRequirement,
0)) {
return false;
}
@ -2471,8 +2478,8 @@ std::optional<uint64_t> OICodeGen::generateMember(
currOffsetBits = 0;
VLOG(1) << "Member size: " << memberSize;
} else {
addSizeComment(feature(Feature::GenPaddingStats), code, currOffsetBits,
memberSize);
addSizeComment(
feature(Feature::GenPaddingStats), code, currOffsetBits, memberSize);
currOffsetBits = currOffsetBits + memberSize;
}
@ -2499,8 +2506,12 @@ bool OICodeGen::generateParent(
auto* underlyingType = drgn_utils::underlyingType(p);
uint64_t offsetBits = 0;
if (!generateStructMembers(underlyingType, memberNames, code, offsetBits,
paddingInfo, violatesAlignmentRequirement,
if (!generateStructMembers(underlyingType,
memberNames,
code,
offsetBits,
paddingInfo,
violatesAlignmentRequirement,
offsetToNextMember)) {
return false;
}
@ -2657,8 +2668,11 @@ bool OICodeGen::generateStructMembers(
size_t prevOffsetBits = currOffsetBits;
auto newCurrOffsetBits =
generateMember(members[memberIndex], memberNames, currOffsetBits,
code, drgn_type_kind(e) == DRGN_TYPE_UNION);
generateMember(members[memberIndex],
memberNames,
currOffsetBits,
code,
drgn_type_kind(e) == DRGN_TYPE_UNION);
if (!newCurrOffsetBits.has_value()) {
return false;
@ -2770,8 +2784,11 @@ bool OICodeGen::generateStructMembers(
}
}
if (!generateParent(parentClasses[e][parentIndex].type, memberNames,
currOffsetBits, code, offsetToNextMember)) {
if (!generateParent(parentClasses[e][parentIndex].type,
memberNames,
currOffsetBits,
code,
offsetToNextMember)) {
return false;
}
@ -2869,8 +2886,8 @@ bool OICodeGen::generateStructDefs(std::string& code) {
if (parentClassesCopy.find(e) != parentClassesCopy.end()) {
auto& parents = parentClassesCopy[e];
for (auto& p : parents) {
auto it2 = std::find(structDefTypeCopy.begin(),
structDefTypeCopy.end(), p.type);
auto it2 = std::find(
structDefTypeCopy.begin(), structDefTypeCopy.end(), p.type);
if (it2 != structDefTypeCopy.cend()) {
skip = true;
break;
@ -2886,7 +2903,8 @@ bool OICodeGen::generateStructDefs(std::string& code) {
if (underlyingType != e) {
auto it2 = std::find(structDefTypeCopy.begin(),
structDefTypeCopy.end(), underlyingType);
structDefTypeCopy.end(),
underlyingType);
if (it2 != structDefTypeCopy.cend()) {
skip = true;
break;
@ -3204,8 +3222,8 @@ bool OICodeGen::generateJitCode(std::string& code) {
std::string functionsCode;
functionsCode.append("namespace OIInternal {\nnamespace {\n");
functionsCode.append("// functions -----\n");
if (!funcGen.DeclareGetSizeFuncs(functionsCode, containerTypesFuncDef,
config.features)) {
if (!funcGen.DeclareGetSizeFuncs(
functionsCode, containerTypesFuncDef, config.features)) {
LOG(ERROR) << "declaring get size for containers failed";
return false;
}
@ -3235,8 +3253,8 @@ bool OICodeGen::generateJitCode(std::string& code) {
funcGen.DeclareEncodeData(functionsCode);
funcGen.DeclareEncodeDataSize(functionsCode);
if (!funcGen.DefineGetSizeFuncs(functionsCode, containerTypesFuncDef,
config.features)) {
if (!funcGen.DefineGetSizeFuncs(
functionsCode, containerTypesFuncDef, config.features)) {
LOG(ERROR) << "defining get size for containers failed";
return false;
}
@ -3289,8 +3307,8 @@ bool OICodeGen::generateJitCode(std::string& code) {
bool generateOffsetAsserts =
(drgn_type_kind(structType) != DRGN_TYPE_UNION);
if (!addStaticAssertsForType(structType, generateOffsetAsserts,
functionsCode)) {
if (!addStaticAssertsForType(
structType, generateOffsetAsserts, functionsCode)) {
return false;
}
}
@ -3328,11 +3346,11 @@ bool OICodeGen::generateJitCode(std::string& code) {
if (rootTypeStr.starts_with("unique_ptr") ||
rootTypeStr.starts_with("LowPtr") ||
rootTypeStr.starts_with("shared_ptr")) {
funcGen.DefineTopLevelGetSizeSmartPtr(functionsCode, rawTypeName,
config.features);
funcGen.DefineTopLevelGetSizeSmartPtr(
functionsCode, rawTypeName, config.features);
} else {
funcGen.DefineTopLevelGetSizeRef(functionsCode, rawTypeName,
config.features);
funcGen.DefineTopLevelGetSizeRef(
functionsCode, rawTypeName, config.features);
}
}
@ -3593,7 +3611,9 @@ bool OICodeGen::staticAssertMemberOffsets(
// Operate on the underlying type for typedefs
return staticAssertMemberOffsets(struct_name,
drgn_utils::underlyingType(struct_type),
assert_str, memberNames, base_offset);
assert_str,
memberNames,
base_offset);
}
const auto* tag = drgn_type_tag(struct_type);
@ -3606,8 +3626,11 @@ bool OICodeGen::staticAssertMemberOffsets(
// Recurse into parents to find inherited members
for (const auto& parent : parentClasses[struct_type]) {
auto parentOffset = base_offset + parent.bit_offset / CHAR_BIT;
if (!staticAssertMemberOffsets(struct_name, parent.type, assert_str,
memberNames, parentOffset)) {
if (!staticAssertMemberOffsets(struct_name,
parent.type,
assert_str,
memberNames,
parentOffset)) {
return false;
}
}

View File

@ -79,8 +79,8 @@ static struct LLVMInitializer {
llvm::InitializeNativeTargetAsmPrinter();
llvm::InitializeNativeTargetDisassembler();
disassemblerContext = LLVMCreateDisasm("x86_64-pc-linux", nullptr, 0,
nullptr, symbolLookupCallback);
disassemblerContext = LLVMCreateDisasm(
"x86_64-pc-linux", nullptr, 0, nullptr, symbolLookupCallback);
if (!disassemblerContext) {
throw std::runtime_error("Failed to initialize disassemblerContext");
}
@ -106,10 +106,13 @@ OICompiler::Disassembler::operator()() {
return std::nullopt;
}
size_t instSize = LLVMDisasmInstruction(
disassemblerContext, const_cast<uint8_t*>(std::data(funcText)),
std::size(funcText), 0, std::data(disassemblyBuffer),
std::size(disassemblyBuffer));
size_t instSize =
LLVMDisasmInstruction(disassemblerContext,
const_cast<uint8_t*>(std::data(funcText)),
std::size(funcText),
0,
std::data(disassemblyBuffer),
std::size(disassemblyBuffer));
if (instSize == 0) {
return std::nullopt;
}
@ -150,7 +153,9 @@ class OIMemoryManager : public RTDyldMemoryManager {
std::error_code errorCode;
auto mem = sys::Memory::allocateMappedMemory(
alignTo(totalSize + 256, 256), // Extra to fit paddings added below
nullptr, sys::Memory::MF_READ | sys::Memory::MF_WRITE, errorCode);
nullptr,
sys::Memory::MF_READ | sys::Memory::MF_WRITE,
errorCode);
/*
* It looks like report_fatal_error() calls exit() by default. If it's
@ -509,7 +514,9 @@ bool OICompiler::compile(const std::string& code,
for (const auto& path : config.userHeaderPaths) {
headerSearchOptions.AddPath(
path.c_str(), clang::frontend::IncludeDirGroup::IndexHeaderMap, false,
path.c_str(),
clang::frontend::IncludeDirGroup::IndexHeaderMap,
false,
false);
}
@ -518,22 +525,25 @@ bool OICompiler::compile(const std::string& code,
path.c_str(), clang::frontend::IncludeDirGroup::System, false, false);
}
static const auto syntheticHeaders = std::array<
std::pair<Feature, std::pair<std::string_view, std::string>>, 7>{{
{Feature::TypedDataSegment, {headers::oi_types_st_h, "oi/types/st.h"}},
{Feature::TreeBuilderTypeChecking,
{headers::oi_types_dy_h, "oi/types/dy.h"}},
{Feature::TreeBuilderV2,
{headers::oi_exporters_inst_h, "oi/exporters/inst.h"}},
{Feature::TreeBuilderV2,
{headers::oi_exporters_ParsedData_h, "oi/exporters/ParsedData.h"}},
{Feature::TreeBuilderV2,
{headers::oi_result_Element_h, "oi/result/Element.h"}},
{Feature::Library,
{headers::oi_IntrospectionResult_h, "oi/IntrospectionResult.h"}},
{Feature::Library,
{headers::oi_IntrospectionResult_inl_h, "oi/IntrospectionResult-inl.h"}},
}};
static const auto syntheticHeaders =
std::array<std::pair<Feature, std::pair<std::string_view, std::string>>,
7>{{
{Feature::TypedDataSegment,
{headers::oi_types_st_h, "oi/types/st.h"}},
{Feature::TreeBuilderTypeChecking,
{headers::oi_types_dy_h, "oi/types/dy.h"}},
{Feature::TreeBuilderV2,
{headers::oi_exporters_inst_h, "oi/exporters/inst.h"}},
{Feature::TreeBuilderV2,
{headers::oi_exporters_ParsedData_h, "oi/exporters/ParsedData.h"}},
{Feature::TreeBuilderV2,
{headers::oi_result_Element_h, "oi/result/Element.h"}},
{Feature::Library,
{headers::oi_IntrospectionResult_h, "oi/IntrospectionResult.h"}},
{Feature::Library,
{headers::oi_IntrospectionResult_inl_h,
"oi/IntrospectionResult-inl.h"}},
}};
for (const auto& [k, v] : syntheticHeaders) {
if (!config.features[k])
continue;
@ -546,7 +556,9 @@ bool OICompiler::compile(const std::string& code,
if (config.features[k]) {
headerSearchOptions.AddPath(
"/synthetic/headers",
clang::frontend::IncludeDirGroup::IndexHeaderMap, false, false);
clang::frontend::IncludeDirGroup::IndexHeaderMap,
false,
false);
break;
}
}
@ -657,9 +669,10 @@ std::optional<OICompiler::RelocResult> OICompiler::applyRelocs(
<< currentRelocAddress + offset;
}
res.relocInfos.push_back(RelocResult::RelocInfo{
(uintptr_t)slab.memBlock.base(), currentRelocAddress,
slab.memBlock.allocatedSize()});
res.relocInfos.push_back(
RelocResult::RelocInfo{(uintptr_t)slab.memBlock.base(),
currentRelocAddress,
slab.memBlock.allocatedSize()});
currentRelocAddress =
alignTo(currentRelocAddress + slab.memBlock.allocatedSize(), 128);
res.newBaseRelocAddr = currentRelocAddress;

View File

@ -108,51 +108,90 @@ enum ExitStatus {
constexpr static OIOpts opts{
OIOpt{'h', "help", no_argument, nullptr, "Print this message and exit"},
OIOpt{'p', "pid", required_argument, "<pid>",
"Target process to attach to"},
OIOpt{'c', "config-file", required_argument, nullptr,
"</path/to/oid.toml>"},
OIOpt{'x', "data-buf-size", required_argument, "<bytes>",
OIOpt{
'p', "pid", required_argument, "<pid>", "Target process to attach to"},
OIOpt{
'c', "config-file", required_argument, nullptr, "</path/to/oid.toml>"},
OIOpt{'x',
"data-buf-size",
required_argument,
"<bytes>",
"Size of data segment (default:1MB)\n"
"Accepts multiplicative suffix: K, M, G, T, P, E"},
OIOpt{'d', "debug-level", required_argument, "<level>",
OIOpt{'d',
"debug-level",
required_argument,
"<level>",
"Verbose level for logging"},
OIOpt{'r', "remove-mappings", no_argument, nullptr,
OIOpt{'r',
"remove-mappings",
no_argument,
nullptr,
"Remove oid mappings from target process"},
OIOpt{'s', "script", required_argument, nullptr, "</path/to/script.oid>"},
OIOpt{'S', "script-source", required_argument, nullptr, "type:symbol:arg"},
OIOpt{'t', "timeout", required_argument, "<seconds>",
OIOpt{'t',
"timeout",
required_argument,
"<seconds>",
"How long to probe the target process for"},
OIOpt{'k', "custom-code-file", required_argument, nullptr,
OIOpt{'k',
"custom-code-file",
required_argument,
nullptr,
"</path/to/code.cpp>\n"
"Use your own CPP file instead of CodeGen"},
OIOpt{'e', "compile-and-exit", no_argument, nullptr,
OIOpt{'e',
"compile-and-exit",
no_argument,
nullptr,
"Compile only then exit"},
OIOpt{'o', "cache-path", required_argument, "<path>",
OIOpt{'o',
"cache-path",
required_argument,
"<path>",
"Enable caching using the provided directory"},
OIOpt{'u', "cache-remote", required_argument, nullptr,
OIOpt{'u',
"cache-remote",
required_argument,
nullptr,
"Enable upload/download of cache files\n"
"Pick from {both,upload,download}"},
OIOpt{'i', "debug-path", required_argument, nullptr,
OIOpt{'i',
"debug-path",
required_argument,
nullptr,
"</path/to/binary>\n"
"Run oid on a executable with debug infos instead of a running "
"process"},
// Optional arguments are pretty nasty - it will only work as
// "--dump-json=PATH" and not "--dump-json PATH". Try and make this take a
// required argument at a later point
OIOpt{'J', "dump-json", optional_argument, "[oid_out.json]",
OIOpt{'J',
"dump-json",
optional_argument,
"[oid_out.json]",
"File to dump the results to, as JSON\n"
"(in addition to the default RocksDB output)"},
OIOpt{
'B', "dump-data-segment", no_argument, nullptr,
'B',
"dump-data-segment",
no_argument,
nullptr,
"Dump the data segment's content, before TreeBuilder processes it\n"
"Each argument gets its own dump file: 'dataseg.<oid-pid>.<arg>.dump'"},
OIOpt{'a', "log-all-structs", no_argument, nullptr, "Log all structures"},
OIOpt{'m', "mode", required_argument, "MODE",
OIOpt{'m',
"mode",
required_argument,
"MODE",
"Allows to specify a mode of operation/group of settings"},
OIOpt{'f', "enable-feature", required_argument, "FEATURE",
"Enable feature"},
OIOpt{'F', "disable-feature", required_argument, "FEATURE",
OIOpt{
'f', "enable-feature", required_argument, "FEATURE", "Enable feature"},
OIOpt{'F',
"disable-feature",
required_argument,
"FEATURE",
"Disable feature"},
};
@ -287,11 +326,11 @@ static ExitStatus::ExitStatus runScript(
std::shared_ptr<OIDebugger> oid; // share oid with the global signal handler
if (oidConfig.pid != 0) {
oid = std::make_shared<OIDebugger>(oidConfig.pid, codeGenConfig,
compilerConfig, tbConfig);
oid = std::make_shared<OIDebugger>(
oidConfig.pid, codeGenConfig, compilerConfig, tbConfig);
} else {
oid = std::make_shared<OIDebugger>(oidConfig.debugInfoFile, codeGenConfig,
compilerConfig, tbConfig);
oid = std::make_shared<OIDebugger>(
oidConfig.debugInfoFile, codeGenConfig, compilerConfig, tbConfig);
}
weak_oid = oid; // set the weak_ptr for signal handlers
@ -496,8 +535,8 @@ int main(int argc, char* argv[]) {
google::SetStderrLogging(google::WARNING);
int c = 0;
while ((c = getopt_long(argc, argv, opts.shortOpts(), opts.longOpts(),
nullptr)) != -1) {
while ((c = getopt_long(
argc, argv, opts.shortOpts(), opts.longOpts(), nullptr)) != -1) {
switch (c) {
case 'F':
[[fallthrough]];
@ -675,8 +714,8 @@ int main(int argc, char* argv[]) {
.jsonPath = jsonPath,
};
auto featureSet = config::processConfigFiles(oidConfig.configFiles, features,
compilerConfig, codeGenConfig);
auto featureSet = config::processConfigFiles(
oidConfig.configFiles, features, compilerConfig, codeGenConfig);
if (!featureSet) {
return ExitStatus::UsageError;
}
@ -690,15 +729,15 @@ int main(int argc, char* argv[]) {
return ExitStatus::FileNotFoundError;
}
std::ifstream script(scriptFile);
auto status = runScript(scriptFile, script, oidConfig, codeGenConfig,
compilerConfig, tbConfig);
auto status = runScript(
scriptFile, script, oidConfig, codeGenConfig, compilerConfig, tbConfig);
if (status != ExitStatus::Success) {
return status;
}
} else if (!scriptSource.empty()) {
std::istringstream script(scriptSource);
auto status = runScript(scriptFile, script, oidConfig, codeGenConfig,
compilerConfig, tbConfig);
auto status = runScript(
scriptFile, script, oidConfig, codeGenConfig, compilerConfig, tbConfig);
if (status != ExitStatus::Success) {
return status;
}

View File

@ -67,8 +67,9 @@ namespace oi::detail {
constexpr int oidMagicId = 0x01DE8;
bool OIDebugger::isGlobalDataProbeEnabled(void) const {
return std::any_of(cbegin(pdata), cend(pdata),
[](const auto& r) { return r.type == "global"; });
return std::any_of(cbegin(pdata), cend(pdata), [](const auto& r) {
return r.type == "global";
});
}
bool OIDebugger::parseScript(std::istream& script) {
@ -214,7 +215,8 @@ bool OIDebugger::setupLogFile(void) {
* The memory will be re-used anyway and the path will get overwritten.
*/
if (!writeTargetMemory((void*)logFilePath.c_str(),
(void*)segConfig.textSegBase, logFilePathLen)) {
(void*)segConfig.textSegBase,
logFilePathLen)) {
LOG(ERROR) << "Failed to write Log File's path into target process";
return false;
}
@ -381,9 +383,15 @@ void OIDebugger::deleteSegmentConfig(bool deleteSegConfigFile) {
*/
std::string OIDebugger::taskStateToString(OIDebugger::StatusType status) {
/* Must reflect the order of OIDebugger::StatusType enum */
static const std::array enumMapping{"SLEEP", "TRACED", "RUNNING",
"ZOMBIE", "DEAD", "DISK SLEEP",
"STOPPED", "OTHER", "BAD"};
static const std::array enumMapping{"SLEEP",
"TRACED",
"RUNNING",
"ZOMBIE",
"DEAD",
"DISK SLEEP",
"STOPPED",
"OTHER",
"BAD"};
return enumMapping[static_cast<int>(status)];
}
@ -583,7 +591,8 @@ bool OIDebugger::locateObjectsAddresses(const trapInfo& tInfo,
}
VLOG(4) << "Entry: arg addr: " << std::hex << *addr;
if (!writeTargetMemory((void*)(&addr.value()), (void*)remoteObjAddr->second,
if (!writeTargetMemory((void*)(&addr.value()),
(void*)remoteObjAddr->second,
sizeof(*addr))) {
LOG(ERROR) << "Entry: writeTargetMemory remoteObjAddr failed!";
ret = false;
@ -882,8 +891,8 @@ bool OIDebugger::processGlobal(const std::string& varName) {
return false;
}
if (!writeTargetMemory((void*)&addr, (void*)remoteObjAddr->second,
sizeof(addr))) {
if (!writeTargetMemory(
(void*)&addr, (void*)remoteObjAddr->second, sizeof(addr))) {
LOG(ERROR) << "processGlobal: writeTargetMemory remoteObjAddr failed!";
}
@ -1023,7 +1032,9 @@ OIDebugger::processTrapRet OIDebugger::processTrap(pid_t pid,
VLOG(4) << "child was stopped with: " << WSTOPSIG(tstatus);
}
ptrace(PTRACE_SETOPTIONS, childPid, NULL,
ptrace(PTRACE_SETOPTIONS,
childPid,
NULL,
PTRACE_O_TRACESYSGOOD | PTRACE_O_TRACEFORK | PTRACE_O_TRACECLONE |
PTRACE_O_TRACEVFORK);
@ -1230,8 +1241,9 @@ OIDebugger::processTrapRet OIDebugger::processTrap(pid_t pid,
std::optional<std::vector<uintptr_t>> OIDebugger::findRetLocs(FuncDesc& fd) {
size_t maxSize = std::accumulate(
fd.ranges.begin(), fd.ranges.end(), size_t(0),
[](auto currMax, auto& r) { return std::max(currMax, r.size()); });
fd.ranges.begin(), fd.ranges.end(), size_t(0), [](auto currMax, auto& r) {
return std::max(currMax, r.size());
});
std::vector<uintptr_t> retLocs;
std::vector<std::byte> text(maxSize);
@ -1384,8 +1396,9 @@ bool OIDebugger::functionPatch(const prequest& req) {
/* 1. Locate all TRAP points and create a corresponding empty trapInfo in
* tiVec */
bool hasArg = std::any_of(begin(req.args), end(req.args),
[](auto& arg) { return arg != "retval"; });
bool hasArg = std::any_of(begin(req.args), end(req.args), [](auto& arg) {
return arg != "retval";
});
if (req.type == "entry" || hasArg) {
trapType tType =
@ -1414,8 +1427,8 @@ bool OIDebugger::functionPatch(const prequest& req) {
}
for (auto addr : *retLocs) {
tiVec.push_back(std::make_shared<trapInfo>(OID_TRAP_VECT_RET, addr,
segConfig.textSegBase));
tiVec.push_back(std::make_shared<trapInfo>(
OID_TRAP_VECT_RET, addr, segConfig.textSegBase));
}
}
@ -1433,8 +1446,12 @@ bool OIDebugger::functionPatch(const prequest& req) {
}
errno = 0;
auto readBytes = process_vm_readv(traceePid, localIov.data(), localIov.size(),
remoteIov.data(), remoteIov.size(), 0);
auto readBytes = process_vm_readv(traceePid,
localIov.data(),
localIov.size(),
remoteIov.data(),
remoteIov.size(),
0);
if (readBytes < 0) {
LOG(ERROR) << "Failed to get original instructions: " << strerror(errno);
return false;
@ -1489,9 +1506,12 @@ bool OIDebugger::functionPatch(const prequest& req) {
/* 4. Save the original instructions in our Replay Instruction buffer */
errno = 0;
auto writtenBytes =
process_vm_writev(traceePid, localIov.data(), localIov.size(),
remoteIov.data(), remoteIov.size(), 0);
auto writtenBytes = process_vm_writev(traceePid,
localIov.data(),
localIov.size(),
remoteIov.data(),
remoteIov.size(),
0);
if (writtenBytes < 0) {
LOG(ERROR) << "Failed to save original instructions: " << strerror(errno);
return false;
@ -1588,8 +1608,12 @@ std::optional<typename Sys::RetType> OIDebugger::remoteSyscall(Args... _args) {
* x86-64 rdi rsi rdx r10 r8 r9 -
*/
const std::array<unsigned long long*, 6> argToReg = {
&newregs.rdi, &newregs.rsi, &newregs.rdx,
&newregs.r10, &newregs.r8, &newregs.r9,
&newregs.rdi,
&newregs.rsi,
&newregs.rdx,
&newregs.r10,
&newregs.r8,
&newregs.r9,
};
unsigned long long args[] = {(unsigned long long)_args...};
@ -1682,15 +1706,19 @@ bool OIDebugger::setupSegment(SegType seg) {
std::optional<void*> segAddr;
if (seg == SegType::text) {
segAddr =
remoteSyscall<SysMmap>(nullptr, textSegSize, // addr & size
remoteSyscall<SysMmap>(nullptr,
textSegSize, // addr & size
PROT_READ | PROT_WRITE | PROT_EXEC, // prot
MAP_PRIVATE | MAP_ANONYMOUS, // flags
-1, 0); // fd & offset
-1,
0); // fd & offset
} else {
segAddr = remoteSyscall<SysMmap>(nullptr, dataSegSize, // addr & size
segAddr = remoteSyscall<SysMmap>(nullptr,
dataSegSize, // addr & size
PROT_READ | PROT_WRITE, // prot
MAP_SHARED | MAP_ANONYMOUS, // flags
-1, 0); // fd & offset
-1,
0); // fd & offset
}
if (!segAddr.has_value()) {
@ -1835,13 +1863,16 @@ bool OIDebugger::removeTrap(pid_t pid, const trapInfo& t) {
break;
}
memcpy(repatchedBytes.data() + off, it->second->patchedTextBytes,
memcpy(repatchedBytes.data() + off,
it->second->patchedTextBytes,
windowSize - off);
}
}
VLOG(4) << "removeTrap removing int3 at " << std::hex << t.trapAddr;
if (ptrace(PTRACE_POKETEXT, (!pid ? traceePid : pid), t.trapAddr,
if (ptrace(PTRACE_POKETEXT,
(!pid ? traceePid : pid),
t.trapAddr,
*reinterpret_cast<uintptr_t*>(repatchedBytes.data())) < 0) {
LOG(ERROR) << "Execute: Couldn't poke text: " << strerror(errno);
return false;
@ -2120,8 +2151,8 @@ bool OIDebugger::writePrologue(
assert(off <= prologueLength);
return writeTargetMemory(&newInsts, (void*)segConfig.textSegBase,
prologueLength);
return writeTargetMemory(
&newInsts, (void*)segConfig.textSegBase, prologueLength);
}
/*
@ -2161,7 +2192,9 @@ bool OIDebugger::compileCode() {
} else {
LOG(INFO) << "Attempting to get cache request from gobs";
ObjectIntrospection::GobsService::requestCache(
procpath, std::string(buf, buf_size), req.toString(),
procpath,
std::string(buf, buf_size),
req.toString(),
generatorConfig.toOptions());
}
#endif
@ -2236,7 +2269,8 @@ bool OIDebugger::compileCode() {
}
const auto& [rootType, typeHierarchy, paddingInfo] = typeInfos.at(req);
cache.store(req, OICache::Entity::TypeHierarchy,
cache.store(req,
OICache::Entity::TypeHierarchy,
std::make_pair(rootType, typeHierarchy));
cache.store(req, OICache::Entity::PaddingInfo, paddingInfo);
}
@ -2256,8 +2290,8 @@ bool OIDebugger::compileCode() {
for (const auto& o : objectFiles) {
VLOG(2) << " * " << o;
}
auto relocRes = compiler.applyRelocs(segConfig.jitCodeStart, objectFiles,
syntheticSymbols);
auto relocRes = compiler.applyRelocs(
segConfig.jitCodeStart, objectFiles, syntheticSymbols);
if (!relocRes.has_value()) {
LOG(ERROR) << "Failed to relocate object code";
return false;
@ -2292,7 +2326,8 @@ bool OIDebugger::compileCode() {
return false;
}
if (!writeTargetMemory(&dataSegSize, (void*)syntheticSymbols["dataSize"],
if (!writeTargetMemory(&dataSegSize,
(void*)syntheticSymbols["dataSize"],
sizeof(dataSegSize))) {
LOG(ERROR) << "Failed to write dataSegSize in probe's dataSize";
return false;
@ -2307,8 +2342,8 @@ bool OIDebugger::compileCode() {
int logFile =
generatorConfig.features[Feature::JitLogging] ? segConfig.logFile : 0;
if (!writeTargetMemory(&logFile, (void*)syntheticSymbols["logFile"],
sizeof(logFile))) {
if (!writeTargetMemory(
&logFile, (void*)syntheticSymbols["logFile"], sizeof(logFile))) {
LOG(ERROR) << "Failed to write logFile in probe's cookieValue";
return false;
}
@ -2329,8 +2364,9 @@ void OIDebugger::restoreState(void) {
* Ensure we don't have any trap in the target process still active.
*/
const size_t activeTrapsCount = std::count_if(
activeTraps.cbegin(), activeTraps.cend(),
[](const auto& t) { return t.second->trapKind != OID_TRAP_JITCODERET; });
activeTraps.cbegin(), activeTraps.cend(), [](const auto& t) {
return t.second->trapKind != OID_TRAP_JITCODERET;
});
VLOG(1) << "Active traps still within the target process: "
<< activeTrapsCount;
assert(activeTrapsCount == 0);
@ -2562,7 +2598,9 @@ bool OIDebugger::targetAttach() {
* here (note: ptrace(2) overloads the ESRCH return but with a seize
* I think it can only mean one thing).
*/
if (ptrace(PTRACE_SEIZE, pid, NULL,
if (ptrace(PTRACE_SEIZE,
pid,
NULL,
PTRACE_O_TRACECLONE | PTRACE_O_TRACEFORK |
PTRACE_O_TRACEVFORK | PTRACE_O_TRACEEXIT) < 0) {
LOG(ERROR) << "Couldn't seize thread " << pid
@ -2750,9 +2788,11 @@ bool OIDebugger::decodeTargetData(const DataHeader& dataHeader,
static bool dumpDataSegment(const irequest& req,
const std::vector<uint64_t>& dataSeg) {
char dumpPath[PATH_MAX] = {0};
auto dumpPathSize =
snprintf(dumpPath, sizeof(dumpPath), "/tmp/dataseg.%d.%s.dump", getpid(),
req.arg.c_str());
auto dumpPathSize = snprintf(dumpPath,
sizeof(dumpPath),
"/tmp/dataseg.%d.%s.dump",
getpid(),
req.arg.c_str());
if (dumpPathSize < 0 || (size_t)dumpPathSize > sizeof(dumpPath)) {
LOG(ERROR) << "Failed to generate data-segment path";
return false;
@ -2781,7 +2821,8 @@ bool OIDebugger::processTargetData() {
std::vector<std::byte> buf{dataSegSize};
if (!readTargetMemory(reinterpret_cast<void*>(segConfig.dataSegBase),
buf.data(), dataSegSize)) {
buf.data(),
dataSegSize)) {
LOG(ERROR) << "Failed to read data segment from target process";
return false;
}
@ -2838,8 +2879,8 @@ bool OIDebugger::processTargetData() {
}
try {
typeTree.build(outVec, rootType.varName, rootType.type.type,
typeHierarchy);
typeTree.build(
outVec, rootType.varName, rootType.type.type, typeHierarchy);
} catch (std::exception& e) {
LOG(ERROR) << "Failed to run TreeBuilder for " << req.arg;
LOG(ERROR) << e.what();
@ -2901,7 +2942,8 @@ std::optional<std::string> OIDebugger::generateCode(const irequest& req) {
typeInfos.emplace(
req,
std::make_tuple(RootInfo{rootInfo.varName, codegen->getRootType()},
codegen->getTypeHierarchy(), codegen->getPaddingInfo()));
codegen->getTypeHierarchy(),
codegen->getPaddingInfo()));
if (generatorConfig.features[Feature::TypeGraph]) {
CodeGen codegen2{generatorConfig, *symbols};

View File

@ -113,7 +113,8 @@ class OIDebugger {
return std::all_of(
std::begin(pdata), std::end(pdata), [this](const auto& req) {
return std::all_of(
std::begin(req.args), std::end(req.args),
std::begin(req.args),
std::end(req.args),
[this, &req](const auto& arg) {
return cache.upload(irequest{req.type, req.func, arg});
});
@ -123,7 +124,8 @@ class OIDebugger {
return std::all_of(
std::begin(pdata), std::end(pdata), [this](const auto& req) {
return std::all_of(
std::begin(req.args), std::end(req.args),
std::begin(req.args),
std::end(req.args),
[this, &req](const auto& arg) {
return cache.download(irequest{req.type, req.func, arg});
});

View File

@ -169,9 +169,12 @@ int OIGenerator::generate(fs::path& primaryObject, SymbolService& symbols) {
{
std::array<const char*, 1> objectPaths = {{primaryObject.c_str()}};
if (auto err = drgnplusplus::error(drgn_program_load_debug_info(
prog.get(), std::data(objectPaths), std::size(objectPaths), false,
false))) {
if (auto err = drgnplusplus::error(
drgn_program_load_debug_info(prog.get(),
std::data(objectPaths),
std::size(objectPaths),
false,
false))) {
LOG(ERROR) << "error loading debug info program: " << err;
throw err;
}
@ -193,8 +196,8 @@ int OIGenerator::generate(fs::path& primaryObject, SymbolService& symbols) {
OICompiler::Config compilerConfig{};
compilerConfig.usePIC = pic;
auto features = config::processConfigFiles(configFilePaths, featuresMap,
compilerConfig, generatorConfig);
auto features = config::processConfigFiles(
configFilePaths, featuresMap, compilerConfig, generatorConfig);
if (!features) {
LOG(ERROR) << "failed to process config file";
return -1;
@ -204,8 +207,8 @@ int OIGenerator::generate(fs::path& primaryObject, SymbolService& symbols) {
size_t failures = 0;
for (const auto& [linkageName, type] : oilTypes) {
if (auto obj = generateForType(generatorConfig, compilerConfig, type,
linkageName, symbols);
if (auto obj = generateForType(
generatorConfig, compilerConfig, type, linkageName, symbols);
!obj.empty()) {
std::cout << obj.string() << std::endl;
} else {

View File

@ -40,8 +40,12 @@ drgn_qualified_type getTypeFromAtomicHole(drgn_program* prog, void* hole);
} // namespace
OILibraryImpl::LocalTextSegment::LocalTextSegment(size_t size) {
void* base = mmap(NULL, size, PROT_EXEC | PROT_READ | PROT_WRITE,
MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
void* base = mmap(NULL,
size,
PROT_EXEC | PROT_READ | PROT_WRITE,
MAP_PRIVATE | MAP_ANONYMOUS,
-1,
0);
if (base == MAP_FAILED)
throw std::runtime_error(std::string("segment map failed: ") +
std::strerror(errno));
@ -93,9 +97,10 @@ std::pair<void*, const exporters::inst::Inst&> OILibraryImpl::init() {
}
void OILibraryImpl::processConfigFile() {
auto features =
config::processConfigFiles(opts_.configFilePaths, requestedFeatures_,
compilerConfig_, generatorConfig_);
auto features = config::processConfigFiles(opts_.configFilePaths,
requestedFeatures_,
compilerConfig_,
generatorConfig_);
if (!features)
throw std::runtime_error("failed to process configuration");
@ -164,7 +169,8 @@ std::pair<void*, const exporters::inst::Inst&> OILibraryImpl::compileCode() {
for (const auto& [baseAddr, relocAddr, size] : segments)
std::memcpy(reinterpret_cast<void*>(relocAddr),
reinterpret_cast<void*>(baseAddr), size);
reinterpret_cast<void*>(baseAddr),
size);
textSeg.release(); // don't munmap() the region containing the code
return {fp, *ty};

View File

@ -80,7 +80,8 @@ class ParseData {
public:
void addReq(std::string type, std::string func, std::list<std::string> args) {
// Convert the args std::list into a more efficient std::vector
reqs.emplace_back(std::move(type), std::move(func),
reqs.emplace_back(std::move(type),
std::move(func),
std::vector(std::make_move_iterator(args.begin()),
std::make_move_iterator(args.end())));
}

View File

@ -49,7 +49,8 @@ void PaddingHunter::outputPaddingInfo() {
paddingStatsFile << "Total Saving Opportunity: " << sum << "\n\n\n";
std::sort(paddedStructsVec.begin(), paddedStructsVec.end(),
std::sort(paddedStructsVec.begin(),
paddedStructsVec.end(),
[](const std::pair<std::string, PaddingInfo>& left,
const std::pair<std::string, PaddingInfo>& right) {
return left.second.instancesCnt * left.second.savingSize >

View File

@ -66,7 +66,13 @@ static bool LoadExecutableAddressRange(
while (std::getline(f, line)) {
if (sscanf(line.c_str(),
"%" PRIx64 "-%" PRIx64 " %s %" PRIx64 " %x:%x %" PRIu64 " %n",
&start, &end, perm, &offset, &dmajor, &dminor, &inode,
&start,
&end,
perm,
&offset,
&dmajor,
&dminor,
&inode,
&nread) < 7 ||
nread <= 0) {
return false;
@ -92,7 +98,9 @@ static bool isExecutableAddr(
// Find the smallest exeAddrs range where addr < range.end
auto it = std::upper_bound(
begin(exeAddrs), end(exeAddrs), std::make_pair(addr, addr),
begin(exeAddrs),
end(exeAddrs),
std::make_pair(addr, addr),
[](const auto& r1, const auto& r2) { return r1.second < r2.second; });
return it != end(exeAddrs) && addr >= it->first;
@ -246,8 +254,9 @@ bool SymbolService::loadModulesFromPath(const fs::path& targetPath) {
Dwarf_Addr start = 0;
Dwarf_Addr end = 0;
if (dwfl_module_info(mod, nullptr, &start, &end, nullptr, nullptr, nullptr,
nullptr) == nullptr) {
if (dwfl_module_info(
mod, nullptr, &start, &end, nullptr, nullptr, nullptr, nullptr) ==
nullptr) {
LOG(ERROR) << "dwfl_module_info: " << dwfl_errmsg(dwfl_errno());
return false;
}
@ -442,8 +451,8 @@ struct drgn_program* SymbolService::getDrgnProgram() {
auto executable = fs::read_symlink(
"/proc/" + std::to_string(std::get<pid_t>(target)) + "/exe");
const auto* executableCStr = executable.c_str();
if (auto* err = drgn_program_load_debug_info(prog, &executableCStr, 1,
false, false)) {
if (auto* err = drgn_program_load_debug_info(
prog, &executableCStr, 1, false, false)) {
LOG(ERROR) << "Error loading debug info: " << err->message;
return nullptr;
}
@ -769,8 +778,11 @@ std::shared_ptr<GlobalDesc> SymbolService::findGlobalDesc(
drgn_object_deinit(&globalObj);
};
if (auto* err = drgn_program_find_object(drgnProg, global.c_str(), nullptr,
DRGN_FIND_OBJECT_ANY, &globalObj)) {
if (auto* err = drgn_program_find_object(drgnProg,
global.c_str(),
nullptr,
DRGN_FIND_OBJECT_ANY,
&globalObj)) {
LOG(ERROR) << "Failed to lookup global variable '" << global
<< "': " << err->code << " " << err->message;

View File

@ -455,7 +455,8 @@ TreeBuilder::Node TreeBuilder::process(NodeID id, Variable variable) {
auto childID = nextNodeID++;
auto child = process(childID, Variable{entry->second, "", ""});
node.children = {childID, childID + 1};
setSize(node, child.staticSize + child.dynamicSize,
setSize(node,
child.staticSize + child.dynamicSize,
child.staticSize + child.dynamicSize);
}
}
@ -477,8 +478,8 @@ TreeBuilder::Node TreeBuilder::process(NodeID id, Variable variable) {
auto childID = nextNodeID++;
auto child = process(childID, Variable{entry->second, "", ""});
node.children = {childID, childID + 1};
setSize(node, child.dynamicSize,
child.dynamicSize + child.staticSize);
setSize(
node, child.dynamicSize, child.dynamicSize + child.staticSize);
}
} break;
case DRGN_TYPE_CLASS:
@ -532,10 +533,12 @@ TreeBuilder::Node TreeBuilder::process(NodeID id, Variable variable) {
}
}
const auto& member = members[i];
auto child =
process(childID++,
Variable{member.type, member.member_name,
member.member_name, isset, member.isStubbed});
auto child = process(childID++,
Variable{member.type,
member.member_name,
member.member_name,
isset,
member.isStubbed});
node.dynamicSize += child.dynamicSize;
memberSizes += child.dynamicSize + child.staticSize;
}
@ -582,8 +585,8 @@ void TreeBuilder::processContainer(const Variable& variable, Node& node) {
arrayElementType = drgn_type_type(variable.type).type;
numElems = drgn_type_length(variable.type);
} else {
drgn_utils::getDrgnArrayElementType(variable.type, &arrayElementType,
numElems);
drgn_utils::getDrgnArrayElementType(
variable.type, &arrayElementType, numElems);
}
assert(numElems > 0);
elementTypes.push_back(
@ -675,10 +678,11 @@ void TreeBuilder::processContainer(const Variable& variable, Node& node) {
// elementTypes is only populated with the underlying container type for
// container adapters
auto containerType = elementTypes[0];
auto child = process(
childID++, {.type = containerType.type,
.name = "",
.typePath = drgnTypeToName(containerType.type) + "[]"});
auto child =
process(childID++,
{.type = containerType.type,
.name = "",
.typePath = drgnTypeToName(containerType.type) + "[]"});
setSize(node, child.dynamicSize, child.dynamicSize + child.staticSize);
node.containerStats = child.containerStats;
@ -715,10 +719,11 @@ void TreeBuilder::processContainer(const Variable& variable, Node& node) {
auto childID = node.children->first;
auto elementType = elementTypes[index];
auto child = process(
childID++, {.type = elementType.type,
.name = "",
.typePath = drgnTypeToName(elementType.type) + "[]"});
auto child =
process(childID++,
{.type = elementType.type,
.name = "",
.typePath = drgnTypeToName(elementType.type) + "[]"});
setSize(node, child.dynamicSize, child.dynamicSize + child.staticSize);
}
@ -879,8 +884,9 @@ void TreeBuilder::processContainer(const Variable& variable, Node& node) {
"uninitialized data in the target process");
}
if (std::ranges::all_of(
elementTypes.cbegin(), elementTypes.cend(),
[this](auto& type) { return isPrimitive(type.type); })) {
elementTypes.cbegin(), elementTypes.cend(), [this](auto& type) {
return isPrimitive(type.type);
})) {
VLOG(1)
<< "Container [" << node.id
<< "] contains only primitive types, skipping processing its members";
@ -900,10 +906,10 @@ void TreeBuilder::processContainer(const Variable& variable, Node& node) {
uint64_t memberSizes = 0;
for (size_t i = 0; i < containerStats.length; i++) {
for (auto& type : elementTypes) {
auto child =
process(childID++, {.type = type.type,
.name = "",
.typePath = drgnTypeToName(type.type) + "[]"});
auto child = process(childID++,
{.type = type.type,
.name = "",
.typePath = drgnTypeToName(type.type) + "[]"});
node.dynamicSize += child.dynamicSize;
memberSizes += child.dynamicSize + child.staticSize;
}

View File

@ -87,8 +87,8 @@ void Json::print(IntrospectionResult::const_iterator& it,
out_ << (pretty_ ? ",\n" : ",") << indent;
out_ << tab << "\"typeNames\"" << space << ':' << space;
printStringList(out_, it->type_names.begin(), it->type_names.end(),
pretty_);
printStringList(
out_, it->type_names.begin(), it->type_names.end(), pretty_);
out_ << ',' << endl << indent;
out_ << tab << "\"staticSize\":" << space << it->static_size << ',' << endl

View File

@ -145,8 +145,8 @@ TEST(TypeCheckingWalker, TestListEmpty) {
TEST(TypeCheckingWalker, TestListSome) {
// ASSIGN
std::array<uint64_t, 3> listElements{59942, 44126, 64525};
std::vector<uint64_t> data{listElements.size(), listElements[0],
listElements[1], listElements[2]};
std::vector<uint64_t> data{
listElements.size(), listElements[0], listElements[1], listElements[2]};
types::dy::VarInt varint;
types::dy::List rootType{varint};

View File

@ -123,8 +123,8 @@ void AddPadding::addPadding(uint64_t paddingStartBits,
if (paddingBits % 8 != 0) {
// Pad with a bitfield up to the next byte
paddedMembers.emplace_back(primitive, MemberPrefix, paddingStartBits,
paddingBits % 8);
paddedMembers.emplace_back(
primitive, MemberPrefix, paddingStartBits, paddingBits % 8);
}
uint64_t paddingBytes = paddingBits / 8;

View File

@ -180,8 +180,8 @@ Class& DrgnParser::enumerateClass(struct drgn_type* type) {
std::to_string(drgn_type_kind(type))};
}
auto& c = makeType<Class>(type, kind, std::move(name), std::move(fqName),
size, virtuality);
auto& c = makeType<Class>(
type, kind, std::move(name), std::move(fqName), size, virtuality);
enumerateClassTemplateParams(type, c.templateParams);
enumerateClassParents(type, c.parents);
@ -402,7 +402,8 @@ void DrgnParser::enumerateClassFunctions(struct drgn_type* type,
drgn_qualified_type t{};
if (auto* err = drgn_member_function_type(&drgn_functions[i], &t)) {
warnForDrgnError(
type, "Error looking up member function (" + std::to_string(i) + ")",
type,
"Error looking up member function (" + std::to_string(i) + ")",
err);
continue;
}

View File

@ -54,8 +54,8 @@ void flattenParent(const Parent& parent,
}
} else if (auto* parentContainer = dynamic_cast<Container*>(&parentType)) {
// Create a new member to represent this parent container
flattenedMembers.emplace_back(*parentContainer, Flattener::ParentPrefix,
parent.bitOffset);
flattenedMembers.emplace_back(
*parentContainer, Flattener::ParentPrefix, parent.bitOffset);
} else if (auto* parentPrimitive = dynamic_cast<Incomplete*>(&parentType)) {
// Bad DWARF can lead to us seeing incomplete parent types. Just ignore
// these as there is nothing we can do to recover the missing info.
@ -151,7 +151,8 @@ void Flattener::visit(Class& c) {
for (const auto& parent : c.parents) {
Type& parentType = stripTypedefs(parent.type());
if (Class* parentClass = dynamic_cast<Class*>(&parentType)) {
c.functions.insert(c.functions.end(), parentClass->functions.begin(),
c.functions.insert(c.functions.end(),
parentClass->functions.begin(),
parentClass->functions.end());
}
}
@ -201,8 +202,8 @@ void Flattener::visit(Class& c) {
// Pull in children from flattened children
// This may result in duplicates, but that shouldn't be a big deal
for (const Class& child : c.children) {
c.children.insert(c.children.end(), child.children.begin(),
child.children.end());
c.children.insert(
c.children.end(), child.children.begin(), child.children.end());
}
}

View File

@ -112,8 +112,8 @@ void TypeIdentifier::visit(Container& c) {
typeToAllocate, size, param.type().align(), allocator->name());
c.templateParams[i] = dummy;
} else {
auto& dummy = typeGraph_.makeType<Dummy>(size, param.type().align(),
param.type().name());
auto& dummy = typeGraph_.makeType<Dummy>(
size, param.type().align(), param.type().name());
c.templateParams[i] = dummy;
}
}

View File

@ -310,8 +310,8 @@ Type& TypeGraphParser::parseType(std::string_view& input, size_t rootIndent) {
auto size = parseNumericAttribute(line, nodeTypeName, "size: ");
std::string inputName{*tryParseInputName(line)};
auto& typeToAlloc = parseType(input, indent + 2);
type = &typeGraph_.makeType<DummyAllocator>(id, typeToAlloc, size, 0,
inputName);
type = &typeGraph_.makeType<DummyAllocator>(
id, typeToAlloc, size, 0, inputName);
} else {
throw TypeGraphParserError{"Unsupported node type: " +
std::string{nodeTypeName}};

View File

@ -35,17 +35,35 @@ std::vector<std::string> global_oid_args{};
constexpr static OIOpts cliOpts{
OIOpt{'h', "help", no_argument, nullptr, "Print this message and exit"},
OIOpt{'p', "preserve", no_argument, nullptr,
OIOpt{'p',
"preserve",
no_argument,
nullptr,
"Do not clean up files generated by OID after tests are finished"},
OIOpt{'P', "preserve-on-failure", no_argument, nullptr,
OIOpt{'P',
"preserve-on-failure",
no_argument,
nullptr,
"Do not clean up files generated by OID for failed tests"},
OIOpt{'v', "verbose", no_argument, nullptr,
OIOpt{'v',
"verbose",
no_argument,
nullptr,
"Verbose output. Show OID's stdout and stderr on test failure"},
OIOpt{'f', "force", no_argument, nullptr,
OIOpt{'f',
"force",
no_argument,
nullptr,
"Force running tests, even if they are marked as skipped"},
OIOpt{'x', "oid", required_argument, nullptr,
OIOpt{'x',
"oid",
required_argument,
nullptr,
"Path to OID executable to test"},
OIOpt{'\0', "enable-feature", required_argument, nullptr,
OIOpt{'\0',
"enable-feature",
required_argument,
nullptr,
"Enable extra OID feature."},
};
@ -64,8 +82,9 @@ int main(int argc, char* argv[]) {
}
int c;
while ((c = getopt_long(argc, argv, cliOpts.shortOpts(), cliOpts.longOpts(),
nullptr)) != -1) {
while ((c = getopt_long(
argc, argv, cliOpts.shortOpts(), cliOpts.longOpts(), nullptr)) !=
-1) {
switch (c) {
case 'p':
preserve = true;
@ -193,8 +212,8 @@ OidProc OidIntegration::runOidOnProcess(OidOpts opts,
// The arguments are appended in ascending order of precedence (low -> high)
std::vector<std::string> oid_args;
oid_args.insert(oid_args.end(), global_oid_args.begin(),
global_oid_args.end());
oid_args.insert(
oid_args.end(), global_oid_args.begin(), global_oid_args.end());
oid_args.insert(oid_args.end(), extra_args.begin(), extra_args.end());
oid_args.insert(oid_args.end(), default_args.begin(), default_args.end());
@ -269,7 +288,9 @@ OidProc OidIntegration::runOidOnProcess(OidOpts opts,
return OidProc{
.target = Proc{opts.ctx, std::move(targetProcess), {}, {}},
.oid = Proc{opts.ctx, std::move(oidProcess), std::move(std_out),
.oid = Proc{opts.ctx,
std::move(oidProcess),
std::move(std_out),
std::move(std_err)},
};
}
@ -298,8 +319,10 @@ void IntegrationBase::compare_json(const bpt::ptree& expected_json,
for (auto e_it = expected_json.begin(), a_it = actual_json.begin();
e_it != expected_json.end() && a_it != actual_json.end();
e_it++, a_it++) {
compare_json(e_it->second, a_it->second,
full_key + "[" + std::to_string(i) + "]", expect_eq);
compare_json(e_it->second,
a_it->second,
full_key + "[" + std::to_string(i) + "]",
expect_eq);
i++;
}
return;
@ -417,6 +440,8 @@ Proc OilIntegration::runOilTarget(OilOpts opts,
opts.ctx);
// clang-format on
return Proc{opts.ctx, std::move(targetProcess), std::move(std_out),
return Proc{opts.ctx,
std::move(targetProcess),
std::move(std_out),
std::move(std_err)};
}

View File

@ -66,7 +66,8 @@ TEST_F(AddChildrenTest, InheritanceStatic) {
}
TEST_F(AddChildrenTest, InheritancePolymorphic) {
testMultiCompilerGlob("oid_test_case_inheritance_polymorphic_a_as_a", R"(
testMultiCompilerGlob("oid_test_case_inheritance_polymorphic_a_as_a",
R"(
[1] Pointer
[0] Class: A (size: 16)
Member: _vptr$A (offset: 0)

View File

@ -7,7 +7,8 @@
using namespace type_graph;
TEST(AddPaddingTest, BetweenMembers) {
test(AddPadding::createPass(), R"(
test(AddPadding::createPass(),
R"(
[0] Class: MyClass (size: 16)
Member: n1 (offset: 0)
Primitive: int8_t
@ -27,7 +28,8 @@ TEST(AddPaddingTest, BetweenMembers) {
}
TEST(AddPaddingTest, AtBeginning) {
test(AddPadding::createPass(), R"(
test(AddPadding::createPass(),
R"(
[0] Struct: MyStruct (size: 16)
Member: n1 (offset: 8)
Primitive: int64_t
@ -43,7 +45,8 @@ TEST(AddPaddingTest, AtBeginning) {
}
TEST(AddPaddingTest, AtEnd) {
test(AddPadding::createPass(), R"(
test(AddPadding::createPass(),
R"(
[0] Struct: MyStruct (size: 16)
Member: n1 (offset: 0)
Primitive: int64_t
@ -63,7 +66,8 @@ TEST(AddPaddingTest, AtEnd) {
}
TEST(AddPaddingTest, UnionBetweenMembers) {
test(AddPadding::createPass(), R"(
test(AddPadding::createPass(),
R"(
[0] Union: MyUnion (size: 8)
Member: n1 (offset: 0)
Primitive: int64_t
@ -80,7 +84,8 @@ TEST(AddPaddingTest, UnionBetweenMembers) {
}
TEST(AddPaddingTest, UnionAtEnd) {
test(AddPadding::createPass(), R"(
test(AddPadding::createPass(),
R"(
[0] Union: MyUnion (size: 16)
Member: n1 (offset: 0)
Primitive: int64_t
@ -100,7 +105,8 @@ TEST(AddPaddingTest, UnionAtEnd) {
}
TEST(AddPaddingTest, Bitfields) {
test(AddPadding::createPass(), R"(
test(AddPadding::createPass(),
R"(
[0] Class: MyClass (size: 16)
Member: b1 (offset: 0, bitsize: 3)
Primitive: int64_t
@ -148,7 +154,8 @@ TEST(AddPaddingTest, EmptyClass) {
}
TEST(AddPaddingTest, MemberlessClass) {
test(AddPadding::createPass(), R"(
test(AddPadding::createPass(),
R"(
[0] Class: MyClass (size: 12)
)",
R"(
@ -160,7 +167,8 @@ TEST(AddPaddingTest, MemberlessClass) {
}
TEST(AddPaddingTest, MemberlessUnion) {
test(AddPadding::createPass(), R"(
test(AddPadding::createPass(),
R"(
[0] Union: MyUnion (size: 16)
)",
R"(

View File

@ -6,7 +6,8 @@
using namespace type_graph;
TEST(AlignmentCalcTest, PrimitiveMembers) {
test(AlignmentCalc::createPass(), R"(
test(AlignmentCalc::createPass(),
R"(
[0] Class: MyClass (size: 16)
Member: n (offset: 0)
Primitive: int8_t
@ -23,7 +24,8 @@ TEST(AlignmentCalcTest, PrimitiveMembers) {
}
TEST(AlignmentCalcTest, StructMembers) {
test(AlignmentCalc::createPass(), R"(
test(AlignmentCalc::createPass(),
R"(
[0] Class: MyClass (size: 12)
Member: n (offset: 0)
Primitive: int8_t
@ -48,7 +50,8 @@ TEST(AlignmentCalcTest, StructMembers) {
}
TEST(AlignmentCalcTest, StructInContainer) {
test(AlignmentCalc::createPass(), R"(
test(AlignmentCalc::createPass(),
R"(
[0] Container: std::vector (size: 8)
Param
[1] Class: MyClass (size: 16)
@ -69,7 +72,8 @@ TEST(AlignmentCalcTest, StructInContainer) {
}
TEST(AlignmentCalcTest, PackedMembers) {
test(AlignmentCalc::createPass(), R"(
test(AlignmentCalc::createPass(),
R"(
[0] Struct: MyStruct (size: 8)
Member: n1 (offset: 0)
Primitive: int8_t
@ -98,7 +102,8 @@ TEST(AlignmentCalcTest, PackedMembers) {
}
TEST(AlignmentCalcTest, PackedTailPadding) {
test(AlignmentCalc::createPass(), R"(
test(AlignmentCalc::createPass(),
R"(
[0] Struct: MyStruct (size: 5)
Member: n1 (offset: 0)
Primitive: int32_t
@ -115,7 +120,8 @@ TEST(AlignmentCalcTest, PackedTailPadding) {
}
TEST(AlignmentCalcTest, RecurseClassParam) {
test(AlignmentCalc::createPass(), R"(
test(AlignmentCalc::createPass(),
R"(
[0] Class: MyClass (size: 0)
Param
[1] Class: ClassA (size: 16)
@ -136,7 +142,8 @@ TEST(AlignmentCalcTest, RecurseClassParam) {
}
TEST(AlignmentCalcTest, RecurseClassParent) {
test(AlignmentCalc::createPass(), R"(
test(AlignmentCalc::createPass(),
R"(
[0] Class: MyClass (size: 0)
Parent (offset: 0)
[1] Class: ClassA (size: 16)
@ -157,7 +164,8 @@ TEST(AlignmentCalcTest, RecurseClassParent) {
}
TEST(AlignmentCalcTest, RecurseClassMember) {
test(AlignmentCalc::createPass(), R"(
test(AlignmentCalc::createPass(),
R"(
[0] Class: MyClass (size: 0)
Member: xxx (offset: 0)
[1] Class: ClassA (size: 16)
@ -178,7 +186,8 @@ TEST(AlignmentCalcTest, RecurseClassMember) {
}
TEST(AlignmentCalcTest, RecurseClassChild) {
test(AlignmentCalc::createPass(), R"(
test(AlignmentCalc::createPass(),
R"(
[0] Class: MyClass (size: 0)
Child
[1] Class: ClassA (size: 16)
@ -199,7 +208,8 @@ TEST(AlignmentCalcTest, RecurseClassChild) {
}
TEST(AlignmentCalcTest, Bitfields) {
test(AlignmentCalc::createPass(), R"(
test(AlignmentCalc::createPass(),
R"(
[0] Class: MyClass (size: 8)
Member: a (offset: 0, bitsize: 2)
Primitive: int8_t
@ -216,7 +226,8 @@ TEST(AlignmentCalcTest, Bitfields) {
}
TEST(AlignmentCalcTest, Array) {
test(AlignmentCalc::createPass(), R"(
test(AlignmentCalc::createPass(),
R"(
[0] Class: MyClass (size: 1)
Member: a (offset: 0)
[1] Array: (length: 1)
@ -235,7 +246,8 @@ TEST(AlignmentCalcTest, Array) {
}
TEST(AlignmentCalcTest, Typedef) {
test(AlignmentCalc::createPass(), R"(
test(AlignmentCalc::createPass(),
R"(
[0] Class: MyClass (size: 1)
Member: a (offset: 0)
[1] Typedef: MyTypedef

View File

@ -114,7 +114,8 @@ TEST(CodeGenTest, TransformContainerAllocatorParamInParent) {
TEST(CodeGenTest, RemovedMemberAlignment) {
OICodeGen::Config config;
config.membersToStub = {{"MyClass", "b"}};
testTransform(config, R"(
testTransform(config,
R"(
[0] Class: MyClass (size: 24)
Member: a (offset: 0)
Primitive: int8_t

View File

@ -50,9 +50,12 @@ TEST(CompilerTest, CompileAndRelocate) {
EXPECT_TRUE(compiler.compile(code, sourcePath, objectPath));
const size_t relocSlabSize = 4096;
void* relocSlab =
mmap(nullptr, relocSlabSize, PROT_READ | PROT_WRITE | PROT_EXEC,
MAP_ANONYMOUS | MAP_PRIVATE, -1, 0);
void* relocSlab = mmap(nullptr,
relocSlabSize,
PROT_READ | PROT_WRITE | PROT_EXEC,
MAP_ANONYMOUS | MAP_PRIVATE,
-1,
0);
EXPECT_NE(relocSlab, nullptr);
auto relocResult =
@ -128,13 +131,16 @@ TEST(CompilerTest, CompileAndRelocateMultipleObjs) {
EXPECT_TRUE(compiler.compile(codeY, sourceYPath, objectYPath));
const size_t relocSlabSize = 8192;
void* relocSlab =
mmap(nullptr, relocSlabSize, PROT_READ | PROT_WRITE | PROT_EXEC,
MAP_ANONYMOUS | MAP_PRIVATE, -1, 0);
void* relocSlab = mmap(nullptr,
relocSlabSize,
PROT_READ | PROT_WRITE | PROT_EXEC,
MAP_ANONYMOUS | MAP_PRIVATE,
-1,
0);
EXPECT_NE(relocSlab, nullptr);
auto relocResult = compiler.applyRelocs((uintptr_t)relocSlab,
{objectXPath, objectYPath}, {});
auto relocResult = compiler.applyRelocs(
(uintptr_t)relocSlab, {objectXPath, objectYPath}, {});
EXPECT_TRUE(relocResult.has_value());
auto& [_, segs, jitSymbols] = relocResult.value();
@ -254,10 +260,10 @@ TEST(CompilerTest, LocateOpcodes) {
{ /* Large range of differently sized needles */
const std::array needles = {
std::vector{0x41_b, 0x54_b}, /* push r12: 1 instance */
std::vector{0x48_b, 0x83_b, 0xec_b,
0x18_b}, /* sub rsp,0x18: 1 instance */
std::vector(1, 0xe8_b), /* call: 4 instances */
std::vector{0x41_b, 0x5c_b}, /* pop r12: 1 instance */
std::vector{
0x48_b, 0x83_b, 0xec_b, 0x18_b}, /* sub rsp,0x18: 1 instance */
std::vector(1, 0xe8_b), /* call: 4 instances */
std::vector{0x41_b, 0x5c_b}, /* pop r12: 1 instance */
};
auto locs = OICompiler::locateOpcodes(insts, needles);
ASSERT_TRUE(locs.has_value());

View File

@ -253,7 +253,8 @@ TEST_F(DrgnParserTest, InheritanceMultiple) {
}
TEST_F(DrgnParserTest, Container) {
testMultiCompilerGlob("oid_test_case_std_vector_int_empty", R"(
testMultiCompilerGlob("oid_test_case_std_vector_int_empty",
R"(
[13] Pointer
[0] Class: vector<int, std::allocator<int> > (size: 24)
Param
@ -340,7 +341,8 @@ TEST_F(DrgnParserTest, EnumNoValues) {
DrgnParserOptions options{
.readEnumValues = false,
};
test("oid_test_case_enums_scoped", R"(
test("oid_test_case_enums_scoped",
R"(
Enum: ScopedEnum (size: 4)
)",
options);
@ -408,7 +410,8 @@ TEST_F(DrgnParserTest, PointerNoFollow) {
DrgnParserOptions options{
.chaseRawPointers = false,
};
test("oid_test_case_pointers_struct_primitive_ptrs", R"(
test("oid_test_case_pointers_struct_primitive_ptrs",
R"(
[1] Pointer
[0] Struct: PrimitivePtrs (size: 24)
Member: a (offset: 0)
@ -582,7 +585,8 @@ TEST_F(DrgnParserTest, MemberAlignment) {
}
TEST_F(DrgnParserTest, VirtualFunctions) {
testMultiCompiler("oid_test_case_inheritance_polymorphic_a_as_a", R"(
testMultiCompiler("oid_test_case_inheritance_polymorphic_a_as_a",
R"(
[1] Pointer
[0] Class: A (size: 16)
Member: _vptr$A (offset: 0)

View File

@ -6,7 +6,8 @@
using namespace type_graph;
TEST(EnforceCompatibilityTest, ParentContainers) {
test(EnforceCompatibility::createPass(), R"(
test(EnforceCompatibility::createPass(),
R"(
[0] Class: MyClass (size: 24)
Member: __oi_parent (offset: 0)
[1] Container: std::vector (size: 24)
@ -19,7 +20,8 @@ TEST(EnforceCompatibilityTest, ParentContainers) {
}
TEST(EnforceCompatibilityTest, TypesToStub) {
test(EnforceCompatibility::createPass(), R"(
test(EnforceCompatibility::createPass(),
R"(
[0] Class: EnumMap (size: 8)
Member: a (offset: 0)
Primitive: int32_t
@ -32,7 +34,8 @@ TEST(EnforceCompatibilityTest, TypesToStub) {
}
TEST(EnforceCompatibilityTest, VoidPointer) {
test(EnforceCompatibility::createPass(), R"(
test(EnforceCompatibility::createPass(),
R"(
[0] Class: MyClass (size: 8)
Member: p (offset: 0)
[1] Pointer

View File

@ -39,7 +39,8 @@ TEST(FlattenerTest, OnlyParents) {
// int b;
// int c;
// };
test(Flattener::createPass(), R"(
test(Flattener::createPass(),
R"(
[0] Class: ClassA (size: 8)
Parent (offset: 0)
[1] Class: ClassB (size: 4)
@ -72,7 +73,8 @@ TEST(FlattenerTest, ParentsFirst) {
// int a;
// };
test(Flattener::createPass(), R"(
test(Flattener::createPass(),
R"(
[0] Class: ClassA (size: 12)
Parent (offset: 0)
[1] Class: ClassB (size: 4)
@ -109,7 +111,8 @@ TEST(FlattenerTest, MembersFirst) {
// int c;
// };
test(Flattener::createPass(), R"(
test(Flattener::createPass(),
R"(
[0] Class: ClassA (size: 12)
Parent (offset: 4)
[1] Class: ClassB (size: 4)
@ -147,7 +150,8 @@ TEST(FlattenerTest, MixedMembersAndParents) {
// int c;
// };
test(Flattener::createPass(), R"(
test(Flattener::createPass(),
R"(
[0] Class: ClassA (size: 16)
Parent (offset: 0)
[1] Class: ClassB (size: 4)
@ -188,7 +192,8 @@ TEST(FlattenerTest, EmptyParent) {
// int a2;
// };
test(Flattener::createPass(), R"(
test(Flattener::createPass(),
R"(
[0] Class: ClassA (size: 12)
Parent (offset: 0)
[1] Class: ClassB (size: 0)
@ -227,7 +232,8 @@ TEST(FlattenerTest, TwoDeep) {
// int a;
// };
test(Flattener::createPass(), R"(
test(Flattener::createPass(),
R"(
[0] Class: ClassA (size: 16)
Parent (offset: 0)
[1] Class: ClassB (size: 8)
@ -271,7 +277,8 @@ TEST(FlattenerTest, DiamondInheritance) {
// int a;
// };
test(Flattener::createPass(), R"(
test(Flattener::createPass(),
R"(
[0] Class: ClassA (size: 16)
Parent (offset: 0)
[1] Class: ClassB (size: 8)
@ -309,7 +316,8 @@ TEST(FlattenerTest, Member) {
// class B { int c; int b; };
// Class A { int a; B b; };
test(Flattener::createPass(), R"(
test(Flattener::createPass(),
R"(
[0] Class: ClassA (size: 12)
Member: a (offset: 0)
Primitive: int32_t
@ -345,7 +353,8 @@ TEST(FlattenerTest, MemberOfParent) {
// class C { int c; };
// class A { int b; C c; int a; };
test(Flattener::createPass(), R"(
test(Flattener::createPass(),
R"(
[0] Class: ClassA (size: 12)
Parent (offset: 0)
[1] Class: ClassB (size: 8)
@ -381,7 +390,8 @@ TEST(FlattenerTest, ContainerParam) {
// class A { int b; int a; };
// std::vector<A, int>
test(Flattener::createPass(), R"(
test(Flattener::createPass(),
R"(
[0] Container: std::vector (size: 24)
Param
[1] Class: ClassA (size: 8)
@ -413,7 +423,8 @@ TEST(FlattenerTest, Array) {
// class A : B { int a; };
// A[5]
test(Flattener::createPass(), R"(
test(Flattener::createPass(),
R"(
[0] Array: (length: 5)
[1] Class: ClassA (size: 8)
Parent (offset: 0)
@ -439,7 +450,8 @@ TEST(FlattenerTest, Typedef) {
// class A : B { int a; };
// using aliasA = A;
test(Flattener::createPass(), R"(
test(Flattener::createPass(),
R"(
[0] Typedef: aliasA
[1] Class: ClassA (size: 8)
Parent (offset: 0)
@ -465,7 +477,8 @@ TEST(FlattenerTest, TypedefParent) {
// using aliasB = B;
// class A : aliasB { int a; };
test(Flattener::createPass(), R"(
test(Flattener::createPass(),
R"(
[0] Class: ClassA (size: 8)
Parent (offset: 0)
[1] Typedef: aliasB
@ -502,7 +515,8 @@ TEST(FlattenerTest, Pointer) {
auto classC = Class{0, Class::Kind::Class, "ClassC", 8};
classC.members.push_back(Member{ptrA, "a", 0});
test(Flattener::createPass(), R"(
test(Flattener::createPass(),
R"(
[0] Class: ClassC (size: 8)
Member: a (offset: 0)
[1] Pointer
@ -539,7 +553,8 @@ TEST(FlattenerTest, PointerCycle) {
classA.members.push_back(Member{classB, "b", 0});
classB.members.push_back(Member{ptrA, "a", 0});
test(Flattener::createPass(), R"(
test(Flattener::createPass(),
R"(
[0] Class: ClassA (size: 69)
Member: b (offset: 0)
[1] Class: ClassB (size: 69)
@ -565,7 +580,8 @@ TEST(FlattenerTest, Alignment) {
// class B { alignas(8) int b; };
// class A : B, C { int a; };
test(Flattener::createPass(), R"(
test(Flattener::createPass(),
R"(
[0] Class: ClassA (size: 12)
Parent (offset: 0)
[1] Class: ClassB (size: 4)
@ -605,7 +621,8 @@ TEST(FlattenerTest, Functions) {
classB.functions.push_back(Function{"funcB"});
classC.functions.push_back(Function{"funcC"});
test(Flattener::createPass(), R"(
test(Flattener::createPass(),
R"(
[0] Class: ClassA (size: 0)
Parent (offset: 0)
[1] Class: ClassB (size: 0)
@ -629,7 +646,8 @@ TEST(FlattenerTest, Children) {
// class B { int b; };
// class A : B, C { };
test(Flattener::createPass(), R"(
test(Flattener::createPass(),
R"(
[0] Class: ClassB (size: 4)
Member: b (offset: 0)
Primitive: int32_t
@ -664,7 +682,8 @@ TEST(FlattenerTest, ChildrenTwoDeep) {
// class B : D { int b; };
// class A : B, C { int a; };
test(Flattener::createPass(), R"(
test(Flattener::createPass(),
R"(
[0] Class: ClassD (size: 4)
Member: d (offset: 0)
Primitive: int32_t
@ -713,7 +732,8 @@ TEST(FlattenerTest, ChildrenTwoDeep) {
}
TEST(FlattenerTest, ParentContainer) {
test(Flattener::createPass(), R"(
test(Flattener::createPass(),
R"(
[0] Class: ClassA (size: 32)
Parent (offset: 0)
[1] Container: std::vector (size: 24)
@ -734,7 +754,8 @@ TEST(FlattenerTest, ParentContainer) {
}
TEST(FlattenerTest, ParentTwoContainers) {
test(Flattener::createPass(), R"(
test(Flattener::createPass(),
R"(
[0] Class: ClassA (size: 48)
Parent (offset: 0)
[1] Container: std::vector (size: 24)
@ -755,7 +776,8 @@ TEST(FlattenerTest, ParentTwoContainers) {
}
TEST(FlattenerTest, ParentClassAndContainer) {
test(Flattener::createPass(), R"(
test(Flattener::createPass(),
R"(
[0] Class: ClassA (size: 32)
Parent (offset: 0)
[1] Class: ClassB (size: 4)
@ -778,7 +800,8 @@ TEST(FlattenerTest, ParentClassAndContainer) {
}
TEST(FlattenerTest, AllocatorParamInParent) {
test(Flattener::createPass(), R"(
test(Flattener::createPass(),
R"(
[0] Container: std::map (size: 24)
Param
Primitive: int32_t
@ -836,7 +859,8 @@ TEST(FlattenerTest, AllocatorUnfixableNoParent) {
TEST(FlattenerTest, AllocatorUnfixableParentNotClass) {
// This could be supported if need-be, we just don't do it yet
test(Flattener::createPass(), R"(
test(Flattener::createPass(),
R"(
[0] Container: std::vector (size: 24)
Param
Primitive: int32_t
@ -875,7 +899,8 @@ TEST(FlattenerTest, AllocatorUnfixableParentNotClass) {
}
TEST(FlattenerTest, AllocatorUnfixableParentNoParams) {
test(Flattener::createPass(), R"(
test(Flattener::createPass(),
R"(
[0] Container: std::vector (size: 24)
Param
Primitive: int32_t
@ -902,7 +927,8 @@ TEST(FlattenerTest, AllocatorUnfixableParentNoParams) {
}
TEST(FlattenerTest, AllocatorUnfixableParentParamIsValue) {
test(Flattener::createPass(), R"(
test(Flattener::createPass(),
R"(
[0] Container: std::map (size: 24)
Param
Primitive: int32_t
@ -936,7 +962,8 @@ TEST(FlattenerTest, AllocatorUnfixableParentParamIsValue) {
}
TEST(FlattenerTest, ClassParam) {
test(Flattener::createPass(), R"(
test(Flattener::createPass(),
R"(
[0] Class: MyClass (size: 4)
Param
[1] Class: MyChild (size: 4)
@ -955,7 +982,8 @@ TEST(FlattenerTest, ClassParam) {
}
TEST(FlattenerTest, IncompleteParent) {
test(Flattener::createPass(), R"(
test(Flattener::createPass(),
R"(
[0] Class: MyClass (size: 4)
Parent (offset: 0)
Incomplete: [IncompleteParent]

View File

@ -9,7 +9,8 @@ using namespace type_graph;
namespace {
void test(std::string_view input, std::string_view expectedAfter) {
::test(IdentifyContainers::createPass(getContainerInfos()), input,
::test(IdentifyContainers::createPass(getContainerInfos()),
input,
expectedAfter);
}
}; // namespace

View File

@ -11,7 +11,8 @@ TEST(KeyCaptureTest, InClass) {
{"MyClass", "b"},
};
std::vector<std::unique_ptr<ContainerInfo>> containerInfos;
test(KeyCapture::createPass(keysToCapture, containerInfos), R"(
test(KeyCapture::createPass(keysToCapture, containerInfos),
R"(
[0] Class: MyClass (size: 12)
Member: a (offset: 0)
Primitive: int32_t
@ -45,7 +46,8 @@ TEST(KeyCaptureTest, MapInMap) {
{"MyClass", "a"},
};
std::vector<std::unique_ptr<ContainerInfo>> containerInfos;
test(KeyCapture::createPass(keysToCapture, containerInfos), R"(
test(KeyCapture::createPass(keysToCapture, containerInfos),
R"(
[0] Class: MyClass (size: 12)
Member: a (offset: 8)
[1] Container: std::map (size: 24)
@ -79,7 +81,8 @@ TEST(KeyCaptureTest, TopLevel) {
{{}, {}, true},
};
std::vector<std::unique_ptr<ContainerInfo>> containerInfos;
test(KeyCapture::createPass(keysToCapture, containerInfos), R"(
test(KeyCapture::createPass(keysToCapture, containerInfos),
R"(
[0] Container: std::map (size: 24)
Param
Primitive: int32_t

View File

@ -92,7 +92,8 @@ TEST(ParserTest, MangledFunc) {
"EEESaISF_EERS1_IS8_SaIS8_EERS1_ISB_IS8_dESaISM_EE:arg9");
EXPECT_EQ(pdata.numReqs(), 1);
EXPECT_REQ_EQ(
pdata.getReq(0), "entry",
pdata.getReq(0),
"entry",
"_Z7doStuffR3FooRSt6vectorISt3mapINSt7__cxx1112basic_stringIcSt11char_"
"traitsIcESaIcEEES8_St4lessIS8_ESaISt4pairIKS8_S8_EEESaISF_EERS1_IS8_"
"SaIS8_EERS1_ISB_IS8_dESaISM_EE",

View File

@ -6,7 +6,8 @@
using type_graph::Prune;
TEST(PruneTest, PruneClass) {
test(Prune::createPass(), R"(
test(Prune::createPass(),
R"(
[0] Class: MyClass (size: 8)
Param
Primitive: int32_t
@ -34,7 +35,8 @@ TEST(PruneTest, PruneClass) {
}
TEST(PruneTest, RecurseClassMember) {
test(Prune::createPass(), R"(
test(Prune::createPass(),
R"(
[0] Class: MyClass (size: 0)
Member: xxx (offset: 0)
[1] Class: ClassA (size: 12)
@ -48,7 +50,8 @@ TEST(PruneTest, RecurseClassMember) {
}
TEST(PruneTest, RecurseClassChild) {
test(Prune::createPass(), R"(
test(Prune::createPass(),
R"(
[0] Class: MyClass (size: 0)
Child
[1] Class: ClassA (size: 12)

View File

@ -11,7 +11,8 @@ TEST(RemoveMembersTest, Match) {
{"ClassA", "b"},
};
test(RemoveMembers::createPass(membersToIgnore), R"(
test(RemoveMembers::createPass(membersToIgnore),
R"(
[0] Class: ClassA (size: 12)
Member: a (offset: 0)
[1] Class: ClassB (size: 4)
@ -65,7 +66,8 @@ TEST(RemoveMembersTest, RecurseClassParam) {
const std::vector<std::pair<std::string, std::string>>& membersToIgnore = {
{"ClassA", "b"},
};
test(RemoveMembers::createPass(membersToIgnore), R"(
test(RemoveMembers::createPass(membersToIgnore),
R"(
[0] Class: MyClass (size: 0)
Param
[1] Class: ClassA (size: 12)
@ -91,7 +93,8 @@ TEST(RemoveMembersTest, RecurseClassParent) {
const std::vector<std::pair<std::string, std::string>>& membersToIgnore = {
{"ClassA", "b"},
};
test(RemoveMembers::createPass(membersToIgnore), R"(
test(RemoveMembers::createPass(membersToIgnore),
R"(
[0] Class: MyClass (size: 0)
Parent (offset: 0)
[1] Class: ClassA (size: 12)
@ -117,7 +120,8 @@ TEST(RemoveMembersTest, RecurseClassMember) {
const std::vector<std::pair<std::string, std::string>>& membersToIgnore = {
{"ClassA", "b"},
};
test(RemoveMembers::createPass(membersToIgnore), R"(
test(RemoveMembers::createPass(membersToIgnore),
R"(
[0] Class: MyClass (size: 0)
Member: xxx (offset: 0)
[1] Class: ClassA (size: 12)
@ -143,7 +147,8 @@ TEST(RemoveMembersTest, RecurseClassChild) {
const std::vector<std::pair<std::string, std::string>>& membersToIgnore = {
{"ClassA", "b"},
};
test(RemoveMembers::createPass(membersToIgnore), R"(
test(RemoveMembers::createPass(membersToIgnore),
R"(
[0] Class: MyClass (size: 0)
Child
[1] Class: ClassA (size: 12)
@ -166,7 +171,8 @@ TEST(RemoveMembersTest, RecurseClassChild) {
}
TEST(RemoveMembersTest, Union) {
test(RemoveMembers::createPass({}), R"(
test(RemoveMembers::createPass({}),
R"(
[0] Union: MyUnion (size: 4)
Member: a (offset: 0)
Primitive: int32_t

View File

@ -7,7 +7,8 @@
using namespace type_graph;
TEST(RemoveTopLevelPointerTest, TopLevelPointerRemoved) {
test(RemoveTopLevelPointer::createPass(), R"(
test(RemoveTopLevelPointer::createPass(),
R"(
[0] Pointer
[1] Class: MyClass (size: 4)
Member: n (offset: 0)

View File

@ -7,7 +7,8 @@
using namespace type_graph;
TEST(TypeIdentifierTest, StubbedParam) {
test(TypeIdentifier::createPass({}), R"(
test(TypeIdentifier::createPass({}),
R"(
[0] Container: std::vector (size: 24)
Param
Primitive: int32_t
@ -30,7 +31,8 @@ TEST(TypeIdentifierTest, StubbedParam) {
}
TEST(TypeIdentifierTest, Allocator) {
test(TypeIdentifier::createPass({}), R"(
test(TypeIdentifier::createPass({}),
R"(
[0] Container: std::vector (size: 24)
Param
Primitive: int32_t
@ -56,7 +58,8 @@ TEST(TypeIdentifierTest, Allocator) {
}
TEST(TypeIdentifierTest, AllocatorSize1) {
test(TypeIdentifier::createPass({}), R"(
test(TypeIdentifier::createPass({}),
R"(
[0] Container: std::vector (size: 24)
Param
Primitive: int32_t
@ -85,7 +88,8 @@ TEST(TypeIdentifierTest, PassThroughTypes) {
std::vector<ContainerInfo> passThroughTypes;
passThroughTypes.emplace_back("std::allocator", DUMMY_TYPE, "memory");
test(TypeIdentifier::createPass(passThroughTypes), R"(
test(TypeIdentifier::createPass(passThroughTypes),
R"(
[0] Container: std::vector (size: 24)
Param
Primitive: int32_t
@ -111,7 +115,8 @@ TEST(TypeIdentifierTest, PassThroughSameType) {
std::vector<ContainerInfo> passThroughTypes;
passThroughTypes.emplace_back("std::allocator", DUMMY_TYPE, "memory");
test(TypeIdentifier::createPass(passThroughTypes), R"(
test(TypeIdentifier::createPass(passThroughTypes),
R"(
[0] Container: std::vector (size: 24)
Param
Primitive: int32_t
@ -138,7 +143,8 @@ TEST(TypeIdentifierTest, PassThroughSameType) {
}
TEST(TypeIdentifierTest, ContainerNotReplaced) {
test(TypeIdentifier::createPass({}), R"(
test(TypeIdentifier::createPass({}),
R"(
[0] Container: std::vector (size: 24)
Param
Primitive: int32_t

View File

@ -31,17 +31,35 @@ using namespace oi::detail;
constexpr static OIOpts opts{
OIOpt{'h', "help", no_argument, nullptr, "Print this message and exit."},
OIOpt{'o', "output", required_argument, "<file>",
OIOpt{'o',
"output",
required_argument,
"<file>",
"Write output(s) to file(s) with this prefix."},
OIOpt{'c', "config-file", required_argument, "<oid.toml>",
OIOpt{'c',
"config-file",
required_argument,
"<oid.toml>",
"Path to OI configuration file."},
OIOpt{'d', "debug-level", required_argument, "<level>",
OIOpt{'d',
"debug-level",
required_argument,
"<level>",
"Verbose level for logging"},
OIOpt{'j', "dump-jit", optional_argument, "<jit.cpp>",
OIOpt{'j',
"dump-jit",
optional_argument,
"<jit.cpp>",
"Write generated code to a file (for debugging)."},
OIOpt{'e', "exit-code", no_argument, nullptr,
OIOpt{'e',
"exit-code",
no_argument,
nullptr,
"Return a bad exit code if nothing is generated."},
OIOpt{'p', "pic", no_argument, nullptr,
OIOpt{'p',
"pic",
no_argument,
nullptr,
"Generate position independent code."},
};
@ -68,8 +86,8 @@ int main(int argc, char* argv[]) {
bool pic = false;
int c;
while ((c = getopt_long(argc, argv, opts.shortOpts(), opts.longOpts(),
nullptr)) != -1) {
while ((c = getopt_long(
argc, argv, opts.shortOpts(), opts.longOpts(), nullptr)) != -1) {
switch (c) {
case 'h':
usage();

View File

@ -208,7 +208,9 @@ void printFuncArg(const std::shared_ptr<FuncDesc::TargetObject>& funcObj) {
const auto& location = funcArg->locator.locations[i];
printf(
"{\"start\":\"0x%zx\",\"end\":\"0x%zx\",\"expr_size\":%zu,\"expr\":[",
location.start, location.end, location.expr_size);
location.start,
location.end,
location.expr_size);
for (size_t j = 0; j < location.expr_size; j++) {
if (j > 0) {
printf(",");
@ -232,8 +234,8 @@ void printFuncDesc(const std::shared_ptr<FuncDesc>& funcDesc) {
if (!isFirstRange) {
printf(",");
}
printf("{\"start\": \"0x%zx\", \"end\": \"0x%zx\"}", range.start,
range.end);
printf(
"{\"start\": \"0x%zx\", \"end\": \"0x%zx\"}", range.start, range.end);
isFirstRange = false;
}
printf("],");

View File

@ -227,8 +227,10 @@ int main(int argc, const char** argv) {
rocksdb::DB* _db = nullptr;
if (auto status = rocksdb::DB::Open(options, dbpath.string(), &_db);
!status.ok()) {
fprintf(stderr, "Failed to open DB '%s' with error %s\n",
dbpath.string().c_str(), status.ToString().c_str());
fprintf(stderr,
"Failed to open DB '%s' with error %s\n",
dbpath.string().c_str(),
status.ToString().c_str());
return 1;
}
db.reset(_db);

View File

@ -36,15 +36,24 @@ using namespace oi::detail;
constexpr static OIOpts opts{
OIOpt{'h', "help", no_argument, nullptr, "Print this message and exit"},
OIOpt{'a', "log-all-structs", no_argument, nullptr,
OIOpt{'a',
"log-all-structs",
no_argument,
nullptr,
"Enable TreeBuilder::Config::logAllStructs (=true)\n"
"Note: this option is already enabled, this is a no-op"},
OIOpt{'J', "dump-json", optional_argument, "[oid_out.json]",
OIOpt{'J',
"dump-json",
optional_argument,
"[oid_out.json]",
"File to dump the results to, as JSON\n"
"(in addition to the default RocksDB output)"},
OIOpt{'f', "enable-feature", required_argument, "FEATURE",
"Enable feature"},
OIOpt{'F', "disable-feature", required_argument, "FEATURE",
OIOpt{
'f', "enable-feature", required_argument, "FEATURE", "Enable feature"},
OIOpt{'F',
"disable-feature",
required_argument,
"FEATURE",
"Disable feature"},
};
@ -146,8 +155,8 @@ int main(int argc, char* argv[]) {
};
int c = '\0';
while ((c = getopt_long(argc, argv, opts.shortOpts(), opts.longOpts(),
nullptr)) != -1) {
while ((c = getopt_long(
argc, argv, opts.shortOpts(), opts.longOpts(), nullptr)) != -1) {
switch (c) {
case 'h':
usage(std::cout);