object-introspection/oi/OICodeGen.h

Ignoring revisions in .git-blame-ignore-revs. Click here to bypass and see the normal blame view.

335 lines
12 KiB
C
Raw Normal View History

2022-12-19 14:37:51 +00:00
/*
* 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 <filesystem>
#include <map>
#include <memory>
#include <optional>
#include <set>
#include <string>
#include <unordered_map>
#include <vector>
class SymbolService;
struct irequest;
2023-04-26 16:20:53 +01:00
#include "oi/Common.h"
#include "oi/ContainerInfo.h"
#include "oi/Features.h"
#include "oi/FuncGen.h"
#include "oi/PaddingHunter.h"
2022-12-19 14:37:51 +00:00
extern "C" {
#include <drgn.h>
}
using namespace ObjectIntrospection;
2022-12-19 14:37:51 +00:00
namespace fs = std::filesystem;
struct ParentMember {
drgn_type* type;
2022-12-19 14:37:51 +00:00
uint64_t bit_offset;
bool operator<(const ParentMember& parent) const {
2022-12-19 14:37:51 +00:00
return (bit_offset < parent.bit_offset);
}
};
class OICodeGen {
public:
struct Config {
/*
* Note: don't set default values for the config so the user gets an
* uninitialized field" warning if they missed any.
*/
bool useDataSegment;
2023-04-24 16:35:16 +01:00
FeatureSet features{};
2022-12-19 14:37:51 +00:00
std::set<fs::path> containerConfigPaths{};
std::set<std::string> defaultHeaders{};
std::set<std::string> defaultNamespaces{};
std::vector<std::pair<std::string, std::string>> membersToStub{};
std::string toString() const;
std::vector<std::string> toOptions() const;
};
private:
// Private constructor. Please use the fallible `OICodeGen::buildFromConfig`
// for the expected behaviour.
OICodeGen(const Config&, SymbolService&);
2022-12-19 14:37:51 +00:00
public:
static std::unique_ptr<OICodeGen> buildFromConfig(const Config&,
SymbolService&);
bool generate(std::string& code);
2022-12-19 14:37:51 +00:00
[[deprecated("Use generate(std::string&) instead.")]] bool
generateFunctionsForTypesDrgn(std::string& code) {
2022-12-19 14:37:51 +00:00
return generate(code);
}
bool registerContainer(const fs::path&);
2022-12-19 14:37:51 +00:00
// TODO: remove me once all the callsites are gone
static void initializeCodeGen();
drgn_qualified_type getRootType();
void setRootType(drgn_qualified_type rt);
2022-12-19 14:37:51 +00:00
void setLinkageName(std::string name) {
linkageName = name;
};
TypeHierarchy getTypeHierarchy();
std::map<std::string, PaddingInfo> getPaddingInfo();
bool isContainer(drgn_type* type);
2022-12-19 14:37:51 +00:00
bool buildName(drgn_type* type, std::string& text, std::string& outName);
2022-12-19 14:37:51 +00:00
std::string typeToTransformedName(drgn_type* type);
2022-12-19 14:37:51 +00:00
bool enumerateTypesRecurse(drgn_type* type);
static std::string_view drgnKindStr(drgn_type* type);
std::set<drgn_type*> processedTypes;
bool isDynamic(drgn_type* type) const;
2022-12-19 14:37:51 +00:00
private:
Config config{};
FuncGen funcGen;
using ContainerTypeMapEntry =
std::pair<std::reference_wrapper<const ContainerInfo>,
std::vector<drgn_qualified_type>>;
2022-12-19 14:37:51 +00:00
using TemplateParamList =
std::vector<std::pair<drgn_qualified_type, std::string>>;
2022-12-19 14:37:51 +00:00
using SortedTypeDefMap = std::vector<std::pair<drgn_type*, drgn_type*>>;
2022-12-19 14:37:51 +00:00
std::string rootTypeStr;
std::string linkageName;
std::map<drgn_type*, std::string> unnamedUnion;
2022-12-19 14:37:51 +00:00
std::map<std::string, size_t> sizeMap;
std::map<drgn_type*, ContainerTypeMapEntry> containerTypeMapDrgn;
2022-12-19 14:37:51 +00:00
std::vector<std::unique_ptr<ContainerInfo>> containerInfoList;
std::vector<drgn_type*> enumTypes;
2022-12-19 14:37:51 +00:00
std::vector<std::string> knownTypes;
drgn_qualified_type rootType;
drgn_qualified_type rootTypeToIntrospect;
2022-12-19 14:37:51 +00:00
std::map<std::string, std::string> typedefMap;
std::map<drgn_type*, std::vector<ParentMember>> parentClasses;
std::map<std::string, std::vector<drgn_type*>> childClasses;
std::map<drgn_type*, std::vector<drgn_type*>> descendantClasses;
SymbolService& symbols;
2022-12-19 14:37:51 +00:00
size_t pad_index = 0;
std::unordered_map<drgn_type*, std::pair<size_t, size_t>> paddingIndexMap;
std::map<drgn_type*, drgn_type*> typedefTypes;
std::map<drgn_type*, std::vector<DrgnClassMemberInfo>> classMembersMap;
std::map<drgn_type*, std::vector<DrgnClassMemberInfo>> classMembersMapCopy;
std::map<drgn_type*, std::string> typeToNameMap;
std::map<std::string, drgn_type*> nameToTypeMap;
std::set<drgn_type*> funcDefTypeList;
std::vector<drgn_type*> structDefType;
std::set<drgn_type*> knownDummyTypeList;
std::map<drgn_type*, drgn_type*> pointerToTypeMap;
std::set<drgn_type*> thriftIssetStructTypes;
std::vector<drgn_type*> topoSortedStructTypes;
2022-12-19 14:37:51 +00:00
ContainerInfoRefSet containerTypesFuncDef;
2022-12-19 14:37:51 +00:00
std::map<std::string, PaddingInfo> paddedStructs;
std::map<drgn_type*, std::vector<DrgnClassMemberInfo>>& getClassMembersMap();
2022-12-19 14:37:51 +00:00
class DrgnString {
struct FreeDeleter {
void operator()(void* allocated) {
2022-12-19 14:37:51 +00:00
free(allocated);
}
};
public:
std::string_view contents;
DrgnString(char* data, size_t length)
2022-12-19 14:37:51 +00:00
: contents{data, length}, _data{data} {
}
DrgnString() = delete;
private:
std::unique_ptr<char, FreeDeleter> _data;
};
2023-04-24 16:35:16 +01:00
bool feature(Feature f) const {
return config.features[f];
}
static void prependQualifiers(enum drgn_qualifiers, std::string& sb);
2022-12-19 14:37:51 +00:00
static std::string stripFullyQualifiedName(
const std::string& fullyQualifiedName);
2022-12-19 14:37:51 +00:00
std::string stripFullyQualifiedNameWithSeparators(
const std::string& fullyQualifiedname);
static void removeTemplateParamAtIndex(std::vector<std::string>& params,
2022-12-19 14:37:51 +00:00
const size_t index);
std::unordered_map<drgn_type*, DrgnString> fullyQualifiedNames;
std::optional<const std::string_view> fullyQualifiedName(drgn_type* type);
2022-12-19 14:37:51 +00:00
static SortedTypeDefMap getSortedTypeDefMap(
const std::map<drgn_type*, drgn_type*>& typedefTypeMap);
2022-12-19 14:37:51 +00:00
std::optional<std::reference_wrapper<const ContainerInfo>> getContainerInfo(
drgn_type* type);
2022-12-19 14:37:51 +00:00
void printAllTypes();
void printAllTypeNames();
static void addPaddingForBaseClass(drgn_type* type,
std::vector<std::string>& def);
void addTypeToName(drgn_type* type, std::string name);
2022-12-19 14:37:51 +00:00
bool generateNamesForTypes();
bool generateJitCode(std::string& code);
bool generateStructDefs(std::string& code);
bool generateStructDef(drgn_type* e, std::string& code);
bool getDrgnTypeName(drgn_type* type, std::string& outName);
2022-12-19 14:37:51 +00:00
bool getDrgnTypeNameInt(drgn_type* type, std::string& outName);
bool recordChildren(drgn_type* type);
bool enumerateChildClasses();
2022-12-19 14:37:51 +00:00
bool populateDefsAndDecls();
static void memberTransformName(
std::map<std::string, std::string>& templateTransformMap,
std::string& typeName);
2022-12-19 14:37:51 +00:00
bool getMemberDefinition(drgn_type* type);
bool isKnownType(const std::string& type);
bool isKnownType(const std::string& type, std::string& matched);
2022-12-19 14:37:51 +00:00
static bool getTemplateParams(
drgn_type* type,
size_t numTemplateParams,
std::vector<std::pair<drgn_qualified_type, std::string>>& v);
bool enumerateTemplateParamIdxs(drgn_type* type,
const ContainerInfo& containerInfo,
const std::vector<size_t>& paramIdxs,
bool& ifStub);
bool getContainerTemplateParams(drgn_type* type, bool& ifStub);
void enumerateDescendants(drgn_type* type, drgn_type* baseType);
void getFuncDefinitionStr(std::string& code,
drgn_type* type,
const std::string& typeName);
std::optional<uint64_t> getDrgnTypeSize(drgn_type* type);
std::optional<std::string> getNameForType(drgn_type* type);
static std::string preProcessUniquePtr(drgn_type* type, std::string name);
std::string transformTypeName(drgn_type* type, std::string& text);
static std::string templateTransformType(const std::string& typeName);
static std::string structNameTransformType(const std::string& typeName);
bool addPadding(uint64_t padding_bits, std::string& code);
2022-12-19 14:37:51 +00:00
static void deduplicateMemberName(
std::unordered_map<std::string, int>& memberNames,
std::string& memberName);
2022-12-19 14:37:51 +00:00
std::optional<uint64_t> generateMember(
const DrgnClassMemberInfo& m,
std::unordered_map<std::string, int>& memberNames,
uint64_t currOffsetBits,
std::string& code,
bool isInUnion);
bool generateParent(drgn_type* p,
std::unordered_map<std::string, int>& memberNames,
uint64_t& currOffsetBits,
std::string& code,
2022-12-19 14:37:51 +00:00
size_t offsetToNextMember);
std::optional<uint64_t> getAlignmentRequirements(drgn_type* e);
bool generateStructMembers(drgn_type* e,
std::unordered_map<std::string, int>& memberNames,
std::string& code,
uint64_t& out_offset_bits,
PaddingInfo& paddingInfo,
bool& violatesAlignmentRequirement,
2022-12-19 14:37:51 +00:00
size_t offsetToNextMember);
void getFuncDefClassMembers(std::string& code,
drgn_type* type,
std::unordered_map<std::string, int>& memberNames,
2022-12-19 14:37:51 +00:00
bool skipPadding = false);
bool isDrgnSizeComplete(drgn_type* type);
2022-12-19 14:37:51 +00:00
static bool getEnumUnderlyingTypeStr(drgn_type* e,
std::string& enumUnderlyingTypeStr);
2022-12-19 14:37:51 +00:00
bool ifEnumerateClass(const std::string& typeName);
2022-12-19 14:37:51 +00:00
bool enumerateClassParents(drgn_type* type, const std::string& typeName);
bool enumerateClassMembers(drgn_type* type,
const std::string& typeName,
bool& isStubbed);
bool enumerateClassTemplateParams(drgn_type* type,
const std::string& typeName,
bool& isStubbed);
bool ifGenerateMemberDefinition(const std::string& typeName);
bool generateMemberDefinition(drgn_type* type, std::string& typeName);
2022-12-19 14:37:51 +00:00
std::optional<std::pair<std::string_view, std::string_view>> isMemberToStub(
const std::string& type, const std::string& member);
std::optional<std::string_view> isTypeToStub(const std::string& typeName);
bool isTypeToStub(drgn_type* type, const std::string& typeName);
bool isEmptyClassOrFunctionType(drgn_type* type, const std::string& typeName);
bool enumerateClassType(drgn_type* type);
bool enumerateTypeDefType(drgn_type* type);
bool enumerateEnumType(drgn_type* type);
bool enumeratePointerType(drgn_type* type);
bool enumeratePrimitiveType(drgn_type* type);
bool enumerateArrayType(drgn_type* type);
bool isUnnamedStruct(drgn_type* type);
std::string getAnonName(drgn_type*, const char*);
std::string getStructName(drgn_type* type) {
2022-12-19 14:37:51 +00:00
return getAnonName(type, "__anon_struct_");
}
std::string getUnionName(drgn_type* type) {
2022-12-19 14:37:51 +00:00
return getAnonName(type, "__anon_union_");
}
static void declareThriftStruct(std::string& code, std::string_view name);
2022-12-19 14:37:51 +00:00
bool isNumMemberGreaterThanZero(drgn_type* type);
void getClassMembersIncludingParent(drgn_type* type,
std::vector<DrgnClassMemberInfo>& out);
2022-12-19 14:37:51 +00:00
bool staticAssertMemberOffsets(
const std::string& struct_name,
drgn_type* struct_type,
std::string& assert_str,
std::unordered_map<std::string, int>& member_names,
2022-12-19 14:37:51 +00:00
uint64_t base_offset = 0);
bool addStaticAssertsForType(drgn_type* type,
bool generateAssertsForOffsets,
std::string& code);
bool buildNameInt(drgn_type* type,
std::string& nameWithoutTemplate,
std::string& outName);
2022-12-19 14:37:51 +00:00
void replaceTemplateOperator(
std::vector<std::pair<drgn_qualified_type, std::string>>& template_params,
std::vector<std::string>& template_params_strings,
size_t index);
2022-12-19 14:37:51 +00:00
void replaceTemplateParameters(
drgn_type* type,
std::vector<std::pair<drgn_qualified_type, std::string>>& template_params,
std::vector<std::string>& template_params_strings,
const std::string& nameWithoutTemplate);
2022-12-19 14:37:51 +00:00
};