Rizin
unix-like reverse engineering framework and cli tools
basefind.c File Reference
#include <rz_basefind.h>
#include <rz_th.h>

Go to the source code of this file.

Classes

struct  basefind_addresses_t
 
struct  basefind_data_t
 
struct  basefind_thread_data_t
 
struct  basefind_ui_info_t
 

Typedefs

typedef struct basefind_addresses_t BaseFindArray
 
typedef struct basefind_data_t BaseFindData
 
typedef struct basefind_thread_data_t BaseFindThreadData
 
typedef struct basefind_ui_info_t BaseFindUIInfo
 

Functions

static void basefind_stop_all_search_threads (RzThreadPool *pool)
 
static RzBinFilebasefind_new_bin_file (RzCore *core)
 
static void basefind_array_free (BaseFindArray *array)
 
static bool basefind_array_has (const BaseFindArray *array, ut64 value)
 
static BaseFindArraybasefind_create_array_of_addresses (RzCore *core, ut32 min_string_len)
 
static HtUU * basefind_create_pointer_map (RzCore *core, ut32 pointer_size)
 
static bool basefind_pointer_map_iter (BaseFindData *bfd, const ut64 address, const ut64 hits)
 
static int basefind_score_compare (const RzBaseFindScore *a, const RzBaseFindScore *b)
 
static void * basefind_thread_runner (BaseFindThreadData *bftd)
 
static void basefind_set_thread_info (BaseFindThreadData *bftd, RzBaseFindThreadInfo *th_info, ut32 thread_idx)
 
static void * basefind_thread_ui (BaseFindUIInfo *ui_info)
 
static bool create_thread_interval (RzThreadPool *pool, BaseFindThreadData *bfd)
 
RZ_API RZ_OWN RzListrz_basefind (RZ_NONNULL RzCore *core, RZ_NONNULL RzBaseFindOpt *options)
 Calculates a list of possible base addresses candidates using the strings position. More...
 

Typedef Documentation

◆ BaseFindArray

◆ BaseFindData

typedef struct basefind_data_t BaseFindData

◆ BaseFindThreadData

◆ BaseFindUIInfo

Function Documentation

◆ basefind_array_free()

static void basefind_array_free ( BaseFindArray array)
static

Definition at line 91 of file basefind.c.

91  {
92  if (!array) {
93  return;
94  }
95  free(array->ptr);
96  free(array);
97 }
RZ_API void Ht_() free(HtName_(Ht) *ht)
Definition: ht_inc.c:130

References free(), and basefind_addresses_t::ptr.

Referenced by basefind_create_array_of_addresses(), and rz_basefind().

◆ basefind_array_has()

static bool basefind_array_has ( const BaseFindArray array,
ut64  value 
)
static

Definition at line 99 of file basefind.c.

99  {
100  // half-interval search should be better here.
101  for (ut32 i = 0; i < array->size; ++i) {
102  if (array->ptr[i] == value) {
103  return true;
104  }
105  }
106  return false;
107 }
lzma_index ** i
Definition: index.h:629
static int value
Definition: cmd_api.c:93
uint32_t ut32

References i, basefind_addresses_t::ptr, basefind_addresses_t::size, and value.

Referenced by basefind_pointer_map_iter().

◆ basefind_create_array_of_addresses()

static BaseFindArray* basefind_create_array_of_addresses ( RzCore core,
ut32  min_string_len 
)
static

Definition at line 109 of file basefind.c.

