Rizin
unix-like reverse engineering framework and cli tools
egg_Cfile.c File Reference
#include <rz_egg.h>

Go to the source code of this file.

Classes

struct  cEnv_t
 

Functions

static char * rz_egg_Cfile_getCompiler (void)
 
static bool rz_egg_Cfile_armOrMips (const char *arch)
 
static void rz_egg_Cfile_free_cEnv (struct cEnv_t *cEnv)
 
static bool rz_egg_Cfile_check_cEnv (struct cEnv_t *cEnv)
 
static bool isXNU (const char *os)
 
static struct cEnv_trz_egg_Cfile_set_cEnv (const char *arch, const char *os, int bits)
 
static bool rz_egg_Cfile_parseCompiled (const char *file)
 
RZ_API char * rz_egg_Cfile_parser (const char *file, const char *arch, const char *os, int bits)
 

Function Documentation

◆ isXNU()

static bool isXNU ( const char *  os)
inlinestatic

Definition at line 62 of file egg_Cfile.c.

62  {
63  return (!strcmp(os, "darwin") || !strcmp(os, "macos") || !strcmp(os, "tvos") || !strcmp(os, "watchos") || !strcmp(os, "ios"));
64 }

Referenced by rz_egg_Cfile_set_cEnv().

◆ rz_egg_Cfile_armOrMips()

static bool rz_egg_Cfile_armOrMips ( const char *  arch)
inlinestatic

Definition at line 42 of file egg_Cfile.c.

42  {
43  return (!strcmp(arch, "arm") || !strcmp(arch, "arm64") || !strcmp(arch, "aarch64") || !strcmp(arch, "thumb") || !strcmp(arch, "arm32") || !strcmp(arch, "mips") || !strcmp(arch, "mips32") || !strcmp(arch, "mips64"));
44 }
cs_arch arch
Definition: cstool.c:13

References arch.

Referenced by rz_egg_Cfile_set_cEnv().

◆ rz_egg_Cfile_check_cEnv()

static bool rz_egg_Cfile_check_cEnv ( struct cEnv_t cEnv)
inlinestatic

Definition at line 58 of file egg_Cfile.c.

58  {
59  return (!cEnv->SFLIBPATH || !cEnv->CC || !cEnv->CFLAGS || !cEnv->LDFLAGS || !cEnv->SHDR || !cEnv->TRIPLET);
60 }
char * TRIPLET
Definition: egg_Cfile.c:16
char * LDFLAGS
Definition: egg_Cfile.c:12
char * SFLIBPATH
Definition: egg_Cfile.c:8
char * CFLAGS
Definition: egg_Cfile.c:11
char * CC
Definition: egg_Cfile.c:9
char * SHDR
Definition: egg_Cfile.c:15

References cEnv_t::CC, cEnv_t::CFLAGS, cEnv_t::LDFLAGS, cEnv_t::SFLIBPATH, cEnv_t::SHDR, and cEnv_t::TRIPLET.

Referenced by rz_egg_Cfile_set_cEnv().

◆ rz_egg_Cfile_free_cEnv()

static void rz_egg_Cfile_free_cEnv ( struct cEnv_t cEnv)
static

Definition at line 46 of file egg_Cfile.c.

46  {
47  if (cEnv) {
48  free(cEnv->SFLIBPATH);
49  free(cEnv->CC);
50  free(cEnv->CFLAGS);
51  free(cEnv->LDFLAGS);
52  free(cEnv->SHDR);
53  free(cEnv->TRIPLET);
54  }
55  free(cEnv);
56 }
RZ_API void Ht_() free(HtName_(Ht) *ht)
Definition: ht_inc.c:130

References cEnv_t::CC, cEnv_t::CFLAGS, free(), cEnv_t::LDFLAGS, cEnv_t::SFLIBPATH, cEnv_t::SHDR, and cEnv_t::TRIPLET.

Referenced by rz_egg_Cfile_parser(), and rz_egg_Cfile_set_cEnv().

◆ rz_egg_Cfile_getCompiler()

static char* rz_egg_Cfile_getCompiler ( void  )
static

Definition at line 20 of file egg_Cfile.c.

