File: main.cpp

package info (click to toggle)
objconv 2.56%2Bds-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 2,300 kB
  • sloc: cpp: 27,039; makefile: 4; sh: 2
file content (784 lines) | stat: -rw-r--r-- 32,261 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
/****************************   main.cpp   **********************************
* Author:        Agner Fog
* Date created:  2006-07-26
* Last modified: 2011-10-28
* Project:       objconv
* Module:        main.cpp
* Description:
* Objconv is a portable C++ program for converting object file formats.
* Compile for console mode on any platform.
*
* Module main contains the program entry
*
* Copyright 2006-2011 GNU General Public License http://www.gnu.org/licenses
*****************************************************************************/

#include "stdafx.h"

// Texts of option feedback. Adding or removing leading underscores on symbols
SIntTxt UnderscoreOptionNames[] = {
   {CMDL_UNDERSCORE_NOCHANGE, "Not adding or removing underscores for this filetype"},
   {CMDL_UNDERSCORE_REMOVE,   "Removing leading underscores from symbol names"},
   {CMDL_UNDERSCORE_ADD,      "Adding leading underscores to symbol names"},
   {CMDL_UNDERSCORE_REMOVE|CMDL_KEEP_ALIAS, "Removing leading underscores from symbol names. Keeping old name as alias"},
   {CMDL_UNDERSCORE_ADD|CMDL_KEEP_ALIAS,    "Adding leading underscores to symbol names. Keeping old name as alias"}
};

// Texts of option feedback. Changing leading dot or underscore on section names
SIntTxt SectionDotOptionNames[] = {
   {CMDL_SECTIONDOT_NOCHANGE, "Not changing leading character on section names for this filetype"},
   {CMDL_SECTIONDOT_U2DOT, "Changing leading underscores on section names to dot"},
   {CMDL_SECTIONDOT_DOT2U, "Changing leading dot on nonstandard section names to underscore"}
};

// Check that integer type definitions are correct.
// Will generate an error message if the compiler makes the integer types 
// with wrong size.
static void CheckIntegerTypes() {
   if (
      sizeof(uint8_t) != 1 ||
      sizeof(int16_t) != 2 ||
      sizeof(int32_t) != 4 ||
      sizeof(int64_t) != 8) {
      err.submit(9001);                // Make error message if type definitions are wrong
   }
}

// Check that we are running on a machine with little-endian memory organization
static void CheckEndianness() {
   static uint8_t bytes[4] = {1, 2, 3, 4};
   if (*(uint32_t*)bytes != 0x04030201) {
      // Big endian
      err.submit(9002);
   }
}

// Function to convert powers of 2 to index
int FloorLog2(uint32_t x) {
   int i = -1;
   do {
      x >>= 1;
      i++;
   } while (x);
   return i;
}

const char * timestring(uint32_t t) {
   // Convert 32 bit time stamp to string
   // Fix the problem that time_t may be 32 bit or 64 bit
   union {
      time_t t;
      uint32_t t32;
   } utime;
   utime.t = 0;
   utime.t32 = t;
   const char * string = ctime(&utime.t);
   if (string == 0) string = "?";
   return string;
}

// Main. Program starts here
int main(int argc, char * argv[]) {
   CheckIntegerTypes();                // Check that compiler has the right integer sizes
   CheckEndianness();                  // Check that machine is little-endian

#ifdef  _DEBUG
   // For debugging only. You may remove this
   if (argc == 1) {
      const char * dummyarg[] = {"", "@resp.txt"}; // Read command line from file resp.txt
      argc = 2; argv = (char**)dummyarg;}
#endif

   cmd.ReadCommandLine(argc, argv);    // Read command line parameters   
   if (cmd.ShowHelp) return 0;         // Help screen has been printed. Do nothing else

   CMain maincvt;                      // This object takes care of all conversions etc.
   maincvt.Go();          
   // Do everything the command line says

   if (cmd.Verbose) printf("\n");      // End with newline
   return err.GetWorstError();         // Return with error code
}


// Class CMainConverter is used for control of the conversion process
CMain::CMain() : CFileBuffer() {
}

