Merge branch 'geek1011/symbol-check' (closes #15)
This commit is contained in:
15
.github/workflows/test.yaml
vendored
Normal file
15
.github/workflows/test.yaml
vendored
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
name: Test
|
||||||
|
on: [push, pull_request]
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
build:
|
||||||
|
name: NickelMenu / Symbols
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
container: docker.io/golang:1.14
|
||||||
|
steps:
|
||||||
|
- name: Checkout
|
||||||
|
uses: actions/checkout@v1
|
||||||
|
- name: Build
|
||||||
|
run: cd test/syms && go build -o ../../test.syms .
|
||||||
|
- name: Run
|
||||||
|
run: cd src && ../test.syms
|
||||||
14
res/doc
14
res/doc
@@ -39,10 +39,10 @@
|
|||||||
# This is actually the basename of the watch's filename as specified in its KFMon config (i.e., the png).
|
# This is actually the basename of the watch's filename as specified in its KFMon config (i.e., the png).
|
||||||
# You can also check the output of the 'list' command via the kfmon-ipc tool.
|
# You can also check the output of the 'list' command via the kfmon-ipc tool.
|
||||||
# nickel_setting - one of:
|
# nickel_setting - one of:
|
||||||
# invert - toggles FeatureSettings.InvertScreen (all versions)
|
# invert - toggles FeatureSettings.InvertScreen
|
||||||
# lockscreen - toggles PowerSettings.UnlockEnabled (4.12.12111+)
|
# lockscreen - toggles PowerSettings.UnlockEnabled (4.12.12111+)
|
||||||
# screenshots - toggles FeatureSettings.Screenshots (all versions)
|
# screenshots - toggles FeatureSettings.Screenshots
|
||||||
# force_wifi - toggles DeveloperSettings.ForceWifiOn (note: the setting doesn't apply until you toggle WiFi) (all versions)
|
# force_wifi - toggles DeveloperSettings.ForceWifiOn (note: the setting doesn't apply until you toggle WiFi)
|
||||||
# nickel_extras - the mimetype of the plugin, or one of:
|
# nickel_extras - the mimetype of the plugin, or one of:
|
||||||
# web_browser
|
# web_browser
|
||||||
# unblock_it
|
# unblock_it
|
||||||
@@ -52,11 +52,11 @@
|
|||||||
# word_scramble
|
# word_scramble
|
||||||
# nickel_misc - one of:
|
# nickel_misc - one of:
|
||||||
# force_usb_connection - forces a usb connection dialog to be shown
|
# force_usb_connection - forces a usb connection dialog to be shown
|
||||||
# rescan_books - forces nickel to rescan books
|
# rescan_books - forces nickel to rescan books (4.13.12638+)
|
||||||
# rescan_books_full - forces a full usb connect/disconnect cycle
|
# rescan_books_full - forces a full usb connect/disconnect cycle (4.13.12638+)
|
||||||
# power - one of:
|
# power - one of:
|
||||||
# shutdown
|
# shutdown (4.13.12638+)
|
||||||
# reboot
|
# reboot (4.13.12638+)
|
||||||
# cmd_spawn - the command line to pass to /bin/sh -c (started in /)
|
# cmd_spawn - the command line to pass to /bin/sh -c (started in /)
|
||||||
# It can be prefixed with "quiet:" to prevent the toast with the process PID from being displayed.
|
# It can be prefixed with "quiet:" to prevent the toast with the process PID from being displayed.
|
||||||
# cmd_output - the timeout in milliseconds (0 < t < 10000), a colon, then the command line to pass to /bin/sh -c (started in /)
|
# cmd_output - the timeout in milliseconds (0 < t < 10000), a colon, then the command line to pass to /bin/sh -c (started in /)
|
||||||
|
|||||||
@@ -54,26 +54,31 @@ typedef void N3PowerWorkflowManager;
|
|||||||
NM_ACTION_(nickel_setting) {
|
NM_ACTION_(nickel_setting) {
|
||||||
#define NM_ERR_RET nullptr
|
#define NM_ERR_RET nullptr
|
||||||
|
|
||||||
|
//libnickel 4.6 * _ZN6Device16getCurrentDeviceEv
|
||||||
Device *(*Device_getCurrentDevice)();
|
Device *(*Device_getCurrentDevice)();
|
||||||
reinterpret_cast<void*&>(Device_getCurrentDevice) = dlsym(RTLD_DEFAULT, "_ZN6Device16getCurrentDeviceEv");
|
reinterpret_cast<void*&>(Device_getCurrentDevice) = dlsym(RTLD_DEFAULT, "_ZN6Device16getCurrentDeviceEv");
|
||||||
NM_ASSERT(Device_getCurrentDevice, "could not dlsym Device::getCurrentDevice");
|
NM_ASSERT(Device_getCurrentDevice, "could not dlsym Device::getCurrentDevice");
|
||||||
|
|
||||||
|
//libnickel 4.6 * _ZN8SettingsC2ERK6Deviceb _ZN8SettingsC2ERK6Device
|
||||||
void *(*Settings_Settings)(Settings*, Device*, bool);
|
void *(*Settings_Settings)(Settings*, Device*, bool);
|
||||||
void *(*Settings_SettingsLegacy)(Settings*, Device*);
|
void *(*Settings_SettingsLegacy)(Settings*, Device*);
|
||||||
reinterpret_cast<void*&>(Settings_Settings) = dlsym(RTLD_DEFAULT, "_ZN8SettingsC2ERK6Deviceb");
|
reinterpret_cast<void*&>(Settings_Settings) = dlsym(RTLD_DEFAULT, "_ZN8SettingsC2ERK6Deviceb");
|
||||||
reinterpret_cast<void*&>(Settings_SettingsLegacy) = dlsym(RTLD_DEFAULT, "_ZN8SettingsC2ERK6Device");
|
reinterpret_cast<void*&>(Settings_SettingsLegacy) = dlsym(RTLD_DEFAULT, "_ZN8SettingsC2ERK6Device");
|
||||||
NM_ASSERT(Settings_Settings || Settings_SettingsLegacy, "could not dlsym Settings constructor (new and/or old)");
|
NM_ASSERT(Settings_Settings || Settings_SettingsLegacy, "could not dlsym Settings constructor (new and/or old)");
|
||||||
|
|
||||||
|
//libnickel 4.6 * _ZN8SettingsD2Ev
|
||||||
void *(*Settings_SettingsD)(Settings*);
|
void *(*Settings_SettingsD)(Settings*);
|
||||||
reinterpret_cast<void*&>(Settings_SettingsD) = dlsym(RTLD_DEFAULT, "_ZN8SettingsD2Ev");
|
reinterpret_cast<void*&>(Settings_SettingsD) = dlsym(RTLD_DEFAULT, "_ZN8SettingsD2Ev");
|
||||||
NM_ASSERT(Settings_SettingsD, "could not dlsym Settings destructor");
|
NM_ASSERT(Settings_SettingsD, "could not dlsym Settings destructor");
|
||||||
|
|
||||||
// some settings don't have symbols in a usable form, and some are inlined, so we may need to set them directly
|
// some settings don't have symbols in a usable form, and some are inlined, so we may need to set them directly
|
||||||
|
//libnickel 4.6 * _ZN8Settings10getSettingERK7QStringRK8QVariant
|
||||||
QVariant (*Settings_getSetting)(Settings*, QString const&, QVariant const&); // the last param is the default, also note that this requires a subclass of Settings
|
QVariant (*Settings_getSetting)(Settings*, QString const&, QVariant const&); // the last param is the default, also note that this requires a subclass of Settings
|
||||||
reinterpret_cast<void*&>(Settings_getSetting) = dlsym(RTLD_DEFAULT, "_ZN8Settings10getSettingERK7QStringRK8QVariant");
|
reinterpret_cast<void*&>(Settings_getSetting) = dlsym(RTLD_DEFAULT, "_ZN8Settings10getSettingERK7QStringRK8QVariant");
|
||||||
NM_ASSERT(Settings_getSetting, "could not dlsym Settings::getSetting");
|
NM_ASSERT(Settings_getSetting, "could not dlsym Settings::getSetting");
|
||||||
|
|
||||||
// ditto
|
// ditto
|
||||||
|
//libnickel 4.6 * _ZN8Settings11saveSettingERK7QStringRK8QVariantb
|
||||||
void *(*Settings_saveSetting)(Settings*, QString const&, QVariant const&, bool); // the last param is whether to do a full disk sync immediately (rather than waiting for the kernel to do it)
|
void *(*Settings_saveSetting)(Settings*, QString const&, QVariant const&, bool); // the last param is whether to do a full disk sync immediately (rather than waiting for the kernel to do it)
|
||||||
reinterpret_cast<void*&>(Settings_saveSetting) = dlsym(RTLD_DEFAULT, "_ZN8Settings11saveSettingERK7QStringRK8QVariantb");
|
reinterpret_cast<void*&>(Settings_saveSetting) = dlsym(RTLD_DEFAULT, "_ZN8Settings11saveSettingERK7QStringRK8QVariantb");
|
||||||
NM_ASSERT(Settings_saveSetting, "could not dlsym Settings::saveSetting");
|
NM_ASSERT(Settings_saveSetting, "could not dlsym Settings::saveSetting");
|
||||||
@@ -106,6 +111,7 @@ NM_ACTION_(nickel_setting) {
|
|||||||
#define vtable_ptr(x) *reinterpret_cast<void**&>(settings)
|
#define vtable_ptr(x) *reinterpret_cast<void**&>(settings)
|
||||||
#define vtable_target(x) reinterpret_cast<void*>(reinterpret_cast<uintptr_t>(x)+8)
|
#define vtable_target(x) reinterpret_cast<void*>(reinterpret_cast<uintptr_t>(x)+8)
|
||||||
|
|
||||||
|
//libnickel 4.6 * _ZTV8Settings
|
||||||
void *Settings_vtable = dlsym(RTLD_DEFAULT, "_ZTV8Settings");
|
void *Settings_vtable = dlsym(RTLD_DEFAULT, "_ZTV8Settings");
|
||||||
NM_ASSERT(Settings_vtable, "could not dlsym the vtable for Settings");
|
NM_ASSERT(Settings_vtable, "could not dlsym the vtable for Settings");
|
||||||
NM_ASSERT(vtable_ptr(settings) == vtable_target(Settings_vtable), "unexpected vtable layout (expected class to start with a pointer to 8 bytes into the vtable)");
|
NM_ASSERT(vtable_ptr(settings) == vtable_target(Settings_vtable), "unexpected vtable layout (expected class to start with a pointer to 8 bytes into the vtable)");
|
||||||
@@ -113,15 +119,18 @@ NM_ACTION_(nickel_setting) {
|
|||||||
bool v = false;
|
bool v = false;
|
||||||
|
|
||||||
if (!strcmp(arg, "invert") || !strcmp(arg, "screenshots")) {
|
if (!strcmp(arg, "invert") || !strcmp(arg, "screenshots")) {
|
||||||
|
//libnickel 4.6 * _ZTV15FeatureSettings
|
||||||
void *FeatureSettings_vtable = dlsym(RTLD_DEFAULT, "_ZTV15FeatureSettings");
|
void *FeatureSettings_vtable = dlsym(RTLD_DEFAULT, "_ZTV15FeatureSettings");
|
||||||
NM_ASSERT(FeatureSettings_vtable, "could not dlsym the vtable for FeatureSettings");
|
NM_ASSERT(FeatureSettings_vtable, "could not dlsym the vtable for FeatureSettings");
|
||||||
vtable_ptr(settings) = vtable_target(FeatureSettings_vtable);
|
vtable_ptr(settings) = vtable_target(FeatureSettings_vtable);
|
||||||
|
|
||||||
if (!strcmp(arg, "invert")) {
|
if (!strcmp(arg, "invert")) {
|
||||||
|
//libnickel 4.6 * _ZN15FeatureSettings12invertScreenEv
|
||||||
bool (*FeatureSettings_invertScreen)(Settings*);
|
bool (*FeatureSettings_invertScreen)(Settings*);
|
||||||
reinterpret_cast<void*&>(FeatureSettings_invertScreen) = dlsym(RTLD_DEFAULT, "_ZN15FeatureSettings12invertScreenEv");
|
reinterpret_cast<void*&>(FeatureSettings_invertScreen) = dlsym(RTLD_DEFAULT, "_ZN15FeatureSettings12invertScreenEv");
|
||||||
NM_ASSERT(FeatureSettings_invertScreen, "could not dlsym FeatureSettings::invertScreen");
|
NM_ASSERT(FeatureSettings_invertScreen, "could not dlsym FeatureSettings::invertScreen");
|
||||||
|
|
||||||
|
//libnickel 4.6 * _ZN15FeatureSettings15setInvertScreenEb
|
||||||
bool (*FeatureSettings_setInvertScreen)(Settings*, bool);
|
bool (*FeatureSettings_setInvertScreen)(Settings*, bool);
|
||||||
reinterpret_cast<void*&>(FeatureSettings_setInvertScreen) = dlsym(RTLD_DEFAULT, "_ZN15FeatureSettings15setInvertScreenEb");
|
reinterpret_cast<void*&>(FeatureSettings_setInvertScreen) = dlsym(RTLD_DEFAULT, "_ZN15FeatureSettings15setInvertScreenEb");
|
||||||
NM_ASSERT(FeatureSettings_setInvertScreen, "could not dlsym FeatureSettings::setInvertScreen");
|
NM_ASSERT(FeatureSettings_setInvertScreen, "could not dlsym FeatureSettings::setInvertScreen");
|
||||||
@@ -157,10 +166,12 @@ NM_ACTION_(nickel_setting) {
|
|||||||
vtable_ptr(settings) = vtable_target(PowerSettings_vtable);
|
vtable_ptr(settings) = vtable_target(PowerSettings_vtable);
|
||||||
|
|
||||||
if (!strcmp(arg, "lockscreen")) {
|
if (!strcmp(arg, "lockscreen")) {
|
||||||
|
//libnickel 4.12.12111 * _ZN13PowerSettings16getUnlockEnabledEv
|
||||||
bool (*PowerSettings__getUnlockEnabled)(Settings*);
|
bool (*PowerSettings__getUnlockEnabled)(Settings*);
|
||||||
reinterpret_cast<void*&>(PowerSettings__getUnlockEnabled) = dlsym(RTLD_DEFAULT, "_ZN13PowerSettings16getUnlockEnabledEv");
|
reinterpret_cast<void*&>(PowerSettings__getUnlockEnabled) = dlsym(RTLD_DEFAULT, "_ZN13PowerSettings16getUnlockEnabledEv");
|
||||||
NM_ASSERT(PowerSettings__getUnlockEnabled, "could not dlsym PowerSettings::getUnlockEnabled");
|
NM_ASSERT(PowerSettings__getUnlockEnabled, "could not dlsym PowerSettings::getUnlockEnabled");
|
||||||
|
|
||||||
|
//libnickel 4.12.12111 * _ZN13PowerSettings16setUnlockEnabledEb
|
||||||
bool (*PowerSettings__setUnlockEnabled)(Settings*, bool);
|
bool (*PowerSettings__setUnlockEnabled)(Settings*, bool);
|
||||||
reinterpret_cast<void*&>(PowerSettings__setUnlockEnabled) = dlsym(RTLD_DEFAULT, "_ZN13PowerSettings16setUnlockEnabledEb");
|
reinterpret_cast<void*&>(PowerSettings__setUnlockEnabled) = dlsym(RTLD_DEFAULT, "_ZN13PowerSettings16setUnlockEnabledEb");
|
||||||
NM_ASSERT(PowerSettings__setUnlockEnabled, "could not dlsym PowerSettings::setUnlockEnabled");
|
NM_ASSERT(PowerSettings__setUnlockEnabled, "could not dlsym PowerSettings::setUnlockEnabled");
|
||||||
@@ -175,6 +186,7 @@ NM_ACTION_(nickel_setting) {
|
|||||||
vtable_ptr(settings) = vtable_target(PowerSettings_vtable);
|
vtable_ptr(settings) = vtable_target(PowerSettings_vtable);
|
||||||
}
|
}
|
||||||
} else if (!strcmp(arg, "force_wifi")) {
|
} else if (!strcmp(arg, "force_wifi")) {
|
||||||
|
//libnickel 4.6 * _ZTV11DevSettings
|
||||||
void *PowerSettings_vtable = dlsym(RTLD_DEFAULT, "_ZTV11DevSettings");
|
void *PowerSettings_vtable = dlsym(RTLD_DEFAULT, "_ZTV11DevSettings");
|
||||||
NM_ASSERT(PowerSettings_vtable, "could not dlsym the vtable for DevSettings");
|
NM_ASSERT(PowerSettings_vtable, "could not dlsym the vtable for DevSettings");
|
||||||
vtable_ptr(settings) = vtable_target(PowerSettings_vtable);
|
vtable_ptr(settings) = vtable_target(PowerSettings_vtable);
|
||||||
@@ -212,14 +224,17 @@ NM_ACTION_(nickel_extras) {
|
|||||||
#define NM_ERR_RET nullptr
|
#define NM_ERR_RET nullptr
|
||||||
|
|
||||||
if (!strcmp(arg, "web_browser")) {
|
if (!strcmp(arg, "web_browser")) {
|
||||||
|
//libnickel 4.6 * _ZN26N3SettingsExtrasControllerC2Ev
|
||||||
void (*N3SettingsExtrasController_N3SettingsExtrasController)(N3SettingsExtrasController*);
|
void (*N3SettingsExtrasController_N3SettingsExtrasController)(N3SettingsExtrasController*);
|
||||||
reinterpret_cast<void*&>(N3SettingsExtrasController_N3SettingsExtrasController) = dlsym(RTLD_DEFAULT, "_ZN26N3SettingsExtrasControllerC2Ev");
|
reinterpret_cast<void*&>(N3SettingsExtrasController_N3SettingsExtrasController) = dlsym(RTLD_DEFAULT, "_ZN26N3SettingsExtrasControllerC2Ev");
|
||||||
NM_ASSERT(N3SettingsExtrasController_N3SettingsExtrasController, "could not dlsym N3SettingsExtrasController constructor");
|
NM_ASSERT(N3SettingsExtrasController_N3SettingsExtrasController, "could not dlsym N3SettingsExtrasController constructor");
|
||||||
|
|
||||||
|
//libnickel 4.6 * _ZN26N3SettingsExtrasControllerD1Ev
|
||||||
void (*N3SettingsExtrasController_N3SettingsExtrasControllerD)(N3SettingsExtrasController*);
|
void (*N3SettingsExtrasController_N3SettingsExtrasControllerD)(N3SettingsExtrasController*);
|
||||||
reinterpret_cast<void*&>(N3SettingsExtrasController_N3SettingsExtrasControllerD) = dlsym(RTLD_DEFAULT, "_ZN26N3SettingsExtrasControllerD1Ev");
|
reinterpret_cast<void*&>(N3SettingsExtrasController_N3SettingsExtrasControllerD) = dlsym(RTLD_DEFAULT, "_ZN26N3SettingsExtrasControllerD1Ev");
|
||||||
NM_ASSERT(N3SettingsExtrasController_N3SettingsExtrasControllerD, "could not dlsym N3SettingsExtrasController destructor");
|
NM_ASSERT(N3SettingsExtrasController_N3SettingsExtrasControllerD, "could not dlsym N3SettingsExtrasController destructor");
|
||||||
|
|
||||||
|
//libnickel 4.6 * _ZN26N3SettingsExtrasController11openBrowserEv
|
||||||
void (*N3SettingsExtrasController_openBrowser)(N3SettingsExtrasController*);
|
void (*N3SettingsExtrasController_openBrowser)(N3SettingsExtrasController*);
|
||||||
reinterpret_cast<void*&>(N3SettingsExtrasController_openBrowser) = dlsym(RTLD_DEFAULT, "_ZN26N3SettingsExtrasController11openBrowserEv");
|
reinterpret_cast<void*&>(N3SettingsExtrasController_openBrowser) = dlsym(RTLD_DEFAULT, "_ZN26N3SettingsExtrasController11openBrowserEv");
|
||||||
NM_ASSERT(N3SettingsExtrasController_openBrowser, "could not dlsym BrowserWorkflowManager::openBrowser");
|
NM_ASSERT(N3SettingsExtrasController_openBrowser, "could not dlsym BrowserWorkflowManager::openBrowser");
|
||||||
@@ -230,17 +245,21 @@ NM_ACTION_(nickel_extras) {
|
|||||||
N3SettingsExtrasController_N3SettingsExtrasControllerD(nse);
|
N3SettingsExtrasController_N3SettingsExtrasControllerD(nse);
|
||||||
|
|
||||||
// the QObject is only used to pass events to it, but there's something I'm missing here which leads to it segfaulting after connecting to WiFi if it isn't already connected
|
// the QObject is only used to pass events to it, but there's something I'm missing here which leads to it segfaulting after connecting to WiFi if it isn't already connected
|
||||||
/*void (*BrowserWorkflowManager_BrowserWorkflowManager)(BrowserWorkflowManager*, QObject*);
|
/*
|
||||||
|
//libnickel 4.11.11911 * _ZN22BrowserWorkflowManagerC1EP7QObject
|
||||||
|
void (*BrowserWorkflowManager_BrowserWorkflowManager)(BrowserWorkflowManager*, QObject*);
|
||||||
reinterpret_cast<void*&>(BrowserWorkflowManager_BrowserWorkflowManager) = dlsym(RTLD_DEFAULT, "_ZN22BrowserWorkflowManagerC1EP7QObject");
|
reinterpret_cast<void*&>(BrowserWorkflowManager_BrowserWorkflowManager) = dlsym(RTLD_DEFAULT, "_ZN22BrowserWorkflowManagerC1EP7QObject");
|
||||||
NM_ASSERT(BrowserWorkflowManager_BrowserWorkflowManager, "could not dlsym BrowserWorkflowManager constructor");
|
NM_ASSERT(BrowserWorkflowManager_BrowserWorkflowManager, "could not dlsym BrowserWorkflowManager constructor");
|
||||||
|
|
||||||
|
//libnickel 4.6 * _ZN22BrowserWorkflowManager11openBrowserEbRK4QUrlRK7QString
|
||||||
void (*BrowserWorkflowManager_openBrowser)(BrowserWorkflowManager*, bool, QUrl const&, QString const&); // the bool is whether to open it as a modal, the string is CSS to inject
|
void (*BrowserWorkflowManager_openBrowser)(BrowserWorkflowManager*, bool, QUrl const&, QString const&); // the bool is whether to open it as a modal, the string is CSS to inject
|
||||||
reinterpret_cast<void*&>(BrowserWorkflowManager_openBrowser) = dlsym(RTLD_DEFAULT, "_ZN22BrowserWorkflowManager11openBrowserEbRK4QUrlRK7QString");
|
reinterpret_cast<void*&>(BrowserWorkflowManager_openBrowser) = dlsym(RTLD_DEFAULT, "_ZN22BrowserWorkflowManager11openBrowserEbRK4QUrlRK7QString");
|
||||||
NM_ASSERT(BrowserWorkflowManager_openBrowser, "could not dlsym BrowserWorkflowManager::openBrowser");
|
NM_ASSERT(BrowserWorkflowManager_openBrowser, "could not dlsym BrowserWorkflowManager::openBrowser");
|
||||||
|
|
||||||
BrowserWorkflowManager *bwm = alloca(128); // as of 4.20.14622, it's actually 20 bytes, but we're going to stay on the safe side
|
BrowserWorkflowManager *bwm = alloca(128); // as of 4.20.14622, it's actually 20 bytes, but we're going to stay on the safe side
|
||||||
BrowserWorkflowManager_BrowserWorkflowManager(bwm, new QObject());
|
BrowserWorkflowManager_BrowserWorkflowManager(bwm, new QObject());
|
||||||
BrowserWorkflowManager_openBrowser(bwm, false, QUrl(), QStringLiteral("")); // if !QUrl::isValid(), it loads the homepage*/
|
BrowserWorkflowManager_openBrowser(bwm, false, QUrl(), QStringLiteral("")); // if !QUrl::isValid(), it loads the homepage
|
||||||
|
*/
|
||||||
NM_RETURN_OK(nm_action_result_silent());
|
NM_RETURN_OK(nm_action_result_silent());
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -253,6 +272,7 @@ NM_ACTION_(nickel_extras) {
|
|||||||
else if (!strcmp(arg, "word_scramble")) mimetype = "application/x-games-Boggle";
|
else if (!strcmp(arg, "word_scramble")) mimetype = "application/x-games-Boggle";
|
||||||
else NM_RETURN_ERR("unknown beta feature name or plugin mimetype '%s'", arg);
|
else NM_RETURN_ERR("unknown beta feature name or plugin mimetype '%s'", arg);
|
||||||
|
|
||||||
|
//libnickel 4.6 * _ZN18ExtrasPluginLoader10loadPluginEPKc
|
||||||
void (*ExtrasPluginLoader_loadPlugin)(const char*);
|
void (*ExtrasPluginLoader_loadPlugin)(const char*);
|
||||||
reinterpret_cast<void*&>(ExtrasPluginLoader_loadPlugin) = dlsym(RTLD_DEFAULT, "_ZN18ExtrasPluginLoader10loadPluginEPKc");
|
reinterpret_cast<void*&>(ExtrasPluginLoader_loadPlugin) = dlsym(RTLD_DEFAULT, "_ZN18ExtrasPluginLoader10loadPluginEPKc");
|
||||||
NM_ASSERT(ExtrasPluginLoader_loadPlugin, "could not dlsym ExtrasPluginLoader::loadPlugin");
|
NM_ASSERT(ExtrasPluginLoader_loadPlugin, "could not dlsym ExtrasPluginLoader::loadPlugin");
|
||||||
@@ -265,10 +285,12 @@ NM_ACTION_(nickel_extras) {
|
|||||||
NM_ACTION_(nickel_misc) {
|
NM_ACTION_(nickel_misc) {
|
||||||
#define NM_ERR_RET nullptr
|
#define NM_ERR_RET nullptr
|
||||||
if (!strcmp(arg, "rescan_books")) {
|
if (!strcmp(arg, "rescan_books")) {
|
||||||
|
//libnickel 4.13.12638 * _ZN19PlugWorkflowManager14sharedInstanceEv
|
||||||
PlugWorkflowManager *(*PlugWorkflowManager_sharedInstance)();
|
PlugWorkflowManager *(*PlugWorkflowManager_sharedInstance)();
|
||||||
reinterpret_cast<void*&>(PlugWorkflowManager_sharedInstance) = dlsym(RTLD_DEFAULT, "_ZN19PlugWorkflowManager14sharedInstanceEv");
|
reinterpret_cast<void*&>(PlugWorkflowManager_sharedInstance) = dlsym(RTLD_DEFAULT, "_ZN19PlugWorkflowManager14sharedInstanceEv");
|
||||||
NM_ASSERT(PlugWorkflowManager_sharedInstance, "could not dlsym PlugWorkflowManager::sharedInstance");
|
NM_ASSERT(PlugWorkflowManager_sharedInstance, "could not dlsym PlugWorkflowManager::sharedInstance");
|
||||||
|
|
||||||
|
//libnickel 4.13.12638 * _ZN19PlugWorkflowManager4syncEv
|
||||||
void (*PlugWorkflowManager_sync)(PlugWorkflowManager*);
|
void (*PlugWorkflowManager_sync)(PlugWorkflowManager*);
|
||||||
reinterpret_cast<void*&>(PlugWorkflowManager_sync) = dlsym(RTLD_DEFAULT, "_ZN19PlugWorkflowManager4syncEv");
|
reinterpret_cast<void*&>(PlugWorkflowManager_sync) = dlsym(RTLD_DEFAULT, "_ZN19PlugWorkflowManager4syncEv");
|
||||||
NM_ASSERT(PlugWorkflowManager_sync, "could not dlsym PlugWorkflowManager::sync");
|
NM_ASSERT(PlugWorkflowManager_sync, "could not dlsym PlugWorkflowManager::sync");
|
||||||
@@ -278,15 +300,18 @@ NM_ACTION_(nickel_misc) {
|
|||||||
|
|
||||||
PlugWorkflowManager_sync(wf);
|
PlugWorkflowManager_sync(wf);
|
||||||
} else if (!strcmp(arg, "rescan_books_full")) {
|
} else if (!strcmp(arg, "rescan_books_full")) {
|
||||||
|
//libnickel 4.13.12638 * _ZN19PlugWorkflowManager14sharedInstanceEv
|
||||||
PlugWorkflowManager *(*PlugWorkflowManager_sharedInstance)();
|
PlugWorkflowManager *(*PlugWorkflowManager_sharedInstance)();
|
||||||
reinterpret_cast<void*&>(PlugWorkflowManager_sharedInstance) = dlsym(RTLD_DEFAULT, "_ZN19PlugWorkflowManager14sharedInstanceEv");
|
reinterpret_cast<void*&>(PlugWorkflowManager_sharedInstance) = dlsym(RTLD_DEFAULT, "_ZN19PlugWorkflowManager14sharedInstanceEv");
|
||||||
NM_ASSERT(PlugWorkflowManager_sharedInstance, "could not dlsym PlugWorkflowManager::sharedInstance");
|
NM_ASSERT(PlugWorkflowManager_sharedInstance, "could not dlsym PlugWorkflowManager::sharedInstance");
|
||||||
|
|
||||||
// this is what is called by PlugWorkflowManager::plugged after confirmation
|
// this is what is called by PlugWorkflowManager::plugged after confirmation
|
||||||
|
//libnickel 4.13.12638 * _ZN19PlugWorkflowManager18onCancelAndConnectEv
|
||||||
void (*PlugWorkflowManager_onCancelAndConnect)(PlugWorkflowManager*);
|
void (*PlugWorkflowManager_onCancelAndConnect)(PlugWorkflowManager*);
|
||||||
reinterpret_cast<void*&>(PlugWorkflowManager_onCancelAndConnect) = dlsym(RTLD_DEFAULT, "_ZN19PlugWorkflowManager18onCancelAndConnectEv");
|
reinterpret_cast<void*&>(PlugWorkflowManager_onCancelAndConnect) = dlsym(RTLD_DEFAULT, "_ZN19PlugWorkflowManager18onCancelAndConnectEv");
|
||||||
NM_ASSERT(PlugWorkflowManager_onCancelAndConnect, "could not dlsym PlugWorkflowManager::onCancelAndConnect");
|
NM_ASSERT(PlugWorkflowManager_onCancelAndConnect, "could not dlsym PlugWorkflowManager::onCancelAndConnect");
|
||||||
|
|
||||||
|
//libnickel 4.13.12638 * _ZN19PlugWorkflowManager9unpluggedEv
|
||||||
void (*PlugWorkflowManager_unplugged)(PlugWorkflowManager*);
|
void (*PlugWorkflowManager_unplugged)(PlugWorkflowManager*);
|
||||||
reinterpret_cast<void*&>(PlugWorkflowManager_unplugged) = dlsym(RTLD_DEFAULT, "_ZN19PlugWorkflowManager9unpluggedEv");
|
reinterpret_cast<void*&>(PlugWorkflowManager_unplugged) = dlsym(RTLD_DEFAULT, "_ZN19PlugWorkflowManager9unpluggedEv");
|
||||||
NM_ASSERT(PlugWorkflowManager_unplugged, "could not dlsym PlugWorkflowManager::unplugged");
|
NM_ASSERT(PlugWorkflowManager_unplugged, "could not dlsym PlugWorkflowManager::unplugged");
|
||||||
@@ -316,6 +341,7 @@ NM_ACTION_(nickel_misc) {
|
|||||||
NM_ACTION_(power) {
|
NM_ACTION_(power) {
|
||||||
#define NM_ERR_RET nullptr
|
#define NM_ERR_RET nullptr
|
||||||
if (!strcmp(arg, "shutdown") || !strcmp(arg, "reboot")) {
|
if (!strcmp(arg, "shutdown") || !strcmp(arg, "reboot")) {
|
||||||
|
//libnickel 4.13.12638 * _ZN22N3PowerWorkflowManager14sharedInstanceEv
|
||||||
N3PowerWorkflowManager *(*N3PowerWorkflowManager_sharedInstance)();
|
N3PowerWorkflowManager *(*N3PowerWorkflowManager_sharedInstance)();
|
||||||
reinterpret_cast<void*&>(N3PowerWorkflowManager_sharedInstance) = dlsym(RTLD_DEFAULT, "_ZN22N3PowerWorkflowManager14sharedInstanceEv");
|
reinterpret_cast<void*&>(N3PowerWorkflowManager_sharedInstance) = dlsym(RTLD_DEFAULT, "_ZN22N3PowerWorkflowManager14sharedInstanceEv");
|
||||||
NM_ASSERT(N3PowerWorkflowManager_sharedInstance, "could not dlsym N3PowerWorkflowManager::sharedInstance, so cannot perform action cleanly (if you must, report a bug and use cmd_spawn instead)");
|
NM_ASSERT(N3PowerWorkflowManager_sharedInstance, "could not dlsym N3PowerWorkflowManager::sharedInstance, so cannot perform action cleanly (if you must, report a bug and use cmd_spawn instead)");
|
||||||
@@ -324,6 +350,7 @@ NM_ACTION_(power) {
|
|||||||
NM_ASSERT(pwm, "could not get shared power manager pointer");
|
NM_ASSERT(pwm, "could not get shared power manager pointer");
|
||||||
|
|
||||||
if (!strcmp(arg, "shutdown")) {
|
if (!strcmp(arg, "shutdown")) {
|
||||||
|
//libnickel 4.13.12638 * _ZN22N3PowerWorkflowManager8powerOffEb
|
||||||
void (*N3PowerWorkflowManager_powerOff)(N3PowerWorkflowManager*, bool); // bool is for if it's due to low battery
|
void (*N3PowerWorkflowManager_powerOff)(N3PowerWorkflowManager*, bool); // bool is for if it's due to low battery
|
||||||
reinterpret_cast<void*&>(N3PowerWorkflowManager_powerOff) = dlsym(RTLD_DEFAULT, "_ZN22N3PowerWorkflowManager8powerOffEb");
|
reinterpret_cast<void*&>(N3PowerWorkflowManager_powerOff) = dlsym(RTLD_DEFAULT, "_ZN22N3PowerWorkflowManager8powerOffEb");
|
||||||
NM_ASSERT(N3PowerWorkflowManager_powerOff, "could not dlsym N3PowerWorkflowManager::powerOff");
|
NM_ASSERT(N3PowerWorkflowManager_powerOff, "could not dlsym N3PowerWorkflowManager::powerOff");
|
||||||
@@ -331,6 +358,7 @@ NM_ACTION_(power) {
|
|||||||
N3PowerWorkflowManager_powerOff(pwm, false);
|
N3PowerWorkflowManager_powerOff(pwm, false);
|
||||||
NM_RETURN_OK(nm_action_result_toast("Shutting down..."));
|
NM_RETURN_OK(nm_action_result_toast("Shutting down..."));
|
||||||
} else if (!strcmp(arg, "reboot")) {
|
} else if (!strcmp(arg, "reboot")) {
|
||||||
|
//libnickel 4.13.12638 * _ZN22N3PowerWorkflowManager6rebootEv
|
||||||
void (*N3PowerWorkflowManager_reboot)(N3PowerWorkflowManager*);
|
void (*N3PowerWorkflowManager_reboot)(N3PowerWorkflowManager*);
|
||||||
reinterpret_cast<void*&>(N3PowerWorkflowManager_reboot) = dlsym(RTLD_DEFAULT, "_ZN22N3PowerWorkflowManager6rebootEv");
|
reinterpret_cast<void*&>(N3PowerWorkflowManager_reboot) = dlsym(RTLD_DEFAULT, "_ZN22N3PowerWorkflowManager6rebootEv");
|
||||||
NM_ASSERT(N3PowerWorkflowManager_reboot, "could not dlsym N3PowerWorkflowManager::reboot");
|
NM_ASSERT(N3PowerWorkflowManager_reboot, "could not dlsym N3PowerWorkflowManager::reboot");
|
||||||
|
|||||||
@@ -50,10 +50,15 @@ static size_t _items_n;
|
|||||||
|
|
||||||
extern "C" int nm_menu_hook(void *libnickel, nm_menu_item_t **items, size_t items_n, char **err_out) {
|
extern "C" int nm_menu_hook(void *libnickel, nm_menu_item_t **items, size_t items_n, char **err_out) {
|
||||||
#define NM_ERR_RET 1
|
#define NM_ERR_RET 1
|
||||||
|
//libnickel 4.6 * _ZN28AbstractNickelMenuController18createMenuTextItemEP5QMenuRK7QStringbbS4_
|
||||||
reinterpret_cast<void*&>(AbstractNickelMenuController_createMenuTextItem) = dlsym(libnickel, "_ZN28AbstractNickelMenuController18createMenuTextItemEP5QMenuRK7QStringbbS4_");
|
reinterpret_cast<void*&>(AbstractNickelMenuController_createMenuTextItem) = dlsym(libnickel, "_ZN28AbstractNickelMenuController18createMenuTextItemEP5QMenuRK7QStringbbS4_");
|
||||||
|
//libnickel 4.6 * _ZN22AbstractMenuController12createActionEP5QMenuP7QWidgetbbb
|
||||||
reinterpret_cast<void*&>(AbstractNickelMenuController_createAction) = dlsym(libnickel, "_ZN22AbstractMenuController12createActionEP5QMenuP7QWidgetbbb");
|
reinterpret_cast<void*&>(AbstractNickelMenuController_createAction) = dlsym(libnickel, "_ZN22AbstractMenuController12createActionEP5QMenuP7QWidgetbbb");
|
||||||
|
//libnickel 4.6 * _ZN25ConfirmationDialogFactory12showOKDialogERK7QStringS2_
|
||||||
reinterpret_cast<void*&>(ConfirmationDialogFactory_showOKDialog) = dlsym(libnickel, "_ZN25ConfirmationDialogFactory12showOKDialogERK7QStringS2_");
|
reinterpret_cast<void*&>(ConfirmationDialogFactory_showOKDialog) = dlsym(libnickel, "_ZN25ConfirmationDialogFactory12showOKDialogERK7QStringS2_");
|
||||||
|
//libnickel 4.6 * _ZN20MainWindowController14sharedInstanceEv
|
||||||
reinterpret_cast<void*&>(MainWindowController_sharedInstance) = dlsym(libnickel, "_ZN20MainWindowController14sharedInstanceEv");
|
reinterpret_cast<void*&>(MainWindowController_sharedInstance) = dlsym(libnickel, "_ZN20MainWindowController14sharedInstanceEv");
|
||||||
|
//libnickel 4.6 * _ZN20MainWindowController5toastERK7QStringS2_i
|
||||||
reinterpret_cast<void*&>(MainWindowController_toast) = dlsym(libnickel, "_ZN20MainWindowController5toastERK7QStringS2_i");
|
reinterpret_cast<void*&>(MainWindowController_toast) = dlsym(libnickel, "_ZN20MainWindowController5toastERK7QStringS2_i");
|
||||||
|
|
||||||
NM_ASSERT(AbstractNickelMenuController_createMenuTextItem, "unsupported firmware: could not find AbstractNickelMenuController::createMenuTextItem(void* _this, QMenu*, QString, bool, bool, QString const&)");
|
NM_ASSERT(AbstractNickelMenuController_createMenuTextItem, "unsupported firmware: could not find AbstractNickelMenuController::createMenuTextItem(void* _this, QMenu*, QString, bool, bool, QString const&)");
|
||||||
@@ -66,6 +71,7 @@ extern "C" int nm_menu_hook(void *libnickel, nm_menu_item_t **items, size_t item
|
|||||||
NM_ASSERT(nmh, "internal error: could not dlsym _nm_menu_hook");
|
NM_ASSERT(nmh, "internal error: could not dlsym _nm_menu_hook");
|
||||||
|
|
||||||
char *err;
|
char *err;
|
||||||
|
//libnickel 4.6 * _ZN28AbstractNickelMenuController18createMenuTextItemEP5QMenuRK7QStringbbS4_
|
||||||
reinterpret_cast<void*&>(AbstractNickelMenuController_createMenuTextItem_orig) = nm_dlhook(libnickel, "_ZN28AbstractNickelMenuController18createMenuTextItemEP5QMenuRK7QStringbbS4_", nmh, &err);
|
reinterpret_cast<void*&>(AbstractNickelMenuController_createMenuTextItem_orig) = nm_dlhook(libnickel, "_ZN28AbstractNickelMenuController18createMenuTextItemEP5QMenuRK7QStringbbS4_", nmh, &err);
|
||||||
NM_ASSERT(AbstractNickelMenuController_createMenuTextItem_orig, "failed to hook _ZN28AbstractNickelMenuController18createMenuTextItemEP5QMenuRK7QStringbbS4_: %s", err);
|
NM_ASSERT(AbstractNickelMenuController_createMenuTextItem_orig, "failed to hook _ZN28AbstractNickelMenuController18createMenuTextItemEP5QMenuRK7QStringbbS4_: %s", err);
|
||||||
|
|
||||||
|
|||||||
8
test/syms/go.mod
Normal file
8
test/syms/go.mod
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
module github.com/geek1011/NickelMenu/test/syms
|
||||||
|
|
||||||
|
go 1.14
|
||||||
|
|
||||||
|
require (
|
||||||
|
github.com/geek1011/kobopatch v0.15.0
|
||||||
|
github.com/xi2/xz v0.0.0-20171230120015-48954b6210f8
|
||||||
|
)
|
||||||
19
test/syms/go.sum
Normal file
19
test/syms/go.sum
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||||
|
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||||
|
github.com/geek1011/czlib v0.0.3 h1:Cp9hWIbzdvyj/QmpciCghWLbRpRaMpJS7wL7bTxwgUM=
|
||||||
|
github.com/geek1011/czlib v0.0.3/go.mod h1:iw913x/pjDqhfoak/AU3XWgycIcGL9H6kjgPP2YqzQM=
|
||||||
|
github.com/geek1011/kobopatch v0.15.0 h1:xIxJPHNoiwbD7VkwBmZRzQAVHfjPqxuEvFNtDfKGPiE=
|
||||||
|
github.com/geek1011/kobopatch v0.15.0/go.mod h1:4/PuLBLcPPNO20/gBRJh9VhdVyNZmuwCvo8wffcVWiQ=
|
||||||
|
github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6 h1:UDMh68UUwekSh5iP2OMhRRZJiiBccgV7axzUG8vi56c=
|
||||||
|
github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc=
|
||||||
|
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||||
|
github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
|
||||||
|
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||||
|
github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA=
|
||||||
|
github.com/xi2/xz v0.0.0-20171230120015-48954b6210f8 h1:nIPpBwaJSVYIxUFsDv3M8ofmx9yWTog9BfvIu0q41lo=
|
||||||
|
github.com/xi2/xz v0.0.0-20171230120015-48954b6210f8/go.mod h1:HUYIGzjTL3rfEspMxjDjgmT5uz5wzYJKVo23qUhYTos=
|
||||||
|
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||||
|
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||||
|
gopkg.in/yaml.v3 v3.0.0-20190709130402-674ba3eaed22/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||||
|
rsc.io/arm v0.0.0-20150420010332-9c32f2193064 h1:bBbas3KhLwE6f59Z9lUipY23xUX9qrvyLBdQzzV2Tko=
|
||||||
|
rsc.io/arm v0.0.0-20150420010332-9c32f2193064/go.mod h1:MVYPdlFruujBlzEY3x2Q3XBk7XLdYRNZ7zDbrzYFO7w=
|
||||||
276
test/syms/main.go
Normal file
276
test/syms/main.go
Normal file
@@ -0,0 +1,276 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"archive/tar"
|
||||||
|
"bufio"
|
||||||
|
"bytes"
|
||||||
|
"fmt"
|
||||||
|
"io"
|
||||||
|
"io/ioutil"
|
||||||
|
"net/http"
|
||||||
|
"os"
|
||||||
|
"path/filepath"
|
||||||
|
"sort"
|
||||||
|
"strconv"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"github.com/geek1011/kobopatch/patchlib"
|
||||||
|
"github.com/xi2/xz"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
sc, err := FindSymChecks(".")
|
||||||
|
if err != nil {
|
||||||
|
fmt.Fprintf(os.Stderr, "[FTL] find symbol checks: %v\n", err)
|
||||||
|
os.Exit(1)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
versions := []string{
|
||||||
|
"4.6.9960", "4.6.9995", "4.7.10075", "4.7.10364", "4.7.10413",
|
||||||
|
"4.8.10956", "4.8.11073", "4.8.11090", "4.9.11311", "4.9.11314",
|
||||||
|
"4.10.11591", "4.10.11655", "4.11.11911", "4.11.11976", "4.11.11980",
|
||||||
|
"4.11.11982", "4.11.12019", "4.12.12111", "4.13.12638", "4.14.12777",
|
||||||
|
"4.15.12920", "4.16.13162", "4.17.13651", "4.17.13694", "4.18.13737",
|
||||||
|
"4.19.14123", "4.20.14601", "4.20.14617", "4.20.14622",
|
||||||
|
}
|
||||||
|
|
||||||
|
checks := map[string]map[string][]SymCheck{}
|
||||||
|
for _, c := range sc {
|
||||||
|
var sm, em int
|
||||||
|
for _, version := range versions {
|
||||||
|
if c.StartVersion == "*" || strings.HasPrefix(version+".", c.StartVersion+".") {
|
||||||
|
sm++
|
||||||
|
}
|
||||||
|
if c.EndVersion == "*" || strings.HasPrefix(version+".", c.EndVersion+".") {
|
||||||
|
em++
|
||||||
|
}
|
||||||
|
if versioncmp(c.StartVersion, version) <= 0 && versioncmp(version, c.EndVersion) >= 0 {
|
||||||
|
if _, ok := checks[version]; !ok {
|
||||||
|
checks[version] = map[string][]SymCheck{}
|
||||||
|
}
|
||||||
|
checks[version][c.Library] = append(checks[version][c.Library], c)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if sm == 0 {
|
||||||
|
fmt.Printf("[WRN] %s: no exact match for the base version in specifier %#v\n", c.File, c.StartVersion)
|
||||||
|
}
|
||||||
|
if em == 0 {
|
||||||
|
fmt.Printf("[WRN] %s: no exact match for the base version in specifier %#v\n", c.File, c.EndVersion)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var checkVersions []string
|
||||||
|
for version := range checks {
|
||||||
|
checkVersions = append(checkVersions, version)
|
||||||
|
}
|
||||||
|
sort.Slice(checkVersions, func(i, j int) bool {
|
||||||
|
return versioncmp(checkVersions[i], checkVersions[j]) == -1
|
||||||
|
})
|
||||||
|
|
||||||
|
var errs []error
|
||||||
|
gherrs := map[string][]string{}
|
||||||
|
for _, version := range checkVersions {
|
||||||
|
var checkLibs []string
|
||||||
|
for lib := range checks[version] {
|
||||||
|
checkLibs = append(checkLibs, lib)
|
||||||
|
}
|
||||||
|
sort.Strings(checkLibs)
|
||||||
|
|
||||||
|
for _, lib := range checkLibs {
|
||||||
|
fmt.Printf("[INF] checking %s@%s\n", lib, version)
|
||||||
|
|
||||||
|
pt, err := GetPatcher(version, lib)
|
||||||
|
if err != nil {
|
||||||
|
fmt.Fprintf(os.Stderr, "[FTL] get patcher: %v\n", err)
|
||||||
|
os.Exit(1)
|
||||||
|
return
|
||||||
|
} else if pt == nil {
|
||||||
|
fmt.Printf("[WRN] no data available, skipping\n")
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
_, err = pt.ExtractDynsyms(true)
|
||||||
|
if err != nil {
|
||||||
|
fmt.Fprintf(os.Stderr, "[FTL] extract symbols: %v\n", err)
|
||||||
|
os.Exit(1)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, check := range checks[version][lib] {
|
||||||
|
fmt.Printf("[INF] %s:\n checking for one of %+s\n", check.File, check.Symbols)
|
||||||
|
var f bool
|
||||||
|
for _, sym := range check.Symbols {
|
||||||
|
off, err := pt.ResolveSym(sym)
|
||||||
|
if err != nil {
|
||||||
|
fmt.Printf(" %s not found\n", sym)
|
||||||
|
} else {
|
||||||
|
fmt.Printf(" %s found at %#x\n", sym, off)
|
||||||
|
f = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if !f {
|
||||||
|
err := fmt.Errorf("%s: one of %+s not found in %s@%s", check.File, check.Symbols, lib, version)
|
||||||
|
fmt.Printf("[ERR] %v\n", err)
|
||||||
|
errs = append(errs, err)
|
||||||
|
|
||||||
|
spl := strings.Split(check.File, ":")
|
||||||
|
gherrf := fmt.Sprintf("file=%s,line=%s,col=%s", spl[0], spl[1], spl[2])
|
||||||
|
gherrs[gherrf] = append(gherrs[gherrf], fmt.Sprintf("one of symbols %+s not found in %s@%s", check.Symbols, lib, version))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if len(errs) == 0 {
|
||||||
|
os.Exit(0)
|
||||||
|
}
|
||||||
|
|
||||||
|
fmt.Printf("[FTL] check failed\n")
|
||||||
|
for _, err := range errs {
|
||||||
|
fmt.Printf(" %v\n", err)
|
||||||
|
}
|
||||||
|
if os.Getenv("GITHUB_ACTIONS") == "true" {
|
||||||
|
var ghfs []string
|
||||||
|
for ghf := range gherrs {
|
||||||
|
ghfs = append(ghfs, ghf)
|
||||||
|
}
|
||||||
|
sort.Strings(ghfs)
|
||||||
|
for _, ghf := range ghfs {
|
||||||
|
fmt.Printf("::error %s::%s\n", ghf, strings.Join(gherrs[ghf], "%0A"))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
os.Exit(1)
|
||||||
|
}
|
||||||
|
|
||||||
|
func GetPatcher(version, lib string) (*patchlib.Patcher, error) {
|
||||||
|
resp, err := http.Get("https://github.com/geek1011/kobopatch-patches/raw/master/testdata/" + version + ".tar.xz")
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("get kobopatch testdata for %#v: %w", version, err)
|
||||||
|
}
|
||||||
|
defer resp.Body.Close()
|
||||||
|
|
||||||
|
if resp.StatusCode == http.StatusNotFound {
|
||||||
|
return nil, nil
|
||||||
|
} else if resp.StatusCode != http.StatusOK {
|
||||||
|
return nil, fmt.Errorf("get kobopatch testdata for %#v: response status %s", version, resp.Status)
|
||||||
|
}
|
||||||
|
|
||||||
|
zr, err := xz.NewReader(resp.Body, 0)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("read kobopatch testdata: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
tr := tar.NewReader(zr)
|
||||||
|
for {
|
||||||
|
th, err := tr.Next()
|
||||||
|
if err != nil {
|
||||||
|
if err == io.EOF {
|
||||||
|
return nil, fmt.Errorf("read kobopatch testdata: file %#v not found", lib)
|
||||||
|
}
|
||||||
|
return nil, fmt.Errorf("read kobopatch testdata: %w", err)
|
||||||
|
}
|
||||||
|
if filepath.Clean(th.Name) == filepath.Clean(lib) {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
buf, err := ioutil.ReadAll(tr)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("read kobopatch testdata: %w", err)
|
||||||
|
}
|
||||||
|
return patchlib.NewPatcher(buf), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
type SymCheck struct {
|
||||||
|
File string
|
||||||
|
Library string
|
||||||
|
StartVersion string
|
||||||
|
EndVersion string
|
||||||
|
Symbols []string // or
|
||||||
|
}
|
||||||
|
|
||||||
|
func FindSymChecks(dir string) ([]SymCheck, error) {
|
||||||
|
var checks []SymCheck
|
||||||
|
if err := filepath.Walk(dir, func(path string, info os.FileInfo, err error) error {
|
||||||
|
var m bool
|
||||||
|
for _, ext := range []string{".c", ".cc", ".cpp", ".h"} {
|
||||||
|
if filepath.Ext(path) == ext {
|
||||||
|
m = true
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if !m {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
f, err := os.OpenFile(path, os.O_RDONLY, 0)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("open %#v: %w", path, err)
|
||||||
|
}
|
||||||
|
defer f.Close()
|
||||||
|
|
||||||
|
sc := bufio.NewScanner(f)
|
||||||
|
var line int
|
||||||
|
for sc.Scan() {
|
||||||
|
line++
|
||||||
|
col := bytes.Index(sc.Bytes(), []byte("//libnickel"))
|
||||||
|
if col == -1 {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
args := strings.Fields(string(bytes.TrimSpace(sc.Bytes()[col+len("//libnickel"):])))
|
||||||
|
if len(args) < 3 || args[0] == "*" {
|
||||||
|
return fmt.Errorf("parse %#v: line %d, col %d: expected comment to be in the format '//libnickel <start_version> <end_version|*> <sym>...'", path, line, col+1)
|
||||||
|
}
|
||||||
|
|
||||||
|
checks = append(checks, SymCheck{
|
||||||
|
File: fmt.Sprintf("%s:%d:%d", path, line, col+1),
|
||||||
|
Library: "libnickel.so.1.0.0",
|
||||||
|
StartVersion: args[0],
|
||||||
|
EndVersion: args[1],
|
||||||
|
Symbols: args[2:],
|
||||||
|
})
|
||||||
|
}
|
||||||
|
if err := sc.Err(); err != nil {
|
||||||
|
return fmt.Errorf("read %#v: %w", path, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return checks, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func versioncmp(a, b string) int {
|
||||||
|
if a == "*" || b == "*" {
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
aspl, bspl := splint(a), splint(b)
|
||||||
|
mlen := len(aspl)
|
||||||
|
if len(bspl) > mlen {
|
||||||
|
mlen = len(bspl)
|
||||||
|
}
|
||||||
|
for i := 0; i < mlen; i++ {
|
||||||
|
switch {
|
||||||
|
case i == len(bspl):
|
||||||
|
return 1
|
||||||
|
case i == len(aspl):
|
||||||
|
return -1
|
||||||
|
case aspl[i] > bspl[i]:
|
||||||
|
return 1
|
||||||
|
case bspl[i] > aspl[i]:
|
||||||
|
return -1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
func splint(str string) []int64 {
|
||||||
|
spl := strings.Split(str, ".")
|
||||||
|
ints := make([]int64, len(spl))
|
||||||
|
for i, p := range spl {
|
||||||
|
ints[i], _ = strconv.ParseInt(p, 10, 64)
|
||||||
|
}
|
||||||
|
return ints
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user