20  {
21  size_t i;
22  const char *compilers[] = { "llvm-gcc", "clang", "gcc" };
23  char *output = rz_sys_getenv("CC");
24 
25  if (output) {
26  return output;
27  }
28 
29  for (i = 0; i < 3; i++) {
30  output = rz_file_path(compilers[i]);
31  if (strcmp(output, compilers[i])) {
32  free(output);
33  return strdup(compilers[i]);
34  }
35  free(output);
36  }
37 
38  eprintf("Couldn't find a compiler ! Please, set CC.\n");
39  return NULL;
40 }
lzma_index ** i
Definition: index.h:629
#define NULL
Definition: cris-opc.c:27
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")
#define eprintf(x, y...)
Definition: rlcc.c:7
RZ_API char * rz_file_path(const char *bin)
Definition: file.c:354
RZ_API char * rz_sys_getenv(const char *key)
Get the value of an environment variable named key or NULL if none exists.
Definition: sys.c:483
diff_output_t output
Definition: zipcmp.c:237

References eprintf, free(), i, NULL, output, rz_file_path(), rz_sys_getenv(), and strdup().

Referenced by rz_egg_Cfile_set_cEnv().

◆ rz_egg_Cfile_parseCompiled()

static bool rz_egg_Cfile_parseCompiled ( const char *  file)
static

Definition at line 212 of file egg_Cfile.c.

