int section_align(section sec, int size) { int align; align = sec->size % size; if (align) section_write(sec, size - align, NULL); return align; }
section section_create_by_copy(section sec) { section newsec; newsec = section_create(sec->name); section_write(newsec, sec->size, sec->data); return newsec; }
int main(int Argc, char **Argv) { if (Argc < 2) { puts("Usage: rlink [-o output] [-l listing] inputs ... "); } else { bfd_init(); stringtable_put(SupportedFiles, ".rlib", (void *)add_library_file); stringtable_put(SupportedFiles, ".rdef", (void *)add_definition_file); stringtable_put(SupportedFiles, ".a", (void *)add_object_file); stringtable_put(SupportedFiles, ".o", (void *)add_object_file); stringtable_put(SupportedFiles, ".obj", (void *)add_object_file); stringtable_put(SupportedFiles, ".mo", (void *)add_object_file); stringtable_put(SupportedFiles, ".io", (void *)add_object_file); char *OutFile = 0; char *ListFile = 0; for (int I = 1; I < Argc; ++I) { if (Argv[I][0] == '-') { switch (Argv[I][1]) { case 'o': OutFile = Argv[I] + 2; break; case 'l': add_file(Argv[I] + 2); break; case 'L': add_path(Argv[I] + 2); case 's': break; case 'm': Platform = Argv[I] + 2; case '?': ListFile = Argv[I] + 2; break; }; } else { add_file(Argv[I]); }; }; for (export_t *Export = Exports.Head; Export; Export = Export->Next) { symbol_t *Symbol = (symbol_t *)stringtable_get(GlobalTable, Export->Internal); if (Symbol) { section_require(Export->Section = Symbol->Section); Export->Offset = Symbol->Offset; } else { printf("exported symbol not found: %s.\n", Export->Internal); exit(1); }; }; if (ListFile) { FILE *File = fopen(ListFile, "w"); for (section_t *Section = Sections.Head; Section; Section = Section->Next) section_debug(Section, File); for (export_t *Export = Exports.Head; Export; Export = Export->Next) { fprintf(File, "export: %s -> %d[%d]\n", Export->External, Export->Section->Index, Export->Offset); }; for (require_t *Require = Requires.Head; Require; Require = Require->Next) { fprintf(File, "require: %s[%d]\n", Require->Library, Require->Flags); }; fclose(File); }; if (OutFile) { uint32_t Temp; gzFile File = gzopen(OutFile, "wb9"); gzwrite(File, "RIVA", 4); Temp = NoOfSections; gzwrite(File, &Temp, 4); Temp = NoOfExports; gzwrite(File, &Temp, 4); Temp = NoOfRequires; gzwrite(File, &Temp, 4); for (section_t *Section = Sections.Head; Section; Section = Section->Next) section_write(Section, File); for (export_t *Export = Exports.Head; Export; Export = Export->Next) { Temp = Export->Flags; gzwrite(File, &Temp, 1); Temp = Export->Section->Index; gzwrite(File, &Temp, 4); Temp = Export->Offset; gzwrite(File, &Temp, 4); Temp = strlen(Export->External); gzwrite(File, &Temp, 4); gzwrite(File, Export->External, Temp); }; for (require_t *Require = Requires.Head; Require; Require = Require->Next) { Temp = Require->Flags; gzwrite(File, &Temp, 1); Temp = strlen(Require->Library); gzwrite(File, &Temp, 4); gzwrite(File, Require->Library, Temp); }; gzclose(File); }; }; };
section_list coff_read(char *buf) { section_list seclist; section sec; struct coff_header *header = (struct coff_header *)buf; struct coff_optional_header *ohdr; struct coff_section_header *shdr; char name[sizeof(shdr->name) + 1]; int i, num; short sflags; long lflags; if (b16r(&header->magic) == 0x8301) { printf("This is COFF file.\n"); } else { printf("This is not COFF file.\n"); return NULL; } seclist = section_list_create(); printf("\nCOFF header information.\n"); printf("flags:"); sflags = b16r(&header->flags); if (sflags & COFF_HDR_FLAG_REL) { printf(" REL"); section_list_set_type(seclist, SECTION_LIST_TYPE_RELOCATE); } if (sflags & COFF_HDR_FLAG_EXEC) { printf(" EXEC"); section_list_set_type(seclist, SECTION_LIST_TYPE_EXEC); } if (sflags & COFF_HDR_FLAG_NOLNNUM) { printf(" NOLNNUM"); } if (sflags & COFF_HDR_FLAG_NOSYM) { printf(" NOSYM"); } printf("\n"); printf("\nOptional header information.\n"); ohdr = (struct coff_optional_header *) ((char *)header + sizeof(struct coff_header)); printf("magic : %s\n", v2ss(b16r(&ohdr->magic))); printf("version : %s\n", v2ss(b16r(&ohdr->version))); printf("text size : %s\n", v2sl(b32r(&ohdr->text_size))); printf("data size : %s\n", v2sl(b32r(&ohdr->data_size))); printf("BSS size : %s\n", v2sl(b32r(&ohdr->bss_size))); printf("entry point : %s\n", v2sl(b32r(&ohdr->entry_point))); printf("text offset : %s\n", v2sl(b32r(&ohdr->text_offset))); printf("data offset : %s\n", v2sl(b32r(&ohdr->data_offset))); section_list_set_entry_point(seclist, b32r(&ohdr->entry_point)); printf("\nSection header information.\n"); num = b16r(&header->section_num); for (i = 0; i < num; i++) { shdr = (struct coff_section_header *) ((char *)header + sizeof(struct coff_header) + b16r(&header->optional_header_size) + sizeof(struct coff_section_header) * i); strncpy(name, shdr->name, sizeof(name)); sec = section_create(name); section_list_insert(seclist, NULL, sec); printf("\n"); printf("%s\n", name); printf("paddr :0x%08lx ", b32r(&shdr->physical_addr)); printf("vaddr :0x%08lx ", b32r(&shdr->virtual_addr)); printf("size :0x%08lx ", b32r(&shdr->size)); printf("offset :0x%08lx\n", b32r(&shdr->offset)); printf("reloc :0x%08lx ", b32r(&shdr->relocation)); printf("lnnum :0x%08lx ", b32r(&shdr->line_number)); printf("nreloc :0x%04x ", b16r(&shdr->relocation_num)); printf("nlnnum :0x%04x\n", b16r(&shdr->line_number_num)); section_set_physical_addr(sec, b32r(&shdr->physical_addr)); section_set_virtual_addr(sec, b32r(&shdr->virtual_addr)); lflags = b32r(&shdr->flags); printf("flags :0x%08lx (", lflags); section_set_type(sec, SECTION_TYPE_OTHER); if (lflags & COFF_SHDR_FLAG_TEXT) { printf(" TEXT"); if (!strcmp(name, ".rodata")) section_set_type(sec, SECTION_TYPE_RODATA); else section_set_type(sec, SECTION_TYPE_TEXT); } if (lflags & COFF_SHDR_FLAG_DATA) { printf(" DATA"); section_set_type(sec, SECTION_TYPE_DATA); } if (lflags & COFF_SHDR_FLAG_BSS) { printf(" BSS"); section_set_type(sec, SECTION_TYPE_BSS); } printf(" )\n"); section_set_memory_size(sec, b32r(&shdr->size)); if (b32r(&shdr->offset)) { section_write(sec, b32r(&shdr->size), ((char *)header + b32r(&shdr->offset))); section_set_file_size(sec, section_get_size(sec)); } } return seclist; }