Subversion Repositories Kolibri OS

Rev

Rev 8620 | Rev 8959 | 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.         printf("Writing COFF Relocations {\n");
  277.         for (size_t sec_i = 0; sec_i < cvec_pchar_size(&ir->section_names_set); sec_i++) {
  278.                 char *name = ir->section_names_set[sec_i];
  279.                 SectionInfo si = cdict_CStr_SectionInfo_get_v(&ir->info_per_section, name);
  280.  
  281.                 printf(" Writing relocations of %s {\n", name);
  282.                 for (size_t i = 0; i < cvec_ObjIdSecId_size(&si.source); i++) {
  283.                         ObjIdSecId id = cvec_ObjIdSecId_at(&si.source, i);
  284.                         CoffObject *object = &ir->objects[id.obj_id];
  285.                         Epep *epep = &object->epep;
  286.  
  287.                         size_t strtab_size = 0;
  288.                         if (!epep_get_string_table_size(epep, &strtab_size)) {
  289.                                 ERROR_EPEP(epep);
  290.                         }
  291.  
  292.                         char *obj_strtab = malloc(strtab_size);
  293.                         if (!epep_get_string_table(epep, obj_strtab)) {
  294.                                 ERROR_EPEP(epep);
  295.                         }
  296.  
  297.                         EpepSectionHeader sh = { 0 };
  298.                         if (!epep_get_section_header_by_index(epep, &sh, id.sec_id)) {
  299.                                 ERROR_EPEP(epep);
  300.                         }
  301.                         for (size_t rel_i = 0; rel_i < sh.NumberOfRelocations; rel_i++) {
  302.                                 EpepCoffRelocation rel = { 0 };
  303.  
  304.                                 if (!epep_get_section_relocation_by_index(epep, &sh, &rel, rel_i)) {
  305.                                         ERROR_EPEP(epep);
  306.                                 }
  307.                                 printf("  { %02x, %02x, %02x }", rel.VirtualAddress, rel.SymbolTableIndex, rel.Type);
  308.                                 rel.VirtualAddress += object->section_offsets[sec_i];
  309.                                 {
  310.                                         size_t index = rel.SymbolTableIndex;
  311.                                         EpepCoffSymbol sym = { 0 };
  312.  
  313.                                         if (!epep_get_symbol_by_index(epep, &sym, index)) {
  314.                                                 ERROR_EPEP(epep);
  315.                                         }
  316.  
  317.                                         size_t name_max = 1024;
  318.                                         char name[name_max];
  319.  
  320.                                         if (sym.symbol.Zeroes == 0) {
  321.                                                 strcpy(name, &obj_strtab[sym.symbol.Offset]);
  322.                                         } else {
  323.                                                 memcpy(name, sym.symbol.ShortName, 8);
  324.                                                 name[8] = '\0';
  325.                                         }
  326.  
  327.                                         if (!strcmp(name, "_EXPORTS")) {
  328.                                                 strcpy(name, "EXPORTS");
  329.                                         }
  330.  
  331.                                         if (sym.symbol.StorageClass != 2) {
  332.                                                 sprintf(name, "%s@%s", name, object->name);
  333.                                         }
  334.  
  335.                                         Symbol old_sym = cdict_CStr_Symbol_get_v(&ir->symtab, name);
  336.  
  337.                                         if (old_sym.name == NULL) {
  338.                                                 printf("Internal error: Symbol of %s relocation not found", name);
  339.                                                 exit(-1);
  340.                                         }
  341.  
  342.                                         rel.SymbolTableIndex = old_sym.index;
  343.                                         printf(" -> { %02x, %02x, %02x }: ", rel.VirtualAddress, rel.SymbolTableIndex, rel.Type);
  344.                                         printf("New relocation of %s in %s\n", name, sh.Name);
  345.                                 }
  346.                                 fwrite(&rel, 1, 10, out);
  347.                         }
  348.                 }
  349.                 printf(" }\n");
  350.         }
  351.         printf("}\n");
  352.  
  353.         // Symbols Table
  354.         printf("Writing symbols {\n");
  355.         for (size_t sym_i = 0; sym_i < cvec_pchar_size(&ir->sym_name_set); sym_i++) {
  356.                 char *name = ir->sym_name_set[sym_i];
  357.  
  358.                 Symbol sym = cdict_CStr_Symbol_get_v(&ir->symtab, name);
  359.  
  360.                 if (sym.sym.symbol.SectionNumber == 0xffff ||
  361.                         sym.sym.symbol.SectionNumber == 0xfffe ||
  362.                         (sym.sym.symbol.StorageClass != 2 && sym.sym.symbol.StorageClass != 3)) {
  363.                         fwrite(&sym.sym.symbol, 1, 18, out);
  364.                 } else {
  365.                         size_t sec_name_max = 1024;
  366.                         char sec_name[sec_name_max];
  367.  
  368.                         size_t object_index = sym.object_index;
  369.                         CoffObject *object = &ir->objects[object_index];
  370.                         Epep *epep = &object->epep;
  371.                         size_t section_offset = object->section_offsets[sym.sym.symbol.SectionNumber - 1];
  372.  
  373.                         size_t strtab_size = 0;
  374.                         if (!epep_get_string_table_size(epep, &strtab_size)) {
  375.                                 ERROR_EPEP(epep);
  376.                         }
  377.  
  378.                         char *obj_strtab = malloc(strtab_size);
  379.                         if (!epep_get_string_table(epep, obj_strtab)) {
  380.                                 ERROR_EPEP(epep);
  381.                         }
  382.  
  383.                         EpepSectionHeader sh = { 0 };
  384.                         if (!epep_get_section_header_by_index(epep, &sh, sym.sym.symbol.SectionNumber - 1)) {
  385.                                 ERROR_EPEP(epep);
  386.                         }
  387.  
  388.                         if (sh.Name[0] == '/') {
  389.                                 strcpy(sec_name, &obj_strtab[atoi(&sh.Name[1])]);
  390.                         } else {
  391.                                 memcpy(sec_name, sh.Name, 8);
  392.                                 sec_name[8] = '\0';
  393.                         }
  394.  
  395.                         printf("%s:\n", sym.name);
  396.                         printf(" Section:      %s\n", sec_name);
  397.                         printf(" StorageClass: %u\n", sym.sym.symbol.StorageClass);
  398.  
  399.                         sym.sym.symbol.SectionNumber = get_section_number(&ir->section_names_set, sec_name);
  400.  
  401.                         if (sym.sym.symbol.SectionNumber == 0) {
  402.                                 printf("Internal error: %s section is not found in output file");
  403.                                 exit(-1);
  404.                         }
  405.  
  406.                         sym.sym.symbol.Value += section_offset;
  407.  
  408.                         if (strlen(sym.name) <= 8) {
  409.                                 strcpy(sym.sym.symbol.ShortName, sym.name);
  410.                         } else {
  411.                                 sym.sym.symbol.Zeroes = 0;
  412.                                 sym.sym.symbol.Offset = strtab_add(&strtab, name);
  413.                         }
  414.  
  415.                         fwrite(&sym.sym.symbol, 1, 18, out);
  416.                 }
  417.                 for (size_t aux_i = 0; aux_i < sym.sym.symbol.NumberOfAuxSymbols; aux_i++) {
  418.                         fwrite(&sym.auxes[aux_i].symbol, 1, 18, out);
  419.                 }
  420.         }
  421.         printf("}\n");
  422.  
  423.         // COFF String Table
  424.         printf("Writing COFF String Table... ");
  425.         fwrite32(out, cvec_pchar_size(&strtab) + 4);
  426.         fwrite(strtab, 1, cvec_pchar_size(&strtab), out);
  427.         printf("Done.\n");
  428. }
  429.  
  430. static ObjectIr parse_objects(int argc, char **argv) {
  431.         CoffObject *objects = cvec_CoffObject_new(128);
  432.         char **section_names_set = cvec_pchar_new(4);
  433.         char **sym_name_set = cvec_pchar_new(128);
  434.         size_t number_of_symbols = 0;
  435.  
  436.         for (int i = 1; i < argc; i++) {
  437.                 printf("Primary parsing of %s... ", argv[i]);
  438.  
  439.                 CoffObject object = { 0 };
  440.                 object.name = argv[i];
  441.                 object.section_offsets = cvec_size_t_new(128);
  442.                
  443.                 {
  444.                         FILE *fp = fopen(object.name, "rb");
  445.                         if (!fp) {
  446.                                 printf("Error: Can't open \"%s\"", object.name);
  447.                                 exit(-1);
  448.                         }
  449.  
  450.                         if (!epep_init(&object.epep, fp)) {
  451.                                 ERROR_EPEP(&object.epep);
  452.                         }
  453.                 }
  454.  
  455.                 cvec_CoffObject_push_back(&objects, object);
  456.  
  457.                 printf("Done.\n");
  458.         }
  459.  
  460.         CDict_CStr_Symbol symtab;
  461.  
  462.         if (!cdict_CStr_Symbol_init(&symtab)) {
  463.                 ERROR_CDICT(&symtab);
  464.         }
  465.  
  466.         CDict_CStr_SectionInfo info_per_section;
  467.  
  468.         if (!cdict_CStr_SectionInfo_init(&info_per_section)) {
  469.                 ERROR_CDICT(&info_per_section);
  470.         }
  471.  
  472.         for (size_t i = 0; i < cvec_CoffObject_size(&objects); i++) {
  473.                 printf("Secondary parsing of %s {\n", objects[i].name);
  474.  
  475.                 Epep *epep = &(objects[i].epep);
  476.  
  477.                 size_t strtab_size = 0;
  478.                 if (!epep_get_string_table_size(epep, &strtab_size)) {
  479.                         ERROR_EPEP(epep);
  480.                 }
  481.  
  482.                 char *strtab = malloc(strtab_size);
  483.                 if (!epep_get_string_table(epep, strtab)) {
  484.                         ERROR_EPEP(epep);
  485.                 }
  486.  
  487.                 // Fill symbols table
  488.                 printf(" Symbols {\n");
  489.                 for (size_t sym_i = 0; sym_i < epep->coffFileHeader.NumberOfSymbols; sym_i++) {
  490.                         EpepCoffSymbol sym = { 0 };
  491.  
  492.                         if (!epep_get_symbol_by_index(epep, &sym, sym_i)) {
  493.                                 ERROR_EPEP(epep);
  494.                         }
  495.  
  496.                         size_t name_max = 1024;
  497.                         char name[name_max];
  498.  
  499.                         if (sym.symbol.Zeroes == 0) {
  500.                                 strcpy(name, &strtab[sym.symbol.Offset]);
  501.                         } else {
  502.                                 memcpy(name, sym.symbol.ShortName, 8);
  503.                                 name[8] = '\0';
  504.                         }
  505.  
  506.                         if (!strcmp(name, "_EXPORTS")) {
  507.                                 strcpy(name, "EXPORTS");
  508.                         }
  509.  
  510.                         if (sym.symbol.StorageClass != 2) {
  511.                                 sprintf(name, "%s@%s", name, objects[i].name);
  512.                         }
  513.  
  514.                         if (sym.symbol.StorageClass != 2 || sym.symbol.SectionNumber) {
  515.                                 if (memcmp(cdict_CStr_Symbol_get_v(&symtab, name).sym.symbol.ShortName, "\0\0\0\0\0\0\0\0", 8)) {
  516.                                         printf("Error: Redefinition of \"%s\"", name);
  517.                                         exit(-1);
  518.                                 }
  519.  
  520.                                 EpepCoffSymbol *auxes = cvec_EpepCoffSymbol_new(1);
  521.                                 size_t index = number_of_symbols;
  522.  
  523.                                 for (size_t aux_i = 0; aux_i < sym.symbol.NumberOfAuxSymbols; aux_i++) {
  524.                                         EpepCoffSymbol aux = { 0 };
  525.  
  526.                                         if (!epep_get_symbol_by_index(epep, &aux, sym_i + aux_i)) {
  527.                                                 ERROR_EPEP(epep);
  528.                                         }
  529.                                         cvec_EpepCoffSymbol_push_back(&auxes, aux);
  530.                                         number_of_symbols++;
  531.                                 }
  532.  
  533.                                 Symbol new_sym = { sym, auxes, strdup(name), i, index };
  534.                                 if (!cdict_CStr_Symbol_add_vv(&symtab, strdup(name), new_sym, CDICT_NO_CHECK)) {
  535.                                         ERROR_CDICT(&symtab);
  536.                                 }
  537.                                 number_of_symbols++;
  538.  
  539.                                 printf("  Symbol #%u: %s (%u auxes, #%u)\n", sym_i, name, cvec_EpepCoffSymbol_size(&auxes), number_of_symbols - 1);
  540.  
  541.                                 add_name_to_set(strdup(name), &sym_name_set);
  542.                         }
  543.  
  544.                         sym_i += sym.symbol.NumberOfAuxSymbols;
  545.                 }
  546.                 printf(" }\n");
  547.  
  548.                 // Set section offsets and fill unique section name set
  549.                 printf(" Sections {\n");
  550.                 for (size_t sec_i = 0; sec_i < epep->coffFileHeader.NumberOfSections; sec_i++) {
  551.                         EpepSectionHeader sh = { 0 };
  552.  
  553.                         if (!epep_get_section_header_by_index(epep, &sh, sec_i)) {
  554.                                 ERROR_EPEP(epep);
  555.                         }
  556.  
  557.                         size_t name_max = 1024;
  558.                         char name[name_max];
  559.  
  560.                         if (sh.Name[0] == '/') {
  561.                                 strcpy(name, &strtab[atoi(&sh.Name[1])]);
  562.                         } else {
  563.                                 memcpy(name, sh.Name, 8);
  564.                                 name[8] = '\0';
  565.                         }
  566.  
  567.                         add_name_to_set(strdup(name), &section_names_set);
  568.  
  569.                         SectionInfo si = cdict_CStr_SectionInfo_get_v(&info_per_section, name);
  570.                         if (si.source == NULL) {
  571.                                 si.source = cvec_ObjIdSecId_new(32);
  572.                         }
  573.  
  574.                         size_t sec_offset = si.size;
  575.                         cvec_size_t_push_back(&objects[i].section_offsets, sec_offset);
  576.  
  577.                         si.size += sh.SizeOfRawData;
  578.                         si.characteristics |= sh.Characteristics;
  579.                         si.number_of_relocations += sh.NumberOfRelocations;
  580.                         cvec_ObjIdSecId_push_back(&si.source, (ObjIdSecId){ i, sec_i });
  581.                         cdict_CStr_SectionInfo_add_vv(&info_per_section, strdup(name), si, CDICT_REPLACE_EXIST);
  582.  
  583.                         printf("  Section #%llu {\n", sec_i);
  584.                         printf("   Name:                      %s\n", name);
  585.                         printf("   Virtual Address:           %u\n", sh.VirtualAddress);
  586.                         printf("   Characteristics:           %08x\n", sh.Characteristics);
  587.                         printf("   Offset in the big section: %u\n", objects[i].section_offsets[sec_i]);
  588.                         printf("  }\n");
  589.                 }
  590.                 printf(" }\n");
  591.                 printf("}\n");
  592.         }
  593.  
  594.         ObjectIr ir;
  595.         ir.objects = objects;
  596.         ir.section_names_set = section_names_set;
  597.         ir.info_per_section = info_per_section;
  598.         ir.symtab = symtab;
  599.         ir.sym_name_set = sym_name_set;
  600.         ir.number_of_symbols = number_of_symbols;
  601.         return ir;
  602. }
  603.  
  604. int main(int argc, char **argv) {
  605.         ObjectIr ir = parse_objects(argc, argv);
  606.         build(&ir);
  607.         return 0;
  608. }
  609.