1 /****************************   main.cpp   **********************************
2 * Author:        Agner Fog
3 * Date created:  2006-07-26
4 * Last modified: 2011-10-28
5 * Project:       objconv
6 * Module:        main.cpp
7 * Description:
8 * Objconv is a portable C++ program for converting object file formats.
9 * Compile for console mode on any platform.
10 *
11 * Module main contains the program entry
12 *
13 * Copyright 2006-2011 GNU General Public License http://www.gnu.org/licenses
14 *****************************************************************************/
15 
16 #include "stdafx.h"
17 
18 // Texts of option feedback. Adding or removing leading underscores on symbols
19 SIntTxt UnderscoreOptionNames[] = {
20    {CMDL_UNDERSCORE_NOCHANGE, "Not adding or removing underscores for this filetype"},
21    {CMDL_UNDERSCORE_REMOVE,   "Removing leading underscores from symbol names"},
22    {CMDL_UNDERSCORE_ADD,      "Adding leading underscores to symbol names"},
23    {CMDL_UNDERSCORE_REMOVE|CMDL_KEEP_ALIAS, "Removing leading underscores from symbol names. Keeping old name as alias"},
24    {CMDL_UNDERSCORE_ADD|CMDL_KEEP_ALIAS,    "Adding leading underscores to symbol names. Keeping old name as alias"}
25 };
26 
27 // Texts of option feedback. Changing leading dot or underscore on section names
28 SIntTxt SectionDotOptionNames[] = {
29    {CMDL_SECTIONDOT_NOCHANGE, "Not changing leading character on section names for this filetype"},
30    {CMDL_SECTIONDOT_U2DOT, "Changing leading underscores on section names to dot"},
31    {CMDL_SECTIONDOT_DOT2U, "Changing leading dot on nonstandard section names to underscore"}
32 };
33 
34 // Check that integer type definitions are correct.
35 // Will generate an error message if the compiler makes the integer types
36 // with wrong size.
CheckIntegerTypes()37 static void CheckIntegerTypes() {
38    if (
39       sizeof(uint8_t) != 1 ||
40       sizeof(int16_t) != 2 ||
41       sizeof(int32_t) != 4 ||
42       sizeof(int64_t) != 8) {
43       err.submit(9001);                // Make error message if type definitions are wrong
44    }
45 }
46 
47 // Check that we are running on a machine with little-endian memory organization
CheckEndianness()48 static void CheckEndianness() {
49    static uint8_t bytes[4] = {1, 2, 3, 4};
50    if (*(uint32_t*)bytes != 0x04030201) {
51       // Big endian
52       err.submit(9002);
53    }
54 }
55 
56 // Function to convert powers of 2 to index
FloorLog2(uint32_t x)57 int FloorLog2(uint32_t x) {
58    int i = -1;
59    do {
60       x >>= 1;
61       i++;
62    } while (x);
63    return i;
64 }
65 
timestring(uint32_t t)66 const char * timestring(uint32_t t) {
67    // Convert 32 bit time stamp to string
68    // Fix the problem that time_t may be 32 bit or 64 bit
69    union {
70       time_t t;
71       uint32_t t32;
72    } utime;
73    utime.t = 0;
74    utime.t32 = t;
75    const char * string = ctime(&utime.t);
76    if (string == 0) string = "?";
77    return string;
78 }
79 
80 // Main. Program starts here
main(int argc,char * argv[])81 int main(int argc, char * argv[]) {
82    CheckIntegerTypes();                // Check that compiler has the right integer sizes
83    CheckEndianness();                  // Check that machine is little-endian
84 
85 #ifdef  _DEBUG
86    // For debugging only. You may remove this
87    if (argc == 1) {
88       const char * dummyarg[] = {"", "@resp.txt"}; // Read command line from file resp.txt
89       argc = 2; argv = (char**)dummyarg;}
90 #endif
91 
92    cmd.ReadCommandLine(argc, argv);    // Read command line parameters
93    if (cmd.ShowHelp) return 0;         // Help screen has been printed. Do nothing else
94 
95    CMain maincvt;                      // This object takes care of all conversions etc.
96    maincvt.Go();
97    // Do everything the command line says
98 
99    if (cmd.Verbose) printf("\n");      // End with newline
100    return err.GetWorstError();         // Return with error code
101 }
102 
103 
104 // Class CMainConverter is used for control of the conversion process
CMain()105 CMain::CMain() : CFileBuffer() {
106 }
107 
Go()108 void CMain::Go() {
109    // Do whatever the command line parameters say
110    FileName = cmd.InputFile;           // Get input file name from command line
111    // Ignore nonexisting filename when building library
112    int IgnoreError = (cmd.FileOptions & CMDL_FILE_IN_IF_EXISTS) && !cmd.OutputFile;
113    Read(IgnoreError);                  // Read input file
114    GetFileType();                      // Determine file type
115    cmd.InputType = FileType;           // Save input file type in cmd for access from other modules
116    if (cmd.OutputType == 0) {
117        // desired type not specified
118        cmd.OutputType = FileType;
119    }
120    if (err.Number()) return;           // Return if error
121    CheckOutputFileName();              // Construct output file name with default extension
122    if (err.Number()) return;
123 
124    if ((FileType & (FILETYPE_LIBRARY | FILETYPE_OMFLIBRARY))
125    || (cmd.LibraryOptions & CMDL_LIBRARY_ADDMEMBER)) {
126       // Input file is a library or we are building a library
127       CLibrary lib;                    // Library handler object
128       *this >> lib;                    // Transfer my file buffer to lib
129       lib.Go();                        // Do conversion or dump
130       *this << lib;                    // Get file buffer back
131    }
132    else {
133       // Input file is an object file
134       CConverter conv;                 // Make converter object
135       *this >> conv;                   // Transfer my file buffer to conv
136       conv.Go();                       // Do conversion or dump
137       *this << conv;                   // Get file buffer back
138    }
139    if ((cmd.FileOptions & CMDL_FILE_OUTPUT) && OutputFileName) {
140       // There is an output file to write
141       cmd.CheckSymbolModifySuccess();  // Check if symbols to modify were found
142       if (err.Number()) return;        // Return if error
143       FileName = OutputFileName;       // Output file name
144       Write();                         // Write output file
145       if (cmd.Verbose) cmd.ReportStatistics(); // Report statistics
146    }
147 }
148 
CConverter()149 CConverter::CConverter() {
150    // Constructor
151 }
152 
DumpCOF()153 void CConverter::DumpCOF() {
154    // Dump COFF file
155    CCOFF cof;                          // Make object for interpreting COFF file
156    *this >> cof;                       // Give it my buffer
157    cof.ParseFile();                    // Parse file buffer
158    if (err.Number()) return;           // Return if error
159    cof.Dump(cmd.DumpOptions);          // Dump file
160    *this << cof;                       // Take back my buffer
161 }
162 
DumpELF()163 void CConverter::DumpELF() {
164    // Dump ELF file
165    if (WordSize == 32) {
166       // Make object for interpreting 32 bit ELF file
167       CELF<ELF32STRUCTURES> elf;
168       *this >> elf;                    // Give it my buffer
169       elf.ParseFile();                 // Parse file buffer
170       if (err.Number()) return;        // Return if error
171       elf.Dump(cmd.DumpOptions);       // Dump file
172       *this << elf;                    // Take back my buffer
173    }
174    else {
175       // Make object for interpreting 32 bit ELF file
176       CELF<ELF64STRUCTURES> elf;
177       *this >> elf;                    // Give it my buffer
178       elf.ParseFile();                 // Parse file buffer
179       if (err.Number()) return;        // Return if error
180       elf.Dump(cmd.DumpOptions);       // Dump file
181       *this << elf;                    // Take back my buffer
182    }
183 }
184 
DumpMACHO()185 void CConverter::DumpMACHO() {
186    // Dump Mach-O file
187    if (WordSize == 32) {
188       // Make object for interpreting 32 bit Mach-O file
189       CMACHO<MAC32STRUCTURES> macho;
190       *this >> macho;                     // Give it my buffer
191       macho.ParseFile();                  // Parse file buffer
192       if (err.Number()) return;           // Return if error
193       macho.Dump(cmd.DumpOptions);        // Dump file
194       *this << macho;                     // Take back my buffer
195    }
196    else {
197       // Make object for interpreting 64 bit Mach-O file
198       CMACHO<MAC64STRUCTURES> macho;
199       *this >> macho;                     // Give it my buffer
200       macho.ParseFile();                  // Parse file buffer
201       if (err.Number()) return;           // Return if error
202       macho.Dump(cmd.DumpOptions);        // Dump file
203       *this << macho;                     // Take back my buffer
204    }
205 }
206 
ParseMACUnivBin()207 void CConverter::ParseMACUnivBin() {
208    // Dump Mac universal binary
209    CMACUNIV macuniv;                   // Make object for interpreting Mac universal binary file
210    *this >> macuniv;                   // Give it my buffer
211    macuniv.Go(cmd.DumpOptions);        // Dump file components
212    *this << macuniv;                   // Take back my buffer
213 }
214 
DumpOMF()215 void CConverter::DumpOMF() {
216    // Dump OMF file
217    COMF omf;                           // Make object for interpreting OMF file
218    *this >> omf;                       // Give it my buffer
219    omf.ParseFile();                    // Parse file buffer
220    if (err.Number()) return;           // Return if error
221    omf.Dump(cmd.DumpOptions);          // Dump file
222    *this << omf;                       // Take back my buffer
223 }
224 
COF2ELF()225 void CConverter::COF2ELF() {
226    // Convert COFF to ELF file
227    if (WordSize == 32) {
228       // Make instance of converter, 32 bit template
229       CCOF2ELF<ELF32STRUCTURES> conv;  // Make object for conversion
230       *this >> conv;                   // Give it my buffer
231       conv.ParseFile();                // Parse file buffer
232       if (err.Number()) return;        // Return if error
233       conv.Convert();                  // Convert
234       *this << conv;                   // Take back converted buffer
235    }
236    else {
237       // Make instance of converter, 64 bit template
238       CCOF2ELF<ELF64STRUCTURES> conv;  // Make object for conversion
239       *this >> conv;                   // Give it my buffer
240       conv.ParseFile();                // Parse file buffer
241       if (err.Number()) return;        // Return if error
242       conv.Convert();                  // Convert
243       *this << conv;                   // Take back converted buffer
244    }
245 }
246 
COF2OMF()247 void CConverter::COF2OMF() {
248    // Convert COFF to OMF file
249    CCOF2OMF conv;                      // Make object for conversion
250    *this >> conv;                      // Give it my buffer
251    conv.ParseFile();                   // Parse file buffer
252    if (err.Number()) return;           // Return if error
253    conv.Convert();                     // Convert
254    *this << conv;                      // Take back converted buffer
255 }
256 
OMF2COF()257 void CConverter::OMF2COF() {
258    // Convert OMF to COFF file
259    COMF2COF conv;                      // Make object for conversion
260    *this >> conv;                      // Give it my buffer
261    conv.ParseFile();                   // Parse file buffer
262    if (err.Number()) return;           // Return if error
263    conv.Convert();                     // Convert
264    *this << conv;                      // Take back converted buffer
265 }
266 
ELF2COF()267 void CConverter::ELF2COF() {
268    // Convert ELF to COFF file
269    if (WordSize == 32) {
270       // Make instance of converter, 32 bit template
271       CELF2COF<ELF32STRUCTURES> conv;
272       *this >> conv;                   // Give it my buffer
273       conv.ParseFile();                // Parse file buffer
274       if (err.Number()) return;        // Return if error
275       conv.Convert();                  // Convert
276       *this << conv;                   // Take back converted buffer
277    }
278    else {
279       // Make instance of converter, 64 bit template
280       CELF2COF<ELF64STRUCTURES> conv;
281       *this >> conv;                   // Give it my buffer
282       conv.ParseFile();                // Parse file buffer
283       if (err.Number()) return;        // Return if error
284       conv.Convert();                  // Convert
285       *this << conv;                   // Take back converted buffer
286    }
287 }
288 
ELF2MAC()289 void CConverter::ELF2MAC() {
290    // Convert ELF to Mach-O file
291    if (WordSize == 32) {
292       // Make instance of converter, 32 bit template
293       CELF2MAC<ELF32STRUCTURES,MAC32STRUCTURES> conv;
294       *this >> conv;                      // Give it my buffer
295       conv.ParseFile();                   // Parse file buffer
296       if (err.Number()) return;           // Return if error
297       conv.Convert();                     // Convert
298       *this << conv;                      // Take back converted buffer
299    }
300    else {
301       // Make instance of converter, 64 bit template
302       CELF2MAC<ELF64STRUCTURES,MAC64STRUCTURES> conv;
303       *this >> conv;                      // Give it my buffer
304       conv.ParseFile();                   // Parse file buffer
305       if (err.Number()) return;           // Return if error
306       conv.Convert();                     // Convert
307       *this << conv;                      // Take back converted buffer
308    }
309 }
310 
MAC2ELF()311 void CConverter::MAC2ELF() {
312    // Convert Mach-O file to ELF file
313    if (WordSize == 32) {
314       // Make instance of converter, 32 bit template
315       CMAC2ELF<MAC32STRUCTURES,ELF32STRUCTURES> conv;
316       *this >> conv;                      // Give it my buffer
317       conv.ParseFile();                   // Parse file buffer
318       if (err.Number()) return;           // Return if error
319       conv.Convert();                     // Convert
320       *this << conv;                      // Take back converted buffer
321    }
322    else {
323       // Make instance of converter, 64 bit template
324       CMAC2ELF<MAC64STRUCTURES,ELF64STRUCTURES> conv;
325       *this >> conv;                      // Give it my buffer
326       conv.ParseFile();                   // Parse file buffer
327       if (err.Number()) return;           // Return if error
328       conv.Convert();                     // Convert
329       *this << conv;                      // Take back converted buffer
330    }
331 }
332 
COF2ASM()333 void CConverter::COF2ASM() {
334    // Disassemble COFF file
335    CCOF2ASM conv;                      // Make object for conversion
336    *this >> conv;                      // Give it my buffer
337    conv.ParseFile();                   // Parse file buffer
338    if (err.Number()) return;           // Return if error
339    conv.Convert();                     // Convert
340    *this << conv;                      // Take back converted buffer
341 }
342 
ELF2ASM()343 void CConverter::ELF2ASM() {
344    // Disassemble ELF file
345    if (WordSize == 32) {
346       // Make instance of converter, 32 bit template
347       CELF2ASM<ELF32STRUCTURES> conv;
348       *this >> conv;                      // Give it my buffer
349       conv.ParseFile();                   // Parse file buffer
350       if (err.Number()) return;           // Return if error
351       conv.Convert();                     // Convert
352       *this << conv;                      // Take back converted buffer
353    }
354    else {
355       // Make instance of converter, 64 bit template
356       CELF2ASM<ELF64STRUCTURES> conv;
357       *this >> conv;                      // Give it my buffer
358       conv.ParseFile();                   // Parse file buffer
359       if (err.Number()) return;           // Return if error
360       conv.Convert();                     // Convert
361       *this << conv;                      // Take back converted buffer
362    }
363 }
364 
MAC2ASM()365 void CConverter::MAC2ASM() {
366    // Disassemble Mach-O file
367    if (WordSize == 32) {
368       // Make instance of converter, 32 bit template
369       CMAC2ASM<MAC32STRUCTURES> conv;
370       *this >> conv;                      // Give it my buffer
371       conv.ParseFile();                   // Parse file buffer
372       if (err.Number()) return;           // Return if error
373       conv.Convert();                     // Convert
374       *this << conv;                      // Take back converted buffer
375    }
376    else {
377       // Make instance of converter, 64 bit template
378       CMAC2ASM<MAC64STRUCTURES> conv;
379       *this >> conv;                      // Give it my buffer
380       conv.ParseFile();                   // Parse file buffer
381       if (err.Number()) return;           // Return if error
382       conv.Convert();                     // Convert
383       *this << conv;                      // Take back converted buffer
384    }
385 }
386 
OMF2ASM()387 void CConverter::OMF2ASM() {
388    // Disassemble OMF file
389    COMF2ASM conv;                      // Make object for conversion
390    *this >> conv;                      // Give it my buffer
391    conv.ParseFile();                   // Parse file buffer
392    if (err.Number()) return;           // Return if error
393    conv.Convert();                     // Convert
394    *this << conv;                      // Take back converted buffer
395 }
396 
COF2COF()397 void CConverter::COF2COF() {
398    // Make changes in COFF file
399    CCOF2COF conv;                      // Make instance of converter
400    *this >> conv;                      // Give it my buffer
401    conv.ParseFile();                   // Parse file buffer
402    if (err.Number()) return;           // Return if error
403    conv.Convert();                     // Convert
404    *this << conv;                      // Take back converted buffer
405 }
406 
ELF2ELF()407 void CConverter::ELF2ELF() {
408    // Make changes in ELF file
409    if (WordSize == 32) {
410       // Make instance of converter, 32 bit template
411       CELF2ELF<ELF32STRUCTURES> conv;
412       *this >> conv;                   // Give it my buffer
413       conv.ParseFile();                // Parse file buffer
414       if (err.Number()) return;        // Return if error
415       conv.Convert();                  // Convert
416       *this << conv;                   // Take back converted buffer
417    }
418    else {
419       // Make instance of converter, 64 bit template
420       CELF2ELF<ELF64STRUCTURES> conv;
421       *this >> conv;                   // Give it my buffer
422       conv.ParseFile();                // Parse file buffer
423       if (err.Number()) return;        // Return if error
424       conv.Convert();                  // Convert
425       *this << conv;                   // Take back converted buffer
426    }
427 }
428 
MAC2MAC()429 void CConverter::MAC2MAC() {
430    // Make changes in Mach-O file
431    if (WordSize == 32) {
432       // Make instance of converter, 32 bit template
433       CMAC2MAC<MAC32STRUCTURES> conv;
434       *this >> conv;                   // Give it my buffer
435       conv.ParseFile();                // Parse file buffer
436       if (err.Number()) return;        // Return if error
437       conv.Convert();                  // Convert
438       *this << conv;                   // Take back converted buffer
439    }
440    else {
441       // Make instance of converter, 64 bit template
442       CMAC2MAC<MAC64STRUCTURES> conv;
443       *this >> conv;                   // Give it my buffer
444       conv.ParseFile();                // Parse file buffer
445       if (err.Number()) return;        // Return if error
446       conv.Convert();                  // Convert
447       *this << conv;                   // Take back converted buffer
448    }
449 }
450 
Go()451 void CConverter::Go() {
452    // Convert or dump file, depending on command line parameters
453    GetFileType();                      // Determine file type
454    cmd.InputType = FileType;           // Save input file type in cmd for access from other modules
455    if (err.Number()) return;           // Return if error
456 
457    if (cmd.OutputType == CMDL_OUTPUT_DUMP) {
458       // File dump requested
459       if (cmd.Verbose > 0) {
460          // Tell what we are doing:
461          printf("\nDump of file: %s, type: %s%i", FileName, GetFileFormatName(FileType), WordSize);
462       }
463 
464       switch(FileType) {
465       case FILETYPE_ELF:
466          DumpELF();  break;
467 
468       case FILETYPE_COFF:
469          DumpCOF();   break;
470 
471       case FILETYPE_MACHO_LE:
472          DumpMACHO();   break;
473 
474       case FILETYPE_OMF:
475          DumpOMF();   break;
476 
477       case FILETYPE_MAC_UNIVBIN:
478          ParseMACUnivBin();   break;
479 
480       default:
481          err.submit(2010, GetFileFormatName(FileType));  // Dump of this file type not supported
482       }
483       printf("\n");                              // New line
484    }
485    else {
486       // File conversion requested
487       if (cmd.DesiredWordSize == 0) cmd.DesiredWordSize = WordSize;
488       if (WordSize && WordSize != cmd.DesiredWordSize) {
489          err.submit(2012, WordSize, cmd.DesiredWordSize); // Cannot convert word size
490          return;
491       }
492       if (Executable && cmd.OutputType != CMDL_OUTPUT_MASM) {
493          // Attempt to convert executable file
494          err.submit(2022);
495       }
496       if (err.Number()) return;        // Return if error
497 
498       if (cmd.Verbose > (uint32_t)(cmd.LibraryOptions != 0)) {
499          // Tell what we are doing:
500          printf("\nInput file: %s, output file: %s", FileName, OutputFileName);
501          if (FileType != cmd.OutputType) {
502             printf("\nConverting from %s%2i to %s%2i",
503                GetFileFormatName(FileType), WordSize,
504                GetFileFormatName(cmd.OutputType), WordSize);
505          }
506          else {
507             printf("\nModifying %s%2i file", GetFileFormatName(FileType), WordSize);
508          }
509       }
510 
511       // Check underscore options
512       if (cmd.Underscore && cmd.OutputType != 0) {
513          if (cmd.Underscore == CMDL_UNDERSCORE_CHANGE) {
514             // Find underscore option for desired conversion
515             if (WordSize == 32) {
516                // In 32-bit, all formats except ELF have underscores
517                if (FileType == FILETYPE_ELF && cmd.OutputType != FILETYPE_ELF) {
518                   // Converting from ELF32. Add underscores
519                   cmd.Underscore = CMDL_UNDERSCORE_ADD;
520                }
521                else if (FileType != FILETYPE_ELF && cmd.OutputType == FILETYPE_ELF) {
522                   // Converting to ELF32. Remove underscores
523                   cmd.Underscore = CMDL_UNDERSCORE_REMOVE;
524                }
525                else {
526                   // Anything else 32-bit. No change
527                   cmd.Underscore = CMDL_UNDERSCORE_NOCHANGE;
528                }
529             }
530             else {
531                // In 64-bit, only Mach-O has underscores
532                if (FileType == FILETYPE_MACHO_LE && cmd.OutputType != FILETYPE_MACHO_LE) {
533                   // Converting from MachO-64. Remove underscores
534                   cmd.Underscore = CMDL_UNDERSCORE_REMOVE;
535                }
536                else if (FileType != FILETYPE_MACHO_LE && cmd.OutputType == FILETYPE_MACHO_LE) {
537                   // Converting to MachO-64. Add underscores
538                   cmd.Underscore = CMDL_UNDERSCORE_ADD;
539                }
540                else {
541                   // Anything else 64-bit. No change
542                   cmd.Underscore = CMDL_UNDERSCORE_NOCHANGE;
543                }
544             }
545          }
546          if (cmd.Verbose > (uint32_t)(cmd.LibraryOptions != 0)) { // Tell which option is chosen
547             printf("\n%s", Lookup(UnderscoreOptionNames, cmd.Underscore));
548          }
549       }
550 
551       // Check sectionname options
552       if (cmd.SegmentDot && cmd.OutputType != 0) {
553          if (cmd.SegmentDot == CMDL_SECTIONDOT_CHANGE) {
554             if (cmd.OutputType == FILETYPE_COFF || cmd.OutputType == FILETYPE_MACHO_LE || cmd.OutputType == FILETYPE_OMF) {
555                // Change leading '.' to '_' in nonstandard section names
556                cmd.SegmentDot = CMDL_SECTIONDOT_DOT2U;
557             }
558             else if (cmd.OutputType == FILETYPE_ELF) {
559                // Change leading '_' to '.' in nonstandard section names
560                cmd.SegmentDot = CMDL_SECTIONDOT_U2DOT;
561             }
562             else {
563                cmd.SegmentDot = CMDL_SECTIONDOT_NOCHANGE;
564             }
565          }
566          if (cmd.Verbose > (uint32_t)(cmd.LibraryOptions != 0)) { // Tell which option is chosen
567             printf("\n%s", Lookup(SectionDotOptionNames, cmd.SegmentDot));
568          }
569       }
570 
571       // Check debug info options
572       if (cmd.DebugInfo == CMDL_DEBUG_DEFAULT) {
573          cmd.DebugInfo = (FileType != cmd.OutputType) ? CMDL_DEBUG_STRIP : CMDL_DEBUG_PRESERVE;
574       }
575 
576       // Check exception handler info options
577       if (cmd.ExeptionInfo == CMDL_EXCEPTION_DEFAULT) {
578          cmd.ExeptionInfo = (FileType != cmd.OutputType) ? CMDL_EXCEPTION_STRIP : CMDL_EXCEPTION_PRESERVE;
579       }
580 
581       // Choose conversion
582       switch (FileType) {
583 
584       // Conversion from ELF
585       case FILETYPE_ELF:
586          switch (cmd.OutputType) {
587          case FILETYPE_COFF:
588             // Conversion from ELF to COFF
589             ELF2ELF();                 // Make symbol changes in ELF file
590             if (err.Number()) return;  // Return if error
591             ELF2COF();                 // Convert to COFF
592             break;
593 
594          case FILETYPE_MACHO_LE:
595             // Conversion from ELF to Mach-O
596             ELF2MAC();                 // Convert to Mach-O
597             if (err.Number()) return;  // Return if error
598             MAC2MAC();                 // Make symbol changes in Mach-O file, sort symbol tables alphabetically
599             break;
600 
601          case FILETYPE_OMF:
602             // Conversion from ELF to OMF
603             ELF2ELF();                 // Make symbol changes in ELF file
604             if (err.Number()) return;  // Return if error
605             ELF2COF();                 // Convert to COFF first
606             if (err.Number()) return;  // Return if error
607             COF2OMF();                 // Then convert to OMF
608             break;
609 
610          case FILETYPE_ELF:
611             // Make changes in ELF file
612             if (cmd.SymbolChangesRequested()) {
613                ELF2ELF();              // Make symbol changes in ELF file
614             }
615             else if (!cmd.LibraryOptions) {
616                err.submit(1006);       // Warning: nothing to do
617             }
618             break;
619 
620          case CMDL_OUTPUT_MASM:
621             // Disassemble ELF file
622             ELF2ASM();                 // Disassemble
623             break;
624 
625          default:
626             // Conversion not supported
627             err.submit(2013, GetFileFormatName(FileType), GetFileFormatName(cmd.OutputType));
628          }
629          break;
630 
631 
632       // Conversion from COFF
633       case FILETYPE_COFF:
634          switch (cmd.OutputType) {
635          case FILETYPE_COFF:
636             // No conversion. Modify file
637             if (cmd.DebugInfo == CMDL_DEBUG_STRIP || cmd.ExeptionInfo == CMDL_EXCEPTION_STRIP) {
638                COF2ELF();              // Convert to ELF and back again to strip debug and exception info
639                if (err.Number()) return;  // Return if error
640                ELF2COF();
641                err.submit(1008);       // Warning: Converting to ELF and back again
642             }
643             if (cmd.SymbolChangesRequested()) {
644                COF2COF();              // Make symbol name changes in COFF file
645             }
646             else if (cmd.DebugInfo != CMDL_DEBUG_STRIP && cmd.ExeptionInfo != CMDL_EXCEPTION_STRIP && !cmd.LibraryOptions) {
647                err.submit(1006);       // Warning: nothing to do
648             }
649             break;
650 
651          case FILETYPE_ELF:
652             COF2COF();                 // Make symbol changes in COFF file
653             if (err.Number()) return;  // Return if error
654             COF2ELF();                 // Convert to ELF
655             break;
656 
657          case FILETYPE_OMF:
658             COF2COF();                 // Make symbol changes in COFF file
659             if (err.Number()) return;  // Return if error
660             COF2OMF();                 // Convert to OMF
661             break;
662 
663          case FILETYPE_MACHO_LE:
664             COF2ELF();                 // Convert from COFF to ELF
665             if (err.Number()) return;  // Return if error
666             ELF2MAC();                 // Then convert from ELF to Mach-O
667             if (err.Number()) return;  // Return if error
668             MAC2MAC();                 // Make symbol changes in Mach-O file and sort symbol table
669             break;
670 
671          case CMDL_OUTPUT_MASM:
672             // Disassemble COFF file
673             COF2ASM();                 // Disassemble
674             break;
675 
676          default:
677             // Conversion not supported
678             err.submit(2013, GetFileFormatName(FileType), GetFileFormatName(cmd.OutputType));
679          }
680          break;
681 
682 
683       // Conversion from OMF
684       case FILETYPE_OMF:
685          switch (cmd.OutputType) {
686          case FILETYPE_OMF:
687             // No conversion. Modify file
688             if (cmd.SymbolChangesRequested() || cmd.DebugInfo == CMDL_DEBUG_STRIP || cmd.ExeptionInfo == CMDL_EXCEPTION_STRIP) {
689                OMF2COF();              // Convert to COFF and back again to do requested changes
690                if (err.Number()) return;  // Return if error
691                COF2COF();              // Make symbol changes in COFF file
692                if (err.Number()) return;  // Return if error
693                COF2OMF();
694                err.submit(1009);       // Warning: Converting to COFF and back again
695             }
696             break;
697 
698          case FILETYPE_COFF:
699             OMF2COF();                 // Convert to COFF
700             if (err.Number()) return;  // Return if error
701             COF2COF();                 // Make symbol changes in COFF file
702             break;
703 
704          case FILETYPE_ELF:
705             OMF2COF();                 // Convert to COFF
706             if (err.Number()) return;  // Return if error
707             COF2COF();                 // Make symbol changes in COFF file
708             if (err.Number()) return;  // Return if error
709             COF2ELF();                 // Convert to ELF
710             break;
711 
712          case FILETYPE_MACHO_LE:
713             OMF2COF();                 // Convert to COFF
714             if (err.Number()) return;  // Return if error
715             COF2ELF();                 // Convert from COFF to ELF
716             if (err.Number()) return;  // Return if error
717             ELF2MAC();                 // Then convert from ELF to Mach-O
718             if (err.Number()) return;  // Return if error
719             MAC2MAC();                 // Make symbol changes in Mach-O file and sort symbol table
720             break;
721 
722          case CMDL_OUTPUT_MASM:
723             // Disassemble OMF file
724             OMF2ASM();                 // Disassemble
725             break;
726 
727          default:
728             // Conversion not supported
729             err.submit(2013, GetFileFormatName(FileType), GetFileFormatName(cmd.OutputType));
730          }
731          break;
732 
733       // Conversions from Mach-O
734       case FILETYPE_MACHO_LE:
735 
736          switch (cmd.OutputType) {
737          case FILETYPE_ELF:
738             MAC2ELF();                 // Convert to ELF
739             if (err.Number()) return;  // Return if error
740             ELF2ELF();                 // Make symbol changes in ELF file
741             break;
742 
743          case FILETYPE_COFF:
744             MAC2ELF();                 // Convert to ELF
745             if (err.Number()) return;  // Return if error
746             ELF2ELF();                 // Make symbol changes in ELF file
747             if (err.Number()) return;  // Return if error
748             ELF2COF();                 // Convert to COFF
749             break;
750 
751          case FILETYPE_OMF:
752             MAC2ELF();                 // Convert to ELF
753             if (err.Number()) return;  // Return if error
754             ELF2ELF();                 // Make symbol changes in ELF file
755             if (err.Number()) return;  // Return if error
756             ELF2COF();                 // Convert to COFF
757             if (err.Number()) return;  // Return if error
758             COF2OMF();                 // Convert to OMF
759             break;
760 
761          case FILETYPE_MACHO_LE:
762             MAC2MAC();                 // Make symbol changes in mACH-o file
763             break;
764 
765          case CMDL_OUTPUT_MASM:
766             // Disassemble Mach-O file
767             MAC2ASM();                 // Disassemble
768             break;
769 
770          default:
771             // Conversion not supported
772             err.submit(2013, GetFileFormatName(FileType), GetFileFormatName(cmd.OutputType));
773          }
774          break;
775 
776       case FILETYPE_MAC_UNIVBIN:
777          ParseMACUnivBin();   break;
778 
779       // Conversion from other types
780       default:
781          err.submit(2006, FileName, GetFileFormatName(FileType));   // Conversion of this file type not supported
782       }
783    }
784 }
785