Lingue: English | 简体中文 | 繁體中文 | 日本語 | 한국어 | Français | Deutsch | Español | Italiano | Русский | العربية
I plugin nativi di NeverD sono librerie condivise fidate caricate nel processo
host. Usano le dichiarazioni C pure in neverd/sdk/NeverDPlugin.h e chiamano
l’API C pubblica in neverd/sdk/NeverDCAPI.h. Usa la
guida ai plugin Python quando è più appropriato
sviluppare in Python all’interno dello stesso processo.
L’attuale descrittore neverd_plugin_t non contiene un campo per la versione
dell’ABI né per la dimensione della struttura. Compila il plugin con gli header
preparati dalla revisione esatta di NeverD che lo caricherà e ricompilalo a ogni
aggiornamento di NeverD. Plugin e host devono inoltre usare lo stesso sistema
operativo e la stessa architettura, oltre a toolchain compatibili con l’ABI.
I plugin nativi sono codice arbitrario eseguito all’interno del processo. NeverD non li esegue in una sandbox, non isola i crash e non limita il loro accesso alla sessione o al processo host. Carica solo plugin di cui ti fidi.
Ogni libreria esporta un solo simbolo dati chiamato esattamente
neverd_plugin:
#include "neverd/sdk/NeverDPlugin.h"
static int on_init(neverd_session_t session) {
(void)session;
return 0;
}
static void on_term(void) {}
static int on_run(neverd_session_t session, int arg) {
(void)session;
return arg;
}
static int on_event(const neverd_event_t *event) {
if (event && event->Type == NEVERD_EVT_BINARY_LOADED) {
const char *path = event->Data.BinaryLoaded.Path; /* borrowed */
(void)path;
}
return 0;
}
NEVERD_PLUGIN_EXPORT neverd_plugin_t neverd_plugin = {
.Name = "My Plugin",
.Version = "1.0.0",
.Author = "Your Name",
.Description = "A native NeverD extension",
.Type = NEVERD_PLUGIN_GENERIC,
.Init = on_init,
.Term = on_term,
.Run = on_run,
.Event = on_event,
};NEVERD_PLUGIN_EXPORT si espande in __declspec(dllexport) su Windows e nella
visibilità ELF/Mach-O predefinita altrove. Mantieni il sorgente in C oppure
assegna esplicitamente al descrittore il linkage C se un’implementazione C++ è
inevitabile.
Name deve essere non vuoto e univoco all’interno di un host. Durante il
caricamento, l’host copia tutte e quattro le stringhe di metadati. Version,
Author e Description possono essere vuoti. I quattro valori di tipo sono
esclusivamente metadati di classificazione:
| Valore | Significato attuale |
|---|---|
NEVERD_PLUGIN_GENERIC |
Etichetta per un’estensione generica |
NEVERD_PLUGIN_LOADER |
Etichetta loader; non registra un loader di binari |
NEVERD_PLUGIN_PROCESSOR |
Etichetta di analisi/elaborazione; non pianifica lavoro |
NEVERD_PLUGIN_UI |
Etichetta UI; NeverD non fornisce un host GUI per plugin nativi |
Tutti i puntatori a callback sono opzionali. Le chiamate sono dirette e sincrone sul thread del chiamante host.
| Callback | Contratto |
|---|---|
Init(session) |
Restituisce 0 in caso di successo. Un risultato diverso da zero registra un errore; Term non viene chiamato dopo tale inizializzazione fallita. |
Term() |
Viene chiamato durante la terminazione solo dopo un Init riuscito. La libreria viene quindi scaricata. |
Run(session, arg) |
Esegue il lavoro del plugin e restituisce un risultato intero. La CLI passa 0; l’API C che integra il plugin può scegliere un altro argomento. Una callback assente restituisce -1. |
Event(event) |
Gestisce un evento inviato dall’host. Restituisce 0 in caso di successo; un risultato diverso da zero registra un errore. Una callback assente non esegue alcuna operazione. |
L’ordine di integrazione normale è caricamento, inizializzazione, esecuzione o
invio di eventi, quindi terminazione. L’API C non impone questo ordine a Run o
Event, quindi il ciclo di vita è responsabilità dell’host che integra il
plugin.
neverd_event_t contiene uno dei sei valori di evento:
| Evento | Payload in event->Data |
|---|---|
NEVERD_EVT_BINARY_LOADED |
BinaryLoaded.Path |
NEVERD_EVT_BINARY_CLOSING |
Nessun payload |
NEVERD_EVT_FUNC_SELECTED |
FuncSelected.Addr, FuncSelected.Name |
NEVERD_EVT_ADDR_CHANGED |
AddrChanged.Addr |
NEVERD_EVT_ANALYSIS_DONE |
Nessun payload |
NEVERD_EVT_PATCH_APPLIED |
PatchApplied.OutputPath, PatchApplied.CodeSize |
Gli eventi non vengono emessi automaticamente dalle API di sessione né dallo
strumento a riga di comando neverd. Un host di integrazione costruisce e invia
l’evento:
neverd_event_t event = {0};
event.Type = NEVERD_EVT_BINARY_LOADED;
event.Session = session;
event.Data.BinaryLoaded.Path = input_path;
neverd_plugins_dispatch_event(session, &event);L’evento e le stringhe del payload sono presi in prestito fino al ritorno della
callback; non liberarli né conservarli. L’handle di sessione appartiene all’host:
un plugin non deve distruggerlo né usarlo dopo la terminazione dell’host. I
risultati allocati dall’API C di NeverD appartengono a NeverD e devono essere
liberati con neverd_free_string(). NeverD non garantisce l’accesso concorrente
alle callback o alla sessione: gli host di integrazione devono serializzare le
chiamate del ciclo di vita, di esecuzione e degli eventi, salvo che forniscano
una propria sincronizzazione sicura.
Abilita esplicitamente gli esempi; il valore predefinito resta
NEVERD_BUILD_PLUGINS=OFF:
cmake -S . -B build -G Ninja \
-DCMAKE_BUILD_TYPE=Release \
-DNEVERD_BUILD_PLUGINS=ON
cmake --build build --target neverd example_pluginPer un generatore a configurazione singola, gli artefatti rilevanti sono:
| Artefatto | Percorso |
|---|---|
| CLI | build/bin/neverd (neverd.exe su Windows) |
| Libreria host | build/bin/libneverd.so, build/bin/libneverd.dylib o build/bin/neverd.dll |
| Header preparati | build/bin/sdk/neverd/sdk/ |
| Esempio | build/bin/plugins/example_plugin.so, .dylib o .dll |
Una build multiconfigurazione colloca gli stessi artefatti di runtime sotto la
configurazione selezionata, per esempio build/bin/Release/, con il plugin in
build/bin/Release/plugins/ e gli header in build/bin/Release/sdk/:
cmake -S . -B build -G "Ninja Multi-Config" \
-DNEVERD_BUILD_PLUGINS=ON
cmake --build build --config Release --target neverd example_pluginNeverD attualmente non installa il proprio SDK né fornisce un
NeverDConfig.cmake, quindi non esiste un find_package(NeverD) supportato.
Indirizza una build autonoma agli header preparati e a una libreria di link
esplicita proveniente dalla build esatta dell’host:
cmake_minimum_required(VERSION 3.20)
project(my_neverd_plugin LANGUAGES C)
set(NEVERD_SDK_ROOT "" CACHE PATH
"Directory containing neverd/sdk/NeverDPlugin.h")
set(NEVERD_LINK_LIBRARY "" CACHE FILEPATH
"libneverd.so, libneverd.dylib, or the Windows neverd.lib import library")
if(NOT EXISTS "${NEVERD_SDK_ROOT}/neverd/sdk/NeverDPlugin.h")
message(FATAL_ERROR "Set NEVERD_SDK_ROOT to the staged NeverD SDK")
endif()
if(NOT EXISTS "${NEVERD_LINK_LIBRARY}")
message(FATAL_ERROR "Set NEVERD_LINK_LIBRARY to the matching libneverd")
endif()
add_library(my_plugin SHARED my_plugin.c)
target_include_directories(my_plugin PRIVATE "${NEVERD_SDK_ROOT}")
target_link_libraries(my_plugin PRIVATE "${NEVERD_LINK_LIBRARY}")
set_target_properties(my_plugin PROPERTIES
C_STANDARD 11
C_STANDARD_REQUIRED YES
PREFIX "")Configura con NEVERD_SDK_ROOT=/absolute/path/to/build/bin/sdk (o la directory
sdk specifica della configurazione). Su Linux/macOS,
NEVERD_LINK_LIBRARY è il file .so/.dylib corrispondente. Su Windows è la
libreria di importazione neverd.lib prodotta dal generatore, mentre il file
neverd.dll corrispondente deve restare accanto all’eseguibile host. I percorsi
delle librerie di importazione dipendono dal generatore, quindi passa
esplicitamente il file effettivo.
La CLI esamina le directory in questo ordine; prevalgono i primi percorsi canonici e i primi nomi dei plugin:
pluginsaccanto all’eseguibileneverdin esecuzione.$HOME/.neverd/plugins(HOMEviene usata quando non è vuota; su Windows, la directory del profilo nativa è il fallback).- Ogni voce non vuota di
NEVERD_PLUGIN_PATH, nell’ordine. - La directory fornita da
--plugin-dir.
NEVERD_PLUGIN_PATH usa : tra le voci su Linux/macOS e ; su Windows. Le
directory canonicamente equivalenti vengono esaminate una sola volta. Per le
librerie native viene considerato solo il suffisso dell’host: .so su Linux,
.dylib su macOS e .dll su Windows. Le build con Python abilitato esaminano
anche i file .py.
L’esempio nell’albero di build si trova già nella directory adiacente a quella dell’eseguibile:
build/bin/neverd plugins --list
build/bin/neverd plugins --list --json
build/bin/neverd plugins --run "Example Plugin"
build/bin/neverd plugins --run "Example Plugin" --binary path/to/binaryPer una build multiconfigurazione, sostituisci build/bin con
build/bin/Release. Per installare una copia destinata a un eseguibile NeverD
che non abbia già lo stesso plugin accanto, usa il comando per la piattaforma
host, quindi esegui quel binario con le stesse opzioni --list e --run:
# Linux
mkdir -p "$HOME/.neverd/plugins"
cp build/bin/plugins/example_plugin.so "$HOME/.neverd/plugins/"
# macOS
mkdir -p "$HOME/.neverd/plugins"
cp build/bin/plugins/example_plugin.dylib "$HOME/.neverd/plugins/"
# Windows PowerShell
New-Item -ItemType Directory -Force "$HOME/.neverd/plugins"
Copy-Item build/bin/plugins/example_plugin.dll "$HOME/.neverd/plugins/"Le directory opzionali mancanti accanto all’eseguibile o nel profilo vengono
ignorate. Un plugin malformato in una directory opzionale produce un avviso e
la scansione continua. Ogni directory indicata da NEVERD_PLUGIN_PATH e
--plugin-dir è obbligatoria: una directory mancante o un candidato rifiutato
fa terminare la CLI con un codice diverso da zero. Vengono rifiutati i file
canonici duplicati, i nomi di plugin duplicati, l’assenza dell’export
neverd_plugin e i tipi di descrittore non validi. Anche una chiamata diretta a
neverd_plugins_load_file rifiuta un file con un suffisso non supportato.
Gli host di integrazione devono controllare sia i risultati della gestione dei
plugin sia neverd_last_error(session). neverd_plugins_load_file restituisce
1 o 0; neverd_plugins_load_dir restituisce il numero caricato e può
segnalare candidati rifiutati anche dopo un successo parziale.
neverd_plugins_run restituisce il risultato del plugin e usa -1 quando il
plugin è assente o non può essere eseguito. Libera con neverd_free_string()
ogni stringa di errore o JSON restituita dall’API C.