109  {
110  RzList *strings = NULL;
111  BaseFindArray *array = NULL;
112  RzBinFile *alloc = NULL;
113  RzBinFile *current = rz_bin_cur(core->bin);
114  if (!current) {
115  current = alloc = basefind_new_bin_file(core);
116  if (!current) {
117  return NULL;
118  }
119  }
120 
121  // if this list is sorted we can improve speed via half-interval search
122  strings = rz_bin_file_strings(current, min_string_len, true);
123  if (!strings || rz_list_empty(strings)) {
124  RZ_LOG_ERROR("basefind: cannot find strings in binary with a minimum size of %u.\n", min_string_len);
126  return NULL;
127  }
128 
129  array = RZ_NEW0(BaseFindArray);
130  if (!array) {
131  RZ_LOG_ERROR("basefind: cannot allocate BaseFindArray.\n");
132  goto error;
133  }
134 
135  array->size = rz_list_length(strings);
136  array->ptr = RZ_NEWS0(ut64, array->size);
137  if (!array->ptr) {
138  RZ_LOG_ERROR("basefind: cannot allocate array of addresses.\n");
139  basefind_array_free(array);
140  array = NULL;
141  goto error;
142  }
143 
144  ut32 i = 0;
145  RzListIter *iter;
146  RzBinString *string;
147  rz_list_foreach (strings, iter, string) {
148  RZ_LOG_VERBOSE("basefind: 0x%016" PFMT64x " '%s'\n", string->paddr, string->string);
149  array->ptr[i] = string->paddr;
150  i++;
151  }
152  RZ_LOG_INFO("basefind: located %u strings\n", array->size);
153 
154 error:
156  if (alloc) {
157  rz_buf_free(alloc->buf);
158  free(alloc->file);
159  free(alloc);
160  }
161  return array;
162 }
static void basefind_array_free(BaseFindArray *array)
Definition: basefind.c:91
static RzBinFile * basefind_new_bin_file(RzCore *core)
Definition: basefind.c:60
RZ_API RZ_OWN RzList * rz_bin_file_strings(RZ_NONNULL RzBinFile *bf, size_t min_length, bool raw_strings)
Generates a RzList struct containing RzBinString from a given RzBinFile.
Definition: bfile_string.c:325
RZ_API RzBinFile * rz_bin_cur(RzBin *bin)
Definition: bin.c:895
#define NULL
Definition: cris-opc.c:27
checking print the parsed form of the magic use in n conjunction with m to debug a new magic file n before installing it n output MIME type strings(--mime-type and\n" " --mime-encoding)\n") OPT('s'
RZ_API ut32 rz_list_length(RZ_NONNULL const RzList *list)
Returns the length of the list.
Definition: list.c:109
RZ_API void rz_list_free(RZ_NONNULL RzList *list)
Empties the list and frees the list pointer.
Definition: list.c:137
RZ_API void rz_buf_free(RzBuffer *b)
Free all internal data hold by the buffer and the buffer.
Definition: buf.c:1253
#define RZ_LOG_VERBOSE(fmtstr,...)
Definition: rz_log.h:52
#define RZ_LOG_INFO(fmtstr,...)
Definition: rz_log.h:54
#define RZ_LOG_ERROR(fmtstr,...)
Definition: rz_log.h:58
#define RZ_NEW0(x)
Definition: rz_types.h:284
#define RZ_NEWS0(x, y)
Definition: rz_types.h:282
#define PFMT64x
Definition: rz_types.h:393
XX curplugin == o->plugin.
Definition: rz_bin.h:298
char * file
Definition: rz_bin.h:299
RzBuffer * buf
Definition: rz_bin.h:303
char * string
Definition: rz_bin.h:752
RzBin * bin
Definition: rz_core.h:298
void error(const char *msg)
Definition: untgz.c:593
ut64(WINAPI *w32_GetEnabledXStateFeatures)()

References basefind_array_free(), basefind_new_bin_file(), rz_core_t::bin, rz_bin_file_t::buf, error(), rz_bin_file_t::file, free(), i, NULL, rz_bin_string_t::paddr, PFMT64x, basefind_addresses_t::ptr, rz_bin_cur(), rz_bin_file_strings(), rz_buf_free(), rz_list_free(), rz_list_length(), RZ_LOG_ERROR, RZ_LOG_INFO, RZ_LOG_VERBOSE, RZ_NEW0, RZ_NEWS0, basefind_addresses_t::size, rz_bin_string_t::string, strings(), and ut64().

Referenced by rz_basefind().

◆ basefind_create_pointer_map()

static HtUU* basefind_create_pointer_map ( RzCore core,
ut32  pointer_size 
)
static

Definition at line 164 of file basefind.c.

164  {
165  rz_return_val_if_fail(pointer_size == sizeof(ut32) || pointer_size == sizeof(ut64), NULL);
166 
167  HtUU *map = ht_uu_new0();
168  if (!map) {
169  RZ_LOG_ERROR("basefind: cannot allocate hashmap for pointer.\n");
170  return NULL;
171  }
172 
173  ut8 buffer[sizeof(ut64)];
174  ut64 io_size = rz_io_size(core->io);
175  ut64 address = 0;
176  bool big_endian = rz_config_get_b(core->config, "cfg.bigendian");
177 
178  for (ut64 pos = 0; pos < io_size; pos += pointer_size) {
179  rz_io_pread_at(core->io, pos, buffer, pointer_size);
180  address = pointer_size == sizeof(ut64) ? rz_read_ble64(buffer, big_endian) : rz_read_ble32(buffer, big_endian);
181  ut64 value = ht_uu_find(map, address, NULL) + 1;
182  ht_uu_insert(map, address, value);
183  }
184  RZ_LOG_INFO("basefind: located %u pointers\n", map->count);
185 
186  return map;
187 }
RZ_API bool rz_config_get_b(RzConfig *cfg, RZ_NONNULL const char *name)
Definition: config.c:142
size_t map(int syms, int left, int len)
Definition: enough.c:237
uint8_t ut8
Definition: lh5801.h:11
#define rz_return_val_if_fail(expr, val)
Definition: rz_assert.h:108
static ut64 rz_read_ble64(const void *src, bool big_endian)
Definition: rz_endian.h:501
static ut32 rz_read_ble32(const void *src, bool big_endian)
Definition: rz_endian.h:497
RZ_API ut64 rz_io_size(RzIO *io)
Definition: io.c:399
RZ_API int rz_io_pread_at(RzIO *io, ut64 paddr, ut8 *buf, int len)
Definition: io.c:269
Definition: buffer.h:15
RzIO * io
Definition: rz_core.h:313
RzConfig * config
Definition: rz_core.h:300
int pos
Definition: main.c:11

