Subversion Repositories Kolibri OS

Rev

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

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