mirror of
https://github.com/JakeHillion/object-introspection.git
synced 2024-11-12 21:56:54 +00:00
features: switch to bitset
This commit is contained in:
parent
66a171eedc
commit
a9ace14466
@ -45,4 +45,10 @@ const char* featureToStr(Feature f) {
|
||||
}
|
||||
}
|
||||
|
||||
FeatureSet::FeatureSet(std::initializer_list<Feature> features) {
|
||||
for (auto f : features) {
|
||||
(*this)[f] = true;
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace ObjectIntrospection
|
||||
|
@ -16,6 +16,7 @@
|
||||
#pragma once
|
||||
|
||||
#include <array>
|
||||
#include <bitset>
|
||||
#include <string_view>
|
||||
|
||||
#define OI_FEATURE_LIST \
|
||||
@ -43,4 +44,23 @@ constexpr std::array allFeatures = {
|
||||
#undef X
|
||||
};
|
||||
|
||||
class FeatureSet {
|
||||
private:
|
||||
using BitsetType = std::bitset<allFeatures.size() + 1>;
|
||||
|
||||
public:
|
||||
FeatureSet() = default;
|
||||
FeatureSet(std::initializer_list<Feature>);
|
||||
|
||||
constexpr bool operator[](Feature f) const {
|
||||
return bitset[(size_t)f];
|
||||
}
|
||||
BitsetType::reference operator[](Feature f) {
|
||||
return bitset[(size_t)f];
|
||||
}
|
||||
|
||||
private:
|
||||
BitsetType bitset;
|
||||
};
|
||||
|
||||
} // namespace ObjectIntrospection
|
||||
|
@ -62,13 +62,6 @@ std::unique_ptr<OICodeGen> OICodeGen::buildFromConfig(const Config& c,
|
||||
|
||||
OICodeGen::OICodeGen(const Config& c, SymbolService& s)
|
||||
: config{c}, symbols{s} {
|
||||
chaseRawPointers = config.features.contains(Feature::ChaseRawPointers);
|
||||
packStructs = config.features.contains(Feature::PackStructs);
|
||||
genPaddingStats = config.features.contains(Feature::GenPaddingStats);
|
||||
captureThriftIsset = config.features.contains(Feature::CaptureThriftIsset);
|
||||
polymorphicInheritance =
|
||||
config.features.contains(Feature::PolymorphicInheritance);
|
||||
|
||||
// TODO: Should folly::Range just be added as a container?
|
||||
auto typesToStub = std::array{
|
||||
"SharedMutex",
|
||||
@ -998,7 +991,7 @@ bool OICodeGen::recordChildren(drgn_type* type) {
|
||||
* types in the program to build the reverse mapping.
|
||||
*/
|
||||
bool OICodeGen::enumerateChildClasses() {
|
||||
if (!polymorphicInheritance) {
|
||||
if (!feature(Feature::PolymorphicInheritance)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -1327,7 +1320,8 @@ bool OICodeGen::isEmptyClassOrFunctionType(drgn_type* type,
|
||||
* one or more virtual member functions or virtual base classes).
|
||||
*/
|
||||
bool OICodeGen::isDynamic(drgn_type* type) const {
|
||||
if (!polymorphicInheritance || !drgn_type_has_virtuality(type)) {
|
||||
if (!feature(Feature::PolymorphicInheritance) ||
|
||||
!drgn_type_has_virtuality(type)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -2008,7 +2002,7 @@ bool OICodeGen::getDrgnTypeNameInt(drgn_type* type, std::string& outName) {
|
||||
name.assign(drgn_type_name(type));
|
||||
} else if (drgn_type_kind(type) == DRGN_TYPE_POINTER) {
|
||||
drgn_type* underlyingType = getPtrUnderlyingType(type);
|
||||
if (chaseRawPointers &&
|
||||
if (feature(Feature::ChaseRawPointers) &&
|
||||
drgn_type_kind(underlyingType) != DRGN_TYPE_FUNCTION) {
|
||||
// For pointers, figure out name for the underlying type then add
|
||||
// appropriate number of '*'
|
||||
@ -2278,7 +2272,7 @@ bool OICodeGen::generateStructDef(drgn_type* e, std::string& code) {
|
||||
|
||||
std::string structDefinition;
|
||||
|
||||
if (paddingInfo.paddingSize != 0 && genPaddingStats) {
|
||||
if (paddingInfo.paddingSize != 0 && feature(Feature::GenPaddingStats)) {
|
||||
structDefinition.append("/* offset | size */ ");
|
||||
}
|
||||
|
||||
@ -2294,7 +2288,8 @@ bool OICodeGen::generateStructDef(drgn_type* e, std::string& code) {
|
||||
std::to_string(*alignment / CHAR_BIT) + ")");
|
||||
}
|
||||
|
||||
if (packStructs && (kind == DRGN_TYPE_STRUCT || kind == DRGN_TYPE_CLASS) &&
|
||||
if (feature(Feature::PackStructs) &&
|
||||
(kind == DRGN_TYPE_STRUCT || kind == DRGN_TYPE_CLASS) &&
|
||||
violatesAlignmentRequirement && paddingInfo.paddingSize == 0) {
|
||||
structDefinition.append(" __attribute__((__packed__))");
|
||||
}
|
||||
@ -2313,7 +2308,7 @@ bool OICodeGen::generateStructDef(drgn_type* e, std::string& code) {
|
||||
|
||||
structDefinition.append("};\n");
|
||||
|
||||
if (genPaddingStats) {
|
||||
if (feature(Feature::GenPaddingStats)) {
|
||||
auto paddedStructFound = paddedStructs.find(*tmpStr);
|
||||
|
||||
if (paddedStructFound == paddedStructs.end()) {
|
||||
@ -2509,7 +2504,8 @@ std::optional<uint64_t> OICodeGen::generateMember(
|
||||
currOffsetBits = 0;
|
||||
VLOG(1) << "Member size: " << memberSize;
|
||||
} else {
|
||||
addSizeComment(genPaddingStats, code, currOffsetBits, memberSize);
|
||||
addSizeComment(feature(Feature::GenPaddingStats), code, currOffsetBits,
|
||||
memberSize);
|
||||
currOffsetBits = currOffsetBits + memberSize;
|
||||
}
|
||||
|
||||
@ -2709,12 +2705,12 @@ bool OICodeGen::generateStructMembers(
|
||||
bool isThriftIssetStruct =
|
||||
typeName.starts_with("isset_bitset<") && memberName == "__isset";
|
||||
|
||||
if (captureThriftIsset && isThriftIssetStruct &&
|
||||
if (feature(Feature::CaptureThriftIsset) && isThriftIssetStruct &&
|
||||
memberIndex == members.size() - 1) {
|
||||
thriftIssetStructTypes.insert(e);
|
||||
}
|
||||
|
||||
if (genPaddingStats) {
|
||||
if (feature(Feature::GenPaddingStats)) {
|
||||
paddingInfo.isThriftStruct = isThriftIssetStruct;
|
||||
|
||||
/*
|
||||
@ -3258,12 +3254,12 @@ bool OICodeGen::generateJitCode(std::string& code) {
|
||||
functionsCode.append("namespace OIInternal {\nnamespace {\n");
|
||||
functionsCode.append("// functions -----\n");
|
||||
if (!funcGen.DeclareGetSizeFuncs(functionsCode, containerTypesFuncDef,
|
||||
chaseRawPointers)) {
|
||||
feature(Feature::ChaseRawPointers))) {
|
||||
LOG(ERROR) << "declaring get size for containers failed";
|
||||
return false;
|
||||
}
|
||||
|
||||
if (chaseRawPointers) {
|
||||
if (feature(Feature::ChaseRawPointers)) {
|
||||
functionsCode.append(R"(
|
||||
template<typename T>
|
||||
void getSizeType(const T* t, size_t& returnArg);
|
||||
@ -3284,7 +3280,7 @@ bool OICodeGen::generateJitCode(std::string& code) {
|
||||
}
|
||||
}
|
||||
|
||||
if (config.useDataSegment || chaseRawPointers) {
|
||||
if (config.useDataSegment || feature(Feature::ChaseRawPointers)) {
|
||||
funcGen.DeclareStoreData(functionsCode);
|
||||
}
|
||||
|
||||
@ -3296,12 +3292,12 @@ bool OICodeGen::generateJitCode(std::string& code) {
|
||||
}
|
||||
|
||||
if (!funcGen.DefineGetSizeFuncs(functionsCode, containerTypesFuncDef,
|
||||
chaseRawPointers)) {
|
||||
feature(Feature::ChaseRawPointers))) {
|
||||
LOG(ERROR) << "defining get size for containers failed";
|
||||
return false;
|
||||
}
|
||||
|
||||
if (chaseRawPointers) {
|
||||
if (feature(Feature::ChaseRawPointers)) {
|
||||
functionsCode.append(R"(
|
||||
template<typename T>
|
||||
void getSizeType(const T* s_ptr, size_t& returnArg)
|
||||
@ -3780,7 +3776,7 @@ std::vector<std::string> OICodeGen::Config::toOptions() const {
|
||||
options.reserve(allFeatures.size());
|
||||
|
||||
for (const auto f : allFeatures) {
|
||||
if (features.contains(f)) {
|
||||
if (features[f]) {
|
||||
options.emplace_back(std::string("-f") + featureToStr(f));
|
||||
} else {
|
||||
options.emplace_back(std::string("-F") + featureToStr(f));
|
||||
|
@ -57,7 +57,7 @@ class OICodeGen {
|
||||
*/
|
||||
bool useDataSegment;
|
||||
|
||||
std::set<Feature> features{};
|
||||
FeatureSet features{};
|
||||
|
||||
std::set<fs::path> containerConfigPaths{};
|
||||
std::set<std::string> defaultHeaders{};
|
||||
@ -113,12 +113,6 @@ class OICodeGen {
|
||||
Config config{};
|
||||
FuncGen funcGen;
|
||||
|
||||
bool chaseRawPointers;
|
||||
bool packStructs;
|
||||
bool genPaddingStats;
|
||||
bool captureThriftIsset;
|
||||
bool polymorphicInheritance;
|
||||
|
||||
using ContainerTypeMapEntry =
|
||||
std::pair<std::reference_wrapper<const ContainerInfo>,
|
||||
std::vector<drgn_qualified_type>>;
|
||||
@ -185,6 +179,9 @@ class OICodeGen {
|
||||
std::unique_ptr<char, FreeDeleter> _data;
|
||||
};
|
||||
|
||||
bool feature(Feature f) const {
|
||||
return config.features[f];
|
||||
}
|
||||
static void prependQualifiers(enum drgn_qualifiers, std::string& sb);
|
||||
static std::string stripFullyQualifiedName(
|
||||
const std::string& fullyQualifiedName);
|
||||
|
@ -2852,7 +2852,7 @@ bool OIDebugger::processTargetData() {
|
||||
const auto& [rootType, typeHierarchy, paddingInfos] = typeInfo->second;
|
||||
VLOG(1) << "Root type addr: " << (void*)rootType.type.type;
|
||||
|
||||
if (treeBuilderConfig.features.contains(Feature::GenPaddingStats)) {
|
||||
if (treeBuilderConfig.features[Feature::GenPaddingStats]) {
|
||||
paddingHunter.localPaddedStructs = paddingInfos;
|
||||
typeTree.setPaddedStructs(&paddingHunter.localPaddedStructs);
|
||||
}
|
||||
@ -2876,7 +2876,7 @@ bool OIDebugger::processTargetData() {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (treeBuilderConfig.features.contains(Feature::GenPaddingStats)) {
|
||||
if (treeBuilderConfig.features[Feature::GenPaddingStats]) {
|
||||
paddingHunter.processLocalPaddingInfo();
|
||||
}
|
||||
}
|
||||
@ -2890,7 +2890,7 @@ bool OIDebugger::processTargetData() {
|
||||
typeTree.dumpJson();
|
||||
}
|
||||
|
||||
if (treeBuilderConfig.features.contains(Feature::GenPaddingStats)) {
|
||||
if (treeBuilderConfig.features[Feature::GenPaddingStats]) {
|
||||
paddingHunter.outputPaddingInfo();
|
||||
}
|
||||
|
||||
|
@ -31,7 +31,7 @@ namespace OIUtils {
|
||||
using namespace ObjectIntrospection;
|
||||
using namespace std::literals;
|
||||
|
||||
std::optional<std::set<Feature>> processConfigFile(
|
||||
std::optional<ObjectIntrospection::FeatureSet> processConfigFile(
|
||||
const std::string& configFilePath,
|
||||
std::map<Feature, bool> featureMap,
|
||||
OICompiler::Config& compilerConfig,
|
||||
@ -153,10 +153,10 @@ std::optional<std::set<Feature>> processConfigFile(
|
||||
}
|
||||
}
|
||||
|
||||
std::set<Feature> featuresSet;
|
||||
ObjectIntrospection::FeatureSet featuresSet;
|
||||
for (auto [k, v] : featureMap) {
|
||||
if (v) {
|
||||
featuresSet.insert(k);
|
||||
featuresSet[k] = true;
|
||||
}
|
||||
}
|
||||
return featuresSet;
|
||||
|
@ -24,7 +24,7 @@
|
||||
|
||||
namespace OIUtils {
|
||||
|
||||
std::optional<std::set<Feature>> processConfigFile(
|
||||
std::optional<ObjectIntrospection::FeatureSet> processConfigFile(
|
||||
const std::string& configFilePath,
|
||||
std::map<Feature, bool> featureMap,
|
||||
OICompiler::Config& compilerConfig,
|
||||
|
@ -53,9 +53,6 @@ enum class TrackPointerTag : uint64_t {
|
||||
TreeBuilder::TreeBuilder(Config c) : config{std::move(c)} {
|
||||
buffer = std::make_unique<msgpack::sbuffer>();
|
||||
|
||||
chaseRawPointers = config.features.contains(Feature::ChaseRawPointers);
|
||||
genPaddingStats = config.features.contains(Feature::GenPaddingStats);
|
||||
|
||||
auto testdbPath = "/tmp/testdb_" + std::to_string(getpid());
|
||||
if (auto status = rocksdb::DestroyDB(testdbPath, {}); !status.ok()) {
|
||||
LOG(FATAL) << "RocksDB error while destroying database: "
|
||||
@ -429,7 +426,7 @@ TreeBuilder::Node TreeBuilder::process(NodeID id, Variable variable) {
|
||||
if (!variable.isStubbed) {
|
||||
switch (drgn_type_kind(variable.type)) {
|
||||
case DRGN_TYPE_POINTER:
|
||||
if (chaseRawPointers) {
|
||||
if (config.features[Feature::ChaseRawPointers]) {
|
||||
// Pointers to incomplete types are stubbed out
|
||||
// See OICodeGen::enumeratePointerType
|
||||
if (th->knownDummyTypeList.contains(variable.type)) {
|
||||
@ -544,7 +541,7 @@ TreeBuilder::Node TreeBuilder::process(NodeID id, Variable variable) {
|
||||
break;
|
||||
}
|
||||
|
||||
if (genPaddingStats) {
|
||||
if (config.features[Feature::GenPaddingStats]) {
|
||||
auto entry = paddedStructs->find(node.typeName);
|
||||
if (entry != paddedStructs->end()) {
|
||||
entry->second.instancesCnt++;
|
||||
|
@ -41,7 +41,7 @@ class TreeBuilder {
|
||||
struct Config {
|
||||
// Don't set default values for the config so the user gets
|
||||
// an "unitialized field" warning if he missed any.
|
||||
std::set<ObjectIntrospection::Feature> features;
|
||||
ObjectIntrospection::FeatureSet features;
|
||||
bool logAllStructs;
|
||||
bool dumpDataSegment;
|
||||
std::optional<std::string> jsonPath;
|
||||
@ -69,9 +69,6 @@ class TreeBuilder {
|
||||
const std::vector<uint64_t>* oidData = nullptr;
|
||||
std::map<std::string, PaddingInfo>* paddedStructs = nullptr;
|
||||
|
||||
bool genPaddingStats;
|
||||
bool chaseRawPointers;
|
||||
|
||||
/*
|
||||
* The RocksDB output needs versioning so they are imported correctly in
|
||||
* Scuba. Version 1 had no concept of versioning and no header.
|
||||
|
@ -120,10 +120,8 @@ static std::ostream&
|
||||
operator<<(std::ostream& out, TreeBuilder::Config tbc) {
|
||||
out << "TreeBuilde::Config = [";
|
||||
out << "\n logAllStructs = " << tbc.logAllStructs;
|
||||
out << "\n chaseRawPointers = "
|
||||
<< tbc.features.contains(Feature::ChaseRawPointers);
|
||||
out << "\n genPaddingStats = "
|
||||
<< tbc.features.contains(Feature::GenPaddingStats);
|
||||
out << "\n chaseRawPointers = " << tbc.features[Feature::ChaseRawPointers];
|
||||
out << "\n genPaddingStats = " << tbc.features[Feature::GenPaddingStats];
|
||||
out << "\n dumpDataSegment = " << tbc.dumpDataSegment;
|
||||
out << "\n jsonPath = " << (tbc.jsonPath ? *tbc.jsonPath : "NONE");
|
||||
out << "\n]\n";
|
||||
@ -157,10 +155,10 @@ int main(int argc, char* argv[]) {
|
||||
true; // Weird that we're setting it to true, again...
|
||||
break;
|
||||
case 'n':
|
||||
tbConfig.features.insert(Feature::ChaseRawPointers);
|
||||
tbConfig.features[Feature::ChaseRawPointers] = true;
|
||||
break;
|
||||
case 'w':
|
||||
tbConfig.features.erase(Feature::GenPaddingStats);
|
||||
tbConfig.features[Feature::GenPaddingStats] = false;
|
||||
break;
|
||||
case 'J':
|
||||
tbConfig.jsonPath = optarg ? optarg : "oid_out.json";
|
||||
@ -189,7 +187,7 @@ int main(int argc, char* argv[]) {
|
||||
|
||||
TreeBuilder typeTree(tbConfig);
|
||||
|
||||
if (tbConfig.features.contains(Feature::GenPaddingStats)) {
|
||||
if (tbConfig.features[Feature::GenPaddingStats]) {
|
||||
LOG(INFO) << "Setting-up PaddingHunter...";
|
||||
typeTree.setPaddedStructs(&paddingInfos);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user