References rz_core_t::config, rz_core_t::io, map(), NULL, pos, rz_config_get_b(), rz_io_pread_at(), rz_io_size(), RZ_LOG_ERROR, RZ_LOG_INFO, rz_read_ble32(), rz_read_ble64(), rz_return_val_if_fail, ut64(), and value.

Referenced by rz_basefind().

◆ basefind_new_bin_file()

static RzBinFile* basefind_new_bin_file ( RzCore core)
static

Definition at line 60 of file basefind.c.

60  {
61  // Copied from cbin.c -> rz_core_bin_whole_strings_print
62  // TODO: manually creating an RzBinFile like this is a hack and abuse of RzBin API
63  // If we don't want to use an RzBinFile for searching strings, the raw strings search
64  // should be refactored out of bin.
65  RzIODesc *desc = rz_io_desc_get(core->io, core->file->fd);
66  if (!desc) {
67  RZ_LOG_ERROR("basefind: cannot get RzIODesc from core.\n");
68  return NULL;
69  }
70 
72  if (!bf) {
73  RZ_LOG_ERROR("basefind: cannot allocate RzBinFile structure.\n");
74  return NULL;
75  }
76 
77  bf->file = strdup(desc->name);
78  bf->size = rz_io_desc_size(desc);
79  if (bf->size == UT64_MAX) {
80  RZ_LOG_ERROR("basefind: filesize exeeds memory size (UT64_MAX).\n");
81  free(bf->file);
82  free(bf);
83  return NULL;
84  }
85 
86  bf->buf = rz_buf_new_with_io_fd(&core->bin->iob, core->file->fd);
87  bf->rbin = core->bin;
88  return bf;
89 }
const char * desc
Definition: bin_vsf.c:19
return strdup("=SP r13\n" "=LR r14\n" "=PC r15\n" "=A0 r0\n" "=A1 r1\n" "=A2 r2\n" "=A3 r3\n" "=ZF zf\n" "=SF nf\n" "=OF vf\n" "=CF cf\n" "=SN or0\n" "gpr lr .32 56 0\n" "gpr pc .32 60 0\n" "gpr cpsr .32 64 0 ____tfiae_________________qvczn\n" "gpr or0 .32 68 0\n" "gpr tf .1 64.5 0 thumb\n" "gpr ef .1 64.9 0 endian\n" "gpr jf .1 64.24 0 java\n" "gpr qf .1 64.27 0 sticky_overflow\n" "gpr vf .1 64.28 0 overflow\n" "gpr cf .1 64.29 0 carry\n" "gpr zf .1 64.30 0 zero\n" "gpr nf .1 64.31 0 negative\n" "gpr itc .4 64.10 0 if_then_count\n" "gpr gef .4 64.16 0 great_or_equal\n" "gpr r0 .32 0 0\n" "gpr r1 .32 4 0\n" "gpr r2 .32 8 0\n" "gpr r3 .32 12 0\n" "gpr r4 .32 16 0\n" "gpr r5 .32 20 0\n" "gpr r6 .32 24 0\n" "gpr r7 .32 28 0\n" "gpr r8 .32 32 0\n" "gpr r9 .32 36 0\n" "gpr r10 .32 40 0\n" "gpr r11 .32 44 0\n" "gpr r12 .32 48 0\n" "gpr r13 .32 52 0\n" "gpr r14 .32 56 0\n" "gpr r15 .32 60 0\n" "gpr r16 .32 64 0\n" "gpr r17 .32 68 0\n")
RZ_API RZ_OWN RzBuffer * rz_buf_new_with_io_fd(RZ_NONNULL void *iob, int fd)
Creates a new buffer wrapping a file descriptor accessed through RzIOBind.
Definition: buf.c:490
RZ_API ut64 rz_io_desc_size(RzIODesc *desc)
Definition: io_desc.c:224
RZ_API RzIODesc * rz_io_desc_get(RzIO *io, int fd)
Definition: io_desc.c:73
#define UT64_MAX
Definition: rz_types_base.h:86
struct rz_bin_t * rbin
Definition: rz_bin.h:316
RzIOBind iob
Definition: rz_bin.h:347
RzCoreFile * file
Definition: rz_core.h:314