void CMain::Go() {
   // Do whatever the command line parameters say
   FileName = cmd.InputFile;           // Get input file name from command line
   // Ignore nonexisting filename when building library
   int IgnoreError = (cmd.FileOptions & CMDL_FILE_IN_IF_EXISTS) && !cmd.OutputFile;
   Read(IgnoreError);                  // Read input file
   GetFileType();                      // Determine file type
   cmd.InputType = FileType;           // Save input file type in cmd for access from other modules
   if (cmd.OutputType == 0) {
       // desired type not specified
       cmd.OutputType = FileType;
   }
   if (err.Number()) return;           // Return if error
   CheckOutputFileName();              // Construct output file name with default extension
   if (err.Number()) return;

   if ((FileType & (FILETYPE_LIBRARY | FILETYPE_OMFLIBRARY)) 
   || (cmd.LibraryOptions & CMDL_LIBRARY_ADDMEMBER)) {
      // Input file is a library or we are building a library
      CLibrary lib;                    // Library handler object
      *this >> lib;                    // Transfer my file buffer to lib
      lib.Go();                        // Do conversion or dump
      *this << lib;                    // Get file buffer back
   }
   else {
      // Input file is an object file
      CConverter conv;                 // Make converter object
      *this >> conv;                   // Transfer my file buffer to conv
      conv.Go();                       // Do conversion or dump
      *this << conv;                   // Get file buffer back
   }
   if ((cmd.FileOptions & CMDL_FILE_OUTPUT) && OutputFileName) {
      // There is an output file to write
      cmd.CheckSymbolModifySuccess();  // Check if symbols to modify were found
      if (err.Number()) return;        // Return if error
      FileName = OutputFileName;       // Output file name
      Write();                         // Write output file
      if (cmd.Verbose) cmd.ReportStatistics(); // Report statistics
   }
}

CConverter::CConverter() {
   // Constructor
}

void CConverter::DumpCOF() {
   // Dump COFF file
   CCOFF cof;                          // Make object for interpreting COFF file
   *this >> cof;                       // Give it my buffer
   cof.ParseFile();                    // Parse file buffer
   if (err.Number()) return;           // Return if error
   cof.Dump(cmd.DumpOptions);          // Dump file
   *this << cof;                       // Take back my buffer
}

void CConverter::DumpELF() {
   // Dump ELF file
   if (WordSize == 32) {
      // Make object for interpreting 32 bit ELF file
      CELF<ELF32STRUCTURES> elf;
      *this >> elf;                    // Give it my buffer
      elf.ParseFile();                 // Parse file buffer
      if (err.Number()) return;        // Return if error
      elf.Dump(cmd.DumpOptions);       // Dump file
      *this << elf;                    // Take back my buffer
   }
   else {
      // Make object for interpreting 32 bit ELF file
      CELF<ELF64STRUCTURES> elf;
      *this >> elf;                    // Give it my buffer
      elf.ParseFile();                 // Parse file buffer
      if (err.Number()) return;        // Return if error
      elf.Dump(cmd.DumpOptions);       // Dump file
      *this << elf;                    // Take back my buffer
   }
}

void CConverter::DumpMACHO() {
   // Dump Mach-O file
   if (WordSize == 32) {
      // Make object for interpreting 32 bit Mach-O file
      CMACHO<MAC32STRUCTURES> macho;
      *this >> macho;                     // Give it my buffer
      macho.ParseFile();                  // Parse file buffer
      if (err.Number()) return;           // Return if error
      macho.Dump(cmd.DumpOptions);        // Dump file
      *this << macho;                     // Take back my buffer
   }
   else {
      // Make object for interpreting 64 bit Mach-O file
      CMACHO<MAC64STRUCTURES> macho;
      *this >> macho;                     // Give it my buffer
      macho.ParseFile();                  // Parse file buffer
      if (err.Number()) return;           // Return if error
      macho.Dump(cmd.DumpOptions);        // Dump file
      *this << macho;                     // Take back my buffer
   }
}

void CConverter::ParseMACUnivBin() {
   // Dump Mac universal binary
   CMACUNIV macuniv;                   // Make object for interpreting Mac universal binary file
   *this >> macuniv;                   // Give it my buffer
   macuniv.Go(cmd.DumpOptions);        // Dump file components
   *this << macuniv;                   // Take back my buffer
}

