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;
|
|
|
|
|
|
|
|
#include "Common.h"
|
|
|
|
#include "ContainerInfo.h"
|
|
|
|
#include "FuncGen.h"
|
|
|
|
#include "PaddingHunter.h"
|
|
|
|
|
|
|
|
extern "C" {
|
|
|
|
#include <drgn.h>
|
|
|
|
}
|
|
|
|
|
|
|
|
namespace fs = std::filesystem;
|
|
|
|
|
|
|
|
struct ParentMember {
|
2023-01-04 17:54:07 +00:00
|
|
|
drgn_type *type;
|
2022-12-19 14:37:51 +00:00
|
|
|
uint64_t bit_offset;
|
|
|
|
|
|
|
|
bool operator<(const ParentMember &parent) const {
|
|
|
|
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;
|
|
|
|
bool chaseRawPointers;
|
|
|
|
bool packStructs;
|
|
|
|
bool genPaddingStats;
|
|
|
|
bool captureThriftIsset;
|
2023-01-25 14:37:16 +00:00
|
|
|
bool polymorphicInheritance;
|
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.
|
2023-01-25 14:37:16 +00:00
|
|
|
OICodeGen(const Config &, SymbolService &);
|
2022-12-19 14:37:51 +00:00
|
|
|
|
|
|
|
public:
|
2023-01-25 14:37:16 +00:00
|
|
|
static std::unique_ptr<OICodeGen> buildFromConfig(const Config &,
|
|
|
|
SymbolService &);
|
2022-12-19 14:37:51 +00:00
|
|
|
bool generate(std::string &code);
|
|
|
|
|
|
|
|
[[deprecated("Use generate(std::string&) instead.")]] bool
|
|
|
|
generateFunctionsForTypesDrgn(std::string &code) {
|
|
|
|
return generate(code);
|
|
|
|
}
|
|
|
|
|
|
|
|
bool registerContainer(const fs::path &);
|
|
|
|
|
|
|
|
// TODO: remove me once all the callsites are gone
|
|
|
|
static void initializeCodeGen();
|
|
|
|
|
2023-01-04 17:54:07 +00:00
|
|
|
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();
|
|
|
|
|
2023-01-04 17:54:07 +00:00
|
|
|
bool isContainer(drgn_type *type);
|
2022-12-19 14:37:51 +00:00
|
|
|
|
2023-01-04 17:54:07 +00:00
|
|
|
static drgn_type *drgnUnderlyingType(drgn_type *type);
|
2022-12-19 14:37:51 +00:00
|
|
|
|
2023-01-04 17:54:07 +00:00
|
|
|
bool buildName(drgn_type *type, std::string &text, std::string &outName);
|
2022-12-19 14:37:51 +00:00
|
|
|
|
2023-01-04 17:54:07 +00:00
|
|
|
std::string typeToTransformedName(drgn_type *type);
|
2022-12-19 14:37:51 +00:00
|
|
|
|
2023-01-04 17:54:07 +00:00
|
|
|
bool enumerateTypesRecurse(drgn_type *type);
|
|
|
|
static std::string_view drgnKindStr(drgn_type *type);
|
|
|
|
std::set<drgn_type *> processedTypes;
|
2023-01-25 14:37:16 +00:00
|
|
|
bool isDynamic(drgn_type *type) const;
|
2022-12-19 14:37:51 +00:00
|
|
|
|
|
|
|
private:
|
|
|
|
Config config{};
|
|
|
|
FuncGen funcGen;
|
|
|
|
|
|
|
|
using ContainerTypeMap =
|
2023-01-04 17:54:07 +00:00
|
|
|
std::pair<ContainerInfo, std::vector<drgn_qualified_type>>;
|
2022-12-19 14:37:51 +00:00
|
|
|
|
|
|
|
using TemplateParamList =
|
2023-01-04 17:54:07 +00:00
|
|
|
std::vector<std::pair<drgn_qualified_type, std::string>>;
|
2022-12-19 14:37:51 +00:00
|
|
|
|
2023-01-04 17:54:07 +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;
|
2023-01-04 17:54:07 +00:00
|
|
|
std::map<drgn_type *, std::string> unnamedUnion;
|
2022-12-19 14:37:51 +00:00
|
|
|
std::map<std::string, size_t> sizeMap;
|
2023-01-04 17:54:07 +00:00
|
|
|
std::map<drgn_type *, ContainerTypeMap> containerTypeMapDrgn;
|
2022-12-19 14:37:51 +00:00
|
|
|
std::vector<std::unique_ptr<ContainerInfo>> containerInfoList;
|
2023-01-04 17:54:07 +00:00
|
|
|
std::vector<drgn_type *> enumTypes;
|
2022-12-19 14:37:51 +00:00
|
|
|
std::vector<std::string> knownTypes;
|
2023-01-04 17:54:07 +00:00
|
|
|
drgn_qualified_type rootType;
|
|
|
|
drgn_qualified_type rootTypeToIntrospect;
|
2022-12-19 14:37:51 +00:00
|
|
|
|
|
|
|
std::map<std::string, std::string> typedefMap;
|
2023-01-04 17:54:07 +00:00
|
|
|
std::map<drgn_type *, std::vector<ParentMember>> parentClasses;
|
2023-01-25 14:37:16 +00:00
|
|
|
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;
|
2023-01-04 17:54:07 +00:00
|
|
|
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
|
|
|
|
|
|
|
std::set<ContainerInfo> containerTypesFuncDef;
|
|
|
|
|
|
|
|
std::map<std::string, PaddingInfo> paddedStructs;
|
|
|
|
|
2023-01-04 17:54:07 +00:00
|
|
|
std::map<drgn_type *, std::vector<DrgnClassMemberInfo>> &getClassMembersMap();
|
2022-12-19 14:37:51 +00:00
|
|
|
|
|
|
|
class DrgnString {
|
|
|
|
struct FreeDeleter {
|
|
|
|
void operator()(void *allocated) {
|
|
|
|
free(allocated);
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
public:
|
|
|
|
std::string_view contents;
|
|
|
|
DrgnString(char *data, size_t length)
|
|
|
|
: contents{data, length}, _data{data} {
|
|
|
|
}
|
|
|
|
DrgnString() = delete;
|
|
|
|
|
|
|
|
private:
|
|
|
|
std::unique_ptr<char, FreeDeleter> _data;
|
|
|
|
};
|
|
|
|
|
|
|
|
static void prependQualifiers(enum drgn_qualifiers, std::string &sb);
|
|
|
|
static std::string stripFullyQualifiedName(
|
|
|
|
const std::string &fullyQualifiedName);
|
|
|
|
std::string stripFullyQualifiedNameWithSeparators(
|
|
|
|
const std::string &fullyQualifiedname);
|
|
|
|
static void removeTemplateParamAtIndex(std::vector<std::string> ¶ms,
|
|
|
|
const size_t index);
|
2023-01-04 17:54:07 +00:00
|
|
|
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(
|
2023-01-04 17:54:07 +00:00
|
|
|
const std::map<drgn_type *, drgn_type *> &typedefTypeMap);
|
2022-12-19 14:37:51 +00:00
|
|
|
|
2023-01-04 17:54:07 +00:00
|
|
|
std::optional<ContainerInfo> getContainerInfo(drgn_type *type);
|
2022-12-19 14:37:51 +00:00
|
|
|
void printAllTypes();
|
|
|
|
void printAllTypeNames();
|
|
|
|
|
2023-01-04 17:54:07 +00:00
|
|
|
static void addPaddingForBaseClass(drgn_type *type,
|
2022-12-19 14:37:51 +00:00
|
|
|
std::vector<std::string> &def);
|
2023-01-04 17:54:07 +00:00
|
|
|
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);
|
2023-01-04 17:54:07 +00:00
|
|
|
bool generateStructDef(drgn_type *e, std::string &code);
|
|
|
|
bool getDrgnTypeName(drgn_type *type, std::string &outName);
|
2022-12-19 14:37:51 +00:00
|
|
|
|
2023-01-04 17:54:07 +00:00
|
|
|
bool getDrgnTypeNameInt(drgn_type *type, std::string &outName);
|
2023-01-25 14:37:16 +00:00
|
|
|
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);
|
|
|
|
|
2023-01-04 17:54:07 +00:00
|
|
|
bool getMemberDefinition(drgn_type *type);
|
2022-12-19 14:37:51 +00:00
|
|
|
bool isKnownType(const std::string &type);
|
|
|
|
bool isKnownType(const std::string &type, std::string &matched);
|
|
|
|
|
|
|
|
static bool getTemplateParams(
|
2023-01-04 17:54:07 +00:00
|
|
|
drgn_type *type, size_t numTemplateParams,
|
|
|
|
std::vector<std::pair<drgn_qualified_type, std::string>> &v);
|
2022-12-19 14:37:51 +00:00
|
|
|
|
2023-01-04 17:54:07 +00:00
|
|
|
bool enumerateTemplateParamIdxs(drgn_type *type,
|
2022-12-19 14:37:51 +00:00
|
|
|
const ContainerInfo &containerInfo,
|
|
|
|
const std::vector<size_t> ¶mIdxs,
|
|
|
|
bool &ifStub);
|
2023-01-04 17:54:07 +00:00
|
|
|
bool getContainerTemplateParams(drgn_type *type, bool &ifStub);
|
2023-01-25 14:37:16 +00:00
|
|
|
void enumerateDescendants(drgn_type *type, drgn_type *baseType);
|
2023-01-04 17:54:07 +00:00
|
|
|
void getFuncDefinitionStr(std::string &code, drgn_type *type,
|
2022-12-19 14:37:51 +00:00
|
|
|
const std::string &typeName);
|
2023-01-04 17:54:07 +00:00
|
|
|
std::optional<uint64_t> getDrgnTypeSize(drgn_type *type);
|
2022-12-19 14:37:51 +00:00
|
|
|
|
2023-01-04 17:54:07 +00:00
|
|
|
std::optional<std::string> getNameForType(drgn_type *type);
|
2022-12-19 14:37:51 +00:00
|
|
|
|
2023-01-04 17:54:07 +00:00
|
|
|
static std::string preProcessUniquePtr(drgn_type *type, std::string name);
|
|
|
|
std::string transformTypeName(drgn_type *type, std::string &text);
|
2022-12-19 14:37:51 +00:00
|
|
|
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);
|
|
|
|
static void deduplicateMemberName(
|
|
|
|
std::unordered_map<std::string, int> &memberNames,
|
|
|
|
std::string &memberName);
|
|
|
|
std::optional<uint64_t> generateMember(
|
|
|
|
const DrgnClassMemberInfo &m,
|
|
|
|
std::unordered_map<std::string, int> &memberNames,
|
|
|
|
uint64_t currOffsetBits, std::string &code, bool isInUnion);
|
2023-01-04 17:54:07 +00:00
|
|
|
bool generateParent(drgn_type *p,
|
2022-12-19 14:37:51 +00:00
|
|
|
std::unordered_map<std::string, int> &memberNames,
|
|
|
|
uint64_t &currOffsetBits, std::string &code,
|
|
|
|
size_t offsetToNextMember);
|
2023-01-04 17:54:07 +00:00
|
|
|
std::optional<uint64_t> getAlignmentRequirements(drgn_type *e);
|
|
|
|
bool generateStructMembers(drgn_type *e,
|
2022-12-19 14:37:51 +00:00
|
|
|
std::unordered_map<std::string, int> &memberNames,
|
|
|
|
std::string &code, uint64_t &out_offset_bits,
|
|
|
|
PaddingInfo &paddingInfo,
|
|
|
|
bool &violatesAlignmentRequirement,
|
|
|
|
size_t offsetToNextMember);
|
2023-01-04 17:54:07 +00:00
|
|
|
void getFuncDefClassMembers(std::string &code, drgn_type *type,
|
2022-12-19 14:37:51 +00:00
|
|
|
std::unordered_map<std::string, int> &memberNames,
|
|
|
|
bool skipPadding = false);
|
2023-01-04 17:54:07 +00:00
|
|
|
bool isDrgnSizeComplete(drgn_type *type);
|
2022-12-19 14:37:51 +00:00
|
|
|
|
2023-01-04 17:54:07 +00:00
|
|
|
static bool getEnumUnderlyingTypeStr(drgn_type *e,
|
2022-12-19 14:37:51 +00:00
|
|
|
std::string &enumUnderlyingTypeStr);
|
|
|
|
|
|
|
|
bool ifEnumerateClass(const std::string &typeName);
|
|
|
|
|
2023-01-04 17:54:07 +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,
|
2022-12-19 14:37:51 +00:00
|
|
|
const std::string &typeName,
|
|
|
|
bool &isStubbed);
|
|
|
|
bool ifGenerateMemberDefinition(const std::string &typeName);
|
2023-01-04 17:54:07 +00:00
|
|
|
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);
|
2023-01-04 17:54:07 +00:00
|
|
|
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_");
|
|
|
|
}
|
2023-01-04 17:54:07 +00:00
|
|
|
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);
|
|
|
|
|
2023-01-04 17:54:07 +00:00
|
|
|
bool isNumMemberGreaterThanZero(drgn_type *type);
|
|
|
|
void getClassMembersIncludingParent(drgn_type *type,
|
2022-12-19 14:37:51 +00:00
|
|
|
std::vector<DrgnClassMemberInfo> &out);
|
|
|
|
bool staticAssertMemberOffsets(
|
2023-01-04 17:54:07 +00:00
|
|
|
const std::string &struct_name, drgn_type *struct_type,
|
2022-12-19 14:37:51 +00:00
|
|
|
std::string &assert_str,
|
|
|
|
std::unordered_map<std::string, int> &member_names,
|
|
|
|
uint64_t base_offset = 0);
|
2023-01-04 17:54:07 +00:00
|
|
|
bool addStaticAssertsForType(drgn_type *type, bool generateAssertsForOffsets,
|
2022-12-19 14:37:51 +00:00
|
|
|
std::string &code);
|
2023-01-04 17:54:07 +00:00
|
|
|
bool buildNameInt(drgn_type *type, std::string &nameWithoutTemplate,
|
2022-12-19 14:37:51 +00:00
|
|
|
std::string &outName);
|
|
|
|
void replaceTemplateOperator(
|
2023-01-04 17:54:07 +00:00
|
|
|
std::vector<std::pair<drgn_qualified_type, std::string>> &template_params,
|
2022-12-19 14:37:51 +00:00
|
|
|
std::vector<std::string> &template_params_strings, size_t index);
|
|
|
|
void replaceTemplateParameters(
|
2023-01-04 17:54:07 +00:00
|
|
|
drgn_type *type,
|
|
|
|
std::vector<std::pair<drgn_qualified_type, std::string>> &template_params,
|
2022-12-19 14:37:51 +00:00
|
|
|
std::vector<std::string> &template_params_strings,
|
|
|
|
const std::string &nameWithoutTemplate);
|
|
|
|
};
|