References rz_core_t::bin, rz_bin_file_t::buf, desc, rz_core_file_t::fd, rz_bin_file_t::file, rz_core_t::file, free(), rz_core_t::io, rz_bin_t::iob, NULL, rz_bin_file_t::rbin, rz_buf_new_with_io_fd(), rz_io_desc_get(), rz_io_desc_size(), RZ_LOG_ERROR, RZ_NEW0, rz_bin_file_t::size, strdup(), and UT64_MAX.

Referenced by basefind_create_array_of_addresses().

◆ basefind_pointer_map_iter()

static bool basefind_pointer_map_iter ( BaseFindData bfd,
const ut64  address,
const ut64  hits 
)
static

Definition at line 189 of file basefind.c.

189  {
190  if (rz_cons_is_breaked()) {
191  return false;
192  }
193  if (address < bfd->start || address >= bfd->end) {
194  return true;
195  }
196  ut64 offset = address - bfd->start;
197  if (basefind_array_has(bfd->array, offset)) {
198  bfd->score += hits;
199  }
200  return true;
201 }
static bool basefind_array_has(const BaseFindArray *array, ut64 value)
Definition: basefind.c:99
RZ_API bool rz_cons_is_breaked(void)
Definition: cons.c:373
static static sync static getppid static getegid const char static filename char static len const char char static bufsiz static mask static vfork const void static prot static getpgrp const char static swapflags static arg static fd static protocol static who struct sockaddr static addrlen static backlog struct timeval struct timezone static tz const struct iovec static count static mode const void const struct sockaddr static tolen const char static pathname void static offset struct stat static buf void long static basep static whence static length const void static len static semflg const void static shmflg const struct timespec struct timespec static rem const char static group const void start
Definition: sflib.h:133
voidpf uLong offset
Definition: ioapi.h:144
Definition: mybfd.h:4212

References basefind_array_has(), rz_cons_is_breaked(), start, and ut64().

Referenced by basefind_thread_runner().

◆ basefind_score_compare()

static int basefind_score_compare ( const RzBaseFindScore a,
const RzBaseFindScore b 
)
static

Definition at line 203 of file basefind.c.

203  {
204  if (b->score == a->score) {
205  if (b->candidate == a->candidate) {
206  return 0;
207  } else if (b->candidate < a->candidate) {
208  return -1;
209  }
210  return 1;
211  } else if (b->score < a->score) {
212  return -1;
213  }
214  return 1;
215 }
#define b(i)
Definition: sha256.c:42
#define a(i)
Definition: sha256.c:41

References a, and b.

Referenced by rz_basefind().

◆ basefind_set_thread_info()

static void basefind_set_thread_info ( BaseFindThreadData bftd,
RzBaseFindThreadInfo th_info,
ut32  thread_idx 
)
static

Definition at line 262 of file basefind.c.

262  {
263  ut32 percentage = ((bftd->current - bftd->base_start) * 100) / (bftd->base_end - bftd->base_start);
264  if (percentage > 100) {
265  percentage = 100;
266  }
267 
268  th_info->thread_idx = thread_idx;
269  th_info->begin_address = bftd->base_start;
270  th_info->current_address = bftd->current;
271  th_info->end_address = bftd->base_end;
272  th_info->percentage = percentage;
273 }
ut64 current_address
Thread related search address (current).
Definition: rz_basefind.h:28
ut32 percentage
Progress made by the search thread.
Definition: rz_basefind.h:30
ut64 begin_address
Thread related search address (start).
Definition: rz_basefind.h:27
ut32 thread_idx
Sesarch thread number.
Definition: rz_basefind.h:26
ut64 end_address
Thread related search address (end).
Definition: rz_basefind.h:29
double percentage
Definition: main.c:10

References basefind_thread_data_t::base_end, basefind_thread_data_t::base_start, rz_basefind_info_t::begin_address, basefind_thread_data_t::current, rz_basefind_info_t::current_address, rz_basefind_info_t::end_address, rz_basefind_info_t::percentage, percentage, and rz_basefind_info_t::thread_idx.

Referenced by basefind_thread_ui(), and rz_basefind().

◆ basefind_stop_all_search_threads()

static void basefind_stop_all_search_threads ( RzThreadPool pool)
static

Definition at line 48 of file basefind.c.

48  {
49  size_t pool_size = rz_th_pool_size(pool);
50  for (ut32 i = 0; i < pool_size; ++i) {
51  RzThread *th = rz_th_pool_get_thread(pool, i);
52  if (!th) {
53  continue;
54  }
56  rz_atomic_bool_set(bftd->loop, false);
57  }
58 }
RZ_API RZ_OWN void * rz_th_get_user(RZ_NONNULL RzThread *th)
Returns user pointer of thread.
Definition: thread.c:263
RzAtomicBool * loop
Definition: basefind.c:38
Definition: thread.h:84
RZ_API RZ_BORROW RzThread * rz_th_pool_get_thread(RZ_NONNULL RzThreadPool *pool, size_t index)
Returns the n-th thread in the thread pool.
Definition: thread_pool.c:158
RZ_API size_t rz_th_pool_size(RZ_NONNULL RzThreadPool *pool)
Returns the thread pool size.
Definition: thread_pool.c:189
RZ_API void rz_atomic_bool_set(RZ_NONNULL RzAtomicBool *tbool, bool value)
Sets the value int the RzAtomicBool structure.
Definition: thread_types.c:68

