Allow parsing binaries via `pacparse`
This commit is contained in:
parent
df55813d59
commit
653867a49c
|
@ -24,14 +24,35 @@ set(CONFIGURATION_PACKAGE_SUFFIX
|
||||||
find_package(c++utilities${CONFIGURATION_PACKAGE_SUFFIX} 5.0.0 REQUIRED)
|
find_package(c++utilities${CONFIGURATION_PACKAGE_SUFFIX} 5.0.0 REQUIRED)
|
||||||
use_cpp_utilities()
|
use_cpp_utilities()
|
||||||
|
|
||||||
|
# find reflective-rapidjson
|
||||||
|
find_package(reflective_rapidjson${CONFIGURATION_PACKAGE_SUFFIX} REQUIRED)
|
||||||
|
use_reflective_rapidjson(VISIBILITY PUBLIC)
|
||||||
|
|
||||||
# find backend libraries
|
# find backend libraries
|
||||||
find_package(libpkg ${META_APP_VERSION} REQUIRED)
|
find_package(libpkg ${META_APP_VERSION} REQUIRED)
|
||||||
use_libpkg()
|
use_libpkg()
|
||||||
|
|
||||||
list(APPEND PRIVATE_LIBRARIES pthread)
|
list(APPEND PRIVATE_LIBRARIES pthread)
|
||||||
|
|
||||||
# include modules to apply configuration
|
# apply basic configuration
|
||||||
include(BasicConfig)
|
include(BasicConfig)
|
||||||
|
|
||||||
|
# add reflection generator invocation
|
||||||
|
include(ReflectionGenerator)
|
||||||
|
add_reflection_generator_invocation(
|
||||||
|
INPUT_FILES
|
||||||
|
main.cpp
|
||||||
|
CLANG_OPTIONS_FROM_TARGETS
|
||||||
|
"${META_TARGET_NAME}"
|
||||||
|
CLANG_OPTIONS_FROM_DEPENDENCIES
|
||||||
|
"${PUBLIC_LIBRARIES};${PRIVATE_LIBRARIES}"
|
||||||
|
GENERATORS
|
||||||
|
json
|
||||||
|
OUTPUT_LISTS
|
||||||
|
SRC_FILES
|
||||||
|
ERROR_RESILIENT)
|
||||||
|
|
||||||
|
# apply further configuration
|
||||||
include(WindowsResources)
|
include(WindowsResources)
|
||||||
include(AppTarget)
|
include(AppTarget)
|
||||||
include(TestTarget)
|
include(TestTarget)
|
||||||
|
|
|
@ -11,6 +11,8 @@
|
||||||
|
|
||||||
#include <reflective_rapidjson/json/reflector.h>
|
#include <reflective_rapidjson/json/reflector.h>
|
||||||
|
|
||||||
|
#include <atomic>
|
||||||
|
#include <cstdlib>
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include <mutex>
|
#include <mutex>
|
||||||
#include <thread>
|
#include <thread>
|
||||||
|
@ -18,56 +20,106 @@
|
||||||
|
|
||||||
using namespace CppUtilities;
|
using namespace CppUtilities;
|
||||||
|
|
||||||
|
struct BinaryInfo : public ReflectiveRapidJSON::JsonSerializable<BinaryInfo> {
|
||||||
|
std::string name;
|
||||||
|
std::string architecture;
|
||||||
|
std::set<std::string> symbols;
|
||||||
|
std::set<std::string> requiredLibs;
|
||||||
|
std::string rpath;
|
||||||
|
std::string prefix;
|
||||||
|
bool isBigEndian = false;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct PacparseResults : public ReflectiveRapidJSON::JsonSerializable<PacparseResults> {
|
||||||
|
std::vector<std::shared_ptr<LibPkg::Package>> packages;
|
||||||
|
std::vector<BinaryInfo> binaries;
|
||||||
|
};
|
||||||
|
|
||||||
int main(int argc, const char *argv[])
|
int main(int argc, const char *argv[])
|
||||||
{
|
{
|
||||||
SET_APPLICATION_INFO;
|
SET_APPLICATION_INFO;
|
||||||
|
|
||||||
// read cli args
|
// read cli args
|
||||||
auto parser = ArgumentParser();
|
auto parser = ArgumentParser();
|
||||||
auto packagesArg = Argument("packages", 'p', "specifies the paths of the package files to parse");
|
auto packagesArg = ConfigValueArgument("packages", 'p', "specifies the paths of the package files to parse", { "path" });
|
||||||
packagesArg.setRequiredValueCount(Argument::varValueCount);
|
packagesArg.setRequiredValueCount(Argument::varValueCount);
|
||||||
packagesArg.setValueNames({ "path" });
|
|
||||||
packagesArg.setImplicit(true);
|
packagesArg.setImplicit(true);
|
||||||
parser.setMainArguments({ &packagesArg, &parser.helpArg() });
|
auto binariesArg = ConfigValueArgument("binaries", 'b', "specifies the paths of the binaries", { "path" });
|
||||||
|
binariesArg.setRequiredValueCount(Argument::varValueCount);
|
||||||
|
parser.setMainArguments({ &packagesArg, &binariesArg, &parser.helpArg() });
|
||||||
parser.setDefaultArgument(&parser.helpArg());
|
parser.setDefaultArgument(&parser.helpArg());
|
||||||
parser.parseArgs(argc, argv);
|
parser.parseArgs(argc, argv);
|
||||||
|
if (parser.helpArg().isPresent()) {
|
||||||
|
return EXIT_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
auto packages = std::vector<std::shared_ptr<LibPkg::Package>>();
|
auto res = PacparseResults();
|
||||||
auto packageMutex = std::mutex();
|
auto packageMutex = std::mutex();
|
||||||
|
auto binaryMutex = std::mutex();
|
||||||
|
auto returnCode = std::atomic<int>(EXIT_SUCCESS);
|
||||||
|
|
||||||
auto pi = std::vector<const char *>::const_iterator();
|
auto pi = std::vector<const char *>::const_iterator();
|
||||||
auto pend = std::vector<const char *>::const_iterator();
|
auto pend = std::vector<const char *>::const_iterator();
|
||||||
auto piMutex = std::mutex();
|
auto bi = std::vector<const char *>::const_iterator();
|
||||||
|
auto bend = std::vector<const char *>::const_iterator();
|
||||||
|
auto imutex = std::mutex();
|
||||||
if (packagesArg.isPresent()) {
|
if (packagesArg.isPresent()) {
|
||||||
const auto &packagePaths = packagesArg.values();
|
const auto &packagePaths = packagesArg.values();
|
||||||
pi = packagePaths.begin();
|
pi = packagePaths.begin();
|
||||||
pend = packagePaths.end();
|
pend = packagePaths.end();
|
||||||
packages.reserve(packagePaths.size());
|
res.packages.reserve(packagePaths.size());
|
||||||
|
}
|
||||||
|
if (binariesArg.isPresent()) {
|
||||||
|
const auto &binaryPaths = binariesArg.values();
|
||||||
|
bi = binaryPaths.begin();
|
||||||
|
bend = binaryPaths.end();
|
||||||
|
res.binaries.reserve(binaryPaths.size());
|
||||||
}
|
}
|
||||||
|
|
||||||
const auto processPackage = [&] {
|
const auto processPackage = [&] {
|
||||||
for (;;) {
|
for (;;) {
|
||||||
// get next package path
|
// get next package path
|
||||||
auto piLock = std::unique_lock<std::mutex>(piMutex);
|
const char *path = nullptr;
|
||||||
if (pi == pend) {
|
auto isBinary = false;
|
||||||
|
auto ilock = std::unique_lock<std::mutex>(imutex);
|
||||||
|
if (pi != pend) {
|
||||||
|
path = *pi++;
|
||||||
|
} else if (bi != bend) {
|
||||||
|
isBinary = true;
|
||||||
|
path = *bi++;
|
||||||
|
} else {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
auto packagePath = *(pi++);
|
ilock.unlock();
|
||||||
piLock.unlock();
|
|
||||||
|
|
||||||
// parse package
|
// parse package
|
||||||
try {
|
try {
|
||||||
auto package = LibPkg::Package::fromPkgFile(packagePath);
|
if (isBinary) {
|
||||||
auto packageLock = std::unique_lock<std::mutex>(packageMutex);
|
auto binary = LibPkg::Binary();
|
||||||
packages.emplace_back(std::move(package));
|
binary.load(path);
|
||||||
|
auto binaryLock = std::unique_lock<std::mutex>(binaryMutex);
|
||||||
|
auto &binaryInfo = res.binaries.emplace_back();
|
||||||
|
binaryInfo.prefix = binary.addPrefix(std::string_view());
|
||||||
|
binaryInfo.name = std::move(binary.name);
|
||||||
|
binaryInfo.architecture = std::move(binary.architecture);
|
||||||
|
binaryInfo.isBigEndian = binary.isBigEndian;
|
||||||
|
binaryInfo.rpath = std::move(binary.rpath);
|
||||||
|
binaryInfo.symbols = std::move(binary.symbols);
|
||||||
|
binaryInfo.requiredLibs = std::move(binary.requiredLibs);
|
||||||
|
} else {
|
||||||
|
auto package = LibPkg::Package::fromPkgFile(path);
|
||||||
|
auto binaryLock = std::unique_lock<std::mutex>(packageMutex);
|
||||||
|
res.packages.emplace_back(std::move(package));
|
||||||
|
}
|
||||||
} catch (const std::runtime_error &e) {
|
} catch (const std::runtime_error &e) {
|
||||||
std::cerr << "Unable to parse \"" << packagePath << "\": " << e.what() << '\n';
|
std::cerr << "Unable to parse \"" << path << "\": " << e.what() << '\n';
|
||||||
|
returnCode = EXIT_FAILURE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
auto threads
|
auto threads = std::vector<std::thread>(
|
||||||
= std::vector<std::thread>(std::max<std::size_t>(std::min<std::size_t>(std::thread::hardware_concurrency(), packages.capacity()), 1u) - 1);
|
std::max<std::size_t>(std::min<std::size_t>(std::thread::hardware_concurrency(), res.packages.capacity() + res.binaries.capacity()), 1u) - 1);
|
||||||
for (auto &t : threads) {
|
for (auto &t : threads) {
|
||||||
t = std::thread(processPackage);
|
t = std::thread(processPackage);
|
||||||
}
|
}
|
||||||
|
@ -76,7 +128,9 @@ int main(int argc, const char *argv[])
|
||||||
t.join();
|
t.join();
|
||||||
}
|
}
|
||||||
|
|
||||||
const auto json = ReflectiveRapidJSON::JsonReflector::toJson(packages);
|
const auto json = ReflectiveRapidJSON::JsonReflector::toJson(res);
|
||||||
std::cout << std::string_view(json.GetString(), json.GetSize());
|
std::cout << std::string_view(json.GetString(), json.GetSize());
|
||||||
return 0;
|
return returnCode;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#include "reflection/main.h"
|
||||||
|
|
Loading…
Reference in New Issue