The Witchcraft Compiler Collection
WCC
 All Data Structures Files Functions Variables Typedefs Macros
wcc.c
Go to the documentation of this file.
1 
31 #define __USE_GNU
32 #define _GNU_SOURCE
33 #include <bfd.h>
34 #include <dlfcn.h>
35 #include <elf.h>
36 #include <errno.h>
37 #include <fcntl.h>
38 #include <getopt.h>
39 #include <limits.h>
40 #include <stdio.h>
41 #include <stdlib.h>
42 #include <string.h>
43 #include <sys/mman.h>
44 #include <sys/procfs.h>
45 #include <sys/stat.h>
46 #include <sys/types.h>
47 #include <sys/ucontext.h>
48 #include <unistd.h>
49 #include <utlist.h>
50 #include <ctype.h>
51 #include <stdio.h>
52 #include <string.h>
53 #include <stdlib.h>
54 #include <unistd.h>
55 #include <sys/types.h>
56 #include <sys/stat.h>
57 #include <fcntl.h>
58 
59 #include <libelf.h>
60 #include <gelf.h>
61 
62 #include <nametotype.h>
63 #include <nametoalign.h>
64 #include <nametoentsz.h>
65 #include <nametolink.h>
66 #include <nametoinfo.h>
67 #include <arch.h>
68 #include <inttypes.h>
69 
70 #include <config.h>
71 
72 #define DEFAULT_STRNDX_SIZE 4096
73 
74 // Valid flags for msec_t->flags
75 #define FLAG_BSS 1
76 #define FLAG_NOBIT 2
77 #define FLAG_NOWRITE 4
78 #define FLAG_TEXT 8
79 
80 #define ifis(x) if(!strncmp(name, x, strlen(x)))
81 #define elis(x) else if(!strncmp(name, x, strlen(x)))
82 
83 #define MAXPADLEN 20
84 
85 #define EXTRA_CREATED_SECTIONS 4
86 
87 
88 #define RELOC_X86_64 1
89 #define RELOC_X86_32 2
90 
91 //#ifdef __x86_64__
92 #ifdef __LP64__ // Generic 64b
93 #define Elf_Ehdr Elf64_Ehdr
94 #define Elf_Shdr Elf64_Shdr
95 #define Elf_Sym Elf64_Sym
96 #define Elf_Addr Elf64_Addr
97 #define Elf_Sword Elf64_Sxword
98 #define Elf_Section Elf64_Half
99 #define ELF_ST_BIND ELF64_ST_BIND
100 #define ELF_ST_TYPE ELF64_ST_TYPE
101 #define Elf_Rel Elf64_Rel
102 #define Elf_Rela Elf64_Rela
103 #define ELF_R_SYM ELF64_R_SYM
104 #define ELF_R_TYPE ELF64_R_TYPE
105 #define ELF_R_INFO ELF64_R_INFO
106 #define Elf_Phdr Elf64_Phdr
107 #define Elf_Xword Elf64_Xword
108 #define Elf_Word Elf64_Word
109 #define Elf_Off Elf64_Off
110 #define ELFCLASS ELFCLASS64
111 #define ELFMACHINE EM_X86_64
112 #define CS_MODE CS_MODE_64
113 #define RELOC_MODE RELOC_X86_64
114 #else // Generic 32b
115 #define Elf_Ehdr Elf32_Ehdr
116 #define Elf_Shdr Elf32_Shdr
117 #define Elf_Sym Elf32_Sym
118 #define Elf_Addr Elf32_Addr
119 #define Elf_Sword Elf64_Sword
120 #define Elf_Section Elf32_Half
121 #define ELF_ST_BIND ELF32_ST_BIND
122 #define ELF_ST_TYPE ELF32_ST_TYPE
123 #define Elf_Rel Elf32_Rel
124 #define Elf_Rela Elf32_Rela
125 #define ELF_R_SYM ELF32_R_SYM
126 #define ELF_R_TYPE ELF32_R_TYPE
127 #define ELF_R_INFO ELF32_R_INFO
128 #define Elf_Phdr Elf32_Phdr
129 #define Elf_Xword Elf32_Xword
130 #define Elf_Word Elf32_Word
131 #define Elf_Off Elf32_Off
132 #define ELFCLASS ELFCLASS32
133 #define ELFMACHINE EM_386
134 #define CS_MODE CS_MODE_32
135 #define RELOC_MODE RELOC_X86_32
136 #endif
137 
138 
139 #define nullstr "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
140 unsigned int maxoldsec = 0, maxnewsec = 0;
141 unsigned int deltastrtab = 0;
142 
143 char *allowed_sections[] = {
144  ".rodata",
145  ".data",
146  ".text",
147  ".load",
148  ".strtab",
149  ".symtab",
150  ".comment",
151  ".note.GNU-stack",
152  ".rsrc",
153  ".bss",
154 // ".rela.plt",
155 // ".rela.dyn"
156 };
157 
158 char *blnames[] = {
159  "__init_array_start",
160  "__init_array_end",
161  "__libc_csu_init",
162  "__libc_csu_fini",
163  "__x86.get_pc_thunk.bx", // this is 32b only
164  ".bss",
165  ".comment",
166  ".data",
167  ".dynamic",
168  ".fini",
169  ".fini_array",
170  ".got",
171  ".got.plt",
172  ".init",
173  ".init_array",
174  ".jcr",
175  ".plt",
176  ".plt.got",
177  ".text",
178  "__GNU_EH_FRAME_HDR",
179  "__FRAME_END__",
180  ".interp",
181  ".note.ABI-tag",
182  ".note.gnu.build-id",
183  ".gnu.hash",
184  ".dynsym",
185  ".dynstr",
186  ".gnu.version",
187  ".gnu.version_r",
188  ".rela.dyn",
189  ".rela.plt",
190  ".rodata",
191  ".eh_frame_hdr",
192  ".eh_frame",
193  "_ITM_registerTMCloneTable",
194  "_ITM_deregisterTMClone",
195  "_ITM_deregisterTMCloneTab",
196  "_Jv_RegisterClasses",
197  "_ITM_registerTMCloneTa",
198  "__cxa_finalize",
199  "_DYNAMIC",
200  "_GLOBAL_OFFSET_TABLE_",
201  "__JCR_END__",
202  "__JCR_LIST__",
203  "__TMC_END__",
204  "__bss_start",
205  "__data_start",
206  "_IO_stdin_used",
207  "__do_global_dtors_aux",
208  "__do_global_dtors_aux_fini_array_entry",
209  "__dso_handle",
210  "__frame_dummy_init_array_entry",
211  "__libc_csu_fini",
212  "_edata",
213  "_end",
214  "_fini",
215  "__fini",
216  "_init",
217  "_start",
218  "data_start",
219  "deregister_tm_clones",
220  "frame_dummy",
221  "register_tm_clones",
222 //"__libc_start_main",
223  "__gmon_start__"
224 };
225 
229 typedef struct msec_t {
230  char *name;
231  unsigned long int len;
232  unsigned char *data;
233  char *outoffset;
234  unsigned int flags; // See above
235 
236  asection *s_bfd;
238 
239  struct msec_t *prev; // utlist.h
240  struct msec_t *next; // utlist.h
241 
242 } msec_t;
243 
244 
248 typedef struct mseg_t {
251  Elf_Off p_offset; // Segment file offset
252  Elf_Addr p_vaddr; // Segment virtual address
253  Elf_Addr p_paddr; // Segment physical address
254  Elf_Xword p_filesz; // Segment size in file
255  Elf_Xword p_memsz; // Segment size in memory
256  Elf_Xword p_align; // Segment alignment, file & memory
257 
258  struct msec_t *prev; // utlist.h
259  struct msec_t *next; // utlist.h
260 
261 } mseg_t;
262 
263 
264 typedef struct ctx_t {
265 
269  char *binname;
270  unsigned int archsz; // Architecture size (64 or 32)
271  unsigned int shnum;
272  unsigned int phnum; // Number of program headers
273  char *strndx; // pointer to section string table in memory
274  unsigned int strndx_len; // length of section string table in bytes
275  unsigned int strndx_index; // offset of sections string table in binary
276  unsigned int start_shdrs; // Offset of section headers in output binary
277  unsigned int start_phdrs; // Offset of Program headers in output binary
278  int fdout;
279  bfd *abfd;
280  unsigned int corefile; // 1 if file is a core file
281 
282 
283  unsigned int base_address; // VMA Address of first PT_LOAD segment in memory
284 
285  // Meta section headers (double linked list)
287  unsigned int mshnum;
288 
289  // Meta segment headers (double linked list)
291  unsigned int mphnum;
292 
293  unsigned int has_relativerelocations; // 1 if binary has relative relocations (R_X86_64_RELATIVE)
297  char *opt_binname;
298  char *opt_interp;
299  unsigned int opt_arch;
300  unsigned int opt_static;
301  unsigned int opt_reloc;
302  unsigned int opt_strip;
303  unsigned int opt_sstrip;
304  unsigned int opt_exec;
305  unsigned int opt_core;
306  unsigned int opt_shared;
307  unsigned int opt_verbose;
308  unsigned long int opt_entrypoint;
309  unsigned char opt_poison;
310  unsigned int opt_original;
311  unsigned int opt_debug;
312  unsigned int opt_asmdebug;
313  unsigned int opt_flags; // used in setting eabi
314 
315 } ctx_t;
316 
317 
318 
322 int craft_section(ctx_t * ctx, msec_t * m);
323 unsigned int secindex_from_name(ctx_t * ctx, const char *name);
324 msec_t *section_from_name(ctx_t * ctx, char *name);
325 msec_t *section_from_addr(ctx_t * ctx, unsigned long int addr);
326 int print_bfd_sections(ctx_t * ctx);
327 unsigned int secindex_from_name(ctx_t * ctx, const char *name);
328 msec_t *section_from_index(ctx_t * ctx, unsigned int index);
329 unsigned int secindex_from_name_after_strip(ctx_t * ctx, const char *name);
330 int analyze_text(ctx_t * ctx, char *data, unsigned int datalen,
331  unsigned long int addr);
332 int save_reloc(ctx_t * ctx, Elf_Rela * r, unsigned int sindex, int has_addend);
333 
334 
338 char *globalsymtab = 0;
340 unsigned int globalsymtableoffset = 0;
341 
342 char *globalstrtab = 0;
343 unsigned int globalstrtablen = 0;
344 unsigned int globalstrtableoffset = 0;
345 
346 unsigned int globalsymindex = 0;
347 
348 char *globalreloc = 0;
349 unsigned int globalreloclen = 0;
350 unsigned int globalrelocoffset = 0;
351 
352 unsigned long int mintext = -1;
353 unsigned long int maxtext = 0;
354 unsigned long int textvma = 0;
355 
356 unsigned long int mindata = -1;
357 unsigned long int maxdata = 0;
358 unsigned long int datavma = 0;
359 
360 unsigned long int orig_text = 0;
361 unsigned long int orig_sz = 0;
362 
366 static int parse_bfd_perm(int perm)
367 {
368  int heal_perm = 0;
369 
370  heal_perm |= (perm & SEC_CODE ? 1 : 0);
371  heal_perm |= (perm & SEC_DATA ? 2 : 0);
372  heal_perm |= (perm & SEC_ALLOC ? 4 : 0);
373  heal_perm = (perm & SEC_READONLY ? heal_perm : 4);
374 
375  return heal_perm;
376 }
377 
381 unsigned int protect_perms(unsigned int perms)
382 {
383  unsigned int memperms = 0;
384 
385  switch (perms) {
386  case 7:
387  memperms = PROT_READ | PROT_WRITE | PROT_EXEC;
388  break;
389  case 6:
390  memperms = PROT_READ;
391  break;
392  case 5:
393  memperms = PROT_READ | PROT_EXEC;
394  break;
395  case 4:
396  memperms = PROT_READ | PROT_WRITE;
397  break;
398  default:
399  memperms = 0;
400  break;
401  }
402  return memperms;
403 }
404 
405 struct symaddr {
406  struct symaddr *next;
407  char *name;
408  int addr;
409 } *symaddrs;
410 
411 
412 /*
413 typedef struct {
414  Elf_Word st_name;
415  unsigned char st_info;
416  unsigned char st_other;
417  Elf_Half st_shndx;
418  Elf_Addr st_value;
419  Elf_Xword st_size;
420 } Elf_Sym;
421 */
422 
423 void add_symaddr(ctx_t * ctx, const char *name, int addr, char symclass)
424 {
425 
426  struct symaddr *sa;
427  Elf_Sym *s = 0;
428  unsigned long int nameptr = 0;
429  unsigned int i;
430 
431  if (*name == '\0')
432  return;
433 
434  // search this address in symbol table : duplicates here trigger a NULL ptr dereference in ld
435  for (i = 0; i < globalsymtablen / sizeof(Elf_Sym); i++) {
436  s = (Elf_Sym *) (globalsymtab + i * sizeof(Elf_Sym));
437  //
438  if ((s->st_value == addr - textvma) && (s->st_value != 0)) {
439  return; // already in symtab
440  }
441  }
442 
443  // check if name is in blacklist
444  for (i = 0; i < sizeof(blnames) / sizeof(char *); i++) {
445  if ((strlen(name) == strlen(blnames[i]))
446  && (!strncmp(name, blnames[i], strlen(blnames[i])))) {
447  return;
448  }
449  }
450  sa = (struct symaddr *) malloc(sizeof(struct symaddr));
451  memset(sa, 0, sizeof(struct symaddr));
452  sa->name = strdup(name);
453  sa->addr = addr;
454  sa->next = symaddrs;
455  symaddrs = sa;
456 
457  if (ctx->opt_verbose) {
458  int pad;
459  pad = MAXPADLEN - strlen(sa->name);
460  if (pad < 0) {
461  pad = 0;
462  }
463 
464  printf("%s% *s\t\t%x\t\t%c\n", sa->name, pad, "", sa->addr, symclass);
465  }
466 
470  if (globalstrtab == 0) {
471  globalstrtab = calloc(1, strlen(sa->name) + 3);
472  globalstrtablen++; // Start with a null byte
473  } else {
474  globalstrtab =
475  realloc(globalstrtab, globalstrtablen + strlen(sa->name) + 2);
476  }
477  memcpy(globalstrtab + globalstrtablen, sa->name, strlen(sa->name) + 1);
478  nameptr = globalstrtablen;
479  globalstrtablen += strlen(sa->name) + 1;
480 
485  if (globalsymtab == 0) {
486  globalsymtab = calloc(1, sizeof(Elf_Sym) * 2);
487  globalsymtablen += sizeof(Elf_Sym); // Skip 1 NULL entry
488  } else {
489  globalsymtab = realloc(globalsymtab, sizeof(Elf_Sym) + globalsymtablen);
490  }
491 
493  s->st_name = nameptr;
494  s->st_size = 100; // default function size... (in bytes)
495  s->st_value = addr;
496  s->st_info = 0;
497  s->st_other = 0;
498  s->st_shndx = 0;
499 
500  switch (symclass) {
501  case 'T':
502  case 't':
503 
504  case 'C':
505  case 'c':
506 // s->st_value = addr;
507  ;
508  // adjust value from vma
509  msec_t *t = section_from_name(ctx, ".text");
510 // s->st_value -= t->s_elf->sh_addr;
511  if (ctx->opt_reloc) {
512  s->st_value -= t->s_bfd->vma;
513 //s->st_value -= orig_text;
514  s->st_shndx = 1; // index to .text
515  }
516  s->st_info = STT_FUNC;
517  break;
518 
519  case 'D':
520  case 'd':
521  case 'B':
522  case 'b':
523  case 'V':
524  case 'v':
525  ;
526 // adjust value from vma
527 // msec_t *t2 = section_from_addr(ctx, s->st_value);
528 // s->st_value -= t2->s_bfd->vma;
529 
530  s->st_info = STT_OBJECT;
531  break;
532 
533  case 'A':
534  case 'a':
535  s->st_info = STT_FILE;
536  break;
537 
538  case 'R':
539  case 'r':
540  s->st_size = 0;
541  s->st_info = STT_SECTION;
542  break;
543 
544  default:
545  break;
546  }
547 
548 
549  if (isupper(symclass)) {
550  s->st_info += 0x10;
551  }
552 
553 
554  globalsymtablen += sizeof(Elf_Sym);
555  return;
556 }
557 
562 {
563  add_symaddr(ctx, "old_plt", textvma, 0x54);
564  add_symaddr(ctx, "old_text", orig_text, 0x54);
565  add_symaddr(ctx, "old_text_end", orig_text + maxtext - mintext, 0x54);
566 
567  return 0;
568 }
569 
574 int rd_symbols(ctx_t * ctx)
575 {
576  long storage_needed;
577  asymbol **symbol_table = NULL;
578  long number_of_symbols;
579  long i;
580  int ret = 0;
581 
582  const char *sym_name;
583  int symclass;
584  int sym_value;
585 
586  if (ctx->opt_verbose) {
587  printf("\n\n -- Reading symbols\n\n");
588  printf(" Symbol\t\t\t\taddress\t\tclass\n");
589  printf(" -----------------------------------------------------\n");
590  }
591 
595  storage_needed = bfd_get_symtab_upper_bound(ctx->abfd);
596  if (storage_needed < 0) {
597  bfd_perror("warning: bfd_get_symtab_upper_bound");
598  ret = 0;
599  goto dynsym;
600  }
601  if (storage_needed == 0) {
602  fprintf(stderr, "warning: no symbols\n");
603  goto dynsym;
604  }
605  symbol_table = (asymbol **) malloc(storage_needed);
606  number_of_symbols = bfd_canonicalize_symtab(ctx->abfd, symbol_table);
607  if (number_of_symbols < 0) {
608  bfd_perror("warning: bfd_canonicalize_symtab");
609  ret = 0;
610  goto dynsym;
611  }
612  for (i = 0; i < number_of_symbols; i++) {
613  asymbol *asym = symbol_table[i];
614  sym_name = bfd_asymbol_name(asym);
615  symclass = bfd_decode_symclass(asym);
616  sym_value = bfd_asymbol_value(asym);
617  if (*sym_name == '\0') {
618  continue;
619  }
620  if (bfd_is_undefined_symclass(symclass)) {
621  continue;
622  }
623 
624  if (!ctx->opt_strip) { // process additional symbols from symbol table
625  add_symaddr(ctx, sym_name, sym_value, symclass);
626  }
627  }
628 
632 dynsym:
633  if (symbol_table) {
634  free(symbol_table);
635  }
636  symbol_table = NULL;
637 
638  storage_needed = bfd_get_dynamic_symtab_upper_bound(ctx->abfd);
639  if (storage_needed < 0) {
640  bfd_perror("warning: bfd_get_dynamic_symtab_upper_bound");
641  ret = 0;
642  goto out;
643  }
644  if (storage_needed == 0) {
645  fprintf(stderr, "warning: no symbols\n");
646  goto out;
647  }
648  symbol_table = (asymbol **) malloc(storage_needed);
649  number_of_symbols = bfd_canonicalize_dynamic_symtab(ctx->abfd, symbol_table);
650  if (number_of_symbols < 0) {
651  bfd_perror("warning: bfd_canonicalize_symtab");
652  ret = 0;
653  goto dynsym;
654  }
655  for (i = 0; i < number_of_symbols; i++) {
656  asymbol *asym = symbol_table[i];
657  sym_name = bfd_asymbol_name(asym);
658  symclass = bfd_decode_symclass(asym);
659  sym_value = bfd_asymbol_value(asym);
660  if (*sym_name == '\0') {
661  continue;
662  }
663  if (bfd_is_undefined_symclass(symclass)) {
664  continue;
665  }
666  }
667 out:
668  if (symbol_table) {
669  free(symbol_table);
670  }
671 
672  if (ctx->opt_verbose) {
673  printf("\n");
674  }
675 
676  return ret;
677 }
678 
682 int entszfromname(const char *name)
683 {
684  unsigned int i = 0;
685 
686  for (i = 0; i < sizeof(nametosize) / sizeof(assoc_nametosz_t); i++) {
687  if (!strncmp(nametosize[i].name, name, strlen(name))) {
688  return nametosize[i].sz;
689  }
690  }
691  return 0;
692 }
693 
697 unsigned int max(unsigned int a, unsigned int b)
698 {
699  return a < b ? b : a;
700 }
701 
706 {
707  msec_t *s;
708 
709  DL_FOREACH(ctx->mshdrs, s) {
710  if (!strncmp(s->name, name, max(strlen(name), strlen(s->name)))) {
711  return s;
712  }
713  }
714  return 0;
715 }
716 
720 msec_t *section_from_addr(ctx_t * ctx, unsigned long int addr)
721 {
722  msec_t *s;
723 
724  DL_FOREACH(ctx->mshdrs, s) {
725  if ((s->s_bfd->vma) && (s->s_bfd->vma <= addr)
726  && (s->s_bfd->vma + s->s_bfd->size > addr)) {
727  return s;
728  }
729  }
730  return 0;
731 }
732 
736 msec_t *section_from_index(ctx_t * ctx, unsigned int index)
737 {
738  msec_t *s;
739  unsigned int i = 1; // We count from 1
740  DL_FOREACH(ctx->mshdrs, s) {
741  if (index == i) {
742  return s;
743  }
744  i++;
745  }
746  return 0;
747 }
748 
749 
753 unsigned int secindex_from_name(ctx_t * ctx, const char *name)
754 {
755  msec_t *s;
756  unsigned int i = 1; // We count from 1
757 
758  DL_FOREACH(ctx->mshdrs, s) {
759  if (!strncmp(s->name, name, max(strlen(name), strlen(s->name)))) {
760  return i;
761  }
762  i++;
763  }
764  return 0;
765 }
766 
770 unsigned int secindex_from_name_after_strip(ctx_t * ctx, const char *name)
771 {
772  msec_t *s;
773  unsigned int i = 1; // We count from 1
774  unsigned int j;
775 
776  DL_FOREACH(ctx->mshdrs, s) {
777  if (!strncmp(s->name, name, max(strlen(name), strlen(s->name)))) {
778  return i;
779  }
780 
781  for (j = 0; j < sizeof(allowed_sections) / sizeof(char *); j++) {
782  if (!strncmp(s->name, allowed_sections[j], strlen(allowed_sections[j]))) {
783  i++; // Ok, this section is allowed
784  break;
785  }
786  }
787  }
788  return 0;
789 }
790 
791 char *sec_name_from_index_after_strip(ctx_t * ctx, unsigned int index)
792 {
793 
794  msec_t *s;
795  unsigned int i = 0;
796  unsigned int j;
797 
798  DL_FOREACH(ctx->mshdrs, s) {
799 
800  for (j = 0; j < sizeof(allowed_sections) / sizeof(char *); j++) {
801  if (!strncmp(s->name, allowed_sections[j], strlen(allowed_sections[j]))) {
802  i++; // Ok, this section is allowed
803  break;
804  }
805  }
806 
807  if (i == index) {
808  return s->name;
809  }
810 
811  }
812 
813  return NULL;
814 }
815 
816 
820 int link_from_name(ctx_t * ctx, const char *name)
821 {
822  unsigned int i = 0;
823  char *destsec = 0;
824  unsigned int d = 0;
825 
826  for (i = 0; i < sizeof(nametolink) / sizeof(assoc_nametolink_t); i++) {
827  if (!strncmp(nametolink[i].name, name, strlen(name))) {
828  destsec = nametolink[i].dst;
829  }
830  }
831 
832  if (!destsec) {
833  return 0;
834  }
835 
836  d = secindex_from_name(ctx, destsec);
837  return d;
838 }
839 
843 int info_from_name(ctx_t * ctx, const char *name)
844 {
845  unsigned int i = 0;
846  char *destsec = 0;
847  unsigned int d = 0;
848 
849  for (i = 0; i < sizeof(nametoinfo) / sizeof(assoc_nametoinfo_t); i++) {
850  if (!strncmp(nametoinfo[i].name, name, strlen(name))) {
851  destsec = nametoinfo[i].dst;
852  }
853  }
854 
855  if (!destsec) {
856  return 0;
857  }
858 
859  d = secindex_from_name(ctx, destsec);
860  return d;
861 }
862 
866 int typefromname(const char *name)
867 {
868  unsigned int i = 0;
869 
870  for (i = 0; i < sizeof(nametotype) / sizeof(assoc_nametotype_t); i++) {
871  if (!strncmp(nametotype[i].name, name, strlen(name))) {
872  return nametotype[i].type;
873  }
874  }
875  return SHT_PROGBITS;
876 }
877 
881 unsigned int alignfromname(const char *name)
882 {
883  unsigned int i = 0;
884 
885  for (i = 0; i < sizeof(nametoalign) / sizeof(assoc_nametoalign_t); i++) {
886  if (!strncmp(nametoalign[i].name, name, strlen(name))) {
887  return nametoalign[i].alignment;
888  }
889  }
890  return 8;
891 }
892 
896 unsigned int ptype_from_section(msec_t * ms)
897 {
898  // Return type based on section name
899 
900  if (!strncmp(ms->name, ".interp", 7)) {
901  return PT_INTERP;
902  }
903 
904  if (!strncmp(ms->name, ".dynamic", 8)) {
905  return PT_DYNAMIC;
906  }
907 
908  if (!strncmp(ms->name, ".eh_frame_hdr", 13)) {
909  return PT_GNU_EH_FRAME;
910  }
911 
912  switch (ms->s_elf->sh_type) {
913  case SHT_NULL:
914  return PT_NULL;
915  case SHT_PROGBITS:
916  return PT_LOAD;
917  case SHT_NOTE:
918  return PT_NOTE;
919  case SHT_DYNAMIC:
920  return PT_DYNAMIC;
921  case SHT_SYMTAB:
922  case SHT_STRTAB:
923  case SHT_RELA:
924  case SHT_HASH:
925  case SHT_NOBITS:
926  case SHT_REL:
927  case SHT_SHLIB:
928  case SHT_DYNSYM:
929  case SHT_NUM:
930  case SHT_LOSUNW:
931  case SHT_GNU_verdef:
932  case SHT_GNU_verneed:
933  case SHT_GNU_versym:
934  default:
935  break;
936  }
937  return PT_LOAD;
938 }
939 
943 unsigned int pflag_from_section(msec_t * ms)
944 {
945  unsigned int dperms = 0;
946  dperms = 0;
947 
948  switch (ms->s_elf->sh_flags) {
949  case SHF_ALLOC | SHF_WRITE | SHF_EXECINSTR:
950  dperms = PF_R | PF_W | PF_X; // "rwx";
951  break;
952  case SHF_ALLOC:
953  dperms = PF_R; //"r--";
954  break;
955  case SHF_ALLOC | SHF_EXECINSTR:
956  dperms = PF_R | PF_X; // "r-x";
957  break;
958  case SHF_ALLOC | SHF_WRITE:
959  dperms = PF_R | PF_W; // "rw-"
960  break;
961  default:
962  dperms = 0; // "---"
963  break;
964  }
965  return dperms;
966 }
967 
972 {
973  if (a->p_type != b->p_type) {
974  return a->p_type - b->p_type;
975  } // Sort by type
976  return a->p_vaddr - b->p_vaddr; // else by vma
977 }
978 
982 int phdr_cmp(mseg_t * a, mseg_t * b)
983 {
984  return a->p_vaddr - b->p_vaddr; // This is correct, see elf.pdf
985 }
986 
991 int sort_phdrs(ctx_t * ctx)
992 {
993  DL_SORT(ctx->mphdrs, phdr_cmp);
994  return 0;
995 }
996 
1001 {
1002  DL_SORT(ctx->mphdrs, phdr_cmp_premerge);
1003  return 0;
1004 }
1005 
1010 {
1011  mseg_t *p;
1012  Elf_Shdr *s;
1013 
1014  s = ms->s_elf;
1015  p = calloc(1, sizeof(mseg_t));
1016 
1017  p->p_type = ptype_from_section(ms);
1018  p->p_flags = pflag_from_section(ms);
1019  p->p_offset = s->sh_offset;
1020  p->p_vaddr = s->sh_addr;
1021  p->p_paddr = s->sh_addr;
1022  p->p_filesz = s->sh_size;
1023  p->p_memsz = s->sh_size;
1024  p->p_align = s->sh_addralign;
1025 
1026  return p;
1027 }
1028 
1033 {
1034  msec_t *ms, *tmp;
1035  mseg_t *p = 0;
1036 
1037  DL_FOREACH_SAFE(ctx->mshdrs, ms, tmp) {
1038 
1039  p = alloc_phdr(ms);
1040 
1041  if (p->p_type == PT_LOAD) {
1042  unsigned int r = 0; // reminder
1043  p->p_align = 0x200000;
1044  // We need to align segment p_vaddr - p_offset on page boundaries
1045  r = (p->p_vaddr - p->p_offset) % 4096;
1046  p->p_vaddr -= r; // Adjust initial address
1047  p->p_paddr -= r; // Adjust initial address
1048  p->p_filesz += r; // Adjust size
1049  p->p_memsz += r; // Adjust size
1050  }
1051 
1052  if (p->p_flags) {
1053  // Add to linked list of segments
1054  DL_APPEND(ctx->mphdrs, p);
1055  ctx->mphnum++;
1056  ctx->phnum++;
1057  } else {
1058  // Sections not mapped have no segment
1059  free(p);
1060  }
1061  }
1062  return 0;
1063 }
1064 
1073 int merge_phdrs(ctx_t * ctx)
1074 {
1075  mseg_t *ms, *n;
1076 retry:
1077  ms = ctx->mphdrs;
1078  while (ms) {
1079  if (ms->next) {
1080  n = (mseg_t *) ms->next;
1081  if (ms->p_flags != n->p_flags) {
1082  goto skipseg;
1083  }
1084  if (ms->p_type != n->p_type) {
1085  goto skipseg;
1086  }
1087  // merge sections into the first one :
1088  // extend section
1089  ms->p_filesz = n->p_filesz + (n->p_offset - ms->p_offset);
1090  ms->p_memsz = ms->p_memsz + (n->p_offset - ms->p_offset);
1091  // unlink deleted section from double linked list
1092  if (n->next) {
1093  n->next->prev = (void *) ms;
1094  }
1095  ms->next = n->next;
1096  free(n);
1097  ctx->mphnum--;
1098  ctx->phnum--;
1099  goto retry;
1100 
1101  }
1102  skipseg:
1103  ms = (mseg_t *) ms->next;
1104  }
1105  return 0;
1106 }
1107 
1109 {
1110  mseg_t *ms;
1111 
1112  // find base address (first allocated PT_LOAD chunk)
1113  ms = ctx->mphdrs;
1114  while (ms) {
1115  if ((ms->p_type == PT_LOAD) && (ms->p_flags == (PF_R))) {
1116  if (ctx->base_address > (ms->p_vaddr & ~0xfff)) {
1117  ctx->base_address = ms->p_vaddr & ~0xfff;
1118  }
1119  }
1120  ms = (mseg_t *) ms->next;
1121  }
1122 
1123  if (ctx->base_address == 0) {
1124  ctx->base_address = ctx->mphdrs->p_vaddr & ~0xfff;
1125  }
1126 
1127  if (ctx->opt_debug) {
1128  printf("\n * first loadable segment at: 0x%x\n", ctx->base_address);
1129  }
1130  // patch load address of first chunk PT_LOAD allocated RX
1131  ms = ctx->mphdrs;
1132  while (ms) {
1133  if ((ms->p_type == PT_LOAD) && (ms->p_flags == (PF_R | PF_X))) {
1134  if (ctx->opt_debug) {
1135  printf
1136  (" -- patching base load address of first PT_LOAD Segment: %lu -->> %u\n",
1137  ms->p_vaddr, ctx->base_address);
1138  }
1139  ms->p_vaddr = ctx->base_address;
1140  ms->p_paddr = ctx->base_address;
1141  ms->p_memsz += ms->p_offset;
1142  ms->p_filesz += ms->p_offset;
1143  ms->p_offset = 0;
1144  break;
1145  }
1146  ms = (void *) ms->next;
1147  }
1148  return 0;
1149 }
1150 
1154 static unsigned int rd_phdrs(ctx_t * ctx)
1155 {
1156  struct stat sb;
1157  char *p;
1158  int fdin;
1159  Elf_Ehdr *e = 0;
1160  unsigned int i = 0;
1161  int nread;
1162  Elf_Phdr *phdr, *eph;
1163 
1164  if (stat(ctx->binname, &sb) == -1) {
1165  perror("stat");
1166  exit(EXIT_FAILURE);
1167  }
1168 
1169  p = calloc(1, sb.st_size);
1170  fdin = open(ctx->binname, O_RDONLY);
1171  if (fdin <= 0) {
1172  perror("open");
1173  exit(-1);
1174  }
1175  nread = read(fdin, p, sb.st_size);
1176  if (nread != sb.st_size) {
1177  perror("read");
1178  exit(EXIT_FAILURE);
1179  }
1180  close(fdin);
1181 
1182  printf(" -- read: %u bytes\n", nread);
1183 
1184  e = (Elf_Ehdr *) p;
1185  phdr = (Elf_Phdr *) (p + e->e_phoff);
1186  eph = phdr + e->e_phnum;
1187  for (; phdr < eph; phdr++) {
1188  // Add to linked list
1189 
1190  // Create Meta section
1191  mseg_t *ms = calloc(1, sizeof(mseg_t));
1192  if (!ms) {
1193  perror("calloc");
1194  exit(EXIT_FAILURE);
1195  }
1196 
1197  memcpy(ms, phdr, sizeof(Elf_Phdr));
1198 
1199  // Add to double linked list of msec_t Meta sections
1200  DL_APPEND(ctx->mphdrs, ms);
1201  ctx->mphnum++;
1202  ctx->phnum++;
1203  i++;
1204  }
1205 
1206  printf(" -- Original: %u\n", i);
1207  return 0;
1208 }
1209 
1213 static unsigned int mk_phdrs(ctx_t * ctx)
1214 {
1218  create_phdrs(ctx);
1219 
1223  sort_phdrs_premerge(ctx);
1224 
1228  merge_phdrs(ctx);
1229 
1230  sort_phdrs(ctx);
1231 
1232  adjust_baseaddress(ctx);
1233 
1234  sort_phdrs(ctx); // Need to resort after patching
1235  merge_phdrs(ctx);
1236  sort_phdrs(ctx); // Need to resort after patching
1237 
1238  return 0;
1239 }
1240 
1244 static unsigned int write_phdrs(ctx_t * ctx)
1245 {
1246  unsigned int tmpm = 0;
1247 
1248  // Goto end of file, align on 8 bytes boundaries
1249  tmpm = lseek(ctx->fdout, 0x00, SEEK_END);
1250  write(ctx->fdout, nullstr, 20);
1251  if ((tmpm % 8) == 0) {
1252  tmpm += 8;
1253  }
1254  tmpm &= ~0xf;
1255  tmpm += sizeof(Elf_Phdr); // Prepend NULL section
1256  ftruncate(ctx->fdout, tmpm);
1257 
1258  ctx->start_phdrs = lseek(ctx->fdout, 0x00, SEEK_END);
1259 
1260  ctx->phnum += 2;
1261 
1262  if (ctx->opt_verbose) {
1263  printf(" -- Writting %u segment headers\n", ctx->phnum);
1264  }
1265  // first entry is the program header itself
1266  Elf_Phdr *phdr = calloc(1, sizeof(Elf_Phdr));
1267  phdr->p_vaddr = ctx->base_address;
1268  phdr->p_paddr = ctx->base_address;
1269  phdr->p_type = PT_PHDR;
1270  phdr->p_offset = ctx->start_phdrs;
1271  phdr->p_flags = 5;
1272  phdr->p_filesz = ctx->phnum * sizeof(Elf_Phdr);
1273  phdr->p_memsz = ctx->phnum * sizeof(Elf_Phdr);
1274  phdr->p_align = 8;
1275  write(ctx->fdout, phdr, sizeof(Elf_Phdr));
1276 
1277  // Copy all the Phdrs
1278  mseg_t *p;
1279  DL_FOREACH(ctx->mphdrs, p) {
1280  write(ctx->fdout, p, sizeof(Elf_Phdr));
1281  }
1282 
1283  // Append a Program Header for the stack
1284  phdr->p_vaddr = 0;
1285  phdr->p_paddr = 0;
1286  phdr->p_type = PT_GNU_STACK;
1287  phdr->p_offset = 0;
1288  phdr->p_flags = 3;
1289  phdr->p_filesz = 0;
1290  phdr->p_memsz = 0;
1291  phdr->p_align = 0x10;
1292  write(ctx->fdout, phdr, sizeof(Elf_Phdr));
1293 
1294  return ctx->start_phdrs;
1295 }
1296 
1297 
1301 static unsigned int write_phdrs_original(ctx_t * ctx)
1302 {
1303  unsigned int tmpm = 0;
1304 
1305  // Goto end of file, align on 8 bytes boundaries
1306  tmpm = lseek(ctx->fdout, 0x00, SEEK_END);
1307  write(ctx->fdout, nullstr, 20);
1308  if ((tmpm % 8) == 0) {
1309  tmpm += 8;
1310  }
1311  tmpm &= ~0xf;
1312 
1313  ftruncate(ctx->fdout, tmpm);
1314 
1315  ctx->start_phdrs = lseek(ctx->fdout, 0x00, SEEK_END);
1316 
1317  mseg_t *p;
1318  unsigned int i = 0;
1319  DL_FOREACH(ctx->mphdrs, p) {
1320  if (i == 0) { // First Phdr is the Program Header itself
1321  p->p_offset = ctx->start_phdrs; // Patch offset of Program header
1322  i = 1;
1323  }
1324  write(ctx->fdout, p, sizeof(Elf_Phdr));
1325  }
1326  return ctx->start_phdrs;
1327 }
1328 
1329 
1331 {
1332  msec_t *ms;
1333 
1334  // allocate memory
1335  ms = calloc(1, sizeof(msec_t));
1336  if (!ms) {
1337  perror("calloc");
1338  exit(EXIT_FAILURE);
1339  }
1340 
1341  ms->s_elf = calloc(1, sizeof(Elf_Shdr));
1342  if (!ms->s_elf) {
1343  perror("calloc");
1344  exit(EXIT_FAILURE);
1345  }
1346 
1347  return ms;
1348 }
1349 
1350 
1351 
1352 static int write_strtab_and_reloc(ctx_t * ctx)
1353 {
1354 
1355  unsigned int tmpm = 0;
1356 
1357  if (ctx->opt_debug) {
1358  printf(" * .strtab length:\t\t\t%u\n", globalstrtablen);
1359  printf(" * .symtab length:\t\t\t%u\n", globalsymtablen);
1360  }
1361  // Goto end of file
1362  tmpm = lseek(ctx->fdout, 0x00, SEEK_END);
1363  write(ctx->fdout, nullstr, 20);
1364  // align on 8 bytes boundaries
1365  if ((tmpm % 8) == 0) {
1366  tmpm += 8;
1367  };
1368  tmpm &= ~0xf;
1369  // truncate
1370  ftruncate(ctx->fdout, tmpm);
1371 
1372  // write relocations to binary
1373  tmpm = lseek(ctx->fdout, 0x00, SEEK_END);
1374  globalrelocoffset = tmpm;
1375  write(ctx->fdout, globalreloc, globalreloclen);
1376 
1377  // write string table to binary
1378  tmpm = lseek(ctx->fdout, 0x00, SEEK_END);
1379  globalstrtableoffset = tmpm;
1380  write(ctx->fdout, globalstrtab, globalstrtablen);
1381 
1382  // write symbol table to binary
1383  tmpm = lseek(ctx->fdout, 0x00, SEEK_END);
1384  globalsymtableoffset = tmpm;
1385  write(ctx->fdout, globalsymtab, globalsymtablen);
1386 
1387  return 0;
1388 }
1389 
1390 
1391 char *reloc_htype_x86_64(int thetype)
1392 {
1393 
1394  char *htype;
1395 
1396  switch (thetype) {
1397  case R_X86_64_NONE:
1398  htype = "R_X86_64_NONE";
1399  break;
1400 
1401  case R_X86_64_64:
1402  htype = "R_X86_64_64";
1403  break;
1404 
1405  case R_X86_64_32:
1406  htype = "R_X86_64_32";
1407  break;
1408 
1409  case R_X86_64_32S:
1410  htype = "R_X86_64_32S";
1411  break;
1412 
1413  case R_X86_64_PC32:
1414  htype = "R_X86_64_PC32";
1415  break;
1416 
1417  case R_X86_64_GOT32:
1418  htype = "R_X86_64_GOT32";
1419  break;
1420 
1421  case R_X86_64_PLT32:
1422  htype = "R_X86_64_PLT32";
1423  break;
1424 
1425  case R_X86_64_COPY:
1426  htype = "R_X86_64_COPY";
1427  break;
1428 
1429  case R_X86_64_GLOB_DAT:
1430  htype = "R_X86_64_GLOB_DAT";
1431  break;
1432 
1433  case R_X86_64_JUMP_SLOT:
1434  htype = "R_X86_64_JUMP_SLOT";
1435  break;
1436 
1437  case R_X86_64_RELATIVE:
1438  htype = "R_X86_64_RELATIVE";
1439  break;
1440 
1441  case R_X86_64_GOTPCREL:
1442  htype = "R_X86_64_GOTPCREL";
1443  break;
1444 
1445  case R_X86_64_16:
1446  htype = "R_X86_64_16";
1447  break;
1448 
1449  case R_X86_64_PC16:
1450  htype = "R_X86_64_PC16";
1451  break;
1452 
1453  case R_X86_64_8:
1454  htype = "R_X86_64_8";
1455  break;
1456 
1457  case R_X86_64_PC8:
1458  htype = "R_X86_64_PC8";
1459  break;
1460 
1461  case R_X86_64_NUM:
1462  htype = "R_X86_64_NUM";
1463  break;
1464 
1465  default:
1466  htype = "Unknown";
1467  break;
1468  }
1469 
1470  return htype;
1471 }
1472 
1473 
1474 char *reloc_htype_x86_32(int thetype)
1475 {
1476  char *htype;
1477 
1478  switch (thetype) {
1479  case R_386_NONE:
1480  htype = "R_386_NONE";
1481  break;
1482 
1483  case R_386_32:
1484  htype = "R_386_32";
1485  break;
1486 
1487  case R_386_PC32:
1488  htype = "R_386_PC32";
1489  break;
1490 
1491  case R_386_GOT32:
1492  htype = "R_386_GOT32";
1493  break;
1494 
1495  case R_386_PLT32:
1496  htype = "R_386_PLT32";
1497  break;
1498 
1499  case R_386_COPY:
1500  htype = "R_386_COPY";
1501  break;
1502 
1503  case R_386_GLOB_DAT:
1504  htype = "R_386_GLOB_DAT";
1505  break;
1506 
1507  case R_386_JMP_SLOT:
1508  htype = "R_386_JMP_SLOT";
1509  break;
1510 
1511  case R_386_RELATIVE:
1512  htype = "R_386_RELATIVE";
1513  break;
1514 
1515  case R_386_GOTOFF:
1516  htype = "R_386_GOTOFF";
1517  break;
1518 
1519  case R_386_GOTPC:
1520  htype = "R_386_GOTPC";
1521  break;
1522 
1523  case R_386_NUM:
1524  htype = "R_386_NUM";
1525  break;
1526 
1527  default:
1528  htype = "Unknown";
1529  break;
1530  }
1531 
1532  return htype;
1533 }
1534 
1535 char *reloc_htype(int thetype)
1536 {
1537  switch (RELOC_MODE) {
1538  case RELOC_X86_64:
1539  return reloc_htype_x86_64(thetype);
1540  case RELOC_X86_32:
1541  return reloc_htype_x86_32(thetype);
1542  default:
1543  return "UNKNOWN_RELOCATION";
1544  break;
1545  }
1546 }
1547 
1551 static int parse_reloc(ctx_t * ctx, msec_t * s)
1552 {
1553 
1554  Elf_Shdr *shdr;
1555  Elf_Rela *r;
1556  unsigned int sz;
1557  unsigned int i;
1558  char *htype = 0;
1559  unsigned int sindex = 0;
1560 
1561  unsigned int has_addend = 0;
1562 
1563  shdr = s->s_elf;
1564  sz = shdr->sh_size;
1565 
1566  has_addend = (shdr->sh_type == SHT_RELA) ? 1 : 0; // SHT_RELA has addends, SHT_REL doesn't
1567 
1568  if ((shdr->sh_type == SHT_RELA)
1569  && (shdr->sh_entsize != entszfromname(".rela.dyn"))) {
1570  printf("warning: strange relocation size: %lu != %u in %s\n",
1571  shdr->sh_entsize, entszfromname(".rela.dyn"), s->name);
1572  return -1;
1573  }
1574 
1575  if ((shdr->sh_type == SHT_REL)
1576  && (shdr->sh_entsize != entszfromname(".rel.dyn"))) {
1577  printf("warning: strange relocation size: %lu != %u in %s\n",
1578  shdr->sh_entsize, entszfromname(".rel.dyn"), s->name);
1579  return -1;
1580  }
1581 
1582  if ((shdr->sh_type == SHT_RELA)
1583  && (shdr->sh_size % entszfromname(".rela.dyn"))) {
1584  printf
1585  ("warning: strange relocation section size: %lu not a multiple of %u in %s\n",
1586  shdr->sh_size, entszfromname(".rela.dyn"), s->name);
1587  return -1;
1588  }
1589 
1590  if ((shdr->sh_type == SHT_REL) && (shdr->sh_size % entszfromname(".rel.dyn"))) {
1591  printf
1592  ("warning: strange relocation section size: %lu not a multiple of %u in %s\n",
1593  shdr->sh_size, entszfromname(".rel.dyn"), s->name);
1594  return -1;
1595  }
1596 
1597  if (ctx->opt_verbose) {
1598  printf("\t%s\tsize:%u\t%lu relocations\n", s->name, sz,
1599  sz / shdr->sh_entsize);
1600  }
1601 
1602  for (i = 0; i < sz / shdr->sh_entsize; i++) {
1603  r = s->data + i * shdr->sh_entsize;
1604 
1605  htype = reloc_htype(ELF_R_TYPE(r->r_info));
1606 
1607  if (ELF_R_TYPE(r->r_info) == R_X86_64_RELATIVE) {
1608  if (ctx->opt_debug) {
1609  printf("reloc[%u] %016lx\t%lu\t%s\t%u\taddend:%lx\t\n", i, r->r_offset,
1610  r->r_info, htype, sindex, r->r_addend);
1611  printf(" * Skipping relative relocation\n");
1612  }
1613  ctx->has_relativerelocations = 1; // Binary has relative relocations
1614  continue; // Do not save relocation for R_X86_64_RELATIVE
1615  } else {
1616  sindex = ELF_R_SYM(r->r_info);
1617 
1618  sindex += maxnewsec; // account for section references at top of symbol table
1619 
1620  // write back sindex in symtab
1621  ELF_R_INFO(sindex, ELF_R_TYPE(r->r_info));
1622  }
1623 
1624  if (ctx->opt_verbose) {
1625  printf("reloc[%u] %016lx\t%lu\t%s\t%u\taddend:%lu\t\n", i, r->r_offset,
1626  r->r_info, htype, sindex, r->r_addend);
1627  }
1628 
1629  save_reloc(ctx, r, sindex, has_addend);
1630  }
1631 
1632  if (ctx->opt_verbose) {
1633  printf("\n");
1634  }
1635  return 0;
1636 }
1637 
1639 {
1640 
1641  char *sname = 0;
1642  Elf_Sym *s;
1643  unsigned int i, sindex;
1644 
1645  if (!globalsymtab) {
1646  return 0;
1647  }
1648 
1649  if (!globalstrtab) {
1650  return 0;
1651  }
1652 
1653  if (ctx->opt_debug) {
1654  printf("\n -- Fixing strtab and symtab with delta of %u\n\n", deltastrtab);
1655  }
1656 
1657  for (sindex = maxnewsec + 1; sindex < (globalsymtablen / sizeof(Elf_Sym));
1658  sindex++) {
1659 
1660  // get symbol name from index
1661  s = globalsymtab + sindex * sizeof(Elf_Sym);
1662 
1663  s->st_name += deltastrtab; // fix symbol name offset in symbol table
1664 
1668  for (i = 0; i < sizeof(blnames) / sizeof(char *); i++) {
1669  sname = (char *) (globalstrtab + s->st_name);
1670  if ((s->st_name < globalstrtablen)
1671  && (strlen(sname) == strlen(blnames[i]))
1672  && (!strncmp(sname, blnames[i], strlen(blnames[i])))) {
1673  if (ctx->opt_debug) {
1674  printf(" * name blacklisted: %s at index %u\n", sname, sindex);
1675  }
1676  // generate new symbol name from old one
1677 
1678  globalstrtab =
1679  realloc(globalstrtab, globalstrtablen + strlen(sname) + 5);
1680  sprintf(globalstrtab + globalstrtablen, "old_%s", sname);
1681  s->st_name = globalstrtablen;
1682  globalstrtablen += strlen(globalstrtab + globalstrtablen) + 1;
1683 
1684  // change type and link information
1685  s->st_info = ELF64_ST_INFO(STB_WEAK, STT_NOTYPE);
1686  s->st_shndx = 0;
1687  }
1688  }
1689  }
1690  return 0;
1691 }
1692 
1693 
1694 int fixup_text(ctx_t * ctx)
1695 {
1696  msec_t *s;
1697 
1698  if (ctx->opt_debug) {
1699  printf(" -- Fixup .text\n\n");
1700  }
1701 
1702  DL_FOREACH(ctx->mshdrs, s) {
1703  if (!strncmp(s->name, ".text", 6)) {
1704  unsigned int newsz = datavma - textvma + maxdata - mindata;
1705  if (ctx->opt_debug) {
1706  printf
1707  (" * .text section found, increasing size from 0x%lx to 0x%x (0x%lx)\n",
1708  s->s_elf->sh_size, newsz, s->len);
1709  }
1710  s->s_elf->sh_size = newsz;
1711  // extend data
1712  s->data = realloc(s->data, newsz);
1713  // pad
1714  memset(s->data + s->len, 0x00, newsz - s->len);
1715  s->s_elf->sh_offset = orig_sz;
1716  s->outoffset = orig_sz;
1717  // extend output file
1718  ftruncate(ctx->fdout, s->outoffset + s->s_elf->sh_size);
1719  s->len = newsz;
1720  break;
1721  }
1722  }
1723  return 0;
1724 }
1725 
1729 static unsigned int parse_relocations(ctx_t * ctx)
1730 {
1731  msec_t *s;
1732 
1733  if (ctx->opt_verbose) {
1734  printf("\n -- Parsing existing relocations\n\n");
1735  }
1736  DL_FOREACH(ctx->mshdrs, s) {
1737  if ((s->s_elf) && (s->s_elf->sh_type == SHT_RELA)) { // relocations with addends
1738  parse_reloc(ctx, s);
1739  } else if ((s->s_elf) && (s->s_elf->sh_type == SHT_REL)) { // relocations without addends
1740  parse_reloc(ctx, s);
1741  }
1742  }
1743 
1744  if (ctx->opt_verbose) {
1745  printf("\n");
1746  }
1747 
1748  return 0;
1749 }
1750 
1751 
1755 unsigned int append_sym(Elf_Sym * s)
1756 {
1757 
1758  if (globalsymtab == 0) {
1759  globalsymtab = calloc(1, sizeof(Elf_Sym) * 2);
1760  globalsymtablen += sizeof(Elf_Sym); // Skip 1 NULL entry
1761  } else {
1762  globalsymtab = realloc(globalsymtab, sizeof(Elf_Sym) + globalsymtablen);
1763  }
1764 
1765  memcpy(globalsymtab + globalsymtablen, s, sizeof(Elf_Sym));
1766 
1767  globalsymtablen += sizeof(Elf_Sym);
1768 
1769  return 0;
1770 
1771 }
1772 
1776 unsigned int append_strtab(char *str)
1777 {
1778 
1779  unsigned int nameptr;
1780 
1781  if (globalstrtab == 0) {
1782  globalstrtab = calloc(1, strlen(str) + 3);
1783  globalstrtablen++; // Start with a null byte
1784  } else {
1785  globalstrtab = realloc(globalstrtab, globalstrtablen + strlen(str) + 2);
1786  }
1787  memcpy(globalstrtab + globalstrtablen, str, strlen(str) + 1);
1788  nameptr = globalstrtablen;
1789  globalstrtablen += strlen(str) + 1;
1790 
1791  return nameptr;
1792 }
1793 
1794 
1798 static int create_section_symbols(ctx_t * ctx)
1799 {
1800 
1801  msec_t *tmp;
1802  msec_t *s;
1803  unsigned int nameptr;
1804  Elf_Sym *sym;
1805  unsigned int i, n;
1806 
1807  sym = calloc(1, sizeof(Elf_Sym));
1808 
1809  DL_COUNT(ctx->mshdrs, tmp, maxoldsec); // count before stripping
1810 
1811  for (i = 1; i <= maxoldsec; i++) {
1812  s = section_from_index(ctx, i);
1813  n = secindex_from_name_after_strip(ctx, s->name);
1814  if (n > maxnewsec) {
1815  maxnewsec = n;
1816  }
1817  }
1818 
1819 // maxnewsec += EXTRA_CREATED_SECTIONS; // count sections not yet created
1820  if (ctx->opt_debug) {
1821  printf(" -- Max section index after stripping: %u\n", maxnewsec);
1822  }
1823 
1824  // Create symbol for section
1825  for (i = 1; i <= maxnewsec; i++) {
1826 
1827  char *newsname = 0;
1828 
1829  newsname = sec_name_from_index_after_strip(ctx, i);
1830  if (!newsname) {
1831 
1832  switch (i - EXTRA_CREATED_SECTIONS - 1) {
1833  case 1:
1834  newsname = ".rela.all";
1835  break;
1836  case 2:
1837  newsname = ".strtab";
1838  break;
1839  case 3:
1840  newsname = ".symtab";
1841  break;
1842  case 4:
1843  newsname = ".shstrtab";
1844  break;
1845 
1846  default:
1847  newsname = ".unknown";
1848  break;
1849 
1850  }
1851  }
1852 
1853  nameptr = append_strtab(newsname);
1854 
1855  if (ctx->opt_debug) {
1856  printf("%u %s\n", i, newsname);
1857  }
1858 
1859  sym->st_name = nameptr;
1860  sym->st_size = 0;
1861  sym->st_value = 0;
1862  sym->st_info = STT_SECTION;
1863  sym->st_other = 0;
1864  sym->st_shndx = i;
1865 
1866  append_sym(sym);
1867  }
1868 
1869  free(sym);
1870 
1872 
1873  if (ctx->opt_debug) {
1874  printf(" -- Base sections symbol index: %u\n", 0);
1875  printf(" -- Delta string table: %u\n", deltastrtab);
1876  }
1877 
1878  return 0;
1879 }
1880 
1881 static unsigned int process_text(ctx_t * ctx)
1882 {
1883 
1884  msec_t *t;
1885  unsigned int delta;
1886 
1887  t = section_from_name(ctx, ".text");
1888  delta = orig_text - textvma;
1889 
1890  // create section symbols
1891 // create_section_symbols(ctx);
1892 
1893  // parse text for relocations
1894  analyze_text(ctx, (char *) (t->data + delta), maxtext - mintext - delta,
1895  orig_text);
1896 
1897  return 0;
1898 }
1899 
1903 static unsigned int write_shdrs(ctx_t * ctx)
1904 {
1905  Elf_Shdr *shdr = 0;
1906  unsigned int tmpm = 0;
1907  msec_t *s;
1908 
1912  // Goto end of file
1913  tmpm = lseek(ctx->fdout, 0x00, SEEK_END);
1914  write(ctx->fdout, nullstr, 20);
1915  write(ctx->fdout, nullstr, 20);
1916  write(ctx->fdout, nullstr, 20);
1917  tmpm = lseek(ctx->fdout, 0x00, SEEK_END);
1918  // align on 8 bytes boundaries
1919  if ((tmpm % 8) == 0) {
1920  tmpm += 8;
1921  };
1922  tmpm &= ~0xf;
1923  tmpm += sizeof(Elf_Shdr); // Prepend a NULL section
1924  // truncate
1925  ftruncate(ctx->fdout, tmpm);
1926 
1927  ctx->start_shdrs = lseek(ctx->fdout, 0x00, SEEK_END) - sizeof(Elf_Shdr); // New start of SHDRs
1928  ctx->strndx[0] = 0;
1929  ctx->strndx_len = 1;
1930 
1934  DL_FOREACH(ctx->mshdrs, s) {
1935 
1936  // append name to strndx
1937  memcpy(ctx->strndx + ctx->strndx_len, s->name, strlen(s->name) + 1); // do copy the final "\x00"
1938  s->s_elf->sh_name = ctx->strndx_len;
1939  ctx->strndx_len += strlen(s->name) + 1;
1940 
1941  // adjust section links and info
1942  s->s_elf->sh_link = link_from_name(ctx, s->name); // Link to another section
1943  s->s_elf->sh_info = info_from_name(ctx, s->name); // Additional section information
1944 
1945  // write section header to binary
1946  write(ctx->fdout, s->s_elf, sizeof(Elf_Shdr));
1947  }
1948 
1949 
1953  // append name to strndx
1954  memcpy(ctx->strndx + ctx->strndx_len, ".rela.all", 10);
1955 
1956  shdr = calloc(1, sizeof(Elf_Shdr));
1957 
1958  shdr->sh_name = ctx->strndx_len; // index in string table
1959  shdr->sh_type = SHT_RELA; // Section type
1960  shdr->sh_flags = 2; // Section flags
1961  shdr->sh_addr = 0; // Section virtual addr at execution
1962  shdr->sh_offset = globalrelocoffset; // Section file offset
1963  shdr->sh_size = globalreloclen; // Section size in bytes
1964  shdr->sh_link = ctx->shnum + 3; // Link to another section
1965  shdr->sh_info = 1; // Additional section information : .text
1966  shdr->sh_addralign = 8; // Section alignment
1967  shdr->sh_entsize = entszfromname(".rela.plt"); // Entry size if section holds table
1968 
1969  ctx->strndx_len += 10;
1970 
1971  // append string table section header to binary
1972  write(ctx->fdout, shdr, sizeof(Elf_Shdr));
1973  free(shdr);
1974 
1975  ctx->strndx_index = ctx->shnum + 1;
1976  // append sections strint table to binary
1977 // write(ctx->fdout, ctx->strndx, ctx->strndx_len);
1978 
1982  // append name to strndx
1983  memcpy(ctx->strndx + ctx->strndx_len, ".strtab", 8);
1984 
1985  shdr = calloc(1, sizeof(Elf_Shdr));
1986 
1987  shdr->sh_name = ctx->strndx_len; // index in string table
1988  shdr->sh_type = SHT_STRTAB; // Section type
1989  shdr->sh_flags = 0; // Section flags
1990  shdr->sh_addr = 0; // Section virtual addr at execution
1991  shdr->sh_offset = globalstrtableoffset; // Section file offset
1992  shdr->sh_size = globalstrtablen; // Section size in bytes
1993  shdr->sh_link = 0; // Link to another section
1994  shdr->sh_info = 0; // Additional section information
1995  shdr->sh_addralign = 1; // Section alignment
1996  shdr->sh_entsize = entszfromname(".strtab"); // Entry size if section holds table
1997 
1998  ctx->strndx_len += 8;
1999 
2000  // append string table section header to binary
2001  write(ctx->fdout, shdr, sizeof(Elf_Shdr));
2002  free(shdr);
2003 
2004  ctx->strndx_index = ctx->shnum + 1;
2005  // append sections strint table to binary
2006 // write(ctx->fdout, ctx->strndx, ctx->strndx_len);
2007 
2008 
2012  // append name to strndx
2013  memcpy(ctx->strndx + ctx->strndx_len, ".symtab", 8);
2014 
2015  shdr = calloc(1, sizeof(Elf_Shdr));
2016 
2017  shdr->sh_name = ctx->strndx_len; // index in string table
2018  shdr->sh_type = SHT_SYMTAB; // Section type
2019  shdr->sh_flags = 0; // Section flags
2020  shdr->sh_addr = 0; // Section virtual addr at execution
2021  shdr->sh_offset = globalsymtableoffset; // Section file offset
2022  shdr->sh_size = globalsymtablen; // Section size in bytes
2023  shdr->sh_link = ctx->shnum + 2; // Link to another section (strtab)
2024  shdr->sh_info = ctx->shnum + 1; // Additional section information
2025  shdr->sh_addralign = 8; // Section alignment
2026 // shdr->sh_entsize = 0; // Entry size if section holds table
2027  shdr->sh_entsize = entszfromname(".symtab"); // Entry size if section holds table
2028 
2029  ctx->strndx_len += 8;
2030 
2031  // append string table section header to binary
2032  write(ctx->fdout, shdr, sizeof(Elf_Shdr));
2033  free(shdr);
2034 
2035  ctx->strndx_index = ctx->shnum + 1;
2036  // append sections strint table to binary
2037 // write(ctx->fdout, ctx->strndx, ctx->strndx_len);
2038 
2039 
2044  // append name to strndx
2045  memcpy(ctx->strndx + ctx->strndx_len, ".shstrtab", 10);
2046 
2047  shdr = calloc(1, sizeof(Elf_Shdr));
2048 
2049  shdr->sh_name = ctx->strndx_len; // index in string table
2050  shdr->sh_type = SHT_STRTAB; // Section type
2051  shdr->sh_flags = 0; // Section flags
2052  shdr->sh_addr = 0; // Section virtual addr at execution
2053 // shdr->sh_offset = lseek(ctx->fdout, 0x00, SEEK_END) + 64; // Section file offset
2054  shdr->sh_offset = lseek(ctx->fdout, 0x00, SEEK_END) + sizeof(Elf_Shdr); // Section file offset
2055  shdr->sh_size = ctx->strndx_len + 10; // Section size in bytes
2056  shdr->sh_link = 0; // Link to another section
2057  shdr->sh_info = 0; // Additional section information
2058  shdr->sh_addralign = 1; // Section alignment
2059  shdr->sh_entsize = 0; // Entry size if section holds table
2060 
2061  ctx->strndx_len += 9 + 1;
2062 
2063  // append string table section header to binary
2064  write(ctx->fdout, shdr, sizeof(Elf_Shdr));
2065  free(shdr);
2066 
2067  ctx->strndx_index = ctx->shnum + 1;
2068  // append sections strint table to binary
2069  write(ctx->fdout, ctx->strndx, ctx->strndx_len);
2070 
2071  if (ctx->opt_debug) {
2072  printf(" * section headers at:\t\t\t0x%x\n", ctx->start_shdrs);
2073  printf(" * section string table index:\t\t%u\n", ctx->shnum);
2074  }
2075  return ctx->start_shdrs;
2076 }
2077 
2081 static int mk_ehdr(ctx_t * ctx)
2082 {
2083  Elf_Ehdr *e = 0;
2084 
2085  e = calloc(1, sizeof(Elf_Ehdr));
2086  if (!e) {
2087  perror("calloc");
2088  exit(EXIT_FAILURE);
2089  }
2090 
2095  // Set ELF signature
2096  memcpy(e->e_ident, "\x7f\x45\x4c\x46\x02\x01\x01", 7);
2097  e->e_ident[EI_CLASS] = ELFCLASS; // 64 or 32 bits
2098  e->e_entry = bfd_get_start_address(ctx->abfd);
2099  // Set type of ELF based on command line options and compilation target
2100  e->e_type = ET_DYN; // Default is shared library
2101  e->e_machine = ctx->opt_arch ? ctx->opt_arch : ELFMACHINE; // Default : idem compiler cpu, else, user specified
2102  e->e_version = 0x1; // ABI Version, Always 1
2103  e->e_phoff = ctx->start_phdrs;
2104  e->e_shoff = ctx->start_shdrs;
2105  e->e_flags = ctx->opt_flags; // default is null. Used in setting some EABI versions on ARM
2106  e->e_ehsize = sizeof(Elf_Ehdr); // Size of this header
2107  e->e_phentsize = sizeof(Elf_Phdr); // Size of each program header
2108  e->e_phnum = ctx->phnum;
2109  e->e_shentsize = sizeof(Elf_Shdr); // Size of each section header
2110  e->e_shnum = ctx->shnum + 5; // We added a null section and a string table index + .strtab + .symtab + .rela.all
2111  e->e_shstrndx = ctx->shnum + 4; // Sections Seader String table index is last valid
2112 
2116  if (ctx->opt_sstrip) {
2117  e->e_shoff = 0;
2118  e->e_shnum = 0;
2119  e->e_shstrndx = 0; // Sections Seader String table index is last valid
2120  e->e_shentsize = 0;
2121  }
2122 
2123  if ((ctx->opt_exec) || (ctx->opt_static)) {
2124  e->e_type = ET_EXEC; // Executable
2125  }
2126  if (ctx->opt_shared) {
2127  e->e_type = ET_DYN; // Shared library
2128  }
2129  if (ctx->opt_reloc) {
2130  e->e_type = ET_REL; // Relocatable object
2131  e->e_entry = 0;
2132  e->e_phoff = 0;
2133  e->e_phnum = 0;
2134  e->e_phentsize = 0;
2135  }
2136 
2137  if (ctx->opt_core) {
2138  e->e_type = ET_CORE; // Core file
2139  }
2140  // write ELF Header
2141  lseek(ctx->fdout, 0x00, SEEK_SET);
2142  write(ctx->fdout, e, sizeof(Elf_Ehdr));
2143  return 0;
2144 }
2145 
2149 static int write_section(ctx_t * ctx, msec_t * m)
2150 {
2151  unsigned int nwrite = 0;
2152 
2153  // Go to correct offset in output binary
2154  lseek(ctx->fdout, (unsigned long int) m->outoffset, SEEK_SET);
2155 
2156  // write to fdout
2157  nwrite = write(ctx->fdout, m->data, m->len);
2158  if (nwrite != m->len) {
2159  printf("write failed: %u != %lu %s\n", nwrite, m->len, strerror(errno));
2160  exit(EXIT_FAILURE);
2161  }
2162  return nwrite;
2163 }
2164 
2165 static int rd_extended_text(ctx_t * ctx)
2166 {
2167  unsigned int i;
2168  asection *s;
2169 
2170  if (ctx->opt_debug) {
2171  printf(" -- Finding .text segment boundaries\n\n");
2172 
2173  printf(" index\t\tname\t\t\trange\tsize\tpermissions\toffset\n");
2174  printf
2175  ("--------------------------------------------------------------------\n");
2176  }
2177  s = ctx->abfd->sections;
2178  for (i = 0; i < ctx->shnum; i++) {
2179  unsigned perms = parse_bfd_perm(s->flags);
2180  if (perms == 5) {
2181  if (ctx->opt_debug) {
2182  int pad;
2183  pad = MAXPADLEN - strlen(s->name);
2184  if (pad < 0) {
2185  pad = 0;
2186  }
2187 
2188  printf(" [%2u] \t%s% *s\t%012llx-%012llx %llu\t%s\t%llu\n", i + 1,
2189  s->name, pad, "", s->vma, s->vma + s->size, s->size, "RX",
2190  s->filepos);
2191  }
2192 
2193  if (s->filepos < mintext) {
2194  mintext = s->filepos;
2195  textvma = s->vma;
2196  }
2197  if (s->filepos + s->size > maxtext) {
2198  maxtext = s->filepos + s->size;
2199  }
2200  }
2201  s = s->next;
2202  }
2203 
2204  if (ctx->opt_debug) {
2205  printf(" --> .text future boundaries: offset:%lu sz:%lu vma:%lx\n\n",
2206  mintext, maxtext - mintext, textvma);
2207  }
2208  return 0;
2209 }
2210 
2211 static int rd_extended_data(ctx_t * ctx)
2212 {
2213  unsigned int i;
2214  asection *s;
2215 
2216  if (ctx->opt_debug) {
2217  printf(" -- Finding .data segment boundaries\n\n");
2218 
2219  printf(" index\t\tname\t\t\trange\tsize\tpermissions\toffset\n");
2220  printf("--------------------------------------------------------------------\n");
2221  }
2222  s = ctx->abfd->sections;
2223  for (i = 0; i < ctx->shnum; i++) {
2224  unsigned perms = parse_bfd_perm(s->flags);
2225  if (perms == 4) {
2226  if (ctx->opt_debug) {
2227  int pad;
2228  pad = MAXPADLEN - strlen(s->name);
2229  if (pad < 0) {
2230  pad = 0;
2231  }
2232 
2233  printf(" [%2u] \t%s % *s\t%012llx-%012llx %llu\t%s\t%lu\n", i + 1,
2234  s->name, pad, "", s->vma, s->vma + s->size, s->size, "RW",
2235  s->filepos);
2236  }
2237 
2238  if (s->filepos < mindata) {
2239  mindata = s->filepos;
2240  datavma = s->vma;
2241  }
2242  if (s->filepos + s->size > maxdata) {
2243  maxdata = s->filepos + s->size;
2244  }
2245  }
2246  s = s->next;
2247  }
2248 
2249  if (ctx->opt_debug) {
2250  printf(" --> .data future boundaries: offset:%lu sz:%lu vma:%lx\n\n",
2252  }
2253  return 0;
2254 }
2255 
2256 
2257 static int extend_text(ctx_t * ctx)
2258 {
2259  unsigned int i;
2260  asection *s;
2261 
2262  if (ctx->opt_debug) {
2263  printf(" -- Extending .text\n\n");
2264  }
2265 
2266  s = ctx->abfd->sections;
2267  for (i = 0; i < ctx->shnum; i++) {
2268  if (!strncmp(s->name, ".text", 5)) {
2269  orig_text = s->vma;
2270  s->vma = textvma;
2271  s->filepos = mintext;
2272  s->flags = -1;
2273  s->size = maxtext - mintext;
2274  if (ctx->opt_debug) {
2275  printf(" * extending section %s\n", s->name);
2276  printf(" * new .text boundaries: offset:%lu sz:%lu vma:%lx\n\n",
2277  mintext, s->size, textvma);
2278  }
2279  }
2280  s = s->next;
2281  }
2282  return 0;
2283 }
2284 
2289 {
2290  unsigned int i;
2291  asection *s;
2292  int pad;
2293  unsigned perms;
2294  char *hperms;
2295 
2296  if (ctx->opt_verbose) {
2297  printf("\n -- Input binary sections\n\n");
2298  printf
2299  (" name address range pages perms offset\n");
2300  printf
2301  (" --------------------------------------------------------------------------------\n");
2302  }
2303 
2304  s = ctx->abfd->sections;
2305  for (i = 0; i < ctx->shnum; i++) {
2306  perms = parse_bfd_perm(s->flags);
2307  switch (perms) {
2308  case 7:
2309  hperms = "rwx";
2310  break;
2311  case 6:
2312  hperms = "r--";
2313  break;
2314  case 5:
2315  hperms = "r-x";
2316  break;
2317  case 4:
2318  hperms = "rw-";
2319  break;
2320  default:
2321  hperms = "---";
2322  break;
2323  }
2324 
2325  pad = MAXPADLEN - strlen(s->name);
2326  if (pad < 0) {
2327  pad = 0;
2328  }
2329 
2330  if (ctx->opt_verbose) {
2331  printf(" [%2u] %s% *s\t%012llx-%012llx %llu\t%s\t%lu\n", i + 1, s->name,
2332  pad, "", s->vma, s->vma + s->size, s->size, hperms, s->filepos);
2333  }
2334  s = s->next;
2335  }
2336 
2337  if (ctx->opt_verbose) {
2338  printf("\n");
2339  }
2340  return 0;
2341 }
2342 
2346 void hexdump(unsigned char *data, size_t size)
2347 {
2348  size_t i, j;
2349 
2350  for (j = 0; j < size; j += 16) {
2351  for (i = j; i < j + 16; i++) {
2352  if (i < size) {
2353  printf("%02x ", data[i] & 255);
2354  } else {
2355  printf(" ");
2356  }
2357  }
2358  printf(" ");
2359  for (i = j; i < j + 16; i++) {
2360  if (i < size)
2361  putchar(32 <= (data[i] & 127)
2362  && (data[i] & 127) < 127 ? data[i] & 127 : '.');
2363  else
2364  putchar(' ');
2365  }
2366  putchar('\n');
2367  }
2368 }
2369 
2373 unsigned int open_best(ctx_t * ctx)
2374 {
2375  int formatok = 0;
2376 
2377  // Open as object
2378  formatok = bfd_check_format(ctx->abfd, bfd_object);
2379  ctx->shnum = bfd_count_sections(ctx->abfd);
2380  ctx->corefile = 0;
2381 
2382  // Open as core file
2383  if ((!formatok) || (!ctx->shnum)) {
2384  formatok = bfd_check_format(ctx->abfd, bfd_core);
2385  ctx->shnum = bfd_count_sections(ctx->abfd);
2386  ctx->corefile = 1;
2387  }
2388  // Open as archive
2389  if ((!formatok) || (!ctx->shnum)) {
2390  formatok = bfd_check_format(ctx->abfd, bfd_archive);
2391  ctx->shnum = bfd_count_sections(ctx->abfd);
2392  ctx->corefile = 0;
2393  }
2394 
2395  if ((!formatok) || (!ctx->shnum)) {
2396  printf(" -- couldn't find a format for %s\n", ctx->binname);
2397  return 0;
2398  }
2399  return ctx->shnum;
2400 }
2401 
2405 int open_target(ctx_t * ctx)
2406 {
2407  int fd = 0;
2408  struct stat sb;
2409  char *newname;
2410  char *p;
2411 
2412  if (stat(ctx->binname, &sb) == -1) {
2413  perror("stat");
2414  exit(EXIT_FAILURE);
2415  }
2416 
2417  if ((ctx->opt_binname) && (strlen(ctx->opt_binname))) {
2418  newname = ctx->opt_binname;
2419  } else {
2420  newname = calloc(1, strlen(ctx->binname) + 20);
2421  sprintf(newname, "a.out");
2422  }
2423 
2424  if (ctx->opt_debug) {
2425  printf(" -- Creating output file: %s\n\n", newname);
2426  }
2427 
2428  fd = open(newname, O_RDWR | O_CREAT | O_TRUNC, 0666);
2429  if (fd <= 0) {
2430  printf(" ERROR: open(%s) %s\n", newname, strerror(errno));
2431  exit(EXIT_FAILURE);
2432  }
2433  // set end of file
2434  ftruncate(fd, sb.st_size);
2435 
2436  // Copy default content : poison bytes or original data
2437  p = calloc(1, sb.st_size);
2438  if (ctx->opt_poison) {
2439  // map entire binary with poison byte
2440  memset(p, ctx->opt_poison, sb.st_size);
2441  } else {
2442  // Default : copy original binary
2443  int fdin = open(ctx->binname, O_RDONLY);
2444  read(fdin, p, sb.st_size);
2445  close(fdin);
2446  }
2447  lseek(fd, 0x00, SEEK_SET);
2448  write(fd, p, sb.st_size);
2449  free(p);
2450  lseek(fd, 0x00, SEEK_SET);
2451 
2452  ctx->fdout = fd;
2453  return fd;
2454 }
2455 
2459 int copy_body(ctx_t * ctx)
2460 {
2461  msec_t *s;
2462 
2463  DL_FOREACH(ctx->mshdrs, s) {
2464  write_section(ctx, s);
2465  }
2466  return 0;
2467 }
2468 
2472 int load_binary(ctx_t * ctx)
2473 {
2474  ctx->abfd = bfd_openr(ctx->binname, NULL);
2475  ctx->shnum = open_best(ctx);
2476  ctx->archsz = bfd_get_arch_size(ctx->abfd);
2477  if (ctx->opt_verbose) {
2478  printf(" -- Architecture size: %u\n", ctx->archsz);
2479  }
2480  return 0;
2481 }
2482 
2486 int flags_from_name(const char *name)
2487 {
2488  ifis(".bss") {
2489  return FLAG_BSS | FLAG_NOBIT | FLAG_NOWRITE;
2490  }
2491  elis(".text") {
2492  return FLAG_TEXT;
2493  }
2494  return 0;
2495 }
2496 
2500 int craft_section(ctx_t * ctx, msec_t * m)
2501 {
2502  asection *s = m->s_bfd;
2503  Elf_Shdr *shdr = m->s_elf;
2504  unsigned int dalign = 0;
2505  unsigned int dperms = 0;
2506 
2507  unsigned perms = parse_bfd_perm(s->flags);
2508  dperms = 0;
2509  switch (perms & 0xf) {
2510  case 7:
2511  dperms = SHF_ALLOC | SHF_WRITE | SHF_EXECINSTR; // "rwx";
2512  break;
2513  case 6:
2514  dperms = SHF_ALLOC; //"r--";
2515  break;
2516  case 5:
2517  dperms = SHF_ALLOC | SHF_EXECINSTR; // "r-x";
2518  break;
2519  case 4:
2520  dperms = SHF_ALLOC | SHF_WRITE; // "rw-"
2521  break;
2522  default:
2523  dalign = 1;
2524  dperms = 0; // "---"
2525  break;
2526  }
2527 
2528  // append name to strndx
2529  memcpy(ctx->strndx + ctx->strndx_len, s->name, strlen(s->name));
2530 
2531  shdr->sh_name = ctx->strndx_len; // Section name (string tbl index)
2532  shdr->sh_type = typefromname(s->name); // Section type
2533  shdr->sh_flags = dperms; // Section flags
2534  shdr->sh_addr = s->vma; // Section virtual addr at execution
2535 
2536  if (ctx->opt_reloc) {
2537  shdr->sh_addr = 0; // vma is null in relocatable files
2538  }
2539 
2540  shdr->sh_offset = s->filepos; // Section file offset
2541  shdr->sh_size = s->size; // Section size in bytes
2542  shdr->sh_addralign = dalign ? dalign : alignfromname(s->name); // Section alignment
2543  shdr->sh_entsize = entszfromname(s->name); // Entry size if section holds table
2544 
2545  ctx->strndx_len += strlen(s->name) + 1;
2546  return 0;
2547 }
2548 
2552 static int read_section(ctx_t * ctx, asection * s)
2553 {
2554  int fd = 0;
2555  unsigned int n, nread = 0, nwrite = 0;
2556  asection *buf;
2557  unsigned int wantedsz = 0;
2558 
2559  // Open input binary
2560  fd = open(ctx->binname, O_RDONLY);
2561  if (fd <= 0) {
2562  printf("error: open(%s) : %s\n", ctx->binname, strerror(errno));
2563  exit(0);
2564  }
2565  // Go to correct offset
2566  lseek(fd, s->filepos, SEEK_SET);
2567 
2568  // allocate tmp memory
2569  wantedsz = s->size;
2570  if (!strncmp(s->name, ".text", 5)) {
2571  wantedsz = s->size;
2572  }
2573  buf = calloc(1, wantedsz);
2574 
2575  // Create Meta section
2576  msec_t *ms = calloc(1, sizeof(msec_t));
2577  if (!ms) {
2578  perror("calloc");
2579  exit(EXIT_FAILURE);
2580  }
2581 
2582  ms->s_elf = calloc(1, sizeof(Elf_Shdr));
2583  if (!ms->s_elf) {
2584  perror("calloc");
2585  exit(EXIT_FAILURE);
2586  }
2587  // read data from disk
2588  if (!strncmp(s->name, ".bss", 4)) {
2589  // SHT_NOBITS Section contains no data (Global Uninitialized Data)
2590  n = 0;
2591  buf = realloc(buf, 0);
2592  } else {
2593  // read from disk
2594  n = 0;
2595  nread = read(fd, buf, s->size);
2596  while ((nread != 0) && (n <= s->size)) {
2597  n += nread;
2598  nread = read(fd, buf + n, s->size - n);
2599  }
2600 
2601  if ((n != s->size) && (!strncmp(s->name, ".text", 5))) {
2602  n = s->size;
2603  // initialized at 0x00 by calloc
2604  } else if (n != s->size) {
2605  printf("read failed: %u != %u\n", n, (unsigned int) s->size);
2606  }
2607  }
2608 
2609  // fill Meta section
2610  ms->s_bfd = s;
2611  ms->len = n;
2612  ms->name = strdup(s->name);
2613  ms->data = (unsigned char *) buf;
2614  ms->outoffset = (char *) s->filepos;
2615 
2616  // fill ELF section
2617  craft_section(ctx, ms);
2618 
2619  ms->flags = flags_from_name(s->name);
2620 
2621  // Add to double linked list of msec_t Meta sections
2622  DL_APPEND(ctx->mshdrs, ms);
2623  ctx->mshnum++;
2624 
2625  // Close file descriptor
2626  close(fd);
2627  return nwrite;
2628 }
2629 
2633 int print_msec(ctx_t * ctx)
2634 {
2635  msec_t *ms;
2636  unsigned int count;
2637 
2638  DL_COUNT(ctx->mshdrs, ms, count);
2639  printf(" -- %u elements\n", count);
2640 
2641  DL_FOREACH(ctx->mshdrs, ms) {
2642  printf("%s %lu\n", ms->name, ms->len);
2643  }
2644  return 0;
2645 }
2646 
2650 int rd_sections(ctx_t * ctx)
2651 {
2652  unsigned int i;
2653 
2654  asection *s = ctx->abfd->sections;
2655  for (i = 0; i < ctx->shnum; i++) {
2656  read_section(ctx, s);
2657  s = s->next;
2658  }
2659  return 0;
2660 }
2661 
2662 
2663 int save_dynstr(ctx_t * ctx, GElf_Shdr shdr, char *binary)
2664 {
2665 
2666  if (globalstrtab == 0) {
2667  globalstrtab = calloc(1, shdr.sh_size + 3);
2668  globalstrtablen++; // Start with a null byte
2669  } else {
2670  globalstrtab = realloc(globalstrtab, globalstrtablen + shdr.sh_size + 2);
2671  }
2672  memcpy(globalstrtab + globalstrtablen, binary + shdr.sh_offset,
2673  shdr.sh_size + 1);
2674  globalstrtablen += shdr.sh_size + 1;
2675 
2676  return 0;
2677 }
2678 
2679 
2680 
2681 int save_dynsym(ctx_t * ctx, GElf_Shdr shdr, char *binary)
2682 {
2683 
2684  if (globalsymtab == 0) {
2685  globalsymtab = calloc(1, sizeof(Elf_Sym) + shdr.sh_size);
2686 // globalsymtablen += sizeof(Elf_Sym); // Skip 1 NULL entry
2687  } else {
2688  globalsymtab = realloc(globalsymtab, shdr.sh_size + globalsymtablen);
2689  }
2690 
2691  memcpy(globalsymtab + globalsymtablen,
2692  binary + shdr.sh_offset + sizeof(Elf_Sym),
2693  shdr.sh_size - sizeof(Elf_Sym));
2694 
2695  globalsymtablen += shdr.sh_size - sizeof(Elf_Sym);
2696 
2697  return 0;
2698 }
2699 
2700 
2702 {
2703  msec_t *sec;
2704  char *sname;
2705 
2706  sname = globalstrtab + s->st_name;
2707 
2708  sec = section_from_index(ctx, s->st_shndx); // section related to this object
2709  if (sec) {
2710  // patch section index in symbol table
2711  s->st_shndx = secindex_from_name_after_strip(ctx, sec->name);
2712  } else {
2713 // printf(" no section info for symbol: %s\n", sname);
2714  }
2715 
2716  return 0;
2717 }
2718 
2719 
2721 {
2722 
2723  Elf_Sym *s;
2724  unsigned int sindex;
2725 
2726  for (sindex = maxnewsec + 1; sindex < globalsymtablen / sizeof(Elf_Sym);
2727  sindex++) {
2728 
2729  // get symbol name from index
2730  s = globalsymtab + sindex * sizeof(Elf_Sym);
2731 
2732  if (s->st_shndx) {
2733  patch_symbol_index(ctx, s);
2734  }
2735 
2736  }
2737  return 0;
2738 }
2739 
2741 {
2742 
2743  unsigned int i;
2744  Elf_Rela *s;
2745 
2746  // search this address in reloc table
2747  for (i = 0; i < globalreloclen / sizeof(Elf_Rela); i++) {
2748  s = globalreloc + i * sizeof(Elf_Rela);
2749  //
2750  if (s->r_offset == r->r_offset) {
2751  printf("warning: already have a relocation at %lu\n", r->r_offset);
2752  return -1; // already in relocation section
2753  }
2754  }
2755 
2756  // save relocation
2757  if (!globalreloc) {
2758  globalreloc = calloc(1, sizeof(Elf_Rela));
2759  } else {
2760  globalreloc = realloc(globalreloc, sizeof(Elf_Rela) + globalreloclen);
2761  }
2762 
2763  memcpy(globalreloc + globalreloclen, r, sizeof(Elf_Rela));
2764  globalreloclen += sizeof(Elf_Rela);
2765 
2766  return 0;
2767 
2768 }
2769 
2770 typedef struct gimport_t {
2771  char *sname;
2774  int rtype;
2775  unsigned int sindex;
2776 } gimport_t;
2777 
2779 unsigned int gimportslen = 0;
2780 
2781 int save_global_import(ctx_t * ctx, char *sname, msec_t * sec, Elf_Rela * r, unsigned int sindex)
2782 {
2783  int rtype;
2784  gimport_t *g;
2785  Elf_Rela *rnew;
2786 
2787  rtype = ELF_R_TYPE(r->r_info);
2788 
2789  if (ctx->opt_verbose) {
2790  printf
2791  ("recording blobal import variable %s in section: %s\t%s\tat:%lu\toff:%lu\n",
2792  sname, sec->name, reloc_htype(rtype), r->r_offset,
2793  r->r_offset - textvma);
2794  }
2795 
2796  g = calloc(1, sizeof(gimport_t));
2797  g->sname = strdup(sname);
2798  g->sec = sec;
2799  g->sindex = sindex; // index of symbol in symbol table
2800 
2801  rnew = calloc(1, sizeof(Elf_Rela));
2802  memcpy(rnew, r, sizeof(Elf_Rela));
2803  g->r = rnew;
2804  g->rtype = rtype;
2805 
2806  if (!gimports) {
2807  gimports = calloc(1, sizeof(gimport_t *));
2808  } else {
2809  gimports = realloc(gimports, sizeof(gimport_t *) * (gimportslen + 1));
2810  }
2811  gimports[gimportslen++] = g;
2812  return 0;
2813 }
2814 
2818 int check_global_import(unsigned long int addr)
2819 {
2820  unsigned i;
2821 
2822  if (addr < 4096) {
2823  return -1;
2824  }
2825 
2826  for (i = 0; i < gimportslen; i++) {
2827  if ((gimports[i]) && (gimports[i]->r) && (gimports[i]->r->r_offset == addr)) {
2828  return i;
2829  }
2830  }
2831 
2832  return -1;
2833 }
2834 
2835 int save_reloc(ctx_t * ctx, Elf_Rela * r, unsigned int sindex, int has_addend)
2836 {
2837 
2838  Elf_Sym *s;
2839  char *sname = 0;
2840  unsigned int i;
2841 
2842  int rtype, outtype;
2843  char *htype;
2844  msec_t *sec;
2845 
2846  Elf_Rela *rout;
2847 
2848  rout = calloc(1, sizeof(Elf_Rela)); // Work on a copy of the relocation instead of the original one
2849  memcpy(rout, r, sizeof(Elf_Rela));
2850 
2851  if (!has_addend) {
2852  rout->r_addend = 0;
2853  };
2854 
2855  // search symbol corresponding to this index
2856  if (!globalsymtab) {
2857  printf("warning: no symbol table for relocation index %u\n", sindex);
2858  return 0;
2859  }
2860 
2861  if (sindex > globalsymtablen / sizeof(Elf_Sym)) { // verify index is within bound of symtab...
2862  printf("warning: symbol index %u is out of bounds of symbol table\n",
2863  sindex);
2864  return 0;
2865  }
2866 
2867  if (!globalstrtab) {
2868  printf("warning: no string table for relocation index %u\n", sindex);
2869  return 0;
2870  }
2871  // get symbol name from index
2872  s = globalsymtab + sindex * sizeof(Elf_Sym);
2873  sname = globalstrtab + s->st_name;
2874 
2875  // check if name is "old_" : if so, skip
2876  if (!strncmp(sname, "old_", 4)) {
2877  return -1;
2878  }
2879  // check if name is in blacklist
2880  for (i = 0; i < sizeof(blnames) / sizeof(char *); i++) {
2881  if ((strlen(sname) == strlen(blnames[i]))
2882  && (!strncmp(sname, blnames[i], strlen(blnames[i])))) {
2883  if (ctx->opt_verbose) {
2884  printf(" * name blacklisted: %s\n", sname);
2885  }
2886  return -1; // Name in blacklist
2887  }
2888  }
2889 
2890  if (ctx->opt_debug) {
2891  printf(" * adding relocation for: %s\n", sname);
2892  }
2893 
2898  outtype = 0;
2899  rtype = ELF_R_TYPE(rout->r_info);
2900  sec = section_from_index(ctx, s->st_shndx); // section related to this object
2901  if (sec) {
2902 
2903  if (!strncmp(sec->name, ".bss", 4)) {
2904  // Save global import
2905  save_global_import(ctx, sname, sec, r, sindex);
2906  return 0;
2907  } else {
2908  // Skip
2909  if (ctx->opt_debug) {
2910  printf
2911  ("warning: skipping unknown relocation for symbol: %s in section: %s\t%s\tat:%lu\toff:%lu\n",
2912  sname, sec->name, reloc_htype(rtype), rout->r_offset,
2913  rout->r_offset - textvma);
2914  }
2915  s->st_shndx = 0;
2916  s->st_value = 0; // Actual value is null in this case
2917  return 0;
2918  }
2919 
2920  } else if (rtype == R_X86_64_RELATIVE) {
2921  if (ctx->opt_debug) {
2922  printf(" * Not saving Relative relocation %lu %lu\n", rout->r_offset,
2923  rout->r_addend);
2924  }
2925 // rout->r_offset -= textvma;
2926  return 0;
2927  } else { // Jump slots
2928  if (ctx->opt_debug) {
2929  printf(" no section info for symbol: %s\n", sname);
2930  }
2931 //#define R_386_JUMP_SLOT 7
2932 
2933 #ifdef __x86_64__
2934  outtype = R_X86_64_64;
2935 #else
2936  outtype = R_386_32;
2937 //printf("textvma: %llx\n", textvma);
2938 // rout->r_addend = +4;
2939 #endif
2940  rout->r_offset -= textvma;
2941  rout->r_info = ELF_R_INFO(sindex, outtype);
2942  }
2943 
2944 
2945  if (ctx->opt_debug) {
2946  htype = reloc_htype(outtype);
2947  printf("-->> %016lx\t%lu\t%s\t%u\taddend:%lu\t\n\n", rout->r_offset,
2948  rout->r_info, htype, sindex, rout->r_addend);
2949  }
2950 
2951  append_reloc(rout);
2952 
2953  return 0;
2954 }
2955 
2956 #include <capstone/capstone.h>
2957 
2958 static void print_string_hex(char *comment, unsigned char *str, size_t len)
2959 {
2960  unsigned char *c;
2961 
2962  printf("%s", comment);
2963  for (c = str; c < str + len; c++) {
2964  printf("0x%02x ", *c & 0xff);
2965  }
2966 
2967  printf("\n");
2968 }
2969 
2970 
2971 
2972 static void print_insn_detail(ctx_t * ctx, csh handle, cs_mode mode,
2973  cs_insn * ins)
2974 {
2975  int count, i;
2976  cs_x86 *x86;
2977 
2978  // detail can be NULL on "data" instruction if SKIPDATA option is turned ON
2979  if (ins->detail == NULL)
2980  return;
2981 
2982  x86 = &(ins->detail->x86);
2983  printf("\tAddress: %lu\n", ins->address);
2984  printf("\tInstruction Length: %u\n", ins->size);
2985 
2986  print_string_hex("\tPrefix:", x86->prefix, 4);
2987 
2988  print_string_hex("\tOpcode:", x86->opcode, 4);
2989 
2990  printf("\trex: 0x%x\n", x86->rex);
2991 
2992  printf("\taddr_size: %u\n", x86->addr_size);
2993  printf("\tmodrm: 0x%x\n", x86->modrm);
2994  printf("\tdisp: 0x%x\n", x86->disp);
2995 
2996  // SIB is not available in 16-bit mode
2997  if ((mode & CS_MODE_16) == 0) {
2998  printf("\tsib: 0x%x\n", x86->sib);
2999  if (x86->sib_base != X86_REG_INVALID)
3000  printf("\t\tsib_base: %s\n", cs_reg_name(handle, x86->sib_base));
3001  if (x86->sib_index != X86_REG_INVALID)
3002  printf("\t\tsib_index: %s\n", cs_reg_name(handle, x86->sib_index));
3003  if (x86->sib_scale != 0)
3004  printf("\t\tsib_scale: %d\n", x86->sib_scale);
3005  }
3006  // SSE code condition
3007  if (x86->sse_cc != X86_SSE_CC_INVALID) {
3008  printf("\tsse_cc: %u\n", x86->sse_cc);
3009  }
3010  // AVX code condition
3011  if (x86->avx_cc != X86_AVX_CC_INVALID) {
3012  printf("\tavx_cc: %u\n", x86->avx_cc);
3013  }
3014  // AVX Suppress All Exception
3015  if (x86->avx_sae) {
3016  printf("\tavx_sae: %u\n", x86->avx_sae);
3017  }
3018  // AVX Rounding Mode
3019  if (x86->avx_rm != X86_AVX_RM_INVALID) {
3020  printf("\tavx_rm: %u\n", x86->avx_rm);
3021  }
3022 
3023  count = cs_op_count(handle, ins, X86_OP_IMM);
3024  if (count) {
3025  printf("\timm_count: %u\n", count);
3026  for (i = 1; i < count + 1; i++) {
3027  int index = cs_op_index(handle, ins, X86_OP_IMM, i);
3028  printf("\t\timms[%u]: 0x%" PRIx64 "\n", i, x86->operands[index].imm);
3029  }
3030  }
3031 
3032  if (x86->op_count)
3033  printf("\top_count: %u\n", x86->op_count);
3034  for (i = 0; i < x86->op_count; i++) {
3035  cs_x86_op *op = &(x86->operands[i]);
3036 
3037  switch ((int) op->type) {
3038  case X86_OP_REG:
3039  printf("\t\toperands[%u].type: REG = %s\n", i,
3040  cs_reg_name(handle, op->reg));
3041  break;
3042  case X86_OP_IMM:
3043  printf("\t\toperands[%u].type: IMM = 0x%" PRIx64 "\n", i, op->imm);
3044  break;
3045  case X86_OP_MEM:
3046  printf("\t\toperands[%u].type: MEM\n", i);
3047  if (op->mem.segment != X86_REG_INVALID)
3048  printf("\t\t\toperands[%u].mem.segment: REG = %s\n", i,
3049  cs_reg_name(handle, op->mem.segment));
3050  if (op->mem.base != X86_REG_INVALID)
3051  printf("\t\t\toperands[%u].mem.base: REG = %s\n", i,
3052  cs_reg_name(handle, op->mem.base));
3053  if (op->mem.index != X86_REG_INVALID)
3054  printf("\t\t\toperands[%u].mem.index: REG = %s\n", i,
3055  cs_reg_name(handle, op->mem.index));
3056  if (op->mem.scale != 1)
3057  printf("\t\t\toperands[%u].mem.scale: %u\n", i, op->mem.scale);
3058  if (op->mem.disp != 0)
3059  printf("\t\t\toperands[%u].mem.disp: 0x%" PRIx64 "\n", i, op->mem.disp);
3060  break;
3061  default:
3062  break;
3063  }
3064 
3065  // AVX broadcast type
3066  if (op->avx_bcast != X86_AVX_BCAST_INVALID)
3067  printf("\t\toperands[%u].avx_bcast: %u\n", i, op->avx_bcast);
3068 
3069  // AVX zero opmask {z}
3070  if (op->avx_zero_opmask != false)
3071  printf("\t\toperands[%u].avx_zero_opmask: TRUE\n", i);
3072 
3073  printf("\t\toperands[%u].size: %u\n", i, op->size);
3074  }
3075 
3076  printf("\n");
3077 }
3078 
3079 static int create_text_data_reloc(ctx_t * ctx, cs_insn * ins, msec_t * m,
3080  unsigned int soff, int rip_relative, unsigned int argnum)
3081 {
3082  unsigned int sindex = 0;
3083  unsigned int wheretowrite = 0;
3084  unsigned int n = 0;
3085  int gimport = -1;
3086  cs_x86 *x86;
3087 
3088  x86 = &(ins->detail->x86);
3089  n = x86->op_count;
3090  wheretowrite = ins->size - 4;
3091 
3092  if (ctx->opt_debug) {
3093  printf(" --> transforming relocation from section: %s at ", m->name);
3094  printf("0x%" PRIx64 ":\t%s\t%s\tinslen:%u argoffset:%u\n", ins->address,
3095  ins->mnemonic, ins->op_str, ins->size, wheretowrite);
3096  }
3097 
3098  sindex = secindex_from_name_after_strip(ctx, m->name);
3099 
3100  if ((!strncmp(m->name, ".bss", 4)) && (n == 2) && (!rip_relative)) {
3101  gimport = check_global_import(x86->operands[1].imm);
3102  }
3103 
3104  if (rip_relative) {
3105 // printf(" ** destination: %lx\n", x86->operands[1]->mem.disp + ins->address + 7);
3106  gimport = check_global_import(x86->operands[1].mem.disp + ins->address + 7);
3107  if (ctx->opt_debug) {
3108  printf("** global imports match : %d\n", gimport);
3109  }
3110  }
3111 
3112  if ((gimport != -1) && (!rip_relative)) { // Relocation to .bss with a known global import
3113 
3114  if (ctx->opt_debug) {
3115  printf(" * known imported global : %s\n", gimports[gimport]->sname);
3116  }
3117 
3118  Elf_Rela *r = calloc(1, sizeof(Elf_Rela));
3119  if (!r) {
3120  perror("calloc");
3121  exit(-1);
3122  }
3123 
3124  sindex = gimports[gimport]->sindex;
3125 
3126  // reset string index in symbol table
3127  Elf_Sym *st = 0;
3128  st = globalsymtab + gimports[gimport]->sindex * sizeof(Elf_Sym);
3129  st->st_shndx = 0;
3130  st->st_value = 0;
3131 
3132  r->r_info = ELF_R_INFO(gimports[gimport]->sindex, R_X86_64_PC32);
3133  r->r_addend = 0; //-4;
3134  r->r_offset = ins->address - textvma + wheretowrite;
3135 
3136  // patch back binary
3137  msec_t *t = section_from_name(ctx, ".text");
3138  memset(t->data + r->r_offset, 0x00, 4);
3139 
3140  if (ctx->opt_debug) {
3141  printf("%" PRIx64 "\t%s+%u\t\t\t(%s %s)\n", ins->address, m->name, soff,
3142  ins->mnemonic, ins->op_str);
3143  printf("%012lx\t%012lx\t%s\t%012x\t%s+%u\n", r->r_offset, r->r_info,
3144  "R_X86_64_32", 0, m->name, soff);
3145  }
3146  // append relocation
3147  append_reloc(r);
3148 
3149  free(r);
3150 
3151  } else if ((gimport != -1) && (rip_relative)) { // Relocation to .bss with a known global import via rip relative
3152 
3153  if (ctx->opt_debug) {
3154  printf(" * known imported global (rip relative) : %s\n",
3155  gimports[gimport]->sname);
3156  }
3157 
3158  Elf_Rela *r = calloc(1, sizeof(Elf_Rela));
3159  if (!r) {
3160  perror("calloc");
3161  exit(-1);
3162  }
3163 
3164  sindex = gimports[gimport]->sindex;
3165 
3166  // reset string index in symbol table
3167  Elf_Sym *st = 0;
3168  st = globalsymtab + gimports[gimport]->sindex * sizeof(Elf_Sym);
3169  st->st_shndx = 0;
3170  st->st_value = 0;
3171 
3172  r->r_info = ELF_R_INFO(gimports[gimport]->sindex, R_X86_64_PC32);
3173  r->r_addend = -4;
3174  r->r_offset = ins->address - textvma + wheretowrite;
3175 
3176  // patch back binary
3177  msec_t *t = section_from_name(ctx, ".text");
3178  memset(t->data + r->r_offset, 0x00, 4);
3179 
3180  if (ctx->opt_debug) {
3181  printf("%012lx\t%012lx\t%s\t%012x\t%s+%ld\n", r->r_offset, r->r_info,
3182  "R_X86_64_32", 0, gimports[gimport]->sname, r->r_addend);
3183  }
3184  // append relocation
3185  append_reloc(r);
3186 
3187  free(r);
3188 
3189  } else if (sindex) { // Any other local section relocation (.rodata, .data ...)
3190 
3191  Elf_Rela *r = calloc(1, sizeof(Elf_Rela));
3192  if (!r) {
3193  perror("calloc");
3194  exit(-1);
3195  }
3196 
3197  if (ctx->opt_debug) {
3198  printf("new %s sindex:%u addent:%u, off:0x%lx\thasrel:%u\n",
3199  rip_relative ? "rip relative local" : "local", sindex, soff,
3200  ins->address - textvma + wheretowrite,
3202  }
3203 
3204  int newtype;
3205 #ifdef __x86_64__
3206  newtype = ctx->has_relativerelocations ? R_X86_64_PC32 : R_X86_64_32;
3207 #else
3208 #ifdef __i386__
3209  newtype = R_386_32; //R_386_PLT32;//R_386_GOTOFF;//R_386_GOTPC; //R_386_GOT32; //R_386_COPY; //R_386_RELATIVE; //R_386_PC32; //R_386_GLOB_DAT; //R_386_32;
3210 #endif
3211 #endif
3212 
3213  // patch back .text
3214  msec_t *t = section_from_name(ctx, ".text");
3215 
3216  if (argnum == 0) { // typically: cmp [rip+0xdeadbeef], 0 or something like mov qword ptr [rip+0xdeadbeef], rax
3217  /*
3218  * find at witch position we shall patch by scanning memory for the memory displacement
3219  */
3220  for (wheretowrite = 0; wheretowrite <= ins->size; wheretowrite++) {
3221  unsigned int searchval = x86->operands[0].mem.disp;
3222  if (!memcmp
3223  (t->data + (ins->address - textvma + wheretowrite), &searchval,
3224  4)) {
3225 // printf(" * patching instruction at offset: %u addend: %d relative:%d\n", wheretowrite, soff, rip_relative ? rip_relative : 0);
3226  break;
3227  }
3228  }
3229 
3230  // not found ? Fatal error
3231  if (wheretowrite == ins->size) {
3232  printf("error: can't find patch location\n");
3233  exit(-1);
3234  }
3235 
3236  }
3237 
3238  if (rip_relative) { // compute new addend and set reloc type
3239  cs_x86_op *op = &(x86->operands[argnum]);
3240 
3241  r->r_addend = ((op->mem.disp) + ins->address) - m->s_bfd->vma; // (rip + (immediate|displacement)) - m->s_bfd->vma; // dst - (section vma)
3242 // printf("* new rip based addend : %llx\n", r->r_addend);
3243 
3244  newtype = R_X86_64_PC32;
3245 
3246  } else {
3247  r->r_addend = soff; // default
3248  }
3249 
3250  r->r_info = ELF_R_INFO(sindex, newtype);
3251  r->r_offset = ins->address - textvma + wheretowrite;
3252 
3253  if ((argnum == 0) && (rip_relative)) { // write at custom location
3254  memset(t->data + r->r_offset, 0x00, 4); // write back where computed previously
3255 // r->r_addend = -4;
3256  } else if (rip_relative) { // patch back register index (from rip to 0x00)
3257  memset(t->data + r->r_offset, 0x00, 4); // write back 4 bytes (one 32b address) + 1 if relative (overwrite rip)
3258 // r->r_addend = 0;//0x29a;
3259  } else if (ELFMACHINE == EM_386) { // R_386_32 doesn't account for the addend : write it back to .text
3260  memcpy(t->data + r->r_offset, &soff, 4);
3261  } else {
3262  memset(t->data + r->r_offset, 0x00, 4); // write back 4 bytes (one 32b address) + 1 if relative (overwrite rip)
3263  }
3269 // if (ctx->opt_verbose) {
3270 // printf("%"PRIx64"\t%s+0x%lx\t\t\t(%s %s)\n",ins->address, m->name, soff, ins->mnemonic, ins->op_str);
3271 // printf("%012lx\t%012lx\t%s\t%s+%u\n", r->r_offset, r->r_info, reloc_htype(newtype), m->name, soff);
3272 // }
3273 
3274  // append relocation
3275  append_reloc(r);
3276 
3277  free(r);
3278  } else { // Unhandled relocation
3279  if (ctx->opt_debug) {
3280  printf("warning: unknown relocation section: %s at ", m->name);
3281  printf("0x%" PRIx64 ":\t%s\t%s\n", ins->address, ins->mnemonic,
3282  ins->op_str);
3283  }
3284  }
3285 
3286  return 0;
3287 }
3288 
3289 int internal_function_store(ctx_t * ctx, unsigned long long int addr)
3290 {
3291 
3292  unsigned int i;
3293  char buff[200];
3294  Elf_Sym *s = 0;
3295 
3296  memset(buff, 0x00, 200);
3297  snprintf(buff, 200, "internal_%08llx", addr);
3298 
3299  // search this symbol in string table
3300  for (i = 0; i < globalstrtablen; i += strlen(globalstrtab + i) + 1) {
3301  if (!strncmp(globalstrtab + i, buff, strlen(buff))) {
3302  return -1; // already in strtab, hence in symtab
3303  }
3304  }
3305 
3306  // search this address in symbol table
3307  for (i = 0; i < globalsymtablen / sizeof(Elf_Sym); i++) {
3308  s = globalsymtab + i * sizeof(Elf_Sym);
3309  //
3310  if (s->st_value == addr) {
3311  return -1; // already in symtab
3312  }
3313  }
3314 
3315  add_symaddr(ctx, buff, addr, 0x54);
3316  return 0;
3317 }
3318 
3319 static void parse_text_data_reloc(ctx_t * ctx, csh ud, cs_mode mode,
3320  cs_insn * ins)
3321 {
3322  int i;
3323  cs_x86 *x86;
3324  msec_t *m;
3325  // detail can be NULL on "data" instruction if SKIPDATA option is turned ON
3326  if (ins->detail == NULL)
3327  return;
3328 
3329  x86 = &(ins->detail->x86);
3330 
3331 // if(ctx->opt_debug){
3332 // printf("\t\tRELOC Address: %lu\n", ins->address);
3333 // printf("\t\tRELOC operands.type: MEM, opcount:%u\n", x86->op_count);
3334 // }
3335 
3336  for (i = 0; i < x86->op_count; i++) {
3337  cs_x86_op *op = &(x86->operands[i]);
3338  m = 0;
3339  switch ((int) op->type) {
3340  case X86_OP_IMM:
3341  ;
3342  m = section_from_addr(ctx, op->imm);
3343  if (m) {
3344  if (i == 1) { // only match arg=1 // second argument is of form [0xdeadbeef]
3345  create_text_data_reloc(ctx, ins, m, op->imm - m->s_bfd->vma, 0, i);
3346  } else if (i == 0) { // first argument is of form [0xdeadbeef]
3347 
3348  if ((!strncmp(ins->mnemonic, "call", 4))
3349  && (!strncmp(m->name, ".text", 5))) {
3350 // printf(" --> call to internal function at %lx\n", op->imm);
3351  internal_function_store(ctx, op->imm);
3352  } else {
3353 // TODO instrument internal/cross sections jumps and calls
3354 // printf("We have a problem: (dst section: %s)\n", m->name);
3355 // printf("0x%llx %s %s\n", ins->address, ins->mnemonic, ins->op_str);
3356  }
3357 
3358  }
3359  }
3360  break;
3361  case X86_OP_MEM:
3362  ;
3363  m = section_from_addr(ctx, op->mem.disp + ins->address + 10 * ctx->has_relativerelocations); // assume rip relative
3364 //printf("sec name: %s\t%lx\n", m ? m->name : "-", op->mem.disp + ins->address + 10*ctx->has_relativerelocations);
3365  if ((m) && (m->name) && (strncmp(m->name, ".text", 5) || ctx->has_relativerelocations) && (cs_reg_name(ud, op->mem.base)) && (!strncmp(cs_reg_name(ud, op->mem.base), "rip", 3))) { // destination section can't be .text, must be rip relative
3366  if (i == 1) { // only match arg=1
3367  create_text_data_reloc(ctx, ins, m, op->mem.disp + ins->address - m->s_bfd->vma, 1, i); // Addressing is rip relative
3368  break;
3369  }
3370  }
3371 
3372  if (!strncmp(ins->mnemonic, "nop", 3)) { // ignore nops
3373  break;
3374  }
3375  // handle write to 1st argument, which is a rip relative mapped section
3376  if ((i == 0) && (m) && (m->name)
3377  && (strncmp(m->name, ".text", 5) || ctx->has_relativerelocations)
3378  && (cs_reg_name(ud, op->mem.base))
3379  && (!strncmp(cs_reg_name(ud, op->mem.base), "rip", 3))) {
3380 // printf(" * handling 1st arg access : %llx %s %s (%s)\n",ins->address, ins->mnemonic, ins->op_str, m ? m->name : "-");
3381  create_text_data_reloc(ctx, ins, m, op->mem.disp + ins->address - m->s_bfd->vma, 1, i); // Addressing is rip relative
3382  break;
3383  }
3384 
3385  break;
3386 
3387  case X86_OP_REG:
3388 // case X86_OP_MEM:
3389  default:
3390  break;
3391  }
3392  }
3393 }
3394 
3395 int analyze_text(ctx_t * ctx, char *data, unsigned int datalen,
3396  unsigned long int addr)
3397 {
3398  csh handle;
3399  cs_insn *insn;
3400  size_t count;
3401  size_t j;
3402 
3403  if (cs_open(CS_ARCH_X86, CS_MODE, &handle)) {
3404  printf("error: Failed to initialize capstone library\n");
3405  return -1;
3406  }
3407  // request disassembly details
3408  cs_option(handle, CS_OPT_DETAIL, CS_OPT_ON);
3409 
3410  count = cs_disasm(handle, data, datalen - 1, addr, 0, &insn);
3411  if (!count) {
3412  printf("error: Cannot disassemble code\n");
3413  return -1;
3414  }
3415 
3416  if (ctx->opt_asmdebug) {
3417  printf(" -- parsing %lu instructions from %lx (.text) for relocations\n\n",
3418  count, addr);
3419  printf
3420  ("\n Offset Info Type Sym. Value Sym. Name + Addend\n");
3421  }
3422  // scan instructions for relocations
3423  for (j = 0; j < count; j++) {
3424 
3425  if (ctx->opt_asmdebug) {
3426  printf("0x%" PRIx64 ":\t%s\t%s\n", insn[j].address, insn[j].mnemonic,
3427  insn[j].op_str);
3428  print_insn_detail(ctx, handle, CS_MODE, &insn[j]);
3429  }
3430 
3431  parse_text_data_reloc(ctx, handle, CS_MODE, &insn[j]);
3432  }
3433 
3434  cs_free(insn, count);
3435  cs_close(&handle);
3436 
3437  return 0;
3438 }
3439 
3443 int rd_symtab(ctx_t * ctx)
3444 {
3445  Elf *elf;
3446  Elf_Scn *scn = NULL;
3447  GElf_Shdr shdr;
3448  int fd;
3449  const char *binary;
3450  struct stat sb;
3451  size_t shstrndx;
3452  char *sname = 0;
3453 
3454  if (ctx->opt_debug) {
3455  printf(" -- searching for .strtab/.symtab\n");
3456  }
3457 
3458  elf_version(EV_CURRENT);
3459 
3460  fd = open(ctx->binname, O_RDONLY);
3461  fstat(fd, &sb);
3462  binary = mmap(NULL, sb.st_size, PROT_READ, MAP_PRIVATE, fd, 0);
3463  if (binary == MAP_FAILED) {
3464  perror("mmap");
3465  exit(EXIT_FAILURE);
3466  }
3467 
3468  elf = elf_begin(fd, ELF_C_READ, NULL);
3469  if (!elf) {
3470  printf("error: not a valid ELF\n");
3471  return -1;
3472  }
3473 
3474  if (elf_getshdrstrndx(elf, &shstrndx) != 0) {
3475  printf("error: in elf_getshdrstrndx\n");
3476  return -1;
3477  }
3478 
3479  while ((scn = elf_nextscn(elf, scn)) != NULL) {
3480  gelf_getshdr(scn, &shdr);
3481  sname = elf_strptr(elf, shstrndx, shdr.sh_name);
3482 
3483  switch (shdr.sh_type) {
3484  case SHT_SYMTAB:
3485  if (ctx->opt_debug) {
3486  printf(" * symbol table at offset:%lu, sz:%lu\n", shdr.sh_offset,
3487  shdr.sh_size);
3488  }
3489  break;
3490 
3491  case SHT_STRTAB:
3492  if (!strncmp(sname, ".dynstr", 7)) {
3493  if (ctx->opt_debug) {
3494  printf(" * dynamic string table at offset:%lu, sz:%lu\n",
3495  shdr.sh_offset, shdr.sh_size);
3496  }
3497  save_dynstr(ctx, shdr, binary);
3498  } else {
3499  if (ctx->opt_debug) {
3500  printf(" * string table at offset:%lu, sz:%lu\n", shdr.sh_offset,
3501  shdr.sh_size);
3502  }
3503  }
3504  break;
3505 
3506  case SHT_DYNSYM:
3507  if (ctx->opt_debug) {
3508  printf(" * dynamic symbol table at offset:%lu, sz:%lu\n",
3509  shdr.sh_offset, shdr.sh_size);
3510  }
3511  save_dynsym(ctx, shdr, binary);
3512  break;
3513 
3514  default:
3515  break;
3516  }
3517 
3518  }
3519 
3520  elf_end(elf);
3521  close(fd);
3522 
3523  if ((ctx->opt_verbose) || (ctx->opt_debug)) {
3524  printf("\n");
3525  }
3526 
3527  return 0;
3528 }
3529 
3533 int rm_section(ctx_t * ctx, char *name)
3534 {
3535  msec_t *s;
3536  msec_t *rmsec = 0;
3537 
3538  DL_FOREACH(ctx->mshdrs, s) {
3539  if (!strncmp(s->name, name, strlen(name))) {
3540  rmsec = s;
3541  break;
3542  }
3543  }
3544 
3545  if (!rmsec) {
3546  return 0;
3547  } // Not found
3548 
3549  DL_DELETE(ctx->mshdrs, rmsec);
3550 
3551  ctx->shnum--;
3552  ctx->mshnum--;
3553 
3554  return 0;
3555 }
3556 
3561 {
3562  msec_t *s, *tmp;
3563  unsigned int allowed, i;
3564 
3565  if (ctx->opt_verbose) {
3566  printf("\n -- Stripping\n\n");
3567 
3568  }
3569 
3570  DL_FOREACH_SAFE(ctx->mshdrs, s, tmp) {
3571  allowed = 0;
3572  for (i = 0; i < sizeof(allowed_sections) / sizeof(char *); i++) {
3573  if (!strncmp(s->name, allowed_sections[i], strlen(allowed_sections[i]))) {
3574  allowed = 1;
3575  break;
3576  }
3577  }
3578 
3579  if (!allowed) {
3580  if (ctx->opt_verbose) {
3581  printf(" * %s\n", s->name);
3582  }
3583 
3584  rm_section(ctx, s->name);
3585  }
3586  }
3587 
3588  if (ctx->opt_verbose) {
3589  printf("\n");
3590  }
3591  return 0;
3592 }
3593 
3597 unsigned int libify(ctx_t * ctx)
3598 {
3599  char const *target = NULL;
3600  int is_pe64 = 0, is_pe32 = 0;
3610  load_binary(ctx);
3611 
3615  print_bfd_sections(ctx);
3616 
3620  rd_extended_text(ctx);
3621  rd_extended_data(ctx);
3622 
3623  extend_text(ctx);
3624 
3628  open_target(ctx);
3629 
3633  rd_sections(ctx);
3634 
3635 
3636  create_section_symbols(ctx);
3637 
3641  rd_symtab(ctx);
3642 
3643 
3645 
3649  target = bfd_get_target(ctx->abfd);
3650 
3651  is_pe64 = (strcmp(target, "pe-x86-64") == 0
3652  || strcmp(target, "pei-x86-64") == 0);
3653  is_pe32 = (strcmp(target, "pe-i386") == 0 || strcmp(target, "pei-i386") == 0
3654  || strcmp(target, "pe-arm-wince-little") == 0
3655  || strcmp(target, "pei-arm-wince-little") == 0);
3656 
3657  if ((is_pe64) || (is_pe32)) {
3658  printf("target: %s\n", target);
3659  } else {
3660  rd_symbols(ctx);
3661  }
3662 
3663  fixup_text(ctx);
3664 
3668  add_extra_symbols(ctx);
3669 
3670 
3674  parse_relocations(ctx);
3675 
3676 
3681 
3682  process_text(ctx);
3683 
3693  copy_body(ctx);
3694 
3699  if ((ctx->opt_static) || (ctx->opt_reloc)) {
3700  rm_section(ctx, ".interp");
3701  rm_section(ctx, ".dynamic");
3702  }
3703 
3704  if (ctx->opt_reloc) {
3705  strip_binary_reloc(ctx);
3706  }
3707 
3711  if (!ctx->opt_original) {
3712  mk_phdrs(ctx); // Create Program Headers from sections
3713  } else {
3714  // Read Original Program Headers
3715  rd_phdrs(ctx);
3716  }
3717 
3727  write_strtab_and_reloc(ctx);
3728 
3732  if (!ctx->opt_sstrip) {
3733  write_shdrs(ctx);
3734  }
3735 
3739  if (!ctx->opt_reloc) {
3740  if (!ctx->opt_original) {
3741  write_phdrs(ctx);
3742  } else {
3743  write_phdrs_original(ctx);
3744 
3745  }
3746  }
3747 
3751  mk_ehdr(ctx);
3752 
3757  return 0;
3758 }
3759 
3763 int print_maps(void)
3764 {
3765  char cmd[1024];
3766 
3767  sprintf(cmd, "cat /proc/%u/maps", getpid());
3768  system(cmd);
3769  return 0;
3770 }
3771 
3776 {
3777  ctx_t *ctx;
3778 
3779  bfd_init();
3780  errno = 0;
3781  ctx = calloc(1, sizeof(ctx_t));
3782  if (!ctx) {
3783  printf("error: calloc(): %s\n", strerror(errno));
3784  exit(EXIT_FAILURE);
3785  }
3786 
3790  ctx->strndx = calloc(1, DEFAULT_STRNDX_SIZE);
3791  ctx->mshdrs = NULL;
3792  return ctx;
3793 }
3794 
3795 int usage(char *name)
3796 {
3797  printf("Usage: %s [options] file\n", name);
3798  printf("\noptions:\n\n");
3799  printf(" -o, --output <output file>\n");
3800  printf(" -m, --march <architecture>\n");
3801  printf(" -e, --entrypoint <0xaddress>\n");
3802  printf(" -i, --interpreter <interpreter>\n");
3803  printf(" -p, --poison <poison>\n");
3804  printf(" -s, --shared\n");
3805  printf(" -c, --compile\n");
3806  printf(" -S, --static\n");
3807  printf(" -x, --strip\n");
3808  printf(" -X, --sstrip\n");
3809  printf(" -E, --exec\n");
3810  printf(" -C, --core\n");
3811  printf(" -O, --original\n");
3812  printf(" -D, --disasm\n");
3813  printf(" -d, --debug\n");
3814  printf(" -h, --help\n");
3815  printf(" -v, --verbose\n");
3816  printf(" -V, --version\n");
3817  printf("\n");
3818  return 0;
3819 }
3820 
3821 int print_version(void)
3822 {
3823  printf("%s version:%s (%s %s)\n", WNAME, WVERSION, WTIME, WDATE);
3824  return 0;
3825 }
3826 
3827 int desired_arch(ctx_t * ctx, char *name)
3828 {
3829 
3830  unsigned int i = 0;
3831 
3832  for (i = 0; i < sizeof(wccarch) / sizeof(archi_t); i++) {
3833  if (!strncmp(wccarch[i].name, name, strlen(name))) {
3834  if (ctx->opt_verbose) {
3835  printf(" * architecture: %s\n", name);
3836  }
3837  return wccarch[i].value;
3838  }
3839  }
3840 
3841  printf("error: architecture %s not supported\n", name);
3842  exit(EXIT_FAILURE);
3843 
3844  return 0;
3845 }
3846 
3847 int ctx_getopt(ctx_t * ctx, int argc, char **argv)
3848 {
3849  const char *short_opt = "ho:i:scSEsxCvVXp:Odm:e:f:D";
3850  int count = 0;
3851  struct stat sb;
3852  int c;
3853 
3854  struct option long_opt[] = {
3855  {"help", no_argument, NULL, 'h'},
3856  {"march", required_argument, NULL, 'm'},
3857  {"output", required_argument, NULL, 'o'},
3858  {"shared", no_argument, NULL, 's'},
3859  {"compile", no_argument, NULL, 'c'},
3860  {"debug", no_argument, NULL, 'd'},
3861  {"disasm", no_argument, NULL, 'D'},
3862  {"static", no_argument, NULL, 'S'},
3863  {"exec", no_argument, NULL, 'E'},
3864  {"core", no_argument, NULL, 'C'},
3865  {"strip", no_argument, NULL, 'x'},
3866  {"sstrip", no_argument, NULL, 'X'},
3867  {"entrypoint", required_argument, NULL, 'e'},
3868  {"interpreter", required_argument, NULL, 'i'},
3869  {"poison", required_argument, NULL, 'p'},
3870  {"original", no_argument, NULL, 'O'},
3871  {"verbose", no_argument, NULL, 'v'},
3872  {"version", no_argument, NULL, 'V'},
3873  {NULL, 0, NULL, 0}
3874  };
3875 
3876  // Parse options
3877  if (argc < 2) {
3878  print_version();
3879  printf("\n");
3880  usage(argv[0]);
3881  exit(EXIT_SUCCESS);
3882  }
3883 
3884  while ((c = getopt_long(argc, argv, short_opt, long_opt, NULL)) != -1) {
3885  count++;
3886  switch (c) {
3887  case -1: /* no more arguments */
3888  case 0:
3889  break;
3890 
3891  case 'c':
3892  ctx->opt_reloc = 1;
3893  break;
3894 
3895  case 'C':
3896  ctx->opt_core = 1;
3897  break;
3898 
3899  case 'd':
3900  ctx->opt_debug = 1;
3901  ctx->opt_verbose = 1;
3902  break;
3903 
3904  case 'D':
3905  ctx->opt_asmdebug = 1;
3906  break;
3907 
3908  case 'e':
3909  ctx->opt_entrypoint = strtoul(optarg, NULL, 16);
3910  count++;
3911  break;
3912 
3913  case 'E':
3914  ctx->opt_exec = 1;
3915  break;
3916 
3917  case 'f':
3918  ctx->opt_flags = strtoul(optarg, NULL, 16);
3919  count++;
3920  break;
3921 
3922  case 'h':
3923  usage(argv[0]);
3924  exit(0);
3925  break;
3926 
3927  case 'i':
3928  ctx->opt_interp = strdup(optarg);
3929  count++;
3930  break;
3931 
3932  case 'm':
3933  ctx->opt_arch = desired_arch(ctx, optarg);
3934  count++;
3935  break;
3936 
3937  case 'o':
3938  ctx->opt_binname = strdup(optarg);
3939  count++;
3940  break;
3941 
3942  case 'O':
3943  ctx->opt_original = 1;
3944  break;
3945 
3946  case 'p':
3947  ctx->opt_poison = optarg[0];
3948  count++;
3949  break;
3950 
3951  case 's':
3952  ctx->opt_shared = 1;
3953  break;
3954 
3955  case 'S':
3956  ctx->opt_static = 1;
3957  break;
3958 
3959  case 'v':
3960  ctx->opt_verbose = 1;
3961  break;
3962 
3963  case 'V':
3964  print_version();
3965  exit(EXIT_SUCCESS);
3966  break;
3967 
3968  case 'x':
3969  ctx->opt_strip = 1;
3970  break;
3971 
3972  case 'X':
3973  ctx->opt_sstrip = 1;
3974  break;
3975 
3976  case ':':
3977  case '?':
3978  fprintf(stderr, "Try `%s --help' for more information.\n", argv[0]);
3979  exit(-2);
3980 
3981  default:
3982  fprintf(stderr, "%s: invalid option -- %c\n", argv[0], c);
3983  fprintf(stderr, "Try `%s --help' for more information.\n", argv[0]);
3984  exit(-2);
3985  };
3986  };
3987 
3988  // arguments sanity checks
3989  if (count >= argc - 1) {
3990  fprintf(stderr, "error: No source binary found in arguments.\n");
3991  fprintf(stderr, "Try `%s --help' for more information.\n", argv[0]);
3992  exit(-2);
3993  }
3994  // verify target file exists
3995  if (stat(argv[count + 1], &sb)) {
3996  printf("error: Could not open file %s : %s\n", argv[count + 1],
3997  strerror(errno));
3998  exit(EXIT_FAILURE);
3999  }
4000  // store original size
4001  orig_sz = sb.st_size;
4002 
4003  if (ctx->opt_debug) {
4004  printf(" -- Analysing: %s\n", argv[count + 1]);
4005  }
4006  // copy target file name
4007  ctx->binname = strdup(argv[count + 1]);
4008  return 0;
4009 }
4010 
4014 int main(int argc, char **argv)
4015 {
4016  ctx_t *ctx;
4017 
4018  ctx = ctx_init();
4019  ctx_getopt(ctx, argc, argv);
4020  libify(ctx);
4021 
4022  return 0;
4023 }
unsigned int protect_perms(unsigned int perms)
Definition: wcc.c:381
void hexdump(unsigned char *data, size_t size)
Definition: wcc.c:2346
#define FLAG_NOBIT
Definition: wcc.c:76
int save_reloc(ctx_t *ctx, Elf_Rela *r, unsigned int sindex, int has_addend)
Definition: wcc.c:2835
#define FLAG_BSS
Definition: wcc.c:75
unsigned int append_strtab(char *str)
Definition: wcc.c:1776
char * outoffset
Definition: wcc.c:233
#define elis(x)
Definition: wcc.c:81
int flags_from_name(const char *name)
Definition: wcc.c:2486
int save_dynsym(ctx_t *ctx, GElf_Shdr shdr, char *binary)
Definition: wcc.c:2681
asection * s_bfd
Definition: wcc.c:236
unsigned int max(unsigned int a, unsigned int b)
Definition: wcc.c:697
#define RELOC_MODE
Definition: wcc.c:135
unsigned int start_shdrs
Definition: wcc.c:276
ctx_t * ctx_init(void)
Definition: wcc.c:3775
char * reloc_htype_x86_32(int thetype)
Definition: wcc.c:1474
int fdout
Definition: wcc.c:278
msec_t * section_from_index(ctx_t *ctx, unsigned int index)
Definition: wcc.c:736
int append_reloc(Elf_Rela *r)
Definition: wcc.c:2740
unsigned int corefile
Definition: wcc.c:280
unsigned long int mindata
Definition: wcc.c:356
#define Elf_Phdr
Definition: wcc.c:128
Elf_Word p_type
Definition: wcc.c:249
msec_t * section_from_addr(ctx_t *ctx, unsigned long int addr)
Definition: wcc.c:720
bfd * abfd
Definition: wcc.c:279
char * reloc_htype_x86_64(int thetype)
Definition: wcc.c:1391
char * opt_interp
Definition: wcc.c:298
Elf_Shdr * s_elf
Definition: wcc.c:237
struct symaddr * symaddrs
unsigned int globalsymindex
Definition: wcc.c:346
msec_t * mshdrs
Definition: wcc.c:286
int open_target(ctx_t *ctx)
Definition: wcc.c:2405
char * name
Definition: wcc.c:230
int load_binary(ctx_t *ctx)
Definition: wcc.c:2472
#define ELFCLASS
Definition: wcc.c:132
unsigned int globalrelocoffset
Definition: wcc.c:350
unsigned int opt_original
Definition: wcc.c:310
int print_maps(void)
Definition: wcc.c:3763
struct mseg_t mseg_t
int adjust_baseaddress(ctx_t *ctx)
Definition: wcc.c:1108
int rd_symtab(ctx_t *ctx)
Definition: wcc.c:3443
void exit(int status)
Definition: wsh.c:3137
int sort_phdrs_premerge(ctx_t *ctx)
Definition: wcc.c:1000
int copy_body(ctx_t *ctx)
Definition: wcc.c:2459
int link_from_name(ctx_t *ctx, const char *name)
Definition: wcc.c:820
#define STT_NOTYPE
Definition: wsh.h:156
unsigned char opt_poison
Definition: wcc.c:309
struct msec_t msec_t
int patch_symbol_index(ctx_t *ctx, Elf_Sym *s)
Definition: wcc.c:2701
int check_global_import(unsigned long int addr)
Definition: wcc.c:2818
Definition: wcc.c:229
int globalsymtablen
Definition: wcc.c:339
#define ELF_R_TYPE
Definition: wcc.c:126
#define ELF64_ST_INFO(bind, type)
Definition: wsh.h:148
unsigned int opt_exec
Definition: wcc.c:304
#define Elf_Addr
Definition: wcc.c:118
#define RELOC_X86_64
Definition: wcc.c:88
unsigned int flags
Definition: wcc.c:234
unsigned int secindex_from_name(ctx_t *ctx, const char *name)
Definition: wcc.c:753
#define MAXPADLEN
Definition: wcc.c:83
int ctx_getopt(ctx_t *ctx, int argc, char **argv)
Definition: wcc.c:3847
#define nullstr
Definition: wcc.c:139
char * globalsymtab
Definition: wcc.c:338
unsigned int base_address
Definition: wcc.c:283
Elf_Xword p_memsz
Definition: wcc.c:255
unsigned int globalstrtableoffset
Definition: wcc.c:344
unsigned long int opt_entrypoint
Definition: wcc.c:308
unsigned int opt_debug
Definition: wcc.c:311
Definition: wcc.c:405
int main(int argc, char **argv)
Definition: wcc.c:4014
int print_version(void)
Definition: wcc.c:3821
unsigned int shnum
Definition: wcc.c:271
struct gimport_t gimport_t
char * sec_name_from_index_after_strip(ctx_t *ctx, unsigned int index)
Definition: wcc.c:791
unsigned long int maxdata
Definition: wcc.c:357
#define Elf_Shdr
Definition: wcc.c:116
char * name
Definition: wcc.c:407
unsigned int maxnewsec
Definition: wcc.c:140
#define STT_FILE
Definition: wsh.h:160
#define Elf_Rela
Definition: wcc.c:124
#define Elf_Off
Definition: wcc.c:131
unsigned char * data
Definition: wcc.c:232
unsigned int alignfromname(const char *name)
Definition: wcc.c:881
unsigned int deltastrtab
Definition: wcc.c:141
msec_t * section_from_name(ctx_t *ctx, char *name)
Definition: wcc.c:705
unsigned int pflag_from_section(msec_t *ms)
Definition: wcc.c:943
unsigned int start_phdrs
Definition: wcc.c:277
void add_symaddr(ctx_t *ctx, const char *name, int addr, char symclass)
Definition: wcc.c:423
Elf_Xword p_filesz
Definition: wcc.c:254
char * allowed_sections[]
Definition: wcc.c:143
unsigned long int textvma
Definition: wcc.c:354
#define RELOC_X86_32
Definition: wcc.c:89
#define FLAG_TEXT
Definition: wcc.c:78
unsigned int opt_reloc
Definition: wcc.c:301
unsigned long int maxtext
Definition: wcc.c:353
Elf_Xword p_align
Definition: wcc.c:256
int save_dynstr(ctx_t *ctx, GElf_Shdr shdr, char *binary)
Definition: wcc.c:2663
unsigned long int orig_sz
Definition: wcc.c:361
unsigned int libify(ctx_t *ctx)
Definition: wcc.c:3597
int analyze_text(ctx_t *ctx, char *data, unsigned int datalen, unsigned long int addr)
Definition: wcc.c:3395
int phdr_cmp_premerge(mseg_t *a, mseg_t *b)
Definition: wcc.c:971
unsigned int globalsymtableoffset
Definition: wcc.c:340
int fixup_strtab_and_symtab(ctx_t *ctx)
Definition: wcc.c:1638
int info_from_name(ctx_t *ctx, const char *name)
Definition: wcc.c:843
gimport_t ** gimports
Definition: wcc.c:2778
#define STT_FUNC
Definition: wsh.h:158
unsigned int opt_static
Definition: wcc.c:300
#define Elf_Word
Definition: wcc.c:130
unsigned long int datavma
Definition: wcc.c:358
unsigned int mshnum
Definition: wcc.c:287
int desired_arch(ctx_t *ctx, char *name)
Definition: wcc.c:3827
int entszfromname(const char *name)
Definition: wcc.c:682
unsigned int opt_asmdebug
Definition: wcc.c:312
int strip_binary_reloc(ctx_t *ctx)
Definition: wcc.c:3560
int fixup_symtab_section_index(ctx_t *ctx)
Definition: wcc.c:2720
unsigned int opt_verbose
Definition: wcc.c:307
Elf_Addr p_vaddr
Definition: wcc.c:252
struct ctx_t ctx_t
struct msec_t * prev
Definition: wcc.c:239
#define DEFAULT_STRNDX_SIZE
Definition: wcc.c:72
int addr
Definition: wcc.c:408
int sort_phdrs(ctx_t *ctx)
Definition: wcc.c:991
#define ELF_R_SYM
Definition: wcc.c:125
#define CS_MODE
Definition: wcc.c:134
unsigned int opt_strip
Definition: wcc.c:302
Elf_Rela * r
Definition: wcc.c:2773
mseg_t * mphdrs
Definition: wcc.c:290
int add_extra_symbols(ctx_t *ctx)
Definition: wcc.c:561
int merge_phdrs(ctx_t *ctx)
Definition: wcc.c:1073
struct msec_t * next
Definition: wcc.c:259
unsigned int globalreloclen
Definition: wcc.c:349
Elf_Word p_flags
Definition: wcc.c:250
#define Elf_Sym
Definition: wcc.c:117
#define STT_OBJECT
Definition: wsh.h:157
#define ELFMACHINE
Definition: wcc.c:133
#define ELF_R_INFO
Definition: wcc.c:127
unsigned long int len
Definition: wcc.c:231
#define STT_SECTION
Definition: wsh.h:159
char * globalreloc
Definition: wcc.c:348
char * binname
Definition: wcc.c:269
char * strndx
Definition: wcc.c:273
char * globalstrtab
Definition: wcc.c:342
unsigned int has_relativerelocations
Definition: wcc.c:293
char * opt_binname
Definition: wcc.c:297
Definition: wcc.c:264
#define FLAG_NOWRITE
Definition: wcc.c:77
unsigned int strndx_len
Definition: wcc.c:274
unsigned int ptype_from_section(msec_t *ms)
Definition: wcc.c:896
int craft_section(ctx_t *ctx, msec_t *m)
Definition: wcc.c:2500
int internal_function_store(ctx_t *ctx, unsigned long long int addr)
Definition: wcc.c:3289
#define ifis(x)
Definition: wcc.c:80
int create_phdrs(ctx_t *ctx)
Definition: wcc.c:1032
#define EXTRA_CREATED_SECTIONS
Definition: wcc.c:85
mseg_t * alloc_phdr(msec_t *ms)
Definition: wcc.c:1009
unsigned int opt_sstrip
Definition: wcc.c:303
int print_bfd_sections(ctx_t *ctx)
Definition: wcc.c:2288
unsigned long int mintext
Definition: wcc.c:352
unsigned int mphnum
Definition: wcc.c:291
#define STB_WEAK
Definition: wsh.h:152
unsigned int opt_core
Definition: wcc.c:305
char * reloc_htype(int thetype)
Definition: wcc.c:1535
int rd_symbols(ctx_t *ctx)
Definition: wcc.c:574
unsigned int archsz
Definition: wcc.c:270
unsigned int open_best(ctx_t *ctx)
Definition: wcc.c:2373
struct msec_t * next
Definition: wcc.c:240
unsigned int sindex
Definition: wcc.c:2775
msec_t * mk_section(void)
Definition: wcc.c:1330
int rtype
Definition: wcc.c:2774
#define Elf_Xword
Definition: wcc.c:129
Elf_Addr p_paddr
Definition: wcc.c:253
unsigned int phnum
Definition: wcc.c:272
unsigned int opt_shared
Definition: wcc.c:306
unsigned int opt_flags
Definition: wcc.c:313
int rm_section(ctx_t *ctx, char *name)
Definition: wcc.c:3533
int save_global_import(ctx_t *ctx, char *sname, msec_t *sec, Elf_Rela *r, unsigned int sindex)
Definition: wcc.c:2781
unsigned int secindex_from_name_after_strip(ctx_t *ctx, const char *name)
Definition: wcc.c:770
int print_msec(ctx_t *ctx)
Definition: wcc.c:2633
unsigned int gimportslen
Definition: wcc.c:2779
Definition: wcc.c:248
unsigned long int orig_text
Definition: wcc.c:360
char * blnames[]
Definition: wcc.c:158
unsigned int opt_arch
Definition: wcc.c:299
unsigned int strndx_index
Definition: wcc.c:275
char * sname
Definition: wcc.c:2771
struct msec_t * prev
Definition: wcc.c:258
int typefromname(const char *name)
Definition: wcc.c:866
int usage(char *name)
Definition: wcc.c:3795
unsigned int globalstrtablen
Definition: wcc.c:343
int rd_sections(ctx_t *ctx)
Definition: wcc.c:2650
#define Elf_Ehdr
Definition: wcc.c:115
unsigned int maxoldsec
Definition: wcc.c:140
int phdr_cmp(mseg_t *a, mseg_t *b)
Definition: wcc.c:982
Elf_Off p_offset
Definition: wcc.c:251
msec_t * sec
Definition: wcc.c:2772
unsigned int append_sym(Elf_Sym *s)
Definition: wcc.c:1755
struct symaddr * next
Definition: wcc.c:406
int fixup_text(ctx_t *ctx)
Definition: wcc.c:1694