void CConverter::DumpOMF() {
   // Dump OMF file
   COMF omf;                           // Make object for interpreting OMF file
   *this >> omf;                       // Give it my buffer
   omf.ParseFile();                    // Parse file buffer
   if (err.Number()) return;           // Return if error
   omf.Dump(cmd.DumpOptions);          // Dump file
   *this << omf;                       // Take back my buffer
}

void CConverter::COF2ELF() {
   // Convert COFF to ELF file
   if (WordSize == 32) {
      // Make instance of converter, 32 bit template
      CCOF2ELF<ELF32STRUCTURES> conv;  // Make object for conversion 
      *this >> conv;                   // Give it my buffer
      conv.ParseFile();                // Parse file buffer
      if (err.Number()) return;        // Return if error
      conv.Convert();                  // Convert
      *this << conv;                   // Take back converted buffer
   }
   else {
      // Make instance of converter, 64 bit template
      CCOF2ELF<ELF64STRUCTURES> conv;  // Make object for conversion 
      *this >> conv;                   // Give it my buffer
      conv.ParseFile();                // Parse file buffer
      if (err.Number()) return;        // Return if error
      conv.Convert();                  // Convert
      *this << conv;                   // Take back converted buffer
   }
}

void CConverter::COF2OMF() {
   // Convert COFF to OMF file
   CCOF2OMF conv;                      // Make object for conversion 
   *this >> conv;                      // Give it my buffer
   conv.ParseFile();                   // Parse file buffer
   if (err.Number()) return;           // Return if error
   conv.Convert();                     // Convert
   *this << conv;                      // Take back converted buffer
}

void CConverter::OMF2COF() {
   // Convert OMF to COFF file 
   COMF2COF conv;                      // Make object for conversion 
   *this >> conv;                      // Give it my buffer
   conv.ParseFile();                   // Parse file buffer
   if (err.Number()) return;           // Return if error
   conv.Convert();                     // Convert
   *this << conv;                      // Take back converted buffer
}

void CConverter::ELF2COF() {
   // Convert ELF to COFF file
   if (WordSize == 32) {
      // Make instance of converter, 32 bit template
      CELF2COF<ELF32STRUCTURES> conv;
      *this >> conv;                   // Give it my buffer
      conv.ParseFile();                // Parse file buffer
      if (err.Number()) return;        // Return if error
      conv.Convert();                  // Convert
      *this << conv;                   // Take back converted buffer
   }
   else {
      // Make instance of converter, 64 bit template
      CELF2COF<ELF64STRUCTURES> conv;
      *this >> conv;                   // Give it my buffer
      conv.ParseFile();                // Parse file buffer
      if (err.Number()) return;        // Return if error
      conv.Convert();                  // Convert
      *this << conv;                   // Take back converted buffer
   }
}

void CConverter::ELF2MAC() {
   // Convert ELF to Mach-O file
   if (WordSize == 32) {
      // Make instance of converter, 32 bit template
      CELF2MAC<ELF32STRUCTURES,MAC32STRUCTURES> conv;
      *this >> conv;                      // Give it my buffer
      conv.ParseFile();                   // Parse file buffer
      if (err.Number()) return;           // Return if error
      conv.Convert();                     // Convert
      *this << conv;                      // Take back converted buffer
   }
   else {
      // Make instance of converter, 64 bit template
      CELF2MAC<ELF64STRUCTURES,MAC64STRUCTURES> conv;
      *this >> conv;                      // Give it my buffer
      conv.ParseFile();                   // Parse file buffer
      if (err.Number()) return;           // Return if error
      conv.Convert();                     // Convert
      *this << conv;                      // Take back converted buffer
   }
}

void CConverter::MAC2ELF() {
   // Convert Mach-O file to ELF file
   if (WordSize == 32) {
      // Make instance of converter, 32 bit template
      CMAC2ELF<MAC32STRUCTURES,ELF32STRUCTURES> conv;
      *this >> conv;                      // Give it my buffer
      conv.ParseFile();                   // Parse file buffer
      if (err.Number()) return;           // Return if error
      conv.Convert();                     // Convert
      *this << conv;                      // Take back converted buffer
   }
   else {
      // Make instance of converter, 64 bit template
      CMAC2ELF<MAC64STRUCTURES,ELF64STRUCTURES> conv;
      *this >> conv;                      // Give it my buffer
      conv.ParseFile();                   // Parse file buffer
      if (err.Number()) return;           // Return if error
      conv.Convert();                     // Convert
      *this << conv;                      // Take back converted buffer
   }
}

