Subversion Repositories Kolibri OS

Rev

Rev 8959 | Rev 9080 | Go to most recent revision | Blame | Compare with Previous | Last modification | View Log | Download | RSS feed

  1. #include <stdlib.h>
  2. #include <stdio.h>
  3. #include <stdint.h>
  4. #include <assert.h>
  5. #include <string.h>
  6.  
  7. #define EPEP_INST
  8. #include "epep/epep.h"
  9.  
  10. const char *epep_errors[] = {
  11.         "EPEP_ERR_SUCCESS",
  12.         "EPEP_ERR_DATA_DIRECTORY_INDEX_IS_INVALID",
  13.         "EPEP_ERR_SECTION_HEADER_INDEX_IS_INVALID",
  14.         "EPEP_ERR_SYMBOL_INDEX_IS_INVALID",
  15.         "EPEP_ERR_NOT_AN_OBJECT",
  16.         "EPEP_ERR_ADDRESS_IS_OUT_OF_SECTION_RAW_DATA",
  17.         "EPEP_ERR_OUTPUT_CAPACITY_IS_ZERO",
  18.         "EPEP_ERR_OUTPUT_IS_NULL",
  19.         "EPEP_ERR_ADDRESS_IS_OUT_OF_ANY_SECTION",
  20.         "EPEP_ERR_EXPORT_ADDRESS_TABLE_ENTRY_NAME_NOT_FOUND",
  21.         "EPEP_ERR_NO_BASE_RELOCATION_TABLE",
  22.         "EPEP_ERR_BASE_RELOCATION_IS_ALREADY_END",
  23.         "EPEP_ERR_INVALID_DATA_DIRECTORY_OFFSET",
  24.         "EPEP_ERR_INVALID_SECTION_HEADER_OFFSET",
  25.         "EPEP_ERR_INVALID_SECTION_DATA_OFFSET",
  26.         "EPEP_ERR_INVALID_STRING_TABLE_SIZE_OFFSET",
  27.         "EPEP_ERR_INVALID_SYMBOL_OFFSET",
  28.         "EPEP_ERR_INVALID_IMPORT_DIRECTORY_OFFSET",
  29.         "EPEP_ERR_INVALID_IMPORT_DIRECTORY_NAME_OFFSET",
  30.         "EPEP_ERR_INVALID_LOOKUP_OFFSET",
  31.         "EPEP_ERR_INVALID_LOOKUP_NAME_OFFSET",
  32.         "EPEP_ERR_INVALID_EXPORT_TABLE_OFFSET",
  33.         "EPEP_ERR_INVALID_DLL_NAME_OFFSET",
  34.         "EPEP_ERR_INVALID_EXPORT_NAME_POINTER_OFFSET",
  35.         "EPEP_ERR_INVALID_ORDINAL_TABLE_OFFSET",
  36.         "EPEP_ERR_INVALID_EXPORT_NAME_OFFSET",
  37.         "EPEP_ERR_INVALID_EXPORT_ADDRESS_OFFSET",
  38.         "EPEP_ERR_INVALID_FORWARDER_OFFSET",
  39.         "EPEP_ERR_INVALID_BASE_RELOCATION_BLOCK_OFFSET",
  40.         "EPEP_ERR_INVALID_NEXT_BASE_RELOCATION_BLOCK_OFFSET",
  41.         "EPEP_ERR_INVALID_BASE_RELOCATION_BLOCK_BASE_RELOCATION_OFFSET",
  42.         "EPEP_ERR_INVALID_SECTION_RELOCATION_OFFSET",
  43.         "EPEP_ERR_INVALID_LINENUMBER_OFFSET",
  44. };
  45.  
  46. typedef char *pchar;
  47.  
  48. typedef struct {
  49.         Epep epep;
  50.         char *name;
  51.         size_t *section_offsets;
  52. } CoffObject;
  53.  
  54. typedef struct {
  55.         size_t obj_id;
  56.         size_t sec_id;
  57. } ObjIdSecId;
  58.  
  59. typedef struct {
  60.         ObjIdSecId *source;
  61.         uint32_t characteristics;
  62.         size_t size;
  63.         size_t number_of_relocations;
  64. } SectionInfo;
  65.  
  66. typedef struct {
  67.         EpepCoffSymbol sym;
  68.         EpepCoffSymbol *auxes;
  69.         char *name;
  70.         size_t object_index;
  71.         size_t index;
  72. } Symbol;
  73.  
  74. #define CDICT_VAL_T SectionInfo
  75. #define CDICT_INST
  76. #include "cdict/cdict.h"
  77.  
  78. #define CDICT_VAL_T Symbol
  79. #define CDICT_INST
  80. #include "cdict/cdict.h"
  81.  
  82. typedef struct {
  83.         CoffObject *objects;
  84.         char **section_names_set;
  85.         CDict_CStr_SectionInfo info_per_section;
  86.         CDict_CStr_Symbol symtab;
  87.         char **sym_name_set;
  88.         size_t number_of_symbols;
  89. } ObjectIr;
  90.  
  91. #define CVEC_INST
  92. #define CVEC_TYPE CoffObject
  93. #include "cvec/cvec.h"
  94.  
  95. #define CVEC_INST
  96. #define CVEC_TYPE size_t
  97. #include "cvec/cvec.h"
  98.  
  99. #define CVEC_INST
  100. #define CVEC_TYPE pchar
  101. #include "cvec/cvec.h"
  102.  
  103. #define CVEC_INST
  104. #define CVEC_TYPE char
  105. #include "cvec/cvec.h"
  106.  
  107. #define CVEC_INST
  108. #define CVEC_TYPE ObjIdSecId
  109. #include "cvec/cvec.h"
  110.  
  111. #define CVEC_INST
  112. #define CVEC_TYPE EpepCoffSymbol
  113. #include "cvec/cvec.h"
  114.  
  115. #define ERROR_EPEP(epep) printf("Error: epep returned %u (%s) at "__FILE__":%u", \
  116.                                 (epep)->error_code, epep_errors[(epep)->error_code], __LINE__); exit(-1)
  117.  
  118. #define ERROR_CDICT(cdict) printf("Error: cdict returned %u at "__FILE__":%u", \
  119.                                   (cdict)->error_code, __LINE__); exit(-1);
  120.  
  121. static void fwrite8(FILE *f, uint8_t b) {
  122.         fputc(b, f);
  123. }
  124.  
  125. static void fwrite16(FILE *f, uint16_t w) {
  126.         fputc((w & 0x00ff) >> 0, f);
  127.         fputc((w & 0xff00) >> 8, f);
  128. }
  129.  
  130. static void fwrite32(FILE *f, uint32_t d) {
  131.         fputc((d & 0x000000ff) >> 0, f);
  132.         fputc((d & 0x0000ff00) >> 8, f);
  133.         fputc((d & 0x00ff0000) >> 16, f);
  134.         fputc((d & 0xff000000) >> 24, f);
  135. }
  136.  
  137. static size_t strtab_add(char **strtab, char *str) {
  138.         size_t res = cvec_char_size(strtab);
  139.  
  140.         for (char *p = str; *p; p++) {
  141.                 cvec_char_push_back(strtab, *p);
  142.         }
  143.         cvec_char_push_back(strtab, '\0');
  144.         return res + 4;
  145. }
  146.  
  147. static size_t get_section_number(char ***section_names_set, char *sec_name) {
  148.         for (size_t i = 0; i < cvec_pchar_size(section_names_set); i++) {
  149.                 char *it = cvec_pchar_at(section_names_set, i);
  150.                 if (!strcmp(it, sec_name)) {
  151.                         return i + 1;
  152.                 }
  153.         }
  154.         return 0;
  155. }
  156.  
  157. static void add_name_to_set(char *sym_name, char ***set) {
  158.         for (size_t i = 0; i < cvec_pchar_size(set); i++) {
  159.                 char *it = cvec_pchar_at(set, i);
  160.                 if (!strcmp(it, sym_name)) {
  161.                         return;
  162.                 }
  163.         }
  164.         cvec_pchar_push_back(set, sym_name);
  165. }
  166.  
  167. static void build(ObjectIr *ir) {
  168.         FILE *out = fopen("a.out.obj", "wb");
  169.         char *strtab = cvec_char_new(1024);
  170.         size_t size_of_sections = 0;
  171.         size_t number_of_relocations = 0;
  172.  
  173.         printf("Calculating all sections size and relocations count... ");
  174.         for (size_t sec_i = 0; sec_i < cvec_pchar_size(&ir->section_names_set); sec_i++) {
  175.                 char *name = ir->section_names_set[sec_i];
  176.  
  177.                 SectionInfo si = cdict_CStr_SectionInfo_get_v(&ir->info_per_section, name);
  178.                 size_of_sections += si.size;
  179.                 number_of_relocations += si.number_of_relocations;
  180.         }
  181.         printf("Done: %u & %u\n", size_of_sections, number_of_relocations);
  182.  
  183.         size_t fisrt_section_offset = 20 + 40 * cvec_pchar_size(&ir->section_names_set);
  184.         size_t offset_to_first_relocation = fisrt_section_offset + size_of_sections;
  185.         size_t offset_to_next_relocation = offset_to_first_relocation;
  186.         size_t next_section_offset = fisrt_section_offset;
  187.  
  188.         size_t PointerToSymbolTable = fisrt_section_offset + size_of_sections + number_of_relocations * 10;
  189.  
  190.         // COFF Header
  191.         printf("Writing COFF header... ");
  192.         fwrite16(out, 0x14c);                                   // Machine
  193.         fwrite16(out, cvec_pchar_size(&ir->section_names_set)); // NumberOfSections
  194.         fwrite32(out, 0);                                       // TimeDataStamp
  195.         fwrite32(out, PointerToSymbolTable);                    // PointerToSymbolTable
  196.         fwrite32(out, ir->number_of_symbols);                   // NumberOfSymbols
  197.         fwrite16(out, 0);                                       // SizeOfOptionalHeader
  198.         fwrite16(out, 0);                                       // Characteristics
  199.         printf("Done.\n");
  200.  
  201.         // Section Headers
  202.         printf("Writing section headers {\n");
  203.         for (size_t sec_i = 0; sec_i < cvec_pchar_size(&ir->section_names_set); sec_i++) {
  204.                 char *name = ir->section_names_set[sec_i];
  205.                 SectionInfo si = cdict_CStr_SectionInfo_get_v(&ir->info_per_section, name);
  206.  
  207.                 // Name
  208.                 printf(" Writing %s Section Header... ", name);
  209.                 if (strlen(name) <= 8) {
  210.                         for (size_t i = 0; i < 8; i++) {
  211.                                 size_t sl = strlen(name);
  212.                                 fwrite8(out, i < sl ? name[i] : '\0');
  213.                         }
  214.                 } else {
  215.                         fwrite8(out, '/');
  216.  
  217.                         size_t strtab_index = strtab_add(&strtab, name);
  218.                         char numstr[8] = { 0 };
  219.                         sprintf(numstr, "%u", strtab_index);
  220.                         fwrite(numstr, 1, 7, out);
  221.                 }
  222.                 fwrite32(out, 0);                         // VirtualSize
  223.                 fwrite32(out, 0);                         // VirtualAddress
  224.                 fwrite32(out, si.size);                   // SizeOfRawData
  225.                 fwrite32(out, next_section_offset);       // PointerToRawData
  226.                 next_section_offset += si.size;
  227.                 fwrite32(out, offset_to_next_relocation); // PointerToRelocations
  228.                 offset_to_next_relocation += si.number_of_relocations * 10;
  229.                 fwrite32(out, 0);                         // PointerToLinenumbers
  230.                 fwrite16(out, si.number_of_relocations);  // NumberOfRelocations
  231.                 fwrite16(out, 0);                         // NumberOfLinenumbers
  232.                 fwrite32(out, si.characteristics);        // Characteristics
  233.                 printf("Done.\n");
  234.         }
  235.         printf("}\n");
  236.  
  237.         // Section data
  238.         printf("Writing sections {\n");
  239.         for (size_t sec_i = 0; sec_i < cvec_pchar_size(&ir->section_names_set); sec_i++) {
  240.                 char *name = ir->section_names_set[sec_i];
  241.                 SectionInfo si = cdict_CStr_SectionInfo_get_v(&ir->info_per_section, name);
  242.  
  243.                 printf(" Writing %s... ", name);
  244.                 for (size_t i = 0; i < cvec_ObjIdSecId_size(&si.source); i++) {
  245.                         ObjIdSecId id = cvec_ObjIdSecId_at(&si.source, i);
  246.                         CoffObject *object = &ir->objects[id.obj_id];
  247.                         Epep *epep = &object->epep;
  248.  
  249.                         EpepSectionHeader sh = { 0 };
  250.                         if (!epep_get_section_header_by_index(epep, &sh, id.sec_id)) {
  251.                                 ERROR_EPEP(epep);
  252.                         }
  253.  
  254.                         // If the section contains uninitialized data (BSS)
  255.                         // it should be filled by zeroes
  256.                         // Yes, current implementation emits BSS sections too
  257.                         // cause KOS has no idea they should be allocated automatically
  258.                         // cause FASM has no idea they should be generated without contents
  259.                         // cause Tomasz Grysztar didn't care
  260.                         char *buf = calloc(sh.SizeOfRawData, 1);
  261.  
  262.                         // Othervice it should be filled by its contents from source object
  263.                         if (!(sh.Characteristics & 0x00000080)) {
  264.                                 if (!epep_get_section_contents(epep, &sh, buf)) {
  265.                                         ERROR_EPEP(epep);
  266.                                 }
  267.                         }
  268.  
  269.                         fwrite(buf, 1, sh.SizeOfRawData, out);
  270.                 }
  271.                 printf("Done.\n");
  272.         }
  273.         printf("}\n");
  274.  
  275.         // COFF Relocations
  276.         char **undefined_symbols = cvec_pchar_new(8);
  277.  
  278.         printf("Writing COFF Relocations {\n");
  279.         for (size_t sec_i = 0; sec_i < cvec_pchar_size(&ir->section_names_set); sec_i++) {
  280.                 char *name = ir->section_names_set[sec_i];
  281.                 SectionInfo si = cdict_CStr_SectionInfo_get_v(&ir->info_per_section, name);
  282.  
  283.                 printf(" Writing relocations of %s {\n", name);
  284.                 for (size_t i = 0; i < cvec_ObjIdSecId_size(&si.source); i++) {
  285.                         ObjIdSecId id = cvec_ObjIdSecId_at(&si.source, i);
  286.                         CoffObject *object = &ir->objects[id.obj_id];
  287.                         Epep *epep = &object->epep;
  288.  
  289.                         size_t strtab_size = 0;
  290.                         if (!epep_get_string_table_size(epep, &strtab_size)) {
  291.                                 ERROR_EPEP(epep);
  292.                         }
  293.  
  294.                         char *obj_strtab = malloc(strtab_size);
  295.                         if (!epep_get_string_table(epep, obj_strtab)) {
  296.                                 ERROR_EPEP(epep);
  297.                         }
  298.  
  299.                         EpepSectionHeader sh = { 0 };
  300.                         if (!epep_get_section_header_by_index(epep, &sh, id.sec_id)) {
  301.                                 ERROR_EPEP(epep);
  302.                         }
  303.                         for (size_t rel_i = 0; rel_i < sh.NumberOfRelocations; rel_i++) {
  304.                                 EpepCoffRelocation rel = { 0 };
  305.  
  306.                                 if (!epep_get_section_relocation_by_index(epep, &sh, &rel, rel_i)) {
  307.                                         ERROR_EPEP(epep);
  308.                                 }
  309.                                 printf("  { %02x, %02x, %02x }", rel.VirtualAddress, rel.SymbolTableIndex, rel.Type);
  310.                                 rel.VirtualAddress += object->section_offsets[sec_i];
  311.                                 {
  312.                                         size_t index = rel.SymbolTableIndex;
  313.                                         EpepCoffSymbol sym = { 0 };
  314.  
  315.                                         if (!epep_get_symbol_by_index(epep, &sym, index)) {
  316.                                                 ERROR_EPEP(epep);
  317.                                         }
  318.  
  319.                                         size_t name_max = 1024;
  320.                                         char name[name_max];
  321.  
  322.                                         if (sym.symbol.Zeroes == 0) {
  323.                                                 strcpy(name, &obj_strtab[sym.symbol.Offset]);
  324.                                         } else {
  325.                                                 memcpy(name, sym.symbol.ShortName, 8);
  326.                                                 name[8] = '\0';
  327.                                         }
  328.  
  329.                                         if (!strcmp(name, "_EXPORTS")) {
  330.                                                 strcpy(name, "EXPORTS");
  331.                                         }
  332.  
  333.                                         if (sym.symbol.StorageClass != 2) {
  334.                                                 sprintf(name, "%s@%s", name, object->name);
  335.                                         }
  336.  
  337.                                         Symbol old_sym = cdict_CStr_Symbol_get_v(&ir->symtab, name);
  338.  
  339.                                         if (old_sym.name == NULL) {
  340.                                                 add_name_to_set(strdup(name), &undefined_symbols);
  341.                                         }
  342.  
  343.                                         rel.SymbolTableIndex = old_sym.index;
  344.                                         printf(" -> { %02x, %02x, %02x }: ", rel.VirtualAddress, rel.SymbolTableIndex, rel.Type);
  345.                                         printf("New relocation of %s in %s\n", name, sh.Name);
  346.                                 }
  347.                                 fwrite(&rel, 1, 10, out);
  348.                         }
  349.                 }
  350.                 printf(" }\n");
  351.         }
  352.         printf("}\n");
  353.  
  354.         if (cvec_pchar_size(&undefined_symbols) > 0) {
  355.                 printf("Undefined symbols found, aborting\nUndefined:\n");
  356.                 for (int i = 0; i < cvec_pchar_size(&undefined_symbols); i++) {
  357.                         printf("%s\n", undefined_symbols[i]);
  358.                 }
  359.                 exit(-1);
  360.         }
  361.  
  362.         // Symbols Table
  363.         printf("Writing symbols {\n");
  364.         for (size_t sym_i = 0; sym_i < cvec_pchar_size(&ir->sym_name_set); sym_i++) {
  365.                 char *name = ir->sym_name_set[sym_i];
  366.  
  367.                 Symbol sym = cdict_CStr_Symbol_get_v(&ir->symtab, name);
  368.  
  369.                 if (sym.sym.symbol.SectionNumber == 0xffff ||
  370.                         sym.sym.symbol.SectionNumber == 0xfffe ||
  371.                         (sym.sym.symbol.StorageClass != 2 &&  // Not an external symbol
  372.                          sym.sym.symbol.StorageClass != 3 &&  // Not a static symbol
  373.                          sym.sym.symbol.StorageClass != 6)) { // Not a label
  374.                         fwrite(&sym.sym.symbol, 1, 18, out);
  375.                 } else {
  376.                         size_t sec_name_max = 1024;
  377.                         char sec_name[sec_name_max];
  378.  
  379.                         size_t object_index = sym.object_index;
  380.                         CoffObject *object = &ir->objects[object_index];
  381.                         Epep *epep = &object->epep;
  382.                         size_t section_offset = object->section_offsets[sym.sym.symbol.SectionNumber - 1];
  383.  
  384.                         size_t strtab_size = 0;
  385.                         if (!epep_get_string_table_size(epep, &strtab_size)) {
  386.                                 ERROR_EPEP(epep);
  387.                         }
  388.  
  389.                         char *obj_strtab = malloc(strtab_size);
  390.                         if (!epep_get_string_table(epep, obj_strtab)) {
  391.                                 ERROR_EPEP(epep);
  392.                         }
  393.  
  394.                         EpepSectionHeader sh = { 0 };
  395.                         if (!epep_get_section_header_by_index(epep, &sh, sym.sym.symbol.SectionNumber - 1)) {
  396.                                 ERROR_EPEP(epep);
  397.                         }
  398.  
  399.                         if (sh.Name[0] == '/') {
  400.                                 strcpy(sec_name, &obj_strtab[atoi(&sh.Name[1])]);
  401.                         } else {
  402.                                 memcpy(sec_name, sh.Name, 8);
  403.                                 sec_name[8] = '\0';
  404.                         }
  405.  
  406.                         printf("%s:\n", sym.name);
  407.                         printf(" Section:      %s\n", sec_name);
  408.                         printf(" StorageClass: %u\n", sym.sym.symbol.StorageClass);
  409.  
  410.                         sym.sym.symbol.SectionNumber = get_section_number(&ir->section_names_set, sec_name);
  411.  
  412.                         if (sym.sym.symbol.SectionNumber == 0) {
  413.                                 printf("Internal error: %s section is not found in output file");
  414.                                 exit(-1);
  415.                         }
  416.  
  417.                         sym.sym.symbol.Value += section_offset;
  418.  
  419.                         if (strlen(sym.name) <= 8) {
  420.                                 memcpy(sym.sym.symbol.ShortName, sym.name, 8);
  421.                         } else {
  422.                                 sym.sym.symbol.Zeroes = 0;
  423.                                 sym.sym.symbol.Offset = strtab_add(&strtab, name);
  424.                         }
  425.  
  426.                         fwrite(&sym.sym.symbol, 1, 18, out);
  427.                 }
  428.                 for (size_t aux_i = 0; aux_i < sym.sym.symbol.NumberOfAuxSymbols; aux_i++) {
  429.                         fwrite(&sym.auxes[aux_i].symbol, 1, 18, out);
  430.                 }
  431.         }
  432.         printf("}\n");
  433.  
  434.         // COFF String Table
  435.         printf("Writing COFF String Table... ");
  436.         fwrite32(out, cvec_pchar_size(&strtab) + 4);
  437.         fwrite(strtab, 1, cvec_pchar_size(&strtab), out);
  438.         printf("Done.\n");
  439. }
  440.  
  441. static ObjectIr parse_objects(int argc, char **argv) {
  442.         CoffObject *objects = cvec_CoffObject_new(128);
  443.         char **section_names_set = cvec_pchar_new(4);
  444.         char **sym_name_set = cvec_pchar_new(128);
  445.         size_t number_of_symbols = 0;
  446.  
  447.         for (int i = 1; i < argc; i++) {
  448.                 printf("Primary parsing of %s... ", argv[i]);
  449.  
  450.                 CoffObject object = { 0 };
  451.                 object.name = argv[i];
  452.                 object.section_offsets = cvec_size_t_new(128);
  453.                
  454.                 {
  455.                         FILE *fp = fopen(object.name, "rb");
  456.                         if (!fp) {
  457.                                 printf("Error: Can't open \"%s\"", object.name);
  458.                                 exit(-1);
  459.                         }
  460.  
  461.                         if (!epep_init(&object.epep, fp)) {
  462.                                 ERROR_EPEP(&object.epep);
  463.                         }
  464.                 }
  465.  
  466.                 cvec_CoffObject_push_back(&objects, object);
  467.  
  468.                 printf("Done.\n");
  469.         }
  470.  
  471.         CDict_CStr_Symbol symtab;
  472.  
  473.         if (!cdict_CStr_Symbol_init(&symtab)) {
  474.                 ERROR_CDICT(&symtab);
  475.         }
  476.  
  477.         CDict_CStr_SectionInfo info_per_section;
  478.  
  479.         if (!cdict_CStr_SectionInfo_init(&info_per_section)) {
  480.                 ERROR_CDICT(&info_per_section);
  481.         }
  482.  
  483.         for (size_t i = 0; i < cvec_CoffObject_size(&objects); i++) {
  484.                 printf("Secondary parsing of %s {\n", objects[i].name);
  485.  
  486.                 Epep *epep = &(objects[i].epep);
  487.  
  488.                 size_t strtab_size = 0;
  489.                 if (!epep_get_string_table_size(epep, &strtab_size)) {
  490.                         ERROR_EPEP(epep);
  491.                 }
  492.  
  493.                 char *strtab = malloc(strtab_size);
  494.                 if (!epep_get_string_table(epep, strtab)) {
  495.                         ERROR_EPEP(epep);
  496.                 }
  497.  
  498.                 // Fill symbols table
  499.                 printf(" Symbols {\n");
  500.                 for (size_t sym_i = 0; sym_i < epep->coffFileHeader.NumberOfSymbols; sym_i++) {
  501.                         EpepCoffSymbol sym = { 0 };
  502.  
  503.                         if (!epep_get_symbol_by_index(epep, &sym, sym_i)) {
  504.                                 ERROR_EPEP(epep);
  505.                         }
  506.  
  507.                         size_t name_max = 1024;
  508.                         char name[name_max];
  509.  
  510.                         if (sym.symbol.Zeroes == 0) {
  511.                                 strcpy(name, &strtab[sym.symbol.Offset]);
  512.                         } else {
  513.                                 memcpy(name, sym.symbol.ShortName, 8);
  514.                                 name[8] = '\0';
  515.                         }
  516.  
  517.                         if (!strcmp(name, "_EXPORTS")) {
  518.                                 strcpy(name, "EXPORTS");
  519.                         }
  520.  
  521.                         if (sym.symbol.StorageClass != 2) {
  522.                                 sprintf(name, "%s@%s", name, objects[i].name);
  523.                         }
  524.  
  525.                         if (sym.symbol.StorageClass != 2 || sym.symbol.SectionNumber) {
  526.                                 if (memcmp(cdict_CStr_Symbol_get_v(&symtab, name).sym.symbol.ShortName, "\0\0\0\0\0\0\0\0", 8)) {
  527.                                         printf("Error: Redefinition of \"%s\"", name);
  528.                                         exit(-1);
  529.                                 }
  530.  
  531.                                 EpepCoffSymbol *auxes = cvec_EpepCoffSymbol_new(1);
  532.                                 size_t index = number_of_symbols;
  533.  
  534.                                 for (size_t aux_i = 0; aux_i < sym.symbol.NumberOfAuxSymbols; aux_i++) {
  535.                                         EpepCoffSymbol aux = { 0 };
  536.  
  537.                                         if (!epep_get_symbol_by_index(epep, &aux, sym_i + aux_i)) {
  538.                                                 ERROR_EPEP(epep);
  539.                                         }
  540.                                         cvec_EpepCoffSymbol_push_back(&auxes, aux);
  541.                                         number_of_symbols++;
  542.                                 }
  543.  
  544.                                 Symbol new_sym = { sym, auxes, strdup(name), i, index };
  545.                                 if (!cdict_CStr_Symbol_add_vv(&symtab, strdup(name), new_sym, CDICT_NO_CHECK)) {
  546.                                         ERROR_CDICT(&symtab);
  547.                                 }
  548.                                 number_of_symbols++;
  549.  
  550.                                 printf("  Symbol #%u: %s (%u auxes, #%u)\n", sym_i, name, cvec_EpepCoffSymbol_size(&auxes), number_of_symbols - 1);
  551.  
  552.                                 add_name_to_set(strdup(name), &sym_name_set);
  553.                         }
  554.  
  555.                         sym_i += sym.symbol.NumberOfAuxSymbols;
  556.                 }
  557.                 printf(" }\n");
  558.  
  559.                 // Set section offsets and fill unique section name set
  560.                 printf(" Sections {\n");
  561.                 for (size_t sec_i = 0; sec_i < epep->coffFileHeader.NumberOfSections; sec_i++) {
  562.                         EpepSectionHeader sh = { 0 };
  563.  
  564.                         if (!epep_get_section_header_by_index(epep, &sh, sec_i)) {
  565.                                 ERROR_EPEP(epep);
  566.                         }
  567.  
  568.                         size_t name_max = 1024;
  569.                         char name[name_max];
  570.  
  571.                         if (sh.Name[0] == '/') {
  572.                                 strcpy(name, &strtab[atoi(&sh.Name[1])]);
  573.                         } else {
  574.                                 memcpy(name, sh.Name, 8);
  575.                                 name[8] = '\0';
  576.                         }
  577.  
  578.                         add_name_to_set(strdup(name), &section_names_set);
  579.  
  580.                         SectionInfo si = cdict_CStr_SectionInfo_get_v(&info_per_section, name);
  581.                         if (si.source == NULL) {
  582.                                 si.source = cvec_ObjIdSecId_new(32);
  583.                         }
  584.  
  585.                         size_t sec_offset = si.size;
  586.                         cvec_size_t_push_back(&objects[i].section_offsets, sec_offset);
  587.  
  588.                         si.size += sh.SizeOfRawData;
  589.                         si.characteristics |= sh.Characteristics;
  590.                         si.number_of_relocations += sh.NumberOfRelocations;
  591.                         cvec_ObjIdSecId_push_back(&si.source, (ObjIdSecId){ i, sec_i });
  592.                         cdict_CStr_SectionInfo_add_vv(&info_per_section, strdup(name), si, CDICT_REPLACE_EXIST);
  593.  
  594.                         printf("  Section #%llu {\n", sec_i);
  595.                         printf("   Name:                      %s\n", name);
  596.                         printf("   Virtual Address:           %u\n", sh.VirtualAddress);
  597.                         printf("   Characteristics:           %08x\n", sh.Characteristics);
  598.                         printf("   Offset in the big section: %u\n", objects[i].section_offsets[sec_i]);
  599.                         printf("  }\n");
  600.  
  601.                         if (sh.VirtualAddress != 0) {
  602.                                 printf("\n\n\n\n");
  603.                                 for (int i = 0; i < 42; i++) {
  604.                                         printf("!!!");
  605.                                 }
  606.                                 printf("\n\n\n\n\nWARNING: Handling of section with Virtual Address another that 0 is not implemented\n\n\n\n\n");
  607.                                 for (int i = 0; i < 42; i++) {
  608.                                         printf("!!!");
  609.                                 }
  610.                                 printf("\n\n\n\n");
  611.                         }
  612.                 }
  613.                 printf(" }\n");
  614.                 printf("}\n");
  615.         }
  616.  
  617.         ObjectIr ir;
  618.         ir.objects = objects;
  619.         ir.section_names_set = section_names_set;
  620.         ir.info_per_section = info_per_section;
  621.         ir.symtab = symtab;
  622.         ir.sym_name_set = sym_name_set;
  623.         ir.number_of_symbols = number_of_symbols;
  624.         return ir;
  625. }
  626.  
  627. int main(int argc, char **argv) {
  628.         ObjectIr ir = parse_objects(argc, argv);
  629.         build(&ir);
  630.         return 0;
  631. }
  632.