References i, basefind_thread_data_t::loop, rz_atomic_bool_set(), rz_th_get_user(), rz_th_pool_get_thread(), and rz_th_pool_size().

Referenced by basefind_thread_ui(), and rz_basefind().

◆ basefind_thread_runner()

static void* basefind_thread_runner ( BaseFindThreadData bftd)
static

Definition at line 217 of file basefind.c.

217  {
218  RzAtomicBool *loop = bftd->loop;
219  RzBaseFindScore *pair = NULL;
221  ut64 base;
222 
223  bfd.array = bftd->array;
224  for (base = bftd->base_start; base < bftd->base_end; base += bftd->alignment) {
225  if (!rz_atomic_bool_get(loop)) {
226  break;
227  }
228  bftd->current = base;
229  bfd.score = 0;
230  bfd.start = base;
231  bfd.end = base + bftd->io_size;
232  ht_uu_foreach(bftd->pointers, (HtUUForeachCallback)basefind_pointer_map_iter, &bfd);
233 
234  if (bfd.score < bftd->score_min) {
235  // ignore any score below than score_min
236  continue;
237  }
238 
239  pair = RZ_NEW0(RzBaseFindScore);
240  if (!pair) {
241  RZ_LOG_ERROR("basefind: cannot allocate RzBaseFindScore.\n");
242  break;
243  }
244  pair->score = bfd.score;
245  pair->candidate = base;
246 
247  rz_th_lock_enter(bftd->lock);
248  if (!rz_list_append(bftd->scores, pair)) {
249  rz_th_lock_leave(bftd->lock);
250  free(pair);
251  RZ_LOG_ERROR("basefind: cannot append new score to the scores list.\n");
252  break;
253  }
254  RZ_LOG_DEBUG("basefind: possible candidate at 0x%016" PFMT64x " with score of %u\n", base, bfd.score);
255  rz_th_lock_leave(bftd->lock);
256  }
257  bftd->current = base;
258 
259  return NULL;
260 }
static bool basefind_pointer_map_iter(BaseFindData *bfd, const ut64 address, const ut64 hits)
Definition: basefind.c:189
RZ_API RZ_BORROW RzListIter * rz_list_append(RZ_NONNULL RzList *list, void *data)
Appends at the end of the list a new element.
Definition: list.c:288
struct bfd bfd
Definition: mybfd.h:86
#define RZ_LOG_DEBUG(fmtstr,...)
Definition: rz_log.h:49
BaseFindArray * array
Definition: basefind.c:37
RzThreadLock * lock
Definition: basefind.c:34
ut64 candidate
Candidate physical base address.
Definition: rz_basefind.h:20
ut32 score
Score of the candidate address.
Definition: rz_basefind.h:21
uv_loop_t * loop
Definition: main.c:7
RZ_API void rz_th_lock_leave(RZ_NONNULL RzThreadLock *thl)
Releases a RzThreadLock structure.
Definition: thread_lock.c:75
RZ_API void rz_th_lock_enter(RZ_NONNULL RzThreadLock *thl)
Acquires a RzThreadLock structure.
Definition: thread_lock.c:45
RZ_API bool rz_atomic_bool_get(RZ_NONNULL RzAtomicBool *tbool)
Gets the current value hold by the RzAtomicBool structure.
Definition: thread_types.c:54

References basefind_thread_data_t::alignment, basefind_thread_data_t::array, basefind_thread_data_t::base_start, basefind_pointer_map_iter(), rz_basefind_t::candidate, basefind_thread_data_t::current, free(), basefind_thread_data_t::io_size, basefind_thread_data_t::lock, basefind_thread_data_t::loop, loop, NULL, PFMT64x, basefind_thread_data_t::pointers, rz_atomic_bool_get(), rz_list_append(), RZ_LOG_DEBUG, RZ_LOG_ERROR, RZ_NEW0, rz_th_lock_enter(), rz_th_lock_leave(), rz_basefind_t::score, basefind_thread_data_t::score_min, basefind_thread_data_t::scores, and ut64().

Referenced by create_thread_interval().

◆ basefind_thread_ui()

static void* basefind_thread_ui ( BaseFindUIInfo ui_info)
static

Definition at line 277 of file basefind.c.