void CConverter::COF2ASM() {
   // Disassemble COFF file
   CCOF2ASM conv;                      // Make object for conversion 
   *this >> conv;                      // Give it my buffer
   conv.ParseFile();                   // Parse file buffer
   if (err.Number()) return;           // Return if error
   conv.Convert();                     // Convert
   *this << conv;                      // Take back converted buffer
}

void CConverter::ELF2ASM() {
   // Disassemble ELF file
   if (WordSize == 32) {
      // Make instance of converter, 32 bit template
      CELF2ASM<ELF32STRUCTURES> conv;
      *this >> conv;                      // Give it my buffer
      conv.ParseFile();                   // Parse file buffer
      if (err.Number()) return;           // Return if error
      conv.Convert();                     // Convert
      *this << conv;                      // Take back converted buffer
   }
   else {
      // Make instance of converter, 64 bit template
      CELF2ASM<ELF64STRUCTURES> conv;
      *this >> conv;                      // Give it my buffer
      conv.ParseFile();                   // Parse file buffer
      if (err.Number()) return;           // Return if error
      conv.Convert();                     // Convert
      *this << conv;                      // Take back converted buffer
   }
}

void CConverter::MAC2ASM() {
   // Disassemble Mach-O file
   if (WordSize == 32) {
      // Make instance of converter, 32 bit template
      CMAC2ASM<MAC32STRUCTURES> conv;
      *this >> conv;                      // Give it my buffer
      conv.ParseFile();                   // Parse file buffer
      if (err.Number()) return;           // Return if error
      conv.Convert();                     // Convert
      *this << conv;                      // Take back converted buffer
   }
   else {
      // Make instance of converter, 64 bit template
      CMAC2ASM<MAC64STRUCTURES> conv;
      *this >> conv;                      // Give it my buffer
      conv.ParseFile();                   // Parse file buffer
      if (err.Number()) return;           // Return if error
      conv.Convert();                     // Convert
      *this << conv;                      // Take back converted buffer
   }
}

void CConverter::OMF2ASM() {
   // Disassemble OMF file
   COMF2ASM conv;                      // Make object for conversion 
   *this >> conv;                      // Give it my buffer
   conv.ParseFile();                   // Parse file buffer
   if (err.Number()) return;           // Return if error
   conv.Convert();                     // Convert
   *this << conv;                      // Take back converted buffer
}

void CConverter::COF2COF() {
   // Make changes in COFF file
   CCOF2COF conv;                      // Make instance of converter
   *this >> conv;                      // Give it my buffer
   conv.ParseFile();                   // Parse file buffer
   if (err.Number()) return;           // Return if error
   conv.Convert();                     // Convert
   *this << conv;                      // Take back converted buffer
}

void CConverter::ELF2ELF() {
   // Make changes in ELF file
   if (WordSize == 32) {
      // Make instance of converter, 32 bit template
      CELF2ELF<ELF32STRUCTURES> conv;
      *this >> conv;                   // Give it my buffer
      conv.ParseFile();                // Parse file buffer
      if (err.Number()) return;        // Return if error
      conv.Convert();                  // Convert
      *this << conv;                   // Take back converted buffer
   }
   else {
      // Make instance of converter, 64 bit template
      CELF2ELF<ELF64STRUCTURES> conv;
      *this >> conv;                   // Give it my buffer
      conv.ParseFile();                // Parse file buffer
      if (err.Number()) return;        // Return if error
      conv.Convert();                  // Convert
      *this << conv;                   // Take back converted buffer
   }
}

void CConverter::MAC2MAC() {
   // Make changes in Mach-O file
   if (WordSize == 32) {
      // Make instance of converter, 32 bit template
      CMAC2MAC<MAC32STRUCTURES> conv;
      *this >> conv;                   // Give it my buffer
      conv.ParseFile();                // Parse file buffer
      if (err.Number()) return;        // Return if error
      conv.Convert();                  // Convert
      *this << conv;                   // Take back converted buffer
   }
   else {
      // Make instance of converter, 64 bit template
      CMAC2MAC<MAC64STRUCTURES> conv;
      *this >> conv;                   // Give it my buffer
      conv.ParseFile();                // Parse file buffer
      if (err.Number()) return;        // Return if error
      conv.Convert();                  // Convert
      *this << conv;                   // Take back converted buffer
   }
}

