rizin/librz/bin/format/luac/luac_bin.c
Khairul Azhar Kasmiran c8878d3139
Convert %ll format specifiers to PFMT64 (#6267)
* Convert `%ll` format specifiers to PFMT64
* Remove ` ""` at end of some PFMT64
2026-04-22 05:57:04 +08:00

279 lines
8.2 KiB
C

// SPDX-License-Identifier: LGPL-3.0-only
// SPDX-FileCopyrightText: 2021 Heersin <teablearcher@gmail.com>
// SPDX-FileCopyrightText: 2025-2026 Sergey Sharshunov <s.sharshunov@gmail.com>
#include "luac_common.h"
void luac_add_section(RzPVector /*<RzBinSection *>*/ *section_vec, char *name, ut64 poffset, ut64 voffset, ut32 size, bool is_func) {
if (size == 0)
return;
RzBinSection *bin_sec = RZ_NEW0(RzBinSection);
if (!bin_sec || !name) {
free(bin_sec);
return;
}
bin_sec->name = rz_str_dup(name);
bin_sec->vaddr = voffset;
bin_sec->paddr = poffset;
bin_sec->size = size;
bin_sec->vsize = size;
bin_sec->is_data = is_func ? false : true;
bin_sec->bits = 32;
bin_sec->has_strings = false;
bin_sec->arch = "luac";
if (is_func) {
bin_sec->perm = RZ_PERM_R | RZ_PERM_X;
} else {
bin_sec->perm = RZ_PERM_R;
}
if (!rz_pvector_push(section_vec, bin_sec)) {
rz_bin_section_free(bin_sec);
}
}
void luac_add_symbol(RzList /*<RzBinSymbol *>*/ *symbol_list, char *name, ut64 poffset, ut64 voffset, ut64 size, const char *type) {
RzBinSymbol *bin_sym = RZ_NEW0(RzBinSymbol);
if (!bin_sym) {
return;
}
bin_sym->name = rz_str_dup(name);
bin_sym->vaddr = voffset;
bin_sym->paddr = poffset;
bin_sym->size = size;
bin_sym->type = type;
bin_sym->bits = 32;
rz_list_append(symbol_list, bin_sym);
}
void luac_add_entry(RzPVector /*<RzBinAddr *>*/ *entry_vec, ut64 offset, int entry_type) {
RzBinAddr *entry = RZ_NEW0(RzBinAddr);
if (!entry) {
return;
}
entry->vaddr = offset;
entry->paddr = offset;
entry->type = entry_type;
rz_pvector_push(entry_vec, entry);
}
void luac_add_string(RzList /*<RzBinString *>*/ *string_list, char *string, ut64 poffset, ut64 voffset, ut64 size) {
RzBinString *bin_string = RZ_NEW0(RzBinString);
if (!bin_string) {
return;
}
bin_string->paddr = poffset;
bin_string->vaddr = voffset;
bin_string->size = size + 1;
bin_string->length = size;
bin_string->string = rz_str_dup(string);
bin_string->type = RZ_STRING_ENC_UTF8;
rz_list_append(string_list, bin_string);
}
static void free_rz_section(RzBinSection *section) {
if (!section) {
return;
}
if (section->name) {
RZ_FREE(section->name);
}
RZ_FREE(section);
}
static void free_rz_string(RzBinString *string) {
if (!string) {
return;
}
if (string->string) {
RZ_FREE(string->string);
}
RZ_FREE(string);
}
static void free_rz_addr(RzBinAddr *addr) {
if (!addr) {
return;
}
RZ_FREE(addr);
}
void luac_build_info_free(LuacBinInfo *bin_info) {
if (!bin_info) {
return;
}
free(bin_info->header->src_file_name);
free(bin_info->header);
lua_free_proto_entry(bin_info->proto);
bin_info->proto = NULL;
rz_pvector_free(bin_info->protos_vec);
rz_pvector_free(bin_info->all_const_vec);
rz_pvector_free(bin_info->entry_vec);
rz_list_free(bin_info->symbol_list);
rz_pvector_free(bin_info->line_nums_vec);
rz_pvector_free(bin_info->section_vec);
rz_list_free(bin_info->string_list);
free(bin_info);
}
static void free_line_nums(RzBinSourceLineSample *ln) {
if (!ln) {
return;
}
if (ln->file) {
RZ_FREE(ln->file);
}
RZ_FREE(ln);
}
LuacBinInfo *luac_build_info(RZ_NONNULL LuaProto *proto) {
if (!proto) {
RZ_LOG_ERROR("Invalid luac file\n");
return NULL;
}
LuacBinInfo *ret = RZ_NEW0(LuacBinInfo);
rz_return_val_if_fail(ret, NULL);
ret->protos_vec = rz_pvector_new((RzPVectorFree)NULL);
ret->all_const_vec = rz_pvector_new((RzPVectorFree)NULL);
ret->entry_vec = rz_pvector_new((RzPVectorFree)free_rz_addr);
ret->symbol_list = rz_list_newf((RzListFree)rz_bin_symbol_free);
ret->section_vec = rz_pvector_new((RzPVectorFree)free_rz_section);
ret->line_nums_vec = rz_pvector_new((RzPVectorFree)free_line_nums);
ret->string_list = rz_list_newf((RzListFree)free_rz_string);
if (!(ret->entry_vec && ret->symbol_list && ret->section_vec && ret->string_list)) {
rz_pvector_free(ret->entry_vec);
rz_list_free(ret->symbol_list);
rz_pvector_free(ret->section_vec);
rz_pvector_free(ret->line_nums_vec);
rz_list_free(ret->string_list);
}
_luac_build_info(proto, ret);
LuaConstEntry *const_entry = NULL;
void **it;
rz_pvector_foreach (ret->all_const_vec, it) {
const_entry = *it;
if (const_entry->tag == LUA_VSTRING_IDX) {
const LuaConstEntry *tmp_const = rz_pvector_at(ret->all_const_vec, *(ut8 *)const_entry->data);
rz_warn_if_fail(tmp_const);
RZ_FREE(const_entry->data);
const int new_len = tmp_const->data_len + 1;
const_entry->data = RZ_NEWS(ut8, new_len);
rz_mem_copy(const_entry->data, new_len, tmp_const->data, new_len);
const_entry->data_len = tmp_const->data_len;
const_entry->tag = tmp_const->tag;
const_entry->offset = tmp_const->offset;
const_entry->prev_offset = tmp_const->prev_offset;
const_entry->voffset = tmp_const->voffset;
const_entry->string_start = tmp_const->string_start;
}
}
// add entry of main
ut64 main_entry_offset = 0x0 + PROTO_VBASE;
luac_add_entry(ret->entry_vec, main_entry_offset, RZ_BIN_ENTRY_TYPE_PROGRAM);
size_t paddr = proto->code_offset + proto->code_skipped;
RzBinSymbol *msym = rz_bin_symbol_new("entry0", paddr, main_entry_offset);
msym->type = RZ_BIN_TYPE_FUNC_STR;
msym->bind = RZ_BIN_BIND_GLOBAL_STR;
msym->size = proto->code_size; // section->size;
msym->paddr = paddr;
rz_list_append(ret->symbol_list, msym);
return ret;
}
void _luac_build_info(LuaProto *proto, LuacBinInfo *info) {
/* process proto header info */
char *symbol_name = NULL;
char *proto_name = NULL;
char **upvalue_names = NULL;
RzListIter *iter;
ut64 current_offset = 0;
ut64 current_size = 0;
char *section_name = NULL;
const ut64 proto_vaddr = PROTO_VADDRESS(proto->index);
// 1.0 set section name as function_name.code
current_offset = proto->code_offset + proto->code_skipped;
current_size = proto->code_size;
proto_name = rz_str_newf("fcn.%08" PFMT64x, (ut64)proto_vaddr);
section_name = rz_str_newf("%s.code", proto_name);
luac_add_section(info->section_vec, section_name, current_offset, proto_vaddr, current_size, true);
char *name = proto->line_defined == 0 ? rz_str_dup("entry0") : rz_str_newf("proto%d", proto->index);
RzBinSymbol *proto_sym = rz_bin_symbol_new(name, current_offset, proto_vaddr);
proto_sym->bind = RZ_BIN_BIND_GLOBAL_STR;
proto_sym->type = RZ_BIN_TYPE_FUNC_STR;
proto_sym->bits = 32;
proto_sym->size = current_size;
rz_list_append(info->symbol_list, proto_sym);
RZ_FREE(name);
RZ_FREE(section_name);
// 1.2 set const section
current_offset = proto->const_offset;
current_size = proto->const_size;
section_name = rz_str_newf("%s.const", proto_name);
const ut64 const_voffset = proto_vaddr + CONST_OFFSET;
luac_add_section(info->section_vec, section_name, current_offset, const_voffset, current_size, false);
RZ_FREE(section_name);
LuaLineinfoEntry *line_info_entry;
rz_list_foreach (proto->line_info_entries, iter, line_info_entry) {
RzBinSourceLineSample *new_line_sample = RZ_NEW0(RzBinSourceLineSample);
if (!new_line_sample) {
return;
}
new_line_sample->address = line_info_entry->offset;
new_line_sample->column = 0;
new_line_sample->line = line_info_entry->info_data;
new_line_sample->file = rz_str_dup((const char *)proto->proto_name);
rz_pvector_push(info->line_nums_vec, new_line_sample);
}
// 1.3 upvalue section
current_offset = proto->upvalue_offset;
current_size = proto->upvalue_size;
section_name = rz_str_newf("%s.upvalues", proto_name);
const ut64 upvalues_voffset = proto_vaddr + UPVALUE_OFFSET;
luac_add_section(info->section_vec, section_name, current_offset, upvalues_voffset, current_size, false);
RZ_FREE(section_name);
// 1.4 debug section
current_offset = proto->local_var_offset;
current_size = proto->local_var_size;
section_name = rz_str_newf("%s.lvars", proto_name);
const ut64 lvars_voffset = proto_vaddr + LVARS_OFFSET;
luac_add_section(info->section_vec, section_name, current_offset, lvars_voffset, current_size, false);
RZ_FREE(section_name);
RZ_FREE(proto_name);
// 1.5 construct constant symbols
LuaConstEntry *const_entry = NULL;
void **it;
rz_pvector_foreach (proto->const_entries, it) {
const_entry = *it;
rz_pvector_push(info->all_const_vec, const_entry);
}
(void)symbol_name;
rz_pvector_push(info->protos_vec, proto);
// 1.6 parse sub proto
LuaProto *sub_proto;
rz_list_foreach (proto->proto_entries, iter, sub_proto) {
_luac_build_info(sub_proto, info);
}
free(upvalue_names);
free(proto_name);
}