@@ -254,6 +254,156 @@ int l_goto(lua_State* L) {
254254 return 0 ;
255255}
256256
257+ int l_get_comment (lua_State* L) {
258+ auto * db = get_db (L);
259+ if (!db) { lua_pushstring (L, " " ); return 1 ; }
260+ va_t addr = static_cast <va_t >(luaL_checkinteger (L, 1 ));
261+ auto it = db->comments .find (addr);
262+ if (it != db->comments .end ())
263+ lua_pushstring (L, it->second .c_str ());
264+ else
265+ lua_pushstring (L, " " );
266+ return 1 ;
267+ }
268+
269+ int l_get_string (lua_State* L) {
270+ auto * db = get_db (L);
271+ if (!db) { lua_pushnil (L); return 1 ; }
272+ va_t addr = static_cast <va_t >(luaL_checkinteger (L, 1 ));
273+ for (auto & [sa, ss] : db->strings ) {
274+ if (sa == addr) {
275+ lua_pushstring (L, ss.c_str ());
276+ return 1 ;
277+ }
278+ }
279+ lua_pushnil (L);
280+ return 1 ;
281+ }
282+
283+ int l_get_image_base (lua_State* L) {
284+ auto * db = get_db (L);
285+ if (!db) { lua_pushinteger (L, 0 ); return 1 ; }
286+ lua_pushinteger (L, static_cast <lua_Integer>(db->image_base ));
287+ return 1 ;
288+ }
289+
290+ int l_get_arch (lua_State* L) {
291+ auto * img = get_img (L);
292+ if (!img) { lua_pushstring (L, " unknown" ); return 1 ; }
293+ switch (img->arch ) {
294+ case Arch::X86 : lua_pushstring (L, " x86" ); break ;
295+ case Arch::X64 : lua_pushstring (L, " x64" ); break ;
296+ case Arch::ARM : lua_pushstring (L, " arm" ); break ;
297+ case Arch::ARM64 : lua_pushstring (L, " arm64" ); break ;
298+ case Arch::MIPS : lua_pushstring (L, " mips" ); break ;
299+ case Arch::PPC : lua_pushstring (L, " ppc" ); break ;
300+ default : lua_pushstring (L, " unknown" ); break ;
301+ }
302+ return 1 ;
303+ }
304+
305+ int l_get_segments (lua_State* L) {
306+ auto * img = get_img (L);
307+ if (!img) { lua_newtable (L); return 1 ; }
308+ lua_newtable (L);
309+ int idx = 1 ;
310+ for (auto & seg : img->segments ) {
311+ lua_newtable (L);
312+ lua_pushstring (L, seg.name .c_str ());
313+ lua_setfield (L, -2 , " name" );
314+ lua_pushinteger (L, static_cast <lua_Integer>(seg.va ));
315+ lua_setfield (L, -2 , " addr" );
316+ lua_pushinteger (L, static_cast <lua_Integer>(seg.data .size ()));
317+ lua_setfield (L, -2 , " size" );
318+ lua_pushinteger (L, static_cast <lua_Integer>(seg.flags ));
319+ lua_setfield (L, -2 , " flags" );
320+ lua_rawseti (L, -2 , idx++);
321+ }
322+ return 1 ;
323+ }
324+
325+ int l_get_cursor (lua_State* L) {
326+ // The cursor is held by DisasmView; we expose it via a registry pointer set by App
327+ lua_getfield (L, LUA_REGISTRYINDEX , " __hype_cursor" );
328+ auto * cur = static_cast <va_t *>(lua_touserdata (L, -1 ));
329+ lua_pop (L, 1 );
330+ if (!cur) { lua_pushinteger (L, 0 ); return 1 ; }
331+ lua_pushinteger (L, static_cast <lua_Integer>(*cur));
332+ return 1 ;
333+ }
334+
335+ int l_create_function (lua_State* L) {
336+ auto * db = get_db (L);
337+ if (!db) return 0 ;
338+ va_t addr = static_cast <va_t >(luaL_checkinteger (L, 1 ));
339+ std::lock_guard lk (db->mtx );
340+ if (!db->funcs .count (addr)) {
341+ Function f;
342+ f.entry = addr;
343+ f.name = fmt::format (" sub_{:X}" , addr - db->image_base );
344+ db->funcs [addr] = std::move (f);
345+ db->names [addr] = db->funcs [addr].name ;
346+ }
347+ return 0 ;
348+ }
349+
350+ // -----------------------------------------------------------------------
351+ // open_results(title, headers_table, rows_table)
352+ // headers_table : {"Col1", "Col2", ...}
353+ // rows_table : { {addr=0x..., cols={"v1","v2",...}}, ... }
354+ // -----------------------------------------------------------------------
355+ int l_open_results (lua_State* L) {
356+ auto * eng = get_engine (L);
357+ if (!eng) return 0 ;
358+
359+ const char * title = luaL_checkstring (L, 1 );
360+ luaL_checktype (L, 2 , LUA_TTABLE );
361+ luaL_checktype (L, 3 , LUA_TTABLE );
362+
363+ ResultsWindow w;
364+ w.title = title;
365+
366+ // Read headers
367+ int nhdr = static_cast <int >(lua_rawlen (L, 2 ));
368+ for (int i = 1 ; i <= nhdr; ++i) {
369+ lua_rawgeti (L, 2 , i);
370+ const char * s = lua_tostring (L, -1 );
371+ w.headers .push_back (s ? s : " " );
372+ lua_pop (L, 1 );
373+ }
374+
375+ // Read rows
376+ int nrows = static_cast <int >(lua_rawlen (L, 3 ));
377+ for (int i = 1 ; i <= nrows; ++i) {
378+ lua_rawgeti (L, 3 , i); // push row table
379+ if (!lua_istable (L, -1 )) { lua_pop (L, 1 ); continue ; }
380+
381+ ResultsRow row;
382+
383+ lua_getfield (L, -1 , " addr" );
384+ row.addr = static_cast <va_t >(lua_tointeger (L, -1 ));
385+ lua_pop (L, 1 );
386+
387+ lua_getfield (L, -1 , " cols" ); // push cols table
388+ if (lua_istable (L, -1 )) {
389+ int ncols = static_cast <int >(lua_rawlen (L, -1 ));
390+ for (int c = 1 ; c <= ncols; ++c) {
391+ lua_rawgeti (L, -1 , c);
392+ const char * s = lua_tostring (L, -1 );
393+ row.cols .push_back (s ? s : " " );
394+ lua_pop (L, 1 );
395+ }
396+ }
397+ lua_pop (L, 1 ); // pop cols table
398+ lua_pop (L, 1 ); // pop row table
399+
400+ w.rows .push_back (std::move (row));
401+ }
402+
403+ eng->push_result_window (std::move (w));
404+ return 0 ;
405+ }
406+
257407// -----------------------------------------------------------------------
258408// Plugin registration Lua API
259409// -----------------------------------------------------------------------
@@ -369,16 +519,24 @@ void LuaEngine::register_api() {
369519 lua_setfield (L_ , LUA_REGISTRYINDEX , " __hype_nav" );
370520
371521 // Core API
372- lua_register (L_ , " get_name" , l_get_name);
373- lua_register (L_ , " set_name" , l_set_name);
374- lua_register (L_ , " get_func" , l_get_func);
375- lua_register (L_ , " get_insn" , l_get_insn);
376- lua_register (L_ , " get_bytes" , l_get_bytes);
377- lua_register (L_ , " set_comment" , l_set_comment);
378- lua_register (L_ , " get_xrefs_to" , l_get_xrefs_to);
379- lua_register (L_ , " get_functions" , l_get_functions);
380- lua_register (L_ , " print" , l_print);
381- lua_register (L_ , " goto_addr" , l_goto);
522+ lua_register (L_ , " get_name" , l_get_name);
523+ lua_register (L_ , " set_name" , l_set_name);
524+ lua_register (L_ , " get_func" , l_get_func);
525+ lua_register (L_ , " get_insn" , l_get_insn);
526+ lua_register (L_ , " get_bytes" , l_get_bytes);
527+ lua_register (L_ , " set_comment" , l_set_comment);
528+ lua_register (L_ , " get_comment" , l_get_comment);
529+ lua_register (L_ , " get_xrefs_to" , l_get_xrefs_to);
530+ lua_register (L_ , " get_functions" , l_get_functions);
531+ lua_register (L_ , " print" , l_print);
532+ lua_register (L_ , " goto_addr" , l_goto);
533+ lua_register (L_ , " get_string" , l_get_string);
534+ lua_register (L_ , " get_image_base" , l_get_image_base);
535+ lua_register (L_ , " get_arch" , l_get_arch);
536+ lua_register (L_ , " get_segments" , l_get_segments);
537+ lua_register (L_ , " get_cursor" , l_get_cursor);
538+ lua_register (L_ , " create_function" ,l_create_function);
539+ lua_register (L_ , " open_results" , l_open_results);
382540
383541 // Plugin registration API
384542 lua_register (L_ , " register_plugin" , l_register_plugin);
@@ -398,16 +556,24 @@ void LuaEngine::load_plugins(const std::filesystem::path& dir) {
398556 lua_setfield (L_ , LUA_REGISTRYINDEX , " __hype_output" );
399557
400558 // Register plugin API functions (safe even with null db_/img_)
401- lua_register (L_ , " get_name" , l_get_name);
402- lua_register (L_ , " set_name" , l_set_name);
403- lua_register (L_ , " get_func" , l_get_func);
404- lua_register (L_ , " get_insn" , l_get_insn);
405- lua_register (L_ , " get_bytes" , l_get_bytes);
406- lua_register (L_ , " set_comment" , l_set_comment);
407- lua_register (L_ , " get_xrefs_to" , l_get_xrefs_to);
408- lua_register (L_ , " get_functions" , l_get_functions);
409- lua_register (L_ , " print" , l_print);
410- lua_register (L_ , " goto_addr" , l_goto);
559+ lua_register (L_ , " get_name" , l_get_name);
560+ lua_register (L_ , " set_name" , l_set_name);
561+ lua_register (L_ , " get_func" , l_get_func);
562+ lua_register (L_ , " get_insn" , l_get_insn);
563+ lua_register (L_ , " get_bytes" , l_get_bytes);
564+ lua_register (L_ , " set_comment" , l_set_comment);
565+ lua_register (L_ , " get_comment" , l_get_comment);
566+ lua_register (L_ , " get_xrefs_to" , l_get_xrefs_to);
567+ lua_register (L_ , " get_functions" , l_get_functions);
568+ lua_register (L_ , " print" , l_print);
569+ lua_register (L_ , " goto_addr" , l_goto);
570+ lua_register (L_ , " get_string" , l_get_string);
571+ lua_register (L_ , " get_image_base" , l_get_image_base);
572+ lua_register (L_ , " get_arch" , l_get_arch);
573+ lua_register (L_ , " get_segments" , l_get_segments);
574+ lua_register (L_ , " get_cursor" , l_get_cursor);
575+ lua_register (L_ , " create_function" ,l_create_function);
576+ lua_register (L_ , " open_results" , l_open_results);
411577 lua_register (L_ , " register_plugin" , l_register_plugin);
412578 lua_register (L_ , " register_menu_item" , l_register_menu_item);
413579 lua_register (L_ , " register_hotkey" , l_register_hotkey);
@@ -467,14 +633,8 @@ void LuaEngine::invoke_menu_item(int plugin_idx, int item_idx) {
467633 output_ += std::string (" [plugin error] " ) + (msg ? msg : " unknown" ) + " \n " ;
468634 lua_pop (L_ , 1 );
469635 }
470- // output_ is forwarded to the Script Console by scriptc_ which reads it via execute()
471- // For plugin callbacks we flush directly via the output panel pointer stored in registry
472- lua_getfield (L_ , LUA_REGISTRYINDEX , " __hype_output" );
473- auto * out_ptr = static_cast <std::string*>(lua_touserdata (L_ , -1 ));
474- lua_pop (L_ , 1 );
475- if (out_ptr && out_ptr != &output_) {
476- *out_ptr += output_;
477- }
636+ // output_ holds everything l_print wrote during the call.
637+ // The caller (App::render_menubar) reads it via last_output().
478638}
479639
480640void LuaEngine::run_analysis_complete_callbacks () {
0 commit comments