1 #include "lua/internal.hpp"
2 #include "core/memorymanip.hpp"
3 #include "core/memorywatch.hpp"
4 #include "core/rom.hpp"
5 #include "library/sha256.hpp"
6 #include "library/string.hpp"
7 #include "library/minmax.hpp"
11 template<typename T
, typename U
, U (*rfun
)(uint64_t addr
)>
12 class lua_read_memory
: public lua_function
15 lua_read_memory(const std::string
& name
) : lua_function(LS
, name
) {}
16 int invoke(lua_state
& L
)
18 uint64_t addr
= L
.get_numeric_argument
<uint64_t>(1, fname
.c_str());
19 L
.pushnumber(static_cast<T
>(rfun(addr
)));
24 template<typename T
, bool (*wfun
)(uint64_t addr
, T value
)>
25 class lua_write_memory
: public lua_function
28 lua_write_memory(const std::string
& name
) : lua_function(LS
, name
) {}
29 int invoke(lua_state
& L
)
31 uint64_t addr
= L
.get_numeric_argument
<uint64_t>(1, fname
.c_str());
32 T value
= L
.get_numeric_argument
<T
>(2, fname
.c_str());
42 virtual void read(lua_state
& L
, uint64_t addr
) = 0;
43 virtual void write(lua_state
& L
, uint64_t addr
) = 0;
47 template<typename T
, typename U
, U (*rfun
)(uint64_t addr
), bool (*wfun
)(uint64_t addr
, U value
)>
48 class lua_mmap_memory_helper
: public mmap_base
51 ~lua_mmap_memory_helper() {}
52 void read(lua_state
& L
, uint64_t addr
)
54 L
.pushnumber(static_cast<T
>(rfun(addr
)));
57 void write(lua_state
& L
, uint64_t addr
)
59 T value
= L
.get_numeric_argument
<T
>(3, "aperture(write)");
68 lua_mmap_struct(lua_state
* L
);
74 int index(lua_state
& L
)
76 const char* c
= L
.tostring(2);
82 if(!mappings
.count(c2
)) {
86 auto& x
= mappings
[c2
];
87 x
.first
->read(L
, x
.second
);
90 int newindex(lua_state
& L
)
92 const char* c
= L
.tostring(2);
96 if(!mappings
.count(c2
))
98 auto& x
= mappings
[c2
];
99 x
.first
->write(L
, x
.second
);
103 int map(lua_state
& L
);
105 std::map
<std::string
, std::pair
<mmap_base
*, uint64_t>> mappings
;
110 int aperture_read_fun(lua_State
* _L
)
112 lua_state
& L
= *reinterpret_cast<lua_state
*>(lua_touserdata(_L
, lua_upvalueindex(4)));
113 uint64_t base
= L
.tonumber(lua_upvalueindex(1));
114 uint64_t size
= 0xFFFFFFFFFFFFFFFFULL
;
115 if(L
.type(lua_upvalueindex(2)) == LUA_TNUMBER
)
116 size
= L
.tonumber(lua_upvalueindex(2));
117 mmap_base
* fn
= reinterpret_cast<mmap_base
*>(L
.touserdata(lua_upvalueindex(3)));
118 uint64_t addr
= L
.get_numeric_argument
<uint64_t>(2, "aperture(read)");
119 if(addr
> size
|| addr
+ base
< addr
) {
128 int aperture_write_fun(lua_State
* _L
)
130 lua_state
& L
= *reinterpret_cast<lua_state
*>(lua_touserdata(_L
, lua_upvalueindex(4)));
131 uint64_t base
= L
.tonumber(lua_upvalueindex(1));
132 uint64_t size
= 0xFFFFFFFFFFFFFFFFULL
;
133 if(L
.type(lua_upvalueindex(2)) == LUA_TNUMBER
)
134 size
= L
.tonumber(lua_upvalueindex(2));
135 mmap_base
* fn
= reinterpret_cast<mmap_base
*>(L
.touserdata(lua_upvalueindex(3)));
136 uint64_t addr
= L
.get_numeric_argument
<uint64_t>(2, "aperture(write)");
137 if(addr
> size
|| addr
+ base
< addr
)
144 void aperture_make_fun(lua_state
& L
, uint64_t base
, uint64_t size
, mmap_base
& type
)
148 L
.pushstring( "__index");
154 L
.pushlightuserdata(&type
);
155 L
.pushlightuserdata(&L
);
156 L
.pushcclosure(aperture_read_fun
, 4);
158 L
.pushstring("__newindex");
164 L
.pushlightuserdata(&type
);
165 L
.pushlightuserdata(&L
);
166 L
.pushcclosure(aperture_write_fun
, 4);
171 class lua_mmap_memory
: public lua_function
174 lua_mmap_memory(const std::string
& name
, mmap_base
& _h
) : lua_function(LS
, name
), h(_h
) {}
175 int invoke(lua_state
& L
)
177 if(L
.isnoneornil(1)) {
178 aperture_make_fun(L
, 0, 0xFFFFFFFFFFFFFFFFULL
, h
);
181 uint64_t addr
= L
.get_numeric_argument
<uint64_t>(1, fname
.c_str());
182 uint64_t size
= L
.get_numeric_argument
<uint64_t>(2, fname
.c_str());
184 L
.pushstring("Aperture with zero size is not valid");
188 aperture_make_fun(L
, addr
, size
- 1, h
);
194 function_ptr_luafun
vmacount(LS
, "memory.vma_count", [](lua_state
& L
, const std::string
& fname
) -> int {
195 L
.pushnumber(get_regions().size());
199 int handle_push_vma(lua_state
& L
, std::vector
<memory_region
>& regions
, size_t idx
)
201 if(idx
>= regions
.size()) {
205 memory_region
& r
= regions
[idx
];
207 L
.pushstring("region_name");
208 L
.pushlstring(r
.region_name
.c_str(), r
.region_name
.size());
210 L
.pushstring("baseaddr");
211 L
.pushnumber(r
.baseaddr
);
213 L
.pushstring("size");
214 L
.pushnumber(r
.size
);
216 L
.pushstring("lastaddr");
217 L
.pushnumber(r
.lastaddr
);
219 L
.pushstring("readonly");
220 L
.pushboolean(r
.readonly
);
222 L
.pushstring("iospace");
223 L
.pushboolean(r
.iospace
);
225 L
.pushstring("native_endian");
226 L
.pushboolean(r
.native_endian
);
231 function_ptr_luafun
readvma(LS
, "memory.read_vma", [](lua_state
& L
, const std::string
& fname
) -> int {
232 std::vector
<memory_region
> regions
= get_regions();
233 uint32_t num
= L
.get_numeric_argument
<uint32_t>(1, fname
.c_str());
234 return handle_push_vma(L
, regions
, num
);
237 function_ptr_luafun
findvma(LS
, "memory.find_vma", [](lua_state
& L
, const std::string
& fname
) -> int {
238 std::vector
<memory_region
> regions
= get_regions();
239 uint64_t addr
= L
.get_numeric_argument
<uint64_t>(1, fname
.c_str());
241 for(i
= 0; i
< regions
.size(); i
++)
242 if(addr
>= regions
[i
].baseaddr
&& addr
<= regions
[i
].lastaddr
)
244 return handle_push_vma(L
, regions
, i
);
247 const char* hexes
= "0123456789ABCDEF";
249 function_ptr_luafun
hashstate(LS
, "memory.hash_state", [](lua_state
& L
, const std::string
& fname
) -> int {
251 auto x
= save_core_state();
252 size_t offset
= x
.size() - 32;
253 for(unsigned i
= 0; i
< 32; i
++) {
254 hash
[2 * i
+ 0] = hexes
[static_cast<unsigned char>(x
[offset
+ i
]) >> 4];
255 hash
[2 * i
+ 1] = hexes
[static_cast<unsigned char>(x
[offset
+ i
]) & 0xF];
257 L
.pushlstring(hash
, 64);
261 #define BLOCKSIZE 256
263 function_ptr_luafun
hashmemory(LS
, "memory.hash_region", [](lua_state
& L
, const std::string
& fname
) -> int {
265 uint64_t addr
= L
.get_numeric_argument
<uint64_t>(1, fname
.c_str());
266 uint64_t size
= L
.get_numeric_argument
<uint64_t>(2, fname
.c_str());
267 char buffer
[BLOCKSIZE
];
269 while(size
> BLOCKSIZE
) {
270 for(size_t i
= 0; i
< BLOCKSIZE
; i
++)
271 buffer
[i
] = memory_read_byte(addr
+ i
);
272 h
.write(buffer
, BLOCKSIZE
);
276 for(size_t i
= 0; i
< size
; i
++)
277 buffer
[i
] = memory_read_byte(addr
+ i
);
278 h
.write(buffer
, size
);
280 L
.pushlstring(hash
.c_str(), 64);
284 function_ptr_luafun
readmemoryr(LS
, "memory.readregion", [](lua_state
& L
, const std::string
& fname
) -> int {
286 uint64_t addr
= L
.get_numeric_argument
<uint64_t>(1, fname
.c_str());
287 uint64_t size
= L
.get_numeric_argument
<uint64_t>(2, fname
.c_str());
289 char buffer
[BLOCKSIZE
];
292 size_t rsize
= min(size
, static_cast<uint64_t>(BLOCKSIZE
));
293 memory_read_bytes(addr
, rsize
, buffer
);
294 for(size_t i
= 0; i
< rsize
; i
++) {
296 L
.pushnumber(static_cast<unsigned char>(buffer
[i
]));
305 function_ptr_luafun
writememoryr(LS
, "memory.writeregion", [](lua_state
& L
, const std::string
& fname
) -> int {
307 uint64_t addr
= L
.get_numeric_argument
<uint64_t>(1, fname
.c_str());
308 uint64_t size
= L
.get_numeric_argument
<uint64_t>(2, fname
.c_str());
309 char buffer
[BLOCKSIZE
];
312 size_t rsize
= min(size
, static_cast<uint64_t>(BLOCKSIZE
));
313 for(size_t i
= 0; i
< rsize
; i
++) {
316 buffer
[i
] = L
.tointeger(-1);
319 memory_write_bytes(addr
, rsize
, buffer
);
326 function_ptr_luafun
gui_cbitmap(LS
, "memory.map_structure", [](lua_state
& L
, const std::string
& fname
) ->
328 lua_mmap_struct
* b
= lua_class
<lua_mmap_struct
>::create(L
, &L
);
332 function_ptr_luafun
memory_watchexpr(LS
, "memory.read_expr", [](lua_state
& L
, const std::string
& fname
) ->
334 std::string val
= evaluate_watch(L
.get_string(1, fname
.c_str()));
335 L
.pushstring(val
.c_str());
339 lua_read_memory
<uint8_t, uint8_t, memory_read_byte
> rub("memory.readbyte");
340 lua_read_memory
<int8_t, uint8_t, memory_read_byte
> rsb("memory.readsbyte");
341 lua_read_memory
<uint16_t, uint16_t, memory_read_word
> ruw("memory.readword");
342 lua_read_memory
<int16_t, uint16_t, memory_read_word
> rsw("memory.readsword");
343 lua_read_memory
<uint32_t, uint32_t, memory_read_dword
> rud("memory.readdword");
344 lua_read_memory
<int32_t, uint32_t, memory_read_dword
> rsd("memory.readsdword");
345 lua_read_memory
<uint64_t, uint64_t, memory_read_qword
> ruq("memory.readqword");
346 lua_read_memory
<int64_t, uint64_t, memory_read_qword
> rsq("memory.readsqword");
347 lua_write_memory
<uint8_t, memory_write_byte
> wb("memory.writebyte");
348 lua_write_memory
<uint16_t, memory_write_word
> ww("memory.writeword");
349 lua_write_memory
<uint32_t, memory_write_dword
> wd("memory.writedword");
350 lua_write_memory
<uint64_t, memory_write_qword
> wq("memory.writeqword");
351 lua_mmap_memory_helper
<uint8_t, uint8_t, memory_read_byte
, memory_write_byte
> mhub
;
352 lua_mmap_memory_helper
<int8_t, uint8_t, memory_read_byte
, memory_write_byte
> mhsb
;
353 lua_mmap_memory_helper
<uint16_t, uint16_t, memory_read_word
, memory_write_word
> mhuw
;
354 lua_mmap_memory_helper
<int16_t, uint16_t, memory_read_word
, memory_write_word
> mhsw
;
355 lua_mmap_memory_helper
<uint32_t, uint32_t, memory_read_dword
, memory_write_dword
> mhud
;
356 lua_mmap_memory_helper
<int32_t, uint32_t, memory_read_dword
, memory_write_dword
> mhsd
;
357 lua_mmap_memory_helper
<uint64_t, uint64_t, memory_read_qword
, memory_write_qword
> mhuq
;
358 lua_mmap_memory_helper
<int64_t, uint64_t, memory_read_qword
, memory_write_qword
> mhsq
;
359 lua_mmap_memory
mub("memory.mapbyte", mhub
);
360 lua_mmap_memory
msb("memory.mapsbyte", mhsb
);
361 lua_mmap_memory
muw("memory.mapword", mhuw
);
362 lua_mmap_memory
msw("memory.mapsword", mhsw
);
363 lua_mmap_memory
mud("memory.mapdword", mhud
);
364 lua_mmap_memory
msd("memory.mapsdword", mhsd
);
365 lua_mmap_memory
muq("memory.mapqword", mhuq
);
366 lua_mmap_memory
msq("memory.mapsqword", mhsq
);
370 int lua_mmap_struct::map(lua_state
& L
)
372 const char* name
= L
.tostring(2);
373 uint64_t addr
= L
.get_numeric_argument
<uint64_t>(3, "lua_mmap_struct::map");
374 const char* type
= L
.tostring(4);
376 L
.pushstring("lua_mmap_struct::map: Bad name");
381 L
.pushstring("lua_mmap_struct::map: Bad type");
385 std::string
name2(name
);
386 std::string
type2(type
);
388 mappings
[name2
] = std::make_pair(&mhub
, addr
);
389 else if(type2
== "sbyte")
390 mappings
[name2
] = std::make_pair(&mhsb
, addr
);
391 else if(type2
== "word")
392 mappings
[name2
] = std::make_pair(&mhuw
, addr
);
393 else if(type2
== "sword")
394 mappings
[name2
] = std::make_pair(&mhsw
, addr
);
395 else if(type2
== "dword")
396 mappings
[name2
] = std::make_pair(&mhud
, addr
);
397 else if(type2
== "sdword")
398 mappings
[name2
] = std::make_pair(&mhsd
, addr
);
399 else if(type2
== "qword")
400 mappings
[name2
] = std::make_pair(&mhuq
, addr
);
401 else if(type2
== "sqword")
402 mappings
[name2
] = std::make_pair(&mhsq
, addr
);
404 L
.pushstring("lua_mmap_struct::map: Bad type");
411 DECLARE_LUACLASS(lua_mmap_struct
, "MMAP_STRUCT");
413 lua_mmap_struct::lua_mmap_struct(lua_state
* L
)
416 L
->pushlightuserdata(&key
);
417 L
->rawget(LUA_REGISTRYINDEX
);
418 if(L
->type(-1) == LUA_TNIL
) {
420 L
->pushlightuserdata(&key
);
421 L
->pushboolean(true);
422 L
->rawset(LUA_REGISTRYINDEX
);
423 objclass
<lua_mmap_struct
>().bind(*L
, "__index", &lua_mmap_struct::index
, true);
424 objclass
<lua_mmap_struct
>().bind(*L
, "__newindex", &lua_mmap_struct::newindex
, true);
425 objclass
<lua_mmap_struct
>().bind(*L
, "__call", &lua_mmap_struct::map
);