212  {
213  char *fileExt = rz_str_newf("%s.tmp", file);
214  char *buffer = rz_file_slurp(fileExt, NULL);
215  if (!buffer) {
216  eprintf("Could not open '%s'.\n", fileExt);
217  goto fail;
218  }
219 
220  buffer = rz_str_replace(buffer, "rdata", "text", false);
221  buffer = rz_str_replace(buffer, "rodata", "text", false);
222  buffer = rz_str_replace(buffer, "get_pc_thunk.bx", "__getesp__", true);
223 
224  const char *words[] = { ".cstring", "size", "___main", "section", "__alloca", "zero", "cfi" };
225  size_t i;
226  for (i = 0; i < 7; i++) {
227  rz_str_stripLine(buffer, words[i]);
228  }
229 
230  free(fileExt);
231  fileExt = rz_str_newf("%s.s", file);
232  if (!rz_file_dump(fileExt, (const ut8 *)buffer, strlen(buffer), true)) {
233  eprintf("Error while opening %s.s\n", file);
234  goto fail;
235  }
236 
237  free(buffer);
238  free(fileExt);
239  return true;
240 
241 fail:
242  free(buffer);
243  free(fileExt);
244  return false;
245 }
uint8_t ut8
Definition: lh5801.h:11
RZ_API RZ_OWN char * rz_file_slurp(const char *str, RZ_NULLABLE size_t *usz)
Definition: file.c:454
RZ_API bool rz_file_dump(const char *file, const ut8 *buf, int len, bool append)
Definition: file.c:838
RZ_API char * rz_str_newf(const char *fmt,...) RZ_PRINTF_CHECK(1
RZ_API void rz_str_stripLine(char *str, const char *key)
Definition: str.c:3814
RZ_API char * rz_str_replace(char *str, const char *key, const char *val, int g)
Definition: str.c:1110
Definition: buffer.h:15
Definition: gzappend.c:170
#define fail(test)
Definition: tests.h:29

References eprintf, fail, free(), i, NULL, rz_file_dump(), rz_file_slurp(), rz_str_newf(), rz_str_replace(), and rz_str_stripLine().

Referenced by rz_egg_Cfile_parser().

◆ rz_egg_Cfile_parser()

RZ_API char* rz_egg_Cfile_parser ( const char *  file,
const char *  arch,
const char *  os,
int  bits 
)

Definition at line 247 of file egg_Cfile.c.

247  {
248  char *output = NULL;
249  char *fileExt = NULL; // "file" with extension (.s, .text, ...)
250  struct cEnv_t *cEnv = rz_egg_Cfile_set_cEnv(arch, os, bits);
251 
252  if (!cEnv) {
253  goto fail;
254  }
255 
256  rz_str_sanitize(cEnv->CC);
257 
258  // Compile
259  char *cmd = rz_str_newf("'%s' %s -o '%s.tmp' -S '%s'\n", cEnv->CC, cEnv->CFLAGS, file, file);
260  eprintf("%s\n", cmd);
261  int rc = rz_sys_system(cmd);
262  free(cmd);
263  if (rc != 0) {
264  goto fail;
265  }
266  if (!(fileExt = rz_str_newf("%s.s", file))) {
267  goto fail;
268  }
269 
270  if (!rz_file_dump(fileExt, (const ut8 *)cEnv->SHDR, strlen(cEnv->SHDR), false)) {
271  eprintf("Error while opening %s.s\n", file);
272  goto fail;
273  }
274 
276  goto fail;
277  }
278  // Assemble
279  cmd = rz_str_newf("'%s' %s -o '%s.o' '%s.s'", cEnv->CC, cEnv->LDFLAGS, file, file);
280  eprintf("%s\n", cmd);
281  rc = rz_sys_system(cmd);
282  free(cmd);
283  if (rc != 0) {
284  goto fail;
285  }
286 
287  // Link
288  printf("rz-bin -o '%s.text' -O d/S/'%s' '%s.o'\n", file, cEnv->TEXT, file);
289  output = rz_sys_cmd_strf("rz-bin -o '%s.text' -O d/S/'%s' '%s'.o",
290  file, cEnv->TEXT, file);
291  if (!output) {
292  eprintf("Linkage failed!\n");
293  goto fail;
294  }
295 
296  free(fileExt);
297  if (!(fileExt = rz_str_newf("%s.o", file))) {
298  goto fail;
299  }
300 
301  if (!rz_file_exists(fileExt)) {
302  eprintf("Cannot find %s.o\n", file);
303  goto fail;
304  }
305 
306  free(fileExt);
307  if (!(fileExt = rz_str_newf("%s.text", file))) {
308  goto fail;
309  }
310  if (rz_file_size(fileExt) == 0) {
311  eprintf("FALLBACK: Using objcopy instead of rz_bin");
312  free(output);
313  output = rz_sys_cmd_strf("'%s' -j .text -O binary '%s.o' '%s.text'",
314  cEnv->OBJCOPY, file, file);
315  if (!output) {
316  eprintf("objcopy failed!\n");
317  goto fail;
318  }
319  }
320 
321  size_t i;
322  const char *extArray[] = { "bin", "tmp", "s", "o" };
323  for (i = 0; i < 4; i++) {
324  free(fileExt);
325  if (!(fileExt = rz_str_newf("%s.%s", file, extArray[i]))) {
326  goto fail;
327  }
328  rz_file_rm(fileExt);
329  }
330 
331  free(fileExt);
332  if ((fileExt = rz_str_newf("%s.text", file)) == NULL) {
333  goto fail;
334  }
335 
336  free(output);
338  return fileExt;
339 
340 fail:
341  free(fileExt);
342  free(output);
344  return NULL;
345 }
int bits(struct state *s, int need)
Definition: blast.c:72
_Use_decl_annotations_ int __cdecl printf(const char *const _Format,...)
Definition: cs_driver.c:93
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 cmd
Definition: sflib.h:79
static void rz_egg_Cfile_free_cEnv(struct cEnv_t *cEnv)
Definition: egg_Cfile.c:46
static bool rz_egg_Cfile_parseCompiled(const char *file)
Definition: egg_Cfile.c:212
static struct cEnv_t * rz_egg_Cfile_set_cEnv(const char *arch, const char *os, int bits)
Definition: egg_Cfile.c:66
RZ_API bool rz_file_exists(const char *str)
Definition: file.c:192
RZ_API bool rz_file_rm(const char *file)
Definition: file.c:865
RZ_API ut64 rz_file_size(const char *str)
Definition: file.c:205
RZ_API void rz_str_sanitize(char *c)
Definition: str.c:1381
RZ_API char * rz_sys_cmd_strf(const char *cmd,...) RZ_PRINTF_CHECK(1
RZ_API int rz_sys_system(const char *command)
Definition: sys.c:1658
const char * TEXT
Definition: egg_Cfile.c:17
const char * OBJCOPY
Definition: egg_Cfile.c:10

References arch, bits(), cEnv_t::CC, cEnv_t::CFLAGS, cmd, eprintf, fail, free(), i, cEnv_t::LDFLAGS, NULL, cEnv_t::OBJCOPY, output, printf(), rz_egg_Cfile_free_cEnv(), rz_egg_Cfile_parseCompiled(), rz_egg_Cfile_set_cEnv(), rz_file_dump(), rz_file_exists(), rz_file_rm(), rz_file_size(), rz_str_newf(), rz_str_sanitize(), rz_sys_cmd_strf(), rz_sys_system(), cEnv_t::SHDR, and cEnv_t::TEXT.

Referenced by rz_egg_load_file().

◆ rz_egg_Cfile_set_cEnv()

static struct cEnv_t* rz_egg_Cfile_set_cEnv ( const char *  arch,
const char *  os,
int  bits 
)
static

Definition at line 66 of file egg_Cfile.c.

66  {
67  struct cEnv_t *cEnv = calloc(1, sizeof(struct cEnv_t));
68  bool use_clang;
69  char *buffer = NULL;
70  char *output = NULL;
71 
72  if (!cEnv) {
73  return NULL;
74  }
75 
76  if (!(cEnv->CC = rz_egg_Cfile_getCompiler())) {
77  goto fail;
78  }
79 
80  cEnv->SFLIBPATH = rz_sys_getenv("SFLIBPATH");
81  if (!cEnv->SFLIBPATH) {
82  output = rz_sys_cmd_strf("rizin -hh | grep INCDIR | awk '{print $2}'");
83  if (!output || (output[0] == '\0')) {
84  eprintf("Cannot find SFLIBPATH env var.\n"
85  "Please define it, or fix rizin installation.\n");
86  goto fail;
87  }
88 
89  output[strlen(output) - 1] = '\0'; // strip the ending '\n'
90  if (!(cEnv->SFLIBPATH = rz_str_newf("%s/sflib", output))) {
91  goto fail;
92  }
93  }
94 
95  cEnv->JMP = rz_egg_Cfile_armOrMips(arch) ? "b" : "jmp";
96 
97  // TODO: Missing -Os .. caused some rip-relative LEA to be MOVQ on PIE in CLANG.. so sad
98  if (isXNU(os)) {
99  cEnv->OBJCOPY = "gobjcopy";
100  cEnv->FMT = "mach0";
101  if (!strcmp(arch, "x86")) {
102  if (bits == 32) {
103  cEnv->CFLAGS = strdup("-arch i386 -fPIC -fPIE");
104  cEnv->LDFLAGS = strdup("-arch i386 -shared -c -fPIC -fPIE -pie");
105  } else {
106  cEnv->CFLAGS = strdup("-arch x86_64 -fPIC -fPIE");
107  cEnv->LDFLAGS = strdup("-arch x86_64 -shared -c -fPIC -fPIE -pie");
108  }
109  } else {
110  cEnv->CFLAGS = strdup("-shared -c -fPIC -pie -fPIE");
111  cEnv->LDFLAGS = strdup("-shared -c -fPIC -pie -fPIE");
112  }
113  cEnv->SHDR = rz_str_newf("\n.text\n%s _main\n", cEnv->JMP);
114  } else {
115  cEnv->OBJCOPY = "objcopy";
116  cEnv->FMT = "elf";
117  cEnv->SHDR = rz_str_newf("\n.section .text\n.globl main\n"
118  "// .type main, @function\n%s main\n",
119  cEnv->JMP);
120  if (!strcmp(arch, "x86")) {
121  if (bits == 32) {
122  cEnv->CFLAGS = strdup("-fPIC -fPIE -pie -fpic -m32");
123  cEnv->LDFLAGS = strdup("-fPIC -fPIE -pie -fpic -m32");
124  } else {
125  cEnv->CFLAGS = strdup("-fPIC -fPIE -pie -fpic -m64");
126  cEnv->LDFLAGS = strdup("-fPIC -fPIE -pie -fpic -m64");
127  }
128  } else {
129  cEnv->CFLAGS = strdup("-fPIC -fPIE -pie -fpic -nostartfiles");
130  cEnv->LDFLAGS = strdup("-fPIC -fPIE -pie -fpic -nostartfiles");
131  }
132  }
133 
134  cEnv->TRIPLET = rz_str_newf("%s-%s-%d", os, arch, bits);
135 
136  if (!strcmp(os, "windows")) {
137  cEnv->TEXT = ".text";
138  cEnv->FMT = "pe";
139  } else if (isXNU(os)) {
140  // cEnv->TEXT = "0.__TEXT.__text";
141  cEnv->TEXT = "0..__text";
142  } else {
143  cEnv->TEXT = ".text";
144  }
145 
146  use_clang = false;
147  if (!strcmp(cEnv->TRIPLET, "darwin-arm-64")) {
148  free(cEnv->CC);
149  cEnv->CC = strdup("xcrun --sdk iphoneos gcc -arch arm64 -miphoneos-version-min=0.0");
150  use_clang = true;
151  cEnv->TEXT = "0.__TEXT.__text";
152  } else if (!strcmp(cEnv->TRIPLET, "darwin-arm-32")) {
153  free(cEnv->CC);
154  cEnv->CC = strdup("xcrun --sdk iphoneos gcc -arch armv7 -miphoneos-version-min=0.0");
155  use_clang = true;
156  cEnv->TEXT = "0.__TEXT.__text";
157  }
158 
159  buffer = rz_str_newf("%s -fno-stack-protector -nostdinc -include '%s'/'%s'/sflib.h",
160  cEnv->CFLAGS, cEnv->SFLIBPATH, cEnv->TRIPLET);
161  if (!buffer) {
162  goto fail;
163  }
164  free(cEnv->CFLAGS);
165  cEnv->CFLAGS = strdup(buffer);
166 
167  if (use_clang) {
168  free(buffer);
169  buffer = rz_str_newf("%s -fomit-frame-pointer"
170  " -fno-zero-initialized-in-bss",
171  cEnv->CFLAGS);
172  if (!buffer) {
173  goto fail;
174  }
175  free(cEnv->CFLAGS);
176  cEnv->CFLAGS = strdup(buffer);
177  } else {
178  free(buffer);
179  buffer = rz_str_newf("%s -z execstack -fomit-frame-pointer"
180  " -finline-functions -fno-zero-initialized-in-bss",
181  cEnv->CFLAGS);
182  if (!buffer) {
183  goto fail;
184  }
185  free(cEnv->CFLAGS);
186  cEnv->CFLAGS = strdup(buffer);
187  }
188  free(buffer);
189  buffer = rz_str_newf("%s -nostdlib", cEnv->LDFLAGS);
190  if (!buffer) {
191  goto fail;
192  }
193  free(cEnv->LDFLAGS);
194  cEnv->LDFLAGS = strdup(buffer);
195 
196  if (rz_egg_Cfile_check_cEnv(cEnv)) {
197  eprintf("Error with cEnv allocation!\n");
198  goto fail;
199  }
200 
201  free(buffer);
202  free(output);
203  return cEnv;
204 
205 fail:
206  free(buffer);
207  free(output);
209  return NULL;
210 }
static bool isXNU(const char *os)
Definition: egg_Cfile.c:62
static bool rz_egg_Cfile_check_cEnv(struct cEnv_t *cEnv)
Definition: egg_Cfile.c:58
static bool rz_egg_Cfile_armOrMips(const char *arch)
Definition: egg_Cfile.c:42
static char * rz_egg_Cfile_getCompiler(void)
Definition: egg_Cfile.c:20
void * calloc(size_t number, size_t size)
Definition: malloc.c:102
const char * JMP
Definition: egg_Cfile.c:13
const char * FMT
Definition: egg_Cfile.c:14

References arch, bits(), calloc(), cEnv_t::CC, cEnv_t::CFLAGS, eprintf, fail, cEnv_t::FMT, free(), isXNU(), cEnv_t::JMP, cEnv_t::LDFLAGS, NULL, cEnv_t::OBJCOPY, output, rz_egg_Cfile_armOrMips(), rz_egg_Cfile_check_cEnv(), rz_egg_Cfile_free_cEnv(), rz_egg_Cfile_getCompiler(), rz_str_newf(), rz_sys_cmd_strf(), rz_sys_getenv(), cEnv_t::SFLIBPATH, cEnv_t::SHDR, strdup(), cEnv_t::TEXT, and cEnv_t::TRIPLET.

Referenced by rz_egg_Cfile_parser().