Skip to content

Commit

Permalink
Merge branch 'main' of github.com:buildsi/Smeagle into compress_param…
Browse files Browse the repository at this point in the history
…_properties
  • Loading branch information
vsoch committed Aug 13, 2021
2 parents 0d8d980 + cd8e23a commit bec89fe
Show file tree
Hide file tree
Showing 3 changed files with 103 additions and 10 deletions.
3 changes: 3 additions & 0 deletions source/corpora.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@

#include "smeagle/corpora.h"

#include <cstdio>
#include <iostream>
#include <stdexcept>
#include <string>
Expand All @@ -20,6 +21,8 @@ Corpus::Corpus(std::string _library) : library(std::move(_library)){};

// dump all Type Locations to json
void Corpus::toJson() {
// ensure that we can replace already written characters (buffered output)
std::ios::sync_with_stdio(false);
std::cout << "{\n"
<< " \"library\": \"" << library << "\",\n"
<< " \"locations\":\n"
Expand Down
109 changes: 99 additions & 10 deletions source/parser/x86_64/types.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
#include <vector>

namespace smeagle::x86_64::types {

namespace detail {
/*
* This class has an intentially weird layout. We leave the members public to make it an
Expand Down Expand Up @@ -41,9 +42,14 @@ namespace smeagle::x86_64::types {
}
} // namespace detail

// Parse a parameter into a Smeagle parameter
// Note that this function cannot be named toJson as overload resolution won't work
void makeJson(st::Type *param_type, std::string param_name, std::ostream &out, int indent);

struct none_t final : detail::param {
void toJson(std::ostream &out, int indent) const { out << "none"; }
};

struct scalar_t final : detail::param {
void toJson(std::ostream &out, int indent) const {
auto buf = std::string(indent, ' ');
Expand All @@ -62,25 +68,52 @@ namespace smeagle::x86_64::types {
};
template <typename T> struct struct_t final : detail::param {
T *dyninst_obj;
// Keep track of all of the typenames we've seen.
inline static std::unordered_set<std::string> seen;

struct recursive_t final {};

void toJson(std::ostream &out, int indent, recursive_t) { parse(out, indent); }

void toJson(std::ostream &out, int indent) const {
seen.clear();
parse(out, indent);
}

private:
void parse(std::ostream &out, int indent) const {
auto buf = std::string(indent, ' ');
out << buf << "{\n";
detail::toJson(*this, out, indent + 2);
auto fields = *dyninst_obj->getFields();

{
// Do not re-parse the fields of struct types we've seen before
// This prevents endless recursion
auto [underlying_type, ptr_cnt] = unwrap_underlying_type(dyninst_obj);
auto found = seen.find(underlying_type->getName()) != seen.end();
if (found) {
// terminate the base entry for this struct's type
out << "\n" << buf << "}";
return;
}
seen.insert(underlying_type->getName());
}

auto const &fields = *dyninst_obj->getFields();

// Only print if we have fields
if (fields.size() > 0) {
auto buf = std::string(indent + 2, ' ');
out << ",\n" << buf << "\"fields\": [\n";
for (auto *field : fields) {
// If we are at the last entry, no comma
auto endcomma = (field == fields.back()) ? "" : ",";
out << buf << " {\"size\" : \"" << field->getSize() << "\",\n";
out << buf << " \"name\" : \"" << field->getName() << "\",\n";
out << buf << " \"type\" : \"" << field->getType()->getName() << "\"}" << endcomma
<< "\n";

for (auto cur = fields.begin(); cur != fields.end(); ++cur) {
if (cur != fields.begin()) {
out << ",";
}
auto *field = *cur;
makeJson(field->getType(), field->getName(), out, indent + 3);
}
out << buf << "]\n";
out << "]\n";
}
out << buf << "}";
}
Expand All @@ -105,12 +138,19 @@ namespace smeagle::x86_64::types {
detail::toJson(*this, out, indent + 2);
out << ",\n" << buf << " \"constants\": {\n";

// There seems to be a bug with Dyninst duplicating information?
std::unordered_set<std::string> seen;

// TODO: Dyninst does not provide information about underlying type
// which we would need here
auto constants = dyninst_obj->getConstants();
for (auto const &c : constants) {
auto endcomma = (c == constants.back()) ? "" : ",";
out << buf << " \"" << c.first << "\" : \"" << c.second << "\"" << endcomma << "\n";
auto found = seen.find(c.first) != seen.end();
if (!found) {
out << buf << " \"" << c.first << "\" : \"" << c.second << "\"" << endcomma << "\n";
seen.insert(c.first);
}
}
out << buf << "}}";
}
Expand Down Expand Up @@ -138,4 +178,53 @@ namespace smeagle::x86_64::types {
out << "}";
}
};

// Parse a parameter into a Smeagle parameter
void makeJson(st::Type *param_type, std::string param_name, std::ostream &out, int indent) {
auto [underlying_type, ptr_cnt] = unwrap_underlying_type(param_type);
std::string direction = "";

// Scalar Type
if (auto *t = underlying_type->getScalarType()) {
auto param = types::scalar_t{param_name, param_type->getName(), "Scalar", direction,
"", param_type->getSize()};
param.toJson(out, indent);

// Structure Type
} else if (auto *t = underlying_type->getStructType()) {
using dyn_t = std::decay_t<decltype(*t)>;
auto param = types::struct_t<dyn_t>{param_name, param_type->getName(), "Struct", direction,
"", param_type->getSize(), t};
param.toJson(out, indent, types::struct_t<dyn_t>::recursive_t{});

// Union Type
} else if (auto *t = underlying_type->getUnionType()) {
auto param = types::union_t{param_name, param_type->getName(), "Union", direction,
"", param_type->getSize()};
param.toJson(out, indent);

// Array Type
} else if (auto *t = underlying_type->getArrayType()) {
using dyn_t = std::decay_t<decltype(*t)>;
auto param = types::array_t<dyn_t>{param_name, param_type->getName(), "Array", direction,
"", param_type->getSize()};
param.toJson(out, indent);

// Enum Type
} else if (auto *t = underlying_type->getEnumType()) {
using dyn_t = std::decay_t<decltype(*t)>;
auto param = types::enum_t<dyn_t>{param_name, param_type->getName(), "Enum", direction,
"", param_type->getSize(), t};
param.toJson(out, indent);

// Function Type
} else if (auto *t = underlying_type->getFunctionType()) {
auto param = types::function_t{param_name, param_type->getName(), "Function", direction,
"", param_type->getSize()};
param.toJson(out, indent);

} else {
throw std::runtime_error{"Unknown type " + param_type->getName()};
}
}
} // namespace smeagle::x86_64::types
1 change: 1 addition & 0 deletions source/parser/x86_64/x86_64.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
//
// SPDX-License-Identifier: (Apache-2.0 OR MIT)

#include <stdexcept>
#include <string>
#include <vector>

Expand Down

0 comments on commit bec89fe

Please sign in to comment.