277  {
278  RzThreadPool *pool = ui_info->pool;
279  RzAtomicBool *loop = ui_info->loop;
280  ut32 pool_size = rz_th_pool_size(pool);
281  RzBaseFindThreadInfoCb callback = ui_info->callback;
282  void *user = ui_info->user;
283  RzBaseFindThreadInfo th_info;
284  th_info.n_threads = pool_size;
285 
286  do {
287  for (ut32 i = 0; i < pool_size; ++i) {
288  RzThread *th = rz_th_pool_get_thread(pool, i);
289  if (!th) {
290  continue;
291  }
293  basefind_set_thread_info(bftd, &th_info, i);
294  if (!callback(&th_info, user)) {
296  goto end;
297  }
298  }
299  rz_sys_usleep(100000);
300  } while (rz_atomic_bool_get(loop));
301 end:
302  return NULL;
303 }
static void basefind_set_thread_info(BaseFindThreadData *bftd, RzBaseFindThreadInfo *th_info, ut32 thread_idx)
Definition: basefind.c:262
static void basefind_stop_all_search_threads(RzThreadPool *pool)
Definition: basefind.c:48
bool(* RzBaseFindThreadInfoCb)(const RzBaseFindThreadInfo *th_info, void *user)
Definition: rz_basefind.h:34
RZ_API int rz_sys_usleep(int usecs)
Sleep for usecs microseconds.
Definition: sys.c:317
RzBaseFindThreadInfoCb callback
Definition: basefind.c:45
RzAtomicBool * loop
Definition: basefind.c:42
RzThreadPool * pool
Definition: basefind.c:43
ut32 n_threads
Total number of search threads.
Definition: rz_basefind.h:25
RzThreadPool is a structure which handles n-threads threads.
Definition: thread_pool.c:12

References basefind_set_thread_info(), basefind_stop_all_search_threads(), basefind_ui_info_t::callback, test_evm::end, i, basefind_ui_info_t::loop, loop, rz_basefind_info_t::n_threads, NULL, basefind_ui_info_t::pool, rz_atomic_bool_get(), rz_sys_usleep(), rz_th_get_user(), rz_th_pool_get_thread(), rz_th_pool_size(), and basefind_ui_info_t::user.

Referenced by rz_basefind().

◆ create_thread_interval()

static bool create_thread_interval ( RzThreadPool pool,
BaseFindThreadData bfd 
)
inlinestatic

Definition at line 305 of file basefind.c.

305  {
307  if (!thread) {
308  RZ_LOG_ERROR("basefind: cannot allocate RzThread\n");
309  return false;
310  } else if (!rz_th_pool_add_thread(pool, thread)) {
311  RZ_LOG_ERROR("basefind: cannot add thread to pool\n");
312  rz_th_free(thread);
313  return false;
314  }
315  return true;
316 }
static void * basefind_thread_runner(BaseFindThreadData *bftd)
Definition: basefind.c:217
RZ_API void rz_th_free(RZ_NULLABLE RzThread *th)
Frees a RzThread structure.
Definition: thread.c:246
RZ_API RZ_OWN RzThread * rz_th_new(RZ_NONNULL RzThreadFunction function, RZ_NULLABLE void *user)
Creates and starts a new thread.
Definition: thread.c:198
void *(* RzThreadFunction)(void *user)
Definition: rz_th.h:28
RZ_API bool rz_th_pool_add_thread(RZ_NONNULL RzThreadPool *pool, RZ_NONNULL RzThread *thread)
Adds a thread to the thread pool.
Definition: thread_pool.c:138

References basefind_thread_runner(), RZ_LOG_ERROR, rz_th_free(), rz_th_new(), and rz_th_pool_add_thread().

Referenced by rz_basefind().

◆ rz_basefind()

RZ_API RZ_OWN RzList* rz_basefind ( RZ_NONNULL RzCore core,
RZ_NONNULL RzBaseFindOpt options 
)

Calculates a list of possible base addresses candidates using the strings position.

The code finds all the strings in memory with a minimum acceptable size (via opt.min_string_len) and calculates all possible words 32 or 64 bit large sizes (endianness via cfg.bigendian) in the given binary. These addresses are then compared with the strings and a variable base address which is increased over time by opt.alignment.

The scores are added to the result list with the associated base address if their score are higher than opt.min_score, otherwise they are ignored.

