#include <pro.h>
#include <ida.hpp>
#include <bytes.hpp>
#include <stdexcept>
#include <vector>
#include "gen_bytes.h"
namespace idakit_gen {
namespace {
bool range_loaded(ea_t ea, size_t n) {
for (size_t i = 0; i < n; i++)
if (!is_loaded(ea + i))
return false;
return true;
}
}
rust::Vec<uint8_t> get_bytes(uint64_t ea, size_t size) {
std::vector<uint8_t> buf(size);
int64_t r = (int64_t)::get_bytes(buf.data(), (ssize_t)size, (ea_t)ea, GMB_READALL);
if (r < 0)
throw std::runtime_error("get_bytes failed: unmapped range");
rust::Vec<uint8_t> out;
out.reserve(size);
for (size_t i = 0; i < size; i++)
out.push_back(buf[i]);
return out;
}
uint8_t get_u8(uint64_t ea) {
if (!range_loaded((ea_t)ea, 1))
throw std::runtime_error("get_u8: byte uninitialized");
return (uint8_t)get_byte((ea_t)ea);
}
uint16_t get_u16(uint64_t ea) {
if (!range_loaded((ea_t)ea, 2))
throw std::runtime_error("get_u16: covered byte uninitialized");
return (uint16_t)get_word((ea_t)ea);
}
uint32_t get_u32(uint64_t ea) {
if (!range_loaded((ea_t)ea, 4))
throw std::runtime_error("get_u32: covered byte uninitialized");
return (uint32_t)get_dword((ea_t)ea);
}
uint64_t get_u64(uint64_t ea) {
if (!range_loaded((ea_t)ea, 8))
throw std::runtime_error("get_u64: covered byte uninitialized");
return (uint64_t)get_qword((ea_t)ea);
}
rust::String get_strlit(uint64_t ea, int32_t strtype) {
size_t len = get_max_strlit_length((ea_t)ea, strtype, ALOPT_IGNHEADS);
if (len == 0)
throw std::runtime_error("no string literal at address");
qstring out;
ssize_t r = get_strlit_contents(&out, (ea_t)ea, len, strtype, nullptr, STRCONV_REPLCHAR);
if (r < 0)
throw std::runtime_error("undecodable string literal");
return rust::String(out.c_str(), out.length());
}
uint64_t get_flags(uint64_t ea) { return (uint64_t)::get_flags((ea_t)ea); }
uint64_t get_item_head(uint64_t ea) { return (uint64_t)::get_item_head((ea_t)ea); }
uint64_t get_item_end(uint64_t ea) { return (uint64_t)::get_item_end((ea_t)ea); }
uint64_t get_next_head(uint64_t ea, uint64_t maxea) {
return (uint64_t)next_head((ea_t)ea, (ea_t)maxea);
}
uint64_t get_prev_head(uint64_t ea, uint64_t minea) {
return (uint64_t)prev_head((ea_t)ea, (ea_t)minea);
}
rust::String get_cmt(uint64_t ea, bool rptble) {
qstring out;
if (::get_cmt(&out, (ea_t)ea, rptble) < 0)
throw std::runtime_error("no comment at address");
return rust::String(out.c_str(), out.length());
}
}