Rizin
unix-like reverse engineering framework and cli tools
bin_language.c
Go to the documentation of this file.
1 // SPDX-FileCopyrightText: 2021 RizinOrg <info@rizin.re>
2 // SPDX-FileCopyrightText: 2021 deroad <wargio@libero.it>
3 // SPDX-FileCopyrightText: 2018-2019 pancake <pancake@nopcode.org>
4 // SPDX-License-Identifier: LGPL-3.0-only
5 
6 #include <rz_bin.h>
7 
8 #define LANGUAGE_WITH_BLOCKS " with blocks"
9 #define language_apply_blocks_mask(x, b) (b ? (RZ_BIN_LANGUAGE_BLOCKS | (x)) : (x))
10 #define language_apply_blocks_string(x, b) (RZ_BIN_LANGUAGE_HAS_BLOCKS(x) ? (b LANGUAGE_WITH_BLOCKS) : (b))
11 
12 static inline bool check_rust(RzBinSymbol *sym) {
13  return strstr(sym->name, "_$LT$") ||
14  strstr(sym->name, "_rust_oom");
15 }
16 
17 static inline bool check_objc(RzBinSymbol *sym) {
18  return !strncmp(sym->name, "_OBJC_", 6);
19 }
20 
21 static inline bool check_dlang(RzBinSymbol *sym) {
22  if (!strncmp(sym->name, "_D2", 3)) {
23  return true;
24  }
25  return !strncmp(sym->name, "_D4", 3);
26 }
27 
28 static inline bool check_swift(RzBinSymbol *sym) {
29  return strstr(sym->name, "swift_once");
30 }
31 
32 static inline bool check_golang(RzBinSymbol *sym) {
33  return !strncmp(sym->name, "go.", 3) ||
34  strstr(sym->name, "gopclntab");
35 }
36 
37 static inline bool check_cxx(RzBinSymbol *sym) {
38  if (!strncmp(sym->name, "_Z", 2)) {
39  return true;
40  }
41  return !strncmp(sym->name, "__Z", 3);
42 }
43 
44 static inline bool check_msvc(RzBinSymbol *sym) {
45  return *sym->name == '?';
46 }
47 
48 static inline bool check_kotlin(RzBinSymbol *sym) {
49  return strstr(sym->name, "kotlin_");
50 }
51 
52 static inline bool check_groovy(RzBinSymbol *sym) {
53  return strstr(sym->name, "_groovy");
54 }
55 
56 static inline bool check_dart(RzBinSymbol *sym) {
57  return strstr(sym->name, "io_flutter_");
58 }
59 
70  rz_return_val_if_fail(binfile && binfile->o, RZ_BIN_LANGUAGE_UNKNOWN);
71  RzBinObject *o = binfile->o;
72  RzBinInfo *info = o->info;
73  RzBinSymbol *sym;
76 
77  if (!info) {
79  }
81  if (lang != RZ_BIN_LANGUAGE_UNKNOWN &&
82  lang != RZ_BIN_LANGUAGE_C &&
83  lang != RZ_BIN_LANGUAGE_OBJC) {
84  // avoid detecting a language if was already specified.
85  return lang;
86  }
87 
88  bool is_macho = info->rclass ? strstr(info->rclass, "mach") : false;
89  bool is_elf = info->rclass ? strstr(info->rclass, "elf") : false;
90  bool is_pe = info->rclass ? strstr(info->rclass, "pe") : false;
91  bool is_class = info->rclass ? strstr(info->rclass, "class") : false;
92  bool is_blocks = false;
93  bool is_objc = false;
94  bool is_cpp = false;
95  char *lib = NULL;
96 
97  if (!is_macho && !is_elf && !is_pe && !is_class) {
99  }
100 
101  if (is_macho || is_elf) {
102  rz_list_foreach (o->imports, iter, sym) {
103  const char *name = sym->name;
104  if (!strcmp(name, "_NSConcreteGlobalBlock")) {
105  is_blocks = true;
106  } else if (!strncmp(name, "objc_", 5)) {
107  is_objc = true;
108  }
109  }
110  }
111  rz_list_foreach (o->libs, iter, lib) {
112  if (is_macho && strstr(lib, "swift")) {
113  info->lang = "swift";
115  } else if (strstr(lib, "stdc++") || strstr(lib, "c++")) {
116  is_cpp = true;
117  } else if (strstr(lib, "msvcp")) {
118  info->lang = "msvc";
119  return RZ_BIN_LANGUAGE_MSVC;
120  } else if (strstr(lib, "phobos")) {
121  info->lang = "dlang";
122  return RZ_BIN_LANGUAGE_DLANG;
123  }
124  }
125  if (is_objc) {
126  info->lang = "objc";
128  }
129 
130  rz_list_foreach (o->symbols, iter, sym) {
131  if (!sym->name) {
132  continue;
133  }
134  if (check_rust(sym)) {
135  info->lang = "rust";
136  return RZ_BIN_LANGUAGE_RUST;
137  } else if (check_golang(sym)) {
138  info->lang = "go";
139  return RZ_BIN_LANGUAGE_GO;
140  } else if (check_swift(sym)) {
141  info->lang = "swift";
143  } else if (check_cxx(sym)) {
144  is_cpp = true;
145  } else if (check_objc(sym)) {
146  info->lang = "objc";
148  } else if (check_dlang(sym)) {
149  info->lang = "dlang";
150  return RZ_BIN_LANGUAGE_DLANG;
151  } else if (check_kotlin(sym)) {
152  info->lang = "kotlin";
153  return RZ_BIN_LANGUAGE_KOTLIN;
154  } else if (check_groovy(sym)) {
155  info->lang = "groovy";
156  return RZ_BIN_LANGUAGE_GROOVY;
157  } else if (check_msvc(sym)) {
158  info->lang = "c";
159  return RZ_BIN_LANGUAGE_MSVC;
160  } else if (check_dart(sym)) {
161  info->lang = "dart";
162  return RZ_BIN_LANGUAGE_DART;
163  }
164  }
165 
166  if (is_macho || is_elf) {
167  rz_list_foreach (o->sections, iter, section) {
168  if (!section->name) {
169  continue;
170  }
171  if (strstr(section->name, "note.go.buildid") ||
172  strstr(section->name, "gopclntab") ||
173  strstr(section->name, "go_export")) {
174  info->lang = "go";
175  return RZ_BIN_LANGUAGE_GO;
176  }
177  }
178  }
179  if (is_cpp) {
180  info->lang = "c++";
182  } else if (!info->lang) {
183  info->lang = "c";
184  } else if (strstr(info->lang, "java")) {
185  return RZ_BIN_LANGUAGE_JAVA;
186  }
188 }
189 
194  if (RZ_STR_ISEMPTY(language)) {
196  }
197  bool has_blocks = strstr(language, LANGUAGE_WITH_BLOCKS);
198  if (strstr(language, "swift")) {
200  } else if (strstr(language, "java")) {
201  return RZ_BIN_LANGUAGE_JAVA;
202  } else if (strstr(language, "groovy")) {
203  return RZ_BIN_LANGUAGE_GROOVY;
204  } else if (strstr(language, "kotlin")) {
205  return RZ_BIN_LANGUAGE_KOTLIN;
206  } else if (strstr(language, "objc")) {
208  } else if (strstr(language, "cxx") || strstr(language, "c++")) {
210  } else if (strstr(language, "dlang")) {
211  return RZ_BIN_LANGUAGE_DLANG;
212  } else if (strstr(language, "msvc")) {
213  return RZ_BIN_LANGUAGE_MSVC;
214  } else if (strstr(language, "rust")) {
215  return RZ_BIN_LANGUAGE_RUST;
216  } else if (strstr(language, "dart")) {
217  return RZ_BIN_LANGUAGE_DART;
218  } else if (!strcmp(language, "c") || !strcmp(language, "c" LANGUAGE_WITH_BLOCKS)) {
219  return language_apply_blocks_mask(RZ_BIN_LANGUAGE_C, has_blocks);
220  } else if (!strcmp(language, "go")) {
221  return RZ_BIN_LANGUAGE_GO;
222  }
224 }
225 
230  switch (RZ_BIN_LANGUAGE_MASK(language)) {
232  return language_apply_blocks_string(language, "swift");
233  case RZ_BIN_LANGUAGE_GO:
234  return "go";
236  return "java";
238  return "kotlin";
239  case RZ_BIN_LANGUAGE_C:
240  return language_apply_blocks_string(language, "c");
241  case RZ_BIN_LANGUAGE_CXX:
242  return language_apply_blocks_string(language, "c++");
244  return "dlang";
246  return language_apply_blocks_string(language, "objc");
248  return "msvc";
250  return "rust";
252  return "groovy";
254  return "dart";
255  default:
256  return NULL;
257  }
258 }
static bool check_rust(RzBinSymbol *sym)
Definition: bin_language.c:12
static bool check_kotlin(RzBinSymbol *sym)
Definition: bin_language.c:48
RZ_API RzBinLanguage rz_bin_language_detect(RzBinFile *binfile)
Tries to detect which language is used in the binary based on symbols and libraries.
Definition: bin_language.c:69
static bool check_dlang(RzBinSymbol *sym)
Definition: bin_language.c:21
static bool check_objc(RzBinSymbol *sym)
Definition: bin_language.c:17
#define LANGUAGE_WITH_BLOCKS
Definition: bin_language.c:8
RZ_API RzBinLanguage rz_bin_language_to_id(const char *language)
returns the language identifier based on the given lang name
Definition: bin_language.c:193
#define language_apply_blocks_mask(x, b)
Definition: bin_language.c:9
static bool check_swift(RzBinSymbol *sym)
Definition: bin_language.c:28
static bool check_cxx(RzBinSymbol *sym)
Definition: bin_language.c:37
static bool check_msvc(RzBinSymbol *sym)
Definition: bin_language.c:44
static bool check_groovy(RzBinSymbol *sym)
Definition: bin_language.c:52
RZ_API const char * rz_bin_language_to_string(RzBinLanguage language)
returns the language name based on the given language identifier
Definition: bin_language.c:229
static bool check_golang(RzBinSymbol *sym)
Definition: bin_language.c:32
#define language_apply_blocks_string(x, b)
Definition: bin_language.c:10
static bool check_dart(RzBinSymbol *sym)
Definition: bin_language.c:56
RzBinInfo * info(RzBinFile *bf)
Definition: bin_ne.c:86
#define RZ_API
#define NULL
Definition: cris-opc.c:27
#define rz_return_val_if_fail(expr, val)
Definition: rz_assert.h:108
RzBinLanguage
Definition: rz_bin.h:145
@ RZ_BIN_LANGUAGE_UNKNOWN
Definition: rz_bin.h:146
@ RZ_BIN_LANGUAGE_GROOVY
Definition: rz_bin.h:157
@ RZ_BIN_LANGUAGE_OBJC
Definition: rz_bin.h:151
@ RZ_BIN_LANGUAGE_KOTLIN
Definition: rz_bin.h:156
@ RZ_BIN_LANGUAGE_RUST
Definition: rz_bin.h:155
@ RZ_BIN_LANGUAGE_DLANG
Definition: rz_bin.h:153
@ RZ_BIN_LANGUAGE_C
Definition: rz_bin.h:148
@ RZ_BIN_LANGUAGE_JAVA
Definition: rz_bin.h:147
@ RZ_BIN_LANGUAGE_DART
Definition: rz_bin.h:158
@ RZ_BIN_LANGUAGE_CXX
Definition: rz_bin.h:150
@ RZ_BIN_LANGUAGE_SWIFT
Definition: rz_bin.h:152
@ RZ_BIN_LANGUAGE_MSVC
Definition: rz_bin.h:154
@ RZ_BIN_LANGUAGE_GO
Definition: rz_bin.h:149
#define RZ_BIN_LANGUAGE_MASK(x)
Definition: rz_bin.h:162
#define RZ_STR_ISEMPTY(x)
Definition: rz_str.h:67
Definition: z80asm.h:102
XX curplugin == o->plugin.
Definition: rz_bin.h:298
RzBinObject * o
Definition: rz_bin.h:305
const char * lang
Definition: rz_bin.h:224
char * rclass
Definition: rz_bin.h:213
RzList * imports
Definition: rz_bin.h:268
RzList * symbols
Definition: rz_bin.h:269
RzBinInfo * info
Definition: rz_bin.h:287
RzList * libs
Definition: rz_bin.h:278
RzList * sections
Definition: rz_bin.h:267
char * name
Definition: rz_bin.h:675