It is possible via opt.callback to set a callback function that can stop the search (when returning false) or display the thread statuses (the callback will be called N-times for N spawned threads.

Parameters
coreRzCore struct to use.
optionsPointer to the RzBaseFindOpt structure.

Definition at line 336 of file basefind.c.

336  {
338  RzList *scores = NULL;
339  BaseFindArray *array = NULL;
340  HtUU *pointers = NULL;
341  size_t pool_size = 1;
342  RzThreadPool *pool = NULL;
344  RzThread *user_thread = NULL;
345  BaseFindUIInfo ui_info = { 0 };
346 
347  ut64 base_start = options->start_address;
348  ut64 base_end = options->end_address;
349  ut64 alignment = options->alignment;
350 
351  if (options->pointer_size != 32 && options->pointer_size != 64) {
352  RZ_LOG_ERROR("basefind: supported pointer sizes are 32 and 64 bits.\n");
353  return NULL;
354  } else if (!core->file) {
355  RZ_LOG_ERROR("basefind: the file was not opened via RzCore.\n");
356  return NULL;
357  } else if (base_start >= base_end) {
358  RZ_LOG_ERROR("basefind: start address is greater or equal to end address.\n");
359  return NULL;
360  } else if (alignment < 1) {
361  RZ_LOG_ERROR("basefind: the alignment is set to zero bytes.\n");
362  return NULL;
363  } else if (options->min_score < 1) {
364  RZ_LOG_ERROR("basefind: the minimum score is set to zero.\n");
365  return NULL;
366  } else if (options->min_string_len < 1) {
367  RZ_LOG_ERROR("basefind: the minimum string length is set to zero.\n");
368  return NULL;
369  }
370 
371  if (alignment < RZ_BASEFIND_BASE_ALIGNMENT) {
372  RZ_LOG_WARN("basefind: the alignment is less than 0x%x bytes, "
373  "which may result in a very slow search.\n",
375  }
376 
377  array = basefind_create_array_of_addresses(core, options->min_string_len);
378  if (!array) {
379  goto rz_basefind_end;
380  }
381 
382  pointers = basefind_create_pointer_map(core, options->pointer_size / 8);
383  if (!pointers) {
384  goto rz_basefind_end;
385  }
386 
387  scores = rz_list_newf((RzListFree)free);
388  if (!scores) {
389  RZ_LOG_ERROR("basefind: cannot allocate new scores list.\n");
390  goto rz_basefind_end;
391  }
392 
393  pool = rz_th_pool_new(options->max_threads);
394  if (!pool) {
395  RZ_LOG_ERROR("basefind: cannot allocate thread pool.\n");
396  goto rz_basefind_end;
397  }
398  pool_size = rz_th_pool_size(pool);
399 
400  lock = rz_th_lock_new(false);
401  if (!lock) {
402  RZ_LOG_ERROR("basefind: cannot allocate thread lock.\n");
403  goto rz_basefind_end;
404  }
405 
406  RZ_LOG_VERBOSE("basefind: using %u threads\n", (ut32)pool_size);
407 
408  ut64 io_size = rz_io_size(core->io);
409  ut64 sector_size = (((base_end - base_start) + pool_size - 1) / pool_size);
410  for (size_t i = 0; i < pool_size; ++i) {
412  if (!bftd) {
413  RZ_LOG_ERROR("basefind: cannot allocate BaseFindThreadData.\n");
415  goto rz_basefind_end;
416  }
417  bftd->alignment = alignment;
418  bftd->base_start = base_start + (sector_size * i);
419  bftd->current = bftd->base_start;
420  bftd->base_end = bftd->base_start + sector_size;
421  bftd->score_min = options->min_score;
422  bftd->io_size = io_size;
423  bftd->lock = lock;
424  bftd->scores = scores;
425  bftd->pointers = pointers;
426  bftd->array = array;
427  bftd->loop = rz_atomic_bool_new(true);
428  if (!create_thread_interval(pool, bftd)) {
429  free(bftd);
431  goto rz_basefind_end;
432  }
433  }
434 
435  if (options->callback) {
436  ui_info.pool = pool;
437  ui_info.user = options->user;
438  ui_info.callback = options->callback;
439  ui_info.loop = rz_atomic_bool_new(true);
440  user_thread = rz_th_new((RzThreadFunction)basefind_thread_ui, &ui_info);
441  if (!user_thread) {
443  goto rz_basefind_end;
444  }
445  }
446 
447  // wait the pool to finish
448  rz_th_pool_wait(pool);
449 
450  if (options->callback) {
451  rz_atomic_bool_set(ui_info.loop, false);
452  rz_th_wait(user_thread);
453  rz_th_free(user_thread);
454  rz_atomic_bool_free(ui_info.loop);
455 
456  RzBaseFindThreadInfo th_info;
457  th_info.n_threads = pool_size;
458  for (ut32 i = 0; i < pool_size; ++i) {
459  RzThread *th = rz_th_pool_get_thread(pool, i);
460  if (!th) {
461  continue;
462  }
464  basefind_set_thread_info(bftd, &th_info, i);
465  options->callback(&th_info, options->user);
466  }
467  }
468 
470 
471 rz_basefind_end:
472  if (pool) {
473  for (ut32 i = 0; i < pool_size; ++i) {
474  RzThread *th = rz_th_pool_get_thread(pool, i);
475  if (!th) {
476  continue;
477  }
479  rz_atomic_bool_free(bftd->loop);
480  free(bftd);
481  }
482  rz_th_pool_free(pool);
483  }
485  basefind_array_free(array);
486  ht_uu_free(pointers);
487  return scores;
488 }
static HtUU * basefind_create_pointer_map(RzCore *core, ut32 pointer_size)
Definition: basefind.c:164
static int basefind_score_compare(const RzBaseFindScore *a, const RzBaseFindScore *b)
Definition: basefind.c:203
static void * basefind_thread_ui(BaseFindUIInfo *ui_info)
Definition: basefind.c:277
static BaseFindArray * basefind_create_array_of_addresses(RzCore *core, ut32 min_string_len)
Definition: basefind.c:109
static bool create_thread_interval(RzThreadPool *pool, BaseFindThreadData *bfd)
Definition: basefind.c:305
RZ_API RZ_OWN RzList * rz_list_newf(RzListFree f)
Returns a new initialized RzList pointer and sets the free method.
Definition: list.c:248
RZ_API void rz_list_sort(RZ_NONNULL RzList *list, RZ_NONNULL RzListComparator cmp)
Sorts via merge sort or via insertion sort a list.
Definition: list.c:743
RZ_API bool rz_th_wait(RZ_NONNULL RzThread *th)
Awaits indefinetely for a thread to join.
Definition: thread.c:231
static const char struct stat static buf struct stat static buf static vhangup int options
Definition: sflib.h:145
#define RZ_BASEFIND_BASE_ALIGNMENT
Definition: rz_basefind.h:16
void(* RzListFree)(void *ptr)
Definition: rz_list.h:11
int(* RzListComparator)(const void *value, const void *list_data)
Definition: rz_list.h:33
#define RZ_LOG_WARN(fmtstr,...)
Definition: rz_log.h:56
#define RZ_NEW(x)
Definition: rz_types.h:285
RZ_API void rz_th_lock_free(RZ_NULLABLE RzThreadLock *thl)
Frees a RzThreadLock structure.
Definition: thread_lock.c:89
RZ_API RZ_OWN RzThreadLock * rz_th_lock_new(bool recursive)
Allocates and initialize a RzThreadLock structure.
Definition: thread_lock.c:14
RZ_API void rz_th_pool_free(RZ_NULLABLE RzThreadPool *pool)
Kills (and frees) the threads and frees the RzThreadPool struct.
Definition: thread_pool.c:117
RZ_API bool rz_th_pool_wait(RZ_NONNULL RzThreadPool *pool)
Waits the end of all the threads in the thread pool.
Definition: thread_pool.c:170
RZ_API RZ_OWN RzThreadPool * rz_th_pool_new(size_t max_threads)
returns a new RzThreadPool structure with a pool of thread
Definition: thread_pool.c:96
RZ_API RZ_OWN RzAtomicBool * rz_atomic_bool_new(bool value)
Initialize a thread safe bool type container.
Definition: thread_types.c:24
RZ_API void rz_atomic_bool_free(RZ_NULLABLE RzAtomicBool *tbool)
Frees a RzAtomicBool structure.
Definition: thread_types.c:39
static void lock(volatile int *lk)
Definition: malloc.c:61

References basefind_thread_data_t::alignment, basefind_thread_data_t::array, basefind_thread_data_t::base_end, basefind_thread_data_t::base_start, basefind_array_free(), basefind_create_array_of_addresses(), basefind_create_pointer_map(), basefind_score_compare(), basefind_set_thread_info(), basefind_stop_all_search_threads(), basefind_thread_ui(), basefind_ui_info_t::callback, create_thread_interval(), basefind_thread_data_t::current, free(), i, basefind_thread_data_t::io_size, basefind_thread_data_t::lock, lock(), basefind_thread_data_t::loop, basefind_ui_info_t::loop, rz_basefind_info_t::n_threads, NULL, options, basefind_thread_data_t::pointers, basefind_ui_info_t::pool, rz_atomic_bool_free(), rz_atomic_bool_new(), rz_atomic_bool_set(), RZ_BASEFIND_BASE_ALIGNMENT, rz_io_size(), rz_list_newf(), rz_list_sort(), RZ_LOG_ERROR, RZ_LOG_VERBOSE, RZ_LOG_WARN, RZ_NEW, rz_return_val_if_fail, rz_th_free(), rz_th_get_user(), rz_th_lock_free(), rz_th_lock_new(), rz_th_new(), rz_th_pool_free(), rz_th_pool_get_thread(), rz_th_pool_new(), rz_th_pool_size(), rz_th_pool_wait(), rz_th_wait(), basefind_thread_data_t::score_min, basefind_thread_data_t::scores, basefind_ui_info_t::user, and ut64().

Referenced by rz_core_bin_basefind_print().