Rizin
unix-like reverse engineering framework and cli tools
golang.c
Go to the documentation of this file.
1 // SPDX-FileCopyrightText: 2022 deroad <wargio@libero.it>
2 // SPDX-License-Identifier: LGPL-3.0-only
3 
4 #include <rz_core.h>
5 
6 #define GO_MAX_STRING_SIZE 0x4000
7 
8 #define GO_1_2 (12)
9 #define GO_1_16 (116)
10 #define GO_1_18 (118)
11 
12 #define IS_GOPCLNTAB_1_2_LE(x) (x[0] == 0xfb && x[1] == 0xff && x[2] == 0xff && x[3] == 0xff)
13 #define IS_GOPCLNTAB_1_2_BE(x) (x[3] == 0xfb && x[2] == 0xff && x[1] == 0xff && x[0] == 0xff)
14 #define IS_GOPCLNTAB_1_16_LE(x) (x[0] == 0xfa && x[1] == 0xff && x[2] == 0xff && x[3] == 0xff)
15 #define IS_GOPCLNTAB_1_16_BE(x) (x[3] == 0xfa && x[2] == 0xff && x[1] == 0xff && x[0] == 0xff)
16 #define IS_GOPCLNTAB_1_18_LE(x) (x[0] == 0xf0 && x[1] == 0xff && x[2] == 0xff && x[3] == 0xff)
17 #define IS_GOPCLNTAB_1_18_BE(x) (x[3] == 0xf0 && x[2] == 0xff && x[1] == 0xff && x[0] == 0xff)
18 
19 typedef struct go_pc_line_table_t {
20  RzIO *io;
24  bool big_endian;
26  // quantum is the min instruction size for the program counter.
27  // i386: 1, amd64: 1, wasm: 1, s390x: 2, arm: 4, arm64: 4, mips: 4, mips: 4, ppc: 4, riscv: 4
33  // data offsets
41 
42 typedef struct go_string_recover_t {
49 
50 typedef struct go_string_info_t {
55 
56 typedef struct go_asm_pattern_t {
57  const ut8 *pattern;
58  const ut8 *mask;
60  bool xrefs;
62 
63 typedef bool (*GoDecodeCb)(RzCore *core, GoStrInfo *info, ut64 pc, const ut8 *buffer, const ut32 size);
64 
65 typedef struct go_signature_t {
69 
71 
73  if (pclntab->version >= GO_1_18) {
74  return 4;
75  }
76  return pclntab->ptrsize;
77 }
78 
80  if (pclntab->ptrsize == 4) {
81  return rz_read_ble32(bytes, pclntab->big_endian);
82  }
83  return rz_read_ble64(bytes, pclntab->big_endian);
84 }
85 
86 ut64 go_offset(GoPcLnTab *pclntab, ut32 n_word) {
87  ut8 bytes[8];
88  ut64 location = pclntab->vaddr + 8 + (n_word * pclntab->ptrsize);
89  if (0 > rz_io_nread_at(pclntab->io, location, bytes, sizeof(bytes))) {
90  return UT64_MAX;
91  }
92  return go_uintptr(pclntab, bytes);
93 }
94 
95 ut64 go_data(GoPcLnTab *pclntab, ut32 n_word) {
96  ut64 offset = go_offset(pclntab, n_word);
97  if (offset == UT64_MAX) {
98  return UT64_MAX;
99  }
100  return pclntab->vaddr + offset;
101 }
102 
103 #define is_addr_outside(x) ((x) <= begin || (x) >= end)
104 static bool is_pclntab_valid(GoPcLnTab *pclntab) {
105  ut64 begin = pclntab->vaddr + 8;
106  ut64 end = pclntab->vaddr + pclntab->size;
107 
108  if (pclntab->version > GO_1_2) {
109  if (is_addr_outside(pclntab->funcnametab)) {
110  return false;
111  } else if (is_addr_outside(pclntab->cutab)) {
112  return false;
113  } else if (is_addr_outside(pclntab->pctab)) {
114  return false;
115  } else if (is_addr_outside(pclntab->funcdata)) {
116  return false;
117  }
118  }
119 
120  if (pclntab->version >= GO_1_18 && !pclntab->text_start) {
121  return false;
122  }
123 
124  if (is_addr_outside(pclntab->filetab)) {
125  return false;
126  } else if (is_addr_outside(pclntab->functab)) {
127  return false;
128  } else if (pclntab->functabsize >= (pclntab->size - 8)) {
129  return false;
130  }
131 
132  return true;
133 }
134 #undef is_addr_outside
135 
136 static void add_new_func_symbol(RzCore *core, const char *name, ut64 vaddr) {
137  RzBinFile *bf = rz_bin_cur(core->bin);
138  if (!bf || !bf->o || !bf->o->symbols) {
139  return;
140  }
141  ut64 paddr = rz_io_v2p(core->io, vaddr);
142  RzBinSymbol *symbol = rz_bin_symbol_new(name, paddr, vaddr);
143  if (!symbol) {
144  RZ_LOG_ERROR("Failed allocate new go symbol\n");
145  return;
146  }
147 
148  symbol->bind = RZ_BIN_BIND_GLOBAL_STR;
149  symbol->type = RZ_BIN_TYPE_FUNC_STR;
150  if (!rz_list_append(bf->o->symbols, symbol)) {
151  RZ_LOG_ERROR("Failed append new go symbol to symbols list\n");
152  rz_bin_symbol_free(symbol);
153  }
154 
155  if (!strcmp(name, "main.main")) {
156  rz_flag_set(core->flags, "main", vaddr, 1);
157  }
158 }
159 
161  rz_core_notify_done(core, "Found go 1.18 pclntab data.");
162  ut8 tmp8[8];
163  char name[256];
164  char *flag = NULL;
165  ut32 num_syms = 0;
166  ut64 func_ptr = 0, func_off = 0, name_ptr = 0, name_off = 0;
167 
168  pclntab->nfunctab = (ut32)go_offset(pclntab, 0);
169  pclntab->nfiletab = (ut32)go_offset(pclntab, 1);
170  pclntab->funcnametab = go_data(pclntab, 3);
171  pclntab->cutab = go_data(pclntab, 4);
172  pclntab->filetab = go_data(pclntab, 5);
173  pclntab->pctab = go_data(pclntab, 6);
174  pclntab->funcdata = go_data(pclntab, 7);
175  pclntab->functab = go_data(pclntab, 7);
176  pclntab->functabsize = ((pclntab->nfunctab * 2) + 1) * go_func_tab_field_size(pclntab);
177  pclntab->ptrsize = 4; // GO 1.18+ uses ut32 words.
178 
179  if (!is_pclntab_valid(pclntab)) {
180  rz_core_notify_error(core, "Invalid go 1.18 pclntab (invalid table).");
181  return 0;
182  }
183 
184  rz_flag_space_push(core->flags, RZ_FLAGS_FS_SYMBOLS);
185  for (ut32 i = 0, ptr = 0; i < pclntab->nfunctab; ++i, ptr += (pclntab->ptrsize * 2)) {
186  ut64 offset = pclntab->functab + ptr;
187 
188  // reads the value of the function pointer
189  if (0 > rz_io_nread_at(pclntab->io, offset, tmp8, sizeof(tmp8))) {
190  RZ_LOG_ERROR("Failed to read go function address at 0x%08" PFMT64x "\n", offset);
191  break;
192  }
193  func_ptr = pclntab->text_start + go_uintptr(pclntab, tmp8);
194 
195  // reads the value of the function data offset
196  if (0 > rz_io_nread_at(pclntab->io, offset + pclntab->ptrsize, tmp8, sizeof(tmp8))) {
197  RZ_LOG_ERROR("Failed to read go function data address at 0x%08" PFMT64x "\n", offset);
198  break;
199  }
200  func_off = go_uintptr(pclntab, tmp8);
201 
202  name_ptr = pclntab->functab + func_off + pclntab->ptrsize;
203  // reads the location of the function name within funcnametab
204  if (0 > rz_io_nread_at(pclntab->io, name_ptr, tmp8, sizeof(ut32))) {
205  RZ_LOG_ERROR("Failed to read go function name address at 0x%08" PFMT64x "\n", offset);
206  break;
207  }
208  name_off = pclntab->funcnametab + rz_read_ble32(tmp8, pclntab->big_endian);
209 
210  // ignore failures, we can always create a new name.
211  memset(name, 0, sizeof(name));
212  (void)rz_io_nread_at(pclntab->io, name_off, (ut8 *)name, sizeof(name));
213  name[sizeof(name) - 1] = 0;
214  RZ_LOG_INFO("Recovered symbol at 0x%08" PFMT64x " with name '%s'\n", func_ptr, name);
215  if (rz_str_len_utf8_ansi(name) > 0) {
216  // always add it before filtering the name.
217  add_new_func_symbol(core, name, func_ptr);
218  rz_name_filter(name, 0, true);
219  } else {
220  rz_strf(name, "fcn.pclntab.unknown.%08" PFMT64x, func_ptr);
221  add_new_func_symbol(core, name, func_ptr);
222  }
223 
224  flag = rz_str_newf("sym.go.%s", name);
225  rz_flag_set(core->flags, flag, func_ptr, 1);
226  free(flag);
227 
228  num_syms++;
229  }
230  rz_flag_space_pop(core->flags);
231 
232  return num_syms;
233 }
234 
236  rz_core_notify_done(core, "Found go 1.16 pclntab data.");
237  ut8 tmp8[8];
238  char name[256];
239  char *flag = NULL;
240  ut32 num_syms = 0;
241  ut64 func_ptr = 0, func_off = 0, name_ptr = 0, name_off = 0;
242 
243  pclntab->nfunctab = (ut32)go_offset(pclntab, 0);
244  pclntab->nfiletab = (ut32)go_offset(pclntab, 1);
245  pclntab->funcnametab = go_data(pclntab, 2);
246  pclntab->cutab = go_data(pclntab, 3);
247  pclntab->filetab = go_data(pclntab, 4);
248  pclntab->pctab = go_data(pclntab, 5);
249  pclntab->funcdata = go_data(pclntab, 6);
250  pclntab->functab = go_data(pclntab, 6);
251  pclntab->functabsize = ((pclntab->nfunctab * 2) + 1) * go_func_tab_field_size(pclntab);
252 
253  if (!is_pclntab_valid(pclntab)) {
254  rz_core_notify_error(core, "Invalid go 1.16 pclntab (invalid table).");
255  return 0;
256  }
257 
258  rz_flag_space_push(core->flags, RZ_FLAGS_FS_SYMBOLS);
259  for (ut32 i = 0, ptr = 0; i < pclntab->nfunctab; ++i, ptr += (pclntab->ptrsize * 2)) {
260  ut64 offset = pclntab->functab + ptr;
261 
262  // reads the value of the function pointer
263  if (0 > rz_io_nread_at(pclntab->io, offset, tmp8, sizeof(tmp8))) {
264  RZ_LOG_ERROR("Failed to read go function address at 0x%08" PFMT64x "\n", offset);
265  break;
266  }
267  func_ptr = go_uintptr(pclntab, tmp8);
268 
269  // reads the value of the function data offset
270  if (0 > rz_io_nread_at(pclntab->io, offset + pclntab->ptrsize, tmp8, sizeof(tmp8))) {
271  RZ_LOG_ERROR("Failed to read go function data address at 0x%08" PFMT64x "\n", offset);
272  break;
273  }
274  func_off = go_uintptr(pclntab, tmp8);
275 
276  name_ptr = pclntab->functab + func_off + pclntab->ptrsize;
277  // reads the location of the function name within funcnametab
278  if (0 > rz_io_nread_at(pclntab->io, name_ptr, tmp8, sizeof(ut32))) {
279  RZ_LOG_ERROR("Failed to read go function name address at 0x%08" PFMT64x "\n", offset);
280  break;
281  }
282 
283  name_off = pclntab->funcnametab + rz_read_ble32(tmp8, pclntab->big_endian);
284 
285  // ignore failures, we can always create a new name.
286  memset(name, 0, sizeof(name));
287  (void)rz_io_nread_at(pclntab->io, name_off, (ut8 *)name, sizeof(name));
288  name[sizeof(name) - 1] = 0;
289  RZ_LOG_INFO("Recovered symbol at 0x%08" PFMT64x " with name '%s'\n", func_ptr, name);
290 
291  if (rz_str_len_utf8_ansi(name) > 0) {
292  // always add it before filtering the name.
293  add_new_func_symbol(core, name, func_ptr);
294  rz_name_filter(name, 0, true);
295  } else {
296  rz_strf(name, "fcn.pclntab.unknown.%08" PFMT64x, func_ptr);
297  add_new_func_symbol(core, name, func_ptr);
298  }
299 
300  flag = rz_str_newf("sym.go.%s", name);
301  rz_flag_set(core->flags, flag, func_ptr, 1);
302  free(flag);
303 
304  num_syms++;
305  }
306  rz_flag_space_pop(core->flags);
307 
308  return num_syms;
309 }
310 
311 // Valid for golang 1.2 -> 1.15
313  rz_core_notify_done(core, "Found go 1.12 pclntab data.");
314  ut8 tmp8[8];
315  char name[256];
316  char *flag = NULL;
317  ut32 num_syms = 0;
318  ut64 func_ptr = 0, func_off = 0, name_ptr = 0, name_off = 0;
319 
320  if (0 > rz_io_nread_at(pclntab->io, pclntab->vaddr + 8, tmp8, sizeof(tmp8))) {
321  return 0;
322  }
323 
324  pclntab->nfunctab = (ut32)go_uintptr(pclntab, tmp8);
325  pclntab->functab = pclntab->vaddr + 8 + pclntab->ptrsize;
326  pclntab->functabsize = ((pclntab->nfunctab * 2) + 1) * go_func_tab_field_size(pclntab);
327 
328  if (0 > rz_io_nread_at(pclntab->io, pclntab->functab + pclntab->functabsize, tmp8, sizeof(ut32))) {
329  RZ_LOG_ERROR("Failed to read go functab at 0x%08" PFMT64x "\n", pclntab->functab);
330  return 0;
331  }
332 
333  pclntab->filetab = pclntab->vaddr + rz_read_ble32(tmp8, pclntab->big_endian);
334  if (0 > rz_io_nread_at(pclntab->io, pclntab->filetab, tmp8, sizeof(ut32))) {
335  RZ_LOG_ERROR("Failed to read go filetab at 0x%08" PFMT64x "\n", pclntab->filetab);
336  return 0;
337  }
338  pclntab->nfiletab = rz_read_ble32(tmp8, pclntab->big_endian);
339 
340  if (!is_pclntab_valid(pclntab)) {
341  rz_core_notify_error(core, "Invalid go 1.12 pclntab (invalid table).");
342  return 0;
343  }
344 
345  rz_flag_space_push(core->flags, RZ_FLAGS_FS_SYMBOLS);
346  for (ut32 i = 0, ptr = 0; i < pclntab->nfunctab; ++i, ptr += (pclntab->ptrsize * 2)) {
347  ut64 offset = pclntab->functab + ptr;
348 
349  // reads the value of the function pointer
350  if (0 > rz_io_nread_at(pclntab->io, offset, tmp8, sizeof(tmp8))) {
351  RZ_LOG_ERROR("Failed to read go function address at 0x%08" PFMT64x "\n", offset);
352  break;
353  }
354  func_ptr = go_uintptr(pclntab, tmp8);
355 
356  // reads the value of the function data offset
357  if (0 > rz_io_nread_at(pclntab->io, offset + pclntab->ptrsize, tmp8, sizeof(tmp8))) {
358  RZ_LOG_ERROR("Failed to read go function address data at 0x%08" PFMT64x "\n", offset);
359  break;
360  }
361  func_off = go_uintptr(pclntab, tmp8);
362 
363  name_ptr = pclntab->vaddr + func_off + pclntab->ptrsize;
364  // reads the location of the function name within funcnametab
365  if (0 > rz_io_nread_at(pclntab->io, name_ptr, tmp8, sizeof(ut32))) {
366  RZ_LOG_ERROR("Failed to read go function name address at 0x%08" PFMT64x "\n", offset);
367  break;
368  }
369 
370  name_off = pclntab->vaddr + rz_read_ble32(tmp8, pclntab->big_endian);
371 
372  // ignore failures, we can always create a new name.
373  memset(name, 0, sizeof(name));
374  (void)rz_io_nread_at(pclntab->io, name_off, (ut8 *)name, sizeof(name));
375  name[sizeof(name) - 1] = 0;
376  RZ_LOG_INFO("Recovered symbol at 0x%08" PFMT64x " with name '%s'\n", func_ptr, name);
377 
378  if (rz_str_len_utf8_ansi(name) > 0) {
379  // always add it before filtering the name.
380  add_new_func_symbol(core, name, func_ptr);
381  rz_name_filter(name, 0, true);
382  } else {
383  rz_strf(name, "fcn.pclntab.unknown.%08" PFMT64x, func_ptr);
384  add_new_func_symbol(core, name, func_ptr);
385  }
386 
387  flag = rz_str_newf("sym.go.%s", name);
388  rz_flag_set(core->flags, flag, func_ptr, 1);
389  free(flag);
390 
391  num_syms++;
392  }
393  rz_flag_space_pop(core->flags);
394 
395  return num_syms;
396 }
397 
406  rz_return_val_if_fail(core && core->bin && core->io, false);
407 
408  RzList *section_list = rz_bin_get_sections(core->bin);
409  RzList *symbols_list = rz_bin_get_symbols(core->bin);
410  RzListIter *iter;
412  ut32 num_syms = 0;
413  GoPcLnTab pclntab = { 0 };
414  ut8 header[8] = { 0 };
415 
416  rz_list_foreach (section_list, iter, section) {
417  // on ELF files the pclntab sections is named .gopclntab, but on macho is __gopclntab
418  if (section->vsize >= 16 && strstr(section->name, "gopclntab")) {
419  pclntab.vaddr = section->vaddr;
420  pclntab.size = section->vsize;
421  } else if (!pclntab.text_start &&
422  (!strcmp(section->name, ".text") || strstr(section->name, "__text"))) {
423  pclntab.text_start = section->vaddr;
424  }
425  }
426 
427  if (!pclntab.vaddr) {
428  RzBinSymbol *symbol;
429  rz_list_foreach (symbols_list, iter, symbol) {
430  // on PE files the pclntab sections is inside .rdata, so rizin creates a symbol for it
431  if (symbol->size >= 16 && !strcmp(symbol->name, "gopclntab")) {
432  pclntab.vaddr = symbol->vaddr;
433  pclntab.size = symbol->size;
434  break;
435  }
436  }
437  }
438 
439  if (!pclntab.vaddr) {
440  rz_core_notify_done(core, "Could not find go pclntab section");
441  return false;
442  } else if (0 > rz_io_nread_at(core->io, pclntab.vaddr, header, sizeof(header))) {
443  RZ_LOG_ERROR("Failed to read gopclntab at address %" PFMT64x "\n", pclntab.vaddr);
444  return false;
445  } else if (header[4] != 0 || header[5] != 0 ||
446  (header[6] != 1 && header[6] != 2 && header[6] != 4) || // pc quantum
447  (header[7] != 4 && header[7] != 8)) { // pointer size
448  rz_core_notify_error(core, "Invalid go pclntab (invalid pc quantum or pointer size).");
449  return false;
450  }
451 
452  pclntab.io = core->io;
453  pclntab.quantum = header[6];
454  pclntab.ptrsize = header[7];
455 
457  pclntab.version = GO_1_18;
459  num_syms = core_recover_golang_functions_go_1_18(core, &pclntab);
461  pclntab.version = GO_1_16;
463  num_syms = core_recover_golang_functions_go_1_16(core, &pclntab);
465  pclntab.version = GO_1_2;
467  num_syms = core_recover_golang_functions_go_1_2(core, &pclntab);
468  } else {
469  ut32 magic = rz_read_be32(header);
470  rz_core_notify_error(core, "Invalid go pclntab (unknown version: 0x%x).", magic);
471  return false;
472  }
473 
474  if (num_syms) {
475  rz_core_notify_done(core, "Recovered %u symbols and saved them at sym.go.*", num_syms);
476  rz_core_notify_begin(core, "Analyze all flags starting with sym.go. (aF @@f:sym.go.*)");
477  rz_core_cmd0(core, "aF @@f:sym.go.*");
478  rz_core_notify_done(core, "Analyze all flags starting with sym.go. (aF @@f:sym.go.*)");
479  return true;
480  }
481 
482  rz_core_notify_error(core, "Could not recover any symbol from the go pclntab.");
483  return false;
484 }
485 
486 static bool add_new_bin_string(RzCore *core, char *string, ut64 vaddr, ut32 size) {
487  ut32 ordinal = 0;
488  RzBinString *bstr;
489  RzBin *bin = core->bin;
490  RzBinFile *bf = rz_bin_cur(bin);
491  if (!bf || !bf->o || !bf->o->strings) {
492  free(string);
493  return false;
494  }
495 
496  bstr = rz_bin_object_get_string_at(bf->o, vaddr, true);
497  if (bstr && bstr->vaddr == vaddr && bstr->size == size) {
498  free(string);
499  return true;
500  }
501 
503  ordinal = rz_list_length(strings);
504 
505  ut64 paddr = rz_io_v2p(core->io, vaddr);
506 
507  bstr = RZ_NEW0(RzBinString);
508  if (!bstr) {
509  RZ_LOG_ERROR("Failed allocate new go string\n");
510  free(string);
511  return false;
512  }
513  bstr->paddr = paddr;
514  bstr->vaddr = vaddr;
515  bstr->ordinal = ordinal;
516  bstr->length = bstr->size = size;
517  bstr->string = string;
518  bstr->type = RZ_STRING_ENC_UTF8;
519  if (!rz_bin_string_database_add(bf->o->strings, bstr)) {
520  RZ_LOG_ERROR("Failed append new go string to strings database\n");
521  rz_bin_string_free(bstr);
522  return false;
523  }
524  return true;
525 }
526 
527 static bool recover_string_at(GoStrRecover *ctx, ut64 str_addr, ut64 str_size) {
528  // check that the values are acceptable.
529  if (str_size < 2 || str_size > GO_MAX_STRING_SIZE || str_addr < 1 || str_addr == UT64_MAX) {
530  return false;
531  }
532 
533  RzBinObject *obj = rz_bin_cur_object(ctx->core->bin);
534  if (!obj || !rz_bin_get_section_at(obj, str_addr, true)) {
535  // skip any possible string from invalid sections.
536  return false;
537  }
538 
539  const size_t n_prefix = strlen("str.");
540  // string size + strlen('str.') + \0
541  char *flag = malloc(str_size + n_prefix + 1);
542  char *raw = malloc(str_size + 1);
543  if (!flag || !raw) {
544  RZ_LOG_ERROR("Cannot allocate buffer to read string.");
545  free(flag);
546  free(raw);
547  return false;
548  }
549 
550  // set prefix and zero-terminator
551  flag[0] = 's';
552  flag[1] = 't';
553  flag[2] = 'r';
554  flag[3] = '.';
555  flag[str_size + 4] = 0;
556  raw[str_size] = 0;
557 
558  if (0 > rz_io_nread_at(ctx->core->io, str_addr, (ut8 *)raw, str_size)) {
559  RZ_LOG_ERROR("Failed to read string value at address %" PFMT64x "\n", str_addr);
560  free(flag);
561  free(raw);
562  return false;
563  } else if (rz_str_len_utf8_ansi(raw) != str_size) {
564  free(flag);
565  free(raw);
566  return false;
567  }
568  memcpy(flag + n_prefix, raw, str_size);
569 
570  // apply any filter to the new flag name
571  rz_name_filter(flag + n_prefix, str_size, true);
572 
573  // verify is a valid flag.
574  if (rz_str_len_utf8_ansi(flag) < 5) {
575  free(flag);
576  free(raw);
577  return false;
578  }
579 
580  // add new string to string list (raw is freed/owned by add_new_bin_string)
581  if (!add_new_bin_string(ctx->core, raw, str_addr, str_size)) {
582  free(flag);
583  return false;
584  }
585 
586  // remove any flag already set at this address
587  rz_flag_unset_all_off(ctx->core->flags, str_addr);
588 
589  // add string to string flag space.
590  rz_flag_space_push(ctx->core->flags, RZ_FLAGS_FS_STRINGS);
591  rz_flag_set(ctx->core->flags, flag, str_addr, str_size);
592  rz_flag_space_pop(ctx->core->flags);
593  free(flag);
594  ctx->n_recovered++;
595 
596  return true;
597 }
598 
599 static bool go_is_sign_match(GoStrRecover *ctx, GoStrInfo *info, GoSignature *sigs, const size_t n_sigs) {
600  ut8 copy[32]; // big enough to handle any pattern.
601  ut32 nlen = 0;
602  memset(info, 0, sizeof(GoStrInfo));
603 
604  for (size_t i = 0; i < n_sigs; ++i) {
605  if (nlen >= ctx->size) {
606  return false;
607  }
608 
609  GoSignature *sig = &sigs[i];
610  ut8 *bytes = ctx->bytes + nlen;
611  ut32 size = ctx->size - nlen;
612  if (sig->pasm->size > size) {
613  return false;
614  }
615 
616  // copy opcodes
617  memcpy(copy, bytes, sig->pasm->size);
618 
619  // apply mask
620  for (ut32 j = 0; j < sig->pasm->size; ++j) {
621  copy[j] = copy[j] & sig->pasm->mask[j];
622  }
623 
624  // verify the masked input matches the pattern
625  if (memcmp(copy, sig->pasm->pattern, sig->pasm->size)) {
626  return false;
627  }
628 
629  // decode info
630  if (sig->decode && !sig->decode(ctx->core, info, ctx->pc + nlen, bytes, size)) {
631  return false;
632  }
633 
634  // sets from where the xrefs starts.
635  if (sig->pasm->xrefs) {
636  info->xref = ctx->pc + nlen;
637  }
638 
639  nlen += sig->pasm->size;
640  }
641 
642  return true;
643 }
644 
646  RzAnalysisOp aop;
647  rz_analysis_op_init(&aop);
648  if (rz_analysis_op(ctx->core->analysis, &aop, ctx->pc, ctx->bytes, ctx->size, RZ_ANALYSIS_OP_MASK_DISASM) < 1) {
649  rz_analysis_op_fini(&aop);
650  return 0;
651  }
652  int size = aop.size;
653  rz_analysis_op_fini(&aop);
654  return size > 0 ? size : 0;
655 }
656 
657 #define go_is_sign_match_autosize(ctx, info, sigs) go_is_sign_match(ctx, info, sigs, RZ_ARRAY_SIZE(sigs))
658 #define go_asm_pattern_name(arch, bits, mnemonic) go_##arch##_##bits##_##mnemonic
659 #define go_asm_pattern_define(arch, bits, mnemonic, pattern, mask, set_xref) \
660  static GoAsmPattern go_asm_pattern_name(arch, bits, mnemonic) = { (const ut8 *)pattern, (const ut8 *)mask, (sizeof(pattern) - 1), set_xref }
661 
662 static bool decode_from_table(RzCore *core, GoStrInfo *info, ut64 pc, const ut8 *buffer, const ut32 size) {
663  RzAnalysis *analysis = core->analysis;
664  ut8 tmp[16];
665  if (0 > rz_io_nread_at(core->io, info->addr, tmp, sizeof(tmp))) {
666  return false;
667  }
668  ut32 offset = analysis->bits / 8;
669  info->addr = rz_read_ble(tmp, analysis->big_endian, analysis->bits);
670  info->size = rz_read_ble(tmp + offset, analysis->big_endian, analysis->bits);
671  return true;
672 }
673 
674 static bool decode_val_set_size(RzCore *core, GoStrInfo *info, ut64 pc, const ut8 *buffer, const ut32 size) {
675  RzAnalysisOp aop;
676  rz_analysis_op_init(&aop);
677  if (rz_analysis_op(core->analysis, &aop, pc, buffer, size, RZ_ANALYSIS_OP_MASK_DISASM) < 1) {
678  rz_analysis_op_fini(&aop);
679  return false;
680  }
681  info->size = aop.val;
682  rz_analysis_op_fini(&aop);
683  return true;
684 }
685 
686 static bool decode_val_set_addr(RzCore *core, GoStrInfo *info, ut64 pc, const ut8 *buffer, const ut32 size) {
687  RzAnalysisOp aop;
688  rz_analysis_op_init(&aop);
689  if (rz_analysis_op(core->analysis, &aop, pc, buffer, size, RZ_ANALYSIS_OP_MASK_DISASM) < 1) {
690  rz_analysis_op_fini(&aop);
691  return false;
692  }
693  info->addr = aop.val;
694  rz_analysis_op_fini(&aop);
695  return true;
696 }
697 
698 static bool decode_val_add_addr(RzCore *core, GoStrInfo *info, ut64 pc, const ut8 *buffer, const ut32 size) {
699  RzAnalysisOp aop;
700  rz_analysis_op_init(&aop);
701  if (rz_analysis_op(core->analysis, &aop, pc, buffer, size, RZ_ANALYSIS_OP_MASK_DISASM) < 1) {
702  rz_analysis_op_fini(&aop);
703  return false;
704  }
705  info->addr += aop.val;
706  rz_analysis_op_fini(&aop);
707  return true;
708 }
709 
710 static bool decode_ptr_set_addr(RzCore *core, GoStrInfo *info, ut64 pc, const ut8 *buffer, const ut32 size) {
711  RzAnalysisOp aop;
712  rz_analysis_op_init(&aop);
713  if (rz_analysis_op(core->analysis, &aop, pc, buffer, size, RZ_ANALYSIS_OP_MASK_DISASM) < 1) {
714  rz_analysis_op_fini(&aop);
715  return false;
716  }
717  info->addr = aop.ptr;
718  rz_analysis_op_fini(&aop);
719  return true;
720 }
721 
722 static bool decode_disp_set_addr(RzCore *core, GoStrInfo *info, ut64 pc, const ut8 *buffer, const ut32 size) {
723  RzAnalysisOp aop;
724  rz_analysis_op_init(&aop);
725  if (rz_analysis_op(core->analysis, &aop, pc, buffer, size, RZ_ANALYSIS_OP_MASK_DISASM) < 1) {
726  rz_analysis_op_fini(&aop);
727  return false;
728  }
729  info->addr = aop.disp;
730  rz_analysis_op_fini(&aop);
731  return true;
732 }
733 // 0x004881da 48c7401003000000 mov qword [rax + 0x10], 3
734 // 0x004881e2 488d0d8d8c0100 lea rcx, [0x004a0e76]
735 go_asm_pattern_define(x86, 64, lea, "\x48\x00\x00\x00\x00\x00\x00", "\xff\x00\x00\x00\x00\x00\x00", true);
736 go_asm_pattern_define(x86, 64, mov_imm0, "\xb9\x00\x00\x00\x00", "\xff\x00\x00\x00\x00", false);
737 go_asm_pattern_define(x86, 64, mov_imm1, "\x48\xc7\x00\x00\x00\x00\x00\x00", "\xff\xff\x00\x00\x00\x00\x00\x00", false);
738 go_asm_pattern_define(x86, 64, mov_imm2, "\x41\x00\x00\x00\x00\x00", "\xff\x00\x00\x00\x00\x00", false);
739 go_asm_pattern_define(x86, 64, mov_imm3, "\xbb\x00\x00\x00\x00", "\xff\x00\x00\x00\x00", false);
740 go_asm_pattern_define(x86, 64, mov_imm4, "\xbf\x00\x00\x00\x00", "\xff\x00\x00\x00\x00", false);
741 go_asm_pattern_define(x86, 64, mov_reg0, "\x48\x00\x00\x00", "\xff\x00\x00\x00", false);
742 go_asm_pattern_define(x86, 64, mov_reg1, "\x48\x00\x00\x00\x00", "\xff\x00\x00\x00\x00", false);
743 
745  // lea reg, [string_offset]
747  // mov [esp/rsp + 0x..], reg
748  { &go_asm_pattern_name(x86, 64, mov_reg0), NULL },
749  // mov [esp/rsp + 0x..], string_size
750  { &go_asm_pattern_name(x86, 64, mov_imm1), &decode_val_set_size },
751 };
752 
754  // lea reg, [string_offset]
756  // mov [esp/rsp + 0x..], reg
757  { &go_asm_pattern_name(x86, 64, mov_reg1), NULL },
758  // mov [esp/rsp + 0x..], string_size
759  { &go_asm_pattern_name(x86, 64, mov_imm1), &decode_val_set_size },
760 };
761 
763  // lea reg, [string_offset]
765  // mov reg, string_size
766  { &go_asm_pattern_name(x86, 64, mov_imm0), &decode_val_set_size },
767 };
768 
770  // lea reg, [string_offset]
772  // mov reg, string_size
773  { &go_asm_pattern_name(x86, 64, mov_imm2), &decode_val_set_size },
774 };
775 
777  // lea reg, [string_offset]
779  // mov reg, string_size
780  { &go_asm_pattern_name(x86, 64, mov_imm3), &decode_val_set_size },
781 };
782 
784  // lea reg, [string_offset]
786  // mov reg, string_size
787  { &go_asm_pattern_name(x86, 64, mov_imm4), &decode_val_set_size },
788 };
789 
791  // mov reg, string_size
792  { &go_asm_pattern_name(x86, 64, mov_imm0), &decode_val_set_size },
793  // lea reg, [string_offset]
795 };
796 
798  // mov reg, string_size
799  { &go_asm_pattern_name(x86, 64, mov_imm1), &decode_val_set_size },
800  // lea reg, [string_offset]
802 };
803 
805  // mov reg, string_size
806  { &go_asm_pattern_name(x86, 64, mov_imm3), &decode_val_set_size },
807  // lea reg, [string_offset]
809 };
810 
812  // mov reg, string_size
813  { &go_asm_pattern_name(x86, 64, mov_imm4), &decode_val_set_size },
814  // lea reg, [string_offset]
816 };
817 
819  // lea reg, [table_offset]
821  // mov reg, reg
822  { &go_asm_pattern_name(x86, 64, mov_reg0), &decode_from_table },
823 };
824 
826  // lea reg, [table_offset]
828  // mov reg, reg
829  { &go_asm_pattern_name(x86, 64, mov_reg1), &decode_from_table },
830 };
831 
833  RzAnalysis *analysis = ctx->core->analysis;
835  GoStrInfo info = { 0 };
836 
849  return oplen;
850  }
851 
852  // try to recover the string.
853  if (!recover_string_at(ctx, info.addr, info.size)) {
854  return oplen;
855  }
856 
858  return oplen;
859 }
860 
861 go_asm_pattern_define(x86, 32, lea, "\x8d\x00\x00\x00\x00\x00", "\xff\x00\x00\x00\x00\x00", true);
862 go_asm_pattern_define(x86, 32, mov_imm0, "\xc7\x00\x00\x00\x00\x00\x00", "\xff\x00\x00\x00\x00\x00\x00", false);
863 go_asm_pattern_define(x86, 32, mov_imm1, "\xc7\x00\x00\x00\x00\x00\x00\x00", "\xff\x00\x00\x00\x00\x00\x00\x00", false);
864 go_asm_pattern_define(x86, 32, mov_reg0, "\x89\x00\x00", "\xff\x00\x00", false);
865 go_asm_pattern_define(x86, 32, mov_reg1, "\x89\x00\x00\x00", "\xff\x00\x00\x00", false);
866 
868  // lea reg, [string_offset]
870  // mov [esp/rsp + 0x..], reg
871  { &go_asm_pattern_name(x86, 32, mov_reg0), NULL },
872  // mov [esp/rsp + 0x..], string_size
873  { &go_asm_pattern_name(x86, 32, mov_imm1), &decode_val_set_size },
874 };
875 
877  // lea reg, [string_offset]
879  // mov [esp/rsp + 0x..], reg
880  { &go_asm_pattern_name(x86, 32, mov_reg1), NULL },
881  // mov [esp/rsp + 0x..], string_size
882  { &go_asm_pattern_name(x86, 32, mov_imm1), &decode_val_set_size },
883 };
884 
886  // lea reg, [string_offset]
888  // mov reg, string_size
889  { &go_asm_pattern_name(x86, 32, mov_imm0), &decode_val_set_size },
890 };
891 
893  // lea reg, [string_offset]
895  // mov reg, string_size
896  { &go_asm_pattern_name(x86, 32, mov_imm1), &decode_val_set_size },
897 };
898 
900  // mov reg, string_size
901  { &go_asm_pattern_name(x86, 32, mov_imm0), &decode_val_set_size },
902  // lea reg, [string_offset]
904 };
905 
907  // lea reg, [table_offset]
909  // mov reg, reg
910  { &go_asm_pattern_name(x86, 32, mov_reg0), &decode_from_table },
911 };
912 
914  RzAnalysis *analysis = ctx->core->analysis;
916  GoStrInfo info = { 0 };
917 
924  return oplen;
925  }
926 
927  // try to recover the string.
928  if (!recover_string_at(ctx, info.addr, info.size)) {
929  return oplen;
930  }
931 
933  return oplen;
934 }
935 
936 go_asm_pattern_define(arm, 64, adrp, "\x00\x00\x00\x80", "\x00\x00\x00\x8f", true);
937 go_asm_pattern_define(arm, 64, add, "\x00\x00\x00\x01", "\x00\x00\x00\x6f", false);
938 go_asm_pattern_define(arm, 64, orr, "\x00\x00\x00\x22", "\x00\x00\x80\x6f", false);
939 go_asm_pattern_define(arm, 64, movz, "\x00\x00\x80\x42", "\x00\x00\x80\x6f", false);
940 go_asm_pattern_define(arm, 64, any, "\x00\x00\x00\x00", "\x00\x00\x00\x00", false);
941 
943  // adrp reg0, base_str
945  // add reg0, reg0, offset_str
947  // str reg, [sp, ..]
948  { &go_asm_pattern_name(arm, 64, any), NULL },
949  // orr reg1, 0, string_size
951 };
952 
954  // adrp reg0, base_str
956  // add reg0, reg0, offset_str
958  // str reg, [sp, ..]
959  { &go_asm_pattern_name(arm, 64, any), NULL },
960  // movz reg1, string_size
961  { &go_asm_pattern_name(arm, 64, movz), &decode_val_set_size },
962 };
963 
965  // orr reg1, 0, string_size
967  // str reg, [sp, ..]
968  { &go_asm_pattern_name(arm, 64, any), NULL },
969  // adrp reg0, base_str
971  // add reg0, reg0, offset_str
973 };
974 
976  // movz reg1, string_size
977  { &go_asm_pattern_name(arm, 64, movz), &decode_val_set_size },
978  // str reg, [sp, ..]
979  { &go_asm_pattern_name(arm, 64, any), NULL },
980  // adrp reg0, base_str
982  // add reg0, reg0, offset_str
984 };
985 
987  // adrp reg0, base_str
989  // add reg0, reg0, offset_str
991  // orr reg1, 0, string_size
993 };
994 
996  // adrp reg0, base_str
998  // add reg0, reg0, offset_str
1000  // movz reg1, string_size
1001  { &go_asm_pattern_name(arm, 64, movz), &decode_val_set_size },
1002 };
1003 
1005  // adrp reg0, base_str
1007  // add reg0, reg0, offset_str
1009  // str reg, [sp, ..]
1010  { &go_asm_pattern_name(arm, 64, any), &decode_from_table },
1011 };
1012 
1014  RzAnalysis *analysis = ctx->core->analysis;
1015  GoStrInfo info = { 0 };
1016 
1024  return 4;
1025  }
1026 
1027  // try to recover the string.
1028  if (!recover_string_at(ctx, info.addr, info.size)) {
1029  return 4;
1030  }
1031 
1033  return 4;
1034 }
1035 
1036 static bool decode_ldr_set_addr(RzCore *core, GoStrInfo *info, ut64 pc, const ut8 *buffer, const ut32 size) {
1037  RzAnalysisOp aop;
1038  ut8 tmp[4];
1039  ut64 addr = 0;
1040 
1041  rz_analysis_op_init(&aop);
1042  if (rz_analysis_op(core->analysis, &aop, pc, buffer, size, RZ_ANALYSIS_OP_MASK_DISASM) < 1) {
1043  rz_analysis_op_fini(&aop);
1044  return false;
1045  }
1046  addr = aop.ptr;
1047  rz_analysis_op_fini(&aop);
1048 
1049  if (0 > rz_io_nread_at(core->io, addr, tmp, sizeof(tmp))) {
1050  return false;
1051  }
1052  info->addr = rz_read_ble32(tmp, core->analysis->big_endian);
1053  return true;
1054 }
1055 
1056 go_asm_pattern_define(arm, 32, ldr, "\x00\x00\x9f\xe5", "\x00\x00\x9f\xe5", true);
1057 go_asm_pattern_define(arm, 32, mov, "\x00\x00\xa0\xe3", "\x00\x00\xa0\xe3", false);
1058 go_asm_pattern_define(arm, 32, any, "\x00\x00\x00\x00", "\x00\x00\x00\x00", false);
1059 
1061  // ldr reg0, string_offset
1063  // str reg, [sp, ..]
1064  { &go_asm_pattern_name(arm, 32, any), NULL },
1065  // mov reg1, string_size
1067 };
1068 
1070  // mov reg1, string_size
1072  // str reg, [sp, ..]
1073  { &go_asm_pattern_name(arm, 32, any), NULL },
1074  // ldr reg0, string_offset
1076 };
1077 
1079  // ldr reg0, string_offset
1081  // mov reg1, string_size
1083 };
1084 
1086  // ldr reg0, string_offset
1088  // str reg, [sp, ..]
1089  { &go_asm_pattern_name(arm, 32, any), &decode_from_table },
1090 };
1091 
1093  RzAnalysis *analysis = ctx->core->analysis;
1094  GoStrInfo info = { 0 };
1095 
1100  return 4;
1101  }
1102 
1103  // try to recover the string.
1104  if (!recover_string_at(ctx, info.addr, info.size)) {
1105  return 4;
1106  }
1107 
1109  return 4;
1110 }
1111 
1112 static bool decode_lui_set_addr(RzCore *core, GoStrInfo *info, ut64 pc, const ut8 *buffer, const ut32 size) {
1113  RzAnalysisOp aop;
1114  rz_analysis_op_init(&aop);
1115  if (rz_analysis_op(core->analysis, &aop, pc, buffer, size, RZ_ANALYSIS_OP_MASK_DISASM) < 1) {
1116  rz_analysis_op_fini(&aop);
1117  return false;
1118  }
1119  info->addr = aop.val;
1120  info->addr <<= 16;
1121  rz_analysis_op_fini(&aop);
1122  return true;
1123 }
1124 
1125 go_asm_pattern_define(mips, 32, any, "\x00\x00\x00\x00", "\x00\x00\x00\x00", false);
1126 go_asm_pattern_define(mipsbe, 32, addiu, "\x24\x00\x00\x00", "\xff\x00\x00\x00", false);
1127 go_asm_pattern_define(mipsle, 32, addiu, "\x00\x00\x00\x24", "\x00\x00\x00\xff", false);
1128 go_asm_pattern_define(mipsbe, 32, lui, "\x3c\x00\x00\x00", "\xff\x00\x00\x00", true);
1129 go_asm_pattern_define(mipsle, 32, lui, "\x00\x00\x00\x3c", "\x00\x00\x00\xff", true);
1130 
1131 // ---- LE ----
1133  // lui v0, high_string_offset
1134  { &go_asm_pattern_name(mipsle, 32, lui), &decode_lui_set_addr },
1135  // addiu v0, v0, low_string_offset
1136  { &go_asm_pattern_name(mipsle, 32, addiu), &decode_val_add_addr },
1137  // sw v0, 0x08(at)
1138  { &go_asm_pattern_name(mips, 32, any), NULL },
1139  // addiu v0, zero, string_size
1140  { &go_asm_pattern_name(mipsle, 32, addiu), &decode_val_set_size },
1141 };
1142 
1144  // addiu v0, zero, string_size
1145  { &go_asm_pattern_name(mipsle, 32, addiu), &decode_val_set_size },
1146  // sw v0, 0x08(at)
1147  { &go_asm_pattern_name(mips, 32, any), NULL },
1148  // lui v0, high_string_offset
1149  { &go_asm_pattern_name(mipsle, 32, lui), &decode_lui_set_addr },
1150  // addiu v0, v0, low_string_offset
1151  { &go_asm_pattern_name(mipsle, 32, addiu), &decode_val_add_addr },
1152 };
1153 
1155  // lui v0, high_string_offset
1156  { &go_asm_pattern_name(mipsle, 32, lui), &decode_lui_set_addr },
1157  // addiu v0, v0, low_string_offset
1158  { &go_asm_pattern_name(mipsle, 32, addiu), &decode_val_add_addr },
1159  // addiu v0, zero, string_size
1160  { &go_asm_pattern_name(mipsle, 32, addiu), &decode_val_set_size },
1161 };
1162 
1164  // lui v0, high_string_offset
1165  { &go_asm_pattern_name(mipsle, 32, lui), &decode_lui_set_addr },
1166  // addiu v0, v0, low_string_offset
1167  { &go_asm_pattern_name(mipsle, 32, addiu), &decode_val_add_addr },
1168  // sw v0, 0x08(at)
1169  { &go_asm_pattern_name(mips, 32, any), &decode_from_table },
1170 };
1171 
1172 // ---- BE ----
1174  // lui v0, high_string_offset
1175  { &go_asm_pattern_name(mipsbe, 32, lui), &decode_lui_set_addr },
1176  // addiu v0, v0, low_string_offset
1177  { &go_asm_pattern_name(mipsbe, 32, addiu), &decode_val_add_addr },
1178  // sw v0, 0x08(at)
1179  { &go_asm_pattern_name(mips, 32, any), NULL },
1180  // addiu v0, zero, string_size
1181  { &go_asm_pattern_name(mipsbe, 32, addiu), &decode_val_set_size },
1182 };
1183 
1185  // addiu v0, zero, string_size
1186  { &go_asm_pattern_name(mipsbe, 32, addiu), &decode_val_set_size },
1187  // sw v0, 0x08(at)
1188  { &go_asm_pattern_name(mips, 32, any), NULL },
1189  // lui v0, high_string_offset
1190  { &go_asm_pattern_name(mipsbe, 32, lui), &decode_lui_set_addr },
1191  // addiu v0, v0, low_string_offset
1192  { &go_asm_pattern_name(mipsbe, 32, addiu), &decode_val_add_addr },
1193 };
1194 
1196  // lui v0, high_string_offset
1197  { &go_asm_pattern_name(mipsbe, 32, lui), &decode_lui_set_addr },
1198  // addiu v0, v0, low_string_offset
1199  { &go_asm_pattern_name(mipsbe, 32, addiu), &decode_val_add_addr },
1200  // addiu v0, zero, string_size
1201  { &go_asm_pattern_name(mipsbe, 32, addiu), &decode_val_set_size },
1202 };
1203 
1205  // lui v0, high_string_offset
1206  { &go_asm_pattern_name(mipsbe, 32, lui), &decode_lui_set_addr },
1207  // addiu v0, v0, low_string_offset
1208  { &go_asm_pattern_name(mipsbe, 32, addiu), &decode_val_add_addr },
1209  // sw v0, 0x08(at)
1210  { &go_asm_pattern_name(mips, 32, any), &decode_from_table },
1211 };
1212 
1214  RzAnalysis *analysis = ctx->core->analysis;
1215  GoStrInfo info = { 0 };
1216 
1217  if (analysis->big_endian &&
1222  return 4;
1223  } else if (!analysis->big_endian &&
1228  return 4;
1229  }
1230 
1231  // try to recover the string.
1232  if (!recover_string_at(ctx, info.addr, info.size)) {
1233  return 4;
1234  }
1235 
1237  return 4;
1238 }
1239 
1240 go_asm_pattern_define(mips, 64, any, "\x00\x00\x00\x00", "\x00\x00\x00\x00", false);
1241 go_asm_pattern_define(mipsbe, 64, daddu, "\x00\x00\x00\x2d", "\x00\x00\x00\xff", false);
1242 go_asm_pattern_define(mipsle, 64, daddu, "\x2d\x00\x00\x00", "\xff\x00\x00\x00", false);
1243 go_asm_pattern_define(mipsbe, 64, daddiu, "\x64\x00\x00\x00", "\xfc\x00\x00\x00", false);
1244 go_asm_pattern_define(mipsle, 64, daddiu, "\x00\x00\x00\x64", "\x00\x00\x00\xfc", false);
1245 go_asm_pattern_define(mipsbe, 64, move, "\x64\x00\x00\x00", "\xff\xe0\x00\x00", false);
1246 go_asm_pattern_define(mipsle, 64, move, "\x00\x00\x00\x64", "\x00\x00\xe0\xff", false);
1247 go_asm_pattern_define(mipsbe, 64, lui, "\x3c\x00\x00\x00", "\xff\x00\x00\x00", true);
1248 go_asm_pattern_define(mipsle, 64, lui, "\x00\x00\x00\x3c", "\x00\x00\x00\xff", true);
1249 
1250 // ---- LE ----
1252  // lui v0, high_string_offset
1253  { &go_asm_pattern_name(mipsle, 64, lui), &decode_lui_set_addr },
1254  // daddu v0, v0, gp
1255  { &go_asm_pattern_name(mipsle, 64, daddu), NULL },
1256  // daddiu v0, v0, low_string_offset
1257  { &go_asm_pattern_name(mipsle, 64, daddiu), &decode_val_add_addr },
1258  // sd v0, 8(at)
1259  { &go_asm_pattern_name(mips, 64, any), NULL },
1260  // daddiu v0, zero, string_size
1261  { &go_asm_pattern_name(mipsle, 64, move), &decode_val_set_size },
1262 };
1263 
1265  // daddiu v0, zero, string_size
1266  { &go_asm_pattern_name(mipsle, 64, move), &decode_val_set_size },
1267  // sd v0, 8(at)
1268  { &go_asm_pattern_name(mips, 64, any), NULL },
1269  // lui v0, high_string_offset
1270  { &go_asm_pattern_name(mipsle, 64, lui), &decode_lui_set_addr },
1271  // daddu v0, v0, gp
1272  { &go_asm_pattern_name(mipsle, 64, daddu), NULL },
1273  // daddiu v0, v0, low_string_offset
1274  { &go_asm_pattern_name(mipsle, 64, daddiu), &decode_val_add_addr },
1275 };
1276 
1278  // lui v0, high_string_offset
1279  { &go_asm_pattern_name(mipsle, 64, lui), &decode_lui_set_addr },
1280  // daddu v0, v0, gp
1281  { &go_asm_pattern_name(mipsle, 64, daddu), NULL },
1282  // daddiu v0, v0, low_string_offset
1283  { &go_asm_pattern_name(mipsle, 64, daddiu), &decode_val_add_addr },
1284  // daddiu v0, zero, string_size
1285  { &go_asm_pattern_name(mipsle, 64, move), &decode_val_set_size },
1286 };
1287 
1289  // lui v0, high_string_offset
1290  { &go_asm_pattern_name(mipsle, 64, lui), &decode_lui_set_addr },
1291  // daddu v0, v0, gp
1292  { &go_asm_pattern_name(mipsle, 64, daddu), NULL },
1293  // daddiu v0, v0, low_string_offset
1294  { &go_asm_pattern_name(mipsle, 64, daddiu), &decode_val_add_addr },
1295  // sd v0, 8(at)
1296  { &go_asm_pattern_name(mips, 64, any), &decode_from_table },
1297 };
1298 
1299 // ---- BE ----
1301  // lui v0, high_string_offset
1302  { &go_asm_pattern_name(mipsbe, 64, lui), &decode_lui_set_addr },
1303  // daddu v0, v0, gp
1304  { &go_asm_pattern_name(mipsbe, 64, daddu), NULL },
1305  // daddiu v0, v0, low_string_offset
1306  { &go_asm_pattern_name(mipsbe, 64, daddiu), &decode_val_add_addr },
1307  // sd v0, 8(at)
1308  { &go_asm_pattern_name(mips, 64, any), NULL },
1309  // daddiu v0, zero, string_size
1310  { &go_asm_pattern_name(mipsbe, 64, move), &decode_val_set_size },
1311 };
1312 
1314  // daddiu v0, zero, string_size
1315  { &go_asm_pattern_name(mipsbe, 64, move), &decode_val_set_size },
1316  // sd v0, 8(at)
1317  { &go_asm_pattern_name(mips, 64, any), NULL },
1318  // lui v0, high_string_offset
1319  { &go_asm_pattern_name(mipsbe, 64, lui), &decode_lui_set_addr },
1320  // daddu v0, v0, gp
1321  { &go_asm_pattern_name(mipsbe, 64, daddu), NULL },
1322  // daddiu v0, v0, low_string_offset
1323  { &go_asm_pattern_name(mipsbe, 64, daddiu), &decode_val_add_addr },
1324 };
1325 
1327  // lui v0, high_string_offset
1328  { &go_asm_pattern_name(mipsbe, 64, lui), &decode_lui_set_addr },
1329  // daddu v0, v0, gp
1330  { &go_asm_pattern_name(mipsbe, 64, daddu), NULL },
1331  // daddiu v0, v0, low_string_offset
1332  { &go_asm_pattern_name(mipsbe, 64, daddiu), &decode_val_add_addr },
1333  // daddiu v0, zero, string_size
1334  { &go_asm_pattern_name(mipsbe, 64, move), &decode_val_set_size },
1335 };
1336 
1338  // lui v0, high_string_offset
1339  { &go_asm_pattern_name(mipsbe, 64, lui), &decode_lui_set_addr },
1340  // daddu v0, v0, gp
1341  { &go_asm_pattern_name(mipsbe, 64, daddu), NULL },
1342  // daddiu v0, v0, low_string_offset
1343  { &go_asm_pattern_name(mipsbe, 64, daddiu), &decode_val_add_addr },
1344  // sd v0, 8(at)
1345  { &go_asm_pattern_name(mips, 64, any), &decode_from_table },
1346 };
1347 
1349  RzAnalysis *analysis = ctx->core->analysis;
1350  GoStrInfo info = { 0 };
1351 
1352  if (analysis->big_endian &&
1357  return 4;
1358  } else if (!analysis->big_endian &&
1363  return 4;
1364  }
1365 
1366  // try to recover the string.
1367  if (!recover_string_at(ctx, info.addr, info.size)) {
1368  return 4;
1369  }
1370 
1372  return 4;
1373 }
1374 
1375 go_asm_pattern_define(ppc, 64, any, "\x00\x00\x00\x00", "\x00\x00\x00\x00", false);
1376 go_asm_pattern_define(ppcle, 64, lis, "\x00\x00\x00\x3c", "\x00\x00\x00\xfc", true);
1377 go_asm_pattern_define(ppcbe, 64, lis, "\x3c\x00\x00\x00", "\xfc\x00\x00\x00", true);
1378 go_asm_pattern_define(ppcle, 64, addi, "\x00\x00\x00\x38", "\x00\x00\x00\xfc", false);
1379 go_asm_pattern_define(ppcbe, 64, addi, "\x38\x00\x00\x00", "\xfc\x00\x00\x00", false);
1380 go_asm_pattern_define(ppcle, 64, li, "\x00\x00\x00\x38", "\x00\x00\x1f\xfc", false);
1381 go_asm_pattern_define(ppcbe, 64, li, "\x38\x00\x00\x00", "\xfc\x1f\x00\x00", false);
1382 
1383 // ---- LE ----
1385  // lis r3, high_string_offset
1386  { &go_asm_pattern_name(ppcle, 64, lis), &decode_val_set_addr },
1387  // addi r3, r3, low_string_offset
1388  { &go_asm_pattern_name(ppcle, 64, addi), &decode_val_add_addr },
1389  // std r3, 0x20(r1)
1390  { &go_asm_pattern_name(ppc, 64, any), NULL },
1391  // li r3, string_size
1392  { &go_asm_pattern_name(ppcle, 64, li), &decode_val_set_size },
1393 };
1394 
1396  // li r3, string_size
1397  { &go_asm_pattern_name(ppcle, 64, li), &decode_val_set_size },
1398  // std r3, 0x20(r1)
1399  { &go_asm_pattern_name(ppc, 64, any), NULL },
1400  // lis r3, high_string_offset
1401  { &go_asm_pattern_name(ppcle, 64, lis), &decode_val_set_addr },
1402  // addi r3, r3, low_string_offset
1403  { &go_asm_pattern_name(ppcle, 64, addi), &decode_val_add_addr },
1404 };
1405 
1407  // lis r3, high_string_offset
1408  { &go_asm_pattern_name(ppcle, 64, lis), &decode_val_set_addr },
1409  // addi r3, r3, low_string_offset
1410  { &go_asm_pattern_name(ppcle, 64, addi), &decode_val_add_addr },
1411  // li r3, string_size
1412  { &go_asm_pattern_name(ppcle, 64, li), &decode_val_set_size },
1413 };
1414 
1416  // lis r3, high_string_offset
1417  { &go_asm_pattern_name(ppcle, 64, lis), &decode_val_set_addr },
1418  // addi r3, r3, low_string_offset
1419  { &go_asm_pattern_name(ppcle, 64, addi), &decode_val_add_addr },
1420  // std r3, 0x20(r1)
1421  { &go_asm_pattern_name(ppc, 64, any), &decode_from_table },
1422 };
1423 
1424 // ---- BE ----
1426  // lis r3, high_string_offset
1427  { &go_asm_pattern_name(ppcbe, 64, lis), &decode_val_set_addr },
1428  // addi r3, r3, low_string_offset
1429  { &go_asm_pattern_name(ppcbe, 64, addi), &decode_val_add_addr },
1430  // std r3, 0x20(r1)
1431  { &go_asm_pattern_name(ppc, 64, any), NULL },
1432  // li r3, string_size
1433  { &go_asm_pattern_name(ppcbe, 64, li), &decode_val_set_size },
1434 };
1435 
1437  // li r3, string_size
1438  { &go_asm_pattern_name(ppcbe, 64, li), &decode_val_set_size },
1439  // std r3, 0x20(r1)
1440  { &go_asm_pattern_name(ppc, 64, any), NULL },
1441  // lis r3, high_string_offset
1442  { &go_asm_pattern_name(ppcbe, 64, lis), &decode_val_set_addr },
1443  // addi r3, r3, low_string_offset
1444  { &go_asm_pattern_name(ppcbe, 64, addi), &decode_val_add_addr },
1445 };
1446 
1448  // lis r3, high_string_offset
1449  { &go_asm_pattern_name(ppcbe, 64, lis), &decode_val_set_addr },
1450  // addi r3, r3, low_string_offset
1451  { &go_asm_pattern_name(ppcbe, 64, addi), &decode_val_add_addr },
1452  // li r3, string_size
1453  { &go_asm_pattern_name(ppcbe, 64, li), &decode_val_set_size },
1454 };
1455 
1457  // lis r3, high_string_offset
1458  { &go_asm_pattern_name(ppcbe, 64, lis), &decode_val_set_addr },
1459  // addi r3, r3, low_string_offset
1460  { &go_asm_pattern_name(ppcbe, 64, addi), &decode_val_add_addr },
1461  // std r3, 0x20(r1)
1462  { &go_asm_pattern_name(ppc, 64, any), &decode_from_table },
1463 };
1464 
1466  RzAnalysis *analysis = ctx->core->analysis;
1467  GoStrInfo info = { 0 };
1468 
1469  if (analysis->big_endian &&
1473  return 4;
1474  } else if (!analysis->big_endian &&
1478  return 4;
1479  }
1480 
1481  // try to recover the string.
1482  if (!recover_string_at(ctx, info.addr, info.size)) {
1484  return 4;
1486  return 4;
1487  } else if (!recover_string_at(ctx, info.addr, info.size)) {
1488  return 4;
1489  }
1490  }
1491 
1493  return 4;
1494 }
1495 
1496 static bool decode_auipc_set_addr(RzCore *core, GoStrInfo *info, ut64 pc, const ut8 *buffer, const ut32 size) {
1497  RzAnalysisOp aop;
1498  rz_analysis_op_init(&aop);
1499  if (rz_analysis_op(core->analysis, &aop, pc, buffer, size, RZ_ANALYSIS_OP_MASK_DISASM) < 1) {
1500  rz_analysis_op_fini(&aop);
1501  return false;
1502  }
1503  info->addr = pc + aop.val;
1504  rz_analysis_op_fini(&aop);
1505  return true;
1506 }
1507 
1508 go_asm_pattern_define(riscv, 64, auipc, "\x17\x00\x00\x00", "\x7f\x00\x00\x00", true);
1509 go_asm_pattern_define(riscv, 64, addi, "\x13\x00\x00\x00", "\x7f\x00\x00\x00", false);
1510 go_asm_pattern_define(riscv, 64, addiw, "\x1b\x00\x00\x00", "\x7f\x70\x00\x00", false);
1511 go_asm_pattern_define(riscv, 64, li, "\x13\x00\x00\x00", "\x7f\x80\x0F\x00", false);
1512 go_asm_pattern_define(riscv, 64, any, "\x00\x00\x00\x00", "\x00\x00\x00\x00", false);
1513 
1515  // auipc gp, high_string_offset
1516  { &go_asm_pattern_name(riscv, 64, auipc), &decode_auipc_set_addr },
1517  // addi gp, gp, low_string_offset
1518  { &go_asm_pattern_name(riscv, 64, addi), &decode_val_add_addr },
1519  // sd gp, 8(sp)
1520  { &go_asm_pattern_name(riscv, 64, any), NULL },
1521  // addiw gp, zero, string_size
1522  { &go_asm_pattern_name(riscv, 64, addiw), &decode_val_set_size },
1523 };
1524 
1526  // auipc gp, high_string_offset
1527  { &go_asm_pattern_name(riscv, 64, auipc), &decode_auipc_set_addr },
1528  // addi gp, gp, low_string_offset
1529  { &go_asm_pattern_name(riscv, 64, addi), &decode_val_add_addr },
1530  // sd gp, 8(sp)
1531  { &go_asm_pattern_name(riscv, 64, any), NULL },
1532  // li gp, zero, string_size
1533  { &go_asm_pattern_name(riscv, 64, li), &decode_val_set_size },
1534 };
1535 
1537  // li gp, zero, string_size
1538  { &go_asm_pattern_name(riscv, 64, li), &decode_val_set_size },
1539  // sd gp, 8(sp)
1540  { &go_asm_pattern_name(riscv, 64, any), NULL },
1541  // auipc gp, high_string_offset
1542  { &go_asm_pattern_name(riscv, 64, auipc), &decode_auipc_set_addr },
1543  // addi gp, gp, low_string_offset
1544  { &go_asm_pattern_name(riscv, 64, addi), &decode_val_add_addr },
1545 };
1546 
1548  // addiw gp, zero, string_size
1549  { &go_asm_pattern_name(riscv, 64, addiw), &decode_val_set_size },
1550  // sd gp, 8(sp)
1551  { &go_asm_pattern_name(riscv, 64, any), NULL },
1552  // auipc gp, high_string_offset
1553  { &go_asm_pattern_name(riscv, 64, auipc), &decode_auipc_set_addr },
1554  // addi gp, gp, low_string_offset
1555  { &go_asm_pattern_name(riscv, 64, addi), &decode_val_add_addr },
1556 };
1557 
1559  // auipc gp, high_string_offset
1560  { &go_asm_pattern_name(riscv, 64, auipc), &decode_auipc_set_addr },
1561  // addi gp, gp, low_string_offset
1562  { &go_asm_pattern_name(riscv, 64, addi), &decode_val_add_addr },
1563  // addiw gp, zero, string_size
1564  { &go_asm_pattern_name(riscv, 64, addiw), &decode_val_set_size },
1565 };
1566 
1568  // auipc gp, high_string_offset
1569  { &go_asm_pattern_name(riscv, 64, auipc), &decode_auipc_set_addr },
1570  // addi gp, gp, low_string_offset
1571  { &go_asm_pattern_name(riscv, 64, addi), &decode_val_add_addr },
1572  // li gp, zero, string_size
1573  { &go_asm_pattern_name(riscv, 64, li), &decode_val_set_size },
1574 };
1575 
1577  // auipc gp, high_string_offset
1578  { &go_asm_pattern_name(riscv, 64, auipc), &decode_auipc_set_addr },
1579  // addi gp, gp, low_string_offset
1580  { &go_asm_pattern_name(riscv, 64, addi), &decode_val_add_addr },
1581  // sd gp, 8(sp)
1582  { &go_asm_pattern_name(riscv, 64, any), &decode_from_table },
1583 };
1584 
1586  RzAnalysis *analysis = ctx->core->analysis;
1587  GoStrInfo info = { 0 };
1588 
1596  return 4;
1597  }
1598 
1599  // try to recover the string.
1600  if (!recover_string_at(ctx, info.addr, info.size)) {
1601  return 4;
1602  }
1603 
1605  return 4;
1606 }
1607 
1614  rz_return_if_fail(core && core->analysis && core->analysis->fcns && core->io);
1615  rz_core_notify_begin(core, "Analyze all instructions to recover all strings used in sym.go.*");
1616 
1617  const char *asm_arch = rz_config_get(core->config, "asm.arch");
1618  ut32 asm_bits = rz_config_get_i(core->config, "asm.bits");
1619  RzListIter *it, *it2;
1620  RzAnalysisFunction *func;
1621  RzAnalysisBlock *block;
1622  GoStrRecoverCb recover_cb = NULL;
1623  ut8 *bytes = NULL;
1625  GoStrRecover ctx = { 0 };
1626  ctx.core = core;
1627 
1628  if (!strcmp(asm_arch, "x86")) {
1629  switch (asm_bits) {
1630  case 32:
1631  recover_cb = &golang_recover_string_x86;
1632  break;
1633  case 64:
1634  recover_cb = &golang_recover_string_x64;
1635  break;
1636  default:
1637  break;
1638  }
1639  } else if (!strcmp(asm_arch, "arm")) {
1640  switch (asm_bits) {
1641  case 32:
1642  recover_cb = &golang_recover_string_arm32;
1643  break;
1644  case 64:
1645  recover_cb = &golang_recover_string_arm64;
1646  break;
1647  default:
1648  break;
1649  }
1650  } else if (!strcmp(asm_arch, "mips")) {
1651  switch (asm_bits) {
1652  case 32:
1653  recover_cb = &golang_recover_string_mips32;
1654  break;
1655  case 64:
1656  recover_cb = &golang_recover_string_mips64;
1657  break;
1658  default:
1659  break;
1660  }
1661  } else if (!strcmp(asm_arch, "riscv")) {
1662  switch (asm_bits) {
1663  case 64:
1664  recover_cb = &golang_recover_string_riscv64;
1665  break;
1666  default:
1667  break;
1668  }
1669  } else if (!strcmp(asm_arch, "ppc")) {
1670  switch (asm_bits) {
1671  case 64:
1672  recover_cb = &golang_recover_string_ppc64;
1673  break;
1674  default:
1675  break;
1676  }
1677  } else if (!strcmp(asm_arch, "sysz")) {
1678  // sysz uses strings that are all null terminated
1679  // also they are already handled by rizin.
1680  // example: 'larl %r0, str.XXXX' with the correct length.
1681  rz_core_notify_done(core, "Analyze all instructions to recover all strings used in sym.go.*");
1682  return;
1683  }
1684 
1685  if (!recover_cb) {
1686  rz_core_notify_error(core, "Cannot resolve go strings because arch '%s:%u' is not supported.", asm_arch, asm_bits);
1687  return;
1688  }
1689 
1690  rz_list_foreach (core->analysis->fcns, it, func) {
1691  if (rz_cons_is_breaked()) {
1692  break;
1693  }
1694  rz_list_foreach (func->bbs, it2, block) {
1695  bytes = malloc(block->size);
1696  if (!bytes) {
1697  RZ_LOG_ERROR("Failed allocate basic block bytes buffer\n");
1698  return;
1699  } else if (0 > rz_io_nread_at(core->io, block->addr, bytes, block->size)) {
1700  free(bytes);
1701  RZ_LOG_ERROR("Failed to read function basic block at address %" PFMT64x "\n", block->addr);
1702  return;
1703  }
1704 
1705  for (ut32 i = 0; i < block->size;) {
1706  ctx.pc = block->addr + i;
1707  ctx.bytes = bytes + i;
1708  ctx.size = block->size - i;
1709 
1710  ut32 nlen = recover_cb(&ctx);
1711  i += RZ_MAX(nlen, min_op_size);
1712  }
1713  free(bytes);
1714  }
1715  }
1716 
1717  rz_core_notify_done(core, "Analyze all instructions to recover all strings used in sym.go.*");
1718  rz_core_notify_done(core, "Recovered %d strings from the sym.go.* functions.", ctx.n_recovered);
1719 }
RZ_API int rz_analysis_archinfo(RzAnalysis *analysis, int query)
Definition: analysis.c:449
lzma_index ** i
Definition: index.h:629
static RzILOpEffect * ldr(cs_insn *insn, bool is_thumb)
Definition: arm_il32.c:564
static RzILOpEffect * mov(cs_insn *insn, bool is_thumb)
Definition: arm_il32.c:351
static ut32 adrp(ArmOp *op, ut64 addr, ut32 k)
Definition: armass64.c:853
static ut8 bytes[32]
Definition: asm_arc.c:23
RZ_API RzBinObject * rz_bin_cur_object(RzBin *bin)
Definition: bin.c:900
RZ_API RzBinSymbol * rz_bin_symbol_new(const char *name, ut64 paddr, ut64 vaddr)
Definition: bin.c:165
RZ_API void rz_bin_symbol_free(RzBinSymbol *sym)
Definition: bin.c:175
RZ_API void rz_bin_string_free(void *_str)
Definition: bin.c:192
RZ_DEPRECATE RZ_API RZ_BORROW RzList * rz_bin_get_symbols(RZ_NONNULL RzBin *bin)
Definition: bin.c:696
RZ_API RZ_BORROW RzBinSection * rz_bin_get_section_at(RzBinObject *o, ut64 off, int va)
Find the binary section at offset off.
Definition: bin.c:611
RZ_API RzBinFile * rz_bin_cur(RzBin *bin)
Definition: bin.c:895
RZ_DEPRECATE RZ_API RZ_BORROW RzList * rz_bin_get_sections(RZ_NONNULL RzBin *bin)
Definition: bin.c:597
RzBinInfo * info(RzBinFile *bf)
Definition: bin_ne.c:86
RZ_API RZ_BORROW RzBinString * rz_bin_object_get_string_at(RZ_NONNULL RzBinObject *obj, ut64 address, bool is_va)
Return RzBinString if at address there is an entry in the RzBinObject string database.
Definition: bobj.c:861
RZ_API const RzList * rz_bin_object_get_strings(RZ_NONNULL RzBinObject *obj)
Get list of RzBinString representing the strings identified in the binary object.
Definition: bobj.c:798
RZ_API bool rz_bin_string_database_add(RZ_NONNULL RzBinStrDb *db, RZ_NONNULL RzBinString *bstr)
{ function_description }
Definition: bobj.c:1094
struct buffer buffer
RZ_API int rz_core_cmd0(RzCore *core, const char *cmd)
Definition: cmd.c:5428
RZ_API ut64 rz_config_get_i(RzConfig *cfg, RZ_NONNULL const char *name)
Definition: config.c:119
RZ_API RZ_BORROW const char * rz_config_get(RzConfig *cfg, RZ_NONNULL const char *name)
Definition: config.c:75
RZ_API bool rz_cons_is_breaked(void)
Definition: cons.c:373
static GoSignature go_ppcle64_li_std_lis_addi_signature[]
Definition: golang.c:1395
static bool decode_from_table(RzCore *core, GoStrInfo *info, ut64 pc, const ut8 *buffer, const ut32 size)
Definition: golang.c:662
#define GO_1_18
Definition: golang.c:10
#define IS_GOPCLNTAB_1_2_LE(x)
Definition: golang.c:12
static bool decode_val_set_size(RzCore *core, GoStrInfo *info, ut64 pc, const ut8 *buffer, const ut32 size)
Definition: golang.c:674
static GoSignature go_x64_mov3_lea_signature[]
Definition: golang.c:811
static GoSignature go_x64_lea_mov2_signature[]
Definition: golang.c:776
static GoSignature go_ppcbe64_lis_addi_std_li_signature[]
Definition: golang.c:1425
#define IS_GOPCLNTAB_1_16_BE(x)
Definition: golang.c:15
#define go_asm_pattern_name(arch, bits, mnemonic)
Definition: golang.c:658
static GoSignature go_ppcle64_lis_addi_li_signature[]
Definition: golang.c:1406
static GoSignature go_arm64_adrp_add_str_movz_signature[]
Definition: golang.c:953
static GoSignature go_riscv64_li_sd_auipc_add_signature[]
Definition: golang.c:1536
ut64 go_data(GoPcLnTab *pclntab, ut32 n_word)
Definition: golang.c:95
struct go_pc_line_table_t GoPcLnTab
static bool recover_string_at(GoStrRecover *ctx, ut64 str_addr, ut64 str_size)
Definition: golang.c:527
static ut32 decode_one_opcode_size(GoStrRecover *ctx)
Definition: golang.c:645
static ut32 core_recover_golang_functions_go_1_2(RzCore *core, GoPcLnTab *pclntab)
Definition: golang.c:312
#define IS_GOPCLNTAB_1_18_BE(x)
Definition: golang.c:17
static GoSignature go_mipsbe32_table_signature[]
Definition: golang.c:1204
static GoSignature go_ppcbe64_li_std_lis_addi_signature[]
Definition: golang.c:1436
#define GO_MAX_STRING_SIZE
Definition: golang.c:6
RZ_API bool rz_core_analysis_recover_golang_functions(RzCore *core)
reads pclntab table in go binaries and recovers functions. Follows the code https://github....
Definition: golang.c:405
static bool go_is_sign_match(GoStrRecover *ctx, GoStrInfo *info, GoSignature *sigs, const size_t n_sigs)
Definition: golang.c:599
static GoSignature go_mipsle64_daddiu_sd_lui_daddu_daddiu_signature[]
Definition: golang.c:1264
static GoSignature go_mipsle32_table_signature[]
Definition: golang.c:1163
static GoSignature go_mipsle64_table_signature[]
Definition: golang.c:1288
static GoSignature go_arm64_movz_str_adrp_add_signature[]
Definition: golang.c:975
static GoSignature go_ppcbe64_table_signature[]
Definition: golang.c:1456
static GoSignature go_mipsbe64_lui_daddu_daddiu_daddiu_signature[]
Definition: golang.c:1326
static GoSignature go_mipsle64_lui_daddu_daddiu_sd_daddiu_signature[]
Definition: golang.c:1251
static GoSignature go_arm32_ldr_mov_signature[]
Definition: golang.c:1078
static GoSignature go_x86_table_signature[]
Definition: golang.c:906
static GoSignature go_arm64_adrp_add_movz_signature[]
Definition: golang.c:995
static GoSignature go_x64_lea_mov1_mov_signature[]
Definition: golang.c:753
ut64 go_uintptr(GoPcLnTab *pclntab, ut8 *bytes)
Definition: golang.c:79
RZ_API void rz_core_analysis_resolve_golang_strings(RzCore *core)
Attempts to recover all golang string.
Definition: golang.c:1613
static GoSignature go_mipsle32_lui_addiu_sw_addiu_signature[]
Definition: golang.c:1132
static ut32 golang_recover_string_arm64(GoStrRecover *ctx)
Definition: golang.c:1013
static GoSignature go_mipsbe32_addiu_sw_lui_addiu_signature[]
Definition: golang.c:1184
static ut32 golang_recover_string_arm32(GoStrRecover *ctx)
Definition: golang.c:1092
struct go_asm_pattern_t GoAsmPattern
static GoSignature go_x64_table1_signature[]
Definition: golang.c:825
static GoSignature go_mipsle32_addiu_sw_lui_addiu_signature[]
Definition: golang.c:1143
ut64 go_offset(GoPcLnTab *pclntab, ut32 n_word)
Definition: golang.c:86
static ut32 golang_recover_string_ppc64(GoStrRecover *ctx)
Definition: golang.c:1465
static GoSignature go_mipsle32_lui_addiu_addiu_signature[]
Definition: golang.c:1154
static GoSignature go_x64_table0_signature[]
Definition: golang.c:818
static GoSignature go_x64_lea_mov3_signature[]
Definition: golang.c:783
static GoSignature go_x64_mov1_lea_signature[]
Definition: golang.c:797
struct go_string_info_t GoStrInfo
#define is_addr_outside(x)
Definition: golang.c:103
static GoSignature go_mipsle64_lui_daddu_daddiu_daddiu_signature[]
Definition: golang.c:1277
#define GO_1_2
Definition: golang.c:8
static ut32 core_recover_golang_functions_go_1_18(RzCore *core, GoPcLnTab *pclntab)
Definition: golang.c:160
#define go_is_sign_match_autosize(ctx, info, sigs)
Definition: golang.c:657
static GoSignature go_riscv64_table_signature[]
Definition: golang.c:1576
static ut32 golang_recover_string_mips64(GoStrRecover *ctx)
Definition: golang.c:1348
ut32 go_func_tab_field_size(GoPcLnTab *pclntab)
Definition: golang.c:72
static GoSignature go_riscv64_auipc_add_addiw_signature[]
Definition: golang.c:1558
static GoSignature go_arm64_table_signature[]
Definition: golang.c:1004
static GoSignature go_mipsbe32_lui_addiu_sw_addiu_signature[]
Definition: golang.c:1173
static GoSignature go_mipsbe32_lui_addiu_addiu_signature[]
Definition: golang.c:1195
static GoSignature go_mipsbe64_lui_daddu_daddiu_sd_daddiu_signature[]
Definition: golang.c:1300
static GoSignature go_x86_lea_mov0_mov_signature[]
Definition: golang.c:867
static bool decode_disp_set_addr(RzCore *core, GoStrInfo *info, ut64 pc, const ut8 *buffer, const ut32 size)
Definition: golang.c:722
static GoSignature go_x64_lea_mov0_mov_signature[]
Definition: golang.c:744
static bool decode_lui_set_addr(RzCore *core, GoStrInfo *info, ut64 pc, const ut8 *buffer, const ut32 size)
Definition: golang.c:1112
static ut32 core_recover_golang_functions_go_1_16(RzCore *core, GoPcLnTab *pclntab)
Definition: golang.c:235
static GoSignature go_ppcle64_lis_addi_std_li_signature[]
Definition: golang.c:1384
#define go_asm_pattern_define(arch, bits, mnemonic, pattern, mask, set_xref)
Definition: golang.c:659
static GoSignature go_ppcbe64_lis_addi_li_signature[]
Definition: golang.c:1447
static bool add_new_bin_string(RzCore *core, char *string, ut64 vaddr, ut32 size)
Definition: golang.c:486
static GoSignature go_x86_lea_mov1_signature[]
Definition: golang.c:892
static bool decode_auipc_set_addr(RzCore *core, GoStrInfo *info, ut64 pc, const ut8 *buffer, const ut32 size)
Definition: golang.c:1496
static GoSignature go_arm32_mov_str_ldr_signature[]
Definition: golang.c:1069
static GoSignature go_x64_lea_mov0_signature[]
Definition: golang.c:762
ut32(* GoStrRecoverCb)(GoStrRecover *ctx)
Definition: golang.c:70
static GoSignature go_x86_lea_mov1_mov_signature[]
Definition: golang.c:876
static bool decode_ldr_set_addr(RzCore *core, GoStrInfo *info, ut64 pc, const ut8 *buffer, const ut32 size)
Definition: golang.c:1036
static GoSignature go_mipsbe64_daddiu_sd_lui_daddu_daddiu_signature[]
Definition: golang.c:1313
static GoSignature go_riscv64_addiw_sd_auipc_add_signature[]
Definition: golang.c:1547
bool(* GoDecodeCb)(RzCore *core, GoStrInfo *info, ut64 pc, const ut8 *buffer, const ut32 size)
Definition: golang.c:63
static GoSignature go_riscv64_auipc_add_li_signature[]
Definition: golang.c:1567
static GoSignature go_x64_mov2_lea_signature[]
Definition: golang.c:804
static GoSignature go_arm64_orr_str_adrp_add_signature[]
Definition: golang.c:964
struct go_string_recover_t GoStrRecover
static bool decode_val_add_addr(RzCore *core, GoStrInfo *info, ut64 pc, const ut8 *buffer, const ut32 size)
Definition: golang.c:698
static GoSignature go_arm64_adrp_add_orr_signature[]
Definition: golang.c:986
static GoSignature go_x64_mov0_lea_signature[]
Definition: golang.c:790
struct go_signature_t GoSignature
static void add_new_func_symbol(RzCore *core, const char *name, ut64 vaddr)
Definition: golang.c:136
#define GO_1_16
Definition: golang.c:9
static GoSignature go_arm64_adrp_add_str_orr_signature[]
Definition: golang.c:942
#define IS_GOPCLNTAB_1_2_BE(x)
Definition: golang.c:13
static ut32 golang_recover_string_riscv64(GoStrRecover *ctx)
Definition: golang.c:1585
static bool decode_val_set_addr(RzCore *core, GoStrInfo *info, ut64 pc, const ut8 *buffer, const ut32 size)
Definition: golang.c:686
static GoSignature go_arm32_table_signature[]
Definition: golang.c:1085
static ut32 golang_recover_string_mips32(GoStrRecover *ctx)
Definition: golang.c:1213
static GoSignature go_ppcle64_table_signature[]
Definition: golang.c:1415
static GoSignature go_x64_lea_mov1_signature[]
Definition: golang.c:769
static GoSignature go_riscv64_auipc_add_sd_addiw_signature[]
Definition: golang.c:1514
static bool is_pclntab_valid(GoPcLnTab *pclntab)
Definition: golang.c:104
#define IS_GOPCLNTAB_1_18_LE(x)
Definition: golang.c:16
#define IS_GOPCLNTAB_1_16_LE(x)
Definition: golang.c:14
static ut32 golang_recover_string_x86(GoStrRecover *ctx)
Definition: golang.c:913
static GoSignature go_mipsbe64_table_signature[]
Definition: golang.c:1337
static GoSignature go_x86_mov_lea_signature[]
Definition: golang.c:899
static bool decode_ptr_set_addr(RzCore *core, GoStrInfo *info, ut64 pc, const ut8 *buffer, const ut32 size)
Definition: golang.c:710
static GoSignature go_riscv64_auipc_add_sd_li_signature[]
Definition: golang.c:1525
static GoSignature go_arm32_ldr_str_mov_signature[]
Definition: golang.c:1060
static GoSignature go_x86_lea_mov0_signature[]
Definition: golang.c:885
static ut32 golang_recover_string_x64(GoStrRecover *ctx)
Definition: golang.c:832
#define RZ_API
#define NULL
Definition: cris-opc.c:27
uint16_t ut16
uint32_t ut32
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 bool rz_flag_unset_all_off(RzFlag *f, ut64 off)
Definition: flag.c:635
RZ_API RzFlagItem * rz_flag_set(RzFlag *f, const char *name, ut64 off, ut32 size)
Definition: flag.c:521
RZ_API void Ht_() free(HtName_(Ht) *ht)
Definition: ht_inc.c:130
voidpf void uLong size
Definition: ioapi.h:138
voidpf uLong offset
Definition: ioapi.h:144
uint8_t ut8
Definition: lh5801.h:11
return memset(p, 0, total)
memcpy(mem, inblock.get(), min(CONTAINING_RECORD(inblock.get(), MEMBLOCK, data) ->size, size))
RZ_API void rz_core_notify_begin(RZ_NONNULL RzCore *core, RZ_NONNULL const char *format,...)
Prints a message definining the beginning of a task.
Definition: core.c:33
RZ_API void rz_core_notify_done(RZ_NONNULL RzCore *core, RZ_NONNULL const char *format,...)
Prints a message definining the end of a task which succeeded.
Definition: core.c:60
RZ_API void rz_core_notify_error(RZ_NONNULL RzCore *core, RZ_NONNULL const char *format,...)
Prints a message definining the end of a task which errored.
Definition: core.c:87
RZ_API ut32 rz_list_length(RZ_NONNULL const RzList *list)
Returns the length of the list.
Definition: list.c:109
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
void * malloc(size_t size)
Definition: malloc.c:123
#define header(is_bt, len_min, ret_op)
const char * name
Definition: op.c:541
RZ_API bool rz_analysis_op_fini(RzAnalysisOp *op)
Definition: op.c:37
RZ_API void rz_analysis_op_init(RzAnalysisOp *op)
Definition: op.c:23
RZ_API int rz_analysis_op(RzAnalysis *analysis, RzAnalysisOp *op, ut64 addr, const ut8 *data, int len, RzAnalysisOpMask mask)
Definition: op.c:96
@ RZ_ANALYSIS_XREF_TYPE_STRING
Definition: rz_analysis.h:903
@ RZ_ANALYSIS_OP_MASK_DISASM
Definition: rz_analysis.h:445
#define RZ_ANALYSIS_ARCHINFO_MIN_OP_SIZE
Definition: rz_analysis.h:98
#define rz_return_if_fail(expr)
Definition: rz_assert.h:100
#define rz_return_val_if_fail(expr, val)
Definition: rz_assert.h:108
#define RZ_BIN_BIND_GLOBAL_STR
Definition: rz_bin.h:107
#define RZ_BIN_TYPE_FUNC_STR
Definition: rz_bin.h:119
#define RZ_FLAGS_FS_STRINGS
Definition: rz_core.h:66
#define RZ_FLAGS_FS_SYMBOLS
Definition: rz_core.h:67
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
static ut64 rz_read_ble(const void *src, bool big_endian, int size)
Definition: rz_endian.h:517
static ut32 rz_read_be32(const void *src)
Definition: rz_endian.h:87
RZ_API ut64 rz_io_v2p(RzIO *io, ut64 va)
Definition: io.c:541
RZ_API int rz_io_nread_at(RzIO *io, ut64 addr, ut8 *buf, int len)
Definition: io.c:338
#define RZ_LOG_INFO(fmtstr,...)
Definition: rz_log.h:54
#define RZ_LOG_ERROR(fmtstr,...)
Definition: rz_log.h:58
RZ_API bool rz_name_filter(char *name, int len, bool strict)
Definition: name.c:43
RZ_API char * rz_str_newf(const char *fmt,...) RZ_PRINTF_CHECK(1
@ RZ_STRING_ENC_UTF8
Definition: rz_str.h:21
RZ_API size_t rz_str_len_utf8_ansi(const char *str)
Definition: str.c:2723
#define rz_strf(buf,...)
Convenience macro for local temporary strings.
Definition: rz_str.h:59
#define RZ_NEW0(x)
Definition: rz_types.h:284
#define PFMT64x
Definition: rz_types.h:393
#define RZ_MAX(x, y)
#define UT64_MAX
Definition: rz_types_base.h:86
Definition: malloc.c:26
Definition: buffer.h:15
const ut8 * pattern
Definition: golang.c:57
const ut8 * mask
Definition: golang.c:58
ut64 funcnametab
Definition: golang.c:34
ut32 functabsize
Definition: golang.c:32
GoAsmPattern * pasm
Definition: golang.c:66
GoDecodeCb decode
Definition: golang.c:67
RzCore * core
Definition: golang.c:43
Definition: z80asm.h:102
RzList * fcns
Definition: rz_analysis.h:565
XX curplugin == o->plugin.
Definition: rz_bin.h:298
RzBinObject * o
Definition: rz_bin.h:305
RzList * symbols
Definition: rz_bin.h:269
RzBinStrDb * strings
Definition: rz_bin.h:280
ut32 ordinal
Definition: rz_bin.h:755
char * string
Definition: rz_bin.h:752
const char * bind
Definition: rz_bin.h:681
const char * type
Definition: rz_bin.h:682
char * name
Definition: rz_bin.h:675
RzBin * bin
Definition: rz_core.h:298
RzAnalysis * analysis
Definition: rz_core.h:322
RzIO * io
Definition: rz_core.h:313
RzFlag * flags
Definition: rz_core.h:330
RzConfig * config
Definition: rz_core.h:300
Definition: rz_io.h:59
#define bool
Definition: sysdefs.h:146
ut64(WINAPI *w32_GetEnabledXStateFeatures)()
RZ_API bool rz_analysis_xrefs_set(RzAnalysis *analysis, ut64 from, ut64 to, RzAnalysisXRefType type)
Definition: xrefs.c:117
static int addr
Definition: z80asm.c:58
static int add(char *argv[])
Definition: ziptool.c:84