void CConverter::Go() {
   // Convert or dump file, depending on command line parameters
   GetFileType();                      // Determine file type
   cmd.InputType = FileType;           // Save input file type in cmd for access from other modules
   if (err.Number()) return;           // Return if error

   if (cmd.OutputType == CMDL_OUTPUT_DUMP) {
      // File dump requested
      if (cmd.Verbose > 0) {
         // Tell what we are doing:
         printf("\nDump of file: %s, type: %s%i", FileName, GetFileFormatName(FileType), WordSize);
      }

      switch(FileType) {
      case FILETYPE_ELF:
         DumpELF();  break;

      case FILETYPE_COFF:
         DumpCOF();   break;

      case FILETYPE_MACHO_LE:
         DumpMACHO();   break;

      case FILETYPE_OMF:
         DumpOMF();   break;

      case FILETYPE_MAC_UNIVBIN:
         ParseMACUnivBin();   break;

      default:
         err.submit(2010, GetFileFormatName(FileType));  // Dump of this file type not supported
      }
      printf("\n");                              // New line
   }
   else {
      // File conversion requested
      if (cmd.DesiredWordSize == 0) cmd.DesiredWordSize = WordSize;
      if (WordSize && WordSize != cmd.DesiredWordSize) {
         err.submit(2012, WordSize, cmd.DesiredWordSize); // Cannot convert word size
         return;
      }
      if (Executable && cmd.OutputType != CMDL_OUTPUT_MASM) {
         // Attempt to convert executable file
         err.submit(2022);
      }
      if (err.Number()) return;        // Return if error

      if (cmd.Verbose > (uint32_t)(cmd.LibraryOptions != 0)) {
         // Tell what we are doing:
         printf("\nInput file: %s, output file: %s", FileName, OutputFileName);
         if (FileType != cmd.OutputType) {
            printf("\nConverting from %s%2i to %s%2i", 
               GetFileFormatName(FileType), WordSize, 
               GetFileFormatName(cmd.OutputType), WordSize);
         }
         else {
            printf("\nModifying %s%2i file", GetFileFormatName(FileType), WordSize);
         }
      }

      // Check underscore options
      if (cmd.Underscore && cmd.OutputType != 0) {
         if (cmd.Underscore == CMDL_UNDERSCORE_CHANGE) {
            // Find underscore option for desired conversion
            if (WordSize == 32) {
               // In 32-bit, all formats except ELF have underscores
               if (FileType == FILETYPE_ELF && cmd.OutputType != FILETYPE_ELF) {
                  // Converting from ELF32. Add underscores
                  cmd.Underscore = CMDL_UNDERSCORE_ADD;
               }
               else if (FileType != FILETYPE_ELF && cmd.OutputType == FILETYPE_ELF) {
                  // Converting to ELF32. Remove underscores
                  cmd.Underscore = CMDL_UNDERSCORE_REMOVE;
               }
               else {
                  // Anything else 32-bit. No change
                  cmd.Underscore = CMDL_UNDERSCORE_NOCHANGE;
               }
            }
            else { 
               // In 64-bit, only Mach-O has underscores
               if (FileType == FILETYPE_MACHO_LE && cmd.OutputType != FILETYPE_MACHO_LE) {
                  // Converting from MachO-64. Remove underscores
                  cmd.Underscore = CMDL_UNDERSCORE_REMOVE;
               }
               else if (FileType != FILETYPE_MACHO_LE && cmd.OutputType == FILETYPE_MACHO_LE) {
                  // Converting to MachO-64. Add underscores
                  cmd.Underscore = CMDL_UNDERSCORE_ADD;
               }
               else {
                  // Anything else 64-bit. No change
                  cmd.Underscore = CMDL_UNDERSCORE_NOCHANGE;
               }
            }
         }
         if (cmd.Verbose > (uint32_t)(cmd.LibraryOptions != 0)) { // Tell which option is chosen
            printf("\n%s", Lookup(UnderscoreOptionNames, cmd.Underscore));
         }
      }

      // Check sectionname options
      if (cmd.SegmentDot && cmd.OutputType != 0) {
         if (cmd.SegmentDot == CMDL_SECTIONDOT_CHANGE) {
            if (cmd.OutputType == FILETYPE_COFF || cmd.OutputType == FILETYPE_MACHO_LE || cmd.OutputType == FILETYPE_OMF) {
               // Change leading '.' to '_' in nonstandard section names
               cmd.SegmentDot = CMDL_SECTIONDOT_DOT2U;
            }
            else if (cmd.OutputType == FILETYPE_ELF) {
               // Change leading '_' to '.' in nonstandard section names
               cmd.SegmentDot = CMDL_SECTIONDOT_U2DOT;
            }
            else {
               cmd.SegmentDot = CMDL_SECTIONDOT_NOCHANGE;
            }
         }
         if (cmd.Verbose > (uint32_t)(cmd.LibraryOptions != 0)) { // Tell which option is chosen
            printf("\n%s", Lookup(SectionDotOptionNames, cmd.SegmentDot));
         }
      }

      // Check debug info options
      if (cmd.DebugInfo == CMDL_DEBUG_DEFAULT) {
         cmd.DebugInfo = (FileType != cmd.OutputType) ? CMDL_DEBUG_STRIP : CMDL_DEBUG_PRESERVE;
      }

      // Check exception handler info options
      if (cmd.ExeptionInfo == CMDL_EXCEPTION_DEFAULT) {
         cmd.ExeptionInfo = (FileType != cmd.OutputType) ? CMDL_EXCEPTION_STRIP : CMDL_EXCEPTION_PRESERVE;
      }

      // Choose conversion
      switch (FileType) {

      // Conversion from ELF
      case FILETYPE_ELF:
         switch (cmd.OutputType) {
         case FILETYPE_COFF:
            // Conversion from ELF to COFF
            ELF2ELF();                 // Make symbol changes in ELF file
            if (err.Number()) return;  // Return if error
            ELF2COF();                 // Convert to COFF
            break;

         case FILETYPE_MACHO_LE:
            // Conversion from ELF to Mach-O
            ELF2MAC();                 // Convert to Mach-O
            if (err.Number()) return;  // Return if error
            MAC2MAC();                 // Make symbol changes in Mach-O file, sort symbol tables alphabetically
            break;

         case FILETYPE_OMF:
            // Conversion from ELF to OMF
            ELF2ELF();                 // Make symbol changes in ELF file
            if (err.Number()) return;  // Return if error
            ELF2COF();                 // Convert to COFF first
            if (err.Number()) return;  // Return if error
            COF2OMF();                 // Then convert to OMF
            break;

         case FILETYPE_ELF:
            // Make changes in ELF file
            if (cmd.SymbolChangesRequested()) {
               ELF2ELF();              // Make symbol changes in ELF file
            }
            else if (!cmd.LibraryOptions) {
               err.submit(1006);       // Warning: nothing to do
            }
            break;

         case CMDL_OUTPUT_MASM:
            // Disassemble ELF file
            ELF2ASM();                 // Disassemble
            break;
            
         default:
            // Conversion not supported
            err.submit(2013, GetFileFormatName(FileType), GetFileFormatName(cmd.OutputType));
         }
         break;


      // Conversion from COFF
      case FILETYPE_COFF:
         switch (cmd.OutputType) {
         case FILETYPE_COFF:
            // No conversion. Modify file
            if (cmd.DebugInfo == CMDL_DEBUG_STRIP || cmd.ExeptionInfo == CMDL_EXCEPTION_STRIP) {
               COF2ELF();              // Convert to ELF and back again to strip debug and exception info
               if (err.Number()) return;  // Return if error
               ELF2COF();
               err.submit(1008);       // Warning: Converting to ELF and back again
            }
            if (cmd.SymbolChangesRequested()) {
               COF2COF();              // Make symbol name changes in COFF file
            }
            else if (cmd.DebugInfo != CMDL_DEBUG_STRIP && cmd.ExeptionInfo != CMDL_EXCEPTION_STRIP && !cmd.LibraryOptions) {
               err.submit(1006);       // Warning: nothing to do
            }
            break;

         case FILETYPE_ELF:
            COF2COF();                 // Make symbol changes in COFF file
            if (err.Number()) return;  // Return if error
            COF2ELF();                 // Convert to ELF
            break;
            
         case FILETYPE_OMF:
            COF2COF();                 // Make symbol changes in COFF file
            if (err.Number()) return;  // Return if error
            COF2OMF();                 // Convert to OMF
            break;
            
         case FILETYPE_MACHO_LE:
            COF2ELF();                 // Convert from COFF to ELF
            if (err.Number()) return;  // Return if error
            ELF2MAC();                 // Then convert from ELF to Mach-O
            if (err.Number()) return;  // Return if error
            MAC2MAC();                 // Make symbol changes in Mach-O file and sort symbol table
            break;

         case CMDL_OUTPUT_MASM:
            // Disassemble COFF file
            COF2ASM();                 // Disassemble
            break;
            
         default:
            // Conversion not supported
            err.submit(2013, GetFileFormatName(FileType), GetFileFormatName(cmd.OutputType));
         }
         break;


      // Conversion from OMF
      case FILETYPE_OMF:
         switch (cmd.OutputType) {
         case FILETYPE_OMF:
            // No conversion. Modify file
            if (cmd.SymbolChangesRequested() || cmd.DebugInfo == CMDL_DEBUG_STRIP || cmd.ExeptionInfo == CMDL_EXCEPTION_STRIP) {
               OMF2COF();              // Convert to COFF and back again to do requested changes
               if (err.Number()) return;  // Return if error
               COF2COF();              // Make symbol changes in COFF file
               if (err.Number()) return;  // Return if error
               COF2OMF();
               err.submit(1009);       // Warning: Converting to COFF and back again
            }
            break;

         case FILETYPE_COFF:
            OMF2COF();                 // Convert to COFF
            if (err.Number()) return;  // Return if error
            COF2COF();                 // Make symbol changes in COFF file
            break;

         case FILETYPE_ELF:
            OMF2COF();                 // Convert to COFF
            if (err.Number()) return;  // Return if error
            COF2COF();                 // Make symbol changes in COFF file
            if (err.Number()) return;  // Return if error
            COF2ELF();                 // Convert to ELF
            break;
            
         case FILETYPE_MACHO_LE:
            OMF2COF();                 // Convert to COFF
            if (err.Number()) return;  // Return if error
            COF2ELF();                 // Convert from COFF to ELF
            if (err.Number()) return;  // Return if error
            ELF2MAC();                 // Then convert from ELF to Mach-O
            if (err.Number()) return;  // Return if error
            MAC2MAC();                 // Make symbol changes in Mach-O file and sort symbol table
            break;

         case CMDL_OUTPUT_MASM:
            // Disassemble OMF file
            OMF2ASM();                 // Disassemble
            break;
            
         default:
            // Conversion not supported
            err.submit(2013, GetFileFormatName(FileType), GetFileFormatName(cmd.OutputType));
         }
         break;

      // Conversions from Mach-O
      case FILETYPE_MACHO_LE:

         switch (cmd.OutputType) {
         case FILETYPE_ELF:
            MAC2ELF();                 // Convert to ELF
            if (err.Number()) return;  // Return if error
            ELF2ELF();                 // Make symbol changes in ELF file
            break;

         case FILETYPE_COFF:
            MAC2ELF();                 // Convert to ELF
            if (err.Number()) return;  // Return if error
            ELF2ELF();                 // Make symbol changes in ELF file
            if (err.Number()) return;  // Return if error
            ELF2COF();                 // Convert to COFF
            break;

         case FILETYPE_OMF:
            MAC2ELF();                 // Convert to ELF
            if (err.Number()) return;  // Return if error
            ELF2ELF();                 // Make symbol changes in ELF file
            if (err.Number()) return;  // Return if error
            ELF2COF();                 // Convert to COFF
            if (err.Number()) return;  // Return if error
            COF2OMF();                 // Convert to OMF
            break;

         case FILETYPE_MACHO_LE:
            MAC2MAC();                 // Make symbol changes in mACH-o file
            break;

         case CMDL_OUTPUT_MASM:
            // Disassemble Mach-O file
            MAC2ASM();                 // Disassemble
            break;
            
         default:
            // Conversion not supported
            err.submit(2013, GetFileFormatName(FileType), GetFileFormatName(cmd.OutputType));
         }
         break;

      case FILETYPE_MAC_UNIVBIN:
         ParseMACUnivBin();   break;

      // Conversion from other types
      default:
         err.submit(2006, FileName, GetFileFormatName(FileType));   // Conversion of this file type not